InterpAsm-armv5te-vfp.S revision 6bbdd6b005ec5cb567ec9576190a7cd784248c5c
1/*
2 * This file was generated automatically by gen-mterp.py for 'armv5te-vfp'.
3 *
4 * --> DO NOT EDIT <--
5 */
6
7/* File: armv5te/header.S */
8/*
9 * Copyright (C) 2008 The Android Open Source Project
10 *
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 *      http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
22 */
23/*
24 * ARMv5 definitions and declarations.
25 */
26
27/*
28ARM EABI general notes:
29
30r0-r3 hold first 4 args to a method; they are not preserved across method calls
31r4-r8 are available for general use
32r9 is given special treatment in some situations, but not for us
33r10 (sl) seems to be generally available
34r11 (fp) is used by gcc (unless -fomit-frame-pointer is set)
35r12 (ip) is scratch -- not preserved across method calls
36r13 (sp) should be managed carefully in case a signal arrives
37r14 (lr) must be preserved
38r15 (pc) can be tinkered with directly
39
40r0 holds returns of <= 4 bytes
41r0-r1 hold returns of 8 bytes, low word in r0
42
43Callee must save/restore r4+ (except r12) if it modifies them.  If VFP
44is present, registers s16-s31 (a/k/a d8-d15, a/k/a q4-q7) must be preserved,
45s0-s15 (d0-d7, q0-a3) do not need to be.
46
47Stack is "full descending".  Only the arguments that don't fit in the first 4
48registers are placed on the stack.  "sp" points at the first stacked argument
49(i.e. the 5th arg).
50
51VFP: single-precision results in s0, double-precision results in d0.
52
53In the EABI, "sp" must be 64-bit aligned on entry to a function, and any
5464-bit quantities (long long, double) must be 64-bit aligned.
55*/
56
57/*
58Mterp and ARM notes:
59
60The following registers have fixed assignments:
61
62  reg nick      purpose
63  r4  rPC       interpreted program counter, used for fetching instructions
64  r5  rFP       interpreted frame pointer, used for accessing locals and args
65  r6  rGLUE     MterpGlue pointer
66  r7  rINST     first 16-bit code unit of current instruction
67  r8  rIBASE    interpreted instruction base pointer, used for computed goto
68
69Macros are provided for common operations.  Each macro MUST emit only
70one instruction to make instruction-counting easier.  They MUST NOT alter
71unspecified registers or condition codes.
72*/
73
74/* single-purpose registers, given names for clarity */
75#define rPC     r4
76#define rFP     r5
77#define rGLUE   r6
78#define rINST   r7
79#define rIBASE  r8
80
81/* save/restore the PC and/or FP from the glue struct */
82#define LOAD_PC_FROM_GLUE()     ldr     rPC, [rGLUE, #offGlue_pc]
83#define SAVE_PC_TO_GLUE()       str     rPC, [rGLUE, #offGlue_pc]
84#define LOAD_FP_FROM_GLUE()     ldr     rFP, [rGLUE, #offGlue_fp]
85#define SAVE_FP_TO_GLUE()       str     rFP, [rGLUE, #offGlue_fp]
86#define LOAD_PC_FP_FROM_GLUE()  ldmia   rGLUE, {rPC, rFP}
87#define SAVE_PC_FP_TO_GLUE()    stmia   rGLUE, {rPC, rFP}
88
89/*
90 * "export" the PC to the stack frame, f/b/o future exception objects.  Must
91 * be done *before* something calls dvmThrowException.
92 *
93 * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e.
94 * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc)
95 *
96 * It's okay to do this more than once.
97 */
98#define EXPORT_PC() \
99    str     rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)]
100
101/*
102 * Given a frame pointer, find the stack save area.
103 *
104 * In C this is "((StackSaveArea*)(_fp) -1)".
105 */
106#define SAVEAREA_FROM_FP(_reg, _fpreg) \
107    sub     _reg, _fpreg, #sizeofStackSaveArea
108
109/*
110 * Fetch the next instruction from rPC into rINST.  Does not advance rPC.
111 */
112#define FETCH_INST()            ldrh    rINST, [rPC]
113
114/*
115 * Fetch the next instruction from the specified offset.  Advances rPC
116 * to point to the next instruction.  "_count" is in 16-bit code units.
117 *
118 * Because of the limited size of immediate constants on ARM, this is only
119 * suitable for small forward movements (i.e. don't try to implement "goto"
120 * with this).
121 *
122 * This must come AFTER anything that can throw an exception, or the
123 * exception catch may miss.  (This also implies that it must come after
124 * EXPORT_PC().)
125 */
126#define FETCH_ADVANCE_INST(_count) ldrh    rINST, [rPC, #(_count*2)]!
127
128/*
129 * The operation performed here is similar to FETCH_ADVANCE_INST, except the
130 * src and dest registers are parameterized (not hard-wired to rPC and rINST).
131 */
132#define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \
133        ldrh    _dreg, [_sreg, #(_count*2)]!
134
135/*
136 * Fetch the next instruction from an offset specified by _reg.  Updates
137 * rPC to point to the next instruction.  "_reg" must specify the distance
138 * in bytes, *not* 16-bit code units, and may be a signed value.
139 *
140 * We want to write "ldrh rINST, [rPC, _reg, lsl #2]!", but some of the
141 * bits that hold the shift distance are used for the half/byte/sign flags.
142 * In some cases we can pre-double _reg for free, so we require a byte offset
143 * here.
144 */
145#define FETCH_ADVANCE_INST_RB(_reg) ldrh    rINST, [rPC, _reg]!
146
147/*
148 * Fetch a half-word code unit from an offset past the current PC.  The
149 * "_count" value is in 16-bit code units.  Does not advance rPC.
150 *
151 * The "_S" variant works the same but treats the value as signed.
152 */
153#define FETCH(_reg, _count)     ldrh    _reg, [rPC, #(_count*2)]
154#define FETCH_S(_reg, _count)   ldrsh   _reg, [rPC, #(_count*2)]
155
156/*
157 * Fetch one byte from an offset past the current PC.  Pass in the same
158 * "_count" as you would for FETCH, and an additional 0/1 indicating which
159 * byte of the halfword you want (lo/hi).
160 */
161#define FETCH_B(_reg, _count, _byte) ldrb     _reg, [rPC, #(_count*2+_byte)]
162
163/*
164 * Put the instruction's opcode field into the specified register.
165 */
166#define GET_INST_OPCODE(_reg)   and     _reg, rINST, #255
167
168/*
169 * Put the prefetched instruction's opcode field into the specified register.
170 */
171#define GET_PREFETCHED_OPCODE(_oreg, _ireg)   and     _oreg, _ireg, #255
172
173/*
174 * Begin executing the opcode in _reg.  Because this only jumps within the
175 * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork.
176 */
177#define GOTO_OPCODE(_reg)       add     pc, rIBASE, _reg, lsl #6
178#define GOTO_OPCODE_IFEQ(_reg)  addeq   pc, rIBASE, _reg, lsl #6
179#define GOTO_OPCODE_IFNE(_reg)  addne   pc, rIBASE, _reg, lsl #6
180
181/*
182 * Get/set the 32-bit value from a Dalvik register.
183 */
184#define GET_VREG(_reg, _vreg)   ldr     _reg, [rFP, _vreg, lsl #2]
185#define SET_VREG(_reg, _vreg)   str     _reg, [rFP, _vreg, lsl #2]
186
187#if defined(WITH_JIT)
188#define GET_JIT_PROF_TABLE(_reg)    ldr     _reg,[rGLUE,#offGlue_pJitProfTable]
189#define GET_JIT_THRESHOLD(_reg)     ldr     _reg,[rGLUE,#offGlue_jitThreshold]
190#endif
191
192/*
193 * Convert a virtual register index into an address.
194 */
195#define VREG_INDEX_TO_ADDR(_reg, _vreg) \
196        add     _reg, rFP, _vreg, lsl #2
197
198/*
199 * This is a #include, not a %include, because we want the C pre-processor
200 * to expand the macros into assembler assignment statements.
201 */
202#include "../common/asm-constants.h"
203
204#if defined(WITH_JIT)
205#include "../common/jit-config.h"
206#endif
207
208/* File: armv5te/platform.S */
209/*
210 * ===========================================================================
211 *  CPU-version-specific defines
212 * ===========================================================================
213 */
214
215/*
216 * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5.  Essentially a
217 * one-way branch.
218 *
219 * May modify IP.  Does not modify LR.
220 */
221.macro  LDR_PC source
222    ldr     pc, \source
223.endm
224
225/*
226 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5.
227 * Jump to subroutine.
228 *
229 * May modify IP and LR.
230 */
231.macro  LDR_PC_LR source
232    mov     lr, pc
233    ldr     pc, \source
234.endm
235
236/*
237 * Macro for "LDMFD SP!, {...regs...,PC}".
238 *
239 * May modify IP and LR.
240 */
241.macro  LDMFD_PC regs
242    ldmfd   sp!, {\regs,pc}
243.endm
244
245
246/* File: armv5te/entry.S */
247/*
248 * Copyright (C) 2008 The Android Open Source Project
249 *
250 * Licensed under the Apache License, Version 2.0 (the "License");
251 * you may not use this file except in compliance with the License.
252 * You may obtain a copy of the License at
253 *
254 *      http://www.apache.org/licenses/LICENSE-2.0
255 *
256 * Unless required by applicable law or agreed to in writing, software
257 * distributed under the License is distributed on an "AS IS" BASIS,
258 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
259 * See the License for the specific language governing permissions and
260 * limitations under the License.
261 */
262/*
263 * Interpreter entry point.
264 */
265
266/*
267 * We don't have formal stack frames, so gdb scans upward in the code
268 * to find the start of the function (a label with the %function type),
269 * and then looks at the next few instructions to figure out what
270 * got pushed onto the stack.  From this it figures out how to restore
271 * the registers, including PC, for the previous stack frame.  If gdb
272 * sees a non-function label, it stops scanning, so either we need to
273 * have nothing but assembler-local labels between the entry point and
274 * the break, or we need to fake it out.
275 *
276 * When this is defined, we add some stuff to make gdb less confused.
277 */
278#define ASSIST_DEBUGGER 1
279
280    .text
281    .align  2
282    .global dvmMterpStdRun
283    .type   dvmMterpStdRun, %function
284
285/*
286 * On entry:
287 *  r0  MterpGlue* glue
288 *
289 * This function returns a boolean "changeInterp" value.  The return comes
290 * via a call to dvmMterpStdBail().
291 */
292dvmMterpStdRun:
293#define MTERP_ENTRY1 \
294    .save {r4-r10,fp,lr}; \
295    stmfd   sp!, {r4-r10,fp,lr}         @ save 9 regs
296#define MTERP_ENTRY2 \
297    .pad    #4; \
298    sub     sp, sp, #4                  @ align 64
299
300    .fnstart
301    MTERP_ENTRY1
302    MTERP_ENTRY2
303
304    /* save stack pointer, add magic word for debuggerd */
305    str     sp, [r0, #offGlue_bailPtr]  @ save SP for eventual return
306
307    /* set up "named" registers, figure out entry point */
308    mov     rGLUE, r0                   @ set rGLUE
309    ldrb    r1, [r0, #offGlue_entryPoint]   @ InterpEntry enum is char
310    LOAD_PC_FP_FROM_GLUE()              @ load rPC and rFP from "glue"
311    adr     rIBASE, dvmAsmInstructionStart  @ set rIBASE
312    cmp     r1, #kInterpEntryInstr      @ usual case?
313    bne     .Lnot_instr                 @ no, handle it
314
315#if defined(WITH_JIT)
316.Lno_singleStep:
317    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
318    /* Entry is always a possible trace start */
319    GET_JIT_PROF_TABLE(r0)
320    FETCH_INST()
321    mov    r1, #0                       @ prepare the value for the new state
322    str    r1, [r10, #offThread_inJitCodeCache] @ back to the interp land
323    cmp    r0,#0
324    bne    common_updateProfile
325    GET_INST_OPCODE(ip)
326    GOTO_OPCODE(ip)
327#else
328    /* start executing the instruction at rPC */
329    FETCH_INST()                        @ load rINST from rPC
330    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
331    GOTO_OPCODE(ip)                     @ jump to next instruction
332#endif
333
334.Lnot_instr:
335    cmp     r1, #kInterpEntryReturn     @ were we returning from a method?
336    beq     common_returnFromMethod
337
338.Lnot_return:
339    cmp     r1, #kInterpEntryThrow      @ were we throwing an exception?
340    beq     common_exceptionThrown
341
342#if defined(WITH_JIT)
343.Lnot_throw:
344    ldr     r0,[rGLUE, #offGlue_jitResume]
345    ldr     r2,[rGLUE, #offGlue_jitResumePC]
346    cmp     r1, #kInterpEntryResume     @ resuming after Jit single-step?
347    bne     .Lbad_arg
348    cmp     rPC,r2
349    bne     .Lno_singleStep             @ must have branched, don't resume
350    mov     r1, #kInterpEntryInstr
351    strb    r1, [rGLUE, #offGlue_entryPoint]
352    ldr     rINST, .LdvmCompilerTemplate
353    bx      r0                          @ re-enter the translation
354.LdvmCompilerTemplate:
355    .word   dvmCompilerTemplateStart
356#endif
357
358.Lbad_arg:
359    ldr     r0, strBadEntryPoint
360    @ r1 holds value of entryPoint
361    bl      printf
362    bl      dvmAbort
363    .fnend
364
365
366    .global dvmMterpStdBail
367    .type   dvmMterpStdBail, %function
368
369/*
370 * Restore the stack pointer and PC from the save point established on entry.
371 * This is essentially the same as a longjmp, but should be cheaper.  The
372 * last instruction causes us to return to whoever called dvmMterpStdRun.
373 *
374 * We pushed some registers on the stack in dvmMterpStdRun, then saved
375 * SP and LR.  Here we restore SP, restore the registers, and then restore
376 * LR to PC.
377 *
378 * On entry:
379 *  r0  MterpGlue* glue
380 *  r1  bool changeInterp
381 */
382dvmMterpStdBail:
383    ldr     sp, [r0, #offGlue_bailPtr]      @ sp<- saved SP
384    mov     r0, r1                          @ return the changeInterp value
385    add     sp, sp, #4                      @ un-align 64
386    LDMFD_PC "r4-r10,fp"                    @ restore 9 regs and return
387
388
389/*
390 * String references.
391 */
392strBadEntryPoint:
393    .word   .LstrBadEntryPoint
394
395
396
397    .global dvmAsmInstructionStart
398    .type   dvmAsmInstructionStart, %function
399dvmAsmInstructionStart = .L_OP_NOP
400    .text
401
402/* ------------------------------ */
403    .balign 64
404.L_OP_NOP: /* 0x00 */
405/* File: armv5te/OP_NOP.S */
406    FETCH_ADVANCE_INST(1)               @ advance to next instr, load rINST
407    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
408    GOTO_OPCODE(ip)                     @ execute it
409
410#ifdef ASSIST_DEBUGGER
411    /* insert fake function header to help gdb find the stack frame */
412    .type   dalvik_inst, %function
413dalvik_inst:
414    .fnstart
415    MTERP_ENTRY1
416    MTERP_ENTRY2
417    .fnend
418#endif
419
420
421/* ------------------------------ */
422    .balign 64
423.L_OP_MOVE: /* 0x01 */
424/* File: armv5te/OP_MOVE.S */
425    /* for move, move-object, long-to-int */
426    /* op vA, vB */
427    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
428    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
429    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
430    GET_VREG(r2, r1)                    @ r2<- fp[B]
431    and     r0, r0, #15
432    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
433    SET_VREG(r2, r0)                    @ fp[A]<- r2
434    GOTO_OPCODE(ip)                     @ execute next instruction
435
436
437/* ------------------------------ */
438    .balign 64
439.L_OP_MOVE_FROM16: /* 0x02 */
440/* File: armv5te/OP_MOVE_FROM16.S */
441    /* for: move/from16, move-object/from16 */
442    /* op vAA, vBBBB */
443    FETCH(r1, 1)                        @ r1<- BBBB
444    mov     r0, rINST, lsr #8           @ r0<- AA
445    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
446    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
447    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
448    SET_VREG(r2, r0)                    @ fp[AA]<- r2
449    GOTO_OPCODE(ip)                     @ jump to next instruction
450
451
452/* ------------------------------ */
453    .balign 64
454.L_OP_MOVE_16: /* 0x03 */
455/* File: armv5te/OP_MOVE_16.S */
456    /* for: move/16, move-object/16 */
457    /* op vAAAA, vBBBB */
458    FETCH(r1, 2)                        @ r1<- BBBB
459    FETCH(r0, 1)                        @ r0<- AAAA
460    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
461    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
462    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
463    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
464    GOTO_OPCODE(ip)                     @ jump to next instruction
465
466
467/* ------------------------------ */
468    .balign 64
469.L_OP_MOVE_WIDE: /* 0x04 */
470/* File: armv5te/OP_MOVE_WIDE.S */
471    /* move-wide vA, vB */
472    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
473    mov     r2, rINST, lsr #8           @ r2<- A(+)
474    mov     r3, rINST, lsr #12          @ r3<- B
475    and     r2, r2, #15
476    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
477    add     r2, rFP, r2, lsl #2         @ r2<- &fp[A]
478    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[B]
479    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
480    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
481    stmia   r2, {r0-r1}                 @ fp[A]<- r0/r1
482    GOTO_OPCODE(ip)                     @ jump to next instruction
483
484
485/* ------------------------------ */
486    .balign 64
487.L_OP_MOVE_WIDE_FROM16: /* 0x05 */
488/* File: armv5te/OP_MOVE_WIDE_FROM16.S */
489    /* move-wide/from16 vAA, vBBBB */
490    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
491    FETCH(r3, 1)                        @ r3<- BBBB
492    mov     r2, rINST, lsr #8           @ r2<- AA
493    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
494    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
495    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
496    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
497    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
498    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
499    GOTO_OPCODE(ip)                     @ jump to next instruction
500
501
502/* ------------------------------ */
503    .balign 64
504.L_OP_MOVE_WIDE_16: /* 0x06 */
505/* File: armv5te/OP_MOVE_WIDE_16.S */
506    /* move-wide/16 vAAAA, vBBBB */
507    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
508    FETCH(r3, 2)                        @ r3<- BBBB
509    FETCH(r2, 1)                        @ r2<- AAAA
510    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
511    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AAAA]
512    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
513    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
514    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
515    stmia   r2, {r0-r1}                 @ fp[AAAA]<- r0/r1
516    GOTO_OPCODE(ip)                     @ jump to next instruction
517
518
519/* ------------------------------ */
520    .balign 64
521.L_OP_MOVE_OBJECT: /* 0x07 */
522/* File: armv5te/OP_MOVE_OBJECT.S */
523/* File: armv5te/OP_MOVE.S */
524    /* for move, move-object, long-to-int */
525    /* op vA, vB */
526    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
527    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
528    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
529    GET_VREG(r2, r1)                    @ r2<- fp[B]
530    and     r0, r0, #15
531    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
532    SET_VREG(r2, r0)                    @ fp[A]<- r2
533    GOTO_OPCODE(ip)                     @ execute next instruction
534
535
536
537/* ------------------------------ */
538    .balign 64
539.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
540/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */
541/* File: armv5te/OP_MOVE_FROM16.S */
542    /* for: move/from16, move-object/from16 */
543    /* op vAA, vBBBB */
544    FETCH(r1, 1)                        @ r1<- BBBB
545    mov     r0, rINST, lsr #8           @ r0<- AA
546    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
547    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
548    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
549    SET_VREG(r2, r0)                    @ fp[AA]<- r2
550    GOTO_OPCODE(ip)                     @ jump to next instruction
551
552
553
554/* ------------------------------ */
555    .balign 64
556.L_OP_MOVE_OBJECT_16: /* 0x09 */
557/* File: armv5te/OP_MOVE_OBJECT_16.S */
558/* File: armv5te/OP_MOVE_16.S */
559    /* for: move/16, move-object/16 */
560    /* op vAAAA, vBBBB */
561    FETCH(r1, 2)                        @ r1<- BBBB
562    FETCH(r0, 1)                        @ r0<- AAAA
563    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
564    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
565    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
566    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
567    GOTO_OPCODE(ip)                     @ jump to next instruction
568
569
570
571/* ------------------------------ */
572    .balign 64
573.L_OP_MOVE_RESULT: /* 0x0a */
574/* File: armv5te/OP_MOVE_RESULT.S */
575    /* for: move-result, move-result-object */
576    /* op vAA */
577    mov     r2, rINST, lsr #8           @ r2<- AA
578    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
579    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
580    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
581    SET_VREG(r0, r2)                    @ fp[AA]<- r0
582    GOTO_OPCODE(ip)                     @ jump to next instruction
583
584
585/* ------------------------------ */
586    .balign 64
587.L_OP_MOVE_RESULT_WIDE: /* 0x0b */
588/* File: armv5te/OP_MOVE_RESULT_WIDE.S */
589    /* move-result-wide vAA */
590    mov     r2, rINST, lsr #8           @ r2<- AA
591    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
592    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
593    ldmia   r3, {r0-r1}                 @ r0/r1<- retval.j
594    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
595    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
596    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
597    GOTO_OPCODE(ip)                     @ jump to next instruction
598
599
600/* ------------------------------ */
601    .balign 64
602.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
603/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */
604/* File: armv5te/OP_MOVE_RESULT.S */
605    /* for: move-result, move-result-object */
606    /* op vAA */
607    mov     r2, rINST, lsr #8           @ r2<- AA
608    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
609    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
610    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
611    SET_VREG(r0, r2)                    @ fp[AA]<- r0
612    GOTO_OPCODE(ip)                     @ jump to next instruction
613
614
615
616/* ------------------------------ */
617    .balign 64
618.L_OP_MOVE_EXCEPTION: /* 0x0d */
619/* File: armv5te/OP_MOVE_EXCEPTION.S */
620    /* move-exception vAA */
621    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
622    mov     r2, rINST, lsr #8           @ r2<- AA
623    ldr     r3, [r0, #offThread_exception]  @ r3<- dvmGetException bypass
624    mov     r1, #0                      @ r1<- 0
625    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
626    SET_VREG(r3, r2)                    @ fp[AA]<- exception obj
627    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
628    str     r1, [r0, #offThread_exception]  @ dvmClearException bypass
629    GOTO_OPCODE(ip)                     @ jump to next instruction
630
631
632/* ------------------------------ */
633    .balign 64
634.L_OP_RETURN_VOID: /* 0x0e */
635/* File: armv5te/OP_RETURN_VOID.S */
636    b       common_returnFromMethod
637
638
639/* ------------------------------ */
640    .balign 64
641.L_OP_RETURN: /* 0x0f */
642/* File: armv5te/OP_RETURN.S */
643    /*
644     * Return a 32-bit value.  Copies the return value into the "glue"
645     * structure, then jumps to the return handler.
646     *
647     * for: return, return-object
648     */
649    /* op vAA */
650    mov     r2, rINST, lsr #8           @ r2<- AA
651    GET_VREG(r0, r2)                    @ r0<- vAA
652    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
653    b       common_returnFromMethod
654
655
656/* ------------------------------ */
657    .balign 64
658.L_OP_RETURN_WIDE: /* 0x10 */
659/* File: armv5te/OP_RETURN_WIDE.S */
660    /*
661     * Return a 64-bit value.  Copies the return value into the "glue"
662     * structure, then jumps to the return handler.
663     */
664    /* return-wide vAA */
665    mov     r2, rINST, lsr #8           @ r2<- AA
666    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
667    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
668    ldmia   r2, {r0-r1}                 @ r0/r1 <- vAA/vAA+1
669    stmia   r3, {r0-r1}                 @ retval<- r0/r1
670    b       common_returnFromMethod
671
672
673/* ------------------------------ */
674    .balign 64
675.L_OP_RETURN_OBJECT: /* 0x11 */
676/* File: armv5te/OP_RETURN_OBJECT.S */
677/* File: armv5te/OP_RETURN.S */
678    /*
679     * Return a 32-bit value.  Copies the return value into the "glue"
680     * structure, then jumps to the return handler.
681     *
682     * for: return, return-object
683     */
684    /* op vAA */
685    mov     r2, rINST, lsr #8           @ r2<- AA
686    GET_VREG(r0, r2)                    @ r0<- vAA
687    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
688    b       common_returnFromMethod
689
690
691
692/* ------------------------------ */
693    .balign 64
694.L_OP_CONST_4: /* 0x12 */
695/* File: armv5te/OP_CONST_4.S */
696    /* const/4 vA, #+B */
697    mov     r1, rINST, lsl #16          @ r1<- Bxxx0000
698    mov     r0, rINST, lsr #8           @ r0<- A+
699    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
700    mov     r1, r1, asr #28             @ r1<- sssssssB (sign-extended)
701    and     r0, r0, #15
702    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
703    SET_VREG(r1, r0)                    @ fp[A]<- r1
704    GOTO_OPCODE(ip)                     @ execute next instruction
705
706
707/* ------------------------------ */
708    .balign 64
709.L_OP_CONST_16: /* 0x13 */
710/* File: armv5te/OP_CONST_16.S */
711    /* const/16 vAA, #+BBBB */
712    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
713    mov     r3, rINST, lsr #8           @ r3<- AA
714    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
715    SET_VREG(r0, r3)                    @ vAA<- r0
716    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
717    GOTO_OPCODE(ip)                     @ jump to next instruction
718
719
720/* ------------------------------ */
721    .balign 64
722.L_OP_CONST: /* 0x14 */
723/* File: armv5te/OP_CONST.S */
724    /* const vAA, #+BBBBbbbb */
725    mov     r3, rINST, lsr #8           @ r3<- AA
726    FETCH(r0, 1)                        @ r0<- bbbb (low)
727    FETCH(r1, 2)                        @ r1<- BBBB (high)
728    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
729    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
730    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
731    SET_VREG(r0, r3)                    @ vAA<- r0
732    GOTO_OPCODE(ip)                     @ jump to next instruction
733
734
735/* ------------------------------ */
736    .balign 64
737.L_OP_CONST_HIGH16: /* 0x15 */
738/* File: armv5te/OP_CONST_HIGH16.S */
739    /* const/high16 vAA, #+BBBB0000 */
740    FETCH(r0, 1)                        @ r0<- 0000BBBB (zero-extended)
741    mov     r3, rINST, lsr #8           @ r3<- AA
742    mov     r0, r0, lsl #16             @ r0<- BBBB0000
743    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
744    SET_VREG(r0, r3)                    @ vAA<- r0
745    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
746    GOTO_OPCODE(ip)                     @ jump to next instruction
747
748
749/* ------------------------------ */
750    .balign 64
751.L_OP_CONST_WIDE_16: /* 0x16 */
752/* File: armv5te/OP_CONST_WIDE_16.S */
753    /* const-wide/16 vAA, #+BBBB */
754    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
755    mov     r3, rINST, lsr #8           @ r3<- AA
756    mov     r1, r0, asr #31             @ r1<- ssssssss
757    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
758    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
759    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
760    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
761    GOTO_OPCODE(ip)                     @ jump to next instruction
762
763
764/* ------------------------------ */
765    .balign 64
766.L_OP_CONST_WIDE_32: /* 0x17 */
767/* File: armv5te/OP_CONST_WIDE_32.S */
768    /* const-wide/32 vAA, #+BBBBbbbb */
769    FETCH(r0, 1)                        @ r0<- 0000bbbb (low)
770    mov     r3, rINST, lsr #8           @ r3<- AA
771    FETCH_S(r2, 2)                      @ r2<- ssssBBBB (high)
772    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
773    orr     r0, r0, r2, lsl #16         @ r0<- BBBBbbbb
774    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
775    mov     r1, r0, asr #31             @ r1<- ssssssss
776    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
777    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
778    GOTO_OPCODE(ip)                     @ jump to next instruction
779
780
781/* ------------------------------ */
782    .balign 64
783.L_OP_CONST_WIDE: /* 0x18 */
784/* File: armv5te/OP_CONST_WIDE.S */
785    /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
786    FETCH(r0, 1)                        @ r0<- bbbb (low)
787    FETCH(r1, 2)                        @ r1<- BBBB (low middle)
788    FETCH(r2, 3)                        @ r2<- hhhh (high middle)
789    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb (low word)
790    FETCH(r3, 4)                        @ r3<- HHHH (high)
791    mov     r9, rINST, lsr #8           @ r9<- AA
792    orr     r1, r2, r3, lsl #16         @ r1<- HHHHhhhh (high word)
793    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
794    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
795    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
796    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
797    GOTO_OPCODE(ip)                     @ jump to next instruction
798
799
800/* ------------------------------ */
801    .balign 64
802.L_OP_CONST_WIDE_HIGH16: /* 0x19 */
803/* File: armv5te/OP_CONST_WIDE_HIGH16.S */
804    /* const-wide/high16 vAA, #+BBBB000000000000 */
805    FETCH(r1, 1)                        @ r1<- 0000BBBB (zero-extended)
806    mov     r3, rINST, lsr #8           @ r3<- AA
807    mov     r0, #0                      @ r0<- 00000000
808    mov     r1, r1, lsl #16             @ r1<- BBBB0000
809    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
810    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
811    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
812    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
813    GOTO_OPCODE(ip)                     @ jump to next instruction
814
815
816/* ------------------------------ */
817    .balign 64
818.L_OP_CONST_STRING: /* 0x1a */
819/* File: armv5te/OP_CONST_STRING.S */
820    /* const/string vAA, String@BBBB */
821    FETCH(r1, 1)                        @ r1<- BBBB
822    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
823    mov     r9, rINST, lsr #8           @ r9<- AA
824    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
825    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
826    cmp     r0, #0                      @ not yet resolved?
827    beq     .LOP_CONST_STRING_resolve
828    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
829    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
830    SET_VREG(r0, r9)                    @ vAA<- r0
831    GOTO_OPCODE(ip)                     @ jump to next instruction
832
833/* ------------------------------ */
834    .balign 64
835.L_OP_CONST_STRING_JUMBO: /* 0x1b */
836/* File: armv5te/OP_CONST_STRING_JUMBO.S */
837    /* const/string vAA, String@BBBBBBBB */
838    FETCH(r0, 1)                        @ r0<- bbbb (low)
839    FETCH(r1, 2)                        @ r1<- BBBB (high)
840    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
841    mov     r9, rINST, lsr #8           @ r9<- AA
842    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
843    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
844    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
845    cmp     r0, #0
846    beq     .LOP_CONST_STRING_JUMBO_resolve
847    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
848    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
849    SET_VREG(r0, r9)                    @ vAA<- r0
850    GOTO_OPCODE(ip)                     @ jump to next instruction
851
852/* ------------------------------ */
853    .balign 64
854.L_OP_CONST_CLASS: /* 0x1c */
855/* File: armv5te/OP_CONST_CLASS.S */
856    /* const/class vAA, Class@BBBB */
857    FETCH(r1, 1)                        @ r1<- BBBB
858    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
859    mov     r9, rINST, lsr #8           @ r9<- AA
860    ldr     r2, [r2, #offDvmDex_pResClasses]   @ r2<- dvmDex->pResClasses
861    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResClasses[BBBB]
862    cmp     r0, #0                      @ not yet resolved?
863    beq     .LOP_CONST_CLASS_resolve
864    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
865    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
866    SET_VREG(r0, r9)                    @ vAA<- r0
867    GOTO_OPCODE(ip)                     @ jump to next instruction
868
869/* ------------------------------ */
870    .balign 64
871.L_OP_MONITOR_ENTER: /* 0x1d */
872/* File: armv5te/OP_MONITOR_ENTER.S */
873    /*
874     * Synchronize on an object.
875     */
876    /* monitor-enter vAA */
877    mov     r2, rINST, lsr #8           @ r2<- AA
878    GET_VREG(r1, r2)                    @ r1<- vAA (object)
879    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
880    cmp     r1, #0                      @ null object?
881    EXPORT_PC()                         @ need for precise GC, MONITOR_TRACKING
882    beq     common_errNullObject        @ null object, throw an exception
883    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
884    bl      dvmLockObject               @ call(self, obj)
885#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */
886    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
887    ldr     r1, [r0, #offThread_exception] @ check for exception
888    cmp     r1, #0
889    bne     common_exceptionThrown      @ exception raised, bail out
890#endif
891    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
892    GOTO_OPCODE(ip)                     @ jump to next instruction
893
894
895/* ------------------------------ */
896    .balign 64
897.L_OP_MONITOR_EXIT: /* 0x1e */
898/* File: armv5te/OP_MONITOR_EXIT.S */
899    /*
900     * Unlock an object.
901     *
902     * Exceptions that occur when unlocking a monitor need to appear as
903     * if they happened at the following instruction.  See the Dalvik
904     * instruction spec.
905     */
906    /* monitor-exit vAA */
907    mov     r2, rINST, lsr #8           @ r2<- AA
908    EXPORT_PC()                         @ before fetch: export the PC
909    GET_VREG(r1, r2)                    @ r1<- vAA (object)
910    cmp     r1, #0                      @ null object?
911    beq     1f                          @ yes
912    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
913    bl      dvmUnlockObject             @ r0<- success for unlock(self, obj)
914    cmp     r0, #0                      @ failed?
915    FETCH_ADVANCE_INST(1)               @ before throw: advance rPC, load rINST
916    beq     common_exceptionThrown      @ yes, exception is pending
917    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
918    GOTO_OPCODE(ip)                     @ jump to next instruction
9191:
920    FETCH_ADVANCE_INST(1)               @ advance before throw
921    b      common_errNullObject
922
923
924/* ------------------------------ */
925    .balign 64
926.L_OP_CHECK_CAST: /* 0x1f */
927/* File: armv5te/OP_CHECK_CAST.S */
928    /*
929     * Check to see if a cast from one class to another is allowed.
930     */
931    /* check-cast vAA, class@BBBB */
932    mov     r3, rINST, lsr #8           @ r3<- AA
933    FETCH(r2, 1)                        @ r2<- BBBB
934    GET_VREG(r9, r3)                    @ r9<- object
935    ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- pDvmDex
936    cmp     r9, #0                      @ is object null?
937    ldr     r0, [r0, #offDvmDex_pResClasses]    @ r0<- pDvmDex->pResClasses
938    beq     .LOP_CHECK_CAST_okay            @ null obj, cast always succeeds
939    ldr     r1, [r0, r2, lsl #2]        @ r1<- resolved class
940    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
941    cmp     r1, #0                      @ have we resolved this before?
942    beq     .LOP_CHECK_CAST_resolve         @ not resolved, do it now
943.LOP_CHECK_CAST_resolved:
944    cmp     r0, r1                      @ same class (trivial success)?
945    bne     .LOP_CHECK_CAST_fullcheck       @ no, do full check
946.LOP_CHECK_CAST_okay:
947    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
948    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
949    GOTO_OPCODE(ip)                     @ jump to next instruction
950
951/* ------------------------------ */
952    .balign 64
953.L_OP_INSTANCE_OF: /* 0x20 */
954/* File: armv5te/OP_INSTANCE_OF.S */
955    /*
956     * Check to see if an object reference is an instance of a class.
957     *
958     * Most common situation is a non-null object, being compared against
959     * an already-resolved class.
960     */
961    /* instance-of vA, vB, class@CCCC */
962    mov     r3, rINST, lsr #12          @ r3<- B
963    mov     r9, rINST, lsr #8           @ r9<- A+
964    GET_VREG(r0, r3)                    @ r0<- vB (object)
965    and     r9, r9, #15                 @ r9<- A
966    cmp     r0, #0                      @ is object null?
967    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- pDvmDex
968    beq     .LOP_INSTANCE_OF_store           @ null obj, not an instance, store r0
969    FETCH(r3, 1)                        @ r3<- CCCC
970    ldr     r2, [r2, #offDvmDex_pResClasses]    @ r2<- pDvmDex->pResClasses
971    ldr     r1, [r2, r3, lsl #2]        @ r1<- resolved class
972    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
973    cmp     r1, #0                      @ have we resolved this before?
974    beq     .LOP_INSTANCE_OF_resolve         @ not resolved, do it now
975.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class
976    cmp     r0, r1                      @ same class (trivial success)?
977    beq     .LOP_INSTANCE_OF_trivial         @ yes, trivial finish
978    b       .LOP_INSTANCE_OF_fullcheck       @ no, do full check
979
980/* ------------------------------ */
981    .balign 64
982.L_OP_ARRAY_LENGTH: /* 0x21 */
983/* File: armv5te/OP_ARRAY_LENGTH.S */
984    /*
985     * Return the length of an array.
986     */
987    mov     r1, rINST, lsr #12          @ r1<- B
988    mov     r2, rINST, lsr #8           @ r2<- A+
989    GET_VREG(r0, r1)                    @ r0<- vB (object ref)
990    and     r2, r2, #15                 @ r2<- A
991    cmp     r0, #0                      @ is object null?
992    beq     common_errNullObject        @ yup, fail
993    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
994    ldr     r3, [r0, #offArrayObject_length]    @ r3<- array length
995    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
996    SET_VREG(r3, r2)                    @ vB<- length
997    GOTO_OPCODE(ip)                     @ jump to next instruction
998
999
1000/* ------------------------------ */
1001    .balign 64
1002.L_OP_NEW_INSTANCE: /* 0x22 */
1003/* File: armv5te/OP_NEW_INSTANCE.S */
1004    /*
1005     * Create a new instance of a class.
1006     */
1007    /* new-instance vAA, class@BBBB */
1008    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1009    FETCH(r1, 1)                        @ r1<- BBBB
1010    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1011    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1012    EXPORT_PC()                         @ req'd for init, resolve, alloc
1013    cmp     r0, #0                      @ already resolved?
1014    beq     .LOP_NEW_INSTANCE_resolve         @ no, resolve it now
1015.LOP_NEW_INSTANCE_resolved:   @ r0=class
1016    ldrb    r1, [r0, #offClassObject_status]    @ r1<- ClassStatus enum
1017    cmp     r1, #CLASS_INITIALIZED      @ has class been initialized?
1018    bne     .LOP_NEW_INSTANCE_needinit        @ no, init class now
1019.LOP_NEW_INSTANCE_initialized: @ r0=class
1020    mov     r1, #ALLOC_DONT_TRACK       @ flags for alloc call
1021    bl      dvmAllocObject              @ r0<- new object
1022    b       .LOP_NEW_INSTANCE_finish          @ continue
1023
1024/* ------------------------------ */
1025    .balign 64
1026.L_OP_NEW_ARRAY: /* 0x23 */
1027/* File: armv5te/OP_NEW_ARRAY.S */
1028    /*
1029     * Allocate an array of objects, specified with the array class
1030     * and a count.
1031     *
1032     * The verifier guarantees that this is an array class, so we don't
1033     * check for it here.
1034     */
1035    /* new-array vA, vB, class@CCCC */
1036    mov     r0, rINST, lsr #12          @ r0<- B
1037    FETCH(r2, 1)                        @ r2<- CCCC
1038    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1039    GET_VREG(r1, r0)                    @ r1<- vB (array length)
1040    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1041    cmp     r1, #0                      @ check length
1042    ldr     r0, [r3, r2, lsl #2]        @ r0<- resolved class
1043    bmi     common_errNegativeArraySize @ negative length, bail
1044    cmp     r0, #0                      @ already resolved?
1045    EXPORT_PC()                         @ req'd for resolve, alloc
1046    bne     .LOP_NEW_ARRAY_finish          @ resolved, continue
1047    b       .LOP_NEW_ARRAY_resolve         @ do resolve now
1048
1049/* ------------------------------ */
1050    .balign 64
1051.L_OP_FILLED_NEW_ARRAY: /* 0x24 */
1052/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1053    /*
1054     * Create a new array with elements filled from registers.
1055     *
1056     * for: filled-new-array, filled-new-array/range
1057     */
1058    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1059    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1060    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1061    FETCH(r1, 1)                        @ r1<- BBBB
1062    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1063    EXPORT_PC()                         @ need for resolve and alloc
1064    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1065    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1066    cmp     r0, #0                      @ already resolved?
1067    bne     .LOP_FILLED_NEW_ARRAY_continue        @ yes, continue on
10688:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1069    mov     r2, #0                      @ r2<- false
1070    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1071    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1072    cmp     r0, #0                      @ got null?
1073    beq     common_exceptionThrown      @ yes, handle exception
1074    b       .LOP_FILLED_NEW_ARRAY_continue
1075
1076/* ------------------------------ */
1077    .balign 64
1078.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
1079/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */
1080/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1081    /*
1082     * Create a new array with elements filled from registers.
1083     *
1084     * for: filled-new-array, filled-new-array/range
1085     */
1086    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1087    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1088    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1089    FETCH(r1, 1)                        @ r1<- BBBB
1090    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1091    EXPORT_PC()                         @ need for resolve and alloc
1092    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1093    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1094    cmp     r0, #0                      @ already resolved?
1095    bne     .LOP_FILLED_NEW_ARRAY_RANGE_continue        @ yes, continue on
10968:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1097    mov     r2, #0                      @ r2<- false
1098    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1099    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1100    cmp     r0, #0                      @ got null?
1101    beq     common_exceptionThrown      @ yes, handle exception
1102    b       .LOP_FILLED_NEW_ARRAY_RANGE_continue
1103
1104
1105/* ------------------------------ */
1106    .balign 64
1107.L_OP_FILL_ARRAY_DATA: /* 0x26 */
1108/* File: armv5te/OP_FILL_ARRAY_DATA.S */
1109    /* fill-array-data vAA, +BBBBBBBB */
1110    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1111    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1112    mov     r3, rINST, lsr #8           @ r3<- AA
1113    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
1114    GET_VREG(r0, r3)                    @ r0<- vAA (array object)
1115    add     r1, rPC, r1, lsl #1         @ r1<- PC + BBBBbbbb*2 (array data off.)
1116    EXPORT_PC();
1117    bl      dvmInterpHandleFillArrayData@ fill the array with predefined data
1118    cmp     r0, #0                      @ 0 means an exception is thrown
1119    beq     common_exceptionThrown      @ has exception
1120    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
1121    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1122    GOTO_OPCODE(ip)                     @ jump to next instruction
1123
1124/* ------------------------------ */
1125    .balign 64
1126.L_OP_THROW: /* 0x27 */
1127/* File: armv5te/OP_THROW.S */
1128    /*
1129     * Throw an exception object in the current thread.
1130     */
1131    /* throw vAA */
1132    mov     r2, rINST, lsr #8           @ r2<- AA
1133    GET_VREG(r1, r2)                    @ r1<- vAA (exception object)
1134    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
1135    cmp     r1, #0                      @ null object?
1136    beq     common_errNullObject        @ yes, throw an NPE instead
1137    @ bypass dvmSetException, just store it
1138    str     r1, [r0, #offThread_exception]  @ thread->exception<- obj
1139    b       common_exceptionThrown
1140
1141
1142/* ------------------------------ */
1143    .balign 64
1144.L_OP_GOTO: /* 0x28 */
1145/* File: armv5te/OP_GOTO.S */
1146    /*
1147     * Unconditional branch, 8-bit offset.
1148     *
1149     * The branch distance is a signed code-unit offset, which we need to
1150     * double to get a byte offset.
1151     */
1152    /* goto +AA */
1153    mov     r0, rINST, lsl #16          @ r0<- AAxx0000
1154    movs    r9, r0, asr #24             @ r9<- ssssssAA (sign-extended)
1155    mov     r9, r9, lsl #1              @ r9<- byte offset
1156    bmi     common_backwardBranch       @ backward branch, do periodic checks
1157#if defined(WITH_JIT)
1158    GET_JIT_PROF_TABLE(r0)
1159    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1160    cmp     r0,#0
1161    bne     common_updateProfile
1162    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1163    GOTO_OPCODE(ip)                     @ jump to next instruction
1164#else
1165    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1166    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1167    GOTO_OPCODE(ip)                     @ jump to next instruction
1168#endif
1169
1170/* ------------------------------ */
1171    .balign 64
1172.L_OP_GOTO_16: /* 0x29 */
1173/* File: armv5te/OP_GOTO_16.S */
1174    /*
1175     * Unconditional branch, 16-bit offset.
1176     *
1177     * The branch distance is a signed code-unit offset, which we need to
1178     * double to get a byte offset.
1179     */
1180    /* goto/16 +AAAA */
1181    FETCH_S(r0, 1)                      @ r0<- ssssAAAA (sign-extended)
1182    movs    r9, r0, asl #1              @ r9<- byte offset, check sign
1183    bmi     common_backwardBranch       @ backward branch, do periodic checks
1184#if defined(WITH_JIT)
1185    GET_JIT_PROF_TABLE(r0)
1186    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1187    cmp     r0,#0
1188    bne     common_updateProfile
1189    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1190    GOTO_OPCODE(ip)                     @ jump to next instruction
1191#else
1192    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1193    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1194    GOTO_OPCODE(ip)                     @ jump to next instruction
1195#endif
1196
1197
1198/* ------------------------------ */
1199    .balign 64
1200.L_OP_GOTO_32: /* 0x2a */
1201/* File: armv5te/OP_GOTO_32.S */
1202    /*
1203     * Unconditional branch, 32-bit offset.
1204     *
1205     * The branch distance is a signed code-unit offset, which we need to
1206     * double to get a byte offset.
1207     *
1208     * Unlike most opcodes, this one is allowed to branch to itself, so
1209     * our "backward branch" test must be "<=0" instead of "<0".  The ORRS
1210     * instruction doesn't affect the V flag, so we need to clear it
1211     * explicitly.
1212     */
1213    /* goto/32 +AAAAAAAA */
1214    FETCH(r0, 1)                        @ r0<- aaaa (lo)
1215    FETCH(r1, 2)                        @ r1<- AAAA (hi)
1216    cmp     ip, ip                      @ (clear V flag during stall)
1217    orrs    r0, r0, r1, lsl #16         @ r0<- AAAAaaaa, check sign
1218    mov     r9, r0, asl #1              @ r9<- byte offset
1219    ble     common_backwardBranch       @ backward branch, do periodic checks
1220#if defined(WITH_JIT)
1221    GET_JIT_PROF_TABLE(r0)
1222    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1223    cmp     r0,#0
1224    bne     common_updateProfile
1225    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1226    GOTO_OPCODE(ip)                     @ jump to next instruction
1227#else
1228    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1229    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1230    GOTO_OPCODE(ip)                     @ jump to next instruction
1231#endif
1232
1233/* ------------------------------ */
1234    .balign 64
1235.L_OP_PACKED_SWITCH: /* 0x2b */
1236/* File: armv5te/OP_PACKED_SWITCH.S */
1237    /*
1238     * Handle a packed-switch or sparse-switch instruction.  In both cases
1239     * we decode it and hand it off to a helper function.
1240     *
1241     * We don't really expect backward branches in a switch statement, but
1242     * they're perfectly legal, so we check for them here.
1243     *
1244     * for: packed-switch, sparse-switch
1245     */
1246    /* op vAA, +BBBB */
1247    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1248    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1249    mov     r3, rINST, lsr #8           @ r3<- AA
1250    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1251    GET_VREG(r1, r3)                    @ r1<- vAA
1252    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1253    bl      dvmInterpHandlePackedSwitch                       @ r0<- code-unit branch offset
1254    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1255    bmi     common_backwardBranch       @ backward branch, do periodic checks
1256    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1257#if defined(WITH_JIT)
1258    GET_JIT_PROF_TABLE(r0)
1259    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1260    cmp     r0,#0
1261    bne     common_updateProfile
1262    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1263    GOTO_OPCODE(ip)                     @ jump to next instruction
1264#else
1265    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1266    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1267    GOTO_OPCODE(ip)                     @ jump to next instruction
1268#endif
1269
1270
1271/* ------------------------------ */
1272    .balign 64
1273.L_OP_SPARSE_SWITCH: /* 0x2c */
1274/* File: armv5te/OP_SPARSE_SWITCH.S */
1275/* File: armv5te/OP_PACKED_SWITCH.S */
1276    /*
1277     * Handle a packed-switch or sparse-switch instruction.  In both cases
1278     * we decode it and hand it off to a helper function.
1279     *
1280     * We don't really expect backward branches in a switch statement, but
1281     * they're perfectly legal, so we check for them here.
1282     *
1283     * for: packed-switch, sparse-switch
1284     */
1285    /* op vAA, +BBBB */
1286    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1287    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1288    mov     r3, rINST, lsr #8           @ r3<- AA
1289    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1290    GET_VREG(r1, r3)                    @ r1<- vAA
1291    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1292    bl      dvmInterpHandleSparseSwitch                       @ r0<- code-unit branch offset
1293    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1294    bmi     common_backwardBranch       @ backward branch, do periodic checks
1295    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1296#if defined(WITH_JIT)
1297    GET_JIT_PROF_TABLE(r0)
1298    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1299    cmp     r0,#0
1300    bne     common_updateProfile
1301    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1302    GOTO_OPCODE(ip)                     @ jump to next instruction
1303#else
1304    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1305    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1306    GOTO_OPCODE(ip)                     @ jump to next instruction
1307#endif
1308
1309
1310
1311/* ------------------------------ */
1312    .balign 64
1313.L_OP_CMPL_FLOAT: /* 0x2d */
1314/* File: arm-vfp/OP_CMPL_FLOAT.S */
1315    /*
1316     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1317     * destination register based on the results of the comparison.
1318     *
1319     * int compare(x, y) {
1320     *     if (x == y) {
1321     *         return 0;
1322     *     } else if (x > y) {
1323     *         return 1;
1324     *     } else if (x < y) {
1325     *         return -1;
1326     *     } else {
1327     *         return -1;
1328     *     }
1329     * }
1330     */
1331    /* op vAA, vBB, vCC */
1332    FETCH(r0, 1)                        @ r0<- CCBB
1333    mov     r9, rINST, lsr #8           @ r9<- AA
1334    and     r2, r0, #255                @ r2<- BB
1335    mov     r3, r0, lsr #8              @ r3<- CC
1336    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1337    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1338    flds    s0, [r2]                    @ s0<- vBB
1339    flds    s1, [r3]                    @ s1<- vCC
1340    fcmpes  s0, s1                      @ compare (vBB, vCC)
1341    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1342    mvn     r0, #0                      @ r0<- -1 (default)
1343    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1344    fmstat                              @ export status flags
1345    movgt   r0, #1                      @ (greater than) r1<- 1
1346    moveq   r0, #0                      @ (equal) r1<- 0
1347    b       .LOP_CMPL_FLOAT_finish          @ argh
1348
1349
1350/* ------------------------------ */
1351    .balign 64
1352.L_OP_CMPG_FLOAT: /* 0x2e */
1353/* File: arm-vfp/OP_CMPG_FLOAT.S */
1354    /*
1355     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1356     * destination register based on the results of the comparison.
1357     *
1358     * int compare(x, y) {
1359     *     if (x == y) {
1360     *         return 0;
1361     *     } else if (x < y) {
1362     *         return -1;
1363     *     } else if (x > y) {
1364     *         return 1;
1365     *     } else {
1366     *         return 1;
1367     *     }
1368     * }
1369     */
1370    /* op vAA, vBB, vCC */
1371    FETCH(r0, 1)                        @ r0<- CCBB
1372    mov     r9, rINST, lsr #8           @ r9<- AA
1373    and     r2, r0, #255                @ r2<- BB
1374    mov     r3, r0, lsr #8              @ r3<- CC
1375    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1376    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1377    flds    s0, [r2]                    @ s0<- vBB
1378    flds    s1, [r3]                    @ s1<- vCC
1379    fcmpes  s0, s1                      @ compare (vBB, vCC)
1380    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1381    mov     r0, #1                      @ r0<- 1 (default)
1382    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1383    fmstat                              @ export status flags
1384    mvnmi   r0, #0                      @ (less than) r1<- -1
1385    moveq   r0, #0                      @ (equal) r1<- 0
1386    b       .LOP_CMPG_FLOAT_finish          @ argh
1387
1388
1389/* ------------------------------ */
1390    .balign 64
1391.L_OP_CMPL_DOUBLE: /* 0x2f */
1392/* File: arm-vfp/OP_CMPL_DOUBLE.S */
1393    /*
1394     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1395     * destination register based on the results of the comparison.
1396     *
1397     * int compare(x, y) {
1398     *     if (x == y) {
1399     *         return 0;
1400     *     } else if (x > y) {
1401     *         return 1;
1402     *     } else if (x < y) {
1403     *         return -1;
1404     *     } else {
1405     *         return -1;
1406     *     }
1407     * }
1408     */
1409    /* op vAA, vBB, vCC */
1410    FETCH(r0, 1)                        @ r0<- CCBB
1411    mov     r9, rINST, lsr #8           @ r9<- AA
1412    and     r2, r0, #255                @ r2<- BB
1413    mov     r3, r0, lsr #8              @ r3<- CC
1414    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1415    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1416    fldd    d0, [r2]                    @ d0<- vBB
1417    fldd    d1, [r3]                    @ d1<- vCC
1418    fcmped  d0, d1                      @ compare (vBB, vCC)
1419    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1420    mvn     r0, #0                      @ r0<- -1 (default)
1421    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1422    fmstat                              @ export status flags
1423    movgt   r0, #1                      @ (greater than) r1<- 1
1424    moveq   r0, #0                      @ (equal) r1<- 0
1425    b       .LOP_CMPL_DOUBLE_finish          @ argh
1426
1427
1428/* ------------------------------ */
1429    .balign 64
1430.L_OP_CMPG_DOUBLE: /* 0x30 */
1431/* File: arm-vfp/OP_CMPG_DOUBLE.S */
1432    /*
1433     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1434     * destination register based on the results of the comparison.
1435     *
1436     * int compare(x, y) {
1437     *     if (x == y) {
1438     *         return 0;
1439     *     } else if (x < y) {
1440     *         return -1;
1441     *     } else if (x > y) {
1442     *         return 1;
1443     *     } else {
1444     *         return 1;
1445     *     }
1446     * }
1447     */
1448    /* op vAA, vBB, vCC */
1449    FETCH(r0, 1)                        @ r0<- CCBB
1450    mov     r9, rINST, lsr #8           @ r9<- AA
1451    and     r2, r0, #255                @ r2<- BB
1452    mov     r3, r0, lsr #8              @ r3<- CC
1453    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1454    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1455    fldd    d0, [r2]                    @ d0<- vBB
1456    fldd    d1, [r3]                    @ d1<- vCC
1457    fcmped  d0, d1                      @ compare (vBB, vCC)
1458    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1459    mov     r0, #1                      @ r0<- 1 (default)
1460    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1461    fmstat                              @ export status flags
1462    mvnmi   r0, #0                      @ (less than) r1<- -1
1463    moveq   r0, #0                      @ (equal) r1<- 0
1464    b       .LOP_CMPG_DOUBLE_finish          @ argh
1465
1466
1467/* ------------------------------ */
1468    .balign 64
1469.L_OP_CMP_LONG: /* 0x31 */
1470/* File: armv5te/OP_CMP_LONG.S */
1471    /*
1472     * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
1473     * register based on the results of the comparison.
1474     *
1475     * We load the full values with LDM, but in practice many values could
1476     * be resolved by only looking at the high word.  This could be made
1477     * faster or slower by splitting the LDM into a pair of LDRs.
1478     *
1479     * If we just wanted to set condition flags, we could do this:
1480     *  subs    ip, r0, r2
1481     *  sbcs    ip, r1, r3
1482     *  subeqs  ip, r0, r2
1483     * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
1484     * integer value, which we can do with 2 conditional mov/mvn instructions
1485     * (set 1, set -1; if they're equal we already have 0 in ip), giving
1486     * us a constant 5-cycle path plus a branch at the end to the
1487     * instruction epilogue code.  The multi-compare approach below needs
1488     * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
1489     * in the worst case (the 64-bit values are equal).
1490     */
1491    /* cmp-long vAA, vBB, vCC */
1492    FETCH(r0, 1)                        @ r0<- CCBB
1493    mov     r9, rINST, lsr #8           @ r9<- AA
1494    and     r2, r0, #255                @ r2<- BB
1495    mov     r3, r0, lsr #8              @ r3<- CC
1496    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
1497    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
1498    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1499    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
1500    cmp     r1, r3                      @ compare (vBB+1, vCC+1)
1501    blt     .LOP_CMP_LONG_less            @ signed compare on high part
1502    bgt     .LOP_CMP_LONG_greater
1503    subs    r1, r0, r2                  @ r1<- r0 - r2
1504    bhi     .LOP_CMP_LONG_greater         @ unsigned compare on low part
1505    bne     .LOP_CMP_LONG_less
1506    b       .LOP_CMP_LONG_finish          @ equal; r1 already holds 0
1507
1508/* ------------------------------ */
1509    .balign 64
1510.L_OP_IF_EQ: /* 0x32 */
1511/* File: armv5te/OP_IF_EQ.S */
1512/* File: armv5te/bincmp.S */
1513    /*
1514     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1515     * fragment that specifies the *reverse* comparison to perform, e.g.
1516     * for "if-le" you would use "gt".
1517     *
1518     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1519     */
1520    /* if-cmp vA, vB, +CCCC */
1521    mov     r0, rINST, lsr #8           @ r0<- A+
1522    mov     r1, rINST, lsr #12          @ r1<- B
1523    and     r0, r0, #15
1524    GET_VREG(r3, r1)                    @ r3<- vB
1525    GET_VREG(r2, r0)                    @ r2<- vA
1526    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1527    cmp     r2, r3                      @ compare (vA, vB)
1528    bne  1f                      @ branch to 1 if comparison failed
1529    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1530    movs    r9, r9, asl #1              @ convert to bytes, check sign
1531    bmi     common_backwardBranch       @ yes, do periodic checks
15321:
1533#if defined(WITH_JIT)
1534    GET_JIT_PROF_TABLE(r0)
1535    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1536    b        common_testUpdateProfile
1537#else
1538    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1539    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1540    GOTO_OPCODE(ip)                     @ jump to next instruction
1541#endif
1542
1543
1544
1545/* ------------------------------ */
1546    .balign 64
1547.L_OP_IF_NE: /* 0x33 */
1548/* File: armv5te/OP_IF_NE.S */
1549/* File: armv5te/bincmp.S */
1550    /*
1551     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1552     * fragment that specifies the *reverse* comparison to perform, e.g.
1553     * for "if-le" you would use "gt".
1554     *
1555     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1556     */
1557    /* if-cmp vA, vB, +CCCC */
1558    mov     r0, rINST, lsr #8           @ r0<- A+
1559    mov     r1, rINST, lsr #12          @ r1<- B
1560    and     r0, r0, #15
1561    GET_VREG(r3, r1)                    @ r3<- vB
1562    GET_VREG(r2, r0)                    @ r2<- vA
1563    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1564    cmp     r2, r3                      @ compare (vA, vB)
1565    beq  1f                      @ branch to 1 if comparison failed
1566    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1567    movs    r9, r9, asl #1              @ convert to bytes, check sign
1568    bmi     common_backwardBranch       @ yes, do periodic checks
15691:
1570#if defined(WITH_JIT)
1571    GET_JIT_PROF_TABLE(r0)
1572    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1573    b        common_testUpdateProfile
1574#else
1575    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1576    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1577    GOTO_OPCODE(ip)                     @ jump to next instruction
1578#endif
1579
1580
1581
1582/* ------------------------------ */
1583    .balign 64
1584.L_OP_IF_LT: /* 0x34 */
1585/* File: armv5te/OP_IF_LT.S */
1586/* File: armv5te/bincmp.S */
1587    /*
1588     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1589     * fragment that specifies the *reverse* comparison to perform, e.g.
1590     * for "if-le" you would use "gt".
1591     *
1592     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1593     */
1594    /* if-cmp vA, vB, +CCCC */
1595    mov     r0, rINST, lsr #8           @ r0<- A+
1596    mov     r1, rINST, lsr #12          @ r1<- B
1597    and     r0, r0, #15
1598    GET_VREG(r3, r1)                    @ r3<- vB
1599    GET_VREG(r2, r0)                    @ r2<- vA
1600    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1601    cmp     r2, r3                      @ compare (vA, vB)
1602    bge  1f                      @ branch to 1 if comparison failed
1603    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1604    movs    r9, r9, asl #1              @ convert to bytes, check sign
1605    bmi     common_backwardBranch       @ yes, do periodic checks
16061:
1607#if defined(WITH_JIT)
1608    GET_JIT_PROF_TABLE(r0)
1609    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1610    b        common_testUpdateProfile
1611#else
1612    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1613    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1614    GOTO_OPCODE(ip)                     @ jump to next instruction
1615#endif
1616
1617
1618
1619/* ------------------------------ */
1620    .balign 64
1621.L_OP_IF_GE: /* 0x35 */
1622/* File: armv5te/OP_IF_GE.S */
1623/* File: armv5te/bincmp.S */
1624    /*
1625     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1626     * fragment that specifies the *reverse* comparison to perform, e.g.
1627     * for "if-le" you would use "gt".
1628     *
1629     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1630     */
1631    /* if-cmp vA, vB, +CCCC */
1632    mov     r0, rINST, lsr #8           @ r0<- A+
1633    mov     r1, rINST, lsr #12          @ r1<- B
1634    and     r0, r0, #15
1635    GET_VREG(r3, r1)                    @ r3<- vB
1636    GET_VREG(r2, r0)                    @ r2<- vA
1637    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1638    cmp     r2, r3                      @ compare (vA, vB)
1639    blt  1f                      @ branch to 1 if comparison failed
1640    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1641    movs    r9, r9, asl #1              @ convert to bytes, check sign
1642    bmi     common_backwardBranch       @ yes, do periodic checks
16431:
1644#if defined(WITH_JIT)
1645    GET_JIT_PROF_TABLE(r0)
1646    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1647    b        common_testUpdateProfile
1648#else
1649    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1650    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1651    GOTO_OPCODE(ip)                     @ jump to next instruction
1652#endif
1653
1654
1655
1656/* ------------------------------ */
1657    .balign 64
1658.L_OP_IF_GT: /* 0x36 */
1659/* File: armv5te/OP_IF_GT.S */
1660/* File: armv5te/bincmp.S */
1661    /*
1662     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1663     * fragment that specifies the *reverse* comparison to perform, e.g.
1664     * for "if-le" you would use "gt".
1665     *
1666     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1667     */
1668    /* if-cmp vA, vB, +CCCC */
1669    mov     r0, rINST, lsr #8           @ r0<- A+
1670    mov     r1, rINST, lsr #12          @ r1<- B
1671    and     r0, r0, #15
1672    GET_VREG(r3, r1)                    @ r3<- vB
1673    GET_VREG(r2, r0)                    @ r2<- vA
1674    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1675    cmp     r2, r3                      @ compare (vA, vB)
1676    ble  1f                      @ branch to 1 if comparison failed
1677    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1678    movs    r9, r9, asl #1              @ convert to bytes, check sign
1679    bmi     common_backwardBranch       @ yes, do periodic checks
16801:
1681#if defined(WITH_JIT)
1682    GET_JIT_PROF_TABLE(r0)
1683    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1684    b        common_testUpdateProfile
1685#else
1686    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1687    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1688    GOTO_OPCODE(ip)                     @ jump to next instruction
1689#endif
1690
1691
1692
1693/* ------------------------------ */
1694    .balign 64
1695.L_OP_IF_LE: /* 0x37 */
1696/* File: armv5te/OP_IF_LE.S */
1697/* File: armv5te/bincmp.S */
1698    /*
1699     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1700     * fragment that specifies the *reverse* comparison to perform, e.g.
1701     * for "if-le" you would use "gt".
1702     *
1703     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1704     */
1705    /* if-cmp vA, vB, +CCCC */
1706    mov     r0, rINST, lsr #8           @ r0<- A+
1707    mov     r1, rINST, lsr #12          @ r1<- B
1708    and     r0, r0, #15
1709    GET_VREG(r3, r1)                    @ r3<- vB
1710    GET_VREG(r2, r0)                    @ r2<- vA
1711    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1712    cmp     r2, r3                      @ compare (vA, vB)
1713    bgt  1f                      @ branch to 1 if comparison failed
1714    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1715    movs    r9, r9, asl #1              @ convert to bytes, check sign
1716    bmi     common_backwardBranch       @ yes, do periodic checks
17171:
1718#if defined(WITH_JIT)
1719    GET_JIT_PROF_TABLE(r0)
1720    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1721    b        common_testUpdateProfile
1722#else
1723    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1724    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1725    GOTO_OPCODE(ip)                     @ jump to next instruction
1726#endif
1727
1728
1729
1730/* ------------------------------ */
1731    .balign 64
1732.L_OP_IF_EQZ: /* 0x38 */
1733/* File: armv5te/OP_IF_EQZ.S */
1734/* File: armv5te/zcmp.S */
1735    /*
1736     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1737     * fragment that specifies the *reverse* comparison to perform, e.g.
1738     * for "if-le" you would use "gt".
1739     *
1740     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1741     */
1742    /* if-cmp vAA, +BBBB */
1743    mov     r0, rINST, lsr #8           @ r0<- AA
1744    GET_VREG(r2, r0)                    @ r2<- vAA
1745    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1746    cmp     r2, #0                      @ compare (vA, 0)
1747    bne  1f                      @ branch to 1 if comparison failed
1748    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1749    movs    r9, r9, asl #1              @ convert to bytes, check sign
1750    bmi     common_backwardBranch       @ backward branch, do periodic checks
17511:
1752#if defined(WITH_JIT)
1753    GET_JIT_PROF_TABLE(r0)
1754    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1755    cmp     r0,#0
1756    bne     common_updateProfile
1757    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1758    GOTO_OPCODE(ip)                     @ jump to next instruction
1759#else
1760    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1761    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1762    GOTO_OPCODE(ip)                     @ jump to next instruction
1763#endif
1764
1765
1766
1767/* ------------------------------ */
1768    .balign 64
1769.L_OP_IF_NEZ: /* 0x39 */
1770/* File: armv5te/OP_IF_NEZ.S */
1771/* File: armv5te/zcmp.S */
1772    /*
1773     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1774     * fragment that specifies the *reverse* comparison to perform, e.g.
1775     * for "if-le" you would use "gt".
1776     *
1777     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1778     */
1779    /* if-cmp vAA, +BBBB */
1780    mov     r0, rINST, lsr #8           @ r0<- AA
1781    GET_VREG(r2, r0)                    @ r2<- vAA
1782    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1783    cmp     r2, #0                      @ compare (vA, 0)
1784    beq  1f                      @ branch to 1 if comparison failed
1785    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1786    movs    r9, r9, asl #1              @ convert to bytes, check sign
1787    bmi     common_backwardBranch       @ backward branch, do periodic checks
17881:
1789#if defined(WITH_JIT)
1790    GET_JIT_PROF_TABLE(r0)
1791    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1792    cmp     r0,#0
1793    bne     common_updateProfile
1794    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1795    GOTO_OPCODE(ip)                     @ jump to next instruction
1796#else
1797    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1798    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1799    GOTO_OPCODE(ip)                     @ jump to next instruction
1800#endif
1801
1802
1803
1804/* ------------------------------ */
1805    .balign 64
1806.L_OP_IF_LTZ: /* 0x3a */
1807/* File: armv5te/OP_IF_LTZ.S */
1808/* File: armv5te/zcmp.S */
1809    /*
1810     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1811     * fragment that specifies the *reverse* comparison to perform, e.g.
1812     * for "if-le" you would use "gt".
1813     *
1814     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1815     */
1816    /* if-cmp vAA, +BBBB */
1817    mov     r0, rINST, lsr #8           @ r0<- AA
1818    GET_VREG(r2, r0)                    @ r2<- vAA
1819    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1820    cmp     r2, #0                      @ compare (vA, 0)
1821    bge  1f                      @ branch to 1 if comparison failed
1822    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1823    movs    r9, r9, asl #1              @ convert to bytes, check sign
1824    bmi     common_backwardBranch       @ backward branch, do periodic checks
18251:
1826#if defined(WITH_JIT)
1827    GET_JIT_PROF_TABLE(r0)
1828    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1829    cmp     r0,#0
1830    bne     common_updateProfile
1831    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1832    GOTO_OPCODE(ip)                     @ jump to next instruction
1833#else
1834    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1835    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1836    GOTO_OPCODE(ip)                     @ jump to next instruction
1837#endif
1838
1839
1840
1841/* ------------------------------ */
1842    .balign 64
1843.L_OP_IF_GEZ: /* 0x3b */
1844/* File: armv5te/OP_IF_GEZ.S */
1845/* File: armv5te/zcmp.S */
1846    /*
1847     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1848     * fragment that specifies the *reverse* comparison to perform, e.g.
1849     * for "if-le" you would use "gt".
1850     *
1851     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1852     */
1853    /* if-cmp vAA, +BBBB */
1854    mov     r0, rINST, lsr #8           @ r0<- AA
1855    GET_VREG(r2, r0)                    @ r2<- vAA
1856    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1857    cmp     r2, #0                      @ compare (vA, 0)
1858    blt  1f                      @ branch to 1 if comparison failed
1859    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1860    movs    r9, r9, asl #1              @ convert to bytes, check sign
1861    bmi     common_backwardBranch       @ backward branch, do periodic checks
18621:
1863#if defined(WITH_JIT)
1864    GET_JIT_PROF_TABLE(r0)
1865    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1866    cmp     r0,#0
1867    bne     common_updateProfile
1868    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1869    GOTO_OPCODE(ip)                     @ jump to next instruction
1870#else
1871    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1872    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1873    GOTO_OPCODE(ip)                     @ jump to next instruction
1874#endif
1875
1876
1877
1878/* ------------------------------ */
1879    .balign 64
1880.L_OP_IF_GTZ: /* 0x3c */
1881/* File: armv5te/OP_IF_GTZ.S */
1882/* File: armv5te/zcmp.S */
1883    /*
1884     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1885     * fragment that specifies the *reverse* comparison to perform, e.g.
1886     * for "if-le" you would use "gt".
1887     *
1888     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1889     */
1890    /* if-cmp vAA, +BBBB */
1891    mov     r0, rINST, lsr #8           @ r0<- AA
1892    GET_VREG(r2, r0)                    @ r2<- vAA
1893    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1894    cmp     r2, #0                      @ compare (vA, 0)
1895    ble  1f                      @ branch to 1 if comparison failed
1896    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1897    movs    r9, r9, asl #1              @ convert to bytes, check sign
1898    bmi     common_backwardBranch       @ backward branch, do periodic checks
18991:
1900#if defined(WITH_JIT)
1901    GET_JIT_PROF_TABLE(r0)
1902    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1903    cmp     r0,#0
1904    bne     common_updateProfile
1905    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1906    GOTO_OPCODE(ip)                     @ jump to next instruction
1907#else
1908    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1909    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1910    GOTO_OPCODE(ip)                     @ jump to next instruction
1911#endif
1912
1913
1914
1915/* ------------------------------ */
1916    .balign 64
1917.L_OP_IF_LEZ: /* 0x3d */
1918/* File: armv5te/OP_IF_LEZ.S */
1919/* File: armv5te/zcmp.S */
1920    /*
1921     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1922     * fragment that specifies the *reverse* comparison to perform, e.g.
1923     * for "if-le" you would use "gt".
1924     *
1925     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1926     */
1927    /* if-cmp vAA, +BBBB */
1928    mov     r0, rINST, lsr #8           @ r0<- AA
1929    GET_VREG(r2, r0)                    @ r2<- vAA
1930    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1931    cmp     r2, #0                      @ compare (vA, 0)
1932    bgt  1f                      @ branch to 1 if comparison failed
1933    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1934    movs    r9, r9, asl #1              @ convert to bytes, check sign
1935    bmi     common_backwardBranch       @ backward branch, do periodic checks
19361:
1937#if defined(WITH_JIT)
1938    GET_JIT_PROF_TABLE(r0)
1939    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1940    cmp     r0,#0
1941    bne     common_updateProfile
1942    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1943    GOTO_OPCODE(ip)                     @ jump to next instruction
1944#else
1945    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1946    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1947    GOTO_OPCODE(ip)                     @ jump to next instruction
1948#endif
1949
1950
1951
1952/* ------------------------------ */
1953    .balign 64
1954.L_OP_UNUSED_3E: /* 0x3e */
1955/* File: armv5te/OP_UNUSED_3E.S */
1956/* File: armv5te/unused.S */
1957    bl      common_abort
1958
1959
1960
1961/* ------------------------------ */
1962    .balign 64
1963.L_OP_UNUSED_3F: /* 0x3f */
1964/* File: armv5te/OP_UNUSED_3F.S */
1965/* File: armv5te/unused.S */
1966    bl      common_abort
1967
1968
1969
1970/* ------------------------------ */
1971    .balign 64
1972.L_OP_UNUSED_40: /* 0x40 */
1973/* File: armv5te/OP_UNUSED_40.S */
1974/* File: armv5te/unused.S */
1975    bl      common_abort
1976
1977
1978
1979/* ------------------------------ */
1980    .balign 64
1981.L_OP_UNUSED_41: /* 0x41 */
1982/* File: armv5te/OP_UNUSED_41.S */
1983/* File: armv5te/unused.S */
1984    bl      common_abort
1985
1986
1987
1988/* ------------------------------ */
1989    .balign 64
1990.L_OP_UNUSED_42: /* 0x42 */
1991/* File: armv5te/OP_UNUSED_42.S */
1992/* File: armv5te/unused.S */
1993    bl      common_abort
1994
1995
1996
1997/* ------------------------------ */
1998    .balign 64
1999.L_OP_UNUSED_43: /* 0x43 */
2000/* File: armv5te/OP_UNUSED_43.S */
2001/* File: armv5te/unused.S */
2002    bl      common_abort
2003
2004
2005
2006/* ------------------------------ */
2007    .balign 64
2008.L_OP_AGET: /* 0x44 */
2009/* File: armv5te/OP_AGET.S */
2010    /*
2011     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2012     *
2013     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2014     * instructions.  We use a pair of FETCH_Bs instead.
2015     *
2016     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2017     */
2018    /* op vAA, vBB, vCC */
2019    FETCH_B(r2, 1, 0)                   @ r2<- BB
2020    mov     r9, rINST, lsr #8           @ r9<- AA
2021    FETCH_B(r3, 1, 1)                   @ r3<- CC
2022    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2023    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2024    cmp     r0, #0                      @ null array object?
2025    beq     common_errNullObject        @ yes, bail
2026    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2027    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2028    cmp     r1, r3                      @ compare unsigned index, length
2029    bcs     common_errArrayIndex        @ index >= length, bail
2030    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2031    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2032    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2033    SET_VREG(r2, r9)                    @ vAA<- r2
2034    GOTO_OPCODE(ip)                     @ jump to next instruction
2035
2036
2037/* ------------------------------ */
2038    .balign 64
2039.L_OP_AGET_WIDE: /* 0x45 */
2040/* File: armv5te/OP_AGET_WIDE.S */
2041    /*
2042     * Array get, 64 bits.  vAA <- vBB[vCC].
2043     *
2044     * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD.
2045     */
2046    /* aget-wide vAA, vBB, vCC */
2047    FETCH(r0, 1)                        @ r0<- CCBB
2048    mov     r9, rINST, lsr #8           @ r9<- AA
2049    and     r2, r0, #255                @ r2<- BB
2050    mov     r3, r0, lsr #8              @ r3<- CC
2051    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2052    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2053    cmp     r0, #0                      @ null array object?
2054    beq     common_errNullObject        @ yes, bail
2055    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2056    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2057    cmp     r1, r3                      @ compare unsigned index, length
2058    bcc     .LOP_AGET_WIDE_finish          @ okay, continue below
2059    b       common_errArrayIndex        @ index >= length, bail
2060    @ May want to swap the order of these two branches depending on how the
2061    @ branch prediction (if any) handles conditional forward branches vs.
2062    @ unconditional forward branches.
2063
2064/* ------------------------------ */
2065    .balign 64
2066.L_OP_AGET_OBJECT: /* 0x46 */
2067/* File: armv5te/OP_AGET_OBJECT.S */
2068/* File: armv5te/OP_AGET.S */
2069    /*
2070     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2071     *
2072     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2073     * instructions.  We use a pair of FETCH_Bs instead.
2074     *
2075     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2076     */
2077    /* op vAA, vBB, vCC */
2078    FETCH_B(r2, 1, 0)                   @ r2<- BB
2079    mov     r9, rINST, lsr #8           @ r9<- AA
2080    FETCH_B(r3, 1, 1)                   @ r3<- CC
2081    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2082    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2083    cmp     r0, #0                      @ null array object?
2084    beq     common_errNullObject        @ yes, bail
2085    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2086    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2087    cmp     r1, r3                      @ compare unsigned index, length
2088    bcs     common_errArrayIndex        @ index >= length, bail
2089    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2090    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2091    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2092    SET_VREG(r2, r9)                    @ vAA<- r2
2093    GOTO_OPCODE(ip)                     @ jump to next instruction
2094
2095
2096
2097/* ------------------------------ */
2098    .balign 64
2099.L_OP_AGET_BOOLEAN: /* 0x47 */
2100/* File: armv5te/OP_AGET_BOOLEAN.S */
2101/* File: armv5te/OP_AGET.S */
2102    /*
2103     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2104     *
2105     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2106     * instructions.  We use a pair of FETCH_Bs instead.
2107     *
2108     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2109     */
2110    /* op vAA, vBB, vCC */
2111    FETCH_B(r2, 1, 0)                   @ r2<- BB
2112    mov     r9, rINST, lsr #8           @ r9<- AA
2113    FETCH_B(r3, 1, 1)                   @ r3<- CC
2114    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2115    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2116    cmp     r0, #0                      @ null array object?
2117    beq     common_errNullObject        @ yes, bail
2118    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2119    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2120    cmp     r1, r3                      @ compare unsigned index, length
2121    bcs     common_errArrayIndex        @ index >= length, bail
2122    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2123    ldrb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2124    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2125    SET_VREG(r2, r9)                    @ vAA<- r2
2126    GOTO_OPCODE(ip)                     @ jump to next instruction
2127
2128
2129
2130/* ------------------------------ */
2131    .balign 64
2132.L_OP_AGET_BYTE: /* 0x48 */
2133/* File: armv5te/OP_AGET_BYTE.S */
2134/* File: armv5te/OP_AGET.S */
2135    /*
2136     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2137     *
2138     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2139     * instructions.  We use a pair of FETCH_Bs instead.
2140     *
2141     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2142     */
2143    /* op vAA, vBB, vCC */
2144    FETCH_B(r2, 1, 0)                   @ r2<- BB
2145    mov     r9, rINST, lsr #8           @ r9<- AA
2146    FETCH_B(r3, 1, 1)                   @ r3<- CC
2147    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2148    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2149    cmp     r0, #0                      @ null array object?
2150    beq     common_errNullObject        @ yes, bail
2151    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2152    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2153    cmp     r1, r3                      @ compare unsigned index, length
2154    bcs     common_errArrayIndex        @ index >= length, bail
2155    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2156    ldrsb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2157    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2158    SET_VREG(r2, r9)                    @ vAA<- r2
2159    GOTO_OPCODE(ip)                     @ jump to next instruction
2160
2161
2162
2163/* ------------------------------ */
2164    .balign 64
2165.L_OP_AGET_CHAR: /* 0x49 */
2166/* File: armv5te/OP_AGET_CHAR.S */
2167/* File: armv5te/OP_AGET.S */
2168    /*
2169     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2170     *
2171     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2172     * instructions.  We use a pair of FETCH_Bs instead.
2173     *
2174     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2175     */
2176    /* op vAA, vBB, vCC */
2177    FETCH_B(r2, 1, 0)                   @ r2<- BB
2178    mov     r9, rINST, lsr #8           @ r9<- AA
2179    FETCH_B(r3, 1, 1)                   @ r3<- CC
2180    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2181    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2182    cmp     r0, #0                      @ null array object?
2183    beq     common_errNullObject        @ yes, bail
2184    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2185    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2186    cmp     r1, r3                      @ compare unsigned index, length
2187    bcs     common_errArrayIndex        @ index >= length, bail
2188    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2189    ldrh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2190    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2191    SET_VREG(r2, r9)                    @ vAA<- r2
2192    GOTO_OPCODE(ip)                     @ jump to next instruction
2193
2194
2195
2196/* ------------------------------ */
2197    .balign 64
2198.L_OP_AGET_SHORT: /* 0x4a */
2199/* File: armv5te/OP_AGET_SHORT.S */
2200/* File: armv5te/OP_AGET.S */
2201    /*
2202     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2203     *
2204     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2205     * instructions.  We use a pair of FETCH_Bs instead.
2206     *
2207     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2208     */
2209    /* op vAA, vBB, vCC */
2210    FETCH_B(r2, 1, 0)                   @ r2<- BB
2211    mov     r9, rINST, lsr #8           @ r9<- AA
2212    FETCH_B(r3, 1, 1)                   @ r3<- CC
2213    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2214    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2215    cmp     r0, #0                      @ null array object?
2216    beq     common_errNullObject        @ yes, bail
2217    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2218    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2219    cmp     r1, r3                      @ compare unsigned index, length
2220    bcs     common_errArrayIndex        @ index >= length, bail
2221    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2222    ldrsh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2223    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2224    SET_VREG(r2, r9)                    @ vAA<- r2
2225    GOTO_OPCODE(ip)                     @ jump to next instruction
2226
2227
2228
2229/* ------------------------------ */
2230    .balign 64
2231.L_OP_APUT: /* 0x4b */
2232/* File: armv5te/OP_APUT.S */
2233    /*
2234     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2235     *
2236     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2237     * instructions.  We use a pair of FETCH_Bs instead.
2238     *
2239     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2240     */
2241    /* op vAA, vBB, vCC */
2242    FETCH_B(r2, 1, 0)                   @ r2<- BB
2243    mov     r9, rINST, lsr #8           @ r9<- AA
2244    FETCH_B(r3, 1, 1)                   @ r3<- CC
2245    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2246    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2247    cmp     r0, #0                      @ null array object?
2248    beq     common_errNullObject        @ yes, bail
2249    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2250    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2251    cmp     r1, r3                      @ compare unsigned index, length
2252    bcs     common_errArrayIndex        @ index >= length, bail
2253    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2254    GET_VREG(r2, r9)                    @ r2<- vAA
2255    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2256    str  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2257    GOTO_OPCODE(ip)                     @ jump to next instruction
2258
2259
2260/* ------------------------------ */
2261    .balign 64
2262.L_OP_APUT_WIDE: /* 0x4c */
2263/* File: armv5te/OP_APUT_WIDE.S */
2264    /*
2265     * Array put, 64 bits.  vBB[vCC] <- vAA.
2266     *
2267     * Arrays of long/double are 64-bit aligned, so it's okay to use STRD.
2268     */
2269    /* aput-wide vAA, vBB, vCC */
2270    FETCH(r0, 1)                        @ r0<- CCBB
2271    mov     r9, rINST, lsr #8           @ r9<- AA
2272    and     r2, r0, #255                @ r2<- BB
2273    mov     r3, r0, lsr #8              @ r3<- CC
2274    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2275    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2276    cmp     r0, #0                      @ null array object?
2277    beq     common_errNullObject        @ yes, bail
2278    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2279    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2280    cmp     r1, r3                      @ compare unsigned index, length
2281    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2282    bcc     .LOP_APUT_WIDE_finish          @ okay, continue below
2283    b       common_errArrayIndex        @ index >= length, bail
2284    @ May want to swap the order of these two branches depending on how the
2285    @ branch prediction (if any) handles conditional forward branches vs.
2286    @ unconditional forward branches.
2287
2288/* ------------------------------ */
2289    .balign 64
2290.L_OP_APUT_OBJECT: /* 0x4d */
2291/* File: armv5te/OP_APUT_OBJECT.S */
2292    /*
2293     * Store an object into an array.  vBB[vCC] <- vAA.
2294     *
2295     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2296     * instructions.  We use a pair of FETCH_Bs instead.
2297     */
2298    /* op vAA, vBB, vCC */
2299    FETCH(r0, 1)                        @ r0<- CCBB
2300    mov     r9, rINST, lsr #8           @ r9<- AA
2301    and     r2, r0, #255                @ r2<- BB
2302    mov     r3, r0, lsr #8              @ r3<- CC
2303    GET_VREG(r1, r2)                    @ r1<- vBB (array object)
2304    GET_VREG(r0, r3)                    @ r0<- vCC (requested index)
2305    cmp     r1, #0                      @ null array object?
2306    GET_VREG(r9, r9)                    @ r9<- vAA
2307    beq     common_errNullObject        @ yes, bail
2308    ldr     r3, [r1, #offArrayObject_length]    @ r3<- arrayObj->length
2309    add     r10, r1, r0, lsl #2         @ r10<- arrayObj + index*width
2310    cmp     r0, r3                      @ compare unsigned index, length
2311    bcc     .LOP_APUT_OBJECT_finish          @ we're okay, continue on
2312    b       common_errArrayIndex        @ index >= length, bail
2313
2314
2315/* ------------------------------ */
2316    .balign 64
2317.L_OP_APUT_BOOLEAN: /* 0x4e */
2318/* File: armv5te/OP_APUT_BOOLEAN.S */
2319/* File: armv5te/OP_APUT.S */
2320    /*
2321     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2322     *
2323     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2324     * instructions.  We use a pair of FETCH_Bs instead.
2325     *
2326     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2327     */
2328    /* op vAA, vBB, vCC */
2329    FETCH_B(r2, 1, 0)                   @ r2<- BB
2330    mov     r9, rINST, lsr #8           @ r9<- AA
2331    FETCH_B(r3, 1, 1)                   @ r3<- CC
2332    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2333    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2334    cmp     r0, #0                      @ null array object?
2335    beq     common_errNullObject        @ yes, bail
2336    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2337    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2338    cmp     r1, r3                      @ compare unsigned index, length
2339    bcs     common_errArrayIndex        @ index >= length, bail
2340    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2341    GET_VREG(r2, r9)                    @ r2<- vAA
2342    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2343    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2344    GOTO_OPCODE(ip)                     @ jump to next instruction
2345
2346
2347
2348/* ------------------------------ */
2349    .balign 64
2350.L_OP_APUT_BYTE: /* 0x4f */
2351/* File: armv5te/OP_APUT_BYTE.S */
2352/* File: armv5te/OP_APUT.S */
2353    /*
2354     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2355     *
2356     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2357     * instructions.  We use a pair of FETCH_Bs instead.
2358     *
2359     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2360     */
2361    /* op vAA, vBB, vCC */
2362    FETCH_B(r2, 1, 0)                   @ r2<- BB
2363    mov     r9, rINST, lsr #8           @ r9<- AA
2364    FETCH_B(r3, 1, 1)                   @ r3<- CC
2365    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2366    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2367    cmp     r0, #0                      @ null array object?
2368    beq     common_errNullObject        @ yes, bail
2369    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2370    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2371    cmp     r1, r3                      @ compare unsigned index, length
2372    bcs     common_errArrayIndex        @ index >= length, bail
2373    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2374    GET_VREG(r2, r9)                    @ r2<- vAA
2375    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2376    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2377    GOTO_OPCODE(ip)                     @ jump to next instruction
2378
2379
2380
2381/* ------------------------------ */
2382    .balign 64
2383.L_OP_APUT_CHAR: /* 0x50 */
2384/* File: armv5te/OP_APUT_CHAR.S */
2385/* File: armv5te/OP_APUT.S */
2386    /*
2387     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2388     *
2389     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2390     * instructions.  We use a pair of FETCH_Bs instead.
2391     *
2392     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2393     */
2394    /* op vAA, vBB, vCC */
2395    FETCH_B(r2, 1, 0)                   @ r2<- BB
2396    mov     r9, rINST, lsr #8           @ r9<- AA
2397    FETCH_B(r3, 1, 1)                   @ r3<- CC
2398    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2399    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2400    cmp     r0, #0                      @ null array object?
2401    beq     common_errNullObject        @ yes, bail
2402    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2403    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2404    cmp     r1, r3                      @ compare unsigned index, length
2405    bcs     common_errArrayIndex        @ index >= length, bail
2406    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2407    GET_VREG(r2, r9)                    @ r2<- vAA
2408    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2409    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2410    GOTO_OPCODE(ip)                     @ jump to next instruction
2411
2412
2413
2414/* ------------------------------ */
2415    .balign 64
2416.L_OP_APUT_SHORT: /* 0x51 */
2417/* File: armv5te/OP_APUT_SHORT.S */
2418/* File: armv5te/OP_APUT.S */
2419    /*
2420     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2421     *
2422     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2423     * instructions.  We use a pair of FETCH_Bs instead.
2424     *
2425     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2426     */
2427    /* op vAA, vBB, vCC */
2428    FETCH_B(r2, 1, 0)                   @ r2<- BB
2429    mov     r9, rINST, lsr #8           @ r9<- AA
2430    FETCH_B(r3, 1, 1)                   @ r3<- CC
2431    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2432    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2433    cmp     r0, #0                      @ null array object?
2434    beq     common_errNullObject        @ yes, bail
2435    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2436    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2437    cmp     r1, r3                      @ compare unsigned index, length
2438    bcs     common_errArrayIndex        @ index >= length, bail
2439    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2440    GET_VREG(r2, r9)                    @ r2<- vAA
2441    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2442    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2443    GOTO_OPCODE(ip)                     @ jump to next instruction
2444
2445
2446
2447/* ------------------------------ */
2448    .balign 64
2449.L_OP_IGET: /* 0x52 */
2450/* File: armv5te/OP_IGET.S */
2451    /*
2452     * General 32-bit instance field get.
2453     *
2454     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2455     */
2456    /* op vA, vB, field@CCCC */
2457    mov     r0, rINST, lsr #12          @ r0<- B
2458    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2459    FETCH(r1, 1)                        @ r1<- field ref CCCC
2460    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2461    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2462    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2463    cmp     r0, #0                      @ is resolved entry null?
2464    bne     .LOP_IGET_finish          @ no, already resolved
24658:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2466    EXPORT_PC()                         @ resolve() could throw
2467    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2468    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2469    cmp     r0, #0
2470    bne     .LOP_IGET_finish
2471    b       common_exceptionThrown
2472
2473/* ------------------------------ */
2474    .balign 64
2475.L_OP_IGET_WIDE: /* 0x53 */
2476/* File: armv5te/OP_IGET_WIDE.S */
2477    /*
2478     * Wide 32-bit instance field get.
2479     */
2480    /* iget-wide vA, vB, field@CCCC */
2481    mov     r0, rINST, lsr #12          @ r0<- B
2482    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2483    FETCH(r1, 1)                        @ r1<- field ref CCCC
2484    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2485    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2486    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2487    cmp     r0, #0                      @ is resolved entry null?
2488    bne     .LOP_IGET_WIDE_finish          @ no, already resolved
24898:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2490    EXPORT_PC()                         @ resolve() could throw
2491    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2492    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2493    cmp     r0, #0
2494    bne     .LOP_IGET_WIDE_finish
2495    b       common_exceptionThrown
2496
2497/* ------------------------------ */
2498    .balign 64
2499.L_OP_IGET_OBJECT: /* 0x54 */
2500/* File: armv5te/OP_IGET_OBJECT.S */
2501/* File: armv5te/OP_IGET.S */
2502    /*
2503     * General 32-bit instance field get.
2504     *
2505     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2506     */
2507    /* op vA, vB, field@CCCC */
2508    mov     r0, rINST, lsr #12          @ r0<- B
2509    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2510    FETCH(r1, 1)                        @ r1<- field ref CCCC
2511    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2512    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2513    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2514    cmp     r0, #0                      @ is resolved entry null?
2515    bne     .LOP_IGET_OBJECT_finish          @ no, already resolved
25168:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2517    EXPORT_PC()                         @ resolve() could throw
2518    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2519    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2520    cmp     r0, #0
2521    bne     .LOP_IGET_OBJECT_finish
2522    b       common_exceptionThrown
2523
2524
2525/* ------------------------------ */
2526    .balign 64
2527.L_OP_IGET_BOOLEAN: /* 0x55 */
2528/* File: armv5te/OP_IGET_BOOLEAN.S */
2529@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" }
2530/* File: armv5te/OP_IGET.S */
2531    /*
2532     * General 32-bit instance field get.
2533     *
2534     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2535     */
2536    /* op vA, vB, field@CCCC */
2537    mov     r0, rINST, lsr #12          @ r0<- B
2538    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2539    FETCH(r1, 1)                        @ r1<- field ref CCCC
2540    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2541    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2542    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2543    cmp     r0, #0                      @ is resolved entry null?
2544    bne     .LOP_IGET_BOOLEAN_finish          @ no, already resolved
25458:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2546    EXPORT_PC()                         @ resolve() could throw
2547    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2548    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2549    cmp     r0, #0
2550    bne     .LOP_IGET_BOOLEAN_finish
2551    b       common_exceptionThrown
2552
2553
2554/* ------------------------------ */
2555    .balign 64
2556.L_OP_IGET_BYTE: /* 0x56 */
2557/* File: armv5te/OP_IGET_BYTE.S */
2558@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" }
2559/* File: armv5te/OP_IGET.S */
2560    /*
2561     * General 32-bit instance field get.
2562     *
2563     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2564     */
2565    /* op vA, vB, field@CCCC */
2566    mov     r0, rINST, lsr #12          @ r0<- B
2567    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2568    FETCH(r1, 1)                        @ r1<- field ref CCCC
2569    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2570    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2571    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2572    cmp     r0, #0                      @ is resolved entry null?
2573    bne     .LOP_IGET_BYTE_finish          @ no, already resolved
25748:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2575    EXPORT_PC()                         @ resolve() could throw
2576    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2577    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2578    cmp     r0, #0
2579    bne     .LOP_IGET_BYTE_finish
2580    b       common_exceptionThrown
2581
2582
2583/* ------------------------------ */
2584    .balign 64
2585.L_OP_IGET_CHAR: /* 0x57 */
2586/* File: armv5te/OP_IGET_CHAR.S */
2587@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" }
2588/* File: armv5te/OP_IGET.S */
2589    /*
2590     * General 32-bit instance field get.
2591     *
2592     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2593     */
2594    /* op vA, vB, field@CCCC */
2595    mov     r0, rINST, lsr #12          @ r0<- B
2596    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2597    FETCH(r1, 1)                        @ r1<- field ref CCCC
2598    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2599    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2600    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2601    cmp     r0, #0                      @ is resolved entry null?
2602    bne     .LOP_IGET_CHAR_finish          @ no, already resolved
26038:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2604    EXPORT_PC()                         @ resolve() could throw
2605    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2606    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2607    cmp     r0, #0
2608    bne     .LOP_IGET_CHAR_finish
2609    b       common_exceptionThrown
2610
2611
2612/* ------------------------------ */
2613    .balign 64
2614.L_OP_IGET_SHORT: /* 0x58 */
2615/* File: armv5te/OP_IGET_SHORT.S */
2616@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" }
2617/* File: armv5te/OP_IGET.S */
2618    /*
2619     * General 32-bit instance field get.
2620     *
2621     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2622     */
2623    /* op vA, vB, field@CCCC */
2624    mov     r0, rINST, lsr #12          @ r0<- B
2625    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2626    FETCH(r1, 1)                        @ r1<- field ref CCCC
2627    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2628    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2629    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2630    cmp     r0, #0                      @ is resolved entry null?
2631    bne     .LOP_IGET_SHORT_finish          @ no, already resolved
26328:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2633    EXPORT_PC()                         @ resolve() could throw
2634    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2635    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2636    cmp     r0, #0
2637    bne     .LOP_IGET_SHORT_finish
2638    b       common_exceptionThrown
2639
2640
2641/* ------------------------------ */
2642    .balign 64
2643.L_OP_IPUT: /* 0x59 */
2644/* File: armv5te/OP_IPUT.S */
2645    /*
2646     * General 32-bit instance field put.
2647     *
2648     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2649     */
2650    /* op vA, vB, field@CCCC */
2651    mov     r0, rINST, lsr #12          @ r0<- B
2652    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2653    FETCH(r1, 1)                        @ r1<- field ref CCCC
2654    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2655    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2656    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2657    cmp     r0, #0                      @ is resolved entry null?
2658    bne     .LOP_IPUT_finish          @ no, already resolved
26598:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2660    EXPORT_PC()                         @ resolve() could throw
2661    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2662    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2663    cmp     r0, #0                      @ success?
2664    bne     .LOP_IPUT_finish          @ yes, finish up
2665    b       common_exceptionThrown
2666
2667/* ------------------------------ */
2668    .balign 64
2669.L_OP_IPUT_WIDE: /* 0x5a */
2670/* File: armv5te/OP_IPUT_WIDE.S */
2671    /* iput-wide vA, vB, field@CCCC */
2672    mov     r0, rINST, lsr #12          @ r0<- B
2673    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2674    FETCH(r1, 1)                        @ r1<- field ref CCCC
2675    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2676    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2677    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2678    cmp     r0, #0                      @ is resolved entry null?
2679    bne     .LOP_IPUT_WIDE_finish          @ no, already resolved
26808:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2681    EXPORT_PC()                         @ resolve() could throw
2682    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2683    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2684    cmp     r0, #0                      @ success?
2685    bne     .LOP_IPUT_WIDE_finish          @ yes, finish up
2686    b       common_exceptionThrown
2687
2688/* ------------------------------ */
2689    .balign 64
2690.L_OP_IPUT_OBJECT: /* 0x5b */
2691/* File: armv5te/OP_IPUT_OBJECT.S */
2692/* File: armv5te/OP_IPUT.S */
2693    /*
2694     * General 32-bit instance field put.
2695     *
2696     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2697     */
2698    /* op vA, vB, field@CCCC */
2699    mov     r0, rINST, lsr #12          @ r0<- B
2700    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2701    FETCH(r1, 1)                        @ r1<- field ref CCCC
2702    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2703    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2704    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2705    cmp     r0, #0                      @ is resolved entry null?
2706    bne     .LOP_IPUT_OBJECT_finish          @ no, already resolved
27078:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2708    EXPORT_PC()                         @ resolve() could throw
2709    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2710    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2711    cmp     r0, #0                      @ success?
2712    bne     .LOP_IPUT_OBJECT_finish          @ yes, finish up
2713    b       common_exceptionThrown
2714
2715
2716/* ------------------------------ */
2717    .balign 64
2718.L_OP_IPUT_BOOLEAN: /* 0x5c */
2719/* File: armv5te/OP_IPUT_BOOLEAN.S */
2720@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" }
2721/* File: armv5te/OP_IPUT.S */
2722    /*
2723     * General 32-bit instance field put.
2724     *
2725     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2726     */
2727    /* op vA, vB, field@CCCC */
2728    mov     r0, rINST, lsr #12          @ r0<- B
2729    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2730    FETCH(r1, 1)                        @ r1<- field ref CCCC
2731    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2732    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2733    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2734    cmp     r0, #0                      @ is resolved entry null?
2735    bne     .LOP_IPUT_BOOLEAN_finish          @ no, already resolved
27368:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2737    EXPORT_PC()                         @ resolve() could throw
2738    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2739    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2740    cmp     r0, #0                      @ success?
2741    bne     .LOP_IPUT_BOOLEAN_finish          @ yes, finish up
2742    b       common_exceptionThrown
2743
2744
2745/* ------------------------------ */
2746    .balign 64
2747.L_OP_IPUT_BYTE: /* 0x5d */
2748/* File: armv5te/OP_IPUT_BYTE.S */
2749@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" }
2750/* File: armv5te/OP_IPUT.S */
2751    /*
2752     * General 32-bit instance field put.
2753     *
2754     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2755     */
2756    /* op vA, vB, field@CCCC */
2757    mov     r0, rINST, lsr #12          @ r0<- B
2758    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2759    FETCH(r1, 1)                        @ r1<- field ref CCCC
2760    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2761    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2762    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2763    cmp     r0, #0                      @ is resolved entry null?
2764    bne     .LOP_IPUT_BYTE_finish          @ no, already resolved
27658:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2766    EXPORT_PC()                         @ resolve() could throw
2767    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2768    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2769    cmp     r0, #0                      @ success?
2770    bne     .LOP_IPUT_BYTE_finish          @ yes, finish up
2771    b       common_exceptionThrown
2772
2773
2774/* ------------------------------ */
2775    .balign 64
2776.L_OP_IPUT_CHAR: /* 0x5e */
2777/* File: armv5te/OP_IPUT_CHAR.S */
2778@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" }
2779/* File: armv5te/OP_IPUT.S */
2780    /*
2781     * General 32-bit instance field put.
2782     *
2783     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2784     */
2785    /* op vA, vB, field@CCCC */
2786    mov     r0, rINST, lsr #12          @ r0<- B
2787    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2788    FETCH(r1, 1)                        @ r1<- field ref CCCC
2789    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2790    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2791    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2792    cmp     r0, #0                      @ is resolved entry null?
2793    bne     .LOP_IPUT_CHAR_finish          @ no, already resolved
27948:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2795    EXPORT_PC()                         @ resolve() could throw
2796    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2797    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2798    cmp     r0, #0                      @ success?
2799    bne     .LOP_IPUT_CHAR_finish          @ yes, finish up
2800    b       common_exceptionThrown
2801
2802
2803/* ------------------------------ */
2804    .balign 64
2805.L_OP_IPUT_SHORT: /* 0x5f */
2806/* File: armv5te/OP_IPUT_SHORT.S */
2807@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" }
2808/* File: armv5te/OP_IPUT.S */
2809    /*
2810     * General 32-bit instance field put.
2811     *
2812     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2813     */
2814    /* op vA, vB, field@CCCC */
2815    mov     r0, rINST, lsr #12          @ r0<- B
2816    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2817    FETCH(r1, 1)                        @ r1<- field ref CCCC
2818    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2819    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2820    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2821    cmp     r0, #0                      @ is resolved entry null?
2822    bne     .LOP_IPUT_SHORT_finish          @ no, already resolved
28238:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2824    EXPORT_PC()                         @ resolve() could throw
2825    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2826    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2827    cmp     r0, #0                      @ success?
2828    bne     .LOP_IPUT_SHORT_finish          @ yes, finish up
2829    b       common_exceptionThrown
2830
2831
2832/* ------------------------------ */
2833    .balign 64
2834.L_OP_SGET: /* 0x60 */
2835/* File: armv5te/OP_SGET.S */
2836    /*
2837     * General 32-bit SGET handler.
2838     *
2839     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2840     */
2841    /* op vAA, field@BBBB */
2842    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2843    FETCH(r1, 1)                        @ r1<- field ref BBBB
2844    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2845    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2846    cmp     r0, #0                      @ is resolved entry null?
2847    beq     .LOP_SGET_resolve         @ yes, do resolve
2848.LOP_SGET_finish: @ field ptr in r0
2849    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2850    mov     r2, rINST, lsr #8           @ r2<- AA
2851    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2852    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2853    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2854    GOTO_OPCODE(ip)                     @ jump to next instruction
2855
2856/* ------------------------------ */
2857    .balign 64
2858.L_OP_SGET_WIDE: /* 0x61 */
2859/* File: armv5te/OP_SGET_WIDE.S */
2860    /*
2861     * 64-bit SGET handler.
2862     */
2863    /* sget-wide vAA, field@BBBB */
2864    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2865    FETCH(r1, 1)                        @ r1<- field ref BBBB
2866    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2867    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2868    cmp     r0, #0                      @ is resolved entry null?
2869    beq     .LOP_SGET_WIDE_resolve         @ yes, do resolve
2870.LOP_SGET_WIDE_finish:
2871    mov     r1, rINST, lsr #8           @ r1<- AA
2872    ldrd    r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned)
2873    add     r1, rFP, r1, lsl #2         @ r1<- &fp[AA]
2874    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2875    stmia   r1, {r2-r3}                 @ vAA/vAA+1<- r2/r3
2876    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2877    GOTO_OPCODE(ip)                     @ jump to next instruction
2878
2879/* ------------------------------ */
2880    .balign 64
2881.L_OP_SGET_OBJECT: /* 0x62 */
2882/* File: armv5te/OP_SGET_OBJECT.S */
2883/* File: armv5te/OP_SGET.S */
2884    /*
2885     * General 32-bit SGET handler.
2886     *
2887     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2888     */
2889    /* op vAA, field@BBBB */
2890    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2891    FETCH(r1, 1)                        @ r1<- field ref BBBB
2892    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2893    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2894    cmp     r0, #0                      @ is resolved entry null?
2895    beq     .LOP_SGET_OBJECT_resolve         @ yes, do resolve
2896.LOP_SGET_OBJECT_finish: @ field ptr in r0
2897    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2898    mov     r2, rINST, lsr #8           @ r2<- AA
2899    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2900    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2901    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2902    GOTO_OPCODE(ip)                     @ jump to next instruction
2903
2904
2905/* ------------------------------ */
2906    .balign 64
2907.L_OP_SGET_BOOLEAN: /* 0x63 */
2908/* File: armv5te/OP_SGET_BOOLEAN.S */
2909/* File: armv5te/OP_SGET.S */
2910    /*
2911     * General 32-bit SGET handler.
2912     *
2913     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2914     */
2915    /* op vAA, field@BBBB */
2916    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2917    FETCH(r1, 1)                        @ r1<- field ref BBBB
2918    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2919    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2920    cmp     r0, #0                      @ is resolved entry null?
2921    beq     .LOP_SGET_BOOLEAN_resolve         @ yes, do resolve
2922.LOP_SGET_BOOLEAN_finish: @ field ptr in r0
2923    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2924    mov     r2, rINST, lsr #8           @ r2<- AA
2925    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2926    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2927    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2928    GOTO_OPCODE(ip)                     @ jump to next instruction
2929
2930
2931/* ------------------------------ */
2932    .balign 64
2933.L_OP_SGET_BYTE: /* 0x64 */
2934/* File: armv5te/OP_SGET_BYTE.S */
2935/* File: armv5te/OP_SGET.S */
2936    /*
2937     * General 32-bit SGET handler.
2938     *
2939     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2940     */
2941    /* op vAA, field@BBBB */
2942    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2943    FETCH(r1, 1)                        @ r1<- field ref BBBB
2944    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2945    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2946    cmp     r0, #0                      @ is resolved entry null?
2947    beq     .LOP_SGET_BYTE_resolve         @ yes, do resolve
2948.LOP_SGET_BYTE_finish: @ field ptr in r0
2949    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2950    mov     r2, rINST, lsr #8           @ r2<- AA
2951    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2952    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2953    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2954    GOTO_OPCODE(ip)                     @ jump to next instruction
2955
2956
2957/* ------------------------------ */
2958    .balign 64
2959.L_OP_SGET_CHAR: /* 0x65 */
2960/* File: armv5te/OP_SGET_CHAR.S */
2961/* File: armv5te/OP_SGET.S */
2962    /*
2963     * General 32-bit SGET handler.
2964     *
2965     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2966     */
2967    /* op vAA, field@BBBB */
2968    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2969    FETCH(r1, 1)                        @ r1<- field ref BBBB
2970    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2971    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2972    cmp     r0, #0                      @ is resolved entry null?
2973    beq     .LOP_SGET_CHAR_resolve         @ yes, do resolve
2974.LOP_SGET_CHAR_finish: @ field ptr in r0
2975    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2976    mov     r2, rINST, lsr #8           @ r2<- AA
2977    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2978    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2979    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2980    GOTO_OPCODE(ip)                     @ jump to next instruction
2981
2982
2983/* ------------------------------ */
2984    .balign 64
2985.L_OP_SGET_SHORT: /* 0x66 */
2986/* File: armv5te/OP_SGET_SHORT.S */
2987/* File: armv5te/OP_SGET.S */
2988    /*
2989     * General 32-bit SGET handler.
2990     *
2991     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2992     */
2993    /* op vAA, field@BBBB */
2994    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2995    FETCH(r1, 1)                        @ r1<- field ref BBBB
2996    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2997    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2998    cmp     r0, #0                      @ is resolved entry null?
2999    beq     .LOP_SGET_SHORT_resolve         @ yes, do resolve
3000.LOP_SGET_SHORT_finish: @ field ptr in r0
3001    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
3002    mov     r2, rINST, lsr #8           @ r2<- AA
3003    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3004    SET_VREG(r1, r2)                    @ fp[AA]<- r1
3005    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3006    GOTO_OPCODE(ip)                     @ jump to next instruction
3007
3008
3009/* ------------------------------ */
3010    .balign 64
3011.L_OP_SPUT: /* 0x67 */
3012/* File: armv5te/OP_SPUT.S */
3013    /*
3014     * General 32-bit SPUT handler.
3015     *
3016     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3017     */
3018    /* op vAA, field@BBBB */
3019    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3020    FETCH(r1, 1)                        @ r1<- field ref BBBB
3021    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3022    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3023    cmp     r0, #0                      @ is resolved entry null?
3024    beq     .LOP_SPUT_resolve         @ yes, do resolve
3025.LOP_SPUT_finish:   @ field ptr in r0
3026    mov     r2, rINST, lsr #8           @ r2<- AA
3027    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3028    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3029    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3030    str     r1, [r0, #offStaticField_value] @ field<- vAA
3031    GOTO_OPCODE(ip)                     @ jump to next instruction
3032
3033/* ------------------------------ */
3034    .balign 64
3035.L_OP_SPUT_WIDE: /* 0x68 */
3036/* File: armv5te/OP_SPUT_WIDE.S */
3037    /*
3038     * 64-bit SPUT handler.
3039     */
3040    /* sput-wide vAA, field@BBBB */
3041    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3042    FETCH(r1, 1)                        @ r1<- field ref BBBB
3043    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3044    mov     r9, rINST, lsr #8           @ r9<- AA
3045    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3046    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
3047    cmp     r0, #0                      @ is resolved entry null?
3048    beq     .LOP_SPUT_WIDE_resolve         @ yes, do resolve
3049.LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9
3050    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3051    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
3052    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3053    strd    r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1
3054    GOTO_OPCODE(ip)                     @ jump to next instruction
3055
3056/* ------------------------------ */
3057    .balign 64
3058.L_OP_SPUT_OBJECT: /* 0x69 */
3059/* File: armv5te/OP_SPUT_OBJECT.S */
3060/* File: armv5te/OP_SPUT.S */
3061    /*
3062     * General 32-bit SPUT handler.
3063     *
3064     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3065     */
3066    /* op vAA, field@BBBB */
3067    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3068    FETCH(r1, 1)                        @ r1<- field ref BBBB
3069    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3070    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3071    cmp     r0, #0                      @ is resolved entry null?
3072    beq     .LOP_SPUT_OBJECT_resolve         @ yes, do resolve
3073.LOP_SPUT_OBJECT_finish:   @ field ptr in r0
3074    mov     r2, rINST, lsr #8           @ r2<- AA
3075    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3076    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3077    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3078    str     r1, [r0, #offStaticField_value] @ field<- vAA
3079    GOTO_OPCODE(ip)                     @ jump to next instruction
3080
3081
3082/* ------------------------------ */
3083    .balign 64
3084.L_OP_SPUT_BOOLEAN: /* 0x6a */
3085/* File: armv5te/OP_SPUT_BOOLEAN.S */
3086/* File: armv5te/OP_SPUT.S */
3087    /*
3088     * General 32-bit SPUT handler.
3089     *
3090     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3091     */
3092    /* op vAA, field@BBBB */
3093    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3094    FETCH(r1, 1)                        @ r1<- field ref BBBB
3095    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3096    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3097    cmp     r0, #0                      @ is resolved entry null?
3098    beq     .LOP_SPUT_BOOLEAN_resolve         @ yes, do resolve
3099.LOP_SPUT_BOOLEAN_finish:   @ field ptr in r0
3100    mov     r2, rINST, lsr #8           @ r2<- AA
3101    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3102    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3103    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3104    str     r1, [r0, #offStaticField_value] @ field<- vAA
3105    GOTO_OPCODE(ip)                     @ jump to next instruction
3106
3107
3108/* ------------------------------ */
3109    .balign 64
3110.L_OP_SPUT_BYTE: /* 0x6b */
3111/* File: armv5te/OP_SPUT_BYTE.S */
3112/* File: armv5te/OP_SPUT.S */
3113    /*
3114     * General 32-bit SPUT handler.
3115     *
3116     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3117     */
3118    /* op vAA, field@BBBB */
3119    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3120    FETCH(r1, 1)                        @ r1<- field ref BBBB
3121    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3122    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3123    cmp     r0, #0                      @ is resolved entry null?
3124    beq     .LOP_SPUT_BYTE_resolve         @ yes, do resolve
3125.LOP_SPUT_BYTE_finish:   @ field ptr in r0
3126    mov     r2, rINST, lsr #8           @ r2<- AA
3127    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3128    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3129    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3130    str     r1, [r0, #offStaticField_value] @ field<- vAA
3131    GOTO_OPCODE(ip)                     @ jump to next instruction
3132
3133
3134/* ------------------------------ */
3135    .balign 64
3136.L_OP_SPUT_CHAR: /* 0x6c */
3137/* File: armv5te/OP_SPUT_CHAR.S */
3138/* File: armv5te/OP_SPUT.S */
3139    /*
3140     * General 32-bit SPUT handler.
3141     *
3142     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3143     */
3144    /* op vAA, field@BBBB */
3145    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3146    FETCH(r1, 1)                        @ r1<- field ref BBBB
3147    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3148    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3149    cmp     r0, #0                      @ is resolved entry null?
3150    beq     .LOP_SPUT_CHAR_resolve         @ yes, do resolve
3151.LOP_SPUT_CHAR_finish:   @ field ptr in r0
3152    mov     r2, rINST, lsr #8           @ r2<- AA
3153    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3154    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3155    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3156    str     r1, [r0, #offStaticField_value] @ field<- vAA
3157    GOTO_OPCODE(ip)                     @ jump to next instruction
3158
3159
3160/* ------------------------------ */
3161    .balign 64
3162.L_OP_SPUT_SHORT: /* 0x6d */
3163/* File: armv5te/OP_SPUT_SHORT.S */
3164/* File: armv5te/OP_SPUT.S */
3165    /*
3166     * General 32-bit SPUT handler.
3167     *
3168     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3169     */
3170    /* op vAA, field@BBBB */
3171    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3172    FETCH(r1, 1)                        @ r1<- field ref BBBB
3173    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3174    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3175    cmp     r0, #0                      @ is resolved entry null?
3176    beq     .LOP_SPUT_SHORT_resolve         @ yes, do resolve
3177.LOP_SPUT_SHORT_finish:   @ field ptr in r0
3178    mov     r2, rINST, lsr #8           @ r2<- AA
3179    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3180    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3181    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3182    str     r1, [r0, #offStaticField_value] @ field<- vAA
3183    GOTO_OPCODE(ip)                     @ jump to next instruction
3184
3185
3186/* ------------------------------ */
3187    .balign 64
3188.L_OP_INVOKE_VIRTUAL: /* 0x6e */
3189/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3190    /*
3191     * Handle a virtual method call.
3192     *
3193     * for: invoke-virtual, invoke-virtual/range
3194     */
3195    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3196    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3197    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3198    FETCH(r1, 1)                        @ r1<- BBBB
3199    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3200    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3201    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3202    .if     (!0)
3203    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3204    .endif
3205    cmp     r0, #0                      @ already resolved?
3206    EXPORT_PC()                         @ must export for invoke
3207    bne     .LOP_INVOKE_VIRTUAL_continue        @ yes, continue on
3208    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3209    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3210    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3211    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3212    cmp     r0, #0                      @ got null?
3213    bne     .LOP_INVOKE_VIRTUAL_continue        @ no, continue
3214    b       common_exceptionThrown      @ yes, handle exception
3215
3216/* ------------------------------ */
3217    .balign 64
3218.L_OP_INVOKE_SUPER: /* 0x6f */
3219/* File: armv5te/OP_INVOKE_SUPER.S */
3220    /*
3221     * Handle a "super" method call.
3222     *
3223     * for: invoke-super, invoke-super/range
3224     */
3225    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3226    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3227    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3228    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3229    .if     (!0)
3230    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3231    .endif
3232    FETCH(r1, 1)                        @ r1<- BBBB
3233    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3234    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3235    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3236    cmp     r2, #0                      @ null "this"?
3237    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3238    beq     common_errNullObject        @ null "this", throw exception
3239    cmp     r0, #0                      @ already resolved?
3240    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3241    EXPORT_PC()                         @ must export for invoke
3242    bne     .LOP_INVOKE_SUPER_continue        @ resolved, continue on
3243    b       .LOP_INVOKE_SUPER_resolve         @ do resolve now
3244
3245/* ------------------------------ */
3246    .balign 64
3247.L_OP_INVOKE_DIRECT: /* 0x70 */
3248/* File: armv5te/OP_INVOKE_DIRECT.S */
3249    /*
3250     * Handle a direct method call.
3251     *
3252     * (We could defer the "is 'this' pointer null" test to the common
3253     * method invocation code, and use a flag to indicate that static
3254     * calls don't count.  If we do this as part of copying the arguments
3255     * out we could avoiding loading the first arg twice.)
3256     *
3257     * for: invoke-direct, invoke-direct/range
3258     */
3259    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3260    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3261    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3262    FETCH(r1, 1)                        @ r1<- BBBB
3263    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3264    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3265    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3266    .if     (!0)
3267    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3268    .endif
3269    cmp     r0, #0                      @ already resolved?
3270    EXPORT_PC()                         @ must export for invoke
3271    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3272    beq     .LOP_INVOKE_DIRECT_resolve         @ not resolved, do it now
3273.LOP_INVOKE_DIRECT_finish:
3274    cmp     r2, #0                      @ null "this" ref?
3275    bne     common_invokeMethodNoRange   @ no, continue on
3276    b       common_errNullObject        @ yes, throw exception
3277
3278/* ------------------------------ */
3279    .balign 64
3280.L_OP_INVOKE_STATIC: /* 0x71 */
3281/* File: armv5te/OP_INVOKE_STATIC.S */
3282    /*
3283     * Handle a static method call.
3284     *
3285     * for: invoke-static, invoke-static/range
3286     */
3287    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3288    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3289    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3290    FETCH(r1, 1)                        @ r1<- BBBB
3291    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3292    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3293    cmp     r0, #0                      @ already resolved?
3294    EXPORT_PC()                         @ must export for invoke
3295    bne     common_invokeMethodNoRange @ yes, continue on
32960:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3297    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3298    mov     r2, #METHOD_STATIC          @ resolver method type
3299    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3300    cmp     r0, #0                      @ got null?
3301    bne     common_invokeMethodNoRange @ no, continue
3302    b       common_exceptionThrown      @ yes, handle exception
3303
3304
3305/* ------------------------------ */
3306    .balign 64
3307.L_OP_INVOKE_INTERFACE: /* 0x72 */
3308/* File: armv5te/OP_INVOKE_INTERFACE.S */
3309    /*
3310     * Handle an interface method call.
3311     *
3312     * for: invoke-interface, invoke-interface/range
3313     */
3314    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3315    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3316    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3317    FETCH(r1, 1)                        @ r1<- BBBB
3318    .if     (!0)
3319    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3320    .endif
3321    EXPORT_PC()                         @ must export for invoke
3322    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3323    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3324    cmp     r0, #0                      @ null obj?
3325    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3326    beq     common_errNullObject        @ yes, fail
3327    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3328    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3329    cmp     r0, #0                      @ failed?
3330    beq     common_exceptionThrown      @ yes, handle exception
3331    b       common_invokeMethodNoRange @ jump to common handler
3332
3333
3334/* ------------------------------ */
3335    .balign 64
3336.L_OP_UNUSED_73: /* 0x73 */
3337/* File: armv5te/OP_UNUSED_73.S */
3338/* File: armv5te/unused.S */
3339    bl      common_abort
3340
3341
3342
3343/* ------------------------------ */
3344    .balign 64
3345.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
3346/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */
3347/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3348    /*
3349     * Handle a virtual method call.
3350     *
3351     * for: invoke-virtual, invoke-virtual/range
3352     */
3353    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3354    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3355    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3356    FETCH(r1, 1)                        @ r1<- BBBB
3357    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3358    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3359    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3360    .if     (!1)
3361    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3362    .endif
3363    cmp     r0, #0                      @ already resolved?
3364    EXPORT_PC()                         @ must export for invoke
3365    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ yes, continue on
3366    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3367    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3368    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3369    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3370    cmp     r0, #0                      @ got null?
3371    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ no, continue
3372    b       common_exceptionThrown      @ yes, handle exception
3373
3374
3375/* ------------------------------ */
3376    .balign 64
3377.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
3378/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */
3379/* File: armv5te/OP_INVOKE_SUPER.S */
3380    /*
3381     * Handle a "super" method call.
3382     *
3383     * for: invoke-super, invoke-super/range
3384     */
3385    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3386    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3387    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3388    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3389    .if     (!1)
3390    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3391    .endif
3392    FETCH(r1, 1)                        @ r1<- BBBB
3393    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3394    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3395    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3396    cmp     r2, #0                      @ null "this"?
3397    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3398    beq     common_errNullObject        @ null "this", throw exception
3399    cmp     r0, #0                      @ already resolved?
3400    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3401    EXPORT_PC()                         @ must export for invoke
3402    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ resolved, continue on
3403    b       .LOP_INVOKE_SUPER_RANGE_resolve         @ do resolve now
3404
3405
3406/* ------------------------------ */
3407    .balign 64
3408.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
3409/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */
3410/* File: armv5te/OP_INVOKE_DIRECT.S */
3411    /*
3412     * Handle a direct method call.
3413     *
3414     * (We could defer the "is 'this' pointer null" test to the common
3415     * method invocation code, and use a flag to indicate that static
3416     * calls don't count.  If we do this as part of copying the arguments
3417     * out we could avoiding loading the first arg twice.)
3418     *
3419     * for: invoke-direct, invoke-direct/range
3420     */
3421    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3422    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3423    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3424    FETCH(r1, 1)                        @ r1<- BBBB
3425    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3426    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3427    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3428    .if     (!1)
3429    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3430    .endif
3431    cmp     r0, #0                      @ already resolved?
3432    EXPORT_PC()                         @ must export for invoke
3433    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3434    beq     .LOP_INVOKE_DIRECT_RANGE_resolve         @ not resolved, do it now
3435.LOP_INVOKE_DIRECT_RANGE_finish:
3436    cmp     r2, #0                      @ null "this" ref?
3437    bne     common_invokeMethodRange   @ no, continue on
3438    b       common_errNullObject        @ yes, throw exception
3439
3440
3441/* ------------------------------ */
3442    .balign 64
3443.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
3444/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */
3445/* File: armv5te/OP_INVOKE_STATIC.S */
3446    /*
3447     * Handle a static method call.
3448     *
3449     * for: invoke-static, invoke-static/range
3450     */
3451    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3452    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3453    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3454    FETCH(r1, 1)                        @ r1<- BBBB
3455    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3456    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3457    cmp     r0, #0                      @ already resolved?
3458    EXPORT_PC()                         @ must export for invoke
3459    bne     common_invokeMethodRange @ yes, continue on
34600:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3461    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3462    mov     r2, #METHOD_STATIC          @ resolver method type
3463    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3464    cmp     r0, #0                      @ got null?
3465    bne     common_invokeMethodRange @ no, continue
3466    b       common_exceptionThrown      @ yes, handle exception
3467
3468
3469
3470/* ------------------------------ */
3471    .balign 64
3472.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
3473/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */
3474/* File: armv5te/OP_INVOKE_INTERFACE.S */
3475    /*
3476     * Handle an interface method call.
3477     *
3478     * for: invoke-interface, invoke-interface/range
3479     */
3480    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3481    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3482    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3483    FETCH(r1, 1)                        @ r1<- BBBB
3484    .if     (!1)
3485    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3486    .endif
3487    EXPORT_PC()                         @ must export for invoke
3488    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3489    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3490    cmp     r0, #0                      @ null obj?
3491    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3492    beq     common_errNullObject        @ yes, fail
3493    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3494    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3495    cmp     r0, #0                      @ failed?
3496    beq     common_exceptionThrown      @ yes, handle exception
3497    b       common_invokeMethodRange @ jump to common handler
3498
3499
3500
3501/* ------------------------------ */
3502    .balign 64
3503.L_OP_UNUSED_79: /* 0x79 */
3504/* File: armv5te/OP_UNUSED_79.S */
3505/* File: armv5te/unused.S */
3506    bl      common_abort
3507
3508
3509
3510/* ------------------------------ */
3511    .balign 64
3512.L_OP_UNUSED_7A: /* 0x7a */
3513/* File: armv5te/OP_UNUSED_7A.S */
3514/* File: armv5te/unused.S */
3515    bl      common_abort
3516
3517
3518
3519/* ------------------------------ */
3520    .balign 64
3521.L_OP_NEG_INT: /* 0x7b */
3522/* File: armv5te/OP_NEG_INT.S */
3523/* File: armv5te/unop.S */
3524    /*
3525     * Generic 32-bit unary operation.  Provide an "instr" line that
3526     * specifies an instruction that performs "result = op r0".
3527     * This could be an ARM instruction or a function call.
3528     *
3529     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3530     *      int-to-byte, int-to-char, int-to-short
3531     */
3532    /* unop vA, vB */
3533    mov     r3, rINST, lsr #12          @ r3<- B
3534    mov     r9, rINST, lsr #8           @ r9<- A+
3535    GET_VREG(r0, r3)                    @ r0<- vB
3536    and     r9, r9, #15
3537                               @ optional op; may set condition codes
3538    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3539    rsb     r0, r0, #0                              @ r0<- op, r0-r3 changed
3540    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3541    SET_VREG(r0, r9)                    @ vAA<- r0
3542    GOTO_OPCODE(ip)                     @ jump to next instruction
3543    /* 9-10 instructions */
3544
3545
3546/* ------------------------------ */
3547    .balign 64
3548.L_OP_NOT_INT: /* 0x7c */
3549/* File: armv5te/OP_NOT_INT.S */
3550/* File: armv5te/unop.S */
3551    /*
3552     * Generic 32-bit unary operation.  Provide an "instr" line that
3553     * specifies an instruction that performs "result = op r0".
3554     * This could be an ARM instruction or a function call.
3555     *
3556     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3557     *      int-to-byte, int-to-char, int-to-short
3558     */
3559    /* unop vA, vB */
3560    mov     r3, rINST, lsr #12          @ r3<- B
3561    mov     r9, rINST, lsr #8           @ r9<- A+
3562    GET_VREG(r0, r3)                    @ r0<- vB
3563    and     r9, r9, #15
3564                               @ optional op; may set condition codes
3565    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3566    mvn     r0, r0                              @ r0<- op, r0-r3 changed
3567    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3568    SET_VREG(r0, r9)                    @ vAA<- r0
3569    GOTO_OPCODE(ip)                     @ jump to next instruction
3570    /* 9-10 instructions */
3571
3572
3573/* ------------------------------ */
3574    .balign 64
3575.L_OP_NEG_LONG: /* 0x7d */
3576/* File: armv5te/OP_NEG_LONG.S */
3577/* File: armv5te/unopWide.S */
3578    /*
3579     * Generic 64-bit unary operation.  Provide an "instr" line that
3580     * specifies an instruction that performs "result = op r0/r1".
3581     * This could be an ARM instruction or a function call.
3582     *
3583     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3584     */
3585    /* unop vA, vB */
3586    mov     r9, rINST, lsr #8           @ r9<- A+
3587    mov     r3, rINST, lsr #12          @ r3<- B
3588    and     r9, r9, #15
3589    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3590    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3591    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3592    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3593    rsbs    r0, r0, #0                           @ optional op; may set condition codes
3594    rsc     r1, r1, #0                              @ r0/r1<- op, r2-r3 changed
3595    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3596    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3597    GOTO_OPCODE(ip)                     @ jump to next instruction
3598    /* 12-13 instructions */
3599
3600
3601
3602/* ------------------------------ */
3603    .balign 64
3604.L_OP_NOT_LONG: /* 0x7e */
3605/* File: armv5te/OP_NOT_LONG.S */
3606/* File: armv5te/unopWide.S */
3607    /*
3608     * Generic 64-bit unary operation.  Provide an "instr" line that
3609     * specifies an instruction that performs "result = op r0/r1".
3610     * This could be an ARM instruction or a function call.
3611     *
3612     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3613     */
3614    /* unop vA, vB */
3615    mov     r9, rINST, lsr #8           @ r9<- A+
3616    mov     r3, rINST, lsr #12          @ r3<- B
3617    and     r9, r9, #15
3618    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3619    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3620    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3621    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3622    mvn     r0, r0                           @ optional op; may set condition codes
3623    mvn     r1, r1                              @ r0/r1<- op, r2-r3 changed
3624    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3625    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3626    GOTO_OPCODE(ip)                     @ jump to next instruction
3627    /* 12-13 instructions */
3628
3629
3630
3631/* ------------------------------ */
3632    .balign 64
3633.L_OP_NEG_FLOAT: /* 0x7f */
3634/* File: armv5te/OP_NEG_FLOAT.S */
3635/* File: armv5te/unop.S */
3636    /*
3637     * Generic 32-bit unary operation.  Provide an "instr" line that
3638     * specifies an instruction that performs "result = op r0".
3639     * This could be an ARM instruction or a function call.
3640     *
3641     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3642     *      int-to-byte, int-to-char, int-to-short
3643     */
3644    /* unop vA, vB */
3645    mov     r3, rINST, lsr #12          @ r3<- B
3646    mov     r9, rINST, lsr #8           @ r9<- A+
3647    GET_VREG(r0, r3)                    @ r0<- vB
3648    and     r9, r9, #15
3649                               @ optional op; may set condition codes
3650    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3651    add     r0, r0, #0x80000000                              @ r0<- op, r0-r3 changed
3652    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3653    SET_VREG(r0, r9)                    @ vAA<- r0
3654    GOTO_OPCODE(ip)                     @ jump to next instruction
3655    /* 9-10 instructions */
3656
3657
3658/* ------------------------------ */
3659    .balign 64
3660.L_OP_NEG_DOUBLE: /* 0x80 */
3661/* File: armv5te/OP_NEG_DOUBLE.S */
3662/* File: armv5te/unopWide.S */
3663    /*
3664     * Generic 64-bit unary operation.  Provide an "instr" line that
3665     * specifies an instruction that performs "result = op r0/r1".
3666     * This could be an ARM instruction or a function call.
3667     *
3668     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3669     */
3670    /* unop vA, vB */
3671    mov     r9, rINST, lsr #8           @ r9<- A+
3672    mov     r3, rINST, lsr #12          @ r3<- B
3673    and     r9, r9, #15
3674    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3675    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3676    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3677    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3678                               @ optional op; may set condition codes
3679    add     r1, r1, #0x80000000                              @ r0/r1<- op, r2-r3 changed
3680    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3681    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3682    GOTO_OPCODE(ip)                     @ jump to next instruction
3683    /* 12-13 instructions */
3684
3685
3686
3687/* ------------------------------ */
3688    .balign 64
3689.L_OP_INT_TO_LONG: /* 0x81 */
3690/* File: armv5te/OP_INT_TO_LONG.S */
3691/* File: armv5te/unopWider.S */
3692    /*
3693     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3694     * that specifies an instruction that performs "result = op r0", where
3695     * "result" is a 64-bit quantity in r0/r1.
3696     *
3697     * For: int-to-long, int-to-double, float-to-long, float-to-double
3698     */
3699    /* unop vA, vB */
3700    mov     r9, rINST, lsr #8           @ r9<- A+
3701    mov     r3, rINST, lsr #12          @ r3<- B
3702    and     r9, r9, #15
3703    GET_VREG(r0, r3)                    @ r0<- vB
3704    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3705                               @ optional op; may set condition codes
3706    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3707    mov     r1, r0, asr #31                              @ r0<- op, r0-r3 changed
3708    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3709    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3710    GOTO_OPCODE(ip)                     @ jump to next instruction
3711    /* 10-11 instructions */
3712
3713
3714/* ------------------------------ */
3715    .balign 64
3716.L_OP_INT_TO_FLOAT: /* 0x82 */
3717/* File: arm-vfp/OP_INT_TO_FLOAT.S */
3718/* File: arm-vfp/funop.S */
3719    /*
3720     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3721     * line that specifies an instruction that performs "s1 = op s0".
3722     *
3723     * for: int-to-float, float-to-int
3724     */
3725    /* unop vA, vB */
3726    mov     r3, rINST, lsr #12          @ r3<- B
3727    mov     r9, rINST, lsr #8           @ r9<- A+
3728    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3729    flds    s0, [r3]                    @ s0<- vB
3730    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3731    and     r9, r9, #15                 @ r9<- A
3732    fsitos  s1, s0                              @ s1<- op
3733    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3734    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3735    fsts    s1, [r9]                    @ vA<- s1
3736    GOTO_OPCODE(ip)                     @ jump to next instruction
3737
3738
3739/* ------------------------------ */
3740    .balign 64
3741.L_OP_INT_TO_DOUBLE: /* 0x83 */
3742/* File: arm-vfp/OP_INT_TO_DOUBLE.S */
3743/* File: arm-vfp/funopWider.S */
3744    /*
3745     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3746     * "instr" line that specifies an instruction that performs "d0 = op s0".
3747     *
3748     * For: int-to-double, float-to-double
3749     */
3750    /* unop vA, vB */
3751    mov     r3, rINST, lsr #12          @ r3<- B
3752    mov     r9, rINST, lsr #8           @ r9<- A+
3753    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3754    flds    s0, [r3]                    @ s0<- vB
3755    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3756    and     r9, r9, #15                 @ r9<- A
3757    fsitod  d0, s0                              @ d0<- op
3758    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3759    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3760    fstd    d0, [r9]                    @ vA<- d0
3761    GOTO_OPCODE(ip)                     @ jump to next instruction
3762
3763
3764/* ------------------------------ */
3765    .balign 64
3766.L_OP_LONG_TO_INT: /* 0x84 */
3767/* File: armv5te/OP_LONG_TO_INT.S */
3768/* we ignore the high word, making this equivalent to a 32-bit reg move */
3769/* File: armv5te/OP_MOVE.S */
3770    /* for move, move-object, long-to-int */
3771    /* op vA, vB */
3772    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
3773    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
3774    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3775    GET_VREG(r2, r1)                    @ r2<- fp[B]
3776    and     r0, r0, #15
3777    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
3778    SET_VREG(r2, r0)                    @ fp[A]<- r2
3779    GOTO_OPCODE(ip)                     @ execute next instruction
3780
3781
3782
3783/* ------------------------------ */
3784    .balign 64
3785.L_OP_LONG_TO_FLOAT: /* 0x85 */
3786/* File: armv5te/OP_LONG_TO_FLOAT.S */
3787/* File: armv5te/unopNarrower.S */
3788    /*
3789     * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
3790     * that specifies an instruction that performs "result = op r0/r1", where
3791     * "result" is a 32-bit quantity in r0.
3792     *
3793     * For: long-to-float, double-to-int, double-to-float
3794     *
3795     * (This would work for long-to-int, but that instruction is actually
3796     * an exact match for OP_MOVE.)
3797     */
3798    /* unop vA, vB */
3799    mov     r3, rINST, lsr #12          @ r3<- B
3800    mov     r9, rINST, lsr #8           @ r9<- A+
3801    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3802    and     r9, r9, #15
3803    ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
3804    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3805                               @ optional op; may set condition codes
3806    bl      __aeabi_l2f                              @ r0<- op, r0-r3 changed
3807    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3808    SET_VREG(r0, r9)                    @ vA<- r0
3809    GOTO_OPCODE(ip)                     @ jump to next instruction
3810    /* 10-11 instructions */
3811
3812
3813/* ------------------------------ */
3814    .balign 64
3815.L_OP_LONG_TO_DOUBLE: /* 0x86 */
3816/* File: armv5te/OP_LONG_TO_DOUBLE.S */
3817/* File: armv5te/unopWide.S */
3818    /*
3819     * Generic 64-bit unary operation.  Provide an "instr" line that
3820     * specifies an instruction that performs "result = op r0/r1".
3821     * This could be an ARM instruction or a function call.
3822     *
3823     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3824     */
3825    /* unop vA, vB */
3826    mov     r9, rINST, lsr #8           @ r9<- A+
3827    mov     r3, rINST, lsr #12          @ r3<- B
3828    and     r9, r9, #15
3829    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3830    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3831    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3832    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3833                               @ optional op; may set condition codes
3834    bl      __aeabi_l2d                              @ r0/r1<- op, r2-r3 changed
3835    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3836    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3837    GOTO_OPCODE(ip)                     @ jump to next instruction
3838    /* 12-13 instructions */
3839
3840
3841
3842/* ------------------------------ */
3843    .balign 64
3844.L_OP_FLOAT_TO_INT: /* 0x87 */
3845/* File: arm-vfp/OP_FLOAT_TO_INT.S */
3846/* File: arm-vfp/funop.S */
3847    /*
3848     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3849     * line that specifies an instruction that performs "s1 = op s0".
3850     *
3851     * for: int-to-float, float-to-int
3852     */
3853    /* unop vA, vB */
3854    mov     r3, rINST, lsr #12          @ r3<- B
3855    mov     r9, rINST, lsr #8           @ r9<- A+
3856    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3857    flds    s0, [r3]                    @ s0<- vB
3858    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3859    and     r9, r9, #15                 @ r9<- A
3860    ftosizs s1, s0                              @ s1<- op
3861    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3862    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3863    fsts    s1, [r9]                    @ vA<- s1
3864    GOTO_OPCODE(ip)                     @ jump to next instruction
3865
3866
3867/* ------------------------------ */
3868    .balign 64
3869.L_OP_FLOAT_TO_LONG: /* 0x88 */
3870/* File: armv5te/OP_FLOAT_TO_LONG.S */
3871@include "armv5te/unopWider.S" {"instr":"bl      __aeabi_f2lz"}
3872/* File: armv5te/unopWider.S */
3873    /*
3874     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3875     * that specifies an instruction that performs "result = op r0", where
3876     * "result" is a 64-bit quantity in r0/r1.
3877     *
3878     * For: int-to-long, int-to-double, float-to-long, float-to-double
3879     */
3880    /* unop vA, vB */
3881    mov     r9, rINST, lsr #8           @ r9<- A+
3882    mov     r3, rINST, lsr #12          @ r3<- B
3883    and     r9, r9, #15
3884    GET_VREG(r0, r3)                    @ r0<- vB
3885    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3886                               @ optional op; may set condition codes
3887    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3888    bl      f2l_doconv                              @ r0<- op, r0-r3 changed
3889    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3890    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3891    GOTO_OPCODE(ip)                     @ jump to next instruction
3892    /* 10-11 instructions */
3893
3894
3895
3896/* ------------------------------ */
3897    .balign 64
3898.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
3899/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */
3900/* File: arm-vfp/funopWider.S */
3901    /*
3902     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3903     * "instr" line that specifies an instruction that performs "d0 = op s0".
3904     *
3905     * For: int-to-double, float-to-double
3906     */
3907    /* unop vA, vB */
3908    mov     r3, rINST, lsr #12          @ r3<- B
3909    mov     r9, rINST, lsr #8           @ r9<- A+
3910    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3911    flds    s0, [r3]                    @ s0<- vB
3912    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3913    and     r9, r9, #15                 @ r9<- A
3914    fcvtds  d0, s0                              @ d0<- op
3915    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3916    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3917    fstd    d0, [r9]                    @ vA<- d0
3918    GOTO_OPCODE(ip)                     @ jump to next instruction
3919
3920
3921/* ------------------------------ */
3922    .balign 64
3923.L_OP_DOUBLE_TO_INT: /* 0x8a */
3924/* File: arm-vfp/OP_DOUBLE_TO_INT.S */
3925/* File: arm-vfp/funopNarrower.S */
3926    /*
3927     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3928     * "instr" line that specifies an instruction that performs "s0 = op d0".
3929     *
3930     * For: double-to-int, double-to-float
3931     */
3932    /* unop vA, vB */
3933    mov     r3, rINST, lsr #12          @ r3<- B
3934    mov     r9, rINST, lsr #8           @ r9<- A+
3935    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3936    fldd    d0, [r3]                    @ d0<- vB
3937    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3938    and     r9, r9, #15                 @ r9<- A
3939    ftosizd  s0, d0                              @ s0<- op
3940    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3941    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3942    fsts    s0, [r9]                    @ vA<- s0
3943    GOTO_OPCODE(ip)                     @ jump to next instruction
3944
3945
3946/* ------------------------------ */
3947    .balign 64
3948.L_OP_DOUBLE_TO_LONG: /* 0x8b */
3949/* File: armv5te/OP_DOUBLE_TO_LONG.S */
3950@include "armv5te/unopWide.S" {"instr":"bl      __aeabi_d2lz"}
3951/* File: armv5te/unopWide.S */
3952    /*
3953     * Generic 64-bit unary operation.  Provide an "instr" line that
3954     * specifies an instruction that performs "result = op r0/r1".
3955     * This could be an ARM instruction or a function call.
3956     *
3957     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3958     */
3959    /* unop vA, vB */
3960    mov     r9, rINST, lsr #8           @ r9<- A+
3961    mov     r3, rINST, lsr #12          @ r3<- B
3962    and     r9, r9, #15
3963    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3964    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3965    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3966    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3967                               @ optional op; may set condition codes
3968    bl      d2l_doconv                              @ r0/r1<- op, r2-r3 changed
3969    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3970    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3971    GOTO_OPCODE(ip)                     @ jump to next instruction
3972    /* 12-13 instructions */
3973
3974
3975
3976
3977/* ------------------------------ */
3978    .balign 64
3979.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
3980/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */
3981/* File: arm-vfp/funopNarrower.S */
3982    /*
3983     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3984     * "instr" line that specifies an instruction that performs "s0 = op d0".
3985     *
3986     * For: double-to-int, double-to-float
3987     */
3988    /* unop vA, vB */
3989    mov     r3, rINST, lsr #12          @ r3<- B
3990    mov     r9, rINST, lsr #8           @ r9<- A+
3991    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3992    fldd    d0, [r3]                    @ d0<- vB
3993    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3994    and     r9, r9, #15                 @ r9<- A
3995    fcvtsd  s0, d0                              @ s0<- op
3996    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3997    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3998    fsts    s0, [r9]                    @ vA<- s0
3999    GOTO_OPCODE(ip)                     @ jump to next instruction
4000
4001
4002/* ------------------------------ */
4003    .balign 64
4004.L_OP_INT_TO_BYTE: /* 0x8d */
4005/* File: armv5te/OP_INT_TO_BYTE.S */
4006/* File: armv5te/unop.S */
4007    /*
4008     * Generic 32-bit unary operation.  Provide an "instr" line that
4009     * specifies an instruction that performs "result = op r0".
4010     * This could be an ARM instruction or a function call.
4011     *
4012     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4013     *      int-to-byte, int-to-char, int-to-short
4014     */
4015    /* unop vA, vB */
4016    mov     r3, rINST, lsr #12          @ r3<- B
4017    mov     r9, rINST, lsr #8           @ r9<- A+
4018    GET_VREG(r0, r3)                    @ r0<- vB
4019    and     r9, r9, #15
4020    mov     r0, r0, asl #24                           @ optional op; may set condition codes
4021    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4022    mov     r0, r0, asr #24                              @ r0<- op, r0-r3 changed
4023    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4024    SET_VREG(r0, r9)                    @ vAA<- r0
4025    GOTO_OPCODE(ip)                     @ jump to next instruction
4026    /* 9-10 instructions */
4027
4028
4029/* ------------------------------ */
4030    .balign 64
4031.L_OP_INT_TO_CHAR: /* 0x8e */
4032/* File: armv5te/OP_INT_TO_CHAR.S */
4033/* File: armv5te/unop.S */
4034    /*
4035     * Generic 32-bit unary operation.  Provide an "instr" line that
4036     * specifies an instruction that performs "result = op r0".
4037     * This could be an ARM instruction or a function call.
4038     *
4039     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4040     *      int-to-byte, int-to-char, int-to-short
4041     */
4042    /* unop vA, vB */
4043    mov     r3, rINST, lsr #12          @ r3<- B
4044    mov     r9, rINST, lsr #8           @ r9<- A+
4045    GET_VREG(r0, r3)                    @ r0<- vB
4046    and     r9, r9, #15
4047    mov     r0, r0, asl #16                           @ optional op; may set condition codes
4048    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4049    mov     r0, r0, lsr #16                              @ r0<- op, r0-r3 changed
4050    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4051    SET_VREG(r0, r9)                    @ vAA<- r0
4052    GOTO_OPCODE(ip)                     @ jump to next instruction
4053    /* 9-10 instructions */
4054
4055
4056/* ------------------------------ */
4057    .balign 64
4058.L_OP_INT_TO_SHORT: /* 0x8f */
4059/* File: armv5te/OP_INT_TO_SHORT.S */
4060/* File: armv5te/unop.S */
4061    /*
4062     * Generic 32-bit unary operation.  Provide an "instr" line that
4063     * specifies an instruction that performs "result = op r0".
4064     * This could be an ARM instruction or a function call.
4065     *
4066     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4067     *      int-to-byte, int-to-char, int-to-short
4068     */
4069    /* unop vA, vB */
4070    mov     r3, rINST, lsr #12          @ r3<- B
4071    mov     r9, rINST, lsr #8           @ r9<- A+
4072    GET_VREG(r0, r3)                    @ r0<- vB
4073    and     r9, r9, #15
4074    mov     r0, r0, asl #16                           @ optional op; may set condition codes
4075    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4076    mov     r0, r0, asr #16                              @ r0<- op, r0-r3 changed
4077    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4078    SET_VREG(r0, r9)                    @ vAA<- r0
4079    GOTO_OPCODE(ip)                     @ jump to next instruction
4080    /* 9-10 instructions */
4081
4082
4083/* ------------------------------ */
4084    .balign 64
4085.L_OP_ADD_INT: /* 0x90 */
4086/* File: armv5te/OP_ADD_INT.S */
4087/* File: armv5te/binop.S */
4088    /*
4089     * Generic 32-bit binary operation.  Provide an "instr" line that
4090     * specifies an instruction that performs "result = r0 op r1".
4091     * This could be an ARM instruction or a function call.  (If the result
4092     * comes back in a register other than r0, you can override "result".)
4093     *
4094     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4095     * vCC (r1).  Useful for integer division and modulus.  Note that we
4096     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4097     * handles it correctly.
4098     *
4099     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4100     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4101     *      mul-float, div-float, rem-float
4102     */
4103    /* binop vAA, vBB, vCC */
4104    FETCH(r0, 1)                        @ r0<- CCBB
4105    mov     r9, rINST, lsr #8           @ r9<- AA
4106    mov     r3, r0, lsr #8              @ r3<- CC
4107    and     r2, r0, #255                @ r2<- BB
4108    GET_VREG(r1, r3)                    @ r1<- vCC
4109    GET_VREG(r0, r2)                    @ r0<- vBB
4110    .if 0
4111    cmp     r1, #0                      @ is second operand zero?
4112    beq     common_errDivideByZero
4113    .endif
4114
4115    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4116                               @ optional op; may set condition codes
4117    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
4118    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4119    SET_VREG(r0, r9)               @ vAA<- r0
4120    GOTO_OPCODE(ip)                     @ jump to next instruction
4121    /* 11-14 instructions */
4122
4123
4124
4125/* ------------------------------ */
4126    .balign 64
4127.L_OP_SUB_INT: /* 0x91 */
4128/* File: armv5te/OP_SUB_INT.S */
4129/* File: armv5te/binop.S */
4130    /*
4131     * Generic 32-bit binary operation.  Provide an "instr" line that
4132     * specifies an instruction that performs "result = r0 op r1".
4133     * This could be an ARM instruction or a function call.  (If the result
4134     * comes back in a register other than r0, you can override "result".)
4135     *
4136     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4137     * vCC (r1).  Useful for integer division and modulus.  Note that we
4138     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4139     * handles it correctly.
4140     *
4141     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4142     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4143     *      mul-float, div-float, rem-float
4144     */
4145    /* binop vAA, vBB, vCC */
4146    FETCH(r0, 1)                        @ r0<- CCBB
4147    mov     r9, rINST, lsr #8           @ r9<- AA
4148    mov     r3, r0, lsr #8              @ r3<- CC
4149    and     r2, r0, #255                @ r2<- BB
4150    GET_VREG(r1, r3)                    @ r1<- vCC
4151    GET_VREG(r0, r2)                    @ r0<- vBB
4152    .if 0
4153    cmp     r1, #0                      @ is second operand zero?
4154    beq     common_errDivideByZero
4155    .endif
4156
4157    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4158                               @ optional op; may set condition codes
4159    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
4160    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4161    SET_VREG(r0, r9)               @ vAA<- r0
4162    GOTO_OPCODE(ip)                     @ jump to next instruction
4163    /* 11-14 instructions */
4164
4165
4166
4167/* ------------------------------ */
4168    .balign 64
4169.L_OP_MUL_INT: /* 0x92 */
4170/* File: armv5te/OP_MUL_INT.S */
4171/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
4172/* File: armv5te/binop.S */
4173    /*
4174     * Generic 32-bit binary operation.  Provide an "instr" line that
4175     * specifies an instruction that performs "result = r0 op r1".
4176     * This could be an ARM instruction or a function call.  (If the result
4177     * comes back in a register other than r0, you can override "result".)
4178     *
4179     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4180     * vCC (r1).  Useful for integer division and modulus.  Note that we
4181     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4182     * handles it correctly.
4183     *
4184     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4185     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4186     *      mul-float, div-float, rem-float
4187     */
4188    /* binop vAA, vBB, vCC */
4189    FETCH(r0, 1)                        @ r0<- CCBB
4190    mov     r9, rINST, lsr #8           @ r9<- AA
4191    mov     r3, r0, lsr #8              @ r3<- CC
4192    and     r2, r0, #255                @ r2<- BB
4193    GET_VREG(r1, r3)                    @ r1<- vCC
4194    GET_VREG(r0, r2)                    @ r0<- vBB
4195    .if 0
4196    cmp     r1, #0                      @ is second operand zero?
4197    beq     common_errDivideByZero
4198    .endif
4199
4200    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4201                               @ optional op; may set condition codes
4202    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
4203    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4204    SET_VREG(r0, r9)               @ vAA<- r0
4205    GOTO_OPCODE(ip)                     @ jump to next instruction
4206    /* 11-14 instructions */
4207
4208
4209
4210/* ------------------------------ */
4211    .balign 64
4212.L_OP_DIV_INT: /* 0x93 */
4213/* File: armv5te/OP_DIV_INT.S */
4214/* File: armv5te/binop.S */
4215    /*
4216     * Generic 32-bit binary operation.  Provide an "instr" line that
4217     * specifies an instruction that performs "result = r0 op r1".
4218     * This could be an ARM instruction or a function call.  (If the result
4219     * comes back in a register other than r0, you can override "result".)
4220     *
4221     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4222     * vCC (r1).  Useful for integer division and modulus.  Note that we
4223     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4224     * handles it correctly.
4225     *
4226     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4227     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4228     *      mul-float, div-float, rem-float
4229     */
4230    /* binop vAA, vBB, vCC */
4231    FETCH(r0, 1)                        @ r0<- CCBB
4232    mov     r9, rINST, lsr #8           @ r9<- AA
4233    mov     r3, r0, lsr #8              @ r3<- CC
4234    and     r2, r0, #255                @ r2<- BB
4235    GET_VREG(r1, r3)                    @ r1<- vCC
4236    GET_VREG(r0, r2)                    @ r0<- vBB
4237    .if 1
4238    cmp     r1, #0                      @ is second operand zero?
4239    beq     common_errDivideByZero
4240    .endif
4241
4242    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4243                               @ optional op; may set condition codes
4244    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
4245    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4246    SET_VREG(r0, r9)               @ vAA<- r0
4247    GOTO_OPCODE(ip)                     @ jump to next instruction
4248    /* 11-14 instructions */
4249
4250
4251
4252/* ------------------------------ */
4253    .balign 64
4254.L_OP_REM_INT: /* 0x94 */
4255/* File: armv5te/OP_REM_INT.S */
4256/* idivmod returns quotient in r0 and remainder in r1 */
4257/* File: armv5te/binop.S */
4258    /*
4259     * Generic 32-bit binary operation.  Provide an "instr" line that
4260     * specifies an instruction that performs "result = r0 op r1".
4261     * This could be an ARM instruction or a function call.  (If the result
4262     * comes back in a register other than r0, you can override "result".)
4263     *
4264     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4265     * vCC (r1).  Useful for integer division and modulus.  Note that we
4266     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4267     * handles it correctly.
4268     *
4269     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4270     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4271     *      mul-float, div-float, rem-float
4272     */
4273    /* binop vAA, vBB, vCC */
4274    FETCH(r0, 1)                        @ r0<- CCBB
4275    mov     r9, rINST, lsr #8           @ r9<- AA
4276    mov     r3, r0, lsr #8              @ r3<- CC
4277    and     r2, r0, #255                @ r2<- BB
4278    GET_VREG(r1, r3)                    @ r1<- vCC
4279    GET_VREG(r0, r2)                    @ r0<- vBB
4280    .if 1
4281    cmp     r1, #0                      @ is second operand zero?
4282    beq     common_errDivideByZero
4283    .endif
4284
4285    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4286                               @ optional op; may set condition codes
4287    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
4288    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4289    SET_VREG(r1, r9)               @ vAA<- r1
4290    GOTO_OPCODE(ip)                     @ jump to next instruction
4291    /* 11-14 instructions */
4292
4293
4294
4295/* ------------------------------ */
4296    .balign 64
4297.L_OP_AND_INT: /* 0x95 */
4298/* File: armv5te/OP_AND_INT.S */
4299/* File: armv5te/binop.S */
4300    /*
4301     * Generic 32-bit binary operation.  Provide an "instr" line that
4302     * specifies an instruction that performs "result = r0 op r1".
4303     * This could be an ARM instruction or a function call.  (If the result
4304     * comes back in a register other than r0, you can override "result".)
4305     *
4306     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4307     * vCC (r1).  Useful for integer division and modulus.  Note that we
4308     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4309     * handles it correctly.
4310     *
4311     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4312     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4313     *      mul-float, div-float, rem-float
4314     */
4315    /* binop vAA, vBB, vCC */
4316    FETCH(r0, 1)                        @ r0<- CCBB
4317    mov     r9, rINST, lsr #8           @ r9<- AA
4318    mov     r3, r0, lsr #8              @ r3<- CC
4319    and     r2, r0, #255                @ r2<- BB
4320    GET_VREG(r1, r3)                    @ r1<- vCC
4321    GET_VREG(r0, r2)                    @ r0<- vBB
4322    .if 0
4323    cmp     r1, #0                      @ is second operand zero?
4324    beq     common_errDivideByZero
4325    .endif
4326
4327    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4328                               @ optional op; may set condition codes
4329    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
4330    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4331    SET_VREG(r0, r9)               @ vAA<- r0
4332    GOTO_OPCODE(ip)                     @ jump to next instruction
4333    /* 11-14 instructions */
4334
4335
4336
4337/* ------------------------------ */
4338    .balign 64
4339.L_OP_OR_INT: /* 0x96 */
4340/* File: armv5te/OP_OR_INT.S */
4341/* File: armv5te/binop.S */
4342    /*
4343     * Generic 32-bit binary operation.  Provide an "instr" line that
4344     * specifies an instruction that performs "result = r0 op r1".
4345     * This could be an ARM instruction or a function call.  (If the result
4346     * comes back in a register other than r0, you can override "result".)
4347     *
4348     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4349     * vCC (r1).  Useful for integer division and modulus.  Note that we
4350     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4351     * handles it correctly.
4352     *
4353     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4354     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4355     *      mul-float, div-float, rem-float
4356     */
4357    /* binop vAA, vBB, vCC */
4358    FETCH(r0, 1)                        @ r0<- CCBB
4359    mov     r9, rINST, lsr #8           @ r9<- AA
4360    mov     r3, r0, lsr #8              @ r3<- CC
4361    and     r2, r0, #255                @ r2<- BB
4362    GET_VREG(r1, r3)                    @ r1<- vCC
4363    GET_VREG(r0, r2)                    @ r0<- vBB
4364    .if 0
4365    cmp     r1, #0                      @ is second operand zero?
4366    beq     common_errDivideByZero
4367    .endif
4368
4369    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4370                               @ optional op; may set condition codes
4371    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
4372    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4373    SET_VREG(r0, r9)               @ vAA<- r0
4374    GOTO_OPCODE(ip)                     @ jump to next instruction
4375    /* 11-14 instructions */
4376
4377
4378
4379/* ------------------------------ */
4380    .balign 64
4381.L_OP_XOR_INT: /* 0x97 */
4382/* File: armv5te/OP_XOR_INT.S */
4383/* File: armv5te/binop.S */
4384    /*
4385     * Generic 32-bit binary operation.  Provide an "instr" line that
4386     * specifies an instruction that performs "result = r0 op r1".
4387     * This could be an ARM instruction or a function call.  (If the result
4388     * comes back in a register other than r0, you can override "result".)
4389     *
4390     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4391     * vCC (r1).  Useful for integer division and modulus.  Note that we
4392     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4393     * handles it correctly.
4394     *
4395     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4396     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4397     *      mul-float, div-float, rem-float
4398     */
4399    /* binop vAA, vBB, vCC */
4400    FETCH(r0, 1)                        @ r0<- CCBB
4401    mov     r9, rINST, lsr #8           @ r9<- AA
4402    mov     r3, r0, lsr #8              @ r3<- CC
4403    and     r2, r0, #255                @ r2<- BB
4404    GET_VREG(r1, r3)                    @ r1<- vCC
4405    GET_VREG(r0, r2)                    @ r0<- vBB
4406    .if 0
4407    cmp     r1, #0                      @ is second operand zero?
4408    beq     common_errDivideByZero
4409    .endif
4410
4411    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4412                               @ optional op; may set condition codes
4413    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
4414    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4415    SET_VREG(r0, r9)               @ vAA<- r0
4416    GOTO_OPCODE(ip)                     @ jump to next instruction
4417    /* 11-14 instructions */
4418
4419
4420
4421/* ------------------------------ */
4422    .balign 64
4423.L_OP_SHL_INT: /* 0x98 */
4424/* File: armv5te/OP_SHL_INT.S */
4425/* File: armv5te/binop.S */
4426    /*
4427     * Generic 32-bit binary operation.  Provide an "instr" line that
4428     * specifies an instruction that performs "result = r0 op r1".
4429     * This could be an ARM instruction or a function call.  (If the result
4430     * comes back in a register other than r0, you can override "result".)
4431     *
4432     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4433     * vCC (r1).  Useful for integer division and modulus.  Note that we
4434     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4435     * handles it correctly.
4436     *
4437     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4438     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4439     *      mul-float, div-float, rem-float
4440     */
4441    /* binop vAA, vBB, vCC */
4442    FETCH(r0, 1)                        @ r0<- CCBB
4443    mov     r9, rINST, lsr #8           @ r9<- AA
4444    mov     r3, r0, lsr #8              @ r3<- CC
4445    and     r2, r0, #255                @ r2<- BB
4446    GET_VREG(r1, r3)                    @ r1<- vCC
4447    GET_VREG(r0, r2)                    @ r0<- vBB
4448    .if 0
4449    cmp     r1, #0                      @ is second operand zero?
4450    beq     common_errDivideByZero
4451    .endif
4452
4453    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4454    and     r1, r1, #31                           @ optional op; may set condition codes
4455    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
4456    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4457    SET_VREG(r0, r9)               @ vAA<- r0
4458    GOTO_OPCODE(ip)                     @ jump to next instruction
4459    /* 11-14 instructions */
4460
4461
4462
4463/* ------------------------------ */
4464    .balign 64
4465.L_OP_SHR_INT: /* 0x99 */
4466/* File: armv5te/OP_SHR_INT.S */
4467/* File: armv5te/binop.S */
4468    /*
4469     * Generic 32-bit binary operation.  Provide an "instr" line that
4470     * specifies an instruction that performs "result = r0 op r1".
4471     * This could be an ARM instruction or a function call.  (If the result
4472     * comes back in a register other than r0, you can override "result".)
4473     *
4474     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4475     * vCC (r1).  Useful for integer division and modulus.  Note that we
4476     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4477     * handles it correctly.
4478     *
4479     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4480     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4481     *      mul-float, div-float, rem-float
4482     */
4483    /* binop vAA, vBB, vCC */
4484    FETCH(r0, 1)                        @ r0<- CCBB
4485    mov     r9, rINST, lsr #8           @ r9<- AA
4486    mov     r3, r0, lsr #8              @ r3<- CC
4487    and     r2, r0, #255                @ r2<- BB
4488    GET_VREG(r1, r3)                    @ r1<- vCC
4489    GET_VREG(r0, r2)                    @ r0<- vBB
4490    .if 0
4491    cmp     r1, #0                      @ is second operand zero?
4492    beq     common_errDivideByZero
4493    .endif
4494
4495    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4496    and     r1, r1, #31                           @ optional op; may set condition codes
4497    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
4498    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4499    SET_VREG(r0, r9)               @ vAA<- r0
4500    GOTO_OPCODE(ip)                     @ jump to next instruction
4501    /* 11-14 instructions */
4502
4503
4504
4505/* ------------------------------ */
4506    .balign 64
4507.L_OP_USHR_INT: /* 0x9a */
4508/* File: armv5te/OP_USHR_INT.S */
4509/* File: armv5te/binop.S */
4510    /*
4511     * Generic 32-bit binary operation.  Provide an "instr" line that
4512     * specifies an instruction that performs "result = r0 op r1".
4513     * This could be an ARM instruction or a function call.  (If the result
4514     * comes back in a register other than r0, you can override "result".)
4515     *
4516     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4517     * vCC (r1).  Useful for integer division and modulus.  Note that we
4518     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4519     * handles it correctly.
4520     *
4521     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4522     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4523     *      mul-float, div-float, rem-float
4524     */
4525    /* binop vAA, vBB, vCC */
4526    FETCH(r0, 1)                        @ r0<- CCBB
4527    mov     r9, rINST, lsr #8           @ r9<- AA
4528    mov     r3, r0, lsr #8              @ r3<- CC
4529    and     r2, r0, #255                @ r2<- BB
4530    GET_VREG(r1, r3)                    @ r1<- vCC
4531    GET_VREG(r0, r2)                    @ r0<- vBB
4532    .if 0
4533    cmp     r1, #0                      @ is second operand zero?
4534    beq     common_errDivideByZero
4535    .endif
4536
4537    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4538    and     r1, r1, #31                           @ optional op; may set condition codes
4539    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
4540    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4541    SET_VREG(r0, r9)               @ vAA<- r0
4542    GOTO_OPCODE(ip)                     @ jump to next instruction
4543    /* 11-14 instructions */
4544
4545
4546
4547/* ------------------------------ */
4548    .balign 64
4549.L_OP_ADD_LONG: /* 0x9b */
4550/* File: armv5te/OP_ADD_LONG.S */
4551/* File: armv5te/binopWide.S */
4552    /*
4553     * Generic 64-bit binary operation.  Provide an "instr" line that
4554     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4555     * This could be an ARM instruction or a function call.  (If the result
4556     * comes back in a register other than r0, you can override "result".)
4557     *
4558     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4559     * vCC (r1).  Useful for integer division and modulus.
4560     *
4561     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4562     *      xor-long, add-double, sub-double, mul-double, div-double,
4563     *      rem-double
4564     *
4565     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4566     */
4567    /* binop vAA, vBB, vCC */
4568    FETCH(r0, 1)                        @ r0<- CCBB
4569    mov     r9, rINST, lsr #8           @ r9<- AA
4570    and     r2, r0, #255                @ r2<- BB
4571    mov     r3, r0, lsr #8              @ r3<- CC
4572    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4573    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4574    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4575    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4576    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4577    .if 0
4578    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4579    beq     common_errDivideByZero
4580    .endif
4581    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4582
4583    adds    r0, r0, r2                           @ optional op; may set condition codes
4584    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
4585    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4586    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4587    GOTO_OPCODE(ip)                     @ jump to next instruction
4588    /* 14-17 instructions */
4589
4590
4591
4592/* ------------------------------ */
4593    .balign 64
4594.L_OP_SUB_LONG: /* 0x9c */
4595/* File: armv5te/OP_SUB_LONG.S */
4596/* File: armv5te/binopWide.S */
4597    /*
4598     * Generic 64-bit binary operation.  Provide an "instr" line that
4599     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4600     * This could be an ARM instruction or a function call.  (If the result
4601     * comes back in a register other than r0, you can override "result".)
4602     *
4603     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4604     * vCC (r1).  Useful for integer division and modulus.
4605     *
4606     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4607     *      xor-long, add-double, sub-double, mul-double, div-double,
4608     *      rem-double
4609     *
4610     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4611     */
4612    /* binop vAA, vBB, vCC */
4613    FETCH(r0, 1)                        @ r0<- CCBB
4614    mov     r9, rINST, lsr #8           @ r9<- AA
4615    and     r2, r0, #255                @ r2<- BB
4616    mov     r3, r0, lsr #8              @ r3<- CC
4617    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4618    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4619    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4620    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4621    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4622    .if 0
4623    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4624    beq     common_errDivideByZero
4625    .endif
4626    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4627
4628    subs    r0, r0, r2                           @ optional op; may set condition codes
4629    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
4630    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4631    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4632    GOTO_OPCODE(ip)                     @ jump to next instruction
4633    /* 14-17 instructions */
4634
4635
4636
4637/* ------------------------------ */
4638    .balign 64
4639.L_OP_MUL_LONG: /* 0x9d */
4640/* File: armv5te/OP_MUL_LONG.S */
4641    /*
4642     * Signed 64-bit integer multiply.
4643     *
4644     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
4645     *        WX
4646     *      x YZ
4647     *  --------
4648     *     ZW ZX
4649     *  YW YX
4650     *
4651     * The low word of the result holds ZX, the high word holds
4652     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
4653     * it doesn't fit in the low 64 bits.
4654     *
4655     * Unlike most ARM math operations, multiply instructions have
4656     * restrictions on using the same register more than once (Rd and Rm
4657     * cannot be the same).
4658     */
4659    /* mul-long vAA, vBB, vCC */
4660    FETCH(r0, 1)                        @ r0<- CCBB
4661    and     r2, r0, #255                @ r2<- BB
4662    mov     r3, r0, lsr #8              @ r3<- CC
4663    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4664    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4665    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4666    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4667    mul     ip, r2, r1                  @  ip<- ZxW
4668    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
4669    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
4670    mov     r0, rINST, lsr #8           @ r0<- AA
4671    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
4672    add     r0, rFP, r0, lsl #2         @ r0<- &fp[AA]
4673    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4674    b       .LOP_MUL_LONG_finish
4675
4676/* ------------------------------ */
4677    .balign 64
4678.L_OP_DIV_LONG: /* 0x9e */
4679/* File: armv5te/OP_DIV_LONG.S */
4680/* File: armv5te/binopWide.S */
4681    /*
4682     * Generic 64-bit binary operation.  Provide an "instr" line that
4683     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4684     * This could be an ARM instruction or a function call.  (If the result
4685     * comes back in a register other than r0, you can override "result".)
4686     *
4687     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4688     * vCC (r1).  Useful for integer division and modulus.
4689     *
4690     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4691     *      xor-long, add-double, sub-double, mul-double, div-double,
4692     *      rem-double
4693     *
4694     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4695     */
4696    /* binop vAA, vBB, vCC */
4697    FETCH(r0, 1)                        @ r0<- CCBB
4698    mov     r9, rINST, lsr #8           @ r9<- AA
4699    and     r2, r0, #255                @ r2<- BB
4700    mov     r3, r0, lsr #8              @ r3<- CC
4701    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4702    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4703    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4704    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4705    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4706    .if 1
4707    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4708    beq     common_errDivideByZero
4709    .endif
4710    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4711
4712                               @ optional op; may set condition codes
4713    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4714    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4715    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4716    GOTO_OPCODE(ip)                     @ jump to next instruction
4717    /* 14-17 instructions */
4718
4719
4720
4721/* ------------------------------ */
4722    .balign 64
4723.L_OP_REM_LONG: /* 0x9f */
4724/* File: armv5te/OP_REM_LONG.S */
4725/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
4726/* File: armv5te/binopWide.S */
4727    /*
4728     * Generic 64-bit binary operation.  Provide an "instr" line that
4729     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4730     * This could be an ARM instruction or a function call.  (If the result
4731     * comes back in a register other than r0, you can override "result".)
4732     *
4733     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4734     * vCC (r1).  Useful for integer division and modulus.
4735     *
4736     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4737     *      xor-long, add-double, sub-double, mul-double, div-double,
4738     *      rem-double
4739     *
4740     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4741     */
4742    /* binop vAA, vBB, vCC */
4743    FETCH(r0, 1)                        @ r0<- CCBB
4744    mov     r9, rINST, lsr #8           @ r9<- AA
4745    and     r2, r0, #255                @ r2<- BB
4746    mov     r3, r0, lsr #8              @ r3<- CC
4747    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4748    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4749    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4750    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4751    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4752    .if 1
4753    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4754    beq     common_errDivideByZero
4755    .endif
4756    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4757
4758                               @ optional op; may set condition codes
4759    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4760    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4761    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
4762    GOTO_OPCODE(ip)                     @ jump to next instruction
4763    /* 14-17 instructions */
4764
4765
4766
4767/* ------------------------------ */
4768    .balign 64
4769.L_OP_AND_LONG: /* 0xa0 */
4770/* File: armv5te/OP_AND_LONG.S */
4771/* File: armv5te/binopWide.S */
4772    /*
4773     * Generic 64-bit binary operation.  Provide an "instr" line that
4774     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4775     * This could be an ARM instruction or a function call.  (If the result
4776     * comes back in a register other than r0, you can override "result".)
4777     *
4778     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4779     * vCC (r1).  Useful for integer division and modulus.
4780     *
4781     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4782     *      xor-long, add-double, sub-double, mul-double, div-double,
4783     *      rem-double
4784     *
4785     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4786     */
4787    /* binop vAA, vBB, vCC */
4788    FETCH(r0, 1)                        @ r0<- CCBB
4789    mov     r9, rINST, lsr #8           @ r9<- AA
4790    and     r2, r0, #255                @ r2<- BB
4791    mov     r3, r0, lsr #8              @ r3<- CC
4792    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4793    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4794    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4795    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4796    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4797    .if 0
4798    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4799    beq     common_errDivideByZero
4800    .endif
4801    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4802
4803    and     r0, r0, r2                           @ optional op; may set condition codes
4804    and     r1, r1, r3                              @ result<- op, r0-r3 changed
4805    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4806    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4807    GOTO_OPCODE(ip)                     @ jump to next instruction
4808    /* 14-17 instructions */
4809
4810
4811
4812/* ------------------------------ */
4813    .balign 64
4814.L_OP_OR_LONG: /* 0xa1 */
4815/* File: armv5te/OP_OR_LONG.S */
4816/* File: armv5te/binopWide.S */
4817    /*
4818     * Generic 64-bit binary operation.  Provide an "instr" line that
4819     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4820     * This could be an ARM instruction or a function call.  (If the result
4821     * comes back in a register other than r0, you can override "result".)
4822     *
4823     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4824     * vCC (r1).  Useful for integer division and modulus.
4825     *
4826     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4827     *      xor-long, add-double, sub-double, mul-double, div-double,
4828     *      rem-double
4829     *
4830     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4831     */
4832    /* binop vAA, vBB, vCC */
4833    FETCH(r0, 1)                        @ r0<- CCBB
4834    mov     r9, rINST, lsr #8           @ r9<- AA
4835    and     r2, r0, #255                @ r2<- BB
4836    mov     r3, r0, lsr #8              @ r3<- CC
4837    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4838    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4839    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4840    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4841    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4842    .if 0
4843    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4844    beq     common_errDivideByZero
4845    .endif
4846    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4847
4848    orr     r0, r0, r2                           @ optional op; may set condition codes
4849    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
4850    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4851    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4852    GOTO_OPCODE(ip)                     @ jump to next instruction
4853    /* 14-17 instructions */
4854
4855
4856
4857/* ------------------------------ */
4858    .balign 64
4859.L_OP_XOR_LONG: /* 0xa2 */
4860/* File: armv5te/OP_XOR_LONG.S */
4861/* File: armv5te/binopWide.S */
4862    /*
4863     * Generic 64-bit binary operation.  Provide an "instr" line that
4864     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4865     * This could be an ARM instruction or a function call.  (If the result
4866     * comes back in a register other than r0, you can override "result".)
4867     *
4868     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4869     * vCC (r1).  Useful for integer division and modulus.
4870     *
4871     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4872     *      xor-long, add-double, sub-double, mul-double, div-double,
4873     *      rem-double
4874     *
4875     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4876     */
4877    /* binop vAA, vBB, vCC */
4878    FETCH(r0, 1)                        @ r0<- CCBB
4879    mov     r9, rINST, lsr #8           @ r9<- AA
4880    and     r2, r0, #255                @ r2<- BB
4881    mov     r3, r0, lsr #8              @ r3<- CC
4882    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4883    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4884    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4885    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4886    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4887    .if 0
4888    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4889    beq     common_errDivideByZero
4890    .endif
4891    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4892
4893    eor     r0, r0, r2                           @ optional op; may set condition codes
4894    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
4895    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4896    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4897    GOTO_OPCODE(ip)                     @ jump to next instruction
4898    /* 14-17 instructions */
4899
4900
4901
4902/* ------------------------------ */
4903    .balign 64
4904.L_OP_SHL_LONG: /* 0xa3 */
4905/* File: armv5te/OP_SHL_LONG.S */
4906    /*
4907     * Long integer shift.  This is different from the generic 32/64-bit
4908     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4909     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4910     * 6 bits of the shift distance.
4911     */
4912    /* shl-long vAA, vBB, vCC */
4913    FETCH(r0, 1)                        @ r0<- CCBB
4914    mov     r9, rINST, lsr #8           @ r9<- AA
4915    and     r3, r0, #255                @ r3<- BB
4916    mov     r0, r0, lsr #8              @ r0<- CC
4917    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4918    GET_VREG(r2, r0)                    @ r2<- vCC
4919    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4920    and     r2, r2, #63                 @ r2<- r2 & 0x3f
4921    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4922
4923    mov     r1, r1, asl r2              @  r1<- r1 << r2
4924    rsb     r3, r2, #32                 @  r3<- 32 - r2
4925    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
4926    subs    ip, r2, #32                 @  ip<- r2 - 32
4927    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
4928    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4929    b       .LOP_SHL_LONG_finish
4930
4931/* ------------------------------ */
4932    .balign 64
4933.L_OP_SHR_LONG: /* 0xa4 */
4934/* File: armv5te/OP_SHR_LONG.S */
4935    /*
4936     * Long integer shift.  This is different from the generic 32/64-bit
4937     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4938     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4939     * 6 bits of the shift distance.
4940     */
4941    /* shr-long vAA, vBB, vCC */
4942    FETCH(r0, 1)                        @ r0<- CCBB
4943    mov     r9, rINST, lsr #8           @ r9<- AA
4944    and     r3, r0, #255                @ r3<- BB
4945    mov     r0, r0, lsr #8              @ r0<- CC
4946    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4947    GET_VREG(r2, r0)                    @ r2<- vCC
4948    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4949    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4950    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4951
4952    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4953    rsb     r3, r2, #32                 @  r3<- 32 - r2
4954    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4955    subs    ip, r2, #32                 @  ip<- r2 - 32
4956    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
4957    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4958    b       .LOP_SHR_LONG_finish
4959
4960/* ------------------------------ */
4961    .balign 64
4962.L_OP_USHR_LONG: /* 0xa5 */
4963/* File: armv5te/OP_USHR_LONG.S */
4964    /*
4965     * Long integer shift.  This is different from the generic 32/64-bit
4966     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4967     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4968     * 6 bits of the shift distance.
4969     */
4970    /* ushr-long vAA, vBB, vCC */
4971    FETCH(r0, 1)                        @ r0<- CCBB
4972    mov     r9, rINST, lsr #8           @ r9<- AA
4973    and     r3, r0, #255                @ r3<- BB
4974    mov     r0, r0, lsr #8              @ r0<- CC
4975    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4976    GET_VREG(r2, r0)                    @ r2<- vCC
4977    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4978    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4979    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4980
4981    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4982    rsb     r3, r2, #32                 @  r3<- 32 - r2
4983    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4984    subs    ip, r2, #32                 @  ip<- r2 - 32
4985    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
4986    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4987    b       .LOP_USHR_LONG_finish
4988
4989/* ------------------------------ */
4990    .balign 64
4991.L_OP_ADD_FLOAT: /* 0xa6 */
4992/* File: arm-vfp/OP_ADD_FLOAT.S */
4993/* File: arm-vfp/fbinop.S */
4994    /*
4995     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4996     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4997     * use the "softfp" ABI, this must be an instruction, not a function call.
4998     *
4999     * For: add-float, sub-float, mul-float, div-float
5000     */
5001    /* floatop vAA, vBB, vCC */
5002    FETCH(r0, 1)                        @ r0<- CCBB
5003    mov     r9, rINST, lsr #8           @ r9<- AA
5004    mov     r3, r0, lsr #8              @ r3<- CC
5005    and     r2, r0, #255                @ r2<- BB
5006    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5007    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5008    flds    s1, [r3]                    @ s1<- vCC
5009    flds    s0, [r2]                    @ s0<- vBB
5010
5011    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5012    fadds   s2, s0, s1                              @ s2<- op
5013    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5014    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5015    fsts    s2, [r9]                    @ vAA<- s2
5016    GOTO_OPCODE(ip)                     @ jump to next instruction
5017
5018
5019/* ------------------------------ */
5020    .balign 64
5021.L_OP_SUB_FLOAT: /* 0xa7 */
5022/* File: arm-vfp/OP_SUB_FLOAT.S */
5023/* File: arm-vfp/fbinop.S */
5024    /*
5025     * Generic 32-bit floating-point operation.  Provide an "instr" line that
5026     * specifies an instruction that performs "s2 = s0 op s1".  Because we
5027     * use the "softfp" ABI, this must be an instruction, not a function call.
5028     *
5029     * For: add-float, sub-float, mul-float, div-float
5030     */
5031    /* floatop vAA, vBB, vCC */
5032    FETCH(r0, 1)                        @ r0<- CCBB
5033    mov     r9, rINST, lsr #8           @ r9<- AA
5034    mov     r3, r0, lsr #8              @ r3<- CC
5035    and     r2, r0, #255                @ r2<- BB
5036    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5037    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5038    flds    s1, [r3]                    @ s1<- vCC
5039    flds    s0, [r2]                    @ s0<- vBB
5040
5041    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5042    fsubs   s2, s0, s1                              @ s2<- op
5043    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5044    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5045    fsts    s2, [r9]                    @ vAA<- s2
5046    GOTO_OPCODE(ip)                     @ jump to next instruction
5047
5048
5049/* ------------------------------ */
5050    .balign 64
5051.L_OP_MUL_FLOAT: /* 0xa8 */
5052/* File: arm-vfp/OP_MUL_FLOAT.S */
5053/* File: arm-vfp/fbinop.S */
5054    /*
5055     * Generic 32-bit floating-point operation.  Provide an "instr" line that
5056     * specifies an instruction that performs "s2 = s0 op s1".  Because we
5057     * use the "softfp" ABI, this must be an instruction, not a function call.
5058     *
5059     * For: add-float, sub-float, mul-float, div-float
5060     */
5061    /* floatop vAA, vBB, vCC */
5062    FETCH(r0, 1)                        @ r0<- CCBB
5063    mov     r9, rINST, lsr #8           @ r9<- AA
5064    mov     r3, r0, lsr #8              @ r3<- CC
5065    and     r2, r0, #255                @ r2<- BB
5066    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5067    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5068    flds    s1, [r3]                    @ s1<- vCC
5069    flds    s0, [r2]                    @ s0<- vBB
5070
5071    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5072    fmuls   s2, s0, s1                              @ s2<- op
5073    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5074    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5075    fsts    s2, [r9]                    @ vAA<- s2
5076    GOTO_OPCODE(ip)                     @ jump to next instruction
5077
5078
5079/* ------------------------------ */
5080    .balign 64
5081.L_OP_DIV_FLOAT: /* 0xa9 */
5082/* File: arm-vfp/OP_DIV_FLOAT.S */
5083/* File: arm-vfp/fbinop.S */
5084    /*
5085     * Generic 32-bit floating-point operation.  Provide an "instr" line that
5086     * specifies an instruction that performs "s2 = s0 op s1".  Because we
5087     * use the "softfp" ABI, this must be an instruction, not a function call.
5088     *
5089     * For: add-float, sub-float, mul-float, div-float
5090     */
5091    /* floatop vAA, vBB, vCC */
5092    FETCH(r0, 1)                        @ r0<- CCBB
5093    mov     r9, rINST, lsr #8           @ r9<- AA
5094    mov     r3, r0, lsr #8              @ r3<- CC
5095    and     r2, r0, #255                @ r2<- BB
5096    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5097    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5098    flds    s1, [r3]                    @ s1<- vCC
5099    flds    s0, [r2]                    @ s0<- vBB
5100
5101    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5102    fdivs   s2, s0, s1                              @ s2<- op
5103    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5104    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5105    fsts    s2, [r9]                    @ vAA<- s2
5106    GOTO_OPCODE(ip)                     @ jump to next instruction
5107
5108
5109/* ------------------------------ */
5110    .balign 64
5111.L_OP_REM_FLOAT: /* 0xaa */
5112/* File: armv5te/OP_REM_FLOAT.S */
5113/* EABI doesn't define a float remainder function, but libm does */
5114/* File: armv5te/binop.S */
5115    /*
5116     * Generic 32-bit binary operation.  Provide an "instr" line that
5117     * specifies an instruction that performs "result = r0 op r1".
5118     * This could be an ARM instruction or a function call.  (If the result
5119     * comes back in a register other than r0, you can override "result".)
5120     *
5121     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5122     * vCC (r1).  Useful for integer division and modulus.  Note that we
5123     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5124     * handles it correctly.
5125     *
5126     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5127     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5128     *      mul-float, div-float, rem-float
5129     */
5130    /* binop vAA, vBB, vCC */
5131    FETCH(r0, 1)                        @ r0<- CCBB
5132    mov     r9, rINST, lsr #8           @ r9<- AA
5133    mov     r3, r0, lsr #8              @ r3<- CC
5134    and     r2, r0, #255                @ r2<- BB
5135    GET_VREG(r1, r3)                    @ r1<- vCC
5136    GET_VREG(r0, r2)                    @ r0<- vBB
5137    .if 0
5138    cmp     r1, #0                      @ is second operand zero?
5139    beq     common_errDivideByZero
5140    .endif
5141
5142    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5143                               @ optional op; may set condition codes
5144    bl      fmodf                              @ r0<- op, r0-r3 changed
5145    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5146    SET_VREG(r0, r9)               @ vAA<- r0
5147    GOTO_OPCODE(ip)                     @ jump to next instruction
5148    /* 11-14 instructions */
5149
5150
5151
5152/* ------------------------------ */
5153    .balign 64
5154.L_OP_ADD_DOUBLE: /* 0xab */
5155/* File: arm-vfp/OP_ADD_DOUBLE.S */
5156/* File: arm-vfp/fbinopWide.S */
5157    /*
5158     * Generic 64-bit double-precision floating point binary operation.
5159     * Provide an "instr" line that specifies an instruction that performs
5160     * "d2 = d0 op d1".
5161     *
5162     * for: add-double, sub-double, mul-double, div-double
5163     */
5164    /* doubleop vAA, vBB, vCC */
5165    FETCH(r0, 1)                        @ r0<- CCBB
5166    mov     r9, rINST, lsr #8           @ r9<- AA
5167    mov     r3, r0, lsr #8              @ r3<- CC
5168    and     r2, r0, #255                @ r2<- BB
5169    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5170    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5171    fldd    d1, [r3]                    @ d1<- vCC
5172    fldd    d0, [r2]                    @ d0<- vBB
5173
5174    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5175    faddd   d2, d0, d1                              @ s2<- op
5176    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5177    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5178    fstd    d2, [r9]                    @ vAA<- d2
5179    GOTO_OPCODE(ip)                     @ jump to next instruction
5180
5181
5182/* ------------------------------ */
5183    .balign 64
5184.L_OP_SUB_DOUBLE: /* 0xac */
5185/* File: arm-vfp/OP_SUB_DOUBLE.S */
5186/* File: arm-vfp/fbinopWide.S */
5187    /*
5188     * Generic 64-bit double-precision floating point binary operation.
5189     * Provide an "instr" line that specifies an instruction that performs
5190     * "d2 = d0 op d1".
5191     *
5192     * for: add-double, sub-double, mul-double, div-double
5193     */
5194    /* doubleop vAA, vBB, vCC */
5195    FETCH(r0, 1)                        @ r0<- CCBB
5196    mov     r9, rINST, lsr #8           @ r9<- AA
5197    mov     r3, r0, lsr #8              @ r3<- CC
5198    and     r2, r0, #255                @ r2<- BB
5199    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5200    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5201    fldd    d1, [r3]                    @ d1<- vCC
5202    fldd    d0, [r2]                    @ d0<- vBB
5203
5204    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5205    fsubd   d2, d0, d1                              @ s2<- op
5206    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5207    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5208    fstd    d2, [r9]                    @ vAA<- d2
5209    GOTO_OPCODE(ip)                     @ jump to next instruction
5210
5211
5212/* ------------------------------ */
5213    .balign 64
5214.L_OP_MUL_DOUBLE: /* 0xad */
5215/* File: arm-vfp/OP_MUL_DOUBLE.S */
5216/* File: arm-vfp/fbinopWide.S */
5217    /*
5218     * Generic 64-bit double-precision floating point binary operation.
5219     * Provide an "instr" line that specifies an instruction that performs
5220     * "d2 = d0 op d1".
5221     *
5222     * for: add-double, sub-double, mul-double, div-double
5223     */
5224    /* doubleop vAA, vBB, vCC */
5225    FETCH(r0, 1)                        @ r0<- CCBB
5226    mov     r9, rINST, lsr #8           @ r9<- AA
5227    mov     r3, r0, lsr #8              @ r3<- CC
5228    and     r2, r0, #255                @ r2<- BB
5229    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5230    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5231    fldd    d1, [r3]                    @ d1<- vCC
5232    fldd    d0, [r2]                    @ d0<- vBB
5233
5234    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5235    fmuld   d2, d0, d1                              @ s2<- op
5236    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5237    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5238    fstd    d2, [r9]                    @ vAA<- d2
5239    GOTO_OPCODE(ip)                     @ jump to next instruction
5240
5241
5242/* ------------------------------ */
5243    .balign 64
5244.L_OP_DIV_DOUBLE: /* 0xae */
5245/* File: arm-vfp/OP_DIV_DOUBLE.S */
5246/* File: arm-vfp/fbinopWide.S */
5247    /*
5248     * Generic 64-bit double-precision floating point binary operation.
5249     * Provide an "instr" line that specifies an instruction that performs
5250     * "d2 = d0 op d1".
5251     *
5252     * for: add-double, sub-double, mul-double, div-double
5253     */
5254    /* doubleop vAA, vBB, vCC */
5255    FETCH(r0, 1)                        @ r0<- CCBB
5256    mov     r9, rINST, lsr #8           @ r9<- AA
5257    mov     r3, r0, lsr #8              @ r3<- CC
5258    and     r2, r0, #255                @ r2<- BB
5259    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5260    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5261    fldd    d1, [r3]                    @ d1<- vCC
5262    fldd    d0, [r2]                    @ d0<- vBB
5263
5264    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5265    fdivd   d2, d0, d1                              @ s2<- op
5266    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5267    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5268    fstd    d2, [r9]                    @ vAA<- d2
5269    GOTO_OPCODE(ip)                     @ jump to next instruction
5270
5271
5272/* ------------------------------ */
5273    .balign 64
5274.L_OP_REM_DOUBLE: /* 0xaf */
5275/* File: armv5te/OP_REM_DOUBLE.S */
5276/* EABI doesn't define a double remainder function, but libm does */
5277/* File: armv5te/binopWide.S */
5278    /*
5279     * Generic 64-bit binary operation.  Provide an "instr" line that
5280     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5281     * This could be an ARM instruction or a function call.  (If the result
5282     * comes back in a register other than r0, you can override "result".)
5283     *
5284     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5285     * vCC (r1).  Useful for integer division and modulus.
5286     *
5287     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5288     *      xor-long, add-double, sub-double, mul-double, div-double,
5289     *      rem-double
5290     *
5291     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5292     */
5293    /* binop vAA, vBB, vCC */
5294    FETCH(r0, 1)                        @ r0<- CCBB
5295    mov     r9, rINST, lsr #8           @ r9<- AA
5296    and     r2, r0, #255                @ r2<- BB
5297    mov     r3, r0, lsr #8              @ r3<- CC
5298    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5299    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5300    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5301    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5302    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5303    .if 0
5304    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5305    beq     common_errDivideByZero
5306    .endif
5307    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5308
5309                               @ optional op; may set condition codes
5310    bl      fmod                              @ result<- op, r0-r3 changed
5311    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5312    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5313    GOTO_OPCODE(ip)                     @ jump to next instruction
5314    /* 14-17 instructions */
5315
5316
5317
5318/* ------------------------------ */
5319    .balign 64
5320.L_OP_ADD_INT_2ADDR: /* 0xb0 */
5321/* File: armv5te/OP_ADD_INT_2ADDR.S */
5322/* File: armv5te/binop2addr.S */
5323    /*
5324     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5325     * that specifies an instruction that performs "result = r0 op r1".
5326     * This could be an ARM instruction or a function call.  (If the result
5327     * comes back in a register other than r0, you can override "result".)
5328     *
5329     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5330     * vCC (r1).  Useful for integer division and modulus.
5331     *
5332     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5333     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5334     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5335     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5336     */
5337    /* binop/2addr vA, vB */
5338    mov     r9, rINST, lsr #8           @ r9<- A+
5339    mov     r3, rINST, lsr #12          @ r3<- B
5340    and     r9, r9, #15
5341    GET_VREG(r1, r3)                    @ r1<- vB
5342    GET_VREG(r0, r9)                    @ r0<- vA
5343    .if 0
5344    cmp     r1, #0                      @ is second operand zero?
5345    beq     common_errDivideByZero
5346    .endif
5347    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5348
5349                               @ optional op; may set condition codes
5350    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
5351    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5352    SET_VREG(r0, r9)               @ vAA<- r0
5353    GOTO_OPCODE(ip)                     @ jump to next instruction
5354    /* 10-13 instructions */
5355
5356
5357
5358/* ------------------------------ */
5359    .balign 64
5360.L_OP_SUB_INT_2ADDR: /* 0xb1 */
5361/* File: armv5te/OP_SUB_INT_2ADDR.S */
5362/* File: armv5te/binop2addr.S */
5363    /*
5364     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5365     * that specifies an instruction that performs "result = r0 op r1".
5366     * This could be an ARM instruction or a function call.  (If the result
5367     * comes back in a register other than r0, you can override "result".)
5368     *
5369     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5370     * vCC (r1).  Useful for integer division and modulus.
5371     *
5372     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5373     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5374     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5375     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5376     */
5377    /* binop/2addr vA, vB */
5378    mov     r9, rINST, lsr #8           @ r9<- A+
5379    mov     r3, rINST, lsr #12          @ r3<- B
5380    and     r9, r9, #15
5381    GET_VREG(r1, r3)                    @ r1<- vB
5382    GET_VREG(r0, r9)                    @ r0<- vA
5383    .if 0
5384    cmp     r1, #0                      @ is second operand zero?
5385    beq     common_errDivideByZero
5386    .endif
5387    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5388
5389                               @ optional op; may set condition codes
5390    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
5391    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5392    SET_VREG(r0, r9)               @ vAA<- r0
5393    GOTO_OPCODE(ip)                     @ jump to next instruction
5394    /* 10-13 instructions */
5395
5396
5397
5398/* ------------------------------ */
5399    .balign 64
5400.L_OP_MUL_INT_2ADDR: /* 0xb2 */
5401/* File: armv5te/OP_MUL_INT_2ADDR.S */
5402/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
5403/* File: armv5te/binop2addr.S */
5404    /*
5405     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5406     * that specifies an instruction that performs "result = r0 op r1".
5407     * This could be an ARM instruction or a function call.  (If the result
5408     * comes back in a register other than r0, you can override "result".)
5409     *
5410     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5411     * vCC (r1).  Useful for integer division and modulus.
5412     *
5413     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5414     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5415     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5416     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5417     */
5418    /* binop/2addr vA, vB */
5419    mov     r9, rINST, lsr #8           @ r9<- A+
5420    mov     r3, rINST, lsr #12          @ r3<- B
5421    and     r9, r9, #15
5422    GET_VREG(r1, r3)                    @ r1<- vB
5423    GET_VREG(r0, r9)                    @ r0<- vA
5424    .if 0
5425    cmp     r1, #0                      @ is second operand zero?
5426    beq     common_errDivideByZero
5427    .endif
5428    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5429
5430                               @ optional op; may set condition codes
5431    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
5432    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5433    SET_VREG(r0, r9)               @ vAA<- r0
5434    GOTO_OPCODE(ip)                     @ jump to next instruction
5435    /* 10-13 instructions */
5436
5437
5438
5439/* ------------------------------ */
5440    .balign 64
5441.L_OP_DIV_INT_2ADDR: /* 0xb3 */
5442/* File: armv5te/OP_DIV_INT_2ADDR.S */
5443/* File: armv5te/binop2addr.S */
5444    /*
5445     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5446     * that specifies an instruction that performs "result = r0 op r1".
5447     * This could be an ARM instruction or a function call.  (If the result
5448     * comes back in a register other than r0, you can override "result".)
5449     *
5450     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5451     * vCC (r1).  Useful for integer division and modulus.
5452     *
5453     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5454     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5455     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5456     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5457     */
5458    /* binop/2addr vA, vB */
5459    mov     r9, rINST, lsr #8           @ r9<- A+
5460    mov     r3, rINST, lsr #12          @ r3<- B
5461    and     r9, r9, #15
5462    GET_VREG(r1, r3)                    @ r1<- vB
5463    GET_VREG(r0, r9)                    @ r0<- vA
5464    .if 1
5465    cmp     r1, #0                      @ is second operand zero?
5466    beq     common_errDivideByZero
5467    .endif
5468    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5469
5470                               @ optional op; may set condition codes
5471    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
5472    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5473    SET_VREG(r0, r9)               @ vAA<- r0
5474    GOTO_OPCODE(ip)                     @ jump to next instruction
5475    /* 10-13 instructions */
5476
5477
5478
5479/* ------------------------------ */
5480    .balign 64
5481.L_OP_REM_INT_2ADDR: /* 0xb4 */
5482/* File: armv5te/OP_REM_INT_2ADDR.S */
5483/* idivmod returns quotient in r0 and remainder in r1 */
5484/* File: armv5te/binop2addr.S */
5485    /*
5486     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5487     * that specifies an instruction that performs "result = r0 op r1".
5488     * This could be an ARM instruction or a function call.  (If the result
5489     * comes back in a register other than r0, you can override "result".)
5490     *
5491     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5492     * vCC (r1).  Useful for integer division and modulus.
5493     *
5494     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5495     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5496     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5497     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5498     */
5499    /* binop/2addr vA, vB */
5500    mov     r9, rINST, lsr #8           @ r9<- A+
5501    mov     r3, rINST, lsr #12          @ r3<- B
5502    and     r9, r9, #15
5503    GET_VREG(r1, r3)                    @ r1<- vB
5504    GET_VREG(r0, r9)                    @ r0<- vA
5505    .if 1
5506    cmp     r1, #0                      @ is second operand zero?
5507    beq     common_errDivideByZero
5508    .endif
5509    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5510
5511                               @ optional op; may set condition codes
5512    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
5513    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5514    SET_VREG(r1, r9)               @ vAA<- r1
5515    GOTO_OPCODE(ip)                     @ jump to next instruction
5516    /* 10-13 instructions */
5517
5518
5519
5520/* ------------------------------ */
5521    .balign 64
5522.L_OP_AND_INT_2ADDR: /* 0xb5 */
5523/* File: armv5te/OP_AND_INT_2ADDR.S */
5524/* File: armv5te/binop2addr.S */
5525    /*
5526     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5527     * that specifies an instruction that performs "result = r0 op r1".
5528     * This could be an ARM instruction or a function call.  (If the result
5529     * comes back in a register other than r0, you can override "result".)
5530     *
5531     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5532     * vCC (r1).  Useful for integer division and modulus.
5533     *
5534     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5535     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5536     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5537     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5538     */
5539    /* binop/2addr vA, vB */
5540    mov     r9, rINST, lsr #8           @ r9<- A+
5541    mov     r3, rINST, lsr #12          @ r3<- B
5542    and     r9, r9, #15
5543    GET_VREG(r1, r3)                    @ r1<- vB
5544    GET_VREG(r0, r9)                    @ r0<- vA
5545    .if 0
5546    cmp     r1, #0                      @ is second operand zero?
5547    beq     common_errDivideByZero
5548    .endif
5549    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5550
5551                               @ optional op; may set condition codes
5552    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
5553    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5554    SET_VREG(r0, r9)               @ vAA<- r0
5555    GOTO_OPCODE(ip)                     @ jump to next instruction
5556    /* 10-13 instructions */
5557
5558
5559
5560/* ------------------------------ */
5561    .balign 64
5562.L_OP_OR_INT_2ADDR: /* 0xb6 */
5563/* File: armv5te/OP_OR_INT_2ADDR.S */
5564/* File: armv5te/binop2addr.S */
5565    /*
5566     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5567     * that specifies an instruction that performs "result = r0 op r1".
5568     * This could be an ARM instruction or a function call.  (If the result
5569     * comes back in a register other than r0, you can override "result".)
5570     *
5571     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5572     * vCC (r1).  Useful for integer division and modulus.
5573     *
5574     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5575     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5576     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5577     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5578     */
5579    /* binop/2addr vA, vB */
5580    mov     r9, rINST, lsr #8           @ r9<- A+
5581    mov     r3, rINST, lsr #12          @ r3<- B
5582    and     r9, r9, #15
5583    GET_VREG(r1, r3)                    @ r1<- vB
5584    GET_VREG(r0, r9)                    @ r0<- vA
5585    .if 0
5586    cmp     r1, #0                      @ is second operand zero?
5587    beq     common_errDivideByZero
5588    .endif
5589    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5590
5591                               @ optional op; may set condition codes
5592    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
5593    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5594    SET_VREG(r0, r9)               @ vAA<- r0
5595    GOTO_OPCODE(ip)                     @ jump to next instruction
5596    /* 10-13 instructions */
5597
5598
5599
5600/* ------------------------------ */
5601    .balign 64
5602.L_OP_XOR_INT_2ADDR: /* 0xb7 */
5603/* File: armv5te/OP_XOR_INT_2ADDR.S */
5604/* File: armv5te/binop2addr.S */
5605    /*
5606     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5607     * that specifies an instruction that performs "result = r0 op r1".
5608     * This could be an ARM instruction or a function call.  (If the result
5609     * comes back in a register other than r0, you can override "result".)
5610     *
5611     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5612     * vCC (r1).  Useful for integer division and modulus.
5613     *
5614     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5615     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5616     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5617     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5618     */
5619    /* binop/2addr vA, vB */
5620    mov     r9, rINST, lsr #8           @ r9<- A+
5621    mov     r3, rINST, lsr #12          @ r3<- B
5622    and     r9, r9, #15
5623    GET_VREG(r1, r3)                    @ r1<- vB
5624    GET_VREG(r0, r9)                    @ r0<- vA
5625    .if 0
5626    cmp     r1, #0                      @ is second operand zero?
5627    beq     common_errDivideByZero
5628    .endif
5629    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5630
5631                               @ optional op; may set condition codes
5632    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
5633    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5634    SET_VREG(r0, r9)               @ vAA<- r0
5635    GOTO_OPCODE(ip)                     @ jump to next instruction
5636    /* 10-13 instructions */
5637
5638
5639
5640/* ------------------------------ */
5641    .balign 64
5642.L_OP_SHL_INT_2ADDR: /* 0xb8 */
5643/* File: armv5te/OP_SHL_INT_2ADDR.S */
5644/* File: armv5te/binop2addr.S */
5645    /*
5646     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5647     * that specifies an instruction that performs "result = r0 op r1".
5648     * This could be an ARM instruction or a function call.  (If the result
5649     * comes back in a register other than r0, you can override "result".)
5650     *
5651     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5652     * vCC (r1).  Useful for integer division and modulus.
5653     *
5654     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5655     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5656     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5657     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5658     */
5659    /* binop/2addr vA, vB */
5660    mov     r9, rINST, lsr #8           @ r9<- A+
5661    mov     r3, rINST, lsr #12          @ r3<- B
5662    and     r9, r9, #15
5663    GET_VREG(r1, r3)                    @ r1<- vB
5664    GET_VREG(r0, r9)                    @ r0<- vA
5665    .if 0
5666    cmp     r1, #0                      @ is second operand zero?
5667    beq     common_errDivideByZero
5668    .endif
5669    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5670
5671    and     r1, r1, #31                           @ optional op; may set condition codes
5672    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
5673    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5674    SET_VREG(r0, r9)               @ vAA<- r0
5675    GOTO_OPCODE(ip)                     @ jump to next instruction
5676    /* 10-13 instructions */
5677
5678
5679
5680/* ------------------------------ */
5681    .balign 64
5682.L_OP_SHR_INT_2ADDR: /* 0xb9 */
5683/* File: armv5te/OP_SHR_INT_2ADDR.S */
5684/* File: armv5te/binop2addr.S */
5685    /*
5686     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5687     * that specifies an instruction that performs "result = r0 op r1".
5688     * This could be an ARM instruction or a function call.  (If the result
5689     * comes back in a register other than r0, you can override "result".)
5690     *
5691     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5692     * vCC (r1).  Useful for integer division and modulus.
5693     *
5694     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5695     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5696     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5697     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5698     */
5699    /* binop/2addr vA, vB */
5700    mov     r9, rINST, lsr #8           @ r9<- A+
5701    mov     r3, rINST, lsr #12          @ r3<- B
5702    and     r9, r9, #15
5703    GET_VREG(r1, r3)                    @ r1<- vB
5704    GET_VREG(r0, r9)                    @ r0<- vA
5705    .if 0
5706    cmp     r1, #0                      @ is second operand zero?
5707    beq     common_errDivideByZero
5708    .endif
5709    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5710
5711    and     r1, r1, #31                           @ optional op; may set condition codes
5712    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
5713    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5714    SET_VREG(r0, r9)               @ vAA<- r0
5715    GOTO_OPCODE(ip)                     @ jump to next instruction
5716    /* 10-13 instructions */
5717
5718
5719
5720/* ------------------------------ */
5721    .balign 64
5722.L_OP_USHR_INT_2ADDR: /* 0xba */
5723/* File: armv5te/OP_USHR_INT_2ADDR.S */
5724/* File: armv5te/binop2addr.S */
5725    /*
5726     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5727     * that specifies an instruction that performs "result = r0 op r1".
5728     * This could be an ARM instruction or a function call.  (If the result
5729     * comes back in a register other than r0, you can override "result".)
5730     *
5731     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5732     * vCC (r1).  Useful for integer division and modulus.
5733     *
5734     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5735     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5736     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5737     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5738     */
5739    /* binop/2addr vA, vB */
5740    mov     r9, rINST, lsr #8           @ r9<- A+
5741    mov     r3, rINST, lsr #12          @ r3<- B
5742    and     r9, r9, #15
5743    GET_VREG(r1, r3)                    @ r1<- vB
5744    GET_VREG(r0, r9)                    @ r0<- vA
5745    .if 0
5746    cmp     r1, #0                      @ is second operand zero?
5747    beq     common_errDivideByZero
5748    .endif
5749    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5750
5751    and     r1, r1, #31                           @ optional op; may set condition codes
5752    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
5753    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5754    SET_VREG(r0, r9)               @ vAA<- r0
5755    GOTO_OPCODE(ip)                     @ jump to next instruction
5756    /* 10-13 instructions */
5757
5758
5759
5760/* ------------------------------ */
5761    .balign 64
5762.L_OP_ADD_LONG_2ADDR: /* 0xbb */
5763/* File: armv5te/OP_ADD_LONG_2ADDR.S */
5764/* File: armv5te/binopWide2addr.S */
5765    /*
5766     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5767     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5768     * This could be an ARM instruction or a function call.  (If the result
5769     * comes back in a register other than r0, you can override "result".)
5770     *
5771     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5772     * vCC (r1).  Useful for integer division and modulus.
5773     *
5774     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5775     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5776     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5777     *      rem-double/2addr
5778     */
5779    /* binop/2addr vA, vB */
5780    mov     r9, rINST, lsr #8           @ r9<- A+
5781    mov     r1, rINST, lsr #12          @ r1<- B
5782    and     r9, r9, #15
5783    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5784    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5785    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5786    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5787    .if 0
5788    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5789    beq     common_errDivideByZero
5790    .endif
5791    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5792
5793    adds    r0, r0, r2                           @ optional op; may set condition codes
5794    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
5795    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5796    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5797    GOTO_OPCODE(ip)                     @ jump to next instruction
5798    /* 12-15 instructions */
5799
5800
5801
5802/* ------------------------------ */
5803    .balign 64
5804.L_OP_SUB_LONG_2ADDR: /* 0xbc */
5805/* File: armv5te/OP_SUB_LONG_2ADDR.S */
5806/* File: armv5te/binopWide2addr.S */
5807    /*
5808     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5809     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5810     * This could be an ARM instruction or a function call.  (If the result
5811     * comes back in a register other than r0, you can override "result".)
5812     *
5813     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5814     * vCC (r1).  Useful for integer division and modulus.
5815     *
5816     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5817     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5818     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5819     *      rem-double/2addr
5820     */
5821    /* binop/2addr vA, vB */
5822    mov     r9, rINST, lsr #8           @ r9<- A+
5823    mov     r1, rINST, lsr #12          @ r1<- B
5824    and     r9, r9, #15
5825    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5826    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5827    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5828    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5829    .if 0
5830    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5831    beq     common_errDivideByZero
5832    .endif
5833    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5834
5835    subs    r0, r0, r2                           @ optional op; may set condition codes
5836    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
5837    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5838    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5839    GOTO_OPCODE(ip)                     @ jump to next instruction
5840    /* 12-15 instructions */
5841
5842
5843
5844/* ------------------------------ */
5845    .balign 64
5846.L_OP_MUL_LONG_2ADDR: /* 0xbd */
5847/* File: armv5te/OP_MUL_LONG_2ADDR.S */
5848    /*
5849     * Signed 64-bit integer multiply, "/2addr" version.
5850     *
5851     * See OP_MUL_LONG for an explanation.
5852     *
5853     * We get a little tight on registers, so to avoid looking up &fp[A]
5854     * again we stuff it into rINST.
5855     */
5856    /* mul-long/2addr vA, vB */
5857    mov     r9, rINST, lsr #8           @ r9<- A+
5858    mov     r1, rINST, lsr #12          @ r1<- B
5859    and     r9, r9, #15
5860    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5861    add     rINST, rFP, r9, lsl #2      @ rINST<- &fp[A]
5862    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5863    ldmia   rINST, {r0-r1}              @ r0/r1<- vAA/vAA+1
5864    mul     ip, r2, r1                  @  ip<- ZxW
5865    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
5866    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
5867    mov     r0, rINST                   @ r0<- &fp[A] (free up rINST)
5868    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5869    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
5870    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5871    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
5872    GOTO_OPCODE(ip)                     @ jump to next instruction
5873
5874
5875/* ------------------------------ */
5876    .balign 64
5877.L_OP_DIV_LONG_2ADDR: /* 0xbe */
5878/* File: armv5te/OP_DIV_LONG_2ADDR.S */
5879/* File: armv5te/binopWide2addr.S */
5880    /*
5881     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5882     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5883     * This could be an ARM instruction or a function call.  (If the result
5884     * comes back in a register other than r0, you can override "result".)
5885     *
5886     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5887     * vCC (r1).  Useful for integer division and modulus.
5888     *
5889     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5890     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5891     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5892     *      rem-double/2addr
5893     */
5894    /* binop/2addr vA, vB */
5895    mov     r9, rINST, lsr #8           @ r9<- A+
5896    mov     r1, rINST, lsr #12          @ r1<- B
5897    and     r9, r9, #15
5898    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5899    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5900    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5901    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5902    .if 1
5903    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5904    beq     common_errDivideByZero
5905    .endif
5906    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5907
5908                               @ optional op; may set condition codes
5909    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5910    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5911    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5912    GOTO_OPCODE(ip)                     @ jump to next instruction
5913    /* 12-15 instructions */
5914
5915
5916
5917/* ------------------------------ */
5918    .balign 64
5919.L_OP_REM_LONG_2ADDR: /* 0xbf */
5920/* File: armv5te/OP_REM_LONG_2ADDR.S */
5921/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
5922/* File: armv5te/binopWide2addr.S */
5923    /*
5924     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5925     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5926     * This could be an ARM instruction or a function call.  (If the result
5927     * comes back in a register other than r0, you can override "result".)
5928     *
5929     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5930     * vCC (r1).  Useful for integer division and modulus.
5931     *
5932     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5933     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5934     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5935     *      rem-double/2addr
5936     */
5937    /* binop/2addr vA, vB */
5938    mov     r9, rINST, lsr #8           @ r9<- A+
5939    mov     r1, rINST, lsr #12          @ r1<- B
5940    and     r9, r9, #15
5941    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5942    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5943    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5944    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5945    .if 1
5946    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5947    beq     common_errDivideByZero
5948    .endif
5949    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5950
5951                               @ optional op; may set condition codes
5952    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5953    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5954    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
5955    GOTO_OPCODE(ip)                     @ jump to next instruction
5956    /* 12-15 instructions */
5957
5958
5959
5960/* ------------------------------ */
5961    .balign 64
5962.L_OP_AND_LONG_2ADDR: /* 0xc0 */
5963/* File: armv5te/OP_AND_LONG_2ADDR.S */
5964/* File: armv5te/binopWide2addr.S */
5965    /*
5966     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5967     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5968     * This could be an ARM instruction or a function call.  (If the result
5969     * comes back in a register other than r0, you can override "result".)
5970     *
5971     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5972     * vCC (r1).  Useful for integer division and modulus.
5973     *
5974     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5975     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5976     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5977     *      rem-double/2addr
5978     */
5979    /* binop/2addr vA, vB */
5980    mov     r9, rINST, lsr #8           @ r9<- A+
5981    mov     r1, rINST, lsr #12          @ r1<- B
5982    and     r9, r9, #15
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    and     r0, r0, r2                           @ optional op; may set condition codes
5994    and     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_OR_LONG_2ADDR: /* 0xc1 */
6005/* File: armv5te/OP_OR_LONG_2ADDR.S */
6006/* File: armv5te/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     r9, rINST, lsr #8           @ r9<- A+
6023    mov     r1, rINST, lsr #12          @ r1<- B
6024    and     r9, r9, #15
6025    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6026    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6027    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6028    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6029    .if 0
6030    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6031    beq     common_errDivideByZero
6032    .endif
6033    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6034
6035    orr     r0, r0, r2                           @ optional op; may set condition codes
6036    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
6037    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6038    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6039    GOTO_OPCODE(ip)                     @ jump to next instruction
6040    /* 12-15 instructions */
6041
6042
6043
6044/* ------------------------------ */
6045    .balign 64
6046.L_OP_XOR_LONG_2ADDR: /* 0xc2 */
6047/* File: armv5te/OP_XOR_LONG_2ADDR.S */
6048/* File: armv5te/binopWide2addr.S */
6049    /*
6050     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6051     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6052     * This could be an ARM instruction or a function call.  (If the result
6053     * comes back in a register other than r0, you can override "result".)
6054     *
6055     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6056     * vCC (r1).  Useful for integer division and modulus.
6057     *
6058     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6059     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6060     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6061     *      rem-double/2addr
6062     */
6063    /* binop/2addr vA, vB */
6064    mov     r9, rINST, lsr #8           @ r9<- A+
6065    mov     r1, rINST, lsr #12          @ r1<- B
6066    and     r9, r9, #15
6067    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6068    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6069    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6070    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6071    .if 0
6072    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6073    beq     common_errDivideByZero
6074    .endif
6075    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6076
6077    eor     r0, r0, r2                           @ optional op; may set condition codes
6078    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
6079    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6080    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6081    GOTO_OPCODE(ip)                     @ jump to next instruction
6082    /* 12-15 instructions */
6083
6084
6085
6086/* ------------------------------ */
6087    .balign 64
6088.L_OP_SHL_LONG_2ADDR: /* 0xc3 */
6089/* File: armv5te/OP_SHL_LONG_2ADDR.S */
6090    /*
6091     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6092     * 32-bit shift distance.
6093     */
6094    /* shl-long/2addr vA, vB */
6095    mov     r9, rINST, lsr #8           @ r9<- A+
6096    mov     r3, rINST, lsr #12          @ r3<- B
6097    and     r9, r9, #15
6098    GET_VREG(r2, r3)                    @ r2<- vB
6099    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6100    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6101    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6102
6103    mov     r1, r1, asl r2              @  r1<- r1 << r2
6104    rsb     r3, r2, #32                 @  r3<- 32 - r2
6105    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
6106    subs    ip, r2, #32                 @  ip<- r2 - 32
6107    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6108    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
6109    mov     r0, r0, asl r2              @  r0<- r0 << r2
6110    b       .LOP_SHL_LONG_2ADDR_finish
6111
6112/* ------------------------------ */
6113    .balign 64
6114.L_OP_SHR_LONG_2ADDR: /* 0xc4 */
6115/* File: armv5te/OP_SHR_LONG_2ADDR.S */
6116    /*
6117     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6118     * 32-bit shift distance.
6119     */
6120    /* shr-long/2addr vA, vB */
6121    mov     r9, rINST, lsr #8           @ r9<- A+
6122    mov     r3, rINST, lsr #12          @ r3<- B
6123    and     r9, r9, #15
6124    GET_VREG(r2, r3)                    @ r2<- vB
6125    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6126    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6127    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6128
6129    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6130    rsb     r3, r2, #32                 @  r3<- 32 - r2
6131    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6132    subs    ip, r2, #32                 @  ip<- r2 - 32
6133    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6134    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
6135    mov     r1, r1, asr r2              @  r1<- r1 >> r2
6136    b       .LOP_SHR_LONG_2ADDR_finish
6137
6138/* ------------------------------ */
6139    .balign 64
6140.L_OP_USHR_LONG_2ADDR: /* 0xc5 */
6141/* File: armv5te/OP_USHR_LONG_2ADDR.S */
6142    /*
6143     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6144     * 32-bit shift distance.
6145     */
6146    /* ushr-long/2addr vA, vB */
6147    mov     r9, rINST, lsr #8           @ r9<- A+
6148    mov     r3, rINST, lsr #12          @ r3<- B
6149    and     r9, r9, #15
6150    GET_VREG(r2, r3)                    @ r2<- vB
6151    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6152    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6153    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6154
6155    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6156    rsb     r3, r2, #32                 @  r3<- 32 - r2
6157    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6158    subs    ip, r2, #32                 @  ip<- r2 - 32
6159    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6160    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
6161    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
6162    b       .LOP_USHR_LONG_2ADDR_finish
6163
6164/* ------------------------------ */
6165    .balign 64
6166.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
6167/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */
6168/* File: arm-vfp/fbinop2addr.S */
6169    /*
6170     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6171     * an "instr" line that specifies an instruction that performs
6172     * "s2 = s0 op s1".
6173     *
6174     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6175     */
6176    /* binop/2addr vA, vB */
6177    mov     r3, rINST, lsr #12          @ r3<- B
6178    mov     r9, rINST, lsr #8           @ r9<- A+
6179    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6180    and     r9, r9, #15                 @ r9<- A
6181    flds    s1, [r3]                    @ s1<- vB
6182    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6183    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6184    flds    s0, [r9]                    @ s0<- vA
6185
6186    fadds   s2, s0, s1                              @ s2<- op
6187    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6188    fsts    s2, [r9]                    @ vAA<- s2
6189    GOTO_OPCODE(ip)                     @ jump to next instruction
6190
6191
6192/* ------------------------------ */
6193    .balign 64
6194.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
6195/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */
6196/* File: arm-vfp/fbinop2addr.S */
6197    /*
6198     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6199     * an "instr" line that specifies an instruction that performs
6200     * "s2 = s0 op s1".
6201     *
6202     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6203     */
6204    /* binop/2addr vA, vB */
6205    mov     r3, rINST, lsr #12          @ r3<- B
6206    mov     r9, rINST, lsr #8           @ r9<- A+
6207    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6208    and     r9, r9, #15                 @ r9<- A
6209    flds    s1, [r3]                    @ s1<- vB
6210    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6211    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6212    flds    s0, [r9]                    @ s0<- vA
6213
6214    fsubs   s2, s0, s1                              @ s2<- op
6215    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6216    fsts    s2, [r9]                    @ vAA<- s2
6217    GOTO_OPCODE(ip)                     @ jump to next instruction
6218
6219
6220/* ------------------------------ */
6221    .balign 64
6222.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
6223/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */
6224/* File: arm-vfp/fbinop2addr.S */
6225    /*
6226     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6227     * an "instr" line that specifies an instruction that performs
6228     * "s2 = s0 op s1".
6229     *
6230     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6231     */
6232    /* binop/2addr vA, vB */
6233    mov     r3, rINST, lsr #12          @ r3<- B
6234    mov     r9, rINST, lsr #8           @ r9<- A+
6235    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6236    and     r9, r9, #15                 @ r9<- A
6237    flds    s1, [r3]                    @ s1<- vB
6238    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6239    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6240    flds    s0, [r9]                    @ s0<- vA
6241
6242    fmuls   s2, s0, s1                              @ s2<- op
6243    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6244    fsts    s2, [r9]                    @ vAA<- s2
6245    GOTO_OPCODE(ip)                     @ jump to next instruction
6246
6247
6248/* ------------------------------ */
6249    .balign 64
6250.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
6251/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */
6252/* File: arm-vfp/fbinop2addr.S */
6253    /*
6254     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6255     * an "instr" line that specifies an instruction that performs
6256     * "s2 = s0 op s1".
6257     *
6258     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6259     */
6260    /* binop/2addr vA, vB */
6261    mov     r3, rINST, lsr #12          @ r3<- B
6262    mov     r9, rINST, lsr #8           @ r9<- A+
6263    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6264    and     r9, r9, #15                 @ r9<- A
6265    flds    s1, [r3]                    @ s1<- vB
6266    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6267    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6268    flds    s0, [r9]                    @ s0<- vA
6269
6270    fdivs   s2, s0, s1                              @ s2<- op
6271    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6272    fsts    s2, [r9]                    @ vAA<- s2
6273    GOTO_OPCODE(ip)                     @ jump to next instruction
6274
6275
6276/* ------------------------------ */
6277    .balign 64
6278.L_OP_REM_FLOAT_2ADDR: /* 0xca */
6279/* File: armv5te/OP_REM_FLOAT_2ADDR.S */
6280/* EABI doesn't define a float remainder function, but libm does */
6281/* File: armv5te/binop2addr.S */
6282    /*
6283     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6284     * that specifies an instruction that performs "result = r0 op r1".
6285     * This could be an ARM instruction or a function call.  (If the result
6286     * comes back in a register other than r0, you can override "result".)
6287     *
6288     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6289     * vCC (r1).  Useful for integer division and modulus.
6290     *
6291     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6292     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6293     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6294     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6295     */
6296    /* binop/2addr vA, vB */
6297    mov     r9, rINST, lsr #8           @ r9<- A+
6298    mov     r3, rINST, lsr #12          @ r3<- B
6299    and     r9, r9, #15
6300    GET_VREG(r1, r3)                    @ r1<- vB
6301    GET_VREG(r0, r9)                    @ r0<- vA
6302    .if 0
6303    cmp     r1, #0                      @ is second operand zero?
6304    beq     common_errDivideByZero
6305    .endif
6306    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6307
6308                               @ optional op; may set condition codes
6309    bl      fmodf                              @ r0<- op, r0-r3 changed
6310    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6311    SET_VREG(r0, r9)               @ vAA<- r0
6312    GOTO_OPCODE(ip)                     @ jump to next instruction
6313    /* 10-13 instructions */
6314
6315
6316
6317/* ------------------------------ */
6318    .balign 64
6319.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
6320/* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */
6321/* File: arm-vfp/fbinopWide2addr.S */
6322    /*
6323     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6324     * an "instr" line that specifies an instruction that performs
6325     * "d2 = d0 op d1".
6326     *
6327     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6328     *      div-double/2addr
6329     */
6330    /* binop/2addr vA, vB */
6331    mov     r3, rINST, lsr #12          @ r3<- B
6332    mov     r9, rINST, lsr #8           @ r9<- A+
6333    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6334    and     r9, r9, #15                 @ r9<- A
6335    fldd    d1, [r3]                    @ d1<- vB
6336    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6337    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6338    fldd    d0, [r9]                    @ d0<- vA
6339
6340    faddd   d2, d0, d1                              @ d2<- op
6341    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6342    fstd    d2, [r9]                    @ vAA<- d2
6343    GOTO_OPCODE(ip)                     @ jump to next instruction
6344
6345
6346/* ------------------------------ */
6347    .balign 64
6348.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
6349/* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */
6350/* File: arm-vfp/fbinopWide2addr.S */
6351    /*
6352     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6353     * an "instr" line that specifies an instruction that performs
6354     * "d2 = d0 op d1".
6355     *
6356     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6357     *      div-double/2addr
6358     */
6359    /* binop/2addr vA, vB */
6360    mov     r3, rINST, lsr #12          @ r3<- B
6361    mov     r9, rINST, lsr #8           @ r9<- A+
6362    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6363    and     r9, r9, #15                 @ r9<- A
6364    fldd    d1, [r3]                    @ d1<- vB
6365    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6366    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6367    fldd    d0, [r9]                    @ d0<- vA
6368
6369    fsubd   d2, d0, d1                              @ d2<- op
6370    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6371    fstd    d2, [r9]                    @ vAA<- d2
6372    GOTO_OPCODE(ip)                     @ jump to next instruction
6373
6374
6375/* ------------------------------ */
6376    .balign 64
6377.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
6378/* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */
6379/* File: arm-vfp/fbinopWide2addr.S */
6380    /*
6381     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6382     * an "instr" line that specifies an instruction that performs
6383     * "d2 = d0 op d1".
6384     *
6385     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6386     *      div-double/2addr
6387     */
6388    /* binop/2addr vA, vB */
6389    mov     r3, rINST, lsr #12          @ r3<- B
6390    mov     r9, rINST, lsr #8           @ r9<- A+
6391    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6392    and     r9, r9, #15                 @ r9<- A
6393    fldd    d1, [r3]                    @ d1<- vB
6394    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6395    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6396    fldd    d0, [r9]                    @ d0<- vA
6397
6398    fmuld   d2, d0, d1                              @ d2<- op
6399    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6400    fstd    d2, [r9]                    @ vAA<- d2
6401    GOTO_OPCODE(ip)                     @ jump to next instruction
6402
6403
6404/* ------------------------------ */
6405    .balign 64
6406.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
6407/* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */
6408/* File: arm-vfp/fbinopWide2addr.S */
6409    /*
6410     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6411     * an "instr" line that specifies an instruction that performs
6412     * "d2 = d0 op d1".
6413     *
6414     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6415     *      div-double/2addr
6416     */
6417    /* binop/2addr vA, vB */
6418    mov     r3, rINST, lsr #12          @ r3<- B
6419    mov     r9, rINST, lsr #8           @ r9<- A+
6420    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6421    and     r9, r9, #15                 @ r9<- A
6422    fldd    d1, [r3]                    @ d1<- vB
6423    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6424    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6425    fldd    d0, [r9]                    @ d0<- vA
6426
6427    fdivd   d2, d0, d1                              @ d2<- op
6428    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6429    fstd    d2, [r9]                    @ vAA<- d2
6430    GOTO_OPCODE(ip)                     @ jump to next instruction
6431
6432
6433/* ------------------------------ */
6434    .balign 64
6435.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
6436/* File: armv5te/OP_REM_DOUBLE_2ADDR.S */
6437/* EABI doesn't define a double remainder function, but libm does */
6438/* File: armv5te/binopWide2addr.S */
6439    /*
6440     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6441     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6442     * This could be an ARM instruction or a function call.  (If the result
6443     * comes back in a register other than r0, you can override "result".)
6444     *
6445     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6446     * vCC (r1).  Useful for integer division and modulus.
6447     *
6448     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6449     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6450     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6451     *      rem-double/2addr
6452     */
6453    /* binop/2addr vA, vB */
6454    mov     r9, rINST, lsr #8           @ r9<- A+
6455    mov     r1, rINST, lsr #12          @ r1<- B
6456    and     r9, r9, #15
6457    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6458    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6459    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6460    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6461    .if 0
6462    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6463    beq     common_errDivideByZero
6464    .endif
6465    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6466
6467                               @ optional op; may set condition codes
6468    bl      fmod                              @ result<- op, r0-r3 changed
6469    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6470    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6471    GOTO_OPCODE(ip)                     @ jump to next instruction
6472    /* 12-15 instructions */
6473
6474
6475
6476/* ------------------------------ */
6477    .balign 64
6478.L_OP_ADD_INT_LIT16: /* 0xd0 */
6479/* File: armv5te/OP_ADD_INT_LIT16.S */
6480/* File: armv5te/binopLit16.S */
6481    /*
6482     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6483     * that specifies an instruction that performs "result = r0 op r1".
6484     * This could be an ARM instruction or a function call.  (If the result
6485     * comes back in a register other than r0, you can override "result".)
6486     *
6487     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6488     * vCC (r1).  Useful for integer division and modulus.
6489     *
6490     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6491     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6492     */
6493    /* binop/lit16 vA, vB, #+CCCC */
6494    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6495    mov     r2, rINST, lsr #12          @ r2<- B
6496    mov     r9, rINST, lsr #8           @ r9<- A+
6497    GET_VREG(r0, r2)                    @ r0<- vB
6498    and     r9, r9, #15
6499    .if 0
6500    cmp     r1, #0                      @ is second operand zero?
6501    beq     common_errDivideByZero
6502    .endif
6503    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6504
6505    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6506    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6507    SET_VREG(r0, r9)               @ vAA<- r0
6508    GOTO_OPCODE(ip)                     @ jump to next instruction
6509    /* 10-13 instructions */
6510
6511
6512
6513/* ------------------------------ */
6514    .balign 64
6515.L_OP_RSUB_INT: /* 0xd1 */
6516/* File: armv5te/OP_RSUB_INT.S */
6517/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
6518/* File: armv5te/binopLit16.S */
6519    /*
6520     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6521     * that specifies an instruction that performs "result = r0 op r1".
6522     * This could be an ARM instruction or a function call.  (If the result
6523     * comes back in a register other than r0, you can override "result".)
6524     *
6525     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6526     * vCC (r1).  Useful for integer division and modulus.
6527     *
6528     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6529     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6530     */
6531    /* binop/lit16 vA, vB, #+CCCC */
6532    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6533    mov     r2, rINST, lsr #12          @ r2<- B
6534    mov     r9, rINST, lsr #8           @ r9<- A+
6535    GET_VREG(r0, r2)                    @ r0<- vB
6536    and     r9, r9, #15
6537    .if 0
6538    cmp     r1, #0                      @ is second operand zero?
6539    beq     common_errDivideByZero
6540    .endif
6541    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6542
6543    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6544    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6545    SET_VREG(r0, r9)               @ vAA<- r0
6546    GOTO_OPCODE(ip)                     @ jump to next instruction
6547    /* 10-13 instructions */
6548
6549
6550
6551/* ------------------------------ */
6552    .balign 64
6553.L_OP_MUL_INT_LIT16: /* 0xd2 */
6554/* File: armv5te/OP_MUL_INT_LIT16.S */
6555/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6556/* File: armv5te/binopLit16.S */
6557    /*
6558     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6559     * that specifies an instruction that performs "result = r0 op r1".
6560     * This could be an ARM instruction or a function call.  (If the result
6561     * comes back in a register other than r0, you can override "result".)
6562     *
6563     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6564     * vCC (r1).  Useful for integer division and modulus.
6565     *
6566     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6567     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6568     */
6569    /* binop/lit16 vA, vB, #+CCCC */
6570    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6571    mov     r2, rINST, lsr #12          @ r2<- B
6572    mov     r9, rINST, lsr #8           @ r9<- A+
6573    GET_VREG(r0, r2)                    @ r0<- vB
6574    and     r9, r9, #15
6575    .if 0
6576    cmp     r1, #0                      @ is second operand zero?
6577    beq     common_errDivideByZero
6578    .endif
6579    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6580
6581    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6582    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6583    SET_VREG(r0, r9)               @ vAA<- r0
6584    GOTO_OPCODE(ip)                     @ jump to next instruction
6585    /* 10-13 instructions */
6586
6587
6588
6589/* ------------------------------ */
6590    .balign 64
6591.L_OP_DIV_INT_LIT16: /* 0xd3 */
6592/* File: armv5te/OP_DIV_INT_LIT16.S */
6593/* File: armv5te/binopLit16.S */
6594    /*
6595     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6596     * that specifies an instruction that performs "result = r0 op r1".
6597     * This could be an ARM instruction or a function call.  (If the result
6598     * comes back in a register other than r0, you can override "result".)
6599     *
6600     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6601     * vCC (r1).  Useful for integer division and modulus.
6602     *
6603     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6604     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6605     */
6606    /* binop/lit16 vA, vB, #+CCCC */
6607    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6608    mov     r2, rINST, lsr #12          @ r2<- B
6609    mov     r9, rINST, lsr #8           @ r9<- A+
6610    GET_VREG(r0, r2)                    @ r0<- vB
6611    and     r9, r9, #15
6612    .if 1
6613    cmp     r1, #0                      @ is second operand zero?
6614    beq     common_errDivideByZero
6615    .endif
6616    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6617
6618    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6619    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6620    SET_VREG(r0, r9)               @ vAA<- r0
6621    GOTO_OPCODE(ip)                     @ jump to next instruction
6622    /* 10-13 instructions */
6623
6624
6625
6626/* ------------------------------ */
6627    .balign 64
6628.L_OP_REM_INT_LIT16: /* 0xd4 */
6629/* File: armv5te/OP_REM_INT_LIT16.S */
6630/* idivmod returns quotient in r0 and remainder in r1 */
6631/* File: armv5te/binopLit16.S */
6632    /*
6633     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6634     * that specifies an instruction that performs "result = r0 op r1".
6635     * This could be an ARM instruction or a function call.  (If the result
6636     * comes back in a register other than r0, you can override "result".)
6637     *
6638     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6639     * vCC (r1).  Useful for integer division and modulus.
6640     *
6641     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6642     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6643     */
6644    /* binop/lit16 vA, vB, #+CCCC */
6645    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6646    mov     r2, rINST, lsr #12          @ r2<- B
6647    mov     r9, rINST, lsr #8           @ r9<- A+
6648    GET_VREG(r0, r2)                    @ r0<- vB
6649    and     r9, r9, #15
6650    .if 1
6651    cmp     r1, #0                      @ is second operand zero?
6652    beq     common_errDivideByZero
6653    .endif
6654    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6655
6656    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6657    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6658    SET_VREG(r1, r9)               @ vAA<- r1
6659    GOTO_OPCODE(ip)                     @ jump to next instruction
6660    /* 10-13 instructions */
6661
6662
6663
6664/* ------------------------------ */
6665    .balign 64
6666.L_OP_AND_INT_LIT16: /* 0xd5 */
6667/* File: armv5te/OP_AND_INT_LIT16.S */
6668/* File: armv5te/binopLit16.S */
6669    /*
6670     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6671     * that specifies an instruction that performs "result = r0 op r1".
6672     * This could be an ARM instruction or a function call.  (If the result
6673     * comes back in a register other than r0, you can override "result".)
6674     *
6675     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6676     * vCC (r1).  Useful for integer division and modulus.
6677     *
6678     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6679     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6680     */
6681    /* binop/lit16 vA, vB, #+CCCC */
6682    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6683    mov     r2, rINST, lsr #12          @ r2<- B
6684    mov     r9, rINST, lsr #8           @ r9<- A+
6685    GET_VREG(r0, r2)                    @ r0<- vB
6686    and     r9, r9, #15
6687    .if 0
6688    cmp     r1, #0                      @ is second operand zero?
6689    beq     common_errDivideByZero
6690    .endif
6691    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6692
6693    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6694    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6695    SET_VREG(r0, r9)               @ vAA<- r0
6696    GOTO_OPCODE(ip)                     @ jump to next instruction
6697    /* 10-13 instructions */
6698
6699
6700
6701/* ------------------------------ */
6702    .balign 64
6703.L_OP_OR_INT_LIT16: /* 0xd6 */
6704/* File: armv5te/OP_OR_INT_LIT16.S */
6705/* File: armv5te/binopLit16.S */
6706    /*
6707     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6708     * that specifies an instruction that performs "result = r0 op r1".
6709     * This could be an ARM instruction or a function call.  (If the result
6710     * comes back in a register other than r0, you can override "result".)
6711     *
6712     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6713     * vCC (r1).  Useful for integer division and modulus.
6714     *
6715     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6716     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6717     */
6718    /* binop/lit16 vA, vB, #+CCCC */
6719    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6720    mov     r2, rINST, lsr #12          @ r2<- B
6721    mov     r9, rINST, lsr #8           @ r9<- A+
6722    GET_VREG(r0, r2)                    @ r0<- vB
6723    and     r9, r9, #15
6724    .if 0
6725    cmp     r1, #0                      @ is second operand zero?
6726    beq     common_errDivideByZero
6727    .endif
6728    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6729
6730    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6731    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6732    SET_VREG(r0, r9)               @ vAA<- r0
6733    GOTO_OPCODE(ip)                     @ jump to next instruction
6734    /* 10-13 instructions */
6735
6736
6737
6738/* ------------------------------ */
6739    .balign 64
6740.L_OP_XOR_INT_LIT16: /* 0xd7 */
6741/* File: armv5te/OP_XOR_INT_LIT16.S */
6742/* File: armv5te/binopLit16.S */
6743    /*
6744     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6745     * that specifies an instruction that performs "result = r0 op r1".
6746     * This could be an ARM instruction or a function call.  (If the result
6747     * comes back in a register other than r0, you can override "result".)
6748     *
6749     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6750     * vCC (r1).  Useful for integer division and modulus.
6751     *
6752     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6753     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6754     */
6755    /* binop/lit16 vA, vB, #+CCCC */
6756    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6757    mov     r2, rINST, lsr #12          @ r2<- B
6758    mov     r9, rINST, lsr #8           @ r9<- A+
6759    GET_VREG(r0, r2)                    @ r0<- vB
6760    and     r9, r9, #15
6761    .if 0
6762    cmp     r1, #0                      @ is second operand zero?
6763    beq     common_errDivideByZero
6764    .endif
6765    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6766
6767    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
6768    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6769    SET_VREG(r0, r9)               @ vAA<- r0
6770    GOTO_OPCODE(ip)                     @ jump to next instruction
6771    /* 10-13 instructions */
6772
6773
6774
6775/* ------------------------------ */
6776    .balign 64
6777.L_OP_ADD_INT_LIT8: /* 0xd8 */
6778/* File: armv5te/OP_ADD_INT_LIT8.S */
6779/* File: armv5te/binopLit8.S */
6780    /*
6781     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6782     * that specifies an instruction that performs "result = r0 op r1".
6783     * This could be an ARM instruction or a function call.  (If the result
6784     * comes back in a register other than r0, you can override "result".)
6785     *
6786     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6787     * vCC (r1).  Useful for integer division and modulus.
6788     *
6789     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6790     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6791     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6792     */
6793    /* binop/lit8 vAA, vBB, #+CC */
6794    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6795    mov     r9, rINST, lsr #8           @ r9<- AA
6796    and     r2, r3, #255                @ r2<- BB
6797    GET_VREG(r0, r2)                    @ r0<- vBB
6798    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6799    .if 0
6800    @cmp     r1, #0                      @ is second operand zero?
6801    beq     common_errDivideByZero
6802    .endif
6803    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6804
6805                               @ optional op; may set condition codes
6806    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6807    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6808    SET_VREG(r0, r9)               @ vAA<- r0
6809    GOTO_OPCODE(ip)                     @ jump to next instruction
6810    /* 10-12 instructions */
6811
6812
6813
6814/* ------------------------------ */
6815    .balign 64
6816.L_OP_RSUB_INT_LIT8: /* 0xd9 */
6817/* File: armv5te/OP_RSUB_INT_LIT8.S */
6818/* File: armv5te/binopLit8.S */
6819    /*
6820     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6821     * that specifies an instruction that performs "result = r0 op r1".
6822     * This could be an ARM instruction or a function call.  (If the result
6823     * comes back in a register other than r0, you can override "result".)
6824     *
6825     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6826     * vCC (r1).  Useful for integer division and modulus.
6827     *
6828     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6829     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6830     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6831     */
6832    /* binop/lit8 vAA, vBB, #+CC */
6833    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6834    mov     r9, rINST, lsr #8           @ r9<- AA
6835    and     r2, r3, #255                @ r2<- BB
6836    GET_VREG(r0, r2)                    @ r0<- vBB
6837    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6838    .if 0
6839    @cmp     r1, #0                      @ is second operand zero?
6840    beq     common_errDivideByZero
6841    .endif
6842    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6843
6844                               @ optional op; may set condition codes
6845    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6846    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6847    SET_VREG(r0, r9)               @ vAA<- r0
6848    GOTO_OPCODE(ip)                     @ jump to next instruction
6849    /* 10-12 instructions */
6850
6851
6852
6853/* ------------------------------ */
6854    .balign 64
6855.L_OP_MUL_INT_LIT8: /* 0xda */
6856/* File: armv5te/OP_MUL_INT_LIT8.S */
6857/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6858/* File: armv5te/binopLit8.S */
6859    /*
6860     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6861     * that specifies an instruction that performs "result = r0 op r1".
6862     * This could be an ARM instruction or a function call.  (If the result
6863     * comes back in a register other than r0, you can override "result".)
6864     *
6865     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6866     * vCC (r1).  Useful for integer division and modulus.
6867     *
6868     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6869     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6870     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6871     */
6872    /* binop/lit8 vAA, vBB, #+CC */
6873    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6874    mov     r9, rINST, lsr #8           @ r9<- AA
6875    and     r2, r3, #255                @ r2<- BB
6876    GET_VREG(r0, r2)                    @ r0<- vBB
6877    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6878    .if 0
6879    @cmp     r1, #0                      @ is second operand zero?
6880    beq     common_errDivideByZero
6881    .endif
6882    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6883
6884                               @ optional op; may set condition codes
6885    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6886    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6887    SET_VREG(r0, r9)               @ vAA<- r0
6888    GOTO_OPCODE(ip)                     @ jump to next instruction
6889    /* 10-12 instructions */
6890
6891
6892
6893/* ------------------------------ */
6894    .balign 64
6895.L_OP_DIV_INT_LIT8: /* 0xdb */
6896/* File: armv5te/OP_DIV_INT_LIT8.S */
6897/* File: armv5te/binopLit8.S */
6898    /*
6899     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6900     * that specifies an instruction that performs "result = r0 op r1".
6901     * This could be an ARM instruction or a function call.  (If the result
6902     * comes back in a register other than r0, you can override "result".)
6903     *
6904     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6905     * vCC (r1).  Useful for integer division and modulus.
6906     *
6907     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6908     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6909     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6910     */
6911    /* binop/lit8 vAA, vBB, #+CC */
6912    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6913    mov     r9, rINST, lsr #8           @ r9<- AA
6914    and     r2, r3, #255                @ r2<- BB
6915    GET_VREG(r0, r2)                    @ r0<- vBB
6916    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6917    .if 1
6918    @cmp     r1, #0                      @ is second operand zero?
6919    beq     common_errDivideByZero
6920    .endif
6921    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6922
6923                               @ optional op; may set condition codes
6924    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6925    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6926    SET_VREG(r0, r9)               @ vAA<- r0
6927    GOTO_OPCODE(ip)                     @ jump to next instruction
6928    /* 10-12 instructions */
6929
6930
6931
6932/* ------------------------------ */
6933    .balign 64
6934.L_OP_REM_INT_LIT8: /* 0xdc */
6935/* File: armv5te/OP_REM_INT_LIT8.S */
6936/* idivmod returns quotient in r0 and remainder in r1 */
6937/* File: armv5te/binopLit8.S */
6938    /*
6939     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6940     * that specifies an instruction that performs "result = r0 op r1".
6941     * This could be an ARM instruction or a function call.  (If the result
6942     * comes back in a register other than r0, you can override "result".)
6943     *
6944     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6945     * vCC (r1).  Useful for integer division and modulus.
6946     *
6947     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6948     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6949     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6950     */
6951    /* binop/lit8 vAA, vBB, #+CC */
6952    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6953    mov     r9, rINST, lsr #8           @ r9<- AA
6954    and     r2, r3, #255                @ r2<- BB
6955    GET_VREG(r0, r2)                    @ r0<- vBB
6956    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6957    .if 1
6958    @cmp     r1, #0                      @ is second operand zero?
6959    beq     common_errDivideByZero
6960    .endif
6961    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6962
6963                               @ optional op; may set condition codes
6964    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6965    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6966    SET_VREG(r1, r9)               @ vAA<- r1
6967    GOTO_OPCODE(ip)                     @ jump to next instruction
6968    /* 10-12 instructions */
6969
6970
6971
6972/* ------------------------------ */
6973    .balign 64
6974.L_OP_AND_INT_LIT8: /* 0xdd */
6975/* File: armv5te/OP_AND_INT_LIT8.S */
6976/* File: armv5te/binopLit8.S */
6977    /*
6978     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6979     * that specifies an instruction that performs "result = r0 op r1".
6980     * This could be an ARM instruction or a function call.  (If the result
6981     * comes back in a register other than r0, you can override "result".)
6982     *
6983     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6984     * vCC (r1).  Useful for integer division and modulus.
6985     *
6986     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6987     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6988     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6989     */
6990    /* binop/lit8 vAA, vBB, #+CC */
6991    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6992    mov     r9, rINST, lsr #8           @ r9<- AA
6993    and     r2, r3, #255                @ r2<- BB
6994    GET_VREG(r0, r2)                    @ r0<- vBB
6995    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6996    .if 0
6997    @cmp     r1, #0                      @ is second operand zero?
6998    beq     common_errDivideByZero
6999    .endif
7000    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7001
7002                               @ optional op; may set condition codes
7003    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
7004    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7005    SET_VREG(r0, r9)               @ vAA<- r0
7006    GOTO_OPCODE(ip)                     @ jump to next instruction
7007    /* 10-12 instructions */
7008
7009
7010
7011/* ------------------------------ */
7012    .balign 64
7013.L_OP_OR_INT_LIT8: /* 0xde */
7014/* File: armv5te/OP_OR_INT_LIT8.S */
7015/* File: armv5te/binopLit8.S */
7016    /*
7017     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7018     * that specifies an instruction that performs "result = r0 op r1".
7019     * This could be an ARM instruction or a function call.  (If the result
7020     * comes back in a register other than r0, you can override "result".)
7021     *
7022     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7023     * vCC (r1).  Useful for integer division and modulus.
7024     *
7025     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7026     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7027     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7028     */
7029    /* binop/lit8 vAA, vBB, #+CC */
7030    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7031    mov     r9, rINST, lsr #8           @ r9<- AA
7032    and     r2, r3, #255                @ r2<- BB
7033    GET_VREG(r0, r2)                    @ r0<- vBB
7034    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7035    .if 0
7036    @cmp     r1, #0                      @ is second operand zero?
7037    beq     common_errDivideByZero
7038    .endif
7039    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7040
7041                               @ optional op; may set condition codes
7042    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
7043    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7044    SET_VREG(r0, r9)               @ vAA<- r0
7045    GOTO_OPCODE(ip)                     @ jump to next instruction
7046    /* 10-12 instructions */
7047
7048
7049
7050/* ------------------------------ */
7051    .balign 64
7052.L_OP_XOR_INT_LIT8: /* 0xdf */
7053/* File: armv5te/OP_XOR_INT_LIT8.S */
7054/* File: armv5te/binopLit8.S */
7055    /*
7056     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7057     * that specifies an instruction that performs "result = r0 op r1".
7058     * This could be an ARM instruction or a function call.  (If the result
7059     * comes back in a register other than r0, you can override "result".)
7060     *
7061     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7062     * vCC (r1).  Useful for integer division and modulus.
7063     *
7064     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7065     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7066     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7067     */
7068    /* binop/lit8 vAA, vBB, #+CC */
7069    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7070    mov     r9, rINST, lsr #8           @ r9<- AA
7071    and     r2, r3, #255                @ r2<- BB
7072    GET_VREG(r0, r2)                    @ r0<- vBB
7073    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7074    .if 0
7075    @cmp     r1, #0                      @ is second operand zero?
7076    beq     common_errDivideByZero
7077    .endif
7078    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7079
7080                               @ optional op; may set condition codes
7081    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
7082    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7083    SET_VREG(r0, r9)               @ vAA<- r0
7084    GOTO_OPCODE(ip)                     @ jump to next instruction
7085    /* 10-12 instructions */
7086
7087
7088
7089/* ------------------------------ */
7090    .balign 64
7091.L_OP_SHL_INT_LIT8: /* 0xe0 */
7092/* File: armv5te/OP_SHL_INT_LIT8.S */
7093/* File: armv5te/binopLit8.S */
7094    /*
7095     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7096     * that specifies an instruction that performs "result = r0 op r1".
7097     * This could be an ARM instruction or a function call.  (If the result
7098     * comes back in a register other than r0, you can override "result".)
7099     *
7100     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7101     * vCC (r1).  Useful for integer division and modulus.
7102     *
7103     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7104     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7105     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7106     */
7107    /* binop/lit8 vAA, vBB, #+CC */
7108    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7109    mov     r9, rINST, lsr #8           @ r9<- AA
7110    and     r2, r3, #255                @ r2<- BB
7111    GET_VREG(r0, r2)                    @ r0<- vBB
7112    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7113    .if 0
7114    @cmp     r1, #0                      @ is second operand zero?
7115    beq     common_errDivideByZero
7116    .endif
7117    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7118
7119    and     r1, r1, #31                           @ optional op; may set condition codes
7120    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
7121    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7122    SET_VREG(r0, r9)               @ vAA<- r0
7123    GOTO_OPCODE(ip)                     @ jump to next instruction
7124    /* 10-12 instructions */
7125
7126
7127
7128/* ------------------------------ */
7129    .balign 64
7130.L_OP_SHR_INT_LIT8: /* 0xe1 */
7131/* File: armv5te/OP_SHR_INT_LIT8.S */
7132/* File: armv5te/binopLit8.S */
7133    /*
7134     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7135     * that specifies an instruction that performs "result = r0 op r1".
7136     * This could be an ARM instruction or a function call.  (If the result
7137     * comes back in a register other than r0, you can override "result".)
7138     *
7139     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7140     * vCC (r1).  Useful for integer division and modulus.
7141     *
7142     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7143     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7144     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7145     */
7146    /* binop/lit8 vAA, vBB, #+CC */
7147    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7148    mov     r9, rINST, lsr #8           @ r9<- AA
7149    and     r2, r3, #255                @ r2<- BB
7150    GET_VREG(r0, r2)                    @ r0<- vBB
7151    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7152    .if 0
7153    @cmp     r1, #0                      @ is second operand zero?
7154    beq     common_errDivideByZero
7155    .endif
7156    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7157
7158    and     r1, r1, #31                           @ optional op; may set condition codes
7159    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
7160    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7161    SET_VREG(r0, r9)               @ vAA<- r0
7162    GOTO_OPCODE(ip)                     @ jump to next instruction
7163    /* 10-12 instructions */
7164
7165
7166
7167/* ------------------------------ */
7168    .balign 64
7169.L_OP_USHR_INT_LIT8: /* 0xe2 */
7170/* File: armv5te/OP_USHR_INT_LIT8.S */
7171/* File: armv5te/binopLit8.S */
7172    /*
7173     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7174     * that specifies an instruction that performs "result = r0 op r1".
7175     * This could be an ARM instruction or a function call.  (If the result
7176     * comes back in a register other than r0, you can override "result".)
7177     *
7178     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7179     * vCC (r1).  Useful for integer division and modulus.
7180     *
7181     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7182     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7183     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7184     */
7185    /* binop/lit8 vAA, vBB, #+CC */
7186    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7187    mov     r9, rINST, lsr #8           @ r9<- AA
7188    and     r2, r3, #255                @ r2<- BB
7189    GET_VREG(r0, r2)                    @ r0<- vBB
7190    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7191    .if 0
7192    @cmp     r1, #0                      @ is second operand zero?
7193    beq     common_errDivideByZero
7194    .endif
7195    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7196
7197    and     r1, r1, #31                           @ optional op; may set condition codes
7198    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
7199    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7200    SET_VREG(r0, r9)               @ vAA<- r0
7201    GOTO_OPCODE(ip)                     @ jump to next instruction
7202    /* 10-12 instructions */
7203
7204
7205
7206/* ------------------------------ */
7207    .balign 64
7208.L_OP_UNUSED_E3: /* 0xe3 */
7209/* File: armv5te/OP_UNUSED_E3.S */
7210/* File: armv5te/unused.S */
7211    bl      common_abort
7212
7213
7214
7215/* ------------------------------ */
7216    .balign 64
7217.L_OP_UNUSED_E4: /* 0xe4 */
7218/* File: armv5te/OP_UNUSED_E4.S */
7219/* File: armv5te/unused.S */
7220    bl      common_abort
7221
7222
7223
7224/* ------------------------------ */
7225    .balign 64
7226.L_OP_UNUSED_E5: /* 0xe5 */
7227/* File: armv5te/OP_UNUSED_E5.S */
7228/* File: armv5te/unused.S */
7229    bl      common_abort
7230
7231
7232
7233/* ------------------------------ */
7234    .balign 64
7235.L_OP_UNUSED_E6: /* 0xe6 */
7236/* File: armv5te/OP_UNUSED_E6.S */
7237/* File: armv5te/unused.S */
7238    bl      common_abort
7239
7240
7241
7242/* ------------------------------ */
7243    .balign 64
7244.L_OP_UNUSED_E7: /* 0xe7 */
7245/* File: armv5te/OP_UNUSED_E7.S */
7246/* File: armv5te/unused.S */
7247    bl      common_abort
7248
7249
7250
7251/* ------------------------------ */
7252    .balign 64
7253.L_OP_UNUSED_E8: /* 0xe8 */
7254/* File: armv5te/OP_UNUSED_E8.S */
7255/* File: armv5te/unused.S */
7256    bl      common_abort
7257
7258
7259
7260/* ------------------------------ */
7261    .balign 64
7262.L_OP_UNUSED_E9: /* 0xe9 */
7263/* File: armv5te/OP_UNUSED_E9.S */
7264/* File: armv5te/unused.S */
7265    bl      common_abort
7266
7267
7268
7269/* ------------------------------ */
7270    .balign 64
7271.L_OP_UNUSED_EA: /* 0xea */
7272/* File: armv5te/OP_UNUSED_EA.S */
7273/* File: armv5te/unused.S */
7274    bl      common_abort
7275
7276
7277
7278/* ------------------------------ */
7279    .balign 64
7280.L_OP_UNUSED_EB: /* 0xeb */
7281/* File: armv5te/OP_UNUSED_EB.S */
7282/* File: armv5te/unused.S */
7283    bl      common_abort
7284
7285
7286
7287/* ------------------------------ */
7288    .balign 64
7289.L_OP_BREAKPOINT: /* 0xec */
7290/* File: armv5te/OP_BREAKPOINT.S */
7291/* File: armv5te/unused.S */
7292    bl      common_abort
7293
7294
7295
7296/* ------------------------------ */
7297    .balign 64
7298.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
7299/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
7300    /*
7301     * Handle a throw-verification-error instruction.  This throws an
7302     * exception for an error discovered during verification.  The
7303     * exception is indicated by AA, with some detail provided by BBBB.
7304     */
7305    /* op AA, ref@BBBB */
7306    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7307    FETCH(r2, 1)                        @ r2<- BBBB
7308    EXPORT_PC()                         @ export the PC
7309    mov     r1, rINST, lsr #8           @ r1<- AA
7310    bl      dvmThrowVerificationError   @ always throws
7311    b       common_exceptionThrown      @ handle exception
7312
7313
7314/* ------------------------------ */
7315    .balign 64
7316.L_OP_EXECUTE_INLINE: /* 0xee */
7317/* File: armv5te/OP_EXECUTE_INLINE.S */
7318    /*
7319     * Execute a "native inline" instruction.
7320     *
7321     * We need to call an InlineOp4Func:
7322     *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7323     *
7324     * The first four args are in r0-r3, pointer to return value storage
7325     * is on the stack.  The function's return value is a flag that tells
7326     * us if an exception was thrown.
7327     */
7328    /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
7329    FETCH(r10, 1)                       @ r10<- BBBB
7330    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7331    EXPORT_PC()                         @ can throw
7332    sub     sp, sp, #8                  @ make room for arg, +64 bit align
7333    mov     r0, rINST, lsr #12          @ r0<- B
7334    str     r1, [sp]                    @ push &glue->retval
7335    bl      .LOP_EXECUTE_INLINE_continue        @ make call; will return after
7336    add     sp, sp, #8                  @ pop stack
7337    cmp     r0, #0                      @ test boolean result of inline
7338    beq     common_exceptionThrown      @ returned false, handle exception
7339    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7340    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7341    GOTO_OPCODE(ip)                     @ jump to next instruction
7342
7343/* ------------------------------ */
7344    .balign 64
7345.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */
7346/* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */
7347    /*
7348     * Execute a "native inline" instruction, using "/range" semantics.
7349     * Same idea as execute-inline, but we get the args differently.
7350     *
7351     * We need to call an InlineOp4Func:
7352     *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7353     *
7354     * The first four args are in r0-r3, pointer to return value storage
7355     * is on the stack.  The function's return value is a flag that tells
7356     * us if an exception was thrown.
7357     */
7358    /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */
7359    FETCH(r10, 1)                       @ r10<- BBBB
7360    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7361    EXPORT_PC()                         @ can throw
7362    sub     sp, sp, #8                  @ make room for arg, +64 bit align
7363    mov     r0, rINST, lsr #8           @ r0<- AA
7364    str     r1, [sp]                    @ push &glue->retval
7365    bl      .LOP_EXECUTE_INLINE_RANGE_continue        @ make call; will return after
7366    add     sp, sp, #8                  @ pop stack
7367    cmp     r0, #0                      @ test boolean result of inline
7368    beq     common_exceptionThrown      @ returned false, handle exception
7369    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7370    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7371    GOTO_OPCODE(ip)                     @ jump to next instruction
7372
7373/* ------------------------------ */
7374    .balign 64
7375.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
7376/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
7377    /*
7378     * invoke-direct-empty is a no-op in a "standard" interpreter.
7379     */
7380    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7381    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7382    GOTO_OPCODE(ip)                     @ execute it
7383
7384/* ------------------------------ */
7385    .balign 64
7386.L_OP_UNUSED_F1: /* 0xf1 */
7387/* File: armv5te/OP_UNUSED_F1.S */
7388/* File: armv5te/unused.S */
7389    bl      common_abort
7390
7391
7392
7393/* ------------------------------ */
7394    .balign 64
7395.L_OP_IGET_QUICK: /* 0xf2 */
7396/* File: armv5te/OP_IGET_QUICK.S */
7397    /* For: iget-quick, iget-object-quick */
7398    /* op vA, vB, offset@CCCC */
7399    mov     r2, rINST, lsr #12          @ r2<- B
7400    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7401    FETCH(r1, 1)                        @ r1<- field byte offset
7402    cmp     r3, #0                      @ check object for null
7403    mov     r2, rINST, lsr #8           @ r2<- A(+)
7404    beq     common_errNullObject        @ object was null
7405    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7406    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7407    and     r2, r2, #15
7408    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7409    SET_VREG(r0, r2)                    @ fp[A]<- r0
7410    GOTO_OPCODE(ip)                     @ jump to next instruction
7411
7412
7413/* ------------------------------ */
7414    .balign 64
7415.L_OP_IGET_WIDE_QUICK: /* 0xf3 */
7416/* File: armv5te/OP_IGET_WIDE_QUICK.S */
7417    /* iget-wide-quick vA, vB, offset@CCCC */
7418    mov     r2, rINST, lsr #12          @ r2<- B
7419    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7420    FETCH(r1, 1)                        @ r1<- field byte offset
7421    cmp     r3, #0                      @ check object for null
7422    mov     r2, rINST, lsr #8           @ r2<- A(+)
7423    beq     common_errNullObject        @ object was null
7424    ldrd    r0, [r3, r1]                @ r0<- obj.field (64 bits, aligned)
7425    and     r2, r2, #15
7426    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7427    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
7428    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7429    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
7430    GOTO_OPCODE(ip)                     @ jump to next instruction
7431
7432
7433/* ------------------------------ */
7434    .balign 64
7435.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
7436/* File: armv5te/OP_IGET_OBJECT_QUICK.S */
7437/* File: armv5te/OP_IGET_QUICK.S */
7438    /* For: iget-quick, iget-object-quick */
7439    /* op vA, vB, offset@CCCC */
7440    mov     r2, rINST, lsr #12          @ r2<- B
7441    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7442    FETCH(r1, 1)                        @ r1<- field byte offset
7443    cmp     r3, #0                      @ check object for null
7444    mov     r2, rINST, lsr #8           @ r2<- A(+)
7445    beq     common_errNullObject        @ object was null
7446    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7447    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7448    and     r2, r2, #15
7449    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7450    SET_VREG(r0, r2)                    @ fp[A]<- r0
7451    GOTO_OPCODE(ip)                     @ jump to next instruction
7452
7453
7454
7455/* ------------------------------ */
7456    .balign 64
7457.L_OP_IPUT_QUICK: /* 0xf5 */
7458/* File: armv5te/OP_IPUT_QUICK.S */
7459    /* For: iput-quick, iput-object-quick */
7460    /* op vA, vB, offset@CCCC */
7461    mov     r2, rINST, lsr #12          @ r2<- B
7462    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7463    FETCH(r1, 1)                        @ r1<- field byte offset
7464    cmp     r3, #0                      @ check object for null
7465    mov     r2, rINST, lsr #8           @ r2<- A(+)
7466    beq     common_errNullObject        @ object was null
7467    and     r2, r2, #15
7468    GET_VREG(r0, r2)                    @ r0<- fp[A]
7469    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7470    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7471    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7472    GOTO_OPCODE(ip)                     @ jump to next instruction
7473
7474
7475/* ------------------------------ */
7476    .balign 64
7477.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
7478/* File: armv5te/OP_IPUT_WIDE_QUICK.S */
7479    /* iput-wide-quick vA, vB, offset@CCCC */
7480    mov     r0, rINST, lsr #8           @ r0<- A(+)
7481    mov     r1, rINST, lsr #12          @ r1<- B
7482    and     r0, r0, #15
7483    GET_VREG(r2, r1)                    @ r2<- fp[B], the object pointer
7484    add     r3, rFP, r0, lsl #2         @ r3<- &fp[A]
7485    cmp     r2, #0                      @ check object for null
7486    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[A]
7487    beq     common_errNullObject        @ object was null
7488    FETCH(r3, 1)                        @ r3<- field byte offset
7489    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7490    strd    r0, [r2, r3]                @ obj.field (64 bits, aligned)<- r0/r1
7491    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7492    GOTO_OPCODE(ip)                     @ jump to next instruction
7493
7494
7495/* ------------------------------ */
7496    .balign 64
7497.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
7498/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
7499/* File: armv5te/OP_IPUT_QUICK.S */
7500    /* For: iput-quick, iput-object-quick */
7501    /* op vA, vB, offset@CCCC */
7502    mov     r2, rINST, lsr #12          @ r2<- B
7503    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7504    FETCH(r1, 1)                        @ r1<- field byte offset
7505    cmp     r3, #0                      @ check object for null
7506    mov     r2, rINST, lsr #8           @ r2<- A(+)
7507    beq     common_errNullObject        @ object was null
7508    and     r2, r2, #15
7509    GET_VREG(r0, r2)                    @ r0<- fp[A]
7510    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7511    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7512    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7513    GOTO_OPCODE(ip)                     @ jump to next instruction
7514
7515
7516
7517/* ------------------------------ */
7518    .balign 64
7519.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
7520/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7521    /*
7522     * Handle an optimized virtual method call.
7523     *
7524     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7525     */
7526    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7527    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7528    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7529    FETCH(r1, 1)                        @ r1<- BBBB
7530    .if     (!0)
7531    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7532    .endif
7533    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7534    cmp     r2, #0                      @ is "this" null?
7535    beq     common_errNullObject        @ null "this", throw exception
7536    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7537    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7538    EXPORT_PC()                         @ invoke must export
7539    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7540    bl      common_invokeMethodNoRange @ continue on
7541
7542/* ------------------------------ */
7543    .balign 64
7544.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
7545/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
7546/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7547    /*
7548     * Handle an optimized virtual method call.
7549     *
7550     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7551     */
7552    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7553    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7554    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7555    FETCH(r1, 1)                        @ r1<- BBBB
7556    .if     (!1)
7557    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7558    .endif
7559    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7560    cmp     r2, #0                      @ is "this" null?
7561    beq     common_errNullObject        @ null "this", throw exception
7562    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7563    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7564    EXPORT_PC()                         @ invoke must export
7565    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7566    bl      common_invokeMethodRange @ continue on
7567
7568
7569/* ------------------------------ */
7570    .balign 64
7571.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
7572/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7573    /*
7574     * Handle an optimized "super" method call.
7575     *
7576     * for: [opt] invoke-super-quick, invoke-super-quick/range
7577     */
7578    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7579    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7580    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7581    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7582    .if     (!0)
7583    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7584    .endif
7585    FETCH(r1, 1)                        @ r1<- BBBB
7586    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7587    EXPORT_PC()                         @ must export for invoke
7588    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7589    GET_VREG(r3, r10)                   @ r3<- "this"
7590    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7591    cmp     r3, #0                      @ null "this" ref?
7592    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7593    beq     common_errNullObject        @ "this" is null, throw exception
7594    bl      common_invokeMethodNoRange @ continue on
7595
7596
7597/* ------------------------------ */
7598    .balign 64
7599.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
7600/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
7601/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7602    /*
7603     * Handle an optimized "super" method call.
7604     *
7605     * for: [opt] invoke-super-quick, invoke-super-quick/range
7606     */
7607    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7608    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7609    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7610    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7611    .if     (!1)
7612    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7613    .endif
7614    FETCH(r1, 1)                        @ r1<- BBBB
7615    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7616    EXPORT_PC()                         @ must export for invoke
7617    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7618    GET_VREG(r3, r10)                   @ r3<- "this"
7619    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7620    cmp     r3, #0                      @ null "this" ref?
7621    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7622    beq     common_errNullObject        @ "this" is null, throw exception
7623    bl      common_invokeMethodRange @ continue on
7624
7625
7626
7627/* ------------------------------ */
7628    .balign 64
7629.L_OP_UNUSED_FC: /* 0xfc */
7630/* File: armv5te/OP_UNUSED_FC.S */
7631/* File: armv5te/unused.S */
7632    bl      common_abort
7633
7634
7635
7636/* ------------------------------ */
7637    .balign 64
7638.L_OP_UNUSED_FD: /* 0xfd */
7639/* File: armv5te/OP_UNUSED_FD.S */
7640/* File: armv5te/unused.S */
7641    bl      common_abort
7642
7643
7644
7645/* ------------------------------ */
7646    .balign 64
7647.L_OP_UNUSED_FE: /* 0xfe */
7648/* File: armv5te/OP_UNUSED_FE.S */
7649/* File: armv5te/unused.S */
7650    bl      common_abort
7651
7652
7653
7654/* ------------------------------ */
7655    .balign 64
7656.L_OP_UNUSED_FF: /* 0xff */
7657/* File: armv5te/OP_UNUSED_FF.S */
7658/* File: armv5te/unused.S */
7659    bl      common_abort
7660
7661
7662
7663
7664    .balign 64
7665    .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
7666    .global dvmAsmInstructionEnd
7667dvmAsmInstructionEnd:
7668
7669/*
7670 * ===========================================================================
7671 *  Sister implementations
7672 * ===========================================================================
7673 */
7674    .global dvmAsmSisterStart
7675    .type   dvmAsmSisterStart, %function
7676    .text
7677    .balign 4
7678dvmAsmSisterStart:
7679
7680/* continuation for OP_CONST_STRING */
7681
7682    /*
7683     * Continuation if the String has not yet been resolved.
7684     *  r1: BBBB (String ref)
7685     *  r9: target register
7686     */
7687.LOP_CONST_STRING_resolve:
7688    EXPORT_PC()
7689    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7690    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7691    bl      dvmResolveString            @ r0<- String reference
7692    cmp     r0, #0                      @ failed?
7693    beq     common_exceptionThrown      @ yup, handle the exception
7694    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7695    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7696    SET_VREG(r0, r9)                    @ vAA<- r0
7697    GOTO_OPCODE(ip)                     @ jump to next instruction
7698
7699
7700/* continuation for OP_CONST_STRING_JUMBO */
7701
7702    /*
7703     * Continuation if the String has not yet been resolved.
7704     *  r1: BBBBBBBB (String ref)
7705     *  r9: target register
7706     */
7707.LOP_CONST_STRING_JUMBO_resolve:
7708    EXPORT_PC()
7709    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7710    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7711    bl      dvmResolveString            @ r0<- String reference
7712    cmp     r0, #0                      @ failed?
7713    beq     common_exceptionThrown      @ yup, handle the exception
7714    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7715    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7716    SET_VREG(r0, r9)                    @ vAA<- r0
7717    GOTO_OPCODE(ip)                     @ jump to next instruction
7718
7719
7720/* continuation for OP_CONST_CLASS */
7721
7722    /*
7723     * Continuation if the Class has not yet been resolved.
7724     *  r1: BBBB (Class ref)
7725     *  r9: target register
7726     */
7727.LOP_CONST_CLASS_resolve:
7728    EXPORT_PC()
7729    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7730    mov     r2, #1                      @ r2<- true
7731    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7732    bl      dvmResolveClass             @ r0<- Class reference
7733    cmp     r0, #0                      @ failed?
7734    beq     common_exceptionThrown      @ yup, handle the exception
7735    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7736    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7737    SET_VREG(r0, r9)                    @ vAA<- r0
7738    GOTO_OPCODE(ip)                     @ jump to next instruction
7739
7740
7741/* continuation for OP_CHECK_CAST */
7742
7743    /*
7744     * Trivial test failed, need to perform full check.  This is common.
7745     *  r0 holds obj->clazz
7746     *  r1 holds class resolved from BBBB
7747     *  r9 holds object
7748     */
7749.LOP_CHECK_CAST_fullcheck:
7750    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7751    cmp     r0, #0                      @ failed?
7752    bne     .LOP_CHECK_CAST_okay            @ no, success
7753
7754    @ A cast has failed.  We need to throw a ClassCastException with the
7755    @ class of the object that failed to be cast.
7756    EXPORT_PC()                         @ about to throw
7757    ldr     r3, [r9, #offObject_clazz]  @ r3<- obj->clazz
7758    ldr     r0, .LstrClassCastExceptionPtr
7759    ldr     r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor
7760    bl      dvmThrowExceptionWithClassMessage
7761    b       common_exceptionThrown
7762
7763    /*
7764     * Resolution required.  This is the least-likely path.
7765     *
7766     *  r2 holds BBBB
7767     *  r9 holds object
7768     */
7769.LOP_CHECK_CAST_resolve:
7770    EXPORT_PC()                         @ resolve() could throw
7771    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7772    mov     r1, r2                      @ r1<- BBBB
7773    mov     r2, #0                      @ r2<- false
7774    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7775    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7776    cmp     r0, #0                      @ got null?
7777    beq     common_exceptionThrown      @ yes, handle exception
7778    mov     r1, r0                      @ r1<- class resolved from BBB
7779    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
7780    b       .LOP_CHECK_CAST_resolved        @ pick up where we left off
7781
7782.LstrClassCastExceptionPtr:
7783    .word   .LstrClassCastException
7784
7785
7786/* continuation for OP_INSTANCE_OF */
7787
7788    /*
7789     * Trivial test failed, need to perform full check.  This is common.
7790     *  r0 holds obj->clazz
7791     *  r1 holds class resolved from BBBB
7792     *  r9 holds A
7793     */
7794.LOP_INSTANCE_OF_fullcheck:
7795    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7796    @ fall through to OP_INSTANCE_OF_store
7797
7798    /*
7799     * r0 holds boolean result
7800     * r9 holds A
7801     */
7802.LOP_INSTANCE_OF_store:
7803    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7804    SET_VREG(r0, r9)                    @ vA<- r0
7805    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7806    GOTO_OPCODE(ip)                     @ jump to next instruction
7807
7808    /*
7809     * Trivial test succeeded, save and bail.
7810     *  r9 holds A
7811     */
7812.LOP_INSTANCE_OF_trivial:
7813    mov     r0, #1                      @ indicate success
7814    @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
7815    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7816    SET_VREG(r0, r9)                    @ vA<- r0
7817    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7818    GOTO_OPCODE(ip)                     @ jump to next instruction
7819
7820    /*
7821     * Resolution required.  This is the least-likely path.
7822     *
7823     *  r3 holds BBBB
7824     *  r9 holds A
7825     */
7826.LOP_INSTANCE_OF_resolve:
7827    EXPORT_PC()                         @ resolve() could throw
7828    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7829    mov     r1, r3                      @ r1<- BBBB
7830    mov     r2, #1                      @ r2<- true
7831    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7832    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7833    cmp     r0, #0                      @ got null?
7834    beq     common_exceptionThrown      @ yes, handle exception
7835    mov     r1, r0                      @ r1<- class resolved from BBB
7836    mov     r3, rINST, lsr #12          @ r3<- B
7837    GET_VREG(r0, r3)                    @ r0<- vB (object)
7838    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
7839    b       .LOP_INSTANCE_OF_resolved        @ pick up where we left off
7840
7841
7842/* continuation for OP_NEW_INSTANCE */
7843
7844    .balign 32                          @ minimize cache lines
7845.LOP_NEW_INSTANCE_finish: @ r0=new object
7846    mov     r3, rINST, lsr #8           @ r3<- AA
7847    cmp     r0, #0                      @ failed?
7848    beq     common_exceptionThrown      @ yes, handle the exception
7849    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7850    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7851    SET_VREG(r0, r3)                    @ vAA<- r0
7852    GOTO_OPCODE(ip)                     @ jump to next instruction
7853
7854    /*
7855     * Class initialization required.
7856     *
7857     *  r0 holds class object
7858     */
7859.LOP_NEW_INSTANCE_needinit:
7860    mov     r9, r0                      @ save r0
7861    bl      dvmInitClass                @ initialize class
7862    cmp     r0, #0                      @ check boolean result
7863    mov     r0, r9                      @ restore r0
7864    bne     .LOP_NEW_INSTANCE_initialized     @ success, continue
7865    b       common_exceptionThrown      @ failed, deal with init exception
7866
7867    /*
7868     * Resolution required.  This is the least-likely path.
7869     *
7870     *  r1 holds BBBB
7871     */
7872.LOP_NEW_INSTANCE_resolve:
7873    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7874    mov     r2, #0                      @ r2<- false
7875    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7876    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7877    cmp     r0, #0                      @ got null?
7878    bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
7879    b       common_exceptionThrown      @ yes, handle exception
7880
7881.LstrInstantiationErrorPtr:
7882    .word   .LstrInstantiationError
7883
7884
7885/* continuation for OP_NEW_ARRAY */
7886
7887
7888    /*
7889     * Resolve class.  (This is an uncommon case.)
7890     *
7891     *  r1 holds array length
7892     *  r2 holds class ref CCCC
7893     */
7894.LOP_NEW_ARRAY_resolve:
7895    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7896    mov     r9, r1                      @ r9<- length (save)
7897    mov     r1, r2                      @ r1<- CCCC
7898    mov     r2, #0                      @ r2<- false
7899    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7900    bl      dvmResolveClass             @ r0<- call(clazz, ref)
7901    cmp     r0, #0                      @ got null?
7902    mov     r1, r9                      @ r1<- length (restore)
7903    beq     common_exceptionThrown      @ yes, handle exception
7904    @ fall through to OP_NEW_ARRAY_finish
7905
7906    /*
7907     * Finish allocation.
7908     *
7909     *  r0 holds class
7910     *  r1 holds array length
7911     */
7912.LOP_NEW_ARRAY_finish:
7913    mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
7914    bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
7915    cmp     r0, #0                      @ failed?
7916    mov     r2, rINST, lsr #8           @ r2<- A+
7917    beq     common_exceptionThrown      @ yes, handle the exception
7918    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7919    and     r2, r2, #15                 @ r2<- A
7920    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7921    SET_VREG(r0, r2)                    @ vA<- r0
7922    GOTO_OPCODE(ip)                     @ jump to next instruction
7923
7924
7925/* continuation for OP_FILLED_NEW_ARRAY */
7926
7927    /*
7928     * On entry:
7929     *  r0 holds array class
7930     *  r10 holds AA or BA
7931     */
7932.LOP_FILLED_NEW_ARRAY_continue:
7933    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
7934    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
7935    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
7936    .if     0
7937    mov     r1, r10                     @ r1<- AA (length)
7938    .else
7939    mov     r1, r10, lsr #4             @ r1<- B (length)
7940    .endif
7941    cmp     r3, #'I'                    @ array of ints?
7942    cmpne   r3, #'L'                    @ array of objects?
7943    cmpne   r3, #'['                    @ array of arrays?
7944    mov     r9, r1                      @ save length in r9
7945    bne     .LOP_FILLED_NEW_ARRAY_notimpl         @ no, not handled yet
7946    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
7947    cmp     r0, #0                      @ null return?
7948    beq     common_exceptionThrown      @ alloc failed, handle exception
7949
7950    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
7951    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
7952    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
7953    subs    r9, r9, #1                  @ length--, check for neg
7954    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7955    bmi     2f                          @ was zero, bail
7956
7957    @ copy values from registers into the array
7958    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
7959    .if     0
7960    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
79611:  ldr     r3, [r2], #4                @ r3<- *r2++
7962    subs    r9, r9, #1                  @ count--
7963    str     r3, [r0], #4                @ *contents++ = vX
7964    bpl     1b
7965    @ continue at 2
7966    .else
7967    cmp     r9, #4                      @ length was initially 5?
7968    and     r2, r10, #15                @ r2<- A
7969    bne     1f                          @ <= 4 args, branch
7970    GET_VREG(r3, r2)                    @ r3<- vA
7971    sub     r9, r9, #1                  @ count--
7972    str     r3, [r0, #16]               @ contents[4] = vA
79731:  and     r2, r1, #15                 @ r2<- F/E/D/C
7974    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
7975    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
7976    subs    r9, r9, #1                  @ count--
7977    str     r3, [r0], #4                @ *contents++ = vX
7978    bpl     1b
7979    @ continue at 2
7980    .endif
7981
79822:
7983    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7984    GOTO_OPCODE(ip)                     @ execute it
7985
7986    /*
7987     * Throw an exception indicating that we have not implemented this
7988     * mode of filled-new-array.
7989     */
7990.LOP_FILLED_NEW_ARRAY_notimpl:
7991    ldr     r0, .L_strInternalError
7992    ldr     r1, .L_strFilledNewArrayNotImpl
7993    bl      dvmThrowException
7994    b       common_exceptionThrown
7995
7996    .if     (!0)                 @ define in one or the other, not both
7997.L_strFilledNewArrayNotImpl:
7998    .word   .LstrFilledNewArrayNotImpl
7999.L_strInternalError:
8000    .word   .LstrInternalError
8001    .endif
8002
8003
8004/* continuation for OP_FILLED_NEW_ARRAY_RANGE */
8005
8006    /*
8007     * On entry:
8008     *  r0 holds array class
8009     *  r10 holds AA or BA
8010     */
8011.LOP_FILLED_NEW_ARRAY_RANGE_continue:
8012    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8013    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8014    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
8015    .if     1
8016    mov     r1, r10                     @ r1<- AA (length)
8017    .else
8018    mov     r1, r10, lsr #4             @ r1<- B (length)
8019    .endif
8020    cmp     r3, #'I'                    @ array of ints?
8021    cmpne   r3, #'L'                    @ array of objects?
8022    cmpne   r3, #'['                    @ array of arrays?
8023    mov     r9, r1                      @ save length in r9
8024    bne     .LOP_FILLED_NEW_ARRAY_RANGE_notimpl         @ no, not handled yet
8025    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8026    cmp     r0, #0                      @ null return?
8027    beq     common_exceptionThrown      @ alloc failed, handle exception
8028
8029    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8030    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
8031    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8032    subs    r9, r9, #1                  @ length--, check for neg
8033    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8034    bmi     2f                          @ was zero, bail
8035
8036    @ copy values from registers into the array
8037    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8038    .if     1
8039    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
80401:  ldr     r3, [r2], #4                @ r3<- *r2++
8041    subs    r9, r9, #1                  @ count--
8042    str     r3, [r0], #4                @ *contents++ = vX
8043    bpl     1b
8044    @ continue at 2
8045    .else
8046    cmp     r9, #4                      @ length was initially 5?
8047    and     r2, r10, #15                @ r2<- A
8048    bne     1f                          @ <= 4 args, branch
8049    GET_VREG(r3, r2)                    @ r3<- vA
8050    sub     r9, r9, #1                  @ count--
8051    str     r3, [r0, #16]               @ contents[4] = vA
80521:  and     r2, r1, #15                 @ r2<- F/E/D/C
8053    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8054    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8055    subs    r9, r9, #1                  @ count--
8056    str     r3, [r0], #4                @ *contents++ = vX
8057    bpl     1b
8058    @ continue at 2
8059    .endif
8060
80612:
8062    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
8063    GOTO_OPCODE(ip)                     @ execute it
8064
8065    /*
8066     * Throw an exception indicating that we have not implemented this
8067     * mode of filled-new-array.
8068     */
8069.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
8070    ldr     r0, .L_strInternalError
8071    ldr     r1, .L_strFilledNewArrayNotImpl
8072    bl      dvmThrowException
8073    b       common_exceptionThrown
8074
8075    .if     (!1)                 @ define in one or the other, not both
8076.L_strFilledNewArrayNotImpl:
8077    .word   .LstrFilledNewArrayNotImpl
8078.L_strInternalError:
8079    .word   .LstrInternalError
8080    .endif
8081
8082
8083/* continuation for OP_CMPL_FLOAT */
8084.LOP_CMPL_FLOAT_finish:
8085    SET_VREG(r0, r9)                    @ vAA<- r0
8086    GOTO_OPCODE(ip)                     @ jump to next instruction
8087
8088
8089/* continuation for OP_CMPG_FLOAT */
8090.LOP_CMPG_FLOAT_finish:
8091    SET_VREG(r0, r9)                    @ vAA<- r0
8092    GOTO_OPCODE(ip)                     @ jump to next instruction
8093
8094
8095/* continuation for OP_CMPL_DOUBLE */
8096.LOP_CMPL_DOUBLE_finish:
8097    SET_VREG(r0, r9)                    @ vAA<- r0
8098    GOTO_OPCODE(ip)                     @ jump to next instruction
8099
8100
8101/* continuation for OP_CMPG_DOUBLE */
8102.LOP_CMPG_DOUBLE_finish:
8103    SET_VREG(r0, r9)                    @ vAA<- r0
8104    GOTO_OPCODE(ip)                     @ jump to next instruction
8105
8106
8107/* continuation for OP_CMP_LONG */
8108
8109.LOP_CMP_LONG_less:
8110    mvn     r1, #0                      @ r1<- -1
8111    @ Want to cond code the next mov so we can avoid branch, but don't see it;
8112    @ instead, we just replicate the tail end.
8113    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8114    SET_VREG(r1, r9)                    @ vAA<- r1
8115    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8116    GOTO_OPCODE(ip)                     @ jump to next instruction
8117
8118.LOP_CMP_LONG_greater:
8119    mov     r1, #1                      @ r1<- 1
8120    @ fall through to _finish
8121
8122.LOP_CMP_LONG_finish:
8123    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8124    SET_VREG(r1, r9)                    @ vAA<- r1
8125    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8126    GOTO_OPCODE(ip)                     @ jump to next instruction
8127
8128
8129/* continuation for OP_AGET_WIDE */
8130
8131.LOP_AGET_WIDE_finish:
8132    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8133    ldrd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8134    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
8135    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8136    stmia   r9, {r2-r3}                 @ vAA/vAA+1<- r2/r3
8137    GOTO_OPCODE(ip)                     @ jump to next instruction
8138
8139
8140/* continuation for OP_APUT_WIDE */
8141
8142.LOP_APUT_WIDE_finish:
8143    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8144    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
8145    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8146    strd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8147    GOTO_OPCODE(ip)                     @ jump to next instruction
8148
8149
8150/* continuation for OP_APUT_OBJECT */
8151    /*
8152     * On entry:
8153     *  r1 = vBB (arrayObj)
8154     *  r9 = vAA (obj)
8155     *  r10 = offset into array (vBB + vCC * width)
8156     */
8157.LOP_APUT_OBJECT_finish:
8158    cmp     r9, #0                      @ storing null reference?
8159    beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
8160    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
8161    ldr     r1, [r1, #offObject_clazz]  @ r1<- arrayObj->clazz
8162    bl      dvmCanPutArrayElement       @ test object type vs. array type
8163    cmp     r0, #0                      @ okay?
8164    beq     common_errArrayStore        @ no
8165.LOP_APUT_OBJECT_skip_check:
8166    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8167    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8168    str     r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
8169    GOTO_OPCODE(ip)                     @ jump to next instruction
8170
8171
8172/* continuation for OP_IGET */
8173
8174    /*
8175     * Currently:
8176     *  r0 holds resolved field
8177     *  r9 holds object
8178     */
8179.LOP_IGET_finish:
8180    @bl      common_squeak0
8181    cmp     r9, #0                      @ check object for null
8182    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8183    beq     common_errNullObject        @ object was null
8184    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8185    mov     r2, rINST, lsr #8           @ r2<- A+
8186    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8187    and     r2, r2, #15                 @ r2<- A
8188    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8189    SET_VREG(r0, r2)                    @ fp[A]<- r0
8190    GOTO_OPCODE(ip)                     @ jump to next instruction
8191
8192
8193/* continuation for OP_IGET_WIDE */
8194
8195    /*
8196     * Currently:
8197     *  r0 holds resolved field
8198     *  r9 holds object
8199     */
8200.LOP_IGET_WIDE_finish:
8201    cmp     r9, #0                      @ check object for null
8202    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8203    beq     common_errNullObject        @ object was null
8204    mov     r2, rINST, lsr #8           @ r2<- A+
8205    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
8206    and     r2, r2, #15                 @ r2<- A
8207    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8208    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
8209    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8210    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
8211    GOTO_OPCODE(ip)                     @ jump to next instruction
8212
8213
8214/* continuation for OP_IGET_OBJECT */
8215
8216    /*
8217     * Currently:
8218     *  r0 holds resolved field
8219     *  r9 holds object
8220     */
8221.LOP_IGET_OBJECT_finish:
8222    @bl      common_squeak0
8223    cmp     r9, #0                      @ check object for null
8224    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8225    beq     common_errNullObject        @ object was null
8226    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8227    mov     r2, rINST, lsr #8           @ r2<- A+
8228    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8229    and     r2, r2, #15                 @ r2<- A
8230    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8231    SET_VREG(r0, r2)                    @ fp[A]<- r0
8232    GOTO_OPCODE(ip)                     @ jump to next instruction
8233
8234
8235/* continuation for OP_IGET_BOOLEAN */
8236
8237    /*
8238     * Currently:
8239     *  r0 holds resolved field
8240     *  r9 holds object
8241     */
8242.LOP_IGET_BOOLEAN_finish:
8243    @bl      common_squeak1
8244    cmp     r9, #0                      @ check object for null
8245    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8246    beq     common_errNullObject        @ object was null
8247    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8248    mov     r2, rINST, lsr #8           @ r2<- A+
8249    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8250    and     r2, r2, #15                 @ r2<- A
8251    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8252    SET_VREG(r0, r2)                    @ fp[A]<- r0
8253    GOTO_OPCODE(ip)                     @ jump to next instruction
8254
8255
8256/* continuation for OP_IGET_BYTE */
8257
8258    /*
8259     * Currently:
8260     *  r0 holds resolved field
8261     *  r9 holds object
8262     */
8263.LOP_IGET_BYTE_finish:
8264    @bl      common_squeak2
8265    cmp     r9, #0                      @ check object for null
8266    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8267    beq     common_errNullObject        @ object was null
8268    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8269    mov     r2, rINST, lsr #8           @ r2<- A+
8270    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8271    and     r2, r2, #15                 @ r2<- A
8272    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8273    SET_VREG(r0, r2)                    @ fp[A]<- r0
8274    GOTO_OPCODE(ip)                     @ jump to next instruction
8275
8276
8277/* continuation for OP_IGET_CHAR */
8278
8279    /*
8280     * Currently:
8281     *  r0 holds resolved field
8282     *  r9 holds object
8283     */
8284.LOP_IGET_CHAR_finish:
8285    @bl      common_squeak3
8286    cmp     r9, #0                      @ check object for null
8287    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8288    beq     common_errNullObject        @ object was null
8289    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8290    mov     r2, rINST, lsr #8           @ r2<- A+
8291    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8292    and     r2, r2, #15                 @ r2<- A
8293    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8294    SET_VREG(r0, r2)                    @ fp[A]<- r0
8295    GOTO_OPCODE(ip)                     @ jump to next instruction
8296
8297
8298/* continuation for OP_IGET_SHORT */
8299
8300    /*
8301     * Currently:
8302     *  r0 holds resolved field
8303     *  r9 holds object
8304     */
8305.LOP_IGET_SHORT_finish:
8306    @bl      common_squeak4
8307    cmp     r9, #0                      @ check object for null
8308    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8309    beq     common_errNullObject        @ object was null
8310    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8311    mov     r2, rINST, lsr #8           @ r2<- A+
8312    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8313    and     r2, r2, #15                 @ r2<- A
8314    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8315    SET_VREG(r0, r2)                    @ fp[A]<- r0
8316    GOTO_OPCODE(ip)                     @ jump to next instruction
8317
8318
8319/* continuation for OP_IPUT */
8320
8321    /*
8322     * Currently:
8323     *  r0 holds resolved field
8324     *  r9 holds object
8325     */
8326.LOP_IPUT_finish:
8327    @bl      common_squeak0
8328    mov     r1, rINST, lsr #8           @ r1<- A+
8329    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8330    and     r1, r1, #15                 @ r1<- A
8331    cmp     r9, #0                      @ check object for null
8332    GET_VREG(r0, r1)                    @ r0<- fp[A]
8333    beq     common_errNullObject        @ object was null
8334    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8335    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8336    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8337    GOTO_OPCODE(ip)                     @ jump to next instruction
8338
8339
8340/* continuation for OP_IPUT_WIDE */
8341
8342    /*
8343     * Currently:
8344     *  r0 holds resolved field
8345     *  r9 holds object
8346     */
8347.LOP_IPUT_WIDE_finish:
8348    mov     r2, rINST, lsr #8           @ r2<- A+
8349    cmp     r9, #0                      @ check object for null
8350    and     r2, r2, #15                 @ r2<- A
8351    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8352    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
8353    beq     common_errNullObject        @ object was null
8354    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8355    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
8356    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8357    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0
8358    GOTO_OPCODE(ip)                     @ jump to next instruction
8359
8360
8361/* continuation for OP_IPUT_OBJECT */
8362
8363    /*
8364     * Currently:
8365     *  r0 holds resolved field
8366     *  r9 holds object
8367     */
8368.LOP_IPUT_OBJECT_finish:
8369    @bl      common_squeak0
8370    mov     r1, rINST, lsr #8           @ r1<- A+
8371    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8372    and     r1, r1, #15                 @ r1<- A
8373    cmp     r9, #0                      @ check object for null
8374    GET_VREG(r0, r1)                    @ r0<- fp[A]
8375    beq     common_errNullObject        @ object was null
8376    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8377    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8378    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8379    GOTO_OPCODE(ip)                     @ jump to next instruction
8380
8381
8382/* continuation for OP_IPUT_BOOLEAN */
8383
8384    /*
8385     * Currently:
8386     *  r0 holds resolved field
8387     *  r9 holds object
8388     */
8389.LOP_IPUT_BOOLEAN_finish:
8390    @bl      common_squeak1
8391    mov     r1, rINST, lsr #8           @ r1<- A+
8392    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8393    and     r1, r1, #15                 @ r1<- A
8394    cmp     r9, #0                      @ check object for null
8395    GET_VREG(r0, r1)                    @ r0<- fp[A]
8396    beq     common_errNullObject        @ object was null
8397    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8398    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8399    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8400    GOTO_OPCODE(ip)                     @ jump to next instruction
8401
8402
8403/* continuation for OP_IPUT_BYTE */
8404
8405    /*
8406     * Currently:
8407     *  r0 holds resolved field
8408     *  r9 holds object
8409     */
8410.LOP_IPUT_BYTE_finish:
8411    @bl      common_squeak2
8412    mov     r1, rINST, lsr #8           @ r1<- A+
8413    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8414    and     r1, r1, #15                 @ r1<- A
8415    cmp     r9, #0                      @ check object for null
8416    GET_VREG(r0, r1)                    @ r0<- fp[A]
8417    beq     common_errNullObject        @ object was null
8418    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8419    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8420    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8421    GOTO_OPCODE(ip)                     @ jump to next instruction
8422
8423
8424/* continuation for OP_IPUT_CHAR */
8425
8426    /*
8427     * Currently:
8428     *  r0 holds resolved field
8429     *  r9 holds object
8430     */
8431.LOP_IPUT_CHAR_finish:
8432    @bl      common_squeak3
8433    mov     r1, rINST, lsr #8           @ r1<- A+
8434    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8435    and     r1, r1, #15                 @ r1<- A
8436    cmp     r9, #0                      @ check object for null
8437    GET_VREG(r0, r1)                    @ r0<- fp[A]
8438    beq     common_errNullObject        @ object was null
8439    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8440    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8441    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8442    GOTO_OPCODE(ip)                     @ jump to next instruction
8443
8444
8445/* continuation for OP_IPUT_SHORT */
8446
8447    /*
8448     * Currently:
8449     *  r0 holds resolved field
8450     *  r9 holds object
8451     */
8452.LOP_IPUT_SHORT_finish:
8453    @bl      common_squeak4
8454    mov     r1, rINST, lsr #8           @ r1<- A+
8455    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8456    and     r1, r1, #15                 @ r1<- A
8457    cmp     r9, #0                      @ check object for null
8458    GET_VREG(r0, r1)                    @ r0<- fp[A]
8459    beq     common_errNullObject        @ object was null
8460    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8461    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8462    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8463    GOTO_OPCODE(ip)                     @ jump to next instruction
8464
8465
8466/* continuation for OP_SGET */
8467
8468    /*
8469     * Continuation if the field has not yet been resolved.
8470     *  r1: BBBB field ref
8471     */
8472.LOP_SGET_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_finish          @ yes, finish
8479    b       common_exceptionThrown      @ no, handle exception
8480
8481
8482/* continuation for OP_SGET_WIDE */
8483
8484    /*
8485     * Continuation if the field has not yet been resolved.
8486     *  r1: BBBB field ref
8487     */
8488.LOP_SGET_WIDE_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_WIDE_finish          @ yes, finish
8495    b       common_exceptionThrown      @ no, handle exception
8496
8497
8498/* continuation for OP_SGET_OBJECT */
8499
8500    /*
8501     * Continuation if the field has not yet been resolved.
8502     *  r1: BBBB field ref
8503     */
8504.LOP_SGET_OBJECT_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_OBJECT_finish          @ yes, finish
8511    b       common_exceptionThrown      @ no, handle exception
8512
8513
8514/* continuation for OP_SGET_BOOLEAN */
8515
8516    /*
8517     * Continuation if the field has not yet been resolved.
8518     *  r1: BBBB field ref
8519     */
8520.LOP_SGET_BOOLEAN_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_SGET_BOOLEAN_finish          @ yes, finish
8527    b       common_exceptionThrown      @ no, handle exception
8528
8529
8530/* continuation for OP_SGET_BYTE */
8531
8532    /*
8533     * Continuation if the field has not yet been resolved.
8534     *  r1: BBBB field ref
8535     */
8536.LOP_SGET_BYTE_resolve:
8537    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8538    EXPORT_PC()                         @ resolve() could throw, so export now
8539    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8540    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8541    cmp     r0, #0                      @ success?
8542    bne     .LOP_SGET_BYTE_finish          @ yes, finish
8543    b       common_exceptionThrown      @ no, handle exception
8544
8545
8546/* continuation for OP_SGET_CHAR */
8547
8548    /*
8549     * Continuation if the field has not yet been resolved.
8550     *  r1: BBBB field ref
8551     */
8552.LOP_SGET_CHAR_resolve:
8553    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8554    EXPORT_PC()                         @ resolve() could throw, so export now
8555    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8556    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8557    cmp     r0, #0                      @ success?
8558    bne     .LOP_SGET_CHAR_finish          @ yes, finish
8559    b       common_exceptionThrown      @ no, handle exception
8560
8561
8562/* continuation for OP_SGET_SHORT */
8563
8564    /*
8565     * Continuation if the field has not yet been resolved.
8566     *  r1: BBBB field ref
8567     */
8568.LOP_SGET_SHORT_resolve:
8569    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8570    EXPORT_PC()                         @ resolve() could throw, so export now
8571    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8572    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8573    cmp     r0, #0                      @ success?
8574    bne     .LOP_SGET_SHORT_finish          @ yes, finish
8575    b       common_exceptionThrown      @ no, handle exception
8576
8577
8578/* continuation for OP_SPUT */
8579
8580    /*
8581     * Continuation if the field has not yet been resolved.
8582     *  r1: BBBB field ref
8583     */
8584.LOP_SPUT_resolve:
8585    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8586    EXPORT_PC()                         @ resolve() could throw, so export now
8587    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8588    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8589    cmp     r0, #0                      @ success?
8590    bne     .LOP_SPUT_finish          @ yes, finish
8591    b       common_exceptionThrown      @ no, handle exception
8592
8593
8594/* continuation for OP_SPUT_WIDE */
8595
8596    /*
8597     * Continuation if the field has not yet been resolved.
8598     *  r1: BBBB field ref
8599     *  r9: &fp[AA]
8600     */
8601.LOP_SPUT_WIDE_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_WIDE_finish          @ yes, finish
8608    b       common_exceptionThrown      @ no, handle exception
8609
8610
8611/* continuation for OP_SPUT_OBJECT */
8612
8613    /*
8614     * Continuation if the field has not yet been resolved.
8615     *  r1: BBBB field ref
8616     */
8617.LOP_SPUT_OBJECT_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_OBJECT_finish          @ yes, finish
8624    b       common_exceptionThrown      @ no, handle exception
8625
8626
8627/* continuation for OP_SPUT_BOOLEAN */
8628
8629    /*
8630     * Continuation if the field has not yet been resolved.
8631     *  r1: BBBB field ref
8632     */
8633.LOP_SPUT_BOOLEAN_resolve:
8634    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8635    EXPORT_PC()                         @ resolve() could throw, so export now
8636    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8637    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8638    cmp     r0, #0                      @ success?
8639    bne     .LOP_SPUT_BOOLEAN_finish          @ yes, finish
8640    b       common_exceptionThrown      @ no, handle exception
8641
8642
8643/* continuation for OP_SPUT_BYTE */
8644
8645    /*
8646     * Continuation if the field has not yet been resolved.
8647     *  r1: BBBB field ref
8648     */
8649.LOP_SPUT_BYTE_resolve:
8650    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8651    EXPORT_PC()                         @ resolve() could throw, so export now
8652    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8653    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8654    cmp     r0, #0                      @ success?
8655    bne     .LOP_SPUT_BYTE_finish          @ yes, finish
8656    b       common_exceptionThrown      @ no, handle exception
8657
8658
8659/* continuation for OP_SPUT_CHAR */
8660
8661    /*
8662     * Continuation if the field has not yet been resolved.
8663     *  r1: BBBB field ref
8664     */
8665.LOP_SPUT_CHAR_resolve:
8666    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8667    EXPORT_PC()                         @ resolve() could throw, so export now
8668    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8669    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8670    cmp     r0, #0                      @ success?
8671    bne     .LOP_SPUT_CHAR_finish          @ yes, finish
8672    b       common_exceptionThrown      @ no, handle exception
8673
8674
8675/* continuation for OP_SPUT_SHORT */
8676
8677    /*
8678     * Continuation if the field has not yet been resolved.
8679     *  r1: BBBB field ref
8680     */
8681.LOP_SPUT_SHORT_resolve:
8682    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8683    EXPORT_PC()                         @ resolve() could throw, so export now
8684    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8685    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8686    cmp     r0, #0                      @ success?
8687    bne     .LOP_SPUT_SHORT_finish          @ yes, finish
8688    b       common_exceptionThrown      @ no, handle exception
8689
8690
8691/* continuation for OP_INVOKE_VIRTUAL */
8692
8693    /*
8694     * At this point:
8695     *  r0 = resolved base method
8696     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8697     */
8698.LOP_INVOKE_VIRTUAL_continue:
8699    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8700    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8701    cmp     r1, #0                      @ is "this" null?
8702    beq     common_errNullObject        @ null "this", throw exception
8703    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8704    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8705    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8706    bl      common_invokeMethodNoRange @ continue on
8707
8708
8709/* continuation for OP_INVOKE_SUPER */
8710
8711    /*
8712     * At this point:
8713     *  r0 = resolved base method
8714     *  r9 = method->clazz
8715     */
8716.LOP_INVOKE_SUPER_continue:
8717    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8718    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8719    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8720    EXPORT_PC()                         @ must export for invoke
8721    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8722    bcs     .LOP_INVOKE_SUPER_nsm             @ method not present in superclass
8723    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8724    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8725    bl      common_invokeMethodNoRange @ continue on
8726
8727.LOP_INVOKE_SUPER_resolve:
8728    mov     r0, r9                      @ r0<- method->clazz
8729    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8730    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8731    cmp     r0, #0                      @ got null?
8732    bne     .LOP_INVOKE_SUPER_continue        @ no, continue
8733    b       common_exceptionThrown      @ yes, handle exception
8734
8735    /*
8736     * Throw a NoSuchMethodError with the method name as the message.
8737     *  r0 = resolved base method
8738     */
8739.LOP_INVOKE_SUPER_nsm:
8740    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8741    b       common_errNoSuchMethod
8742
8743
8744/* continuation for OP_INVOKE_DIRECT */
8745
8746    /*
8747     * On entry:
8748     *  r1 = reference (BBBB or CCCC)
8749     *  r10 = "this" register
8750     */
8751.LOP_INVOKE_DIRECT_resolve:
8752    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8753    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8754    mov     r2, #METHOD_DIRECT          @ resolver method type
8755    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8756    cmp     r0, #0                      @ got null?
8757    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8758    bne     .LOP_INVOKE_DIRECT_finish          @ no, continue
8759    b       common_exceptionThrown      @ yes, handle exception
8760
8761
8762/* continuation for OP_INVOKE_VIRTUAL_RANGE */
8763
8764    /*
8765     * At this point:
8766     *  r0 = resolved base method
8767     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8768     */
8769.LOP_INVOKE_VIRTUAL_RANGE_continue:
8770    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8771    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8772    cmp     r1, #0                      @ is "this" null?
8773    beq     common_errNullObject        @ null "this", throw exception
8774    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8775    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8776    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8777    bl      common_invokeMethodRange @ continue on
8778
8779
8780/* continuation for OP_INVOKE_SUPER_RANGE */
8781
8782    /*
8783     * At this point:
8784     *  r0 = resolved base method
8785     *  r9 = method->clazz
8786     */
8787.LOP_INVOKE_SUPER_RANGE_continue:
8788    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8789    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8790    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8791    EXPORT_PC()                         @ must export for invoke
8792    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8793    bcs     .LOP_INVOKE_SUPER_RANGE_nsm             @ method not present in superclass
8794    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8795    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8796    bl      common_invokeMethodRange @ continue on
8797
8798.LOP_INVOKE_SUPER_RANGE_resolve:
8799    mov     r0, r9                      @ r0<- method->clazz
8800    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8801    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8802    cmp     r0, #0                      @ got null?
8803    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ no, continue
8804    b       common_exceptionThrown      @ yes, handle exception
8805
8806    /*
8807     * Throw a NoSuchMethodError with the method name as the message.
8808     *  r0 = resolved base method
8809     */
8810.LOP_INVOKE_SUPER_RANGE_nsm:
8811    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8812    b       common_errNoSuchMethod
8813
8814
8815/* continuation for OP_INVOKE_DIRECT_RANGE */
8816
8817    /*
8818     * On entry:
8819     *  r1 = reference (BBBB or CCCC)
8820     *  r10 = "this" register
8821     */
8822.LOP_INVOKE_DIRECT_RANGE_resolve:
8823    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8824    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8825    mov     r2, #METHOD_DIRECT          @ resolver method type
8826    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8827    cmp     r0, #0                      @ got null?
8828    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8829    bne     .LOP_INVOKE_DIRECT_RANGE_finish          @ no, continue
8830    b       common_exceptionThrown      @ yes, handle exception
8831
8832
8833/* continuation for OP_FLOAT_TO_LONG */
8834/*
8835 * Convert the float in r0 to a long in r0/r1.
8836 *
8837 * We have to clip values to long min/max per the specification.  The
8838 * expected common case is a "reasonable" value that converts directly
8839 * to modest integer.  The EABI convert function isn't doing this for us.
8840 */
8841f2l_doconv:
8842    stmfd   sp!, {r4, lr}
8843    mov     r1, #0x5f000000             @ (float)maxlong
8844    mov     r4, r0
8845    bl      __aeabi_fcmpge              @ is arg >= maxlong?
8846    cmp     r0, #0                      @ nonzero == yes
8847    mvnne   r0, #0                      @ return maxlong (7fffffff)
8848    mvnne   r1, #0x80000000
8849    ldmnefd sp!, {r4, pc}
8850
8851    mov     r0, r4                      @ recover arg
8852    mov     r1, #0xdf000000             @ (float)minlong
8853    bl      __aeabi_fcmple              @ is arg <= minlong?
8854    cmp     r0, #0                      @ nonzero == yes
8855    movne   r0, #0                      @ return minlong (80000000)
8856    movne   r1, #0x80000000
8857    ldmnefd sp!, {r4, pc}
8858
8859    mov     r0, r4                      @ recover arg
8860    mov     r1, r4
8861    bl      __aeabi_fcmpeq              @ is arg == self?
8862    cmp     r0, #0                      @ zero == no
8863    moveq   r1, #0                      @ return zero for NaN
8864    ldmeqfd sp!, {r4, pc}
8865
8866    mov     r0, r4                      @ recover arg
8867    bl      __aeabi_f2lz                @ convert float to long
8868    ldmfd   sp!, {r4, pc}
8869
8870
8871/* continuation for OP_DOUBLE_TO_LONG */
8872/*
8873 * Convert the double in r0/r1 to a long in r0/r1.
8874 *
8875 * We have to clip values to long min/max per the specification.  The
8876 * expected common case is a "reasonable" value that converts directly
8877 * to modest integer.  The EABI convert function isn't doing this for us.
8878 */
8879d2l_doconv:
8880    stmfd   sp!, {r4, r5, lr}           @ save regs
8881    mov     r3, #0x43000000             @ maxlong, as a double (high word)
8882    add     r3, #0x00e00000             @  0x43e00000
8883    mov     r2, #0                      @ maxlong, as a double (low word)
8884    sub     sp, sp, #4                  @ align for EABI
8885    mov     r4, r0                      @ save a copy of r0
8886    mov     r5, r1                      @  and r1
8887    bl      __aeabi_dcmpge              @ is arg >= maxlong?
8888    cmp     r0, #0                      @ nonzero == yes
8889    mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
8890    mvnne   r1, #0x80000000
8891    bne     1f
8892
8893    mov     r0, r4                      @ recover arg
8894    mov     r1, r5
8895    mov     r3, #0xc3000000             @ minlong, as a double (high word)
8896    add     r3, #0x00e00000             @  0xc3e00000
8897    mov     r2, #0                      @ minlong, as a double (low word)
8898    bl      __aeabi_dcmple              @ is arg <= minlong?
8899    cmp     r0, #0                      @ nonzero == yes
8900    movne   r0, #0                      @ return minlong (8000000000000000)
8901    movne   r1, #0x80000000
8902    bne     1f
8903
8904    mov     r0, r4                      @ recover arg
8905    mov     r1, r5
8906    mov     r2, r4                      @ compare against self
8907    mov     r3, r5
8908    bl      __aeabi_dcmpeq              @ is arg == self?
8909    cmp     r0, #0                      @ zero == no
8910    moveq   r1, #0                      @ return zero for NaN
8911    beq     1f
8912
8913    mov     r0, r4                      @ recover arg
8914    mov     r1, r5
8915    bl      __aeabi_d2lz                @ convert double to long
8916
89171:
8918    add     sp, sp, #4
8919    ldmfd   sp!, {r4, r5, pc}
8920
8921
8922/* continuation for OP_MUL_LONG */
8923
8924.LOP_MUL_LONG_finish:
8925    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8926    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
8927    GOTO_OPCODE(ip)                     @ jump to next instruction
8928
8929
8930/* continuation for OP_SHL_LONG */
8931
8932.LOP_SHL_LONG_finish:
8933    mov     r0, r0, asl r2              @  r0<- r0 << r2
8934    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8935    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8936    GOTO_OPCODE(ip)                     @ jump to next instruction
8937
8938
8939/* continuation for OP_SHR_LONG */
8940
8941.LOP_SHR_LONG_finish:
8942    mov     r1, r1, asr r2              @  r1<- r1 >> r2
8943    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8944    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8945    GOTO_OPCODE(ip)                     @ jump to next instruction
8946
8947
8948/* continuation for OP_USHR_LONG */
8949
8950.LOP_USHR_LONG_finish:
8951    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
8952    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8953    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8954    GOTO_OPCODE(ip)                     @ jump to next instruction
8955
8956
8957/* continuation for OP_SHL_LONG_2ADDR */
8958
8959.LOP_SHL_LONG_2ADDR_finish:
8960    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8961    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8962    GOTO_OPCODE(ip)                     @ jump to next instruction
8963
8964
8965/* continuation for OP_SHR_LONG_2ADDR */
8966
8967.LOP_SHR_LONG_2ADDR_finish:
8968    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8969    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8970    GOTO_OPCODE(ip)                     @ jump to next instruction
8971
8972
8973/* continuation for OP_USHR_LONG_2ADDR */
8974
8975.LOP_USHR_LONG_2ADDR_finish:
8976    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8977    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8978    GOTO_OPCODE(ip)                     @ jump to next instruction
8979
8980
8981/* continuation for OP_EXECUTE_INLINE */
8982
8983    /*
8984     * Extract args, call function.
8985     *  r0 = #of args (0-4)
8986     *  r10 = call index
8987     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
8988     *
8989     * Other ideas:
8990     * - Use a jump table from the main piece to jump directly into the
8991     *   AND/LDR pairs.  Costs a data load, saves a branch.
8992     * - Have five separate pieces that do the loading, so we can work the
8993     *   interleave a little better.  Increases code size.
8994     */
8995.LOP_EXECUTE_INLINE_continue:
8996    rsb     r0, r0, #4                  @ r0<- 4-r0
8997    FETCH(r9, 2)                        @ r9<- FEDC
8998    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
8999    bl      common_abort                @ (skipped due to ARM prefetch)
90004:  and     ip, r9, #0xf000             @ isolate F
9001    ldr     r3, [rFP, ip, lsr #10]      @ r3<- vF (shift right 12, left 2)
90023:  and     ip, r9, #0x0f00             @ isolate E
9003    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vE
90042:  and     ip, r9, #0x00f0             @ isolate D
9005    ldr     r1, [rFP, ip, lsr #2]       @ r1<- vD
90061:  and     ip, r9, #0x000f             @ isolate C
9007    ldr     r0, [rFP, ip, lsl #2]       @ r0<- vC
90080:
9009    ldr     r9, .LOP_EXECUTE_INLINE_table       @ table of InlineOperation
9010    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
9011    @ (not reached)
9012
9013.LOP_EXECUTE_INLINE_table:
9014    .word   gDvmInlineOpsTable
9015
9016
9017/* continuation for OP_EXECUTE_INLINE_RANGE */
9018
9019    /*
9020     * Extract args, call function.
9021     *  r0 = #of args (0-4)
9022     *  r10 = call index
9023     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
9024     */
9025.LOP_EXECUTE_INLINE_RANGE_continue:
9026    rsb     r0, r0, #4                  @ r0<- 4-r0
9027    FETCH(r9, 2)                        @ r9<- CCCC
9028    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
9029    bl      common_abort                @ (skipped due to ARM prefetch)
90304:  add     ip, r9, #3                  @ base+3
9031    GET_VREG(r3, ip)                    @ r3<- vBase[3]
90323:  add     ip, r9, #2                  @ base+2
9033    GET_VREG(r2, ip)                    @ r2<- vBase[2]
90342:  add     ip, r9, #1                  @ base+1
9035    GET_VREG(r1, ip)                    @ r1<- vBase[1]
90361:  add     ip, r9, #0                  @ (nop)
9037    GET_VREG(r0, ip)                    @ r0<- vBase[0]
90380:
9039    ldr     r9, .LOP_EXECUTE_INLINE_RANGE_table       @ table of InlineOperation
9040    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
9041    @ (not reached)
9042
9043.LOP_EXECUTE_INLINE_RANGE_table:
9044    .word   gDvmInlineOpsTable
9045
9046
9047    .size   dvmAsmSisterStart, .-dvmAsmSisterStart
9048    .global dvmAsmSisterEnd
9049dvmAsmSisterEnd:
9050
9051/* File: armv5te/footer.S */
9052
9053/*
9054 * ===========================================================================
9055 *  Common subroutines and data
9056 * ===========================================================================
9057 */
9058
9059
9060
9061    .text
9062    .align  2
9063
9064#if defined(WITH_JIT)
9065#if defined(WITH_SELF_VERIFICATION)
9066    .global dvmJitToInterpPunt
9067dvmJitToInterpPunt:
9068    mov    r2,#kSVSPunt                 @ r2<- interpreter entry point
9069    b      dvmJitSelfVerificationEnd    @ doesn't return
9070
9071    .global dvmJitToInterpSingleStep
9072dvmJitToInterpSingleStep:
9073    mov    r2,#kSVSSingleStep           @ r2<- interpreter entry point
9074    b      dvmJitSelfVerificationEnd    @ doesn't return
9075
9076    .global dvmJitToTraceSelect
9077dvmJitToTraceSelect:
9078    ldr    r0,[lr, #-1]                 @ pass our target PC
9079    mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
9080    b      dvmJitSelfVerificationEnd    @ doesn't return
9081
9082    .global dvmJitToBackwardBranch
9083dvmJitToBackwardBranch:
9084    ldr    r0,[lr, #-1]                 @ pass our target PC
9085    mov    r2,#kSVSBackwardBranch       @ r2<- interpreter entry point
9086    b      dvmJitSelfVerificationEnd    @ doesn't return
9087
9088    .global dvmJitToInterpNormal
9089dvmJitToInterpNormal:
9090    ldr    r0,[lr, #-1]                 @ pass our target PC
9091    mov    r2,#kSVSNormal               @ r2<- interpreter entry point
9092    b      dvmJitSelfVerificationEnd    @ doesn't return
9093
9094    .global dvmJitToInterpNoChain
9095dvmJitToInterpNoChain:
9096    mov    r0,rPC                       @ pass our target PC
9097    mov    r2,#kSVSNoChain              @ r2<- interpreter entry point
9098    b      dvmJitSelfVerificationEnd    @ doesn't return
9099#else
9100/*
9101 * Return from the translation cache to the interpreter when the compiler is
9102 * having issues translating/executing a Dalvik instruction. We have to skip
9103 * the code cache lookup otherwise it is possible to indefinitely bouce
9104 * between the interpreter and the code cache if the instruction that fails
9105 * to be compiled happens to be at a trace start.
9106 */
9107    .global dvmJitToInterpPunt
9108dvmJitToInterpPunt:
9109    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9110    mov    rPC, r0
9111#ifdef EXIT_STATS
9112    mov    r0,lr
9113    bl     dvmBumpPunt;
9114#endif
9115    EXPORT_PC()
9116    mov    r0, #0
9117    str    r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9118    adrl   rIBASE, dvmAsmInstructionStart
9119    FETCH_INST()
9120    GET_INST_OPCODE(ip)
9121    GOTO_OPCODE(ip)
9122
9123/*
9124 * Return to the interpreter to handle a single instruction.
9125 * On entry:
9126 *    r0 <= PC
9127 *    r1 <= PC of resume instruction
9128 *    lr <= resume point in translation
9129 */
9130    .global dvmJitToInterpSingleStep
9131dvmJitToInterpSingleStep:
9132    str    lr,[rGLUE,#offGlue_jitResume]
9133    str    r1,[rGLUE,#offGlue_jitResumePC]
9134    mov    r1,#kInterpEntryInstr
9135    @ enum is 4 byte in aapcs-EABI
9136    str    r1, [rGLUE, #offGlue_entryPoint]
9137    mov    rPC,r0
9138    EXPORT_PC()
9139
9140    adrl   rIBASE, dvmAsmInstructionStart
9141    mov    r2,#kJitSingleStep     @ Ask for single step and then revert
9142    str    r2,[rGLUE,#offGlue_jitState]
9143    mov    r1,#1                  @ set changeInterp to bail to debug interp
9144    b      common_gotoBail
9145
9146
9147/*
9148 * Return from the translation cache and immediately request
9149 * a translation for the exit target.  Commonly used following
9150 * invokes.
9151 */
9152    .global dvmJitToTraceSelect
9153dvmJitToTraceSelect:
9154    ldr    rPC,[lr, #-1]           @ get our target PC
9155    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9156    add    rINST,lr,#-5            @ save start of chain branch
9157    mov    r0,rPC
9158    bl     dvmJitGetCodeAddr       @ Is there a translation?
9159    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9160    cmp    r0,#0
9161    beq    2f
9162    mov    r1,rINST
9163    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9164    mov    r1, rPC                  @ arg1 of translation may need this
9165    mov    lr, #0                   @ in case target is HANDLER_INTERPRET
9166    cmp    r0,#0                    @ successful chain?
9167    bxne   r0                       @ continue native execution
9168    b      toInterpreter            @ didn't chain - resume with interpreter
9169
9170/* No translation, so request one if profiling isn't disabled*/
91712:
9172    adrl   rIBASE, dvmAsmInstructionStart
9173    GET_JIT_PROF_TABLE(r0)
9174    FETCH_INST()
9175    cmp    r0, #0
9176    bne    common_selectTrace
9177    GET_INST_OPCODE(ip)
9178    GOTO_OPCODE(ip)
9179
9180/*
9181 * Return from the translation cache to the interpreter.
9182 * The return was done with a BLX from thumb mode, and
9183 * the following 32-bit word contains the target rPC value.
9184 * Note that lr (r14) will have its low-order bit set to denote
9185 * its thumb-mode origin.
9186 *
9187 * We'll need to stash our lr origin away, recover the new
9188 * target and then check to see if there is a translation available
9189 * for our new target.  If so, we do a translation chain and
9190 * go back to native execution.  Otherwise, it's back to the
9191 * interpreter (after treating this entry as a potential
9192 * trace start).
9193 */
9194    .global dvmJitToInterpNormal
9195dvmJitToInterpNormal:
9196    ldr    rPC,[lr, #-1]           @ get our target PC
9197    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9198    add    rINST,lr,#-5            @ save start of chain branch
9199#ifdef EXIT_STATS
9200    bl     dvmBumpNormal
9201#endif
9202    mov    r0,rPC
9203    bl     dvmJitGetCodeAddr        @ Is there a translation?
9204    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9205    cmp    r0,#0
9206    beq    toInterpreter            @ go if not, otherwise do chain
9207    mov    r1,rINST
9208    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9209    mov    r1, rPC                  @ arg1 of translation may need this
9210    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9211    cmp    r0,#0                    @ successful chain?
9212    bxne   r0                       @ continue native execution
9213    b      toInterpreter            @ didn't chain - resume with interpreter
9214
9215/*
9216 * Return from the translation cache to the interpreter to do method invocation.
9217 * Check if translation exists for the callee, but don't chain to it.
9218 */
9219    .global dvmJitToInterpNoChain
9220dvmJitToInterpNoChain:
9221#ifdef EXIT_STATS
9222    bl     dvmBumpNoChain
9223#endif
9224    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9225    mov    r0,rPC
9226    bl     dvmJitGetCodeAddr        @ Is there a translation?
9227    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9228    mov    r1, rPC                  @ arg1 of translation may need this
9229    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9230    cmp    r0,#0
9231    bxne   r0                       @ continue native execution if so
9232#endif
9233
9234/*
9235 * No translation, restore interpreter regs and start interpreting.
9236 * rGLUE & rFP were preserved in the translated code, and rPC has
9237 * already been restored by the time we get here.  We'll need to set
9238 * up rIBASE & rINST, and load the address of the JitTable into r0.
9239 */
9240toInterpreter:
9241    EXPORT_PC()
9242    adrl   rIBASE, dvmAsmInstructionStart
9243    FETCH_INST()
9244    GET_JIT_PROF_TABLE(r0)
9245    @ NOTE: intended fallthrough
9246/*
9247 * Common code to update potential trace start counter, and initiate
9248 * a trace-build if appropriate.  On entry, rPC should point to the
9249 * next instruction to execute, and rINST should be already loaded with
9250 * the next opcode word, and r0 holds a pointer to the jit profile
9251 * table (pJitProfTable).
9252 */
9253common_testUpdateProfile:
9254    cmp     r0,#0
9255    GET_INST_OPCODE(ip)
9256    GOTO_OPCODE_IFEQ(ip)       @ if not profiling, fallthrough otherwise */
9257
9258common_updateProfile:
9259    eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
9260    lsl     r3,r3,#(32 - JIT_PROF_SIZE_LOG_2)          @ shift out excess bits
9261    ldrb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter
9262    GET_INST_OPCODE(ip)
9263    subs    r1,r1,#1           @ decrement counter
9264    strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it
9265    GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
9266
9267/*
9268 * Here, we switch to the debug interpreter to request
9269 * trace selection.  First, though, check to see if there
9270 * is already a native translation in place (and, if so,
9271 * jump to it now).
9272 */
9273    GET_JIT_THRESHOLD(r1)
9274    ldr     r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
9275    strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter
9276    EXPORT_PC()
9277    mov     r0,rPC
9278    bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
9279    str     r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9280    mov     r1, rPC                     @ arg1 of translation may need this
9281    mov     lr, #0                      @  in case target is HANDLER_INTERPRET
9282    cmp     r0,#0
9283#if !defined(WITH_SELF_VERIFICATION)
9284    bxne    r0                          @ jump to the translation
9285#else
9286    beq     common_selectTrace
9287    /*
9288     * At this point, we have a target translation.  However, if
9289     * that translation is actually the interpret-only pseudo-translation
9290     * we want to treat it the same as no translation.
9291     */
9292    mov     r10, r0                      @ save target
9293    bl      dvmCompilerGetInterpretTemplate
9294    cmp     r0, r10                      @ special case?
9295    bne     dvmJitSelfVerificationStart  @ set up self verification
9296    GET_INST_OPCODE(ip)
9297    GOTO_OPCODE(ip)
9298    /* no return */
9299#endif
9300
9301common_selectTrace:
9302    mov     r2,#kJitTSelectRequest      @ ask for trace selection
9303    str     r2,[rGLUE,#offGlue_jitState]
9304    mov     r2,#kInterpEntryInstr       @ normal entry reason
9305    str     r2,[rGLUE,#offGlue_entryPoint]
9306    mov     r1,#1                       @ set changeInterp
9307    b       common_gotoBail
9308
9309#if defined(WITH_SELF_VERIFICATION)
9310/*
9311 * Save PC and registers to shadow memory for self verification mode
9312 * before jumping to native translation.
9313 * On entry, r10 contains the address of the target translation.
9314 */
9315dvmJitSelfVerificationStart:
9316    mov     r0,rPC                      @ r0<- program counter
9317    mov     r1,rFP                      @ r1<- frame pointer
9318    mov     r2,rGLUE                    @ r2<- InterpState pointer
9319    mov     r3,r10                      @ r3<- target translation
9320    bl      dvmSelfVerificationSaveState @ save registers to shadow space
9321    ldr     rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
9322    add     rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
9323    bx      r10                         @ jump to the translation
9324
9325/*
9326 * Restore PC, registers, and interpState to original values
9327 * before jumping back to the interpreter.
9328 */
9329dvmJitSelfVerificationEnd:
9330    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9331    mov    r1, #0
9332    str    r1, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9333    mov    r1,rFP                        @ pass ending fp
9334    bl     dvmSelfVerificationRestoreState @ restore pc and fp values
9335    ldr    rPC,[r0,#offShadowSpace_startPC] @ restore PC
9336    ldr    rFP,[r0,#offShadowSpace_fp]   @ restore FP
9337    ldr    rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
9338    ldr    r1,[r0,#offShadowSpace_svState] @ get self verification state
9339    cmp    r1,#0                         @ check for punt condition
9340    beq    1f
9341    mov    r2,#kJitSelfVerification      @ ask for self verification
9342    str    r2,[rGLUE,#offGlue_jitState]
9343    mov    r2,#kInterpEntryInstr         @ normal entry reason
9344    str    r2,[rGLUE,#offGlue_entryPoint]
9345    mov    r1,#1                         @ set changeInterp
9346    b      common_gotoBail
9347
93481:                                       @ exit to interpreter without check
9349    EXPORT_PC()
9350    adrl   rIBASE, dvmAsmInstructionStart
9351    FETCH_INST()
9352    GET_INST_OPCODE(ip)
9353    GOTO_OPCODE(ip)
9354#endif
9355
9356#endif
9357
9358/*
9359 * Common code when a backward branch is taken.
9360 *
9361 * On entry:
9362 *  r9 is PC adjustment *in bytes*
9363 */
9364common_backwardBranch:
9365    mov     r0, #kInterpEntryInstr
9366    bl      common_periodicChecks
9367#if defined(WITH_JIT)
9368    GET_JIT_PROF_TABLE(r0)
9369    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9370    cmp     r0,#0
9371    bne     common_updateProfile
9372    GET_INST_OPCODE(ip)
9373    GOTO_OPCODE(ip)
9374#else
9375    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9376    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9377    GOTO_OPCODE(ip)                     @ jump to next instruction
9378#endif
9379
9380
9381/*
9382 * Need to see if the thread needs to be suspended or debugger/profiler
9383 * activity has begun.
9384 *
9385 * TODO: if JDWP isn't running, zero out pDebuggerActive pointer so we don't
9386 * have to do the second ldr.
9387 *
9388 * TODO: reduce this so we're just checking a single location.
9389 *
9390 * On entry:
9391 *  r0 is reentry type, e.g. kInterpEntryInstr
9392 *  r9 is trampoline PC adjustment *in bytes*
9393 */
9394common_periodicChecks:
9395    ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
9396
9397    @ speculatively store r0 before it is clobbered by dvmCheckSuspendPending
9398    str     r0, [rGLUE, #offGlue_entryPoint]
9399
9400#if defined(WITH_DEBUGGER)
9401    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9402#endif
9403#if defined(WITH_PROFILER)
9404    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9405#endif
9406
9407    ldr     r3, [r3]                    @ r3<- suspendCount (int)
9408
9409#if defined(WITH_DEBUGGER)
9410    ldrb    r1, [r1]                    @ r1<- debuggerActive (boolean)
9411#endif
9412#if defined (WITH_PROFILER)
9413    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9414#endif
9415
9416    cmp     r3, #0                      @ suspend pending?
9417    bne     2f                          @ yes, do full suspension check
9418
9419#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
9420# if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
9421    orrs    r1, r1, r2                  @ r1<- r1 | r2
9422    cmp     r1, #0                      @ debugger attached or profiler started?
9423# elif defined(WITH_DEBUGGER)
9424    cmp     r1, #0                      @ debugger attached?
9425# elif defined(WITH_PROFILER)
9426    cmp     r2, #0                      @ profiler started?
9427# endif
9428    bne     3f                          @ debugger/profiler, switch interp
9429#endif
9430
9431    bx      lr                          @ nothing to do, return
9432
94332:  @ check suspend
9434#if defined(WITH_JIT)
9435    /*
9436     * Refresh the Jit's cached copy of profile table pointer.  This pointer
9437     * doubles as the Jit's on/off switch.
9438     */
9439    ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ r10<-&gDvmJit.pJitProfTable
9440    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9441    ldr     r3, [r3] @ r10 <- pJitProfTable
9442    EXPORT_PC()                         @ need for precise GC
9443    str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch
9444#else
9445    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9446    EXPORT_PC()                         @ need for precise GC
9447#endif
9448    b       dvmCheckSuspendPending      @ suspend if necessary, then return
9449
94503:  @ debugger/profiler enabled, bail out
9451    add     rPC, rPC, r9                @ update rPC
9452    mov     r1, #1                      @ "want switch" = true
9453    b       common_gotoBail
9454
9455
9456/*
9457 * The equivalent of "goto bail", this calls through the "bail handler".
9458 *
9459 * State registers will be saved to the "glue" area before bailing.
9460 *
9461 * On entry:
9462 *  r1 is "bool changeInterp", indicating if we want to switch to the
9463 *     other interpreter or just bail all the way out
9464 */
9465common_gotoBail:
9466    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9467    mov     r0, rGLUE                   @ r0<- glue ptr
9468    b       dvmMterpStdBail             @ call(glue, changeInterp)
9469
9470    @add     r1, r1, #1                  @ using (boolean+1)
9471    @add     r0, rGLUE, #offGlue_jmpBuf  @ r0<- &glue->jmpBuf
9472    @bl      _longjmp                    @ does not return
9473    @bl      common_abort
9474
9475
9476/*
9477 * Common code for method invocation with range.
9478 *
9479 * On entry:
9480 *  r0 is "Method* methodToCall", the method we're trying to call
9481 */
9482common_invokeMethodRange:
9483.LinvokeNewRange:
9484    @ prepare to copy args to "outs" area of current frame
9485    movs    r2, rINST, lsr #8           @ r2<- AA (arg count) -- test for zero
9486    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9487    beq     .LinvokeArgsDone            @ if no args, skip the rest
9488    FETCH(r1, 2)                        @ r1<- CCCC
9489
9490    @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
9491    @ (very few methods have > 10 args; could unroll for common cases)
9492    add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
9493    sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
9494    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
94951:  ldr     r1, [r3], #4                @ val = *fp++
9496    subs    r2, r2, #1                  @ count--
9497    str     r1, [r10], #4               @ *outs++ = val
9498    bne     1b                          @ ...while count != 0
9499    ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
9500    b       .LinvokeArgsDone
9501
9502/*
9503 * Common code for method invocation without range.
9504 *
9505 * On entry:
9506 *  r0 is "Method* methodToCall", the method we're trying to call
9507 */
9508common_invokeMethodNoRange:
9509.LinvokeNewNoRange:
9510    @ prepare to copy args to "outs" area of current frame
9511    movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
9512    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9513    FETCH(r1, 2)                        @ r1<- GFED (load here to hide latency)
9514    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
9515    ldrh    r3, [r0, #offMethod_outsSize]  @ r3<- methodToCall->outsSize
9516    beq     .LinvokeArgsDone
9517
9518    @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
9519.LinvokeNonRange:
9520    rsb     r2, r2, #5                  @ r2<- 5-r2
9521    add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
9522    bl      common_abort                @ (skipped due to ARM prefetch)
95235:  and     ip, rINST, #0x0f00          @ isolate A
9524    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vA (shift right 8, left 2)
9525    mov     r0, r0                      @ nop
9526    str     r2, [r10, #-4]!             @ *--outs = vA
95274:  and     ip, r1, #0xf000             @ isolate G
9528    ldr     r2, [rFP, ip, lsr #10]      @ r2<- vG (shift right 12, left 2)
9529    mov     r0, r0                      @ nop
9530    str     r2, [r10, #-4]!             @ *--outs = vG
95313:  and     ip, r1, #0x0f00             @ isolate F
9532    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vF
9533    mov     r0, r0                      @ nop
9534    str     r2, [r10, #-4]!             @ *--outs = vF
95352:  and     ip, r1, #0x00f0             @ isolate E
9536    ldr     r2, [rFP, ip, lsr #2]       @ r2<- vE
9537    mov     r0, r0                      @ nop
9538    str     r2, [r10, #-4]!             @ *--outs = vE
95391:  and     ip, r1, #0x000f             @ isolate D
9540    ldr     r2, [rFP, ip, lsl #2]       @ r2<- vD
9541    mov     r0, r0                      @ nop
9542    str     r2, [r10, #-4]!             @ *--outs = vD
95430:  @ fall through to .LinvokeArgsDone
9544
9545.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
9546    ldr     r2, [r0, #offMethod_insns]  @ r2<- method->insns
9547    ldr     rINST, [r0, #offMethod_clazz]  @ rINST<- method->clazz
9548    @ find space for the new stack frame, check for overflow
9549    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
9550    sub     r1, r1, r9, lsl #2          @ r1<- newFp (old savearea - regsSize)
9551    SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
9552@    bl      common_dumpRegs
9553    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
9554    sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
9555    cmp     r3, r9                      @ bottom < interpStackEnd?
9556    ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
9557    blt     .LstackOverflow             @ yes, this frame will overflow stack
9558
9559    @ set up newSaveArea
9560#ifdef EASY_GDB
9561    SAVEAREA_FROM_FP(ip, rFP)           @ ip<- stack save area
9562    str     ip, [r10, #offStackSaveArea_prevSave]
9563#endif
9564    str     rFP, [r10, #offStackSaveArea_prevFrame]
9565    str     rPC, [r10, #offStackSaveArea_savedPc]
9566#if defined(WITH_JIT)
9567    mov     r9, #0
9568    str     r9, [r10, #offStackSaveArea_returnAddr]
9569#endif
9570    str     r0, [r10, #offStackSaveArea_method]
9571    tst     r3, #ACC_NATIVE
9572    bne     .LinvokeNative
9573
9574    /*
9575    stmfd   sp!, {r0-r3}
9576    bl      common_printNewline
9577    mov     r0, rFP
9578    mov     r1, #0
9579    bl      dvmDumpFp
9580    ldmfd   sp!, {r0-r3}
9581    stmfd   sp!, {r0-r3}
9582    mov     r0, r1
9583    mov     r1, r10
9584    bl      dvmDumpFp
9585    bl      common_printNewline
9586    ldmfd   sp!, {r0-r3}
9587    */
9588
9589    ldrh    r9, [r2]                        @ r9 <- load INST from new PC
9590    ldr     r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
9591    mov     rPC, r2                         @ publish new rPC
9592    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
9593
9594    @ Update "glue" values for the new method
9595    @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
9596    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
9597    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
9598#if defined(WITH_JIT)
9599    GET_JIT_PROF_TABLE(r0)
9600    mov     rFP, r1                         @ fp = newFp
9601    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
9602    mov     rINST, r9                       @ publish new rINST
9603    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
9604    cmp     r0,#0
9605    bne     common_updateProfile
9606    GOTO_OPCODE(ip)                         @ jump to next instruction
9607#else
9608    mov     rFP, r1                         @ fp = newFp
9609    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
9610    mov     rINST, r9                       @ publish new rINST
9611    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
9612    GOTO_OPCODE(ip)                         @ jump to next instruction
9613#endif
9614
9615.LinvokeNative:
9616    @ Prep for the native call
9617    @ r0=methodToCall, r1=newFp, r10=newSaveArea
9618    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
9619    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
9620    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
9621    str     r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
9622    mov     r9, r3                      @ r9<- glue->self (preserve)
9623
9624    mov     r2, r0                      @ r2<- methodToCall
9625    mov     r0, r1                      @ r0<- newFp (points to args)
9626    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
9627
9628#ifdef ASSIST_DEBUGGER
9629    /* insert fake function header to help gdb find the stack frame */
9630    b       .Lskip
9631    .type   dalvik_mterp, %function
9632dalvik_mterp:
9633    .fnstart
9634    MTERP_ENTRY1
9635    MTERP_ENTRY2
9636.Lskip:
9637#endif
9638
9639    @mov     lr, pc                      @ set return addr
9640    @ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
9641    LDR_PC_LR "[r2, #offMethod_nativeFunc]"
9642
9643#if defined(WITH_JIT)
9644    ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status
9645#endif
9646
9647    @ native return; r9=self, r10=newSaveArea
9648    @ equivalent to dvmPopJniLocals
9649    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
9650    ldr     r1, [r9, #offThread_exception] @ check for exception
9651#if defined(WITH_JIT)
9652    ldr     r3, [r3]                    @ r3 <- gDvmJit.pProfTable
9653#endif
9654    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
9655    cmp     r1, #0                      @ null?
9656    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
9657#if defined(WITH_JIT)
9658    str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch
9659#endif
9660    bne     common_exceptionThrown      @ no, handle exception
9661
9662    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
9663    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9664    GOTO_OPCODE(ip)                     @ jump to next instruction
9665
9666.LstackOverflow:    @ r0=methodToCall
9667    mov     r1, r0                      @ r1<- methodToCall
9668    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
9669    bl      dvmHandleStackOverflow
9670    b       common_exceptionThrown
9671#ifdef ASSIST_DEBUGGER
9672    .fnend
9673#endif
9674
9675
9676    /*
9677     * Common code for method invocation, calling through "glue code".
9678     *
9679     * TODO: now that we have range and non-range invoke handlers, this
9680     *       needs to be split into two.  Maybe just create entry points
9681     *       that set r9 and jump here?
9682     *
9683     * On entry:
9684     *  r0 is "Method* methodToCall", the method we're trying to call
9685     *  r9 is "bool methodCallRange", indicating if this is a /range variant
9686     */
9687     .if    0
9688.LinvokeOld:
9689    sub     sp, sp, #8                  @ space for args + pad
9690    FETCH(ip, 2)                        @ ip<- FEDC or CCCC
9691    mov     r2, r0                      @ A2<- methodToCall
9692    mov     r0, rGLUE                   @ A0<- glue
9693    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9694    mov     r1, r9                      @ A1<- methodCallRange
9695    mov     r3, rINST, lsr #8           @ A3<- AA
9696    str     ip, [sp, #0]                @ A4<- ip
9697    bl      dvmMterp_invokeMethod       @ call the C invokeMethod
9698    add     sp, sp, #8                  @ remove arg area
9699    b       common_resumeAfterGlueCall  @ continue to next instruction
9700    .endif
9701
9702
9703
9704/*
9705 * Common code for handling a return instruction.
9706 *
9707 * This does not return.
9708 */
9709common_returnFromMethod:
9710.LreturnNew:
9711    mov     r0, #kInterpEntryReturn
9712    mov     r9, #0
9713    bl      common_periodicChecks
9714
9715    SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
9716    ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
9717    ldr     r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
9718    ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
9719                                        @ r2<- method we're returning to
9720    ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
9721    cmp     r2, #0                      @ is this a break frame?
9722    ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
9723    mov     r1, #0                      @ "want switch" = false
9724    beq     common_gotoBail             @ break frame, bail out completely
9725
9726    PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
9727    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
9728    ldr     r1, [r10, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
9729    str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
9730#if defined(WITH_JIT)
9731    ldr     r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr
9732    GET_JIT_PROF_TABLE(r0)
9733    mov     rPC, r9                     @ publish new rPC
9734    str     r1, [rGLUE, #offGlue_methodClassDex]
9735    str     r10, [r3, #offThread_inJitCodeCache]  @ may return to JIT'ed land
9736    cmp     r10, #0                      @ caller is compiled code
9737    blxne   r10
9738    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9739    cmp     r0,#0
9740    bne     common_updateProfile
9741    GOTO_OPCODE(ip)                     @ jump to next instruction
9742#else
9743    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9744    mov     rPC, r9                     @ publish new rPC
9745    str     r1, [rGLUE, #offGlue_methodClassDex]
9746    GOTO_OPCODE(ip)                     @ jump to next instruction
9747#endif
9748
9749    /*
9750     * Return handling, calls through "glue code".
9751     */
9752     .if    0
9753.LreturnOld:
9754    SAVE_PC_FP_TO_GLUE()                @ export state
9755    mov     r0, rGLUE                   @ arg to function
9756    bl      dvmMterp_returnFromMethod
9757    b       common_resumeAfterGlueCall
9758    .endif
9759
9760
9761/*
9762 * Somebody has thrown an exception.  Handle it.
9763 *
9764 * If the exception processing code returns to us (instead of falling
9765 * out of the interpreter), continue with whatever the next instruction
9766 * now happens to be.
9767 *
9768 * This does not return.
9769 */
9770     .global dvmMterpCommonExceptionThrown
9771dvmMterpCommonExceptionThrown:
9772common_exceptionThrown:
9773.LexceptionNew:
9774    mov     r0, #kInterpEntryThrow
9775    mov     r9, #0
9776    bl      common_periodicChecks
9777
9778#if defined(WITH_JIT)
9779    mov     r2,#kJitTSelectAbort        @ abandon trace selection in progress
9780    str     r2,[rGLUE,#offGlue_jitState]
9781#endif
9782
9783    ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
9784    ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
9785    mov     r1, r10                     @ r1<- self
9786    mov     r0, r9                      @ r0<- exception
9787    bl      dvmAddTrackedAlloc          @ don't let the exception be GCed
9788    mov     r3, #0                      @ r3<- NULL
9789    str     r3, [r10, #offThread_exception] @ self->exception = NULL
9790
9791    /* set up args and a local for "&fp" */
9792    /* (str sp, [sp, #-4]!  would be perfect here, but is discouraged) */
9793    str     rFP, [sp, #-4]!             @ *--sp = fp
9794    mov     ip, sp                      @ ip<- &fp
9795    mov     r3, #0                      @ r3<- false
9796    str     ip, [sp, #-4]!              @ *--sp = &fp
9797    ldr     r1, [rGLUE, #offGlue_method] @ r1<- glue->method
9798    mov     r0, r10                     @ r0<- self
9799    ldr     r1, [r1, #offMethod_insns]  @ r1<- method->insns
9800    mov     r2, r9                      @ r2<- exception
9801    sub     r1, rPC, r1                 @ r1<- pc - method->insns
9802    mov     r1, r1, asr #1              @ r1<- offset in code units
9803
9804    /* call, r0 gets catchRelPc (a code-unit offset) */
9805    bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
9806
9807    /* fix earlier stack overflow if necessary; may trash rFP */
9808    ldrb    r1, [r10, #offThread_stackOverflowed]
9809    cmp     r1, #0                      @ did we overflow earlier?
9810    beq     1f                          @ no, skip ahead
9811    mov     rFP, r0                     @ save relPc result in rFP
9812    mov     r0, r10                     @ r0<- self
9813    mov     r1, r9                      @ r1<- exception
9814    bl      dvmCleanupStackOverflow     @ call(self)
9815    mov     r0, rFP                     @ restore result
98161:
9817
9818    /* update frame pointer and check result from dvmFindCatchBlock */
9819    ldr     rFP, [sp, #4]               @ retrieve the updated rFP
9820    cmp     r0, #0                      @ is catchRelPc < 0?
9821    add     sp, sp, #8                  @ restore stack
9822    bmi     .LnotCaughtLocally
9823
9824    /* adjust locals to match self->curFrame and updated PC */
9825    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
9826    ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
9827    str     r1, [rGLUE, #offGlue_method]    @ glue->method = new method
9828    ldr     r2, [r1, #offMethod_clazz]      @ r2<- method->clazz
9829    ldr     r3, [r1, #offMethod_insns]      @ r3<- method->insns
9830    ldr     r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
9831    add     rPC, r3, r0, asl #1             @ rPC<- method->insns + catchRelPc
9832    str     r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
9833
9834    /* release the tracked alloc on the exception */
9835    mov     r0, r9                      @ r0<- exception
9836    mov     r1, r10                     @ r1<- self
9837    bl      dvmReleaseTrackedAlloc      @ release the exception
9838
9839    /* restore the exception if the handler wants it */
9840    FETCH_INST()                        @ load rINST from rPC
9841    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9842    cmp     ip, #OP_MOVE_EXCEPTION      @ is it "move-exception"?
9843    streq   r9, [r10, #offThread_exception] @ yes, restore the exception
9844    GOTO_OPCODE(ip)                     @ jump to next instruction
9845
9846.LnotCaughtLocally: @ r9=exception, r10=self
9847    /* fix stack overflow if necessary */
9848    ldrb    r1, [r10, #offThread_stackOverflowed]
9849    cmp     r1, #0                      @ did we overflow earlier?
9850    movne   r0, r10                     @ if yes: r0<- self
9851    movne   r1, r9                      @ if yes: r1<- exception
9852    blne    dvmCleanupStackOverflow     @ if yes: call(self)
9853
9854    @ may want to show "not caught locally" debug messages here
9855#if DVM_SHOW_EXCEPTION >= 2
9856    /* call __android_log_print(prio, tag, format, ...) */
9857    /* "Exception %s from %s:%d not caught locally" */
9858    @ dvmLineNumFromPC(method, pc - method->insns)
9859    ldr     r0, [rGLUE, #offGlue_method]
9860    ldr     r1, [r0, #offMethod_insns]
9861    sub     r1, rPC, r1
9862    asr     r1, r1, #1
9863    bl      dvmLineNumFromPC
9864    str     r0, [sp, #-4]!
9865    @ dvmGetMethodSourceFile(method)
9866    ldr     r0, [rGLUE, #offGlue_method]
9867    bl      dvmGetMethodSourceFile
9868    str     r0, [sp, #-4]!
9869    @ exception->clazz->descriptor
9870    ldr     r3, [r9, #offObject_clazz]
9871    ldr     r3, [r3, #offClassObject_descriptor]
9872    @
9873    ldr     r2, strExceptionNotCaughtLocally
9874    ldr     r1, strLogTag
9875    mov     r0, #3                      @ LOG_DEBUG
9876    bl      __android_log_print
9877#endif
9878    str     r9, [r10, #offThread_exception] @ restore exception
9879    mov     r0, r9                      @ r0<- exception
9880    mov     r1, r10                     @ r1<- self
9881    bl      dvmReleaseTrackedAlloc      @ release the exception
9882    mov     r1, #0                      @ "want switch" = false
9883    b       common_gotoBail             @ bail out
9884
9885
9886    /*
9887     * Exception handling, calls through "glue code".
9888     */
9889    .if     0
9890.LexceptionOld:
9891    SAVE_PC_FP_TO_GLUE()                @ export state
9892    mov     r0, rGLUE                   @ arg to function
9893    bl      dvmMterp_exceptionThrown
9894    b       common_resumeAfterGlueCall
9895    .endif
9896
9897
9898/*
9899 * After returning from a "glued" function, pull out the updated
9900 * values and start executing at the next instruction.
9901 */
9902common_resumeAfterGlueCall:
9903    LOAD_PC_FP_FROM_GLUE()              @ pull rPC and rFP out of glue
9904    FETCH_INST()                        @ load rINST from rPC
9905    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9906    GOTO_OPCODE(ip)                     @ jump to next instruction
9907
9908/*
9909 * Invalid array index.
9910 */
9911common_errArrayIndex:
9912    EXPORT_PC()
9913    ldr     r0, strArrayIndexException
9914    mov     r1, #0
9915    bl      dvmThrowException
9916    b       common_exceptionThrown
9917
9918/*
9919 * Invalid array value.
9920 */
9921common_errArrayStore:
9922    EXPORT_PC()
9923    ldr     r0, strArrayStoreException
9924    mov     r1, #0
9925    bl      dvmThrowException
9926    b       common_exceptionThrown
9927
9928/*
9929 * Integer divide or mod by zero.
9930 */
9931common_errDivideByZero:
9932    EXPORT_PC()
9933    ldr     r0, strArithmeticException
9934    ldr     r1, strDivideByZero
9935    bl      dvmThrowException
9936    b       common_exceptionThrown
9937
9938/*
9939 * Attempt to allocate an array with a negative size.
9940 */
9941common_errNegativeArraySize:
9942    EXPORT_PC()
9943    ldr     r0, strNegativeArraySizeException
9944    mov     r1, #0
9945    bl      dvmThrowException
9946    b       common_exceptionThrown
9947
9948/*
9949 * Invocation of a non-existent method.
9950 */
9951common_errNoSuchMethod:
9952    EXPORT_PC()
9953    ldr     r0, strNoSuchMethodError
9954    mov     r1, #0
9955    bl      dvmThrowException
9956    b       common_exceptionThrown
9957
9958/*
9959 * We encountered a null object when we weren't expecting one.  We
9960 * export the PC, throw a NullPointerException, and goto the exception
9961 * processing code.
9962 */
9963common_errNullObject:
9964    EXPORT_PC()
9965    ldr     r0, strNullPointerException
9966    mov     r1, #0
9967    bl      dvmThrowException
9968    b       common_exceptionThrown
9969
9970/*
9971 * For debugging, cause an immediate fault.  The source address will
9972 * be in lr (use a bl instruction to jump here).
9973 */
9974common_abort:
9975    ldr     pc, .LdeadFood
9976.LdeadFood:
9977    .word   0xdeadf00d
9978
9979/*
9980 * Spit out a "we were here", preserving all registers.  (The attempt
9981 * to save ip won't work, but we need to save an even number of
9982 * registers for EABI 64-bit stack alignment.)
9983 */
9984    .macro  SQUEAK num
9985common_squeak\num:
9986    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9987    ldr     r0, strSqueak
9988    mov     r1, #\num
9989    bl      printf
9990    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9991    bx      lr
9992    .endm
9993
9994    SQUEAK  0
9995    SQUEAK  1
9996    SQUEAK  2
9997    SQUEAK  3
9998    SQUEAK  4
9999    SQUEAK  5
10000
10001/*
10002 * Spit out the number in r0, preserving registers.
10003 */
10004common_printNum:
10005    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10006    mov     r1, r0
10007    ldr     r0, strSqueak
10008    bl      printf
10009    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10010    bx      lr
10011
10012/*
10013 * Print a newline, preserving registers.
10014 */
10015common_printNewline:
10016    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10017    ldr     r0, strNewline
10018    bl      printf
10019    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10020    bx      lr
10021
10022    /*
10023     * Print the 32-bit quantity in r0 as a hex value, preserving registers.
10024     */
10025common_printHex:
10026    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10027    mov     r1, r0
10028    ldr     r0, strPrintHex
10029    bl      printf
10030    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10031    bx      lr
10032
10033/*
10034 * Print the 64-bit quantity in r0-r1, preserving registers.
10035 */
10036common_printLong:
10037    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10038    mov     r3, r1
10039    mov     r2, r0
10040    ldr     r0, strPrintLong
10041    bl      printf
10042    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10043    bx      lr
10044
10045/*
10046 * Print full method info.  Pass the Method* in r0.  Preserves regs.
10047 */
10048common_printMethod:
10049    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10050    bl      dvmMterpPrintMethod
10051    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10052    bx      lr
10053
10054/*
10055 * Call a C helper function that dumps regs and possibly some
10056 * additional info.  Requires the C function to be compiled in.
10057 */
10058    .if     0
10059common_dumpRegs:
10060    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10061    bl      dvmMterpDumpArmRegs
10062    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10063    bx      lr
10064    .endif
10065
10066#if 0
10067/*
10068 * Experiment on VFP mode.
10069 *
10070 * uint32_t setFPSCR(uint32_t val, uint32_t mask)
10071 *
10072 * Updates the bits specified by "mask", setting them to the values in "val".
10073 */
10074setFPSCR:
10075    and     r0, r0, r1                  @ make sure no stray bits are set
10076    fmrx    r2, fpscr                   @ get VFP reg
10077    mvn     r1, r1                      @ bit-invert mask
10078    and     r2, r2, r1                  @ clear masked bits
10079    orr     r2, r2, r0                  @ set specified bits
10080    fmxr    fpscr, r2                   @ set VFP reg
10081    mov     r0, r2                      @ return new value
10082    bx      lr
10083
10084    .align  2
10085    .global dvmConfigureFP
10086    .type   dvmConfigureFP, %function
10087dvmConfigureFP:
10088    stmfd   sp!, {ip, lr}
10089    /* 0x03000000 sets DN/FZ */
10090    /* 0x00009f00 clears the six exception enable flags */
10091    bl      common_squeak0
10092    mov     r0, #0x03000000             @ r0<- 0x03000000
10093    add     r1, r0, #0x9f00             @ r1<- 0x03009f00
10094    bl      setFPSCR
10095    ldmfd   sp!, {ip, pc}
10096#endif
10097
10098
10099/*
10100 * String references, must be close to the code that uses them.
10101 */
10102    .align  2
10103strArithmeticException:
10104    .word   .LstrArithmeticException
10105strArrayIndexException:
10106    .word   .LstrArrayIndexException
10107strArrayStoreException:
10108    .word   .LstrArrayStoreException
10109strDivideByZero:
10110    .word   .LstrDivideByZero
10111strNegativeArraySizeException:
10112    .word   .LstrNegativeArraySizeException
10113strNoSuchMethodError:
10114    .word   .LstrNoSuchMethodError
10115strNullPointerException:
10116    .word   .LstrNullPointerException
10117
10118strLogTag:
10119    .word   .LstrLogTag
10120strExceptionNotCaughtLocally:
10121    .word   .LstrExceptionNotCaughtLocally
10122
10123strNewline:
10124    .word   .LstrNewline
10125strSqueak:
10126    .word   .LstrSqueak
10127strPrintHex:
10128    .word   .LstrPrintHex
10129strPrintLong:
10130    .word   .LstrPrintLong
10131
10132/*
10133 * Zero-terminated ASCII string data.
10134 *
10135 * On ARM we have two choices: do like gcc does, and LDR from a .word
10136 * with the address, or use an ADR pseudo-op to get the address
10137 * directly.  ADR saves 4 bytes and an indirection, but it's using a
10138 * PC-relative addressing mode and hence has a limited range, which
10139 * makes it not work well with mergeable string sections.
10140 */
10141    .section .rodata.str1.4,"aMS",%progbits,1
10142
10143.LstrBadEntryPoint:
10144    .asciz  "Bad entry point %d\n"
10145.LstrArithmeticException:
10146    .asciz  "Ljava/lang/ArithmeticException;"
10147.LstrArrayIndexException:
10148    .asciz  "Ljava/lang/ArrayIndexOutOfBoundsException;"
10149.LstrArrayStoreException:
10150    .asciz  "Ljava/lang/ArrayStoreException;"
10151.LstrClassCastException:
10152    .asciz  "Ljava/lang/ClassCastException;"
10153.LstrDivideByZero:
10154    .asciz  "divide by zero"
10155.LstrFilledNewArrayNotImpl:
10156    .asciz  "filled-new-array only implemented for objects and 'int'"
10157.LstrInternalError:
10158    .asciz  "Ljava/lang/InternalError;"
10159.LstrInstantiationError:
10160    .asciz  "Ljava/lang/InstantiationError;"
10161.LstrNegativeArraySizeException:
10162    .asciz  "Ljava/lang/NegativeArraySizeException;"
10163.LstrNoSuchMethodError:
10164    .asciz  "Ljava/lang/NoSuchMethodError;"
10165.LstrNullPointerException:
10166    .asciz  "Ljava/lang/NullPointerException;"
10167
10168.LstrLogTag:
10169    .asciz  "mterp"
10170.LstrExceptionNotCaughtLocally:
10171    .asciz  "Exception %s from %s:%d not caught locally\n"
10172
10173.LstrNewline:
10174    .asciz  "\n"
10175.LstrSqueak:
10176    .asciz  "<%d>"
10177.LstrPrintHex:
10178    .asciz  "<0x%x>"
10179.LstrPrintLong:
10180    .asciz  "<%lld>"
10181
10182
10183