OSDN Git Service

am 53015360: am 5a57e766: Merge "Change dx.bat to Windows EOL."
[android-x86/dalvik.git] / vm / mterp / out / InterpAsm-armv5te-vfp.S
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 /*
25  * ARMv5 definitions and declarations.
26  */
27
28 /*
29 ARM EABI general notes:
30
31 r0-r3 hold first 4 args to a method; they are not preserved across method calls
32 r4-r8 are available for general use
33 r9 is given special treatment in some situations, but not for us
34 r10 (sl) seems to be generally available
35 r11 (fp) is used by gcc (unless -fomit-frame-pointer is set)
36 r12 (ip) is scratch -- not preserved across method calls
37 r13 (sp) should be managed carefully in case a signal arrives
38 r14 (lr) must be preserved
39 r15 (pc) can be tinkered with directly
40
41 r0 holds returns of <= 4 bytes
42 r0-r1 hold returns of 8 bytes, low word in r0
43
44 Callee must save/restore r4+ (except r12) if it modifies them.  If VFP
45 is present, registers s16-s31 (a/k/a d8-d15, a/k/a q4-q7) must be preserved,
46 s0-s15 (d0-d7, q0-a3) do not need to be.
47
48 Stack is "full descending".  Only the arguments that don't fit in the first 4
49 registers are placed on the stack.  "sp" points at the first stacked argument
50 (i.e. the 5th arg).
51
52 VFP: single-precision results in s0, double-precision results in d0.
53
54 In the EABI, "sp" must be 64-bit aligned on entry to a function, and any
55 64-bit quantities (long long, double) must be 64-bit aligned.
56 */
57
58 /*
59 Mterp and ARM notes:
60
61 The following registers have fixed assignments:
62
63   reg nick      purpose
64   r4  rPC       interpreted program counter, used for fetching instructions
65   r5  rFP       interpreted frame pointer, used for accessing locals and args
66   r6  rGLUE     MterpGlue pointer
67   r7  rINST     first 16-bit code unit of current instruction
68   r8  rIBASE    interpreted instruction base pointer, used for computed goto
69
70 Macros are provided for common operations.  Each macro MUST emit only
71 one instruction to make instruction-counting easier.  They MUST NOT alter
72 unspecified registers or condition codes.
73 */
74
75 /* single-purpose registers, given names for clarity */
76 #define rPC     r4
77 #define rFP     r5
78 #define rGLUE   r6
79 #define rINST   r7
80 #define rIBASE  r8
81
82 /* save/restore the PC and/or FP from the glue struct */
83 #define LOAD_PC_FROM_GLUE()     ldr     rPC, [rGLUE, #offGlue_pc]
84 #define SAVE_PC_TO_GLUE()       str     rPC, [rGLUE, #offGlue_pc]
85 #define LOAD_FP_FROM_GLUE()     ldr     rFP, [rGLUE, #offGlue_fp]
86 #define SAVE_FP_TO_GLUE()       str     rFP, [rGLUE, #offGlue_fp]
87 #define LOAD_PC_FP_FROM_GLUE()  ldmia   rGLUE, {rPC, rFP}
88 #define SAVE_PC_FP_TO_GLUE()    stmia   rGLUE, {rPC, rFP}
89
90 /*
91  * "export" the PC to the stack frame, f/b/o future exception objects.  Must
92  * be done *before* something calls dvmThrowException.
93  *
94  * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e.
95  * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc)
96  *
97  * It's okay to do this more than once.
98  */
99 #define EXPORT_PC() \
100     str     rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)]
101
102 /*
103  * Given a frame pointer, find the stack save area.
104  *
105  * In C this is "((StackSaveArea*)(_fp) -1)".
106  */
107 #define SAVEAREA_FROM_FP(_reg, _fpreg) \
108     sub     _reg, _fpreg, #sizeofStackSaveArea
109
110 /*
111  * Fetch the next instruction from rPC into rINST.  Does not advance rPC.
112  */
113 #define FETCH_INST()            ldrh    rINST, [rPC]
114
115 /*
116  * Fetch the next instruction from the specified offset.  Advances rPC
117  * to point to the next instruction.  "_count" is in 16-bit code units.
118  *
119  * Because of the limited size of immediate constants on ARM, this is only
120  * suitable for small forward movements (i.e. don't try to implement "goto"
121  * with this).
122  *
123  * This must come AFTER anything that can throw an exception, or the
124  * exception catch may miss.  (This also implies that it must come after
125  * EXPORT_PC().)
126  */
127 #define FETCH_ADVANCE_INST(_count) ldrh    rINST, [rPC, #(_count*2)]!
128
129 /*
130  * The operation performed here is similar to FETCH_ADVANCE_INST, except the
131  * src and dest registers are parameterized (not hard-wired to rPC and rINST).
132  */
133 #define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \
134         ldrh    _dreg, [_sreg, #(_count*2)]!
135
136 /*
137  * Fetch the next instruction from an offset specified by _reg.  Updates
138  * rPC to point to the next instruction.  "_reg" must specify the distance
139  * in bytes, *not* 16-bit code units, and may be a signed value.
140  *
141  * We want to write "ldrh rINST, [rPC, _reg, lsl #2]!", but some of the
142  * bits that hold the shift distance are used for the half/byte/sign flags.
143  * In some cases we can pre-double _reg for free, so we require a byte offset
144  * here.
145  */
146 #define FETCH_ADVANCE_INST_RB(_reg) ldrh    rINST, [rPC, _reg]!
147
148 /*
149  * Fetch a half-word code unit from an offset past the current PC.  The
150  * "_count" value is in 16-bit code units.  Does not advance rPC.
151  *
152  * The "_S" variant works the same but treats the value as signed.
153  */
154 #define FETCH(_reg, _count)     ldrh    _reg, [rPC, #(_count*2)]
155 #define FETCH_S(_reg, _count)   ldrsh   _reg, [rPC, #(_count*2)]
156
157 /*
158  * Fetch one byte from an offset past the current PC.  Pass in the same
159  * "_count" as you would for FETCH, and an additional 0/1 indicating which
160  * byte of the halfword you want (lo/hi).
161  */
162 #define FETCH_B(_reg, _count, _byte) ldrb     _reg, [rPC, #(_count*2+_byte)]
163
164 /*
165  * Put the instruction's opcode field into the specified register.
166  */
167 #define GET_INST_OPCODE(_reg)   and     _reg, rINST, #255
168
169 /*
170  * Put the prefetched instruction's opcode field into the specified register.
171  */
172 #define GET_PREFETCHED_OPCODE(_oreg, _ireg)   and     _oreg, _ireg, #255
173
174 /*
175  * Begin executing the opcode in _reg.  Because this only jumps within the
176  * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork.
177  */
178 #define GOTO_OPCODE(_reg)       add     pc, rIBASE, _reg, lsl #6
179 #define GOTO_OPCODE_IFEQ(_reg)  addeq   pc, rIBASE, _reg, lsl #6
180 #define GOTO_OPCODE_IFNE(_reg)  addne   pc, rIBASE, _reg, lsl #6
181
182 /*
183  * Get/set the 32-bit value from a Dalvik register.
184  */
185 #define GET_VREG(_reg, _vreg)   ldr     _reg, [rFP, _vreg, lsl #2]
186 #define SET_VREG(_reg, _vreg)   str     _reg, [rFP, _vreg, lsl #2]
187
188 #if defined(WITH_JIT)
189 #define GET_JIT_PROF_TABLE(_reg)    ldr     _reg,[rGLUE,#offGlue_pJitProfTable]
190 #define GET_JIT_THRESHOLD(_reg)     ldr     _reg,[rGLUE,#offGlue_jitThreshold]
191 #endif
192
193 /*
194  * Convert a virtual register index into an address.
195  */
196 #define VREG_INDEX_TO_ADDR(_reg, _vreg) \
197         add     _reg, rFP, _vreg, lsl #2
198
199 /*
200  * This is a #include, not a %include, because we want the C pre-processor
201  * to expand the macros into assembler assignment statements.
202  */
203 #include "../common/asm-constants.h"
204
205 #if defined(WITH_JIT)
206 #include "../common/jit-config.h"
207 #endif
208
209 /* File: armv5te/platform.S */
210 /*
211  * ===========================================================================
212  *  CPU-version-specific defines
213  * ===========================================================================
214  */
215
216 /*
217  * Macro for data memory barrier; not meaningful pre-ARMv6K.
218  */
219 .macro  SMP_DMB
220 .endm
221
222 /*
223  * Macro for data memory barrier; not meaningful pre-ARMv6K.
224  */
225 .macro  SMP_DMB_ST
226 .endm
227
228 /* File: armv5te/entry.S */
229 /*
230  * Copyright (C) 2008 The Android Open Source Project
231  *
232  * Licensed under the Apache License, Version 2.0 (the "License");
233  * you may not use this file except in compliance with the License.
234  * You may obtain a copy of the License at
235  *
236  *      http://www.apache.org/licenses/LICENSE-2.0
237  *
238  * Unless required by applicable law or agreed to in writing, software
239  * distributed under the License is distributed on an "AS IS" BASIS,
240  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
241  * See the License for the specific language governing permissions and
242  * limitations under the License.
243  */
244 /*
245  * Interpreter entry point.
246  */
247
248 /*
249  * We don't have formal stack frames, so gdb scans upward in the code
250  * to find the start of the function (a label with the %function type),
251  * and then looks at the next few instructions to figure out what
252  * got pushed onto the stack.  From this it figures out how to restore
253  * the registers, including PC, for the previous stack frame.  If gdb
254  * sees a non-function label, it stops scanning, so either we need to
255  * have nothing but assembler-local labels between the entry point and
256  * the break, or we need to fake it out.
257  *
258  * When this is defined, we add some stuff to make gdb less confused.
259  */
260 #define ASSIST_DEBUGGER 1
261
262     .text
263     .align  2
264     .global dvmMterpStdRun
265     .type   dvmMterpStdRun, %function
266
267 /*
268  * On entry:
269  *  r0  MterpGlue* glue
270  *
271  * This function returns a boolean "changeInterp" value.  The return comes
272  * via a call to dvmMterpStdBail().
273  */
274 dvmMterpStdRun:
275 #define MTERP_ENTRY1 \
276     .save {r4-r10,fp,lr}; \
277     stmfd   sp!, {r4-r10,fp,lr}         @ save 9 regs
278 #define MTERP_ENTRY2 \
279     .pad    #4; \
280     sub     sp, sp, #4                  @ align 64
281
282     .fnstart
283     MTERP_ENTRY1
284     MTERP_ENTRY2
285
286     /* save stack pointer, add magic word for debuggerd */
287     str     sp, [r0, #offGlue_bailPtr]  @ save SP for eventual return
288
289     /* set up "named" registers, figure out entry point */
290     mov     rGLUE, r0                   @ set rGLUE
291     ldr     r1, [r0, #offGlue_entryPoint]   @ enum is 4 bytes in aapcs-EABI
292     LOAD_PC_FP_FROM_GLUE()              @ load rPC and rFP from "glue"
293     adr     rIBASE, dvmAsmInstructionStart  @ set rIBASE
294     cmp     r1, #kInterpEntryInstr      @ usual case?
295     bne     .Lnot_instr                 @ no, handle it
296
297 #if defined(WITH_JIT)
298 .LentryInstr:
299     ldr     r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
300     /* Entry is always a possible trace start */
301     GET_JIT_PROF_TABLE(r0)
302     FETCH_INST()
303     mov     r1, #0                      @ prepare the value for the new state
304     str     r1, [r10, #offThread_inJitCodeCache] @ back to the interp land
305     cmp     r0,#0                       @ is profiling disabled?
306 #if !defined(WITH_SELF_VERIFICATION)
307     bne     common_updateProfile        @ profiling is enabled
308 #else
309     ldr     r2, [r10, #offThread_shadowSpace]   @ to find out the jit exit state
310     beq     1f                          @ profiling is disabled
311     ldr     r3, [r2, #offShadowSpace_jitExitState]  @ jit exit state
312     cmp     r3, #kSVSTraceSelect        @ hot trace following?
313     moveq   r2,#kJitTSelectRequestHot   @ ask for trace selection
314     beq     common_selectTrace          @ go build the trace
315     cmp     r3, #kSVSNoProfile          @ don't profile the next instruction?
316     beq     1f                          @ intrepret the next instruction
317     b       common_updateProfile        @ collect profiles
318 #endif
319 1:
320     GET_INST_OPCODE(ip)
321     GOTO_OPCODE(ip)
322 #else
323     /* start executing the instruction at rPC */
324     FETCH_INST()                        @ load rINST from rPC
325     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
326     GOTO_OPCODE(ip)                     @ jump to next instruction
327 #endif
328
329 .Lnot_instr:
330     cmp     r1, #kInterpEntryReturn     @ were we returning from a method?
331     beq     common_returnFromMethod
332
333 .Lnot_return:
334     cmp     r1, #kInterpEntryThrow      @ were we throwing an exception?
335     beq     common_exceptionThrown
336
337 #if defined(WITH_JIT)
338 .Lnot_throw:
339     ldr     r10,[rGLUE, #offGlue_jitResumeNPC]
340     ldr     r2,[rGLUE, #offGlue_jitResumeDPC]
341     cmp     r1, #kInterpEntryResume     @ resuming after Jit single-step?
342     bne     .Lbad_arg
343     cmp     rPC,r2
344     bne     .LentryInstr                @ must have branched, don't resume
345 #if defined(WITH_SELF_VERIFICATION)
346     @ glue->entryPoint will be set in dvmSelfVerificationSaveState
347     b       jitSVShadowRunStart         @ re-enter the translation after the
348                                         @ single-stepped instruction
349     @noreturn
350 #endif
351     mov     r1, #kInterpEntryInstr
352     str     r1, [rGLUE, #offGlue_entryPoint]
353     bx      r10                         @ re-enter the translation
354 #endif
355
356 .Lbad_arg:
357     ldr     r0, strBadEntryPoint
358     @ r1 holds value of entryPoint
359     bl      printf
360     bl      dvmAbort
361     .fnend
362
363
364     .global dvmMterpStdBail
365     .type   dvmMterpStdBail, %function
366
367 /*
368  * Restore the stack pointer and PC from the save point established on entry.
369  * This is essentially the same as a longjmp, but should be cheaper.  The
370  * last instruction causes us to return to whoever called dvmMterpStdRun.
371  *
372  * We pushed some registers on the stack in dvmMterpStdRun, then saved
373  * SP and LR.  Here we restore SP, restore the registers, and then restore
374  * LR to PC.
375  *
376  * On entry:
377  *  r0  MterpGlue* glue
378  *  r1  bool changeInterp
379  */
380 dvmMterpStdBail:
381     ldr     sp, [r0, #offGlue_bailPtr]      @ sp<- saved SP
382     mov     r0, r1                          @ return the changeInterp value
383     add     sp, sp, #4                      @ un-align 64
384     ldmfd   sp!, {r4-r10,fp,pc}             @ restore 9 regs and return
385
386
387 /*
388  * String references.
389  */
390 strBadEntryPoint:
391     .word   .LstrBadEntryPoint
392
393
394     .global dvmAsmInstructionStart
395     .type   dvmAsmInstructionStart, %function
396 dvmAsmInstructionStart = .L_OP_NOP
397     .text
398
399 /* ------------------------------ */
400     .balign 64
401 .L_OP_NOP: /* 0x00 */
402 /* File: armv5te/OP_NOP.S */
403     FETCH_ADVANCE_INST(1)               @ advance to next instr, load rINST
404     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
405     GOTO_OPCODE(ip)                     @ execute it
406
407 #ifdef ASSIST_DEBUGGER
408     /* insert fake function header to help gdb find the stack frame */
409     .type   dalvik_inst, %function
410 dalvik_inst:
411     .fnstart
412     MTERP_ENTRY1
413     MTERP_ENTRY2
414     .fnend
415 #endif
416
417 /* ------------------------------ */
418     .balign 64
419 .L_OP_MOVE: /* 0x01 */
420 /* File: armv5te/OP_MOVE.S */
421     /* for move, move-object, long-to-int */
422     /* op vA, vB */
423     mov     r1, rINST, lsr #12          @ r1<- B from 15:12
424     mov     r0, rINST, lsr #8           @ r0<- A from 11:8
425     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
426     GET_VREG(r2, r1)                    @ r2<- fp[B]
427     and     r0, r0, #15
428     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
429     SET_VREG(r2, r0)                    @ fp[A]<- r2
430     GOTO_OPCODE(ip)                     @ execute next instruction
431
432 /* ------------------------------ */
433     .balign 64
434 .L_OP_MOVE_FROM16: /* 0x02 */
435 /* File: armv5te/OP_MOVE_FROM16.S */
436     /* for: move/from16, move-object/from16 */
437     /* op vAA, vBBBB */
438     FETCH(r1, 1)                        @ r1<- BBBB
439     mov     r0, rINST, lsr #8           @ r0<- AA
440     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
441     GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
442     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
443     SET_VREG(r2, r0)                    @ fp[AA]<- r2
444     GOTO_OPCODE(ip)                     @ jump to next instruction
445
446 /* ------------------------------ */
447     .balign 64
448 .L_OP_MOVE_16: /* 0x03 */
449 /* File: armv5te/OP_MOVE_16.S */
450     /* for: move/16, move-object/16 */
451     /* op vAAAA, vBBBB */
452     FETCH(r1, 2)                        @ r1<- BBBB
453     FETCH(r0, 1)                        @ r0<- AAAA
454     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
455     GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
456     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
457     SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
458     GOTO_OPCODE(ip)                     @ jump to next instruction
459
460 /* ------------------------------ */
461     .balign 64
462 .L_OP_MOVE_WIDE: /* 0x04 */
463 /* File: armv5te/OP_MOVE_WIDE.S */
464     /* move-wide vA, vB */
465     /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
466     mov     r2, rINST, lsr #8           @ r2<- A(+)
467     mov     r3, rINST, lsr #12          @ r3<- B
468     and     r2, r2, #15
469     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
470     add     r2, rFP, r2, lsl #2         @ r2<- &fp[A]
471     ldmia   r3, {r0-r1}                 @ r0/r1<- fp[B]
472     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
473     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
474     stmia   r2, {r0-r1}                 @ fp[A]<- r0/r1
475     GOTO_OPCODE(ip)                     @ jump to next instruction
476
477 /* ------------------------------ */
478     .balign 64
479 .L_OP_MOVE_WIDE_FROM16: /* 0x05 */
480 /* File: armv5te/OP_MOVE_WIDE_FROM16.S */
481     /* move-wide/from16 vAA, vBBBB */
482     /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
483     FETCH(r3, 1)                        @ r3<- BBBB
484     mov     r2, rINST, lsr #8           @ r2<- AA
485     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
486     add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
487     ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
488     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
489     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
490     stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
491     GOTO_OPCODE(ip)                     @ jump to next instruction
492
493 /* ------------------------------ */
494     .balign 64
495 .L_OP_MOVE_WIDE_16: /* 0x06 */
496 /* File: armv5te/OP_MOVE_WIDE_16.S */
497     /* move-wide/16 vAAAA, vBBBB */
498     /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
499     FETCH(r3, 2)                        @ r3<- BBBB
500     FETCH(r2, 1)                        @ r2<- AAAA
501     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
502     add     r2, rFP, r2, lsl #2         @ r2<- &fp[AAAA]
503     ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
504     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
505     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
506     stmia   r2, {r0-r1}                 @ fp[AAAA]<- r0/r1
507     GOTO_OPCODE(ip)                     @ jump to next instruction
508
509 /* ------------------------------ */
510     .balign 64
511 .L_OP_MOVE_OBJECT: /* 0x07 */
512 /* File: armv5te/OP_MOVE_OBJECT.S */
513 /* File: armv5te/OP_MOVE.S */
514     /* for move, move-object, long-to-int */
515     /* op vA, vB */
516     mov     r1, rINST, lsr #12          @ r1<- B from 15:12
517     mov     r0, rINST, lsr #8           @ r0<- A from 11:8
518     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
519     GET_VREG(r2, r1)                    @ r2<- fp[B]
520     and     r0, r0, #15
521     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
522     SET_VREG(r2, r0)                    @ fp[A]<- r2
523     GOTO_OPCODE(ip)                     @ execute next instruction
524
525
526 /* ------------------------------ */
527     .balign 64
528 .L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
529 /* File: armv5te/OP_MOVE_OBJECT_FROM16.S */
530 /* File: armv5te/OP_MOVE_FROM16.S */
531     /* for: move/from16, move-object/from16 */
532     /* op vAA, vBBBB */
533     FETCH(r1, 1)                        @ r1<- BBBB
534     mov     r0, rINST, lsr #8           @ r0<- AA
535     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
536     GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
537     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
538     SET_VREG(r2, r0)                    @ fp[AA]<- r2
539     GOTO_OPCODE(ip)                     @ jump to next instruction
540
541
542 /* ------------------------------ */
543     .balign 64
544 .L_OP_MOVE_OBJECT_16: /* 0x09 */
545 /* File: armv5te/OP_MOVE_OBJECT_16.S */
546 /* File: armv5te/OP_MOVE_16.S */
547     /* for: move/16, move-object/16 */
548     /* op vAAAA, vBBBB */
549     FETCH(r1, 2)                        @ r1<- BBBB
550     FETCH(r0, 1)                        @ r0<- AAAA
551     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
552     GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
553     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
554     SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
555     GOTO_OPCODE(ip)                     @ jump to next instruction
556
557
558 /* ------------------------------ */
559     .balign 64
560 .L_OP_MOVE_RESULT: /* 0x0a */
561 /* File: armv5te/OP_MOVE_RESULT.S */
562     /* for: move-result, move-result-object */
563     /* op vAA */
564     mov     r2, rINST, lsr #8           @ r2<- AA
565     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
566     ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
567     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
568     SET_VREG(r0, r2)                    @ fp[AA]<- r0
569     GOTO_OPCODE(ip)                     @ jump to next instruction
570
571 /* ------------------------------ */
572     .balign 64
573 .L_OP_MOVE_RESULT_WIDE: /* 0x0b */
574 /* File: armv5te/OP_MOVE_RESULT_WIDE.S */
575     /* move-result-wide vAA */
576     mov     r2, rINST, lsr #8           @ r2<- AA
577     add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
578     add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
579     ldmia   r3, {r0-r1}                 @ r0/r1<- retval.j
580     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
581     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
582     stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
583     GOTO_OPCODE(ip)                     @ jump to next instruction
584
585 /* ------------------------------ */
586     .balign 64
587 .L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
588 /* File: armv5te/OP_MOVE_RESULT_OBJECT.S */
589 /* File: armv5te/OP_MOVE_RESULT.S */
590     /* for: move-result, move-result-object */
591     /* op vAA */
592     mov     r2, rINST, lsr #8           @ r2<- AA
593     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
594     ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
595     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
596     SET_VREG(r0, r2)                    @ fp[AA]<- r0
597     GOTO_OPCODE(ip)                     @ jump to next instruction
598
599
600 /* ------------------------------ */
601     .balign 64
602 .L_OP_MOVE_EXCEPTION: /* 0x0d */
603 /* File: armv5te/OP_MOVE_EXCEPTION.S */
604     /* move-exception vAA */
605     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
606     mov     r2, rINST, lsr #8           @ r2<- AA
607     ldr     r3, [r0, #offThread_exception]  @ r3<- dvmGetException bypass
608     mov     r1, #0                      @ r1<- 0
609     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
610     SET_VREG(r3, r2)                    @ fp[AA]<- exception obj
611     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
612     str     r1, [r0, #offThread_exception]  @ dvmClearException bypass
613     GOTO_OPCODE(ip)                     @ jump to next instruction
614
615 /* ------------------------------ */
616     .balign 64
617 .L_OP_RETURN_VOID: /* 0x0e */
618 /* File: armv5te/OP_RETURN_VOID.S */
619     b       common_returnFromMethod
620
621 /* ------------------------------ */
622     .balign 64
623 .L_OP_RETURN: /* 0x0f */
624 /* File: armv5te/OP_RETURN.S */
625     /*
626      * Return a 32-bit value.  Copies the return value into the "glue"
627      * structure, then jumps to the return handler.
628      *
629      * for: return, return-object
630      */
631     /* op vAA */
632     mov     r2, rINST, lsr #8           @ r2<- AA
633     GET_VREG(r0, r2)                    @ r0<- vAA
634     str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
635     b       common_returnFromMethod
636
637 /* ------------------------------ */
638     .balign 64
639 .L_OP_RETURN_WIDE: /* 0x10 */
640 /* File: armv5te/OP_RETURN_WIDE.S */
641     /*
642      * Return a 64-bit value.  Copies the return value into the "glue"
643      * structure, then jumps to the return handler.
644      */
645     /* return-wide vAA */
646     mov     r2, rINST, lsr #8           @ r2<- AA
647     add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
648     add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
649     ldmia   r2, {r0-r1}                 @ r0/r1 <- vAA/vAA+1
650     stmia   r3, {r0-r1}                 @ retval<- r0/r1
651     b       common_returnFromMethod
652
653 /* ------------------------------ */
654     .balign 64
655 .L_OP_RETURN_OBJECT: /* 0x11 */
656 /* File: armv5te/OP_RETURN_OBJECT.S */
657 /* File: armv5te/OP_RETURN.S */
658     /*
659      * Return a 32-bit value.  Copies the return value into the "glue"
660      * structure, then jumps to the return handler.
661      *
662      * for: return, return-object
663      */
664     /* op vAA */
665     mov     r2, rINST, lsr #8           @ r2<- AA
666     GET_VREG(r0, r2)                    @ r0<- vAA
667     str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
668     b       common_returnFromMethod
669
670
671 /* ------------------------------ */
672     .balign 64
673 .L_OP_CONST_4: /* 0x12 */
674 /* File: armv5te/OP_CONST_4.S */
675     /* const/4 vA, #+B */
676     mov     r1, rINST, lsl #16          @ r1<- Bxxx0000
677     mov     r0, rINST, lsr #8           @ r0<- A+
678     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
679     mov     r1, r1, asr #28             @ r1<- sssssssB (sign-extended)
680     and     r0, r0, #15
681     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
682     SET_VREG(r1, r0)                    @ fp[A]<- r1
683     GOTO_OPCODE(ip)                     @ execute next instruction
684
685 /* ------------------------------ */
686     .balign 64
687 .L_OP_CONST_16: /* 0x13 */
688 /* File: armv5te/OP_CONST_16.S */
689     /* const/16 vAA, #+BBBB */
690     FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
691     mov     r3, rINST, lsr #8           @ r3<- AA
692     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
693     SET_VREG(r0, r3)                    @ vAA<- r0
694     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
695     GOTO_OPCODE(ip)                     @ jump to next instruction
696
697 /* ------------------------------ */
698     .balign 64
699 .L_OP_CONST: /* 0x14 */
700 /* File: armv5te/OP_CONST.S */
701     /* const vAA, #+BBBBbbbb */
702     mov     r3, rINST, lsr #8           @ r3<- AA
703     FETCH(r0, 1)                        @ r0<- bbbb (low)
704     FETCH(r1, 2)                        @ r1<- BBBB (high)
705     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
706     orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
707     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
708     SET_VREG(r0, r3)                    @ vAA<- r0
709     GOTO_OPCODE(ip)                     @ jump to next instruction
710
711 /* ------------------------------ */
712     .balign 64
713 .L_OP_CONST_HIGH16: /* 0x15 */
714 /* File: armv5te/OP_CONST_HIGH16.S */
715     /* const/high16 vAA, #+BBBB0000 */
716     FETCH(r0, 1)                        @ r0<- 0000BBBB (zero-extended)
717     mov     r3, rINST, lsr #8           @ r3<- AA
718     mov     r0, r0, lsl #16             @ r0<- BBBB0000
719     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
720     SET_VREG(r0, r3)                    @ vAA<- r0
721     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
722     GOTO_OPCODE(ip)                     @ jump to next instruction
723
724 /* ------------------------------ */
725     .balign 64
726 .L_OP_CONST_WIDE_16: /* 0x16 */
727 /* File: armv5te/OP_CONST_WIDE_16.S */
728     /* const-wide/16 vAA, #+BBBB */
729     FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
730     mov     r3, rINST, lsr #8           @ r3<- AA
731     mov     r1, r0, asr #31             @ r1<- ssssssss
732     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
733     add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
734     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
735     stmia   r3, {r0-r1}                 @ vAA<- r0/r1
736     GOTO_OPCODE(ip)                     @ jump to next instruction
737
738 /* ------------------------------ */
739     .balign 64
740 .L_OP_CONST_WIDE_32: /* 0x17 */
741 /* File: armv5te/OP_CONST_WIDE_32.S */
742     /* const-wide/32 vAA, #+BBBBbbbb */
743     FETCH(r0, 1)                        @ r0<- 0000bbbb (low)
744     mov     r3, rINST, lsr #8           @ r3<- AA
745     FETCH_S(r2, 2)                      @ r2<- ssssBBBB (high)
746     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
747     orr     r0, r0, r2, lsl #16         @ r0<- BBBBbbbb
748     add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
749     mov     r1, r0, asr #31             @ r1<- ssssssss
750     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
751     stmia   r3, {r0-r1}                 @ vAA<- r0/r1
752     GOTO_OPCODE(ip)                     @ jump to next instruction
753
754 /* ------------------------------ */
755     .balign 64
756 .L_OP_CONST_WIDE: /* 0x18 */
757 /* File: armv5te/OP_CONST_WIDE.S */
758     /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
759     FETCH(r0, 1)                        @ r0<- bbbb (low)
760     FETCH(r1, 2)                        @ r1<- BBBB (low middle)
761     FETCH(r2, 3)                        @ r2<- hhhh (high middle)
762     orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb (low word)
763     FETCH(r3, 4)                        @ r3<- HHHH (high)
764     mov     r9, rINST, lsr #8           @ r9<- AA
765     orr     r1, r2, r3, lsl #16         @ r1<- HHHHhhhh (high word)
766     FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
767     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
768     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
769     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
770     GOTO_OPCODE(ip)                     @ jump to next instruction
771
772 /* ------------------------------ */
773     .balign 64
774 .L_OP_CONST_WIDE_HIGH16: /* 0x19 */
775 /* File: armv5te/OP_CONST_WIDE_HIGH16.S */
776     /* const-wide/high16 vAA, #+BBBB000000000000 */
777     FETCH(r1, 1)                        @ r1<- 0000BBBB (zero-extended)
778     mov     r3, rINST, lsr #8           @ r3<- AA
779     mov     r0, #0                      @ r0<- 00000000
780     mov     r1, r1, lsl #16             @ r1<- BBBB0000
781     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
782     add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
783     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
784     stmia   r3, {r0-r1}                 @ vAA<- r0/r1
785     GOTO_OPCODE(ip)                     @ jump to next instruction
786
787 /* ------------------------------ */
788     .balign 64
789 .L_OP_CONST_STRING: /* 0x1a */
790 /* File: armv5te/OP_CONST_STRING.S */
791     /* const/string vAA, String@BBBB */
792     FETCH(r1, 1)                        @ r1<- BBBB
793     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
794     mov     r9, rINST, lsr #8           @ r9<- AA
795     ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
796     ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
797     cmp     r0, #0                      @ not yet resolved?
798     beq     .LOP_CONST_STRING_resolve
799     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
800     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
801     SET_VREG(r0, r9)                    @ vAA<- r0
802     GOTO_OPCODE(ip)                     @ jump to next instruction
803
804 /* ------------------------------ */
805     .balign 64
806 .L_OP_CONST_STRING_JUMBO: /* 0x1b */
807 /* File: armv5te/OP_CONST_STRING_JUMBO.S */
808     /* const/string vAA, String@BBBBBBBB */
809     FETCH(r0, 1)                        @ r0<- bbbb (low)
810     FETCH(r1, 2)                        @ r1<- BBBB (high)
811     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
812     mov     r9, rINST, lsr #8           @ r9<- AA
813     ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
814     orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
815     ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
816     cmp     r0, #0
817     beq     .LOP_CONST_STRING_JUMBO_resolve
818     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
819     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
820     SET_VREG(r0, r9)                    @ vAA<- r0
821     GOTO_OPCODE(ip)                     @ jump to next instruction
822
823 /* ------------------------------ */
824     .balign 64
825 .L_OP_CONST_CLASS: /* 0x1c */
826 /* File: armv5te/OP_CONST_CLASS.S */
827     /* const/class vAA, Class@BBBB */
828     FETCH(r1, 1)                        @ r1<- BBBB
829     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
830     mov     r9, rINST, lsr #8           @ r9<- AA
831     ldr     r2, [r2, #offDvmDex_pResClasses]   @ r2<- dvmDex->pResClasses
832     ldr     r0, [r2, r1, lsl #2]        @ r0<- pResClasses[BBBB]
833     cmp     r0, #0                      @ not yet resolved?
834     beq     .LOP_CONST_CLASS_resolve
835     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
836     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
837     SET_VREG(r0, r9)                    @ vAA<- r0
838     GOTO_OPCODE(ip)                     @ jump to next instruction
839
840 /* ------------------------------ */
841     .balign 64
842 .L_OP_MONITOR_ENTER: /* 0x1d */
843 /* File: armv5te/OP_MONITOR_ENTER.S */
844     /*
845      * Synchronize on an object.
846      */
847     /* monitor-enter vAA */
848     mov     r2, rINST, lsr #8           @ r2<- AA
849     GET_VREG(r1, r2)                    @ r1<- vAA (object)
850     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
851     cmp     r1, #0                      @ null object?
852     EXPORT_PC()                         @ need for precise GC, MONITOR_TRACKING
853     beq     common_errNullObject        @ null object, throw an exception
854     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
855     bl      dvmLockObject               @ call(self, obj)
856 #ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */
857     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
858     ldr     r1, [r0, #offThread_exception] @ check for exception
859     cmp     r1, #0
860     bne     common_exceptionThrown      @ exception raised, bail out
861 #endif
862     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
863     GOTO_OPCODE(ip)                     @ jump to next instruction
864
865 /* ------------------------------ */
866     .balign 64
867 .L_OP_MONITOR_EXIT: /* 0x1e */
868 /* File: armv5te/OP_MONITOR_EXIT.S */
869     /*
870      * Unlock an object.
871      *
872      * Exceptions that occur when unlocking a monitor need to appear as
873      * if they happened at the following instruction.  See the Dalvik
874      * instruction spec.
875      */
876     /* monitor-exit vAA */
877     mov     r2, rINST, lsr #8           @ r2<- AA
878     EXPORT_PC()                         @ before fetch: export the PC
879     GET_VREG(r1, r2)                    @ r1<- vAA (object)
880     cmp     r1, #0                      @ null object?
881     beq     1f                          @ yes
882     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
883     bl      dvmUnlockObject             @ r0<- success for unlock(self, obj)
884     cmp     r0, #0                      @ failed?
885     FETCH_ADVANCE_INST(1)               @ before throw: advance rPC, load rINST
886     beq     common_exceptionThrown      @ yes, exception is pending
887     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
888     GOTO_OPCODE(ip)                     @ jump to next instruction
889 1:
890     FETCH_ADVANCE_INST(1)               @ advance before throw
891     b      common_errNullObject
892
893 /* ------------------------------ */
894     .balign 64
895 .L_OP_CHECK_CAST: /* 0x1f */
896 /* File: armv5te/OP_CHECK_CAST.S */
897     /*
898      * Check to see if a cast from one class to another is allowed.
899      */
900     /* check-cast vAA, class@BBBB */
901     mov     r3, rINST, lsr #8           @ r3<- AA
902     FETCH(r2, 1)                        @ r2<- BBBB
903     GET_VREG(r9, r3)                    @ r9<- object
904     ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- pDvmDex
905     cmp     r9, #0                      @ is object null?
906     ldr     r0, [r0, #offDvmDex_pResClasses]    @ r0<- pDvmDex->pResClasses
907     beq     .LOP_CHECK_CAST_okay            @ null obj, cast always succeeds
908     ldr     r1, [r0, r2, lsl #2]        @ r1<- resolved class
909     ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
910     cmp     r1, #0                      @ have we resolved this before?
911     beq     .LOP_CHECK_CAST_resolve         @ not resolved, do it now
912 .LOP_CHECK_CAST_resolved:
913     cmp     r0, r1                      @ same class (trivial success)?
914     bne     .LOP_CHECK_CAST_fullcheck       @ no, do full check
915 .LOP_CHECK_CAST_okay:
916     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
917     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
918     GOTO_OPCODE(ip)                     @ jump to next instruction
919
920 /* ------------------------------ */
921     .balign 64
922 .L_OP_INSTANCE_OF: /* 0x20 */
923 /* File: armv5te/OP_INSTANCE_OF.S */
924     /*
925      * Check to see if an object reference is an instance of a class.
926      *
927      * Most common situation is a non-null object, being compared against
928      * an already-resolved class.
929      */
930     /* instance-of vA, vB, class@CCCC */
931     mov     r3, rINST, lsr #12          @ r3<- B
932     mov     r9, rINST, lsr #8           @ r9<- A+
933     GET_VREG(r0, r3)                    @ r0<- vB (object)
934     and     r9, r9, #15                 @ r9<- A
935     cmp     r0, #0                      @ is object null?
936     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- pDvmDex
937     beq     .LOP_INSTANCE_OF_store           @ null obj, not an instance, store r0
938     FETCH(r3, 1)                        @ r3<- CCCC
939     ldr     r2, [r2, #offDvmDex_pResClasses]    @ r2<- pDvmDex->pResClasses
940     ldr     r1, [r2, r3, lsl #2]        @ r1<- resolved class
941     ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
942     cmp     r1, #0                      @ have we resolved this before?
943     beq     .LOP_INSTANCE_OF_resolve         @ not resolved, do it now
944 .LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class
945     cmp     r0, r1                      @ same class (trivial success)?
946     beq     .LOP_INSTANCE_OF_trivial         @ yes, trivial finish
947     b       .LOP_INSTANCE_OF_fullcheck       @ no, do full check
948
949 /* ------------------------------ */
950     .balign 64
951 .L_OP_ARRAY_LENGTH: /* 0x21 */
952 /* File: armv5te/OP_ARRAY_LENGTH.S */
953     /*
954      * Return the length of an array.
955      */
956     mov     r1, rINST, lsr #12          @ r1<- B
957     mov     r2, rINST, lsr #8           @ r2<- A+
958     GET_VREG(r0, r1)                    @ r0<- vB (object ref)
959     and     r2, r2, #15                 @ r2<- A
960     cmp     r0, #0                      @ is object null?
961     beq     common_errNullObject        @ yup, fail
962     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
963     ldr     r3, [r0, #offArrayObject_length]    @ r3<- array length
964     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
965     SET_VREG(r3, r2)                    @ vB<- length
966     GOTO_OPCODE(ip)                     @ jump to next instruction
967
968 /* ------------------------------ */
969     .balign 64
970 .L_OP_NEW_INSTANCE: /* 0x22 */
971 /* File: armv5te/OP_NEW_INSTANCE.S */
972     /*
973      * Create a new instance of a class.
974      */
975     /* new-instance vAA, class@BBBB */
976     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
977     FETCH(r1, 1)                        @ r1<- BBBB
978     ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
979     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
980     EXPORT_PC()                         @ req'd for init, resolve, alloc
981     cmp     r0, #0                      @ already resolved?
982     beq     .LOP_NEW_INSTANCE_resolve         @ no, resolve it now
983 .LOP_NEW_INSTANCE_resolved:   @ r0=class
984     ldrb    r1, [r0, #offClassObject_status]    @ r1<- ClassStatus enum
985     cmp     r1, #CLASS_INITIALIZED      @ has class been initialized?
986     bne     .LOP_NEW_INSTANCE_needinit        @ no, init class now
987 .LOP_NEW_INSTANCE_initialized: @ r0=class
988     mov     r1, #ALLOC_DONT_TRACK       @ flags for alloc call
989     bl      dvmAllocObject              @ r0<- new object
990     b       .LOP_NEW_INSTANCE_finish          @ continue
991
992 /* ------------------------------ */
993     .balign 64
994 .L_OP_NEW_ARRAY: /* 0x23 */
995 /* File: armv5te/OP_NEW_ARRAY.S */
996     /*
997      * Allocate an array of objects, specified with the array class
998      * and a count.
999      *
1000      * The verifier guarantees that this is an array class, so we don't
1001      * check for it here.
1002      */
1003     /* new-array vA, vB, class@CCCC */
1004     mov     r0, rINST, lsr #12          @ r0<- B
1005     FETCH(r2, 1)                        @ r2<- CCCC
1006     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1007     GET_VREG(r1, r0)                    @ r1<- vB (array length)
1008     ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1009     cmp     r1, #0                      @ check length
1010     ldr     r0, [r3, r2, lsl #2]        @ r0<- resolved class
1011     bmi     common_errNegativeArraySize @ negative length, bail
1012     cmp     r0, #0                      @ already resolved?
1013     EXPORT_PC()                         @ req'd for resolve, alloc
1014     bne     .LOP_NEW_ARRAY_finish          @ resolved, continue
1015     b       .LOP_NEW_ARRAY_resolve         @ do resolve now
1016
1017 /* ------------------------------ */
1018     .balign 64
1019 .L_OP_FILLED_NEW_ARRAY: /* 0x24 */
1020 /* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1021     /*
1022      * Create a new array with elements filled from registers.
1023      *
1024      * for: filled-new-array, filled-new-array/range
1025      */
1026     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1027     /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1028     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1029     FETCH(r1, 1)                        @ r1<- BBBB
1030     ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1031     EXPORT_PC()                         @ need for resolve and alloc
1032     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1033     mov     r10, rINST, lsr #8          @ r10<- AA or BA
1034     cmp     r0, #0                      @ already resolved?
1035     bne     .LOP_FILLED_NEW_ARRAY_continue        @ yes, continue on
1036 8:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1037     mov     r2, #0                      @ r2<- false
1038     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1039     bl      dvmResolveClass             @ r0<- call(clazz, ref)
1040     cmp     r0, #0                      @ got null?
1041     beq     common_exceptionThrown      @ yes, handle exception
1042     b       .LOP_FILLED_NEW_ARRAY_continue
1043
1044 /* ------------------------------ */
1045     .balign 64
1046 .L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
1047 /* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */
1048 /* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1049     /*
1050      * Create a new array with elements filled from registers.
1051      *
1052      * for: filled-new-array, filled-new-array/range
1053      */
1054     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1055     /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1056     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1057     FETCH(r1, 1)                        @ r1<- BBBB
1058     ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1059     EXPORT_PC()                         @ need for resolve and alloc
1060     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1061     mov     r10, rINST, lsr #8          @ r10<- AA or BA
1062     cmp     r0, #0                      @ already resolved?
1063     bne     .LOP_FILLED_NEW_ARRAY_RANGE_continue        @ yes, continue on
1064 8:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1065     mov     r2, #0                      @ r2<- false
1066     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1067     bl      dvmResolveClass             @ r0<- call(clazz, ref)
1068     cmp     r0, #0                      @ got null?
1069     beq     common_exceptionThrown      @ yes, handle exception
1070     b       .LOP_FILLED_NEW_ARRAY_RANGE_continue
1071
1072
1073 /* ------------------------------ */
1074     .balign 64
1075 .L_OP_FILL_ARRAY_DATA: /* 0x26 */
1076 /* File: armv5te/OP_FILL_ARRAY_DATA.S */
1077     /* fill-array-data vAA, +BBBBBBBB */
1078     FETCH(r0, 1)                        @ r0<- bbbb (lo)
1079     FETCH(r1, 2)                        @ r1<- BBBB (hi)
1080     mov     r3, rINST, lsr #8           @ r3<- AA
1081     orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
1082     GET_VREG(r0, r3)                    @ r0<- vAA (array object)
1083     add     r1, rPC, r1, lsl #1         @ r1<- PC + BBBBbbbb*2 (array data off.)
1084     EXPORT_PC();
1085     bl      dvmInterpHandleFillArrayData@ fill the array with predefined data
1086     cmp     r0, #0                      @ 0 means an exception is thrown
1087     beq     common_exceptionThrown      @ has exception
1088     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
1089     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1090     GOTO_OPCODE(ip)                     @ jump to next instruction
1091
1092 /* ------------------------------ */
1093     .balign 64
1094 .L_OP_THROW: /* 0x27 */
1095 /* File: armv5te/OP_THROW.S */
1096     /*
1097      * Throw an exception object in the current thread.
1098      */
1099     /* throw vAA */
1100     mov     r2, rINST, lsr #8           @ r2<- AA
1101     GET_VREG(r1, r2)                    @ r1<- vAA (exception object)
1102     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
1103     EXPORT_PC()                         @ exception handler can throw
1104     cmp     r1, #0                      @ null object?
1105     beq     common_errNullObject        @ yes, throw an NPE instead
1106     @ bypass dvmSetException, just store it
1107     str     r1, [r0, #offThread_exception]  @ thread->exception<- obj
1108     b       common_exceptionThrown
1109
1110 /* ------------------------------ */
1111     .balign 64
1112 .L_OP_GOTO: /* 0x28 */
1113 /* File: armv5te/OP_GOTO.S */
1114     /*
1115      * Unconditional branch, 8-bit offset.
1116      *
1117      * The branch distance is a signed code-unit offset, which we need to
1118      * double to get a byte offset.
1119      */
1120     /* goto +AA */
1121     mov     r0, rINST, lsl #16          @ r0<- AAxx0000
1122     movs    r9, r0, asr #24             @ r9<- ssssssAA (sign-extended)
1123     mov     r9, r9, lsl #1              @ r9<- byte offset
1124     bmi     common_backwardBranch       @ backward branch, do periodic checks
1125 #if defined(WITH_JIT)
1126     GET_JIT_PROF_TABLE(r0)
1127     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1128     cmp     r0,#0
1129     bne     common_updateProfile
1130     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1131     GOTO_OPCODE(ip)                     @ jump to next instruction
1132 #else
1133     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1134     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1135     GOTO_OPCODE(ip)                     @ jump to next instruction
1136 #endif
1137
1138 /* ------------------------------ */
1139     .balign 64
1140 .L_OP_GOTO_16: /* 0x29 */
1141 /* File: armv5te/OP_GOTO_16.S */
1142     /*
1143      * Unconditional branch, 16-bit offset.
1144      *
1145      * The branch distance is a signed code-unit offset, which we need to
1146      * double to get a byte offset.
1147      */
1148     /* goto/16 +AAAA */
1149     FETCH_S(r0, 1)                      @ r0<- ssssAAAA (sign-extended)
1150     movs    r9, r0, asl #1              @ r9<- byte offset, check sign
1151     bmi     common_backwardBranch       @ backward branch, do periodic checks
1152 #if defined(WITH_JIT)
1153     GET_JIT_PROF_TABLE(r0)
1154     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1155     cmp     r0,#0
1156     bne     common_updateProfile
1157     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1158     GOTO_OPCODE(ip)                     @ jump to next instruction
1159 #else
1160     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1161     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1162     GOTO_OPCODE(ip)                     @ jump to next instruction
1163 #endif
1164
1165 /* ------------------------------ */
1166     .balign 64
1167 .L_OP_GOTO_32: /* 0x2a */
1168 /* File: armv5te/OP_GOTO_32.S */
1169     /*
1170      * Unconditional branch, 32-bit offset.
1171      *
1172      * The branch distance is a signed code-unit offset, which we need to
1173      * double to get a byte offset.
1174      *
1175      * Unlike most opcodes, this one is allowed to branch to itself, so
1176      * our "backward branch" test must be "<=0" instead of "<0".  The ORRS
1177      * instruction doesn't affect the V flag, so we need to clear it
1178      * explicitly.
1179      */
1180     /* goto/32 +AAAAAAAA */
1181     FETCH(r0, 1)                        @ r0<- aaaa (lo)
1182     FETCH(r1, 2)                        @ r1<- AAAA (hi)
1183     cmp     ip, ip                      @ (clear V flag during stall)
1184     orrs    r0, r0, r1, lsl #16         @ r0<- AAAAaaaa, check sign
1185     mov     r9, r0, asl #1              @ r9<- byte offset
1186     ble     common_backwardBranch       @ backward branch, do periodic checks
1187 #if defined(WITH_JIT)
1188     GET_JIT_PROF_TABLE(r0)
1189     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1190     cmp     r0,#0
1191     bne     common_updateProfile
1192     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1193     GOTO_OPCODE(ip)                     @ jump to next instruction
1194 #else
1195     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1196     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1197     GOTO_OPCODE(ip)                     @ jump to next instruction
1198 #endif
1199
1200 /* ------------------------------ */
1201     .balign 64
1202 .L_OP_PACKED_SWITCH: /* 0x2b */
1203 /* File: armv5te/OP_PACKED_SWITCH.S */
1204     /*
1205      * Handle a packed-switch or sparse-switch instruction.  In both cases
1206      * we decode it and hand it off to a helper function.
1207      *
1208      * We don't really expect backward branches in a switch statement, but
1209      * they're perfectly legal, so we check for them here.
1210      *
1211      * for: packed-switch, sparse-switch
1212      */
1213     /* op vAA, +BBBB */
1214     FETCH(r0, 1)                        @ r0<- bbbb (lo)
1215     FETCH(r1, 2)                        @ r1<- BBBB (hi)
1216     mov     r3, rINST, lsr #8           @ r3<- AA
1217     orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1218     GET_VREG(r1, r3)                    @ r1<- vAA
1219     add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1220     bl      dvmInterpHandlePackedSwitch                       @ r0<- code-unit branch offset
1221     movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1222     bmi     common_backwardBranch       @ backward branch, do periodic checks
1223     beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1224 #if defined(WITH_JIT)
1225     GET_JIT_PROF_TABLE(r0)
1226     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1227     cmp     r0,#0
1228     bne     common_updateProfile
1229     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1230     GOTO_OPCODE(ip)                     @ jump to next instruction
1231 #else
1232     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1233     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1234     GOTO_OPCODE(ip)                     @ jump to next instruction
1235 #endif
1236
1237 /* ------------------------------ */
1238     .balign 64
1239 .L_OP_SPARSE_SWITCH: /* 0x2c */
1240 /* File: armv5te/OP_SPARSE_SWITCH.S */
1241 /* File: armv5te/OP_PACKED_SWITCH.S */
1242     /*
1243      * Handle a packed-switch or sparse-switch instruction.  In both cases
1244      * we decode it and hand it off to a helper function.
1245      *
1246      * We don't really expect backward branches in a switch statement, but
1247      * they're perfectly legal, so we check for them here.
1248      *
1249      * for: packed-switch, sparse-switch
1250      */
1251     /* op vAA, +BBBB */
1252     FETCH(r0, 1)                        @ r0<- bbbb (lo)
1253     FETCH(r1, 2)                        @ r1<- BBBB (hi)
1254     mov     r3, rINST, lsr #8           @ r3<- AA
1255     orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1256     GET_VREG(r1, r3)                    @ r1<- vAA
1257     add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1258     bl      dvmInterpHandleSparseSwitch                       @ r0<- code-unit branch offset
1259     movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1260     bmi     common_backwardBranch       @ backward branch, do periodic checks
1261     beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1262 #if defined(WITH_JIT)
1263     GET_JIT_PROF_TABLE(r0)
1264     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1265     cmp     r0,#0
1266     bne     common_updateProfile
1267     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1268     GOTO_OPCODE(ip)                     @ jump to next instruction
1269 #else
1270     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1271     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1272     GOTO_OPCODE(ip)                     @ jump to next instruction
1273 #endif
1274
1275
1276 /* ------------------------------ */
1277     .balign 64
1278 .L_OP_CMPL_FLOAT: /* 0x2d */
1279 /* File: arm-vfp/OP_CMPL_FLOAT.S */
1280     /*
1281      * Compare two floating-point values.  Puts 0, 1, or -1 into the
1282      * destination register based on the results of the comparison.
1283      *
1284      * int compare(x, y) {
1285      *     if (x == y) {
1286      *         return 0;
1287      *     } else if (x > y) {
1288      *         return 1;
1289      *     } else if (x < y) {
1290      *         return -1;
1291      *     } else {
1292      *         return -1;
1293      *     }
1294      * }
1295      */
1296     /* op vAA, vBB, vCC */
1297     FETCH(r0, 1)                        @ r0<- CCBB
1298     mov     r9, rINST, lsr #8           @ r9<- AA
1299     and     r2, r0, #255                @ r2<- BB
1300     mov     r3, r0, lsr #8              @ r3<- CC
1301     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1302     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1303     flds    s0, [r2]                    @ s0<- vBB
1304     flds    s1, [r3]                    @ s1<- vCC
1305     fcmpes  s0, s1                      @ compare (vBB, vCC)
1306     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1307     mvn     r0, #0                      @ r0<- -1 (default)
1308     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1309     fmstat                              @ export status flags
1310     movgt   r0, #1                      @ (greater than) r1<- 1
1311     moveq   r0, #0                      @ (equal) r1<- 0
1312     b       .LOP_CMPL_FLOAT_finish          @ argh
1313
1314
1315 /* ------------------------------ */
1316     .balign 64
1317 .L_OP_CMPG_FLOAT: /* 0x2e */
1318 /* File: arm-vfp/OP_CMPG_FLOAT.S */
1319     /*
1320      * Compare two floating-point values.  Puts 0, 1, or -1 into the
1321      * destination register based on the results of the comparison.
1322      *
1323      * int compare(x, y) {
1324      *     if (x == y) {
1325      *         return 0;
1326      *     } else if (x < y) {
1327      *         return -1;
1328      *     } else if (x > y) {
1329      *         return 1;
1330      *     } else {
1331      *         return 1;
1332      *     }
1333      * }
1334      */
1335     /* op vAA, vBB, vCC */
1336     FETCH(r0, 1)                        @ r0<- CCBB
1337     mov     r9, rINST, lsr #8           @ r9<- AA
1338     and     r2, r0, #255                @ r2<- BB
1339     mov     r3, r0, lsr #8              @ r3<- CC
1340     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1341     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1342     flds    s0, [r2]                    @ s0<- vBB
1343     flds    s1, [r3]                    @ s1<- vCC
1344     fcmpes  s0, s1                      @ compare (vBB, vCC)
1345     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1346     mov     r0, #1                      @ r0<- 1 (default)
1347     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1348     fmstat                              @ export status flags
1349     mvnmi   r0, #0                      @ (less than) r1<- -1
1350     moveq   r0, #0                      @ (equal) r1<- 0
1351     b       .LOP_CMPG_FLOAT_finish          @ argh
1352
1353
1354 /* ------------------------------ */
1355     .balign 64
1356 .L_OP_CMPL_DOUBLE: /* 0x2f */
1357 /* File: arm-vfp/OP_CMPL_DOUBLE.S */
1358     /*
1359      * Compare two floating-point values.  Puts 0, 1, or -1 into the
1360      * destination register based on the results of the comparison.
1361      *
1362      * int compare(x, y) {
1363      *     if (x == y) {
1364      *         return 0;
1365      *     } else if (x > y) {
1366      *         return 1;
1367      *     } else if (x < y) {
1368      *         return -1;
1369      *     } else {
1370      *         return -1;
1371      *     }
1372      * }
1373      */
1374     /* op vAA, vBB, vCC */
1375     FETCH(r0, 1)                        @ r0<- CCBB
1376     mov     r9, rINST, lsr #8           @ r9<- AA
1377     and     r2, r0, #255                @ r2<- BB
1378     mov     r3, r0, lsr #8              @ r3<- CC
1379     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1380     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1381     fldd    d0, [r2]                    @ d0<- vBB
1382     fldd    d1, [r3]                    @ d1<- vCC
1383     fcmped  d0, d1                      @ compare (vBB, vCC)
1384     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1385     mvn     r0, #0                      @ r0<- -1 (default)
1386     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1387     fmstat                              @ export status flags
1388     movgt   r0, #1                      @ (greater than) r1<- 1
1389     moveq   r0, #0                      @ (equal) r1<- 0
1390     b       .LOP_CMPL_DOUBLE_finish          @ argh
1391
1392
1393 /* ------------------------------ */
1394     .balign 64
1395 .L_OP_CMPG_DOUBLE: /* 0x30 */
1396 /* File: arm-vfp/OP_CMPG_DOUBLE.S */
1397     /*
1398      * Compare two floating-point values.  Puts 0, 1, or -1 into the
1399      * destination register based on the results of the comparison.
1400      *
1401      * int compare(x, y) {
1402      *     if (x == y) {
1403      *         return 0;
1404      *     } else if (x < y) {
1405      *         return -1;
1406      *     } else if (x > y) {
1407      *         return 1;
1408      *     } else {
1409      *         return 1;
1410      *     }
1411      * }
1412      */
1413     /* op vAA, vBB, vCC */
1414     FETCH(r0, 1)                        @ r0<- CCBB
1415     mov     r9, rINST, lsr #8           @ r9<- AA
1416     and     r2, r0, #255                @ r2<- BB
1417     mov     r3, r0, lsr #8              @ r3<- CC
1418     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1419     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1420     fldd    d0, [r2]                    @ d0<- vBB
1421     fldd    d1, [r3]                    @ d1<- vCC
1422     fcmped  d0, d1                      @ compare (vBB, vCC)
1423     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1424     mov     r0, #1                      @ r0<- 1 (default)
1425     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1426     fmstat                              @ export status flags
1427     mvnmi   r0, #0                      @ (less than) r1<- -1
1428     moveq   r0, #0                      @ (equal) r1<- 0
1429     b       .LOP_CMPG_DOUBLE_finish          @ argh
1430
1431
1432 /* ------------------------------ */
1433     .balign 64
1434 .L_OP_CMP_LONG: /* 0x31 */
1435 /* File: armv5te/OP_CMP_LONG.S */
1436     /*
1437      * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
1438      * register based on the results of the comparison.
1439      *
1440      * We load the full values with LDM, but in practice many values could
1441      * be resolved by only looking at the high word.  This could be made
1442      * faster or slower by splitting the LDM into a pair of LDRs.
1443      *
1444      * If we just wanted to set condition flags, we could do this:
1445      *  subs    ip, r0, r2
1446      *  sbcs    ip, r1, r3
1447      *  subeqs  ip, r0, r2
1448      * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
1449      * integer value, which we can do with 2 conditional mov/mvn instructions
1450      * (set 1, set -1; if they're equal we already have 0 in ip), giving
1451      * us a constant 5-cycle path plus a branch at the end to the
1452      * instruction epilogue code.  The multi-compare approach below needs
1453      * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
1454      * in the worst case (the 64-bit values are equal).
1455      */
1456     /* cmp-long vAA, vBB, vCC */
1457     FETCH(r0, 1)                        @ r0<- CCBB
1458     mov     r9, rINST, lsr #8           @ r9<- AA
1459     and     r2, r0, #255                @ r2<- BB
1460     mov     r3, r0, lsr #8              @ r3<- CC
1461     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
1462     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
1463     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1464     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
1465     cmp     r1, r3                      @ compare (vBB+1, vCC+1)
1466     blt     .LOP_CMP_LONG_less            @ signed compare on high part
1467     bgt     .LOP_CMP_LONG_greater
1468     subs    r1, r0, r2                  @ r1<- r0 - r2
1469     bhi     .LOP_CMP_LONG_greater         @ unsigned compare on low part
1470     bne     .LOP_CMP_LONG_less
1471     b       .LOP_CMP_LONG_finish          @ equal; r1 already holds 0
1472
1473 /* ------------------------------ */
1474     .balign 64
1475 .L_OP_IF_EQ: /* 0x32 */
1476 /* File: armv5te/OP_IF_EQ.S */
1477 /* File: armv5te/bincmp.S */
1478     /*
1479      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1480      * fragment that specifies the *reverse* comparison to perform, e.g.
1481      * for "if-le" you would use "gt".
1482      *
1483      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1484      */
1485     /* if-cmp vA, vB, +CCCC */
1486     mov     r0, rINST, lsr #8           @ r0<- A+
1487     mov     r1, rINST, lsr #12          @ r1<- B
1488     and     r0, r0, #15
1489     GET_VREG(r3, r1)                    @ r3<- vB
1490     GET_VREG(r2, r0)                    @ r2<- vA
1491     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1492     cmp     r2, r3                      @ compare (vA, vB)
1493     bne  1f                      @ branch to 1 if comparison failed
1494     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1495     movs    r9, r9, asl #1              @ convert to bytes, check sign
1496     bmi     common_backwardBranch       @ yes, do periodic checks
1497 1:
1498 #if defined(WITH_JIT)
1499     GET_JIT_PROF_TABLE(r0)
1500     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1501     b        common_testUpdateProfile
1502 #else
1503     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1504     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1505     GOTO_OPCODE(ip)                     @ jump to next instruction
1506 #endif
1507
1508
1509 /* ------------------------------ */
1510     .balign 64
1511 .L_OP_IF_NE: /* 0x33 */
1512 /* File: armv5te/OP_IF_NE.S */
1513 /* File: armv5te/bincmp.S */
1514     /*
1515      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1516      * fragment that specifies the *reverse* comparison to perform, e.g.
1517      * for "if-le" you would use "gt".
1518      *
1519      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1520      */
1521     /* if-cmp vA, vB, +CCCC */
1522     mov     r0, rINST, lsr #8           @ r0<- A+
1523     mov     r1, rINST, lsr #12          @ r1<- B
1524     and     r0, r0, #15
1525     GET_VREG(r3, r1)                    @ r3<- vB
1526     GET_VREG(r2, r0)                    @ r2<- vA
1527     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1528     cmp     r2, r3                      @ compare (vA, vB)
1529     beq  1f                      @ branch to 1 if comparison failed
1530     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1531     movs    r9, r9, asl #1              @ convert to bytes, check sign
1532     bmi     common_backwardBranch       @ yes, do periodic checks
1533 1:
1534 #if defined(WITH_JIT)
1535     GET_JIT_PROF_TABLE(r0)
1536     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1537     b        common_testUpdateProfile
1538 #else
1539     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1540     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1541     GOTO_OPCODE(ip)                     @ jump to next instruction
1542 #endif
1543
1544
1545 /* ------------------------------ */
1546     .balign 64
1547 .L_OP_IF_LT: /* 0x34 */
1548 /* File: armv5te/OP_IF_LT.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     bge  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
1569 1:
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     .balign 64
1583 .L_OP_IF_GE: /* 0x35 */
1584 /* File: armv5te/OP_IF_GE.S */
1585 /* File: armv5te/bincmp.S */
1586     /*
1587      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1588      * fragment that specifies the *reverse* comparison to perform, e.g.
1589      * for "if-le" you would use "gt".
1590      *
1591      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1592      */
1593     /* if-cmp vA, vB, +CCCC */
1594     mov     r0, rINST, lsr #8           @ r0<- A+
1595     mov     r1, rINST, lsr #12          @ r1<- B
1596     and     r0, r0, #15
1597     GET_VREG(r3, r1)                    @ r3<- vB
1598     GET_VREG(r2, r0)                    @ r2<- vA
1599     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1600     cmp     r2, r3                      @ compare (vA, vB)
1601     blt  1f                      @ branch to 1 if comparison failed
1602     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1603     movs    r9, r9, asl #1              @ convert to bytes, check sign
1604     bmi     common_backwardBranch       @ yes, do periodic checks
1605 1:
1606 #if defined(WITH_JIT)
1607     GET_JIT_PROF_TABLE(r0)
1608     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1609     b        common_testUpdateProfile
1610 #else
1611     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1612     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1613     GOTO_OPCODE(ip)                     @ jump to next instruction
1614 #endif
1615
1616
1617 /* ------------------------------ */
1618     .balign 64
1619 .L_OP_IF_GT: /* 0x36 */
1620 /* File: armv5te/OP_IF_GT.S */
1621 /* File: armv5te/bincmp.S */
1622     /*
1623      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1624      * fragment that specifies the *reverse* comparison to perform, e.g.
1625      * for "if-le" you would use "gt".
1626      *
1627      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1628      */
1629     /* if-cmp vA, vB, +CCCC */
1630     mov     r0, rINST, lsr #8           @ r0<- A+
1631     mov     r1, rINST, lsr #12          @ r1<- B
1632     and     r0, r0, #15
1633     GET_VREG(r3, r1)                    @ r3<- vB
1634     GET_VREG(r2, r0)                    @ r2<- vA
1635     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1636     cmp     r2, r3                      @ compare (vA, vB)
1637     ble  1f                      @ branch to 1 if comparison failed
1638     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1639     movs    r9, r9, asl #1              @ convert to bytes, check sign
1640     bmi     common_backwardBranch       @ yes, do periodic checks
1641 1:
1642 #if defined(WITH_JIT)
1643     GET_JIT_PROF_TABLE(r0)
1644     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1645     b        common_testUpdateProfile
1646 #else
1647     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1648     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1649     GOTO_OPCODE(ip)                     @ jump to next instruction
1650 #endif
1651
1652
1653 /* ------------------------------ */
1654     .balign 64
1655 .L_OP_IF_LE: /* 0x37 */
1656 /* File: armv5te/OP_IF_LE.S */
1657 /* File: armv5te/bincmp.S */
1658     /*
1659      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1660      * fragment that specifies the *reverse* comparison to perform, e.g.
1661      * for "if-le" you would use "gt".
1662      *
1663      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1664      */
1665     /* if-cmp vA, vB, +CCCC */
1666     mov     r0, rINST, lsr #8           @ r0<- A+
1667     mov     r1, rINST, lsr #12          @ r1<- B
1668     and     r0, r0, #15
1669     GET_VREG(r3, r1)                    @ r3<- vB
1670     GET_VREG(r2, r0)                    @ r2<- vA
1671     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1672     cmp     r2, r3                      @ compare (vA, vB)
1673     bgt  1f                      @ branch to 1 if comparison failed
1674     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1675     movs    r9, r9, asl #1              @ convert to bytes, check sign
1676     bmi     common_backwardBranch       @ yes, do periodic checks
1677 1:
1678 #if defined(WITH_JIT)
1679     GET_JIT_PROF_TABLE(r0)
1680     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1681     b        common_testUpdateProfile
1682 #else
1683     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1684     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1685     GOTO_OPCODE(ip)                     @ jump to next instruction
1686 #endif
1687
1688
1689 /* ------------------------------ */
1690     .balign 64
1691 .L_OP_IF_EQZ: /* 0x38 */
1692 /* File: armv5te/OP_IF_EQZ.S */
1693 /* File: armv5te/zcmp.S */
1694     /*
1695      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1696      * fragment that specifies the *reverse* comparison to perform, e.g.
1697      * for "if-le" you would use "gt".
1698      *
1699      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1700      */
1701     /* if-cmp vAA, +BBBB */
1702     mov     r0, rINST, lsr #8           @ r0<- AA
1703     GET_VREG(r2, r0)                    @ r2<- vAA
1704     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1705     cmp     r2, #0                      @ compare (vA, 0)
1706     bne  1f                      @ branch to 1 if comparison failed
1707     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1708     movs    r9, r9, asl #1              @ convert to bytes, check sign
1709     bmi     common_backwardBranch       @ backward branch, do periodic checks
1710 1:
1711 #if defined(WITH_JIT)
1712     GET_JIT_PROF_TABLE(r0)
1713     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1714     cmp     r0,#0
1715     bne     common_updateProfile
1716     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1717     GOTO_OPCODE(ip)                     @ jump to next instruction
1718 #else
1719     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1720     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1721     GOTO_OPCODE(ip)                     @ jump to next instruction
1722 #endif
1723
1724
1725 /* ------------------------------ */
1726     .balign 64
1727 .L_OP_IF_NEZ: /* 0x39 */
1728 /* File: armv5te/OP_IF_NEZ.S */
1729 /* File: armv5te/zcmp.S */
1730     /*
1731      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1732      * fragment that specifies the *reverse* comparison to perform, e.g.
1733      * for "if-le" you would use "gt".
1734      *
1735      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1736      */
1737     /* if-cmp vAA, +BBBB */
1738     mov     r0, rINST, lsr #8           @ r0<- AA
1739     GET_VREG(r2, r0)                    @ r2<- vAA
1740     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1741     cmp     r2, #0                      @ compare (vA, 0)
1742     beq  1f                      @ branch to 1 if comparison failed
1743     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1744     movs    r9, r9, asl #1              @ convert to bytes, check sign
1745     bmi     common_backwardBranch       @ backward branch, do periodic checks
1746 1:
1747 #if defined(WITH_JIT)
1748     GET_JIT_PROF_TABLE(r0)
1749     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1750     cmp     r0,#0
1751     bne     common_updateProfile
1752     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1753     GOTO_OPCODE(ip)                     @ jump to next instruction
1754 #else
1755     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1756     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1757     GOTO_OPCODE(ip)                     @ jump to next instruction
1758 #endif
1759
1760
1761 /* ------------------------------ */
1762     .balign 64
1763 .L_OP_IF_LTZ: /* 0x3a */
1764 /* File: armv5te/OP_IF_LTZ.S */
1765 /* File: armv5te/zcmp.S */
1766     /*
1767      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1768      * fragment that specifies the *reverse* comparison to perform, e.g.
1769      * for "if-le" you would use "gt".
1770      *
1771      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1772      */
1773     /* if-cmp vAA, +BBBB */
1774     mov     r0, rINST, lsr #8           @ r0<- AA
1775     GET_VREG(r2, r0)                    @ r2<- vAA
1776     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1777     cmp     r2, #0                      @ compare (vA, 0)
1778     bge  1f                      @ branch to 1 if comparison failed
1779     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1780     movs    r9, r9, asl #1              @ convert to bytes, check sign
1781     bmi     common_backwardBranch       @ backward branch, do periodic checks
1782 1:
1783 #if defined(WITH_JIT)
1784     GET_JIT_PROF_TABLE(r0)
1785     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1786     cmp     r0,#0
1787     bne     common_updateProfile
1788     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1789     GOTO_OPCODE(ip)                     @ jump to next instruction
1790 #else
1791     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1792     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1793     GOTO_OPCODE(ip)                     @ jump to next instruction
1794 #endif
1795
1796
1797 /* ------------------------------ */
1798     .balign 64
1799 .L_OP_IF_GEZ: /* 0x3b */
1800 /* File: armv5te/OP_IF_GEZ.S */
1801 /* File: armv5te/zcmp.S */
1802     /*
1803      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1804      * fragment that specifies the *reverse* comparison to perform, e.g.
1805      * for "if-le" you would use "gt".
1806      *
1807      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1808      */
1809     /* if-cmp vAA, +BBBB */
1810     mov     r0, rINST, lsr #8           @ r0<- AA
1811     GET_VREG(r2, r0)                    @ r2<- vAA
1812     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1813     cmp     r2, #0                      @ compare (vA, 0)
1814     blt  1f                      @ branch to 1 if comparison failed
1815     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1816     movs    r9, r9, asl #1              @ convert to bytes, check sign
1817     bmi     common_backwardBranch       @ backward branch, do periodic checks
1818 1:
1819 #if defined(WITH_JIT)
1820     GET_JIT_PROF_TABLE(r0)
1821     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1822     cmp     r0,#0
1823     bne     common_updateProfile
1824     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1825     GOTO_OPCODE(ip)                     @ jump to next instruction
1826 #else
1827     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1828     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1829     GOTO_OPCODE(ip)                     @ jump to next instruction
1830 #endif
1831
1832
1833 /* ------------------------------ */
1834     .balign 64
1835 .L_OP_IF_GTZ: /* 0x3c */
1836 /* File: armv5te/OP_IF_GTZ.S */
1837 /* File: armv5te/zcmp.S */
1838     /*
1839      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1840      * fragment that specifies the *reverse* comparison to perform, e.g.
1841      * for "if-le" you would use "gt".
1842      *
1843      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1844      */
1845     /* if-cmp vAA, +BBBB */
1846     mov     r0, rINST, lsr #8           @ r0<- AA
1847     GET_VREG(r2, r0)                    @ r2<- vAA
1848     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1849     cmp     r2, #0                      @ compare (vA, 0)
1850     ble  1f                      @ branch to 1 if comparison failed
1851     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1852     movs    r9, r9, asl #1              @ convert to bytes, check sign
1853     bmi     common_backwardBranch       @ backward branch, do periodic checks
1854 1:
1855 #if defined(WITH_JIT)
1856     GET_JIT_PROF_TABLE(r0)
1857     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1858     cmp     r0,#0
1859     bne     common_updateProfile
1860     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1861     GOTO_OPCODE(ip)                     @ jump to next instruction
1862 #else
1863     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1864     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1865     GOTO_OPCODE(ip)                     @ jump to next instruction
1866 #endif
1867
1868
1869 /* ------------------------------ */
1870     .balign 64
1871 .L_OP_IF_LEZ: /* 0x3d */
1872 /* File: armv5te/OP_IF_LEZ.S */
1873 /* File: armv5te/zcmp.S */
1874     /*
1875      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1876      * fragment that specifies the *reverse* comparison to perform, e.g.
1877      * for "if-le" you would use "gt".
1878      *
1879      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1880      */
1881     /* if-cmp vAA, +BBBB */
1882     mov     r0, rINST, lsr #8           @ r0<- AA
1883     GET_VREG(r2, r0)                    @ r2<- vAA
1884     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1885     cmp     r2, #0                      @ compare (vA, 0)
1886     bgt  1f                      @ branch to 1 if comparison failed
1887     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1888     movs    r9, r9, asl #1              @ convert to bytes, check sign
1889     bmi     common_backwardBranch       @ backward branch, do periodic checks
1890 1:
1891 #if defined(WITH_JIT)
1892     GET_JIT_PROF_TABLE(r0)
1893     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1894     cmp     r0,#0
1895     bne     common_updateProfile
1896     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1897     GOTO_OPCODE(ip)                     @ jump to next instruction
1898 #else
1899     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1900     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1901     GOTO_OPCODE(ip)                     @ jump to next instruction
1902 #endif
1903
1904
1905 /* ------------------------------ */
1906     .balign 64
1907 .L_OP_UNUSED_3E: /* 0x3e */
1908 /* File: armv5te/OP_UNUSED_3E.S */
1909 /* File: armv5te/unused.S */
1910     bl      common_abort
1911
1912
1913 /* ------------------------------ */
1914     .balign 64
1915 .L_OP_UNUSED_3F: /* 0x3f */
1916 /* File: armv5te/OP_UNUSED_3F.S */
1917 /* File: armv5te/unused.S */
1918     bl      common_abort
1919
1920
1921 /* ------------------------------ */
1922     .balign 64
1923 .L_OP_UNUSED_40: /* 0x40 */
1924 /* File: armv5te/OP_UNUSED_40.S */
1925 /* File: armv5te/unused.S */
1926     bl      common_abort
1927
1928
1929 /* ------------------------------ */
1930     .balign 64
1931 .L_OP_UNUSED_41: /* 0x41 */
1932 /* File: armv5te/OP_UNUSED_41.S */
1933 /* File: armv5te/unused.S */
1934     bl      common_abort
1935
1936
1937 /* ------------------------------ */
1938     .balign 64
1939 .L_OP_UNUSED_42: /* 0x42 */
1940 /* File: armv5te/OP_UNUSED_42.S */
1941 /* File: armv5te/unused.S */
1942     bl      common_abort
1943
1944
1945 /* ------------------------------ */
1946     .balign 64
1947 .L_OP_UNUSED_43: /* 0x43 */
1948 /* File: armv5te/OP_UNUSED_43.S */
1949 /* File: armv5te/unused.S */
1950     bl      common_abort
1951
1952
1953 /* ------------------------------ */
1954     .balign 64
1955 .L_OP_AGET: /* 0x44 */
1956 /* File: armv5te/OP_AGET.S */
1957     /*
1958      * Array get, 32 bits or less.  vAA <- vBB[vCC].
1959      *
1960      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
1961      * instructions.  We use a pair of FETCH_Bs instead.
1962      *
1963      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1964      */
1965     /* op vAA, vBB, vCC */
1966     FETCH_B(r2, 1, 0)                   @ r2<- BB
1967     mov     r9, rINST, lsr #8           @ r9<- AA
1968     FETCH_B(r3, 1, 1)                   @ r3<- CC
1969     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
1970     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
1971     cmp     r0, #0                      @ null array object?
1972     beq     common_errNullObject        @ yes, bail
1973     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
1974     add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
1975     cmp     r1, r3                      @ compare unsigned index, length
1976     bcs     common_errArrayIndex        @ index >= length, bail
1977     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1978     ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
1979     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1980     SET_VREG(r2, r9)                    @ vAA<- r2
1981     GOTO_OPCODE(ip)                     @ jump to next instruction
1982
1983 /* ------------------------------ */
1984     .balign 64
1985 .L_OP_AGET_WIDE: /* 0x45 */
1986 /* File: armv5te/OP_AGET_WIDE.S */
1987     /*
1988      * Array get, 64 bits.  vAA <- vBB[vCC].
1989      *
1990      * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD.
1991      */
1992     /* aget-wide vAA, vBB, vCC */
1993     FETCH(r0, 1)                        @ r0<- CCBB
1994     mov     r9, rINST, lsr #8           @ r9<- AA
1995     and     r2, r0, #255                @ r2<- BB
1996     mov     r3, r0, lsr #8              @ r3<- CC
1997     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
1998     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
1999     cmp     r0, #0                      @ null array object?
2000     beq     common_errNullObject        @ yes, bail
2001     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2002     add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2003     cmp     r1, r3                      @ compare unsigned index, length
2004     bcc     .LOP_AGET_WIDE_finish          @ okay, continue below
2005     b       common_errArrayIndex        @ index >= length, bail
2006     @ May want to swap the order of these two branches depending on how the
2007     @ branch prediction (if any) handles conditional forward branches vs.
2008     @ unconditional forward branches.
2009
2010 /* ------------------------------ */
2011     .balign 64
2012 .L_OP_AGET_OBJECT: /* 0x46 */
2013 /* File: armv5te/OP_AGET_OBJECT.S */
2014 /* File: armv5te/OP_AGET.S */
2015     /*
2016      * Array get, 32 bits or less.  vAA <- vBB[vCC].
2017      *
2018      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2019      * instructions.  We use a pair of FETCH_Bs instead.
2020      *
2021      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2022      */
2023     /* op vAA, vBB, vCC */
2024     FETCH_B(r2, 1, 0)                   @ r2<- BB
2025     mov     r9, rINST, lsr #8           @ r9<- AA
2026     FETCH_B(r3, 1, 1)                   @ r3<- CC
2027     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2028     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2029     cmp     r0, #0                      @ null array object?
2030     beq     common_errNullObject        @ yes, bail
2031     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2032     add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2033     cmp     r1, r3                      @ compare unsigned index, length
2034     bcs     common_errArrayIndex        @ index >= length, bail
2035     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2036     ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2037     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2038     SET_VREG(r2, r9)                    @ vAA<- r2
2039     GOTO_OPCODE(ip)                     @ jump to next instruction
2040
2041
2042 /* ------------------------------ */
2043     .balign 64
2044 .L_OP_AGET_BOOLEAN: /* 0x47 */
2045 /* File: armv5te/OP_AGET_BOOLEAN.S */
2046 /* File: armv5te/OP_AGET.S */
2047     /*
2048      * Array get, 32 bits or less.  vAA <- vBB[vCC].
2049      *
2050      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2051      * instructions.  We use a pair of FETCH_Bs instead.
2052      *
2053      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2054      */
2055     /* op vAA, vBB, vCC */
2056     FETCH_B(r2, 1, 0)                   @ r2<- BB
2057     mov     r9, rINST, lsr #8           @ r9<- AA
2058     FETCH_B(r3, 1, 1)                   @ r3<- CC
2059     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2060     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2061     cmp     r0, #0                      @ null array object?
2062     beq     common_errNullObject        @ yes, bail
2063     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2064     add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2065     cmp     r1, r3                      @ compare unsigned index, length
2066     bcs     common_errArrayIndex        @ index >= length, bail
2067     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2068     ldrb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2069     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2070     SET_VREG(r2, r9)                    @ vAA<- r2
2071     GOTO_OPCODE(ip)                     @ jump to next instruction
2072
2073
2074 /* ------------------------------ */
2075     .balign 64
2076 .L_OP_AGET_BYTE: /* 0x48 */
2077 /* File: armv5te/OP_AGET_BYTE.S */
2078 /* File: armv5te/OP_AGET.S */
2079     /*
2080      * Array get, 32 bits or less.  vAA <- vBB[vCC].
2081      *
2082      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2083      * instructions.  We use a pair of FETCH_Bs instead.
2084      *
2085      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2086      */
2087     /* op vAA, vBB, vCC */
2088     FETCH_B(r2, 1, 0)                   @ r2<- BB
2089     mov     r9, rINST, lsr #8           @ r9<- AA
2090     FETCH_B(r3, 1, 1)                   @ r3<- CC
2091     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2092     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2093     cmp     r0, #0                      @ null array object?
2094     beq     common_errNullObject        @ yes, bail
2095     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2096     add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2097     cmp     r1, r3                      @ compare unsigned index, length
2098     bcs     common_errArrayIndex        @ index >= length, bail
2099     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2100     ldrsb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2101     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2102     SET_VREG(r2, r9)                    @ vAA<- r2
2103     GOTO_OPCODE(ip)                     @ jump to next instruction
2104
2105
2106 /* ------------------------------ */
2107     .balign 64
2108 .L_OP_AGET_CHAR: /* 0x49 */
2109 /* File: armv5te/OP_AGET_CHAR.S */
2110 /* File: armv5te/OP_AGET.S */
2111     /*
2112      * Array get, 32 bits or less.  vAA <- vBB[vCC].
2113      *
2114      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2115      * instructions.  We use a pair of FETCH_Bs instead.
2116      *
2117      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2118      */
2119     /* op vAA, vBB, vCC */
2120     FETCH_B(r2, 1, 0)                   @ r2<- BB
2121     mov     r9, rINST, lsr #8           @ r9<- AA
2122     FETCH_B(r3, 1, 1)                   @ r3<- CC
2123     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2124     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2125     cmp     r0, #0                      @ null array object?
2126     beq     common_errNullObject        @ yes, bail
2127     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2128     add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2129     cmp     r1, r3                      @ compare unsigned index, length
2130     bcs     common_errArrayIndex        @ index >= length, bail
2131     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2132     ldrh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2133     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2134     SET_VREG(r2, r9)                    @ vAA<- r2
2135     GOTO_OPCODE(ip)                     @ jump to next instruction
2136
2137
2138 /* ------------------------------ */
2139     .balign 64
2140 .L_OP_AGET_SHORT: /* 0x4a */
2141 /* File: armv5te/OP_AGET_SHORT.S */
2142 /* File: armv5te/OP_AGET.S */
2143     /*
2144      * Array get, 32 bits or less.  vAA <- vBB[vCC].
2145      *
2146      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2147      * instructions.  We use a pair of FETCH_Bs instead.
2148      *
2149      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2150      */
2151     /* op vAA, vBB, vCC */
2152     FETCH_B(r2, 1, 0)                   @ r2<- BB
2153     mov     r9, rINST, lsr #8           @ r9<- AA
2154     FETCH_B(r3, 1, 1)                   @ r3<- CC
2155     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2156     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2157     cmp     r0, #0                      @ null array object?
2158     beq     common_errNullObject        @ yes, bail
2159     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2160     add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2161     cmp     r1, r3                      @ compare unsigned index, length
2162     bcs     common_errArrayIndex        @ index >= length, bail
2163     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2164     ldrsh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2165     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2166     SET_VREG(r2, r9)                    @ vAA<- r2
2167     GOTO_OPCODE(ip)                     @ jump to next instruction
2168
2169
2170 /* ------------------------------ */
2171     .balign 64
2172 .L_OP_APUT: /* 0x4b */
2173 /* File: armv5te/OP_APUT.S */
2174     /*
2175      * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2176      *
2177      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2178      * instructions.  We use a pair of FETCH_Bs instead.
2179      *
2180      * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2181      */
2182     /* op vAA, vBB, vCC */
2183     FETCH_B(r2, 1, 0)                   @ r2<- BB
2184     mov     r9, rINST, lsr #8           @ r9<- AA
2185     FETCH_B(r3, 1, 1)                   @ r3<- CC
2186     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2187     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2188     cmp     r0, #0                      @ null array object?
2189     beq     common_errNullObject        @ yes, bail
2190     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2191     add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2192     cmp     r1, r3                      @ compare unsigned index, length
2193     bcs     common_errArrayIndex        @ index >= length, bail
2194     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2195     GET_VREG(r2, r9)                    @ r2<- vAA
2196     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2197     str  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2198     GOTO_OPCODE(ip)                     @ jump to next instruction
2199
2200 /* ------------------------------ */
2201     .balign 64
2202 .L_OP_APUT_WIDE: /* 0x4c */
2203 /* File: armv5te/OP_APUT_WIDE.S */
2204     /*
2205      * Array put, 64 bits.  vBB[vCC] <- vAA.
2206      *
2207      * Arrays of long/double are 64-bit aligned, so it's okay to use STRD.
2208      */
2209     /* aput-wide vAA, vBB, vCC */
2210     FETCH(r0, 1)                        @ r0<- CCBB
2211     mov     r9, rINST, lsr #8           @ r9<- AA
2212     and     r2, r0, #255                @ r2<- BB
2213     mov     r3, r0, lsr #8              @ r3<- CC
2214     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2215     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2216     cmp     r0, #0                      @ null array object?
2217     beq     common_errNullObject        @ yes, bail
2218     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2219     add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2220     cmp     r1, r3                      @ compare unsigned index, length
2221     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2222     bcc     .LOP_APUT_WIDE_finish          @ okay, continue below
2223     b       common_errArrayIndex        @ index >= length, bail
2224     @ May want to swap the order of these two branches depending on how the
2225     @ branch prediction (if any) handles conditional forward branches vs.
2226     @ unconditional forward branches.
2227
2228 /* ------------------------------ */
2229     .balign 64
2230 .L_OP_APUT_OBJECT: /* 0x4d */
2231 /* File: armv5te/OP_APUT_OBJECT.S */
2232     /*
2233      * Store an object into an array.  vBB[vCC] <- vAA.
2234      */
2235     /* op vAA, vBB, vCC */
2236     FETCH(r0, 1)                        @ r0<- CCBB
2237     mov     r9, rINST, lsr #8           @ r9<- AA
2238     and     r2, r0, #255                @ r2<- BB
2239     mov     r3, r0, lsr #8              @ r3<- CC
2240     GET_VREG(rINST, r2)                 @ rINST<- vBB (array object)
2241     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2242     cmp     rINST, #0                   @ null array object?
2243     GET_VREG(r9, r9)                    @ r9<- vAA
2244     beq     common_errNullObject        @ yes, bail
2245     ldr     r3, [rINST, #offArrayObject_length]   @ r3<- arrayObj->length
2246     add     r10, rINST, r1, lsl #2      @ r10<- arrayObj + index*width
2247     cmp     r1, r3                      @ compare unsigned index, length
2248     bcc     .LOP_APUT_OBJECT_finish          @ we're okay, continue on
2249     b       common_errArrayIndex        @ index >= length, bail
2250
2251
2252 /* ------------------------------ */
2253     .balign 64
2254 .L_OP_APUT_BOOLEAN: /* 0x4e */
2255 /* File: armv5te/OP_APUT_BOOLEAN.S */
2256 /* File: armv5te/OP_APUT.S */
2257     /*
2258      * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2259      *
2260      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2261      * instructions.  We use a pair of FETCH_Bs instead.
2262      *
2263      * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2264      */
2265     /* op vAA, vBB, vCC */
2266     FETCH_B(r2, 1, 0)                   @ r2<- BB
2267     mov     r9, rINST, lsr #8           @ r9<- AA
2268     FETCH_B(r3, 1, 1)                   @ r3<- CC
2269     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2270     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2271     cmp     r0, #0                      @ null array object?
2272     beq     common_errNullObject        @ yes, bail
2273     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2274     add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2275     cmp     r1, r3                      @ compare unsigned index, length
2276     bcs     common_errArrayIndex        @ index >= length, bail
2277     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2278     GET_VREG(r2, r9)                    @ r2<- vAA
2279     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2280     strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2281     GOTO_OPCODE(ip)                     @ jump to next instruction
2282
2283
2284 /* ------------------------------ */
2285     .balign 64
2286 .L_OP_APUT_BYTE: /* 0x4f */
2287 /* File: armv5te/OP_APUT_BYTE.S */
2288 /* File: armv5te/OP_APUT.S */
2289     /*
2290      * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2291      *
2292      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2293      * instructions.  We use a pair of FETCH_Bs instead.
2294      *
2295      * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2296      */
2297     /* op vAA, vBB, vCC */
2298     FETCH_B(r2, 1, 0)                   @ r2<- BB
2299     mov     r9, rINST, lsr #8           @ r9<- AA
2300     FETCH_B(r3, 1, 1)                   @ r3<- CC
2301     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2302     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2303     cmp     r0, #0                      @ null array object?
2304     beq     common_errNullObject        @ yes, bail
2305     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2306     add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2307     cmp     r1, r3                      @ compare unsigned index, length
2308     bcs     common_errArrayIndex        @ index >= length, bail
2309     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2310     GET_VREG(r2, r9)                    @ r2<- vAA
2311     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2312     strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2313     GOTO_OPCODE(ip)                     @ jump to next instruction
2314
2315
2316 /* ------------------------------ */
2317     .balign 64
2318 .L_OP_APUT_CHAR: /* 0x50 */
2319 /* File: armv5te/OP_APUT_CHAR.S */
2320 /* File: armv5te/OP_APUT.S */
2321     /*
2322      * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2323      *
2324      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2325      * instructions.  We use a pair of FETCH_Bs instead.
2326      *
2327      * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2328      */
2329     /* op vAA, vBB, vCC */
2330     FETCH_B(r2, 1, 0)                   @ r2<- BB
2331     mov     r9, rINST, lsr #8           @ r9<- AA
2332     FETCH_B(r3, 1, 1)                   @ r3<- CC
2333     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2334     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2335     cmp     r0, #0                      @ null array object?
2336     beq     common_errNullObject        @ yes, bail
2337     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2338     add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2339     cmp     r1, r3                      @ compare unsigned index, length
2340     bcs     common_errArrayIndex        @ index >= length, bail
2341     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2342     GET_VREG(r2, r9)                    @ r2<- vAA
2343     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2344     strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2345     GOTO_OPCODE(ip)                     @ jump to next instruction
2346
2347
2348 /* ------------------------------ */
2349     .balign 64
2350 .L_OP_APUT_SHORT: /* 0x51 */
2351 /* File: armv5te/OP_APUT_SHORT.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 #1     @ 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     strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2377     GOTO_OPCODE(ip)                     @ jump to next instruction
2378
2379
2380 /* ------------------------------ */
2381     .balign 64
2382 .L_OP_IGET: /* 0x52 */
2383 /* File: armv5te/OP_IGET.S */
2384     /*
2385      * General 32-bit instance field get.
2386      *
2387      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2388      */
2389     /* op vA, vB, field@CCCC */
2390     mov     r0, rINST, lsr #12          @ r0<- B
2391     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2392     FETCH(r1, 1)                        @ r1<- field ref CCCC
2393     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2394     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2395     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2396     cmp     r0, #0                      @ is resolved entry null?
2397     bne     .LOP_IGET_finish          @ no, already resolved
2398 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2399     EXPORT_PC()                         @ resolve() could throw
2400     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2401     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2402     cmp     r0, #0
2403     bne     .LOP_IGET_finish
2404     b       common_exceptionThrown
2405
2406 /* ------------------------------ */
2407     .balign 64
2408 .L_OP_IGET_WIDE: /* 0x53 */
2409 /* File: armv5te/OP_IGET_WIDE.S */
2410     /*
2411      * Wide 32-bit instance field get.
2412      */
2413     /* iget-wide vA, vB, field@CCCC */
2414     mov     r0, rINST, lsr #12          @ r0<- B
2415     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2416     FETCH(r1, 1)                        @ r1<- field ref CCCC
2417     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2418     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2419     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2420     cmp     r0, #0                      @ is resolved entry null?
2421     bne     .LOP_IGET_WIDE_finish          @ no, already resolved
2422 8:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2423     EXPORT_PC()                         @ resolve() could throw
2424     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2425     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2426     cmp     r0, #0
2427     bne     .LOP_IGET_WIDE_finish
2428     b       common_exceptionThrown
2429
2430 /* ------------------------------ */
2431     .balign 64
2432 .L_OP_IGET_OBJECT: /* 0x54 */
2433 /* File: armv5te/OP_IGET_OBJECT.S */
2434 /* File: armv5te/OP_IGET.S */
2435     /*
2436      * General 32-bit instance field get.
2437      *
2438      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2439      */
2440     /* op vA, vB, field@CCCC */
2441     mov     r0, rINST, lsr #12          @ r0<- B
2442     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2443     FETCH(r1, 1)                        @ r1<- field ref CCCC
2444     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2445     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2446     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2447     cmp     r0, #0                      @ is resolved entry null?
2448     bne     .LOP_IGET_OBJECT_finish          @ no, already resolved
2449 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2450     EXPORT_PC()                         @ resolve() could throw
2451     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2452     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2453     cmp     r0, #0
2454     bne     .LOP_IGET_OBJECT_finish
2455     b       common_exceptionThrown
2456
2457
2458 /* ------------------------------ */
2459     .balign 64
2460 .L_OP_IGET_BOOLEAN: /* 0x55 */
2461 /* File: armv5te/OP_IGET_BOOLEAN.S */
2462 @include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" }
2463 /* File: armv5te/OP_IGET.S */
2464     /*
2465      * General 32-bit instance field get.
2466      *
2467      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2468      */
2469     /* op vA, vB, field@CCCC */
2470     mov     r0, rINST, lsr #12          @ r0<- B
2471     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2472     FETCH(r1, 1)                        @ r1<- field ref CCCC
2473     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2474     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2475     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2476     cmp     r0, #0                      @ is resolved entry null?
2477     bne     .LOP_IGET_BOOLEAN_finish          @ no, already resolved
2478 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2479     EXPORT_PC()                         @ resolve() could throw
2480     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2481     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2482     cmp     r0, #0
2483     bne     .LOP_IGET_BOOLEAN_finish
2484     b       common_exceptionThrown
2485
2486
2487 /* ------------------------------ */
2488     .balign 64
2489 .L_OP_IGET_BYTE: /* 0x56 */
2490 /* File: armv5te/OP_IGET_BYTE.S */
2491 @include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" }
2492 /* File: armv5te/OP_IGET.S */
2493     /*
2494      * General 32-bit instance field get.
2495      *
2496      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2497      */
2498     /* op vA, vB, field@CCCC */
2499     mov     r0, rINST, lsr #12          @ r0<- B
2500     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2501     FETCH(r1, 1)                        @ r1<- field ref CCCC
2502     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2503     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2504     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2505     cmp     r0, #0                      @ is resolved entry null?
2506     bne     .LOP_IGET_BYTE_finish          @ no, already resolved
2507 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2508     EXPORT_PC()                         @ resolve() could throw
2509     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2510     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2511     cmp     r0, #0
2512     bne     .LOP_IGET_BYTE_finish
2513     b       common_exceptionThrown
2514
2515
2516 /* ------------------------------ */
2517     .balign 64
2518 .L_OP_IGET_CHAR: /* 0x57 */
2519 /* File: armv5te/OP_IGET_CHAR.S */
2520 @include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" }
2521 /* File: armv5te/OP_IGET.S */
2522     /*
2523      * General 32-bit instance field get.
2524      *
2525      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2526      */
2527     /* op vA, vB, field@CCCC */
2528     mov     r0, rINST, lsr #12          @ r0<- B
2529     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2530     FETCH(r1, 1)                        @ r1<- field ref CCCC
2531     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2532     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2533     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2534     cmp     r0, #0                      @ is resolved entry null?
2535     bne     .LOP_IGET_CHAR_finish          @ no, already resolved
2536 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2537     EXPORT_PC()                         @ resolve() could throw
2538     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2539     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2540     cmp     r0, #0
2541     bne     .LOP_IGET_CHAR_finish
2542     b       common_exceptionThrown
2543
2544
2545 /* ------------------------------ */
2546     .balign 64
2547 .L_OP_IGET_SHORT: /* 0x58 */
2548 /* File: armv5te/OP_IGET_SHORT.S */
2549 @include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" }
2550 /* File: armv5te/OP_IGET.S */
2551     /*
2552      * General 32-bit instance field get.
2553      *
2554      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2555      */
2556     /* op vA, vB, field@CCCC */
2557     mov     r0, rINST, lsr #12          @ r0<- B
2558     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2559     FETCH(r1, 1)                        @ r1<- field ref CCCC
2560     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2561     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2562     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2563     cmp     r0, #0                      @ is resolved entry null?
2564     bne     .LOP_IGET_SHORT_finish          @ no, already resolved
2565 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2566     EXPORT_PC()                         @ resolve() could throw
2567     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2568     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2569     cmp     r0, #0
2570     bne     .LOP_IGET_SHORT_finish
2571     b       common_exceptionThrown
2572
2573
2574 /* ------------------------------ */
2575     .balign 64
2576 .L_OP_IPUT: /* 0x59 */
2577 /* File: armv5te/OP_IPUT.S */
2578     /*
2579      * General 32-bit instance field put.
2580      *
2581      * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2582      */
2583     /* op vA, vB, field@CCCC */
2584     mov     r0, rINST, lsr #12          @ r0<- B
2585     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2586     FETCH(r1, 1)                        @ r1<- field ref CCCC
2587     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2588     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2589     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2590     cmp     r0, #0                      @ is resolved entry null?
2591     bne     .LOP_IPUT_finish          @ no, already resolved
2592 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2593     EXPORT_PC()                         @ resolve() could throw
2594     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2595     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2596     cmp     r0, #0                      @ success?
2597     bne     .LOP_IPUT_finish          @ yes, finish up
2598     b       common_exceptionThrown
2599
2600 /* ------------------------------ */
2601     .balign 64
2602 .L_OP_IPUT_WIDE: /* 0x5a */
2603 /* File: armv5te/OP_IPUT_WIDE.S */
2604     /* iput-wide vA, vB, field@CCCC */
2605     mov     r0, rINST, lsr #12          @ r0<- B
2606     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2607     FETCH(r1, 1)                        @ r1<- field ref CCCC
2608     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2609     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2610     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2611     cmp     r0, #0                      @ is resolved entry null?
2612     bne     .LOP_IPUT_WIDE_finish          @ no, already resolved
2613 8:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2614     EXPORT_PC()                         @ resolve() could throw
2615     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2616     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2617     cmp     r0, #0                      @ success?
2618     bne     .LOP_IPUT_WIDE_finish          @ yes, finish up
2619     b       common_exceptionThrown
2620
2621 /* ------------------------------ */
2622     .balign 64
2623 .L_OP_IPUT_OBJECT: /* 0x5b */
2624 /* File: armv5te/OP_IPUT_OBJECT.S */
2625     /*
2626      * 32-bit instance field put.
2627      *
2628      * for: iput-object, iput-object-volatile
2629      */
2630     /* op vA, vB, field@CCCC */
2631     mov     r0, rINST, lsr #12          @ r0<- B
2632     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2633     FETCH(r1, 1)                        @ r1<- field ref CCCC
2634     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2635     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2636     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2637     cmp     r0, #0                      @ is resolved entry null?
2638     bne     .LOP_IPUT_OBJECT_finish          @ no, already resolved
2639 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2640     EXPORT_PC()                         @ resolve() could throw
2641     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2642     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2643     cmp     r0, #0                      @ success?
2644     bne     .LOP_IPUT_OBJECT_finish          @ yes, finish up
2645     b       common_exceptionThrown
2646
2647 /* ------------------------------ */
2648     .balign 64
2649 .L_OP_IPUT_BOOLEAN: /* 0x5c */
2650 /* File: armv5te/OP_IPUT_BOOLEAN.S */
2651 @include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" }
2652 /* File: armv5te/OP_IPUT.S */
2653     /*
2654      * General 32-bit instance field put.
2655      *
2656      * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2657      */
2658     /* op vA, vB, field@CCCC */
2659     mov     r0, rINST, lsr #12          @ r0<- B
2660     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2661     FETCH(r1, 1)                        @ r1<- field ref CCCC
2662     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2663     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2664     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2665     cmp     r0, #0                      @ is resolved entry null?
2666     bne     .LOP_IPUT_BOOLEAN_finish          @ no, already resolved
2667 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2668     EXPORT_PC()                         @ resolve() could throw
2669     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2670     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2671     cmp     r0, #0                      @ success?
2672     bne     .LOP_IPUT_BOOLEAN_finish          @ yes, finish up
2673     b       common_exceptionThrown
2674
2675
2676 /* ------------------------------ */
2677     .balign 64
2678 .L_OP_IPUT_BYTE: /* 0x5d */
2679 /* File: armv5te/OP_IPUT_BYTE.S */
2680 @include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" }
2681 /* File: armv5te/OP_IPUT.S */
2682     /*
2683      * General 32-bit instance field put.
2684      *
2685      * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2686      */
2687     /* op vA, vB, field@CCCC */
2688     mov     r0, rINST, lsr #12          @ r0<- B
2689     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2690     FETCH(r1, 1)                        @ r1<- field ref CCCC
2691     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2692     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2693     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2694     cmp     r0, #0                      @ is resolved entry null?
2695     bne     .LOP_IPUT_BYTE_finish          @ no, already resolved
2696 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2697     EXPORT_PC()                         @ resolve() could throw
2698     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2699     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2700     cmp     r0, #0                      @ success?
2701     bne     .LOP_IPUT_BYTE_finish          @ yes, finish up
2702     b       common_exceptionThrown
2703
2704
2705 /* ------------------------------ */
2706     .balign 64
2707 .L_OP_IPUT_CHAR: /* 0x5e */
2708 /* File: armv5te/OP_IPUT_CHAR.S */
2709 @include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" }
2710 /* File: armv5te/OP_IPUT.S */
2711     /*
2712      * General 32-bit instance field put.
2713      *
2714      * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2715      */
2716     /* op vA, vB, field@CCCC */
2717     mov     r0, rINST, lsr #12          @ r0<- B
2718     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2719     FETCH(r1, 1)                        @ r1<- field ref CCCC
2720     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2721     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2722     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2723     cmp     r0, #0                      @ is resolved entry null?
2724     bne     .LOP_IPUT_CHAR_finish          @ no, already resolved
2725 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2726     EXPORT_PC()                         @ resolve() could throw
2727     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2728     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2729     cmp     r0, #0                      @ success?
2730     bne     .LOP_IPUT_CHAR_finish          @ yes, finish up
2731     b       common_exceptionThrown
2732
2733
2734 /* ------------------------------ */
2735     .balign 64
2736 .L_OP_IPUT_SHORT: /* 0x5f */
2737 /* File: armv5te/OP_IPUT_SHORT.S */
2738 @include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" }
2739 /* File: armv5te/OP_IPUT.S */
2740     /*
2741      * General 32-bit instance field put.
2742      *
2743      * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2744      */
2745     /* op vA, vB, field@CCCC */
2746     mov     r0, rINST, lsr #12          @ r0<- B
2747     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2748     FETCH(r1, 1)                        @ r1<- field ref CCCC
2749     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2750     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2751     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2752     cmp     r0, #0                      @ is resolved entry null?
2753     bne     .LOP_IPUT_SHORT_finish          @ no, already resolved
2754 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2755     EXPORT_PC()                         @ resolve() could throw
2756     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2757     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2758     cmp     r0, #0                      @ success?
2759     bne     .LOP_IPUT_SHORT_finish          @ yes, finish up
2760     b       common_exceptionThrown
2761
2762
2763 /* ------------------------------ */
2764     .balign 64
2765 .L_OP_SGET: /* 0x60 */
2766 /* File: armv5te/OP_SGET.S */
2767     /*
2768      * General 32-bit SGET handler.
2769      *
2770      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2771      */
2772     /* op vAA, field@BBBB */
2773     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2774     FETCH(r1, 1)                        @ r1<- field ref BBBB
2775     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2776     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2777     cmp     r0, #0                      @ is resolved entry null?
2778     beq     .LOP_SGET_resolve         @ yes, do resolve
2779 .LOP_SGET_finish: @ field ptr in r0
2780     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2781     @ no-op                             @ acquiring load
2782     mov     r2, rINST, lsr #8           @ r2<- AA
2783     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2784     SET_VREG(r1, r2)                    @ fp[AA]<- r1
2785     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2786     GOTO_OPCODE(ip)                     @ jump to next instruction
2787
2788 /* ------------------------------ */
2789     .balign 64
2790 .L_OP_SGET_WIDE: /* 0x61 */
2791 /* File: armv5te/OP_SGET_WIDE.S */
2792     /*
2793      * 64-bit SGET handler.
2794      */
2795     /* sget-wide vAA, field@BBBB */
2796     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2797     FETCH(r1, 1)                        @ r1<- field ref BBBB
2798     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2799     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2800     cmp     r0, #0                      @ is resolved entry null?
2801     beq     .LOP_SGET_WIDE_resolve         @ yes, do resolve
2802 .LOP_SGET_WIDE_finish:
2803     mov     r9, rINST, lsr #8           @ r9<- AA
2804     .if 0
2805     add     r0, r0, #offStaticField_value @ r0<- pointer to data
2806     bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
2807     .else
2808     ldrd    r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
2809     .endif
2810     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2811     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2812     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
2813     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2814     GOTO_OPCODE(ip)                     @ jump to next instruction
2815
2816 /* ------------------------------ */
2817     .balign 64
2818 .L_OP_SGET_OBJECT: /* 0x62 */
2819 /* File: armv5te/OP_SGET_OBJECT.S */
2820 /* File: armv5te/OP_SGET.S */
2821     /*
2822      * General 32-bit SGET handler.
2823      *
2824      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2825      */
2826     /* op vAA, field@BBBB */
2827     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2828     FETCH(r1, 1)                        @ r1<- field ref BBBB
2829     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2830     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2831     cmp     r0, #0                      @ is resolved entry null?
2832     beq     .LOP_SGET_OBJECT_resolve         @ yes, do resolve
2833 .LOP_SGET_OBJECT_finish: @ field ptr in r0
2834     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2835     @ no-op                             @ acquiring load
2836     mov     r2, rINST, lsr #8           @ r2<- AA
2837     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2838     SET_VREG(r1, r2)                    @ fp[AA]<- r1
2839     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2840     GOTO_OPCODE(ip)                     @ jump to next instruction
2841
2842
2843 /* ------------------------------ */
2844     .balign 64
2845 .L_OP_SGET_BOOLEAN: /* 0x63 */
2846 /* File: armv5te/OP_SGET_BOOLEAN.S */
2847 /* File: armv5te/OP_SGET.S */
2848     /*
2849      * General 32-bit SGET handler.
2850      *
2851      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2852      */
2853     /* op vAA, field@BBBB */
2854     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2855     FETCH(r1, 1)                        @ r1<- field ref BBBB
2856     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2857     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2858     cmp     r0, #0                      @ is resolved entry null?
2859     beq     .LOP_SGET_BOOLEAN_resolve         @ yes, do resolve
2860 .LOP_SGET_BOOLEAN_finish: @ field ptr in r0
2861     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2862     @ no-op                             @ acquiring load
2863     mov     r2, rINST, lsr #8           @ r2<- AA
2864     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2865     SET_VREG(r1, r2)                    @ fp[AA]<- r1
2866     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2867     GOTO_OPCODE(ip)                     @ jump to next instruction
2868
2869
2870 /* ------------------------------ */
2871     .balign 64
2872 .L_OP_SGET_BYTE: /* 0x64 */
2873 /* File: armv5te/OP_SGET_BYTE.S */
2874 /* File: armv5te/OP_SGET.S */
2875     /*
2876      * General 32-bit SGET handler.
2877      *
2878      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2879      */
2880     /* op vAA, field@BBBB */
2881     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2882     FETCH(r1, 1)                        @ r1<- field ref BBBB
2883     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2884     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2885     cmp     r0, #0                      @ is resolved entry null?
2886     beq     .LOP_SGET_BYTE_resolve         @ yes, do resolve
2887 .LOP_SGET_BYTE_finish: @ field ptr in r0
2888     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2889     @ no-op                             @ acquiring load
2890     mov     r2, rINST, lsr #8           @ r2<- AA
2891     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2892     SET_VREG(r1, r2)                    @ fp[AA]<- r1
2893     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2894     GOTO_OPCODE(ip)                     @ jump to next instruction
2895
2896
2897 /* ------------------------------ */
2898     .balign 64
2899 .L_OP_SGET_CHAR: /* 0x65 */
2900 /* File: armv5te/OP_SGET_CHAR.S */
2901 /* File: armv5te/OP_SGET.S */
2902     /*
2903      * General 32-bit SGET handler.
2904      *
2905      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2906      */
2907     /* op vAA, field@BBBB */
2908     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2909     FETCH(r1, 1)                        @ r1<- field ref BBBB
2910     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2911     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2912     cmp     r0, #0                      @ is resolved entry null?
2913     beq     .LOP_SGET_CHAR_resolve         @ yes, do resolve
2914 .LOP_SGET_CHAR_finish: @ field ptr in r0
2915     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2916     @ no-op                             @ acquiring load
2917     mov     r2, rINST, lsr #8           @ r2<- AA
2918     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2919     SET_VREG(r1, r2)                    @ fp[AA]<- r1
2920     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2921     GOTO_OPCODE(ip)                     @ jump to next instruction
2922
2923
2924 /* ------------------------------ */
2925     .balign 64
2926 .L_OP_SGET_SHORT: /* 0x66 */
2927 /* File: armv5te/OP_SGET_SHORT.S */
2928 /* File: armv5te/OP_SGET.S */
2929     /*
2930      * General 32-bit SGET handler.
2931      *
2932      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2933      */
2934     /* op vAA, field@BBBB */
2935     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2936     FETCH(r1, 1)                        @ r1<- field ref BBBB
2937     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2938     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2939     cmp     r0, #0                      @ is resolved entry null?
2940     beq     .LOP_SGET_SHORT_resolve         @ yes, do resolve
2941 .LOP_SGET_SHORT_finish: @ field ptr in r0
2942     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2943     @ no-op                             @ acquiring load
2944     mov     r2, rINST, lsr #8           @ r2<- AA
2945     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2946     SET_VREG(r1, r2)                    @ fp[AA]<- r1
2947     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2948     GOTO_OPCODE(ip)                     @ jump to next instruction
2949
2950
2951 /* ------------------------------ */
2952     .balign 64
2953 .L_OP_SPUT: /* 0x67 */
2954 /* File: armv5te/OP_SPUT.S */
2955     /*
2956      * General 32-bit SPUT handler.
2957      *
2958      * for: sput, sput-boolean, sput-byte, sput-char, sput-short
2959      */
2960     /* op vAA, field@BBBB */
2961     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2962     FETCH(r1, 1)                        @ r1<- field ref BBBB
2963     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2964     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2965     cmp     r0, #0                      @ is resolved entry null?
2966     beq     .LOP_SPUT_resolve         @ yes, do resolve
2967 .LOP_SPUT_finish:   @ field ptr in r0
2968     mov     r2, rINST, lsr #8           @ r2<- AA
2969     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2970     GET_VREG(r1, r2)                    @ r1<- fp[AA]
2971     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2972     @ no-op                             @ releasing store
2973     str     r1, [r0, #offStaticField_value] @ field<- vAA
2974     GOTO_OPCODE(ip)                     @ jump to next instruction
2975
2976 /* ------------------------------ */
2977     .balign 64
2978 .L_OP_SPUT_WIDE: /* 0x68 */
2979 /* File: armv5te/OP_SPUT_WIDE.S */
2980     /*
2981      * 64-bit SPUT handler.
2982      */
2983     /* sput-wide vAA, field@BBBB */
2984     ldr     r0, [rGLUE, #offGlue_methodClassDex]  @ r0<- DvmDex
2985     FETCH(r1, 1)                        @ r1<- field ref BBBB
2986     ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
2987     mov     r9, rINST, lsr #8           @ r9<- AA
2988     ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
2989     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2990     cmp     r2, #0                      @ is resolved entry null?
2991     beq     .LOP_SPUT_WIDE_resolve         @ yes, do resolve
2992 .LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9
2993     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2994     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
2995     GET_INST_OPCODE(r10)                @ extract opcode from rINST
2996     .if 0
2997     add     r2, r2, #offStaticField_value @ r2<- pointer to data
2998     bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
2999     .else
3000     strd    r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
3001     .endif
3002     GOTO_OPCODE(r10)                    @ jump to next instruction
3003
3004 /* ------------------------------ */
3005     .balign 64
3006 .L_OP_SPUT_OBJECT: /* 0x69 */
3007 /* File: armv5te/OP_SPUT_OBJECT.S */
3008     /*
3009      * 32-bit SPUT handler for objects
3010      *
3011      * for: sput-object, sput-object-volatile
3012      */
3013     /* op vAA, field@BBBB */
3014     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3015     FETCH(r1, 1)                        @ r1<- field ref BBBB
3016     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3017     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3018     cmp     r0, #0                      @ is resolved entry null?
3019     bne     .LOP_SPUT_OBJECT_finish          @ no, continue
3020     ldr     r9, [rGLUE, #offGlue_method]    @ r9<- current method
3021     EXPORT_PC()                         @ resolve() could throw, so export now
3022     ldr     r0, [r9, #offMethod_clazz]  @ r0<- method->clazz
3023     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
3024     cmp     r0, #0                      @ success?
3025     bne     .LOP_SPUT_OBJECT_finish          @ yes, finish
3026     b       common_exceptionThrown      @ no, handle exception
3027
3028
3029 /* ------------------------------ */
3030     .balign 64
3031 .L_OP_SPUT_BOOLEAN: /* 0x6a */
3032 /* File: armv5te/OP_SPUT_BOOLEAN.S */
3033 /* File: armv5te/OP_SPUT.S */
3034     /*
3035      * General 32-bit SPUT handler.
3036      *
3037      * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3038      */
3039     /* op vAA, field@BBBB */
3040     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3041     FETCH(r1, 1)                        @ r1<- field ref BBBB
3042     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3043     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3044     cmp     r0, #0                      @ is resolved entry null?
3045     beq     .LOP_SPUT_BOOLEAN_resolve         @ yes, do resolve
3046 .LOP_SPUT_BOOLEAN_finish:   @ field ptr in r0
3047     mov     r2, rINST, lsr #8           @ r2<- AA
3048     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3049     GET_VREG(r1, r2)                    @ r1<- fp[AA]
3050     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3051     @ no-op                             @ releasing store
3052     str     r1, [r0, #offStaticField_value] @ field<- vAA
3053     GOTO_OPCODE(ip)                     @ jump to next instruction
3054
3055
3056 /* ------------------------------ */
3057     .balign 64
3058 .L_OP_SPUT_BYTE: /* 0x6b */
3059 /* File: armv5te/OP_SPUT_BYTE.S */
3060 /* File: armv5te/OP_SPUT.S */
3061     /*
3062      * General 32-bit SPUT handler.
3063      *
3064      * for: sput, 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_BYTE_resolve         @ yes, do resolve
3073 .LOP_SPUT_BYTE_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     @ no-op                             @ releasing store
3079     str     r1, [r0, #offStaticField_value] @ field<- vAA
3080     GOTO_OPCODE(ip)                     @ jump to next instruction
3081
3082
3083 /* ------------------------------ */
3084     .balign 64
3085 .L_OP_SPUT_CHAR: /* 0x6c */
3086 /* File: armv5te/OP_SPUT_CHAR.S */
3087 /* File: armv5te/OP_SPUT.S */
3088     /*
3089      * General 32-bit SPUT handler.
3090      *
3091      * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3092      */
3093     /* op vAA, field@BBBB */
3094     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3095     FETCH(r1, 1)                        @ r1<- field ref BBBB
3096     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3097     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3098     cmp     r0, #0                      @ is resolved entry null?
3099     beq     .LOP_SPUT_CHAR_resolve         @ yes, do resolve
3100 .LOP_SPUT_CHAR_finish:   @ field ptr in r0
3101     mov     r2, rINST, lsr #8           @ r2<- AA
3102     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3103     GET_VREG(r1, r2)                    @ r1<- fp[AA]
3104     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3105     @ no-op                             @ releasing store
3106     str     r1, [r0, #offStaticField_value] @ field<- vAA
3107     GOTO_OPCODE(ip)                     @ jump to next instruction
3108
3109
3110 /* ------------------------------ */
3111     .balign 64
3112 .L_OP_SPUT_SHORT: /* 0x6d */
3113 /* File: armv5te/OP_SPUT_SHORT.S */
3114 /* File: armv5te/OP_SPUT.S */
3115     /*
3116      * General 32-bit SPUT handler.
3117      *
3118      * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3119      */
3120     /* op vAA, field@BBBB */
3121     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3122     FETCH(r1, 1)                        @ r1<- field ref BBBB
3123     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3124     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3125     cmp     r0, #0                      @ is resolved entry null?
3126     beq     .LOP_SPUT_SHORT_resolve         @ yes, do resolve
3127 .LOP_SPUT_SHORT_finish:   @ field ptr in r0
3128     mov     r2, rINST, lsr #8           @ r2<- AA
3129     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3130     GET_VREG(r1, r2)                    @ r1<- fp[AA]
3131     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3132     @ no-op                             @ releasing store
3133     str     r1, [r0, #offStaticField_value] @ field<- vAA
3134     GOTO_OPCODE(ip)                     @ jump to next instruction
3135
3136
3137 /* ------------------------------ */
3138     .balign 64
3139 .L_OP_INVOKE_VIRTUAL: /* 0x6e */
3140 /* File: armv5te/OP_INVOKE_VIRTUAL.S */
3141     /*
3142      * Handle a virtual method call.
3143      *
3144      * for: invoke-virtual, invoke-virtual/range
3145      */
3146     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3147     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3148     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3149     FETCH(r1, 1)                        @ r1<- BBBB
3150     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3151     FETCH(r10, 2)                       @ r10<- GFED or CCCC
3152     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3153     .if     (!0)
3154     and     r10, r10, #15               @ r10<- D (or stays CCCC)
3155     .endif
3156     cmp     r0, #0                      @ already resolved?
3157     EXPORT_PC()                         @ must export for invoke
3158     bne     .LOP_INVOKE_VIRTUAL_continue        @ yes, continue on
3159     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3160     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3161     mov     r2, #METHOD_VIRTUAL         @ resolver method type
3162     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3163     cmp     r0, #0                      @ got null?
3164     bne     .LOP_INVOKE_VIRTUAL_continue        @ no, continue
3165     b       common_exceptionThrown      @ yes, handle exception
3166
3167 /* ------------------------------ */
3168     .balign 64
3169 .L_OP_INVOKE_SUPER: /* 0x6f */
3170 /* File: armv5te/OP_INVOKE_SUPER.S */
3171     /*
3172      * Handle a "super" method call.
3173      *
3174      * for: invoke-super, invoke-super/range
3175      */
3176     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3177     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3178     FETCH(r10, 2)                       @ r10<- GFED or CCCC
3179     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3180     .if     (!0)
3181     and     r10, r10, #15               @ r10<- D (or stays CCCC)
3182     .endif
3183     FETCH(r1, 1)                        @ r1<- BBBB
3184     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3185     GET_VREG(r2, r10)                   @ r2<- "this" ptr
3186     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3187     cmp     r2, #0                      @ null "this"?
3188     ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3189     beq     common_errNullObject        @ null "this", throw exception
3190     cmp     r0, #0                      @ already resolved?
3191     ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3192     EXPORT_PC()                         @ must export for invoke
3193     bne     .LOP_INVOKE_SUPER_continue        @ resolved, continue on
3194     b       .LOP_INVOKE_SUPER_resolve         @ do resolve now
3195
3196 /* ------------------------------ */
3197     .balign 64
3198 .L_OP_INVOKE_DIRECT: /* 0x70 */
3199 /* File: armv5te/OP_INVOKE_DIRECT.S */
3200     /*
3201      * Handle a direct method call.
3202      *
3203      * (We could defer the "is 'this' pointer null" test to the common
3204      * method invocation code, and use a flag to indicate that static
3205      * calls don't count.  If we do this as part of copying the arguments
3206      * out we could avoiding loading the first arg twice.)
3207      *
3208      * for: invoke-direct, invoke-direct/range
3209      */
3210     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3211     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3212     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3213     FETCH(r1, 1)                        @ r1<- BBBB
3214     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3215     FETCH(r10, 2)                       @ r10<- GFED or CCCC
3216     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3217     .if     (!0)
3218     and     r10, r10, #15               @ r10<- D (or stays CCCC)
3219     .endif
3220     cmp     r0, #0                      @ already resolved?
3221     EXPORT_PC()                         @ must export for invoke
3222     GET_VREG(r2, r10)                   @ r2<- "this" ptr
3223     beq     .LOP_INVOKE_DIRECT_resolve         @ not resolved, do it now
3224 .LOP_INVOKE_DIRECT_finish:
3225     cmp     r2, #0                      @ null "this" ref?
3226     bne     common_invokeMethodNoRange   @ no, continue on
3227     b       common_errNullObject        @ yes, throw exception
3228
3229 /* ------------------------------ */
3230     .balign 64
3231 .L_OP_INVOKE_STATIC: /* 0x71 */
3232 /* File: armv5te/OP_INVOKE_STATIC.S */
3233     /*
3234      * Handle a static method call.
3235      *
3236      * for: invoke-static, invoke-static/range
3237      */
3238     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3239     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3240     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3241     FETCH(r1, 1)                        @ r1<- BBBB
3242     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3243     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3244     cmp     r0, #0                      @ already resolved?
3245     EXPORT_PC()                         @ must export for invoke
3246     bne     common_invokeMethodNoRange @ yes, continue on
3247 0:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3248     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3249     mov     r2, #METHOD_STATIC          @ resolver method type
3250     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3251     cmp     r0, #0                      @ got null?
3252     bne     common_invokeMethodNoRange @ no, continue
3253     b       common_exceptionThrown      @ yes, handle exception
3254
3255 /* ------------------------------ */
3256     .balign 64
3257 .L_OP_INVOKE_INTERFACE: /* 0x72 */
3258 /* File: armv5te/OP_INVOKE_INTERFACE.S */
3259     /*
3260      * Handle an interface method call.
3261      *
3262      * for: invoke-interface, invoke-interface/range
3263      */
3264     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3265     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3266     FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3267     FETCH(r1, 1)                        @ r1<- BBBB
3268     .if     (!0)
3269     and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3270     .endif
3271     EXPORT_PC()                         @ must export for invoke
3272     GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3273     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3274     cmp     r0, #0                      @ null obj?
3275     ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3276     beq     common_errNullObject        @ yes, fail
3277     ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3278     bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3279     cmp     r0, #0                      @ failed?
3280     beq     common_exceptionThrown      @ yes, handle exception
3281     b       common_invokeMethodNoRange @ jump to common handler
3282
3283 /* ------------------------------ */
3284     .balign 64
3285 .L_OP_UNUSED_73: /* 0x73 */
3286 /* File: armv5te/OP_UNUSED_73.S */
3287 /* File: armv5te/unused.S */
3288     bl      common_abort
3289
3290
3291 /* ------------------------------ */
3292     .balign 64
3293 .L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
3294 /* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */
3295 /* File: armv5te/OP_INVOKE_VIRTUAL.S */
3296     /*
3297      * Handle a virtual method call.
3298      *
3299      * for: invoke-virtual, invoke-virtual/range
3300      */
3301     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3302     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3303     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3304     FETCH(r1, 1)                        @ r1<- BBBB
3305     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3306     FETCH(r10, 2)                       @ r10<- GFED or CCCC
3307     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3308     .if     (!1)
3309     and     r10, r10, #15               @ r10<- D (or stays CCCC)
3310     .endif
3311     cmp     r0, #0                      @ already resolved?
3312     EXPORT_PC()                         @ must export for invoke
3313     bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ yes, continue on
3314     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3315     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3316     mov     r2, #METHOD_VIRTUAL         @ resolver method type
3317     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3318     cmp     r0, #0                      @ got null?
3319     bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ no, continue
3320     b       common_exceptionThrown      @ yes, handle exception
3321
3322
3323 /* ------------------------------ */
3324     .balign 64
3325 .L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
3326 /* File: armv5te/OP_INVOKE_SUPER_RANGE.S */
3327 /* File: armv5te/OP_INVOKE_SUPER.S */
3328     /*
3329      * Handle a "super" method call.
3330      *
3331      * for: invoke-super, invoke-super/range
3332      */
3333     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3334     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3335     FETCH(r10, 2)                       @ r10<- GFED or CCCC
3336     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3337     .if     (!1)
3338     and     r10, r10, #15               @ r10<- D (or stays CCCC)
3339     .endif
3340     FETCH(r1, 1)                        @ r1<- BBBB
3341     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3342     GET_VREG(r2, r10)                   @ r2<- "this" ptr
3343     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3344     cmp     r2, #0                      @ null "this"?
3345     ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3346     beq     common_errNullObject        @ null "this", throw exception
3347     cmp     r0, #0                      @ already resolved?
3348     ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3349     EXPORT_PC()                         @ must export for invoke
3350     bne     .LOP_INVOKE_SUPER_RANGE_continue        @ resolved, continue on
3351     b       .LOP_INVOKE_SUPER_RANGE_resolve         @ do resolve now
3352
3353
3354 /* ------------------------------ */
3355     .balign 64
3356 .L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
3357 /* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */
3358 /* File: armv5te/OP_INVOKE_DIRECT.S */
3359     /*
3360      * Handle a direct method call.
3361      *
3362      * (We could defer the "is 'this' pointer null" test to the common
3363      * method invocation code, and use a flag to indicate that static
3364      * calls don't count.  If we do this as part of copying the arguments
3365      * out we could avoiding loading the first arg twice.)
3366      *
3367      * for: invoke-direct, invoke-direct/range
3368      */
3369     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3370     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3371     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3372     FETCH(r1, 1)                        @ r1<- BBBB
3373     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3374     FETCH(r10, 2)                       @ r10<- GFED or CCCC
3375     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3376     .if     (!1)
3377     and     r10, r10, #15               @ r10<- D (or stays CCCC)
3378     .endif
3379     cmp     r0, #0                      @ already resolved?
3380     EXPORT_PC()                         @ must export for invoke
3381     GET_VREG(r2, r10)                   @ r2<- "this" ptr
3382     beq     .LOP_INVOKE_DIRECT_RANGE_resolve         @ not resolved, do it now
3383 .LOP_INVOKE_DIRECT_RANGE_finish:
3384     cmp     r2, #0                      @ null "this" ref?
3385     bne     common_invokeMethodRange   @ no, continue on
3386     b       common_errNullObject        @ yes, throw exception
3387
3388
3389 /* ------------------------------ */
3390     .balign 64
3391 .L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
3392 /* File: armv5te/OP_INVOKE_STATIC_RANGE.S */
3393 /* File: armv5te/OP_INVOKE_STATIC.S */
3394     /*
3395      * Handle a static method call.
3396      *
3397      * for: invoke-static, invoke-static/range
3398      */
3399     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3400     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3401     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3402     FETCH(r1, 1)                        @ r1<- BBBB
3403     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3404     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3405     cmp     r0, #0                      @ already resolved?
3406     EXPORT_PC()                         @ must export for invoke
3407     bne     common_invokeMethodRange @ yes, continue on
3408 0:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3409     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3410     mov     r2, #METHOD_STATIC          @ resolver method type
3411     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3412     cmp     r0, #0                      @ got null?
3413     bne     common_invokeMethodRange @ no, continue
3414     b       common_exceptionThrown      @ yes, handle exception
3415
3416
3417 /* ------------------------------ */
3418     .balign 64
3419 .L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
3420 /* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */
3421 /* File: armv5te/OP_INVOKE_INTERFACE.S */
3422     /*
3423      * Handle an interface method call.
3424      *
3425      * for: invoke-interface, invoke-interface/range
3426      */
3427     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3428     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3429     FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3430     FETCH(r1, 1)                        @ r1<- BBBB
3431     .if     (!1)
3432     and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3433     .endif
3434     EXPORT_PC()                         @ must export for invoke
3435     GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3436     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3437     cmp     r0, #0                      @ null obj?
3438     ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3439     beq     common_errNullObject        @ yes, fail
3440     ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3441     bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3442     cmp     r0, #0                      @ failed?
3443     beq     common_exceptionThrown      @ yes, handle exception
3444     b       common_invokeMethodRange @ jump to common handler
3445
3446
3447 /* ------------------------------ */
3448     .balign 64
3449 .L_OP_UNUSED_79: /* 0x79 */
3450 /* File: armv5te/OP_UNUSED_79.S */
3451 /* File: armv5te/unused.S */
3452     bl      common_abort
3453
3454
3455 /* ------------------------------ */
3456     .balign 64
3457 .L_OP_UNUSED_7A: /* 0x7a */
3458 /* File: armv5te/OP_UNUSED_7A.S */
3459 /* File: armv5te/unused.S */
3460     bl      common_abort
3461
3462
3463 /* ------------------------------ */
3464     .balign 64
3465 .L_OP_NEG_INT: /* 0x7b */
3466 /* File: armv5te/OP_NEG_INT.S */
3467 /* File: armv5te/unop.S */
3468     /*
3469      * Generic 32-bit unary operation.  Provide an "instr" line that
3470      * specifies an instruction that performs "result = op r0".
3471      * This could be an ARM instruction or a function call.
3472      *
3473      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3474      *      int-to-byte, int-to-char, int-to-short
3475      */
3476     /* unop vA, vB */
3477     mov     r3, rINST, lsr #12          @ r3<- B
3478     mov     r9, rINST, lsr #8           @ r9<- A+
3479     GET_VREG(r0, r3)                    @ r0<- vB
3480     and     r9, r9, #15
3481                                @ optional op; may set condition codes
3482     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3483     rsb     r0, r0, #0                              @ r0<- op, r0-r3 changed
3484     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3485     SET_VREG(r0, r9)                    @ vAA<- r0
3486     GOTO_OPCODE(ip)                     @ jump to next instruction
3487     /* 9-10 instructions */
3488
3489
3490 /* ------------------------------ */
3491     .balign 64
3492 .L_OP_NOT_INT: /* 0x7c */
3493 /* File: armv5te/OP_NOT_INT.S */
3494 /* File: armv5te/unop.S */
3495     /*
3496      * Generic 32-bit unary operation.  Provide an "instr" line that
3497      * specifies an instruction that performs "result = op r0".
3498      * This could be an ARM instruction or a function call.
3499      *
3500      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3501      *      int-to-byte, int-to-char, int-to-short
3502      */
3503     /* unop vA, vB */
3504     mov     r3, rINST, lsr #12          @ r3<- B
3505     mov     r9, rINST, lsr #8           @ r9<- A+
3506     GET_VREG(r0, r3)                    @ r0<- vB
3507     and     r9, r9, #15
3508                                @ optional op; may set condition codes
3509     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3510     mvn     r0, r0                              @ r0<- op, r0-r3 changed
3511     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3512     SET_VREG(r0, r9)                    @ vAA<- r0
3513     GOTO_OPCODE(ip)                     @ jump to next instruction
3514     /* 9-10 instructions */
3515
3516
3517 /* ------------------------------ */
3518     .balign 64
3519 .L_OP_NEG_LONG: /* 0x7d */
3520 /* File: armv5te/OP_NEG_LONG.S */
3521 /* File: armv5te/unopWide.S */
3522     /*
3523      * Generic 64-bit unary operation.  Provide an "instr" line that
3524      * specifies an instruction that performs "result = op r0/r1".
3525      * This could be an ARM instruction or a function call.
3526      *
3527      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3528      */
3529     /* unop vA, vB */
3530     mov     r9, rINST, lsr #8           @ r9<- A+
3531     mov     r3, rINST, lsr #12          @ r3<- B
3532     and     r9, r9, #15
3533     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3534     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3535     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3536     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3537     rsbs    r0, r0, #0                           @ optional op; may set condition codes
3538     rsc     r1, r1, #0                              @ r0/r1<- op, r2-r3 changed
3539     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3540     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3541     GOTO_OPCODE(ip)                     @ jump to next instruction
3542     /* 12-13 instructions */
3543
3544
3545 /* ------------------------------ */
3546     .balign 64
3547 .L_OP_NOT_LONG: /* 0x7e */
3548 /* File: armv5te/OP_NOT_LONG.S */
3549 /* File: armv5te/unopWide.S */
3550     /*
3551      * Generic 64-bit unary operation.  Provide an "instr" line that
3552      * specifies an instruction that performs "result = op r0/r1".
3553      * This could be an ARM instruction or a function call.
3554      *
3555      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3556      */
3557     /* unop vA, vB */
3558     mov     r9, rINST, lsr #8           @ r9<- A+
3559     mov     r3, rINST, lsr #12          @ r3<- B
3560     and     r9, r9, #15
3561     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3562     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3563     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3564     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3565     mvn     r0, r0                           @ optional op; may set condition codes
3566     mvn     r1, r1                              @ r0/r1<- op, r2-r3 changed
3567     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3568     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3569     GOTO_OPCODE(ip)                     @ jump to next instruction
3570     /* 12-13 instructions */
3571
3572
3573 /* ------------------------------ */
3574     .balign 64
3575 .L_OP_NEG_FLOAT: /* 0x7f */
3576 /* File: armv5te/OP_NEG_FLOAT.S */
3577 /* File: armv5te/unop.S */
3578     /*
3579      * Generic 32-bit unary operation.  Provide an "instr" line that
3580      * specifies an instruction that performs "result = op r0".
3581      * This could be an ARM instruction or a function call.
3582      *
3583      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3584      *      int-to-byte, int-to-char, int-to-short
3585      */
3586     /* unop vA, vB */
3587     mov     r3, rINST, lsr #12          @ r3<- B
3588     mov     r9, rINST, lsr #8           @ r9<- A+
3589     GET_VREG(r0, r3)                    @ r0<- vB
3590     and     r9, r9, #15
3591                                @ optional op; may set condition codes
3592     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3593     add     r0, r0, #0x80000000                              @ r0<- op, r0-r3 changed
3594     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3595     SET_VREG(r0, r9)                    @ vAA<- r0
3596     GOTO_OPCODE(ip)                     @ jump to next instruction
3597     /* 9-10 instructions */
3598
3599
3600 /* ------------------------------ */
3601     .balign 64
3602 .L_OP_NEG_DOUBLE: /* 0x80 */
3603 /* File: armv5te/OP_NEG_DOUBLE.S */
3604 /* File: armv5te/unopWide.S */
3605     /*
3606      * Generic 64-bit unary operation.  Provide an "instr" line that
3607      * specifies an instruction that performs "result = op r0/r1".
3608      * This could be an ARM instruction or a function call.
3609      *
3610      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3611      */
3612     /* unop vA, vB */
3613     mov     r9, rINST, lsr #8           @ r9<- A+
3614     mov     r3, rINST, lsr #12          @ r3<- B
3615     and     r9, r9, #15
3616     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3617     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3618     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3619     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3620                                @ optional op; may set condition codes
3621     add     r1, r1, #0x80000000                              @ r0/r1<- op, r2-r3 changed
3622     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3623     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3624     GOTO_OPCODE(ip)                     @ jump to next instruction
3625     /* 12-13 instructions */
3626
3627
3628 /* ------------------------------ */
3629     .balign 64
3630 .L_OP_INT_TO_LONG: /* 0x81 */
3631 /* File: armv5te/OP_INT_TO_LONG.S */
3632 /* File: armv5te/unopWider.S */
3633     /*
3634      * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3635      * that specifies an instruction that performs "result = op r0", where
3636      * "result" is a 64-bit quantity in r0/r1.
3637      *
3638      * For: int-to-long, int-to-double, float-to-long, float-to-double
3639      */
3640     /* unop vA, vB */
3641     mov     r9, rINST, lsr #8           @ r9<- A+
3642     mov     r3, rINST, lsr #12          @ r3<- B
3643     and     r9, r9, #15
3644     GET_VREG(r0, r3)                    @ r0<- vB
3645     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3646                                @ optional op; may set condition codes
3647     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3648     mov     r1, r0, asr #31                              @ r0<- op, r0-r3 changed
3649     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3650     stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3651     GOTO_OPCODE(ip)                     @ jump to next instruction
3652     /* 10-11 instructions */
3653
3654
3655 /* ------------------------------ */
3656     .balign 64
3657 .L_OP_INT_TO_FLOAT: /* 0x82 */
3658 /* File: arm-vfp/OP_INT_TO_FLOAT.S */
3659 /* File: arm-vfp/funop.S */
3660     /*
3661      * Generic 32-bit unary floating-point operation.  Provide an "instr"
3662      * line that specifies an instruction that performs "s1 = op s0".
3663      *
3664      * for: int-to-float, float-to-int
3665      */
3666     /* unop vA, vB */
3667     mov     r3, rINST, lsr #12          @ r3<- B
3668     mov     r9, rINST, lsr #8           @ r9<- A+
3669     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3670     flds    s0, [r3]                    @ s0<- vB
3671     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3672     and     r9, r9, #15                 @ r9<- A
3673     fsitos  s1, s0                              @ s1<- op
3674     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3675     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3676     fsts    s1, [r9]                    @ vA<- s1
3677     GOTO_OPCODE(ip)                     @ jump to next instruction
3678
3679
3680 /* ------------------------------ */
3681     .balign 64
3682 .L_OP_INT_TO_DOUBLE: /* 0x83 */
3683 /* File: arm-vfp/OP_INT_TO_DOUBLE.S */
3684 /* File: arm-vfp/funopWider.S */
3685     /*
3686      * Generic 32bit-to-64bit floating point unary operation.  Provide an
3687      * "instr" line that specifies an instruction that performs "d0 = op s0".
3688      *
3689      * For: int-to-double, float-to-double
3690      */
3691     /* unop vA, vB */
3692     mov     r3, rINST, lsr #12          @ r3<- B
3693     mov     r9, rINST, lsr #8           @ r9<- A+
3694     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3695     flds    s0, [r3]                    @ s0<- vB
3696     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3697     and     r9, r9, #15                 @ r9<- A
3698     fsitod  d0, s0                              @ d0<- op
3699     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3700     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3701     fstd    d0, [r9]                    @ vA<- d0
3702     GOTO_OPCODE(ip)                     @ jump to next instruction
3703
3704
3705 /* ------------------------------ */
3706     .balign 64
3707 .L_OP_LONG_TO_INT: /* 0x84 */
3708 /* File: armv5te/OP_LONG_TO_INT.S */
3709 /* we ignore the high word, making this equivalent to a 32-bit reg move */
3710 /* File: armv5te/OP_MOVE.S */
3711     /* for move, move-object, long-to-int */
3712     /* op vA, vB */
3713     mov     r1, rINST, lsr #12          @ r1<- B from 15:12
3714     mov     r0, rINST, lsr #8           @ r0<- A from 11:8
3715     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3716     GET_VREG(r2, r1)                    @ r2<- fp[B]
3717     and     r0, r0, #15
3718     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
3719     SET_VREG(r2, r0)                    @ fp[A]<- r2
3720     GOTO_OPCODE(ip)                     @ execute next instruction
3721
3722
3723 /* ------------------------------ */
3724     .balign 64
3725 .L_OP_LONG_TO_FLOAT: /* 0x85 */
3726 /* File: armv5te/OP_LONG_TO_FLOAT.S */
3727 /* File: armv5te/unopNarrower.S */
3728     /*
3729      * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
3730      * that specifies an instruction that performs "result = op r0/r1", where
3731      * "result" is a 32-bit quantity in r0.
3732      *
3733      * For: long-to-float, double-to-int, double-to-float
3734      *
3735      * (This would work for long-to-int, but that instruction is actually
3736      * an exact match for OP_MOVE.)
3737      */
3738     /* unop vA, vB */
3739     mov     r3, rINST, lsr #12          @ r3<- B
3740     mov     r9, rINST, lsr #8           @ r9<- A+
3741     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3742     and     r9, r9, #15
3743     ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
3744     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3745                                @ optional op; may set condition codes
3746     bl      __aeabi_l2f                              @ r0<- op, r0-r3 changed
3747     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3748     SET_VREG(r0, r9)                    @ vA<- r0
3749     GOTO_OPCODE(ip)                     @ jump to next instruction
3750     /* 10-11 instructions */
3751
3752
3753 /* ------------------------------ */
3754     .balign 64
3755 .L_OP_LONG_TO_DOUBLE: /* 0x86 */
3756 /* File: armv5te/OP_LONG_TO_DOUBLE.S */
3757 /* File: armv5te/unopWide.S */
3758     /*
3759      * Generic 64-bit unary operation.  Provide an "instr" line that
3760      * specifies an instruction that performs "result = op r0/r1".
3761      * This could be an ARM instruction or a function call.
3762      *
3763      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3764      */
3765     /* unop vA, vB */
3766     mov     r9, rINST, lsr #8           @ r9<- A+
3767     mov     r3, rINST, lsr #12          @ r3<- B
3768     and     r9, r9, #15
3769     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3770     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3771     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3772     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3773                                @ optional op; may set condition codes
3774     bl      __aeabi_l2d                              @ r0/r1<- op, r2-r3 changed
3775     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3776     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3777     GOTO_OPCODE(ip)                     @ jump to next instruction
3778     /* 12-13 instructions */
3779
3780
3781 /* ------------------------------ */
3782     .balign 64
3783 .L_OP_FLOAT_TO_INT: /* 0x87 */
3784 /* File: arm-vfp/OP_FLOAT_TO_INT.S */
3785 /* File: arm-vfp/funop.S */
3786     /*
3787      * Generic 32-bit unary floating-point operation.  Provide an "instr"
3788      * line that specifies an instruction that performs "s1 = op s0".
3789      *
3790      * for: int-to-float, float-to-int
3791      */
3792     /* unop vA, vB */
3793     mov     r3, rINST, lsr #12          @ r3<- B
3794     mov     r9, rINST, lsr #8           @ r9<- A+
3795     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3796     flds    s0, [r3]                    @ s0<- vB
3797     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3798     and     r9, r9, #15                 @ r9<- A
3799     ftosizs s1, s0                              @ s1<- op
3800     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3801     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3802     fsts    s1, [r9]                    @ vA<- s1
3803     GOTO_OPCODE(ip)                     @ jump to next instruction
3804
3805
3806 /* ------------------------------ */
3807     .balign 64
3808 .L_OP_FLOAT_TO_LONG: /* 0x88 */
3809 /* File: armv5te/OP_FLOAT_TO_LONG.S */
3810 @include "armv5te/unopWider.S" {"instr":"bl      __aeabi_f2lz"}
3811 /* File: armv5te/unopWider.S */
3812     /*
3813      * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3814      * that specifies an instruction that performs "result = op r0", where
3815      * "result" is a 64-bit quantity in r0/r1.
3816      *
3817      * For: int-to-long, int-to-double, float-to-long, float-to-double
3818      */
3819     /* unop vA, vB */
3820     mov     r9, rINST, lsr #8           @ r9<- A+
3821     mov     r3, rINST, lsr #12          @ r3<- B
3822     and     r9, r9, #15
3823     GET_VREG(r0, r3)                    @ r0<- vB
3824     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3825                                @ optional op; may set condition codes
3826     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3827     bl      f2l_doconv                              @ r0<- op, r0-r3 changed
3828     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3829     stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3830     GOTO_OPCODE(ip)                     @ jump to next instruction
3831     /* 10-11 instructions */
3832
3833
3834
3835 /* ------------------------------ */
3836     .balign 64
3837 .L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
3838 /* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */
3839 /* File: arm-vfp/funopWider.S */
3840     /*
3841      * Generic 32bit-to-64bit floating point unary operation.  Provide an
3842      * "instr" line that specifies an instruction that performs "d0 = op s0".
3843      *
3844      * For: int-to-double, float-to-double
3845      */
3846     /* unop vA, vB */
3847     mov     r3, rINST, lsr #12          @ r3<- B
3848     mov     r9, rINST, lsr #8           @ r9<- A+
3849     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3850     flds    s0, [r3]                    @ s0<- vB
3851     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3852     and     r9, r9, #15                 @ r9<- A
3853     fcvtds  d0, s0                              @ d0<- op
3854     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3855     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3856     fstd    d0, [r9]                    @ vA<- d0
3857     GOTO_OPCODE(ip)                     @ jump to next instruction
3858
3859
3860 /* ------------------------------ */
3861     .balign 64
3862 .L_OP_DOUBLE_TO_INT: /* 0x8a */
3863 /* File: arm-vfp/OP_DOUBLE_TO_INT.S */
3864 /* File: arm-vfp/funopNarrower.S */
3865     /*
3866      * Generic 64bit-to-32bit unary floating point operation.  Provide an
3867      * "instr" line that specifies an instruction that performs "s0 = op d0".
3868      *
3869      * For: double-to-int, double-to-float
3870      */
3871     /* unop vA, vB */
3872     mov     r3, rINST, lsr #12          @ r3<- B
3873     mov     r9, rINST, lsr #8           @ r9<- A+
3874     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3875     fldd    d0, [r3]                    @ d0<- vB
3876     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3877     and     r9, r9, #15                 @ r9<- A
3878     ftosizd  s0, d0                              @ s0<- op
3879     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3880     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3881     fsts    s0, [r9]                    @ vA<- s0
3882     GOTO_OPCODE(ip)                     @ jump to next instruction
3883
3884
3885 /* ------------------------------ */
3886     .balign 64
3887 .L_OP_DOUBLE_TO_LONG: /* 0x8b */
3888 /* File: armv5te/OP_DOUBLE_TO_LONG.S */
3889 @include "armv5te/unopWide.S" {"instr":"bl      __aeabi_d2lz"}
3890 /* File: armv5te/unopWide.S */
3891     /*
3892      * Generic 64-bit unary operation.  Provide an "instr" line that
3893      * specifies an instruction that performs "result = op r0/r1".
3894      * This could be an ARM instruction or a function call.
3895      *
3896      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3897      */
3898     /* unop vA, vB */
3899     mov     r9, rINST, lsr #8           @ r9<- A+
3900     mov     r3, rINST, lsr #12          @ r3<- B
3901     and     r9, r9, #15
3902     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3903     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3904     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3905     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3906                                @ optional op; may set condition codes
3907     bl      d2l_doconv                              @ r0/r1<- op, r2-r3 changed
3908     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3909     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3910     GOTO_OPCODE(ip)                     @ jump to next instruction
3911     /* 12-13 instructions */
3912
3913
3914
3915 /* ------------------------------ */
3916     .balign 64
3917 .L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
3918 /* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */
3919 /* File: arm-vfp/funopNarrower.S */
3920     /*
3921      * Generic 64bit-to-32bit unary floating point operation.  Provide an
3922      * "instr" line that specifies an instruction that performs "s0 = op d0".
3923      *
3924      * For: double-to-int, double-to-float
3925      */
3926     /* unop vA, vB */
3927     mov     r3, rINST, lsr #12          @ r3<- B
3928     mov     r9, rINST, lsr #8           @ r9<- A+
3929     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3930     fldd    d0, [r3]                    @ d0<- vB
3931     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3932     and     r9, r9, #15                 @ r9<- A
3933     fcvtsd  s0, d0                              @ s0<- op
3934     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3935     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3936     fsts    s0, [r9]                    @ vA<- s0
3937     GOTO_OPCODE(ip)                     @ jump to next instruction
3938
3939
3940 /* ------------------------------ */
3941     .balign 64
3942 .L_OP_INT_TO_BYTE: /* 0x8d */
3943 /* File: armv5te/OP_INT_TO_BYTE.S */
3944 /* File: armv5te/unop.S */
3945     /*
3946      * Generic 32-bit unary operation.  Provide an "instr" line that
3947      * specifies an instruction that performs "result = op r0".
3948      * This could be an ARM instruction or a function call.
3949      *
3950      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3951      *      int-to-byte, int-to-char, int-to-short
3952      */
3953     /* unop vA, vB */
3954     mov     r3, rINST, lsr #12          @ r3<- B
3955     mov     r9, rINST, lsr #8           @ r9<- A+
3956     GET_VREG(r0, r3)                    @ r0<- vB
3957     and     r9, r9, #15
3958     mov     r0, r0, asl #24                           @ optional op; may set condition codes
3959     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3960     mov     r0, r0, asr #24                              @ r0<- op, r0-r3 changed
3961     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3962     SET_VREG(r0, r9)                    @ vAA<- r0
3963     GOTO_OPCODE(ip)                     @ jump to next instruction
3964     /* 9-10 instructions */
3965
3966
3967 /* ------------------------------ */
3968     .balign 64
3969 .L_OP_INT_TO_CHAR: /* 0x8e */
3970 /* File: armv5te/OP_INT_TO_CHAR.S */
3971 /* File: armv5te/unop.S */
3972     /*
3973      * Generic 32-bit unary operation.  Provide an "instr" line that
3974      * specifies an instruction that performs "result = op r0".
3975      * This could be an ARM instruction or a function call.
3976      *
3977      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3978      *      int-to-byte, int-to-char, int-to-short
3979      */
3980     /* unop vA, vB */
3981     mov     r3, rINST, lsr #12          @ r3<- B
3982     mov     r9, rINST, lsr #8           @ r9<- A+
3983     GET_VREG(r0, r3)                    @ r0<- vB
3984     and     r9, r9, #15
3985     mov     r0, r0, asl #16                           @ optional op; may set condition codes
3986     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3987     mov     r0, r0, lsr #16                              @ r0<- op, r0-r3 changed
3988     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3989     SET_VREG(r0, r9)                    @ vAA<- r0
3990     GOTO_OPCODE(ip)                     @ jump to next instruction
3991     /* 9-10 instructions */
3992
3993
3994 /* ------------------------------ */
3995     .balign 64
3996 .L_OP_INT_TO_SHORT: /* 0x8f */
3997 /* File: armv5te/OP_INT_TO_SHORT.S */
3998 /* File: armv5te/unop.S */
3999     /*
4000      * Generic 32-bit unary operation.  Provide an "instr" line that
4001      * specifies an instruction that performs "result = op r0".
4002      * This could be an ARM instruction or a function call.
4003      *
4004      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4005      *      int-to-byte, int-to-char, int-to-short
4006      */
4007     /* unop vA, vB */
4008     mov     r3, rINST, lsr #12          @ r3<- B
4009     mov     r9, rINST, lsr #8           @ r9<- A+
4010     GET_VREG(r0, r3)                    @ r0<- vB
4011     and     r9, r9, #15
4012     mov     r0, r0, asl #16                           @ optional op; may set condition codes
4013     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4014     mov     r0, r0, asr #16                              @ r0<- op, r0-r3 changed
4015     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4016     SET_VREG(r0, r9)                    @ vAA<- r0
4017     GOTO_OPCODE(ip)                     @ jump to next instruction
4018     /* 9-10 instructions */
4019
4020
4021 /* ------------------------------ */
4022     .balign 64
4023 .L_OP_ADD_INT: /* 0x90 */
4024 /* File: armv5te/OP_ADD_INT.S */
4025 /* File: armv5te/binop.S */
4026     /*
4027      * Generic 32-bit binary operation.  Provide an "instr" line that
4028      * specifies an instruction that performs "result = r0 op r1".
4029      * This could be an ARM instruction or a function call.  (If the result
4030      * comes back in a register other than r0, you can override "result".)
4031      *
4032      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4033      * vCC (r1).  Useful for integer division and modulus.  Note that we
4034      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4035      * handles it correctly.
4036      *
4037      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4038      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4039      *      mul-float, div-float, rem-float
4040      */
4041     /* binop vAA, vBB, vCC */
4042     FETCH(r0, 1)                        @ r0<- CCBB
4043     mov     r9, rINST, lsr #8           @ r9<- AA
4044     mov     r3, r0, lsr #8              @ r3<- CC
4045     and     r2, r0, #255                @ r2<- BB
4046     GET_VREG(r1, r3)                    @ r1<- vCC
4047     GET_VREG(r0, r2)                    @ r0<- vBB
4048     .if 0
4049     cmp     r1, #0                      @ is second operand zero?
4050     beq     common_errDivideByZero
4051     .endif
4052
4053     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4054                                @ optional op; may set condition codes
4055     add     r0, r0, r1                              @ r0<- op, r0-r3 changed
4056     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4057     SET_VREG(r0, r9)               @ vAA<- r0
4058     GOTO_OPCODE(ip)                     @ jump to next instruction
4059     /* 11-14 instructions */
4060
4061
4062 /* ------------------------------ */
4063     .balign 64
4064 .L_OP_SUB_INT: /* 0x91 */
4065 /* File: armv5te/OP_SUB_INT.S */
4066 /* File: armv5te/binop.S */
4067     /*
4068      * Generic 32-bit binary operation.  Provide an "instr" line that
4069      * specifies an instruction that performs "result = r0 op r1".
4070      * This could be an ARM instruction or a function call.  (If the result
4071      * comes back in a register other than r0, you can override "result".)
4072      *
4073      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4074      * vCC (r1).  Useful for integer division and modulus.  Note that we
4075      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4076      * handles it correctly.
4077      *
4078      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4079      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4080      *      mul-float, div-float, rem-float
4081      */
4082     /* binop vAA, vBB, vCC */
4083     FETCH(r0, 1)                        @ r0<- CCBB
4084     mov     r9, rINST, lsr #8           @ r9<- AA
4085     mov     r3, r0, lsr #8              @ r3<- CC
4086     and     r2, r0, #255                @ r2<- BB
4087     GET_VREG(r1, r3)                    @ r1<- vCC
4088     GET_VREG(r0, r2)                    @ r0<- vBB
4089     .if 0
4090     cmp     r1, #0                      @ is second operand zero?
4091     beq     common_errDivideByZero
4092     .endif
4093
4094     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4095                                @ optional op; may set condition codes
4096     sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
4097     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4098     SET_VREG(r0, r9)               @ vAA<- r0
4099     GOTO_OPCODE(ip)                     @ jump to next instruction
4100     /* 11-14 instructions */
4101
4102
4103 /* ------------------------------ */
4104     .balign 64
4105 .L_OP_MUL_INT: /* 0x92 */
4106 /* File: armv5te/OP_MUL_INT.S */
4107 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
4108 /* File: armv5te/binop.S */
4109     /*
4110      * Generic 32-bit binary operation.  Provide an "instr" line that
4111      * specifies an instruction that performs "result = r0 op r1".
4112      * This could be an ARM instruction or a function call.  (If the result
4113      * comes back in a register other than r0, you can override "result".)
4114      *
4115      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4116      * vCC (r1).  Useful for integer division and modulus.  Note that we
4117      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4118      * handles it correctly.
4119      *
4120      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4121      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4122      *      mul-float, div-float, rem-float
4123      */
4124     /* binop vAA, vBB, vCC */
4125     FETCH(r0, 1)                        @ r0<- CCBB
4126     mov     r9, rINST, lsr #8           @ r9<- AA
4127     mov     r3, r0, lsr #8              @ r3<- CC
4128     and     r2, r0, #255                @ r2<- BB
4129     GET_VREG(r1, r3)                    @ r1<- vCC
4130     GET_VREG(r0, r2)                    @ r0<- vBB
4131     .if 0
4132     cmp     r1, #0                      @ is second operand zero?
4133     beq     common_errDivideByZero
4134     .endif
4135
4136     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4137                                @ optional op; may set condition codes
4138     mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
4139     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4140     SET_VREG(r0, r9)               @ vAA<- r0
4141     GOTO_OPCODE(ip)                     @ jump to next instruction
4142     /* 11-14 instructions */
4143
4144
4145 /* ------------------------------ */
4146     .balign 64
4147 .L_OP_DIV_INT: /* 0x93 */
4148 /* File: armv5te/OP_DIV_INT.S */
4149 /* File: armv5te/binop.S */
4150     /*
4151      * Generic 32-bit binary operation.  Provide an "instr" line that
4152      * specifies an instruction that performs "result = r0 op r1".
4153      * This could be an ARM instruction or a function call.  (If the result
4154      * comes back in a register other than r0, you can override "result".)
4155      *
4156      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4157      * vCC (r1).  Useful for integer division and modulus.  Note that we
4158      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4159      * handles it correctly.
4160      *
4161      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4162      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4163      *      mul-float, div-float, rem-float
4164      */
4165     /* binop vAA, vBB, vCC */
4166     FETCH(r0, 1)                        @ r0<- CCBB
4167     mov     r9, rINST, lsr #8           @ r9<- AA
4168     mov     r3, r0, lsr #8              @ r3<- CC
4169     and     r2, r0, #255                @ r2<- BB
4170     GET_VREG(r1, r3)                    @ r1<- vCC
4171     GET_VREG(r0, r2)                    @ r0<- vBB
4172     .if 1
4173     cmp     r1, #0                      @ is second operand zero?
4174     beq     common_errDivideByZero
4175     .endif
4176
4177     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4178                                @ optional op; may set condition codes
4179     bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
4180     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4181     SET_VREG(r0, r9)               @ vAA<- r0
4182     GOTO_OPCODE(ip)                     @ jump to next instruction
4183     /* 11-14 instructions */
4184
4185
4186 /* ------------------------------ */
4187     .balign 64
4188 .L_OP_REM_INT: /* 0x94 */
4189 /* File: armv5te/OP_REM_INT.S */
4190 /* idivmod returns quotient in r0 and remainder in r1 */
4191 /* File: armv5te/binop.S */
4192     /*
4193      * Generic 32-bit binary operation.  Provide an "instr" line that
4194      * specifies an instruction that performs "result = r0 op r1".
4195      * This could be an ARM instruction or a function call.  (If the result
4196      * comes back in a register other than r0, you can override "result".)
4197      *
4198      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4199      * vCC (r1).  Useful for integer division and modulus.  Note that we
4200      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4201      * handles it correctly.
4202      *
4203      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4204      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4205      *      mul-float, div-float, rem-float
4206      */
4207     /* binop vAA, vBB, vCC */
4208     FETCH(r0, 1)                        @ r0<- CCBB
4209     mov     r9, rINST, lsr #8           @ r9<- AA
4210     mov     r3, r0, lsr #8              @ r3<- CC
4211     and     r2, r0, #255                @ r2<- BB
4212     GET_VREG(r1, r3)                    @ r1<- vCC
4213     GET_VREG(r0, r2)                    @ r0<- vBB
4214     .if 1
4215     cmp     r1, #0                      @ is second operand zero?
4216     beq     common_errDivideByZero
4217     .endif
4218
4219     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4220                                @ optional op; may set condition codes
4221     bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
4222     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4223     SET_VREG(r1, r9)               @ vAA<- r1
4224     GOTO_OPCODE(ip)                     @ jump to next instruction
4225     /* 11-14 instructions */
4226
4227
4228 /* ------------------------------ */
4229     .balign 64
4230 .L_OP_AND_INT: /* 0x95 */
4231 /* File: armv5te/OP_AND_INT.S */
4232 /* File: armv5te/binop.S */
4233     /*
4234      * Generic 32-bit binary operation.  Provide an "instr" line that
4235      * specifies an instruction that performs "result = r0 op r1".
4236      * This could be an ARM instruction or a function call.  (If the result
4237      * comes back in a register other than r0, you can override "result".)
4238      *
4239      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4240      * vCC (r1).  Useful for integer division and modulus.  Note that we
4241      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4242      * handles it correctly.
4243      *
4244      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4245      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4246      *      mul-float, div-float, rem-float
4247      */
4248     /* binop vAA, vBB, vCC */
4249     FETCH(r0, 1)                        @ r0<- CCBB
4250     mov     r9, rINST, lsr #8           @ r9<- AA
4251     mov     r3, r0, lsr #8              @ r3<- CC
4252     and     r2, r0, #255                @ r2<- BB
4253     GET_VREG(r1, r3)                    @ r1<- vCC
4254     GET_VREG(r0, r2)                    @ r0<- vBB
4255     .if 0
4256     cmp     r1, #0                      @ is second operand zero?
4257     beq     common_errDivideByZero
4258     .endif
4259
4260     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4261                                @ optional op; may set condition codes
4262     and     r0, r0, r1                              @ r0<- op, r0-r3 changed
4263     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4264     SET_VREG(r0, r9)               @ vAA<- r0
4265     GOTO_OPCODE(ip)                     @ jump to next instruction
4266     /* 11-14 instructions */
4267
4268
4269 /* ------------------------------ */
4270     .balign 64
4271 .L_OP_OR_INT: /* 0x96 */
4272 /* File: armv5te/OP_OR_INT.S */
4273 /* File: armv5te/binop.S */
4274     /*
4275      * Generic 32-bit binary operation.  Provide an "instr" line that
4276      * specifies an instruction that performs "result = r0 op r1".
4277      * This could be an ARM instruction or a function call.  (If the result
4278      * comes back in a register other than r0, you can override "result".)
4279      *
4280      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4281      * vCC (r1).  Useful for integer division and modulus.  Note that we
4282      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4283      * handles it correctly.
4284      *
4285      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4286      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4287      *      mul-float, div-float, rem-float
4288      */
4289     /* binop vAA, vBB, vCC */
4290     FETCH(r0, 1)                        @ r0<- CCBB
4291     mov     r9, rINST, lsr #8           @ r9<- AA
4292     mov     r3, r0, lsr #8              @ r3<- CC
4293     and     r2, r0, #255                @ r2<- BB
4294     GET_VREG(r1, r3)                    @ r1<- vCC
4295     GET_VREG(r0, r2)                    @ r0<- vBB
4296     .if 0
4297     cmp     r1, #0                      @ is second operand zero?
4298     beq     common_errDivideByZero
4299     .endif
4300
4301     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4302                                @ optional op; may set condition codes
4303     orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
4304     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4305     SET_VREG(r0, r9)               @ vAA<- r0
4306     GOTO_OPCODE(ip)                     @ jump to next instruction
4307     /* 11-14 instructions */
4308
4309
4310 /* ------------------------------ */
4311     .balign 64
4312 .L_OP_XOR_INT: /* 0x97 */
4313 /* File: armv5te/OP_XOR_INT.S */
4314 /* File: armv5te/binop.S */
4315     /*
4316      * Generic 32-bit binary operation.  Provide an "instr" line that
4317      * specifies an instruction that performs "result = r0 op r1".
4318      * This could be an ARM instruction or a function call.  (If the result
4319      * comes back in a register other than r0, you can override "result".)
4320      *
4321      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4322      * vCC (r1).  Useful for integer division and modulus.  Note that we
4323      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4324      * handles it correctly.
4325      *
4326      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4327      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4328      *      mul-float, div-float, rem-float
4329      */
4330     /* binop vAA, vBB, vCC */
4331     FETCH(r0, 1)                        @ r0<- CCBB
4332     mov     r9, rINST, lsr #8           @ r9<- AA
4333     mov     r3, r0, lsr #8              @ r3<- CC
4334     and     r2, r0, #255                @ r2<- BB
4335     GET_VREG(r1, r3)                    @ r1<- vCC
4336     GET_VREG(r0, r2)                    @ r0<- vBB
4337     .if 0
4338     cmp     r1, #0                      @ is second operand zero?
4339     beq     common_errDivideByZero
4340     .endif
4341
4342     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4343                                @ optional op; may set condition codes
4344     eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
4345     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4346     SET_VREG(r0, r9)               @ vAA<- r0
4347     GOTO_OPCODE(ip)                     @ jump to next instruction
4348     /* 11-14 instructions */
4349
4350
4351 /* ------------------------------ */
4352     .balign 64
4353 .L_OP_SHL_INT: /* 0x98 */
4354 /* File: armv5te/OP_SHL_INT.S */
4355 /* File: armv5te/binop.S */
4356     /*
4357      * Generic 32-bit binary operation.  Provide an "instr" line that
4358      * specifies an instruction that performs "result = r0 op r1".
4359      * This could be an ARM instruction or a function call.  (If the result
4360      * comes back in a register other than r0, you can override "result".)
4361      *
4362      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4363      * vCC (r1).  Useful for integer division and modulus.  Note that we
4364      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4365      * handles it correctly.
4366      *
4367      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4368      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4369      *      mul-float, div-float, rem-float
4370      */
4371     /* binop vAA, vBB, vCC */
4372     FETCH(r0, 1)                        @ r0<- CCBB
4373     mov     r9, rINST, lsr #8           @ r9<- AA
4374     mov     r3, r0, lsr #8              @ r3<- CC
4375     and     r2, r0, #255                @ r2<- BB
4376     GET_VREG(r1, r3)                    @ r1<- vCC
4377     GET_VREG(r0, r2)                    @ r0<- vBB
4378     .if 0
4379     cmp     r1, #0                      @ is second operand zero?
4380     beq     common_errDivideByZero
4381     .endif
4382
4383     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4384     and     r1, r1, #31                           @ optional op; may set condition codes
4385     mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
4386     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4387     SET_VREG(r0, r9)               @ vAA<- r0
4388     GOTO_OPCODE(ip)                     @ jump to next instruction
4389     /* 11-14 instructions */
4390
4391
4392 /* ------------------------------ */
4393     .balign 64
4394 .L_OP_SHR_INT: /* 0x99 */
4395 /* File: armv5te/OP_SHR_INT.S */
4396 /* File: armv5te/binop.S */
4397     /*
4398      * Generic 32-bit binary operation.  Provide an "instr" line that
4399      * specifies an instruction that performs "result = r0 op r1".
4400      * This could be an ARM instruction or a function call.  (If the result
4401      * comes back in a register other than r0, you can override "result".)
4402      *
4403      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4404      * vCC (r1).  Useful for integer division and modulus.  Note that we
4405      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4406      * handles it correctly.
4407      *
4408      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4409      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4410      *      mul-float, div-float, rem-float
4411      */
4412     /* binop vAA, vBB, vCC */
4413     FETCH(r0, 1)                        @ r0<- CCBB
4414     mov     r9, rINST, lsr #8           @ r9<- AA
4415     mov     r3, r0, lsr #8              @ r3<- CC
4416     and     r2, r0, #255                @ r2<- BB
4417     GET_VREG(r1, r3)                    @ r1<- vCC
4418     GET_VREG(r0, r2)                    @ r0<- vBB
4419     .if 0
4420     cmp     r1, #0                      @ is second operand zero?
4421     beq     common_errDivideByZero
4422     .endif
4423
4424     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4425     and     r1, r1, #31                           @ optional op; may set condition codes
4426     mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
4427     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4428     SET_VREG(r0, r9)               @ vAA<- r0
4429     GOTO_OPCODE(ip)                     @ jump to next instruction
4430     /* 11-14 instructions */
4431
4432
4433 /* ------------------------------ */
4434     .balign 64
4435 .L_OP_USHR_INT: /* 0x9a */
4436 /* File: armv5te/OP_USHR_INT.S */
4437 /* File: armv5te/binop.S */
4438     /*
4439      * Generic 32-bit binary operation.  Provide an "instr" line that
4440      * specifies an instruction that performs "result = r0 op r1".
4441      * This could be an ARM instruction or a function call.  (If the result
4442      * comes back in a register other than r0, you can override "result".)
4443      *
4444      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4445      * vCC (r1).  Useful for integer division and modulus.  Note that we
4446      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4447      * handles it correctly.
4448      *
4449      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4450      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4451      *      mul-float, div-float, rem-float
4452      */
4453     /* binop vAA, vBB, vCC */
4454     FETCH(r0, 1)                        @ r0<- CCBB
4455     mov     r9, rINST, lsr #8           @ r9<- AA
4456     mov     r3, r0, lsr #8              @ r3<- CC
4457     and     r2, r0, #255                @ r2<- BB
4458     GET_VREG(r1, r3)                    @ r1<- vCC
4459     GET_VREG(r0, r2)                    @ r0<- vBB
4460     .if 0
4461     cmp     r1, #0                      @ is second operand zero?
4462     beq     common_errDivideByZero
4463     .endif
4464
4465     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4466     and     r1, r1, #31                           @ optional op; may set condition codes
4467     mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
4468     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4469     SET_VREG(r0, r9)               @ vAA<- r0
4470     GOTO_OPCODE(ip)                     @ jump to next instruction
4471     /* 11-14 instructions */
4472
4473
4474 /* ------------------------------ */
4475     .balign 64
4476 .L_OP_ADD_LONG: /* 0x9b */
4477 /* File: armv5te/OP_ADD_LONG.S */
4478 /* File: armv5te/binopWide.S */
4479     /*
4480      * Generic 64-bit binary operation.  Provide an "instr" line that
4481      * specifies an instruction that performs "result = r0-r1 op r2-r3".
4482      * This could be an ARM instruction or a function call.  (If the result
4483      * comes back in a register other than r0, you can override "result".)
4484      *
4485      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4486      * vCC (r1).  Useful for integer division and modulus.
4487      *
4488      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4489      *      xor-long, add-double, sub-double, mul-double, div-double,
4490      *      rem-double
4491      *
4492      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4493      */
4494     /* binop vAA, vBB, vCC */
4495     FETCH(r0, 1)                        @ r0<- CCBB
4496     mov     r9, rINST, lsr #8           @ r9<- AA
4497     and     r2, r0, #255                @ r2<- BB
4498     mov     r3, r0, lsr #8              @ r3<- CC
4499     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4500     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4501     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4502     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4503     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4504     .if 0
4505     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4506     beq     common_errDivideByZero
4507     .endif
4508     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4509
4510     adds    r0, r0, r2                           @ optional op; may set condition codes
4511     adc     r1, r1, r3                              @ result<- op, r0-r3 changed
4512     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4513     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4514     GOTO_OPCODE(ip)                     @ jump to next instruction
4515     /* 14-17 instructions */
4516
4517
4518 /* ------------------------------ */
4519     .balign 64
4520 .L_OP_SUB_LONG: /* 0x9c */
4521 /* File: armv5te/OP_SUB_LONG.S */
4522 /* File: armv5te/binopWide.S */
4523     /*
4524      * Generic 64-bit binary operation.  Provide an "instr" line that
4525      * specifies an instruction that performs "result = r0-r1 op r2-r3".
4526      * This could be an ARM instruction or a function call.  (If the result
4527      * comes back in a register other than r0, you can override "result".)
4528      *
4529      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4530      * vCC (r1).  Useful for integer division and modulus.
4531      *
4532      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4533      *      xor-long, add-double, sub-double, mul-double, div-double,
4534      *      rem-double
4535      *
4536      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4537      */
4538     /* binop vAA, vBB, vCC */
4539     FETCH(r0, 1)                        @ r0<- CCBB
4540     mov     r9, rINST, lsr #8           @ r9<- AA
4541     and     r2, r0, #255                @ r2<- BB
4542     mov     r3, r0, lsr #8              @ r3<- CC
4543     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4544     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4545     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4546     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4547     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4548     .if 0
4549     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4550     beq     common_errDivideByZero
4551     .endif
4552     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4553
4554     subs    r0, r0, r2                           @ optional op; may set condition codes
4555     sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
4556     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4557     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4558     GOTO_OPCODE(ip)                     @ jump to next instruction
4559     /* 14-17 instructions */
4560
4561
4562 /* ------------------------------ */
4563     .balign 64
4564 .L_OP_MUL_LONG: /* 0x9d */
4565 /* File: armv5te/OP_MUL_LONG.S */
4566     /*
4567      * Signed 64-bit integer multiply.
4568      *
4569      * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
4570      *        WX
4571      *      x YZ
4572      *  --------
4573      *     ZW ZX
4574      *  YW YX
4575      *
4576      * The low word of the result holds ZX, the high word holds
4577      * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
4578      * it doesn't fit in the low 64 bits.
4579      *
4580      * Unlike most ARM math operations, multiply instructions have
4581      * restrictions on using the same register more than once (Rd and Rm
4582      * cannot be the same).
4583      */
4584     /* mul-long vAA, vBB, vCC */
4585     FETCH(r0, 1)                        @ r0<- CCBB
4586     and     r2, r0, #255                @ r2<- BB
4587     mov     r3, r0, lsr #8              @ r3<- CC
4588     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4589     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4590     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4591     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4592     mul     ip, r2, r1                  @  ip<- ZxW
4593     umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
4594     mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
4595     mov     r0, rINST, lsr #8           @ r0<- AA
4596     add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
4597     add     r0, rFP, r0, lsl #2         @ r0<- &fp[AA]
4598     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4599     b       .LOP_MUL_LONG_finish
4600
4601 /* ------------------------------ */
4602     .balign 64
4603 .L_OP_DIV_LONG: /* 0x9e */
4604 /* File: armv5te/OP_DIV_LONG.S */
4605 /* File: armv5te/binopWide.S */
4606     /*
4607      * Generic 64-bit binary operation.  Provide an "instr" line that
4608      * specifies an instruction that performs "result = r0-r1 op r2-r3".
4609      * This could be an ARM instruction or a function call.  (If the result
4610      * comes back in a register other than r0, you can override "result".)
4611      *
4612      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4613      * vCC (r1).  Useful for integer division and modulus.
4614      *
4615      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4616      *      xor-long, add-double, sub-double, mul-double, div-double,
4617      *      rem-double
4618      *
4619      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4620      */
4621     /* binop vAA, vBB, vCC */
4622     FETCH(r0, 1)                        @ r0<- CCBB
4623     mov     r9, rINST, lsr #8           @ r9<- AA
4624     and     r2, r0, #255                @ r2<- BB
4625     mov     r3, r0, lsr #8              @ r3<- CC
4626     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4627     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4628     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4629     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4630     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4631     .if 1
4632     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4633     beq     common_errDivideByZero
4634     .endif
4635     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4636
4637                                @ optional op; may set condition codes
4638     bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4639     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4640     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4641     GOTO_OPCODE(ip)                     @ jump to next instruction
4642     /* 14-17 instructions */
4643
4644
4645 /* ------------------------------ */
4646     .balign 64
4647 .L_OP_REM_LONG: /* 0x9f */
4648 /* File: armv5te/OP_REM_LONG.S */
4649 /* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
4650 /* File: armv5te/binopWide.S */
4651     /*
4652      * Generic 64-bit binary operation.  Provide an "instr" line that
4653      * specifies an instruction that performs "result = r0-r1 op r2-r3".
4654      * This could be an ARM instruction or a function call.  (If the result
4655      * comes back in a register other than r0, you can override "result".)
4656      *
4657      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4658      * vCC (r1).  Useful for integer division and modulus.
4659      *
4660      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4661      *      xor-long, add-double, sub-double, mul-double, div-double,
4662      *      rem-double
4663      *
4664      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4665      */
4666     /* binop vAA, vBB, vCC */
4667     FETCH(r0, 1)                        @ r0<- CCBB
4668     mov     r9, rINST, lsr #8           @ r9<- AA
4669     and     r2, r0, #255                @ r2<- BB
4670     mov     r3, r0, lsr #8              @ r3<- CC
4671     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4672     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4673     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4674     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4675     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4676     .if 1
4677     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4678     beq     common_errDivideByZero
4679     .endif
4680     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4681
4682                                @ optional op; may set condition codes
4683     bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4684     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4685     stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
4686     GOTO_OPCODE(ip)                     @ jump to next instruction
4687     /* 14-17 instructions */
4688
4689
4690 /* ------------------------------ */
4691     .balign 64
4692 .L_OP_AND_LONG: /* 0xa0 */
4693 /* File: armv5te/OP_AND_LONG.S */
4694 /* File: armv5te/binopWide.S */
4695     /*
4696      * Generic 64-bit binary operation.  Provide an "instr" line that
4697      * specifies an instruction that performs "result = r0-r1 op r2-r3".
4698      * This could be an ARM instruction or a function call.  (If the result
4699      * comes back in a register other than r0, you can override "result".)
4700      *
4701      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4702      * vCC (r1).  Useful for integer division and modulus.
4703      *
4704      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4705      *      xor-long, add-double, sub-double, mul-double, div-double,
4706      *      rem-double
4707      *
4708      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4709      */
4710     /* binop vAA, vBB, vCC */
4711     FETCH(r0, 1)                        @ r0<- CCBB
4712     mov     r9, rINST, lsr #8           @ r9<- AA
4713     and     r2, r0, #255                @ r2<- BB
4714     mov     r3, r0, lsr #8              @ r3<- CC
4715     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4716     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4717     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4718     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4719     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4720     .if 0
4721     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4722     beq     common_errDivideByZero
4723     .endif
4724     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4725
4726     and     r0, r0, r2                           @ optional op; may set condition codes
4727     and     r1, r1, r3                              @ result<- op, r0-r3 changed
4728     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4729     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4730     GOTO_OPCODE(ip)                     @ jump to next instruction
4731     /* 14-17 instructions */
4732
4733
4734 /* ------------------------------ */
4735     .balign 64
4736 .L_OP_OR_LONG: /* 0xa1 */
4737 /* File: armv5te/OP_OR_LONG.S */
4738 /* File: armv5te/binopWide.S */
4739     /*
4740      * Generic 64-bit binary operation.  Provide an "instr" line that
4741      * specifies an instruction that performs "result = r0-r1 op r2-r3".
4742      * This could be an ARM instruction or a function call.  (If the result
4743      * comes back in a register other than r0, you can override "result".)
4744      *
4745      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4746      * vCC (r1).  Useful for integer division and modulus.
4747      *
4748      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4749      *      xor-long, add-double, sub-double, mul-double, div-double,
4750      *      rem-double
4751      *
4752      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4753      */
4754     /* binop vAA, vBB, vCC */
4755     FETCH(r0, 1)                        @ r0<- CCBB
4756     mov     r9, rINST, lsr #8           @ r9<- AA
4757     and     r2, r0, #255                @ r2<- BB
4758     mov     r3, r0, lsr #8              @ r3<- CC
4759     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4760     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4761     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4762     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4763     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4764     .if 0
4765     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4766     beq     common_errDivideByZero
4767     .endif
4768     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4769
4770     orr     r0, r0, r2                           @ optional op; may set condition codes
4771     orr     r1, r1, r3                              @ result<- op, r0-r3 changed
4772     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4773     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4774     GOTO_OPCODE(ip)                     @ jump to next instruction
4775     /* 14-17 instructions */
4776
4777
4778 /* ------------------------------ */
4779     .balign 64
4780 .L_OP_XOR_LONG: /* 0xa2 */
4781 /* File: armv5te/OP_XOR_LONG.S */
4782 /* File: armv5te/binopWide.S */
4783     /*
4784      * Generic 64-bit binary operation.  Provide an "instr" line that
4785      * specifies an instruction that performs "result = r0-r1 op r2-r3".
4786      * This could be an ARM instruction or a function call.  (If the result
4787      * comes back in a register other than r0, you can override "result".)
4788      *
4789      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4790      * vCC (r1).  Useful for integer division and modulus.
4791      *
4792      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4793      *      xor-long, add-double, sub-double, mul-double, div-double,
4794      *      rem-double
4795      *
4796      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4797      */
4798     /* binop vAA, vBB, vCC */
4799     FETCH(r0, 1)                        @ r0<- CCBB
4800     mov     r9, rINST, lsr #8           @ r9<- AA
4801     and     r2, r0, #255                @ r2<- BB
4802     mov     r3, r0, lsr #8              @ r3<- CC
4803     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4804     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4805     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4806     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4807     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4808     .if 0
4809     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4810     beq     common_errDivideByZero
4811     .endif
4812     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4813
4814     eor     r0, r0, r2                           @ optional op; may set condition codes
4815     eor     r1, r1, r3                              @ result<- op, r0-r3 changed
4816     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4817     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4818     GOTO_OPCODE(ip)                     @ jump to next instruction
4819     /* 14-17 instructions */
4820
4821
4822 /* ------------------------------ */
4823     .balign 64
4824 .L_OP_SHL_LONG: /* 0xa3 */
4825 /* File: armv5te/OP_SHL_LONG.S */
4826     /*
4827      * Long integer shift.  This is different from the generic 32/64-bit
4828      * binary operations because vAA/vBB are 64-bit but vCC (the shift
4829      * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4830      * 6 bits of the shift distance.
4831      */
4832     /* shl-long vAA, vBB, vCC */
4833     FETCH(r0, 1)                        @ r0<- CCBB
4834     mov     r9, rINST, lsr #8           @ r9<- AA
4835     and     r3, r0, #255                @ r3<- BB
4836     mov     r0, r0, lsr #8              @ r0<- CC
4837     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4838     GET_VREG(r2, r0)                    @ r2<- vCC
4839     ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4840     and     r2, r2, #63                 @ r2<- r2 & 0x3f
4841     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4842
4843     mov     r1, r1, asl r2              @  r1<- r1 << r2
4844     rsb     r3, r2, #32                 @  r3<- 32 - r2
4845     orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
4846     subs    ip, r2, #32                 @  ip<- r2 - 32
4847     movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
4848     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4849     b       .LOP_SHL_LONG_finish
4850
4851 /* ------------------------------ */
4852     .balign 64
4853 .L_OP_SHR_LONG: /* 0xa4 */
4854 /* File: armv5te/OP_SHR_LONG.S */
4855     /*
4856      * Long integer shift.  This is different from the generic 32/64-bit
4857      * binary operations because vAA/vBB are 64-bit but vCC (the shift
4858      * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4859      * 6 bits of the shift distance.
4860      */
4861     /* shr-long vAA, vBB, vCC */
4862     FETCH(r0, 1)                        @ r0<- CCBB
4863     mov     r9, rINST, lsr #8           @ r9<- AA
4864     and     r3, r0, #255                @ r3<- BB
4865     mov     r0, r0, lsr #8              @ r0<- CC
4866     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4867     GET_VREG(r2, r0)                    @ r2<- vCC
4868     ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4869     and     r2, r2, #63                 @ r0<- r0 & 0x3f
4870     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4871
4872     mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4873     rsb     r3, r2, #32                 @  r3<- 32 - r2
4874     orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4875     subs    ip, r2, #32                 @  ip<- r2 - 32
4876     movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
4877     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4878     b       .LOP_SHR_LONG_finish
4879
4880 /* ------------------------------ */
4881     .balign 64
4882 .L_OP_USHR_LONG: /* 0xa5 */
4883 /* File: armv5te/OP_USHR_LONG.S */
4884     /*
4885      * Long integer shift.  This is different from the generic 32/64-bit
4886      * binary operations because vAA/vBB are 64-bit but vCC (the shift
4887      * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4888      * 6 bits of the shift distance.
4889      */
4890     /* ushr-long vAA, vBB, vCC */
4891     FETCH(r0, 1)                        @ r0<- CCBB
4892     mov     r9, rINST, lsr #8           @ r9<- AA
4893     and     r3, r0, #255                @ r3<- BB
4894     mov     r0, r0, lsr #8              @ r0<- CC
4895     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4896     GET_VREG(r2, r0)                    @ r2<- vCC
4897     ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4898     and     r2, r2, #63                 @ r0<- r0 & 0x3f
4899     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4900
4901     mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4902     rsb     r3, r2, #32                 @  r3<- 32 - r2
4903     orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4904     subs    ip, r2, #32                 @  ip<- r2 - 32
4905     movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
4906     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4907     b       .LOP_USHR_LONG_finish
4908
4909 /* ------------------------------ */
4910     .balign 64
4911 .L_OP_ADD_FLOAT: /* 0xa6 */
4912 /* File: arm-vfp/OP_ADD_FLOAT.S */
4913 /* File: arm-vfp/fbinop.S */
4914     /*
4915      * Generic 32-bit floating-point operation.  Provide an "instr" line that
4916      * specifies an instruction that performs "s2 = s0 op s1".  Because we
4917      * use the "softfp" ABI, this must be an instruction, not a function call.
4918      *
4919      * For: add-float, sub-float, mul-float, div-float
4920      */
4921     /* floatop vAA, vBB, vCC */
4922     FETCH(r0, 1)                        @ r0<- CCBB
4923     mov     r9, rINST, lsr #8           @ r9<- AA
4924     mov     r3, r0, lsr #8              @ r3<- CC
4925     and     r2, r0, #255                @ r2<- BB
4926     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
4927     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
4928     flds    s1, [r3]                    @ s1<- vCC
4929     flds    s0, [r2]                    @ s0<- vBB
4930
4931     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4932     fadds   s2, s0, s1                              @ s2<- op
4933     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4934     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
4935     fsts    s2, [r9]                    @ vAA<- s2
4936     GOTO_OPCODE(ip)                     @ jump to next instruction
4937
4938
4939 /* ------------------------------ */
4940     .balign 64
4941 .L_OP_SUB_FLOAT: /* 0xa7 */
4942 /* File: arm-vfp/OP_SUB_FLOAT.S */
4943 /* File: arm-vfp/fbinop.S */
4944     /*
4945      * Generic 32-bit floating-point operation.  Provide an "instr" line that
4946      * specifies an instruction that performs "s2 = s0 op s1".  Because we
4947      * use the "softfp" ABI, this must be an instruction, not a function call.
4948      *
4949      * For: add-float, sub-float, mul-float, div-float
4950      */
4951     /* floatop vAA, vBB, vCC */
4952     FETCH(r0, 1)                        @ r0<- CCBB
4953     mov     r9, rINST, lsr #8           @ r9<- AA
4954     mov     r3, r0, lsr #8              @ r3<- CC
4955     and     r2, r0, #255                @ r2<- BB
4956     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
4957     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
4958     flds    s1, [r3]                    @ s1<- vCC
4959     flds    s0, [r2]                    @ s0<- vBB
4960
4961     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4962     fsubs   s2, s0, s1                              @ s2<- op
4963     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4964     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
4965     fsts    s2, [r9]                    @ vAA<- s2
4966     GOTO_OPCODE(ip)                     @ jump to next instruction
4967
4968
4969 /* ------------------------------ */
4970     .balign 64
4971 .L_OP_MUL_FLOAT: /* 0xa8 */
4972 /* File: arm-vfp/OP_MUL_FLOAT.S */
4973 /* File: arm-vfp/fbinop.S */
4974     /*
4975      * Generic 32-bit floating-point operation.  Provide an "instr" line that
4976      * specifies an instruction that performs "s2 = s0 op s1".  Because we
4977      * use the "softfp" ABI, this must be an instruction, not a function call.
4978      *
4979      * For: add-float, sub-float, mul-float, div-float
4980      */
4981     /* floatop vAA, vBB, vCC */
4982     FETCH(r0, 1)                        @ r0<- CCBB
4983     mov     r9, rINST, lsr #8           @ r9<- AA
4984     mov     r3, r0, lsr #8              @ r3<- CC
4985     and     r2, r0, #255                @ r2<- BB
4986     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
4987     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
4988     flds    s1, [r3]                    @ s1<- vCC
4989     flds    s0, [r2]                    @ s0<- vBB
4990
4991     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4992     fmuls   s2, s0, s1                              @ s2<- op
4993     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4994     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
4995     fsts    s2, [r9]                    @ vAA<- s2
4996     GOTO_OPCODE(ip)                     @ jump to next instruction
4997
4998
4999 /* ------------------------------ */
5000     .balign 64
5001 .L_OP_DIV_FLOAT: /* 0xa9 */
5002 /* File: arm-vfp/OP_DIV_FLOAT.S */
5003 /* File: arm-vfp/fbinop.S */
5004     /*
5005      * Generic 32-bit floating-point operation.  Provide an "instr" line that
5006      * specifies an instruction that performs "s2 = s0 op s1".  Because we
5007      * use the "softfp" ABI, this must be an instruction, not a function call.
5008      *
5009      * For: add-float, sub-float, mul-float, div-float
5010      */
5011     /* floatop vAA, vBB, vCC */
5012     FETCH(r0, 1)                        @ r0<- CCBB
5013     mov     r9, rINST, lsr #8           @ r9<- AA
5014     mov     r3, r0, lsr #8              @ r3<- CC
5015     and     r2, r0, #255                @ r2<- BB
5016     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5017     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5018     flds    s1, [r3]                    @ s1<- vCC
5019     flds    s0, [r2]                    @ s0<- vBB
5020
5021     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5022     fdivs   s2, s0, s1                              @ s2<- op
5023     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5024     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5025     fsts    s2, [r9]                    @ vAA<- s2
5026     GOTO_OPCODE(ip)                     @ jump to next instruction
5027
5028
5029 /* ------------------------------ */
5030     .balign 64
5031 .L_OP_REM_FLOAT: /* 0xaa */
5032 /* File: armv5te/OP_REM_FLOAT.S */
5033 /* EABI doesn't define a float remainder function, but libm does */
5034 /* File: armv5te/binop.S */
5035     /*
5036      * Generic 32-bit binary operation.  Provide an "instr" line that
5037      * specifies an instruction that performs "result = r0 op r1".
5038      * This could be an ARM instruction or a function call.  (If the result
5039      * comes back in a register other than r0, you can override "result".)
5040      *
5041      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5042      * vCC (r1).  Useful for integer division and modulus.  Note that we
5043      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5044      * handles it correctly.
5045      *
5046      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5047      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5048      *      mul-float, div-float, rem-float
5049      */
5050     /* binop vAA, vBB, vCC */
5051     FETCH(r0, 1)                        @ r0<- CCBB
5052     mov     r9, rINST, lsr #8           @ r9<- AA
5053     mov     r3, r0, lsr #8              @ r3<- CC
5054     and     r2, r0, #255                @ r2<- BB
5055     GET_VREG(r1, r3)                    @ r1<- vCC
5056     GET_VREG(r0, r2)                    @ r0<- vBB
5057     .if 0
5058     cmp     r1, #0                      @ is second operand zero?
5059     beq     common_errDivideByZero
5060     .endif
5061
5062     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5063                                @ optional op; may set condition codes
5064     bl      fmodf                              @ r0<- op, r0-r3 changed
5065     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5066     SET_VREG(r0, r9)               @ vAA<- r0
5067     GOTO_OPCODE(ip)                     @ jump to next instruction
5068     /* 11-14 instructions */
5069
5070
5071 /* ------------------------------ */
5072     .balign 64
5073 .L_OP_ADD_DOUBLE: /* 0xab */
5074 /* File: arm-vfp/OP_ADD_DOUBLE.S */
5075 /* File: arm-vfp/fbinopWide.S */
5076     /*
5077      * Generic 64-bit double-precision floating point binary operation.
5078      * Provide an "instr" line that specifies an instruction that performs
5079      * "d2 = d0 op d1".
5080      *
5081      * for: add-double, sub-double, mul-double, div-double
5082      */
5083     /* doubleop vAA, vBB, vCC */
5084     FETCH(r0, 1)                        @ r0<- CCBB
5085     mov     r9, rINST, lsr #8           @ r9<- AA
5086     mov     r3, r0, lsr #8              @ r3<- CC
5087     and     r2, r0, #255                @ r2<- BB
5088     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5089     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5090     fldd    d1, [r3]                    @ d1<- vCC
5091     fldd    d0, [r2]                    @ d0<- vBB
5092
5093     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5094     faddd   d2, d0, d1                              @ s2<- op
5095     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5096     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5097     fstd    d2, [r9]                    @ vAA<- d2
5098     GOTO_OPCODE(ip)                     @ jump to next instruction
5099
5100
5101 /* ------------------------------ */
5102     .balign 64
5103 .L_OP_SUB_DOUBLE: /* 0xac */
5104 /* File: arm-vfp/OP_SUB_DOUBLE.S */
5105 /* File: arm-vfp/fbinopWide.S */
5106     /*
5107      * Generic 64-bit double-precision floating point binary operation.
5108      * Provide an "instr" line that specifies an instruction that performs
5109      * "d2 = d0 op d1".
5110      *
5111      * for: add-double, sub-double, mul-double, div-double
5112      */
5113     /* doubleop vAA, vBB, vCC */
5114     FETCH(r0, 1)                        @ r0<- CCBB
5115     mov     r9, rINST, lsr #8           @ r9<- AA
5116     mov     r3, r0, lsr #8              @ r3<- CC
5117     and     r2, r0, #255                @ r2<- BB
5118     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5119     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5120     fldd    d1, [r3]                    @ d1<- vCC
5121     fldd    d0, [r2]                    @ d0<- vBB
5122
5123     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5124     fsubd   d2, d0, d1                              @ s2<- op
5125     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5126     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5127     fstd    d2, [r9]                    @ vAA<- d2
5128     GOTO_OPCODE(ip)                     @ jump to next instruction
5129
5130
5131 /* ------------------------------ */
5132     .balign 64
5133 .L_OP_MUL_DOUBLE: /* 0xad */
5134 /* File: arm-vfp/OP_MUL_DOUBLE.S */
5135 /* File: arm-vfp/fbinopWide.S */
5136     /*
5137      * Generic 64-bit double-precision floating point binary operation.
5138      * Provide an "instr" line that specifies an instruction that performs
5139      * "d2 = d0 op d1".
5140      *
5141      * for: add-double, sub-double, mul-double, div-double
5142      */
5143     /* doubleop vAA, vBB, vCC */
5144     FETCH(r0, 1)                        @ r0<- CCBB
5145     mov     r9, rINST, lsr #8           @ r9<- AA
5146     mov     r3, r0, lsr #8              @ r3<- CC
5147     and     r2, r0, #255                @ r2<- BB
5148     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5149     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5150     fldd    d1, [r3]                    @ d1<- vCC
5151     fldd    d0, [r2]                    @ d0<- vBB
5152
5153     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5154     fmuld   d2, d0, d1                              @ s2<- op
5155     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5156     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5157     fstd    d2, [r9]                    @ vAA<- d2
5158     GOTO_OPCODE(ip)                     @ jump to next instruction
5159
5160
5161 /* ------------------------------ */
5162     .balign 64
5163 .L_OP_DIV_DOUBLE: /* 0xae */
5164 /* File: arm-vfp/OP_DIV_DOUBLE.S */
5165 /* File: arm-vfp/fbinopWide.S */
5166     /*
5167      * Generic 64-bit double-precision floating point binary operation.
5168      * Provide an "instr" line that specifies an instruction that performs
5169      * "d2 = d0 op d1".
5170      *
5171      * for: add-double, sub-double, mul-double, div-double
5172      */
5173     /* doubleop vAA, vBB, vCC */
5174     FETCH(r0, 1)                        @ r0<- CCBB
5175     mov     r9, rINST, lsr #8           @ r9<- AA
5176     mov     r3, r0, lsr #8              @ r3<- CC
5177     and     r2, r0, #255                @ r2<- BB
5178     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5179     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5180     fldd    d1, [r3]                    @ d1<- vCC
5181     fldd    d0, [r2]                    @ d0<- vBB
5182
5183     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5184     fdivd   d2, d0, d1                              @ s2<- op
5185     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5186     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5187     fstd    d2, [r9]                    @ vAA<- d2
5188     GOTO_OPCODE(ip)                     @ jump to next instruction
5189
5190
5191 /* ------------------------------ */
5192     .balign 64
5193 .L_OP_REM_DOUBLE: /* 0xaf */
5194 /* File: armv5te/OP_REM_DOUBLE.S */
5195 /* EABI doesn't define a double remainder function, but libm does */
5196 /* File: armv5te/binopWide.S */
5197     /*
5198      * Generic 64-bit binary operation.  Provide an "instr" line that
5199      * specifies an instruction that performs "result = r0-r1 op r2-r3".
5200      * This could be an ARM instruction or a function call.  (If the result
5201      * comes back in a register other than r0, you can override "result".)
5202      *
5203      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5204      * vCC (r1).  Useful for integer division and modulus.
5205      *
5206      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5207      *      xor-long, add-double, sub-double, mul-double, div-double,
5208      *      rem-double
5209      *
5210      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5211      */
5212     /* binop vAA, vBB, vCC */
5213     FETCH(r0, 1)                        @ r0<- CCBB
5214     mov     r9, rINST, lsr #8           @ r9<- AA
5215     and     r2, r0, #255                @ r2<- BB
5216     mov     r3, r0, lsr #8              @ r3<- CC
5217     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5218     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5219     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5220     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5221     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5222     .if 0
5223     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5224     beq     common_errDivideByZero
5225     .endif
5226     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5227
5228                                @ optional op; may set condition codes
5229     bl      fmod                              @ result<- op, r0-r3 changed
5230     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5231     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5232     GOTO_OPCODE(ip)                     @ jump to next instruction
5233     /* 14-17 instructions */
5234
5235
5236 /* ------------------------------ */
5237     .balign 64
5238 .L_OP_ADD_INT_2ADDR: /* 0xb0 */
5239 /* File: armv5te/OP_ADD_INT_2ADDR.S */
5240 /* File: armv5te/binop2addr.S */
5241     /*
5242      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5243      * that specifies an instruction that performs "result = r0 op r1".
5244      * This could be an ARM instruction or a function call.  (If the result
5245      * comes back in a register other than r0, you can override "result".)
5246      *
5247      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5248      * vCC (r1).  Useful for integer division and modulus.
5249      *
5250      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5251      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5252      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5253      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5254      */
5255     /* binop/2addr vA, vB */
5256     mov     r9, rINST, lsr #8           @ r9<- A+
5257     mov     r3, rINST, lsr #12          @ r3<- B
5258     and     r9, r9, #15
5259     GET_VREG(r1, r3)                    @ r1<- vB
5260     GET_VREG(r0, r9)                    @ r0<- vA
5261     .if 0
5262     cmp     r1, #0                      @ is second operand zero?
5263     beq     common_errDivideByZero
5264     .endif
5265     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5266
5267                                @ optional op; may set condition codes
5268     add     r0, r0, r1                              @ r0<- op, r0-r3 changed
5269     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5270     SET_VREG(r0, r9)               @ vAA<- r0
5271     GOTO_OPCODE(ip)                     @ jump to next instruction
5272     /* 10-13 instructions */
5273
5274
5275 /* ------------------------------ */
5276     .balign 64
5277 .L_OP_SUB_INT_2ADDR: /* 0xb1 */
5278 /* File: armv5te/OP_SUB_INT_2ADDR.S */
5279 /* File: armv5te/binop2addr.S */
5280     /*
5281      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5282      * that specifies an instruction that performs "result = r0 op r1".
5283      * This could be an ARM instruction or a function call.  (If the result
5284      * comes back in a register other than r0, you can override "result".)
5285      *
5286      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5287      * vCC (r1).  Useful for integer division and modulus.
5288      *
5289      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5290      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5291      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5292      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5293      */
5294     /* binop/2addr vA, vB */
5295     mov     r9, rINST, lsr #8           @ r9<- A+
5296     mov     r3, rINST, lsr #12          @ r3<- B
5297     and     r9, r9, #15
5298     GET_VREG(r1, r3)                    @ r1<- vB
5299     GET_VREG(r0, r9)                    @ r0<- vA
5300     .if 0
5301     cmp     r1, #0                      @ is second operand zero?
5302     beq     common_errDivideByZero
5303     .endif
5304     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5305
5306                                @ optional op; may set condition codes
5307     sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
5308     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5309     SET_VREG(r0, r9)               @ vAA<- r0
5310     GOTO_OPCODE(ip)                     @ jump to next instruction
5311     /* 10-13 instructions */
5312
5313
5314 /* ------------------------------ */
5315     .balign 64
5316 .L_OP_MUL_INT_2ADDR: /* 0xb2 */
5317 /* File: armv5te/OP_MUL_INT_2ADDR.S */
5318 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
5319 /* File: armv5te/binop2addr.S */
5320     /*
5321      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5322      * that specifies an instruction that performs "result = r0 op r1".
5323      * This could be an ARM instruction or a function call.  (If the result
5324      * comes back in a register other than r0, you can override "result".)
5325      *
5326      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5327      * vCC (r1).  Useful for integer division and modulus.
5328      *
5329      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5330      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5331      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5332      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5333      */
5334     /* binop/2addr vA, vB */
5335     mov     r9, rINST, lsr #8           @ r9<- A+
5336     mov     r3, rINST, lsr #12          @ r3<- B
5337     and     r9, r9, #15
5338     GET_VREG(r1, r3)                    @ r1<- vB
5339     GET_VREG(r0, r9)                    @ r0<- vA
5340     .if 0
5341     cmp     r1, #0                      @ is second operand zero?
5342     beq     common_errDivideByZero
5343     .endif
5344     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5345
5346                                @ optional op; may set condition codes
5347     mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
5348     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5349     SET_VREG(r0, r9)               @ vAA<- r0
5350     GOTO_OPCODE(ip)                     @ jump to next instruction
5351     /* 10-13 instructions */
5352
5353
5354 /* ------------------------------ */
5355     .balign 64
5356 .L_OP_DIV_INT_2ADDR: /* 0xb3 */
5357 /* File: armv5te/OP_DIV_INT_2ADDR.S */
5358 /* File: armv5te/binop2addr.S */
5359     /*
5360      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5361      * that specifies an instruction that performs "result = r0 op r1".
5362      * This could be an ARM instruction or a function call.  (If the result
5363      * comes back in a register other than r0, you can override "result".)
5364      *
5365      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5366      * vCC (r1).  Useful for integer division and modulus.
5367      *
5368      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5369      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5370      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5371      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5372      */
5373     /* binop/2addr vA, vB */
5374     mov     r9, rINST, lsr #8           @ r9<- A+
5375     mov     r3, rINST, lsr #12          @ r3<- B
5376     and     r9, r9, #15
5377     GET_VREG(r1, r3)                    @ r1<- vB
5378     GET_VREG(r0, r9)                    @ r0<- vA
5379     .if 1
5380     cmp     r1, #0                      @ is second operand zero?
5381     beq     common_errDivideByZero
5382     .endif
5383     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5384
5385                                @ optional op; may set condition codes
5386     bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
5387     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5388     SET_VREG(r0, r9)               @ vAA<- r0
5389     GOTO_OPCODE(ip)                     @ jump to next instruction
5390     /* 10-13 instructions */
5391
5392
5393 /* ------------------------------ */
5394     .balign 64
5395 .L_OP_REM_INT_2ADDR: /* 0xb4 */
5396 /* File: armv5te/OP_REM_INT_2ADDR.S */
5397 /* idivmod returns quotient in r0 and remainder in r1 */
5398 /* File: armv5te/binop2addr.S */
5399     /*
5400      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5401      * that specifies an instruction that performs "result = r0 op r1".
5402      * This could be an ARM instruction or a function call.  (If the result
5403      * comes back in a register other than r0, you can override "result".)
5404      *
5405      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5406      * vCC (r1).  Useful for integer division and modulus.
5407      *
5408      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5409      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5410      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5411      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5412      */
5413     /* binop/2addr vA, vB */
5414     mov     r9, rINST, lsr #8           @ r9<- A+
5415     mov     r3, rINST, lsr #12          @ r3<- B
5416     and     r9, r9, #15
5417     GET_VREG(r1, r3)                    @ r1<- vB
5418     GET_VREG(r0, r9)                    @ r0<- vA
5419     .if 1
5420     cmp     r1, #0                      @ is second operand zero?
5421     beq     common_errDivideByZero
5422     .endif
5423     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5424
5425                                @ optional op; may set condition codes
5426     bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
5427     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5428     SET_VREG(r1, r9)               @ vAA<- r1
5429     GOTO_OPCODE(ip)                     @ jump to next instruction
5430     /* 10-13 instructions */
5431
5432
5433 /* ------------------------------ */
5434     .balign 64
5435 .L_OP_AND_INT_2ADDR: /* 0xb5 */
5436 /* File: armv5te/OP_AND_INT_2ADDR.S */
5437 /* File: armv5te/binop2addr.S */
5438     /*
5439      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5440      * that specifies an instruction that performs "result = r0 op r1".
5441      * This could be an ARM instruction or a function call.  (If the result
5442      * comes back in a register other than r0, you can override "result".)
5443      *
5444      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5445      * vCC (r1).  Useful for integer division and modulus.
5446      *
5447      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5448      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5449      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5450      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5451      */
5452     /* binop/2addr vA, vB */
5453     mov     r9, rINST, lsr #8           @ r9<- A+
5454     mov     r3, rINST, lsr #12          @ r3<- B
5455     and     r9, r9, #15
5456     GET_VREG(r1, r3)                    @ r1<- vB
5457     GET_VREG(r0, r9)                    @ r0<- vA
5458     .if 0
5459     cmp     r1, #0                      @ is second operand zero?
5460     beq     common_errDivideByZero
5461     .endif
5462     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5463
5464                                @ optional op; may set condition codes
5465     and     r0, r0, r1                              @ r0<- op, r0-r3 changed
5466     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5467     SET_VREG(r0, r9)               @ vAA<- r0
5468     GOTO_OPCODE(ip)                     @ jump to next instruction
5469     /* 10-13 instructions */
5470
5471
5472 /* ------------------------------ */
5473     .balign 64
5474 .L_OP_OR_INT_2ADDR: /* 0xb6 */
5475 /* File: armv5te/OP_OR_INT_2ADDR.S */
5476 /* File: armv5te/binop2addr.S */
5477     /*
5478      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5479      * that specifies an instruction that performs "result = r0 op r1".
5480      * This could be an ARM instruction or a function call.  (If the result
5481      * comes back in a register other than r0, you can override "result".)
5482      *
5483      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5484      * vCC (r1).  Useful for integer division and modulus.
5485      *
5486      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5487      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5488      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5489      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5490      */
5491     /* binop/2addr vA, vB */
5492     mov     r9, rINST, lsr #8           @ r9<- A+
5493     mov     r3, rINST, lsr #12          @ r3<- B
5494     and     r9, r9, #15
5495     GET_VREG(r1, r3)                    @ r1<- vB
5496     GET_VREG(r0, r9)                    @ r0<- vA
5497     .if 0
5498     cmp     r1, #0                      @ is second operand zero?
5499     beq     common_errDivideByZero
5500     .endif
5501     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5502
5503                                @ optional op; may set condition codes
5504     orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
5505     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5506     SET_VREG(r0, r9)               @ vAA<- r0
5507     GOTO_OPCODE(ip)                     @ jump to next instruction
5508     /* 10-13 instructions */
5509
5510
5511 /* ------------------------------ */
5512     .balign 64
5513 .L_OP_XOR_INT_2ADDR: /* 0xb7 */
5514 /* File: armv5te/OP_XOR_INT_2ADDR.S */
5515 /* File: armv5te/binop2addr.S */
5516     /*
5517      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5518      * that specifies an instruction that performs "result = r0 op r1".
5519      * This could be an ARM instruction or a function call.  (If the result
5520      * comes back in a register other than r0, you can override "result".)
5521      *
5522      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5523      * vCC (r1).  Useful for integer division and modulus.
5524      *
5525      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5526      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5527      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5528      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5529      */
5530     /* binop/2addr vA, vB */
5531     mov     r9, rINST, lsr #8           @ r9<- A+
5532     mov     r3, rINST, lsr #12          @ r3<- B
5533     and     r9, r9, #15
5534     GET_VREG(r1, r3)                    @ r1<- vB
5535     GET_VREG(r0, r9)                    @ r0<- vA
5536     .if 0
5537     cmp     r1, #0                      @ is second operand zero?
5538     beq     common_errDivideByZero
5539     .endif
5540     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5541
5542                                @ optional op; may set condition codes
5543     eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
5544     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5545     SET_VREG(r0, r9)               @ vAA<- r0
5546     GOTO_OPCODE(ip)                     @ jump to next instruction
5547     /* 10-13 instructions */
5548
5549
5550 /* ------------------------------ */
5551     .balign 64
5552 .L_OP_SHL_INT_2ADDR: /* 0xb8 */
5553 /* File: armv5te/OP_SHL_INT_2ADDR.S */
5554 /* File: armv5te/binop2addr.S */
5555     /*
5556      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5557      * that specifies an instruction that performs "result = r0 op r1".
5558      * This could be an ARM instruction or a function call.  (If the result
5559      * comes back in a register other than r0, you can override "result".)
5560      *
5561      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5562      * vCC (r1).  Useful for integer division and modulus.
5563      *
5564      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5565      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5566      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5567      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5568      */
5569     /* binop/2addr vA, vB */
5570     mov     r9, rINST, lsr #8           @ r9<- A+
5571     mov     r3, rINST, lsr #12          @ r3<- B
5572     and     r9, r9, #15
5573     GET_VREG(r1, r3)                    @ r1<- vB
5574     GET_VREG(r0, r9)                    @ r0<- vA
5575     .if 0
5576     cmp     r1, #0                      @ is second operand zero?
5577     beq     common_errDivideByZero
5578     .endif
5579     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5580
5581     and     r1, r1, #31                           @ optional op; may set condition codes
5582     mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
5583     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5584     SET_VREG(r0, r9)               @ vAA<- r0
5585     GOTO_OPCODE(ip)                     @ jump to next instruction
5586     /* 10-13 instructions */
5587
5588
5589 /* ------------------------------ */
5590     .balign 64
5591 .L_OP_SHR_INT_2ADDR: /* 0xb9 */
5592 /* File: armv5te/OP_SHR_INT_2ADDR.S */
5593 /* File: armv5te/binop2addr.S */
5594     /*
5595      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5596      * that specifies an instruction that performs "result = r0 op r1".
5597      * This could be an ARM instruction or a function call.  (If the result
5598      * comes back in a register other than r0, you can override "result".)
5599      *
5600      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5601      * vCC (r1).  Useful for integer division and modulus.
5602      *
5603      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5604      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5605      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5606      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5607      */
5608     /* binop/2addr vA, vB */
5609     mov     r9, rINST, lsr #8           @ r9<- A+
5610     mov     r3, rINST, lsr #12          @ r3<- B
5611     and     r9, r9, #15
5612     GET_VREG(r1, r3)                    @ r1<- vB
5613     GET_VREG(r0, r9)                    @ r0<- vA
5614     .if 0
5615     cmp     r1, #0                      @ is second operand zero?
5616     beq     common_errDivideByZero
5617     .endif
5618     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5619
5620     and     r1, r1, #31                           @ optional op; may set condition codes
5621     mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
5622     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5623     SET_VREG(r0, r9)               @ vAA<- r0
5624     GOTO_OPCODE(ip)                     @ jump to next instruction
5625     /* 10-13 instructions */
5626
5627
5628 /* ------------------------------ */
5629     .balign 64
5630 .L_OP_USHR_INT_2ADDR: /* 0xba */
5631 /* File: armv5te/OP_USHR_INT_2ADDR.S */
5632 /* File: armv5te/binop2addr.S */
5633     /*
5634      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5635      * that specifies an instruction that performs "result = r0 op r1".
5636      * This could be an ARM instruction or a function call.  (If the result
5637      * comes back in a register other than r0, you can override "result".)
5638      *
5639      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5640      * vCC (r1).  Useful for integer division and modulus.
5641      *
5642      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5643      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5644      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5645      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5646      */
5647     /* binop/2addr vA, vB */
5648     mov     r9, rINST, lsr #8           @ r9<- A+
5649     mov     r3, rINST, lsr #12          @ r3<- B
5650     and     r9, r9, #15
5651     GET_VREG(r1, r3)                    @ r1<- vB
5652     GET_VREG(r0, r9)                    @ r0<- vA
5653     .if 0
5654     cmp     r1, #0                      @ is second operand zero?
5655     beq     common_errDivideByZero
5656     .endif
5657     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5658
5659     and     r1, r1, #31                           @ optional op; may set condition codes
5660     mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
5661     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5662     SET_VREG(r0, r9)               @ vAA<- r0
5663     GOTO_OPCODE(ip)                     @ jump to next instruction
5664     /* 10-13 instructions */
5665
5666
5667 /* ------------------------------ */
5668     .balign 64
5669 .L_OP_ADD_LONG_2ADDR: /* 0xbb */
5670 /* File: armv5te/OP_ADD_LONG_2ADDR.S */
5671 /* File: armv5te/binopWide2addr.S */
5672     /*
5673      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5674      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5675      * This could be an ARM instruction or a function call.  (If the result
5676      * comes back in a register other than r0, you can override "result".)
5677      *
5678      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5679      * vCC (r1).  Useful for integer division and modulus.
5680      *
5681      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5682      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5683      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5684      *      rem-double/2addr
5685      */
5686     /* binop/2addr vA, vB */
5687     mov     r9, rINST, lsr #8           @ r9<- A+
5688     mov     r1, rINST, lsr #12          @ r1<- B
5689     and     r9, r9, #15
5690     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5691     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5692     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5693     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5694     .if 0
5695     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5696     beq     common_errDivideByZero
5697     .endif
5698     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5699
5700     adds    r0, r0, r2                           @ optional op; may set condition codes
5701     adc     r1, r1, r3                              @ result<- op, r0-r3 changed
5702     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5703     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5704     GOTO_OPCODE(ip)                     @ jump to next instruction
5705     /* 12-15 instructions */
5706
5707
5708 /* ------------------------------ */
5709     .balign 64
5710 .L_OP_SUB_LONG_2ADDR: /* 0xbc */
5711 /* File: armv5te/OP_SUB_LONG_2ADDR.S */
5712 /* File: armv5te/binopWide2addr.S */
5713     /*
5714      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5715      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5716      * This could be an ARM instruction or a function call.  (If the result
5717      * comes back in a register other than r0, you can override "result".)
5718      *
5719      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5720      * vCC (r1).  Useful for integer division and modulus.
5721      *
5722      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5723      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5724      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5725      *      rem-double/2addr
5726      */
5727     /* binop/2addr vA, vB */
5728     mov     r9, rINST, lsr #8           @ r9<- A+
5729     mov     r1, rINST, lsr #12          @ r1<- B
5730     and     r9, r9, #15
5731     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5732     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5733     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5734     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5735     .if 0
5736     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5737     beq     common_errDivideByZero
5738     .endif
5739     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5740
5741     subs    r0, r0, r2                           @ optional op; may set condition codes
5742     sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
5743     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5744     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5745     GOTO_OPCODE(ip)                     @ jump to next instruction
5746     /* 12-15 instructions */
5747
5748
5749 /* ------------------------------ */
5750     .balign 64
5751 .L_OP_MUL_LONG_2ADDR: /* 0xbd */
5752 /* File: armv5te/OP_MUL_LONG_2ADDR.S */
5753     /*
5754      * Signed 64-bit integer multiply, "/2addr" version.
5755      *
5756      * See OP_MUL_LONG for an explanation.
5757      *
5758      * We get a little tight on registers, so to avoid looking up &fp[A]
5759      * again we stuff it into rINST.
5760      */
5761     /* mul-long/2addr vA, vB */
5762     mov     r9, rINST, lsr #8           @ r9<- A+
5763     mov     r1, rINST, lsr #12          @ r1<- B
5764     and     r9, r9, #15
5765     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5766     add     rINST, rFP, r9, lsl #2      @ rINST<- &fp[A]
5767     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5768     ldmia   rINST, {r0-r1}              @ r0/r1<- vAA/vAA+1
5769     mul     ip, r2, r1                  @  ip<- ZxW
5770     umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
5771     mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
5772     mov     r0, rINST                   @ r0<- &fp[A] (free up rINST)
5773     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5774     add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
5775     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5776     stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
5777     GOTO_OPCODE(ip)                     @ jump to next instruction
5778
5779 /* ------------------------------ */
5780     .balign 64
5781 .L_OP_DIV_LONG_2ADDR: /* 0xbe */
5782 /* File: armv5te/OP_DIV_LONG_2ADDR.S */
5783 /* File: armv5te/binopWide2addr.S */
5784     /*
5785      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5786      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5787      * This could be an ARM instruction or a function call.  (If the result
5788      * comes back in a register other than r0, you can override "result".)
5789      *
5790      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5791      * vCC (r1).  Useful for integer division and modulus.
5792      *
5793      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5794      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5795      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5796      *      rem-double/2addr
5797      */
5798     /* binop/2addr vA, vB */
5799     mov     r9, rINST, lsr #8           @ r9<- A+
5800     mov     r1, rINST, lsr #12          @ r1<- B
5801     and     r9, r9, #15
5802     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5803     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5804     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5805     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5806     .if 1
5807     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5808     beq     common_errDivideByZero
5809     .endif
5810     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5811
5812                                @ optional op; may set condition codes
5813     bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5814     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5815     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5816     GOTO_OPCODE(ip)                     @ jump to next instruction
5817     /* 12-15 instructions */
5818
5819
5820 /* ------------------------------ */
5821     .balign 64
5822 .L_OP_REM_LONG_2ADDR: /* 0xbf */
5823 /* File: armv5te/OP_REM_LONG_2ADDR.S */
5824 /* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
5825 /* File: armv5te/binopWide2addr.S */
5826     /*
5827      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5828      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5829      * This could be an ARM instruction or a function call.  (If the result
5830      * comes back in a register other than r0, you can override "result".)
5831      *
5832      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5833      * vCC (r1).  Useful for integer division and modulus.
5834      *
5835      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5836      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5837      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5838      *      rem-double/2addr
5839      */
5840     /* binop/2addr vA, vB */
5841     mov     r9, rINST, lsr #8           @ r9<- A+
5842     mov     r1, rINST, lsr #12          @ r1<- B
5843     and     r9, r9, #15
5844     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5845     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5846     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5847     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5848     .if 1
5849     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5850     beq     common_errDivideByZero
5851     .endif
5852     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5853
5854                                @ optional op; may set condition codes
5855     bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5856     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5857     stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
5858     GOTO_OPCODE(ip)                     @ jump to next instruction
5859     /* 12-15 instructions */
5860
5861
5862 /* ------------------------------ */
5863     .balign 64
5864 .L_OP_AND_LONG_2ADDR: /* 0xc0 */
5865 /* File: armv5te/OP_AND_LONG_2ADDR.S */
5866 /* File: armv5te/binopWide2addr.S */
5867     /*
5868      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5869      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5870      * This could be an ARM instruction or a function call.  (If the result
5871      * comes back in a register other than r0, you can override "result".)
5872      *
5873      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5874      * vCC (r1).  Useful for integer division and modulus.
5875      *
5876      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5877      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5878      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5879      *      rem-double/2addr
5880      */
5881     /* binop/2addr vA, vB */
5882     mov     r9, rINST, lsr #8           @ r9<- A+
5883     mov     r1, rINST, lsr #12          @ r1<- B
5884     and     r9, r9, #15
5885     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5886     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5887     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5888     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5889     .if 0
5890     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5891     beq     common_errDivideByZero
5892     .endif
5893     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5894
5895     and     r0, r0, r2                           @ optional op; may set condition codes
5896     and     r1, r1, r3                              @ result<- op, r0-r3 changed
5897     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5898     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5899     GOTO_OPCODE(ip)                     @ jump to next instruction
5900     /* 12-15 instructions */
5901
5902
5903 /* ------------------------------ */
5904     .balign 64
5905 .L_OP_OR_LONG_2ADDR: /* 0xc1 */
5906 /* File: armv5te/OP_OR_LONG_2ADDR.S */
5907 /* File: armv5te/binopWide2addr.S */
5908     /*
5909      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5910      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5911      * This could be an ARM instruction or a function call.  (If the result
5912      * comes back in a register other than r0, you can override "result".)
5913      *
5914      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5915      * vCC (r1).  Useful for integer division and modulus.
5916      *
5917      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5918      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5919      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5920      *      rem-double/2addr
5921      */
5922     /* binop/2addr vA, vB */
5923     mov     r9, rINST, lsr #8           @ r9<- A+
5924     mov     r1, rINST, lsr #12          @ r1<- B
5925     and     r9, r9, #15
5926     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5927     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5928     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5929     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5930     .if 0
5931     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5932     beq     common_errDivideByZero
5933     .endif
5934     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5935
5936     orr     r0, r0, r2                           @ optional op; may set condition codes
5937     orr     r1, r1, r3                              @ result<- op, r0-r3 changed
5938     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5939     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5940     GOTO_OPCODE(ip)                     @ jump to next instruction
5941     /* 12-15 instructions */
5942
5943
5944 /* ------------------------------ */
5945     .balign 64
5946 .L_OP_XOR_LONG_2ADDR: /* 0xc2 */
5947 /* File: armv5te/OP_XOR_LONG_2ADDR.S */
5948 /* File: armv5te/binopWide2addr.S */
5949     /*
5950      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5951      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5952      * This could be an ARM instruction or a function call.  (If the result
5953      * comes back in a register other than r0, you can override "result".)
5954      *
5955      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5956      * vCC (r1).  Useful for integer division and modulus.
5957      *
5958      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5959      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5960      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5961      *      rem-double/2addr
5962      */
5963     /* binop/2addr vA, vB */
5964     mov     r9, rINST, lsr #8           @ r9<- A+
5965     mov     r1, rINST, lsr #12          @ r1<- B
5966     and     r9, r9, #15
5967     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5968     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5969     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5970     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5971     .if 0
5972     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5973     beq     common_errDivideByZero
5974     .endif
5975     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5976
5977     eor     r0, r0, r2                           @ optional op; may set condition codes
5978     eor     r1, r1, r3                              @ result<- op, r0-r3 changed
5979     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5980     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5981     GOTO_OPCODE(ip)                     @ jump to next instruction
5982     /* 12-15 instructions */
5983
5984
5985 /* ------------------------------ */
5986     .balign 64
5987 .L_OP_SHL_LONG_2ADDR: /* 0xc3 */
5988 /* File: armv5te/OP_SHL_LONG_2ADDR.S */
5989     /*
5990      * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
5991      * 32-bit shift distance.
5992      */
5993     /* shl-long/2addr vA, vB */
5994     mov     r9, rINST, lsr #8           @ r9<- A+
5995     mov     r3, rINST, lsr #12          @ r3<- B
5996     and     r9, r9, #15
5997     GET_VREG(r2, r3)                    @ r2<- vB
5998     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5999     and     r2, r2, #63                 @ r2<- r2 & 0x3f
6000     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6001
6002     mov     r1, r1, asl r2              @  r1<- r1 << r2
6003     rsb     r3, r2, #32                 @  r3<- 32 - r2
6004     orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
6005     subs    ip, r2, #32                 @  ip<- r2 - 32
6006     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6007     movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
6008     mov     r0, r0, asl r2              @  r0<- r0 << r2
6009     b       .LOP_SHL_LONG_2ADDR_finish
6010
6011 /* ------------------------------ */
6012     .balign 64
6013 .L_OP_SHR_LONG_2ADDR: /* 0xc4 */
6014 /* File: armv5te/OP_SHR_LONG_2ADDR.S */
6015     /*
6016      * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6017      * 32-bit shift distance.
6018      */
6019     /* shr-long/2addr vA, vB */
6020     mov     r9, rINST, lsr #8           @ r9<- A+
6021     mov     r3, rINST, lsr #12          @ r3<- B
6022     and     r9, r9, #15
6023     GET_VREG(r2, r3)                    @ r2<- vB
6024     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6025     and     r2, r2, #63                 @ r2<- r2 & 0x3f
6026     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6027
6028     mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6029     rsb     r3, r2, #32                 @  r3<- 32 - r2
6030     orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6031     subs    ip, r2, #32                 @  ip<- r2 - 32
6032     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6033     movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
6034     mov     r1, r1, asr r2              @  r1<- r1 >> r2
6035     b       .LOP_SHR_LONG_2ADDR_finish
6036
6037 /* ------------------------------ */
6038     .balign 64
6039 .L_OP_USHR_LONG_2ADDR: /* 0xc5 */
6040 /* File: armv5te/OP_USHR_LONG_2ADDR.S */
6041     /*
6042      * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6043      * 32-bit shift distance.
6044      */
6045     /* ushr-long/2addr vA, vB */
6046     mov     r9, rINST, lsr #8           @ r9<- A+
6047     mov     r3, rINST, lsr #12          @ r3<- B
6048     and     r9, r9, #15
6049     GET_VREG(r2, r3)                    @ r2<- vB
6050     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6051     and     r2, r2, #63                 @ r2<- r2 & 0x3f
6052     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6053
6054     mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6055     rsb     r3, r2, #32                 @  r3<- 32 - r2
6056     orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6057     subs    ip, r2, #32                 @  ip<- r2 - 32
6058     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6059     movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
6060     mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
6061     b       .LOP_USHR_LONG_2ADDR_finish
6062
6063 /* ------------------------------ */
6064     .balign 64
6065 .L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
6066 /* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */
6067 /* File: arm-vfp/fbinop2addr.S */
6068     /*
6069      * Generic 32-bit floating point "/2addr" binary operation.  Provide
6070      * an "instr" line that specifies an instruction that performs
6071      * "s2 = s0 op s1".
6072      *
6073      * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6074      */
6075     /* binop/2addr vA, vB */
6076     mov     r3, rINST, lsr #12          @ r3<- B
6077     mov     r9, rINST, lsr #8           @ r9<- A+
6078     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6079     and     r9, r9, #15                 @ r9<- A
6080     flds    s1, [r3]                    @ s1<- vB
6081     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6082     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6083     flds    s0, [r9]                    @ s0<- vA
6084
6085     fadds   s2, s0, s1                              @ s2<- op
6086     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6087     fsts    s2, [r9]                    @ vAA<- s2
6088     GOTO_OPCODE(ip)                     @ jump to next instruction
6089
6090
6091 /* ------------------------------ */
6092     .balign 64
6093 .L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
6094 /* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */
6095 /* File: arm-vfp/fbinop2addr.S */
6096     /*
6097      * Generic 32-bit floating point "/2addr" binary operation.  Provide
6098      * an "instr" line that specifies an instruction that performs
6099      * "s2 = s0 op s1".
6100      *
6101      * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6102      */
6103     /* binop/2addr vA, vB */
6104     mov     r3, rINST, lsr #12          @ r3<- B
6105     mov     r9, rINST, lsr #8           @ r9<- A+
6106     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6107     and     r9, r9, #15                 @ r9<- A
6108     flds    s1, [r3]                    @ s1<- vB
6109     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6110     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6111     flds    s0, [r9]                    @ s0<- vA
6112
6113     fsubs   s2, s0, s1                              @ s2<- op
6114     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6115     fsts    s2, [r9]                    @ vAA<- s2
6116     GOTO_OPCODE(ip)                     @ jump to next instruction
6117
6118
6119 /* ------------------------------ */
6120     .balign 64
6121 .L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
6122 /* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */
6123 /* File: arm-vfp/fbinop2addr.S */
6124     /*
6125      * Generic 32-bit floating point "/2addr" binary operation.  Provide
6126      * an "instr" line that specifies an instruction that performs
6127      * "s2 = s0 op s1".
6128      *
6129      * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6130      */
6131     /* binop/2addr vA, vB */
6132     mov     r3, rINST, lsr #12          @ r3<- B
6133     mov     r9, rINST, lsr #8           @ r9<- A+
6134     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6135     and     r9, r9, #15                 @ r9<- A
6136     flds    s1, [r3]                    @ s1<- vB
6137     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6138     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6139     flds    s0, [r9]                    @ s0<- vA
6140
6141     fmuls   s2, s0, s1                              @ s2<- op
6142     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6143     fsts    s2, [r9]                    @ vAA<- s2
6144     GOTO_OPCODE(ip)                     @ jump to next instruction
6145
6146
6147 /* ------------------------------ */
6148     .balign 64
6149 .L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
6150 /* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */
6151 /* File: arm-vfp/fbinop2addr.S */
6152     /*
6153      * Generic 32-bit floating point "/2addr" binary operation.  Provide
6154      * an "instr" line that specifies an instruction that performs
6155      * "s2 = s0 op s1".
6156      *
6157      * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6158      */
6159     /* binop/2addr vA, vB */
6160     mov     r3, rINST, lsr #12          @ r3<- B
6161     mov     r9, rINST, lsr #8           @ r9<- A+
6162     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6163     and     r9, r9, #15                 @ r9<- A
6164     flds    s1, [r3]                    @ s1<- vB
6165     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6166     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6167     flds    s0, [r9]                    @ s0<- vA
6168
6169     fdivs   s2, s0, s1                              @ s2<- op
6170     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6171     fsts    s2, [r9]                    @ vAA<- s2
6172     GOTO_OPCODE(ip)                     @ jump to next instruction
6173
6174
6175 /* ------------------------------ */
6176     .balign 64
6177 .L_OP_REM_FLOAT_2ADDR: /* 0xca */
6178 /* File: armv5te/OP_REM_FLOAT_2ADDR.S */
6179 /* EABI doesn't define a float remainder function, but libm does */
6180 /* File: armv5te/binop2addr.S */
6181     /*
6182      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6183      * that specifies an instruction that performs "result = r0 op r1".
6184      * This could be an ARM instruction or a function call.  (If the result
6185      * comes back in a register other than r0, you can override "result".)
6186      *
6187      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6188      * vCC (r1).  Useful for integer division and modulus.
6189      *
6190      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6191      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6192      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6193      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6194      */
6195     /* binop/2addr vA, vB */
6196     mov     r9, rINST, lsr #8           @ r9<- A+
6197     mov     r3, rINST, lsr #12          @ r3<- B
6198     and     r9, r9, #15
6199     GET_VREG(r1, r3)                    @ r1<- vB
6200     GET_VREG(r0, r9)                    @ r0<- vA
6201     .if 0
6202     cmp     r1, #0                      @ is second operand zero?
6203     beq     common_errDivideByZero
6204     .endif
6205     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6206
6207                                @ optional op; may set condition codes
6208     bl      fmodf                              @ r0<- op, r0-r3 changed
6209     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6210     SET_VREG(r0, r9)               @ vAA<- r0
6211     GOTO_OPCODE(ip)                     @ jump to next instruction
6212     /* 10-13 instructions */
6213
6214
6215 /* ------------------------------ */
6216     .balign 64
6217 .L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
6218 /* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */
6219 /* File: arm-vfp/fbinopWide2addr.S */
6220     /*
6221      * Generic 64-bit floating point "/2addr" binary operation.  Provide
6222      * an "instr" line that specifies an instruction that performs
6223      * "d2 = d0 op d1".
6224      *
6225      * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6226      *      div-double/2addr
6227      */
6228     /* binop/2addr vA, vB */
6229     mov     r3, rINST, lsr #12          @ r3<- B
6230     mov     r9, rINST, lsr #8           @ r9<- A+
6231     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6232     and     r9, r9, #15                 @ r9<- A
6233     fldd    d1, [r3]                    @ d1<- vB
6234     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6235     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6236     fldd    d0, [r9]                    @ d0<- vA
6237
6238     faddd   d2, d0, d1                              @ d2<- op
6239     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6240     fstd    d2, [r9]                    @ vAA<- d2
6241     GOTO_OPCODE(ip)                     @ jump to next instruction
6242
6243
6244 /* ------------------------------ */
6245     .balign 64
6246 .L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
6247 /* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */
6248 /* File: arm-vfp/fbinopWide2addr.S */
6249     /*
6250      * Generic 64-bit floating point "/2addr" binary operation.  Provide
6251      * an "instr" line that specifies an instruction that performs
6252      * "d2 = d0 op d1".
6253      *
6254      * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6255      *      div-double/2addr
6256      */
6257     /* binop/2addr vA, vB */
6258     mov     r3, rINST, lsr #12          @ r3<- B
6259     mov     r9, rINST, lsr #8           @ r9<- A+
6260     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6261     and     r9, r9, #15                 @ r9<- A
6262     fldd    d1, [r3]                    @ d1<- vB
6263     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6264     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6265     fldd    d0, [r9]                    @ d0<- vA
6266
6267     fsubd   d2, d0, d1                              @ d2<- op
6268     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6269     fstd    d2, [r9]                    @ vAA<- d2
6270     GOTO_OPCODE(ip)                     @ jump to next instruction
6271
6272
6273 /* ------------------------------ */
6274     .balign 64
6275 .L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
6276 /* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */
6277 /* File: arm-vfp/fbinopWide2addr.S */
6278     /*
6279      * Generic 64-bit floating point "/2addr" binary operation.  Provide
6280      * an "instr" line that specifies an instruction that performs
6281      * "d2 = d0 op d1".
6282      *
6283      * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6284      *      div-double/2addr
6285      */
6286     /* binop/2addr vA, vB */
6287     mov     r3, rINST, lsr #12          @ r3<- B
6288     mov     r9, rINST, lsr #8           @ r9<- A+
6289     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6290     and     r9, r9, #15                 @ r9<- A
6291     fldd    d1, [r3]                    @ d1<- vB
6292     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6293     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6294     fldd    d0, [r9]                    @ d0<- vA
6295
6296     fmuld   d2, d0, d1                              @ d2<- op
6297     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6298     fstd    d2, [r9]                    @ vAA<- d2
6299     GOTO_OPCODE(ip)                     @ jump to next instruction
6300
6301
6302 /* ------------------------------ */
6303     .balign 64
6304 .L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
6305 /* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */
6306 /* File: arm-vfp/fbinopWide2addr.S */
6307     /*
6308      * Generic 64-bit floating point "/2addr" binary operation.  Provide
6309      * an "instr" line that specifies an instruction that performs
6310      * "d2 = d0 op d1".
6311      *
6312      * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6313      *      div-double/2addr
6314      */
6315     /* binop/2addr vA, vB */
6316     mov     r3, rINST, lsr #12          @ r3<- B
6317     mov     r9, rINST, lsr #8           @ r9<- A+
6318     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6319     and     r9, r9, #15                 @ r9<- A
6320     fldd    d1, [r3]                    @ d1<- vB
6321     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6322     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6323     fldd    d0, [r9]                    @ d0<- vA
6324
6325     fdivd   d2, d0, d1                              @ d2<- op
6326     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6327     fstd    d2, [r9]                    @ vAA<- d2
6328     GOTO_OPCODE(ip)                     @ jump to next instruction
6329
6330
6331 /* ------------------------------ */
6332     .balign 64
6333 .L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
6334 /* File: armv5te/OP_REM_DOUBLE_2ADDR.S */
6335 /* EABI doesn't define a double remainder function, but libm does */
6336 /* File: armv5te/binopWide2addr.S */
6337     /*
6338      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6339      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6340      * This could be an ARM instruction or a function call.  (If the result
6341      * comes back in a register other than r0, you can override "result".)
6342      *
6343      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6344      * vCC (r1).  Useful for integer division and modulus.
6345      *
6346      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6347      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6348      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6349      *      rem-double/2addr
6350      */
6351     /* binop/2addr vA, vB */
6352     mov     r9, rINST, lsr #8           @ r9<- A+
6353     mov     r1, rINST, lsr #12          @ r1<- B
6354     and     r9, r9, #15
6355     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6356     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6357     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6358     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6359     .if 0
6360     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6361     beq     common_errDivideByZero
6362     .endif
6363     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6364
6365                                @ optional op; may set condition codes
6366     bl      fmod                              @ result<- op, r0-r3 changed
6367     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6368     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6369     GOTO_OPCODE(ip)                     @ jump to next instruction
6370     /* 12-15 instructions */
6371
6372
6373 /* ------------------------------ */
6374     .balign 64
6375 .L_OP_ADD_INT_LIT16: /* 0xd0 */
6376 /* File: armv5te/OP_ADD_INT_LIT16.S */
6377 /* File: armv5te/binopLit16.S */
6378     /*
6379      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6380      * that specifies an instruction that performs "result = r0 op r1".
6381      * This could be an ARM instruction or a function call.  (If the result
6382      * comes back in a register other than r0, you can override "result".)
6383      *
6384      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6385      * vCC (r1).  Useful for integer division and modulus.
6386      *
6387      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6388      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6389      */
6390     /* binop/lit16 vA, vB, #+CCCC */
6391     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6392     mov     r2, rINST, lsr #12          @ r2<- B
6393     mov     r9, rINST, lsr #8           @ r9<- A+
6394     GET_VREG(r0, r2)                    @ r0<- vB
6395     and     r9, r9, #15
6396     .if 0
6397     cmp     r1, #0                      @ is second operand zero?
6398     beq     common_errDivideByZero
6399     .endif
6400     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6401
6402     add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6403     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6404     SET_VREG(r0, r9)               @ vAA<- r0
6405     GOTO_OPCODE(ip)                     @ jump to next instruction
6406     /* 10-13 instructions */
6407
6408
6409 /* ------------------------------ */
6410     .balign 64
6411 .L_OP_RSUB_INT: /* 0xd1 */
6412 /* File: armv5te/OP_RSUB_INT.S */
6413 /* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
6414 /* File: armv5te/binopLit16.S */
6415     /*
6416      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6417      * that specifies an instruction that performs "result = r0 op r1".
6418      * This could be an ARM instruction or a function call.  (If the result
6419      * comes back in a register other than r0, you can override "result".)
6420      *
6421      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6422      * vCC (r1).  Useful for integer division and modulus.
6423      *
6424      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6425      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6426      */
6427     /* binop/lit16 vA, vB, #+CCCC */
6428     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6429     mov     r2, rINST, lsr #12          @ r2<- B
6430     mov     r9, rINST, lsr #8           @ r9<- A+
6431     GET_VREG(r0, r2)                    @ r0<- vB
6432     and     r9, r9, #15
6433     .if 0
6434     cmp     r1, #0                      @ is second operand zero?
6435     beq     common_errDivideByZero
6436     .endif
6437     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6438
6439     rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6440     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6441     SET_VREG(r0, r9)               @ vAA<- r0
6442     GOTO_OPCODE(ip)                     @ jump to next instruction
6443     /* 10-13 instructions */
6444
6445
6446 /* ------------------------------ */
6447     .balign 64
6448 .L_OP_MUL_INT_LIT16: /* 0xd2 */
6449 /* File: armv5te/OP_MUL_INT_LIT16.S */
6450 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6451 /* File: armv5te/binopLit16.S */
6452     /*
6453      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6454      * that specifies an instruction that performs "result = r0 op r1".
6455      * This could be an ARM instruction or a function call.  (If the result
6456      * comes back in a register other than r0, you can override "result".)
6457      *
6458      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6459      * vCC (r1).  Useful for integer division and modulus.
6460      *
6461      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6462      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6463      */
6464     /* binop/lit16 vA, vB, #+CCCC */
6465     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6466     mov     r2, rINST, lsr #12          @ r2<- B
6467     mov     r9, rINST, lsr #8           @ r9<- A+
6468     GET_VREG(r0, r2)                    @ r0<- vB
6469     and     r9, r9, #15
6470     .if 0
6471     cmp     r1, #0                      @ is second operand zero?
6472     beq     common_errDivideByZero
6473     .endif
6474     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6475
6476     mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6477     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6478     SET_VREG(r0, r9)               @ vAA<- r0
6479     GOTO_OPCODE(ip)                     @ jump to next instruction
6480     /* 10-13 instructions */
6481
6482
6483 /* ------------------------------ */
6484     .balign 64
6485 .L_OP_DIV_INT_LIT16: /* 0xd3 */
6486 /* File: armv5te/OP_DIV_INT_LIT16.S */
6487 /* File: armv5te/binopLit16.S */
6488     /*
6489      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6490      * that specifies an instruction that performs "result = r0 op r1".
6491      * This could be an ARM instruction or a function call.  (If the result
6492      * comes back in a register other than r0, you can override "result".)
6493      *
6494      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6495      * vCC (r1).  Useful for integer division and modulus.
6496      *
6497      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6498      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6499      */
6500     /* binop/lit16 vA, vB, #+CCCC */
6501     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6502     mov     r2, rINST, lsr #12          @ r2<- B
6503     mov     r9, rINST, lsr #8           @ r9<- A+
6504     GET_VREG(r0, r2)                    @ r0<- vB
6505     and     r9, r9, #15
6506     .if 1
6507     cmp     r1, #0                      @ is second operand zero?
6508     beq     common_errDivideByZero
6509     .endif
6510     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6511
6512     bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6513     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6514     SET_VREG(r0, r9)               @ vAA<- r0
6515     GOTO_OPCODE(ip)                     @ jump to next instruction
6516     /* 10-13 instructions */
6517
6518
6519 /* ------------------------------ */
6520     .balign 64
6521 .L_OP_REM_INT_LIT16: /* 0xd4 */
6522 /* File: armv5te/OP_REM_INT_LIT16.S */
6523 /* idivmod returns quotient in r0 and remainder in r1 */
6524 /* File: armv5te/binopLit16.S */
6525     /*
6526      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6527      * that specifies an instruction that performs "result = r0 op r1".
6528      * This could be an ARM instruction or a function call.  (If the result
6529      * comes back in a register other than r0, you can override "result".)
6530      *
6531      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6532      * vCC (r1).  Useful for integer division and modulus.
6533      *
6534      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6535      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6536      */
6537     /* binop/lit16 vA, vB, #+CCCC */
6538     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6539     mov     r2, rINST, lsr #12          @ r2<- B
6540     mov     r9, rINST, lsr #8           @ r9<- A+
6541     GET_VREG(r0, r2)                    @ r0<- vB
6542     and     r9, r9, #15
6543     .if 1
6544     cmp     r1, #0                      @ is second operand zero?
6545     beq     common_errDivideByZero
6546     .endif
6547     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6548
6549     bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6550     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6551     SET_VREG(r1, r9)               @ vAA<- r1
6552     GOTO_OPCODE(ip)                     @ jump to next instruction
6553     /* 10-13 instructions */
6554
6555
6556 /* ------------------------------ */
6557     .balign 64
6558 .L_OP_AND_INT_LIT16: /* 0xd5 */
6559 /* File: armv5te/OP_AND_INT_LIT16.S */
6560 /* File: armv5te/binopLit16.S */
6561     /*
6562      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6563      * that specifies an instruction that performs "result = r0 op r1".
6564      * This could be an ARM instruction or a function call.  (If the result
6565      * comes back in a register other than r0, you can override "result".)
6566      *
6567      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6568      * vCC (r1).  Useful for integer division and modulus.
6569      *
6570      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6571      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6572      */
6573     /* binop/lit16 vA, vB, #+CCCC */
6574     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6575     mov     r2, rINST, lsr #12          @ r2<- B
6576     mov     r9, rINST, lsr #8           @ r9<- A+
6577     GET_VREG(r0, r2)                    @ r0<- vB
6578     and     r9, r9, #15
6579     .if 0
6580     cmp     r1, #0                      @ is second operand zero?
6581     beq     common_errDivideByZero
6582     .endif
6583     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6584
6585     and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6586     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6587     SET_VREG(r0, r9)               @ vAA<- r0
6588     GOTO_OPCODE(ip)                     @ jump to next instruction
6589     /* 10-13 instructions */
6590
6591
6592 /* ------------------------------ */
6593     .balign 64
6594 .L_OP_OR_INT_LIT16: /* 0xd6 */
6595 /* File: armv5te/OP_OR_INT_LIT16.S */
6596 /* File: armv5te/binopLit16.S */
6597     /*
6598      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6599      * that specifies an instruction that performs "result = r0 op r1".
6600      * This could be an ARM instruction or a function call.  (If the result
6601      * comes back in a register other than r0, you can override "result".)
6602      *
6603      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6604      * vCC (r1).  Useful for integer division and modulus.
6605      *
6606      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6607      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6608      */
6609     /* binop/lit16 vA, vB, #+CCCC */
6610     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6611     mov     r2, rINST, lsr #12          @ r2<- B
6612     mov     r9, rINST, lsr #8           @ r9<- A+
6613     GET_VREG(r0, r2)                    @ r0<- vB
6614     and     r9, r9, #15
6615     .if 0
6616     cmp     r1, #0                      @ is second operand zero?
6617     beq     common_errDivideByZero
6618     .endif
6619     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6620
6621     orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6622     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6623     SET_VREG(r0, r9)               @ vAA<- r0
6624     GOTO_OPCODE(ip)                     @ jump to next instruction
6625     /* 10-13 instructions */
6626
6627
6628 /* ------------------------------ */
6629     .balign 64
6630 .L_OP_XOR_INT_LIT16: /* 0xd7 */
6631 /* File: armv5te/OP_XOR_INT_LIT16.S */
6632 /* File: armv5te/binopLit16.S */
6633     /*
6634      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6635      * that specifies an instruction that performs "result = r0 op r1".
6636      * This could be an ARM instruction or a function call.  (If the result
6637      * comes back in a register other than r0, you can override "result".)
6638      *
6639      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6640      * vCC (r1).  Useful for integer division and modulus.
6641      *
6642      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6643      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6644      */
6645     /* binop/lit16 vA, vB, #+CCCC */
6646     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6647     mov     r2, rINST, lsr #12          @ r2<- B
6648     mov     r9, rINST, lsr #8           @ r9<- A+
6649     GET_VREG(r0, r2)                    @ r0<- vB
6650     and     r9, r9, #15
6651     .if 0
6652     cmp     r1, #0                      @ is second operand zero?
6653     beq     common_errDivideByZero
6654     .endif
6655     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6656
6657     eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
6658     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6659     SET_VREG(r0, r9)               @ vAA<- r0
6660     GOTO_OPCODE(ip)                     @ jump to next instruction
6661     /* 10-13 instructions */
6662
6663
6664 /* ------------------------------ */
6665     .balign 64
6666 .L_OP_ADD_INT_LIT8: /* 0xd8 */
6667 /* File: armv5te/OP_ADD_INT_LIT8.S */
6668 /* File: armv5te/binopLit8.S */
6669     /*
6670      * Generic 32-bit "lit8" 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/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6679      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6680      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6681      */
6682     /* binop/lit8 vAA, vBB, #+CC */
6683     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6684     mov     r9, rINST, lsr #8           @ r9<- AA
6685     and     r2, r3, #255                @ r2<- BB
6686     GET_VREG(r0, r2)                    @ r0<- vBB
6687     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6688     .if 0
6689     @cmp     r1, #0                      @ is second operand zero?
6690     beq     common_errDivideByZero
6691     .endif
6692     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6693
6694                                @ optional op; may set condition codes
6695     add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6696     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6697     SET_VREG(r0, r9)               @ vAA<- r0
6698     GOTO_OPCODE(ip)                     @ jump to next instruction
6699     /* 10-12 instructions */
6700
6701
6702 /* ------------------------------ */
6703     .balign 64
6704 .L_OP_RSUB_INT_LIT8: /* 0xd9 */
6705 /* File: armv5te/OP_RSUB_INT_LIT8.S */
6706 /* File: armv5te/binopLit8.S */
6707     /*
6708      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6709      * that specifies an instruction that performs "result = r0 op r1".
6710      * This could be an ARM instruction or a function call.  (If the result
6711      * comes back in a register other than r0, you can override "result".)
6712      *
6713      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6714      * vCC (r1).  Useful for integer division and modulus.
6715      *
6716      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6717      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6718      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6719      */
6720     /* binop/lit8 vAA, vBB, #+CC */
6721     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6722     mov     r9, rINST, lsr #8           @ r9<- AA
6723     and     r2, r3, #255                @ r2<- BB
6724     GET_VREG(r0, r2)                    @ r0<- vBB
6725     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6726     .if 0
6727     @cmp     r1, #0                      @ is second operand zero?
6728     beq     common_errDivideByZero
6729     .endif
6730     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6731
6732                                @ optional op; may set condition codes
6733     rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6734     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6735     SET_VREG(r0, r9)               @ vAA<- r0
6736     GOTO_OPCODE(ip)                     @ jump to next instruction
6737     /* 10-12 instructions */
6738
6739
6740 /* ------------------------------ */
6741     .balign 64
6742 .L_OP_MUL_INT_LIT8: /* 0xda */
6743 /* File: armv5te/OP_MUL_INT_LIT8.S */
6744 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6745 /* File: armv5te/binopLit8.S */
6746     /*
6747      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6748      * that specifies an instruction that performs "result = r0 op r1".
6749      * This could be an ARM instruction or a function call.  (If the result
6750      * comes back in a register other than r0, you can override "result".)
6751      *
6752      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6753      * vCC (r1).  Useful for integer division and modulus.
6754      *
6755      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6756      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6757      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6758      */
6759     /* binop/lit8 vAA, vBB, #+CC */
6760     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6761     mov     r9, rINST, lsr #8           @ r9<- AA
6762     and     r2, r3, #255                @ r2<- BB
6763     GET_VREG(r0, r2)                    @ r0<- vBB
6764     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6765     .if 0
6766     @cmp     r1, #0                      @ is second operand zero?
6767     beq     common_errDivideByZero
6768     .endif
6769     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6770
6771                                @ optional op; may set condition codes
6772     mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6773     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6774     SET_VREG(r0, r9)               @ vAA<- r0
6775     GOTO_OPCODE(ip)                     @ jump to next instruction
6776     /* 10-12 instructions */
6777
6778
6779 /* ------------------------------ */
6780     .balign 64
6781 .L_OP_DIV_INT_LIT8: /* 0xdb */
6782 /* File: armv5te/OP_DIV_INT_LIT8.S */
6783 /* File: armv5te/binopLit8.S */
6784     /*
6785      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6786      * that specifies an instruction that performs "result = r0 op r1".
6787      * This could be an ARM instruction or a function call.  (If the result
6788      * comes back in a register other than r0, you can override "result".)
6789      *
6790      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6791      * vCC (r1).  Useful for integer division and modulus.
6792      *
6793      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6794      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6795      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6796      */
6797     /* binop/lit8 vAA, vBB, #+CC */
6798     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6799     mov     r9, rINST, lsr #8           @ r9<- AA
6800     and     r2, r3, #255                @ r2<- BB
6801     GET_VREG(r0, r2)                    @ r0<- vBB
6802     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6803     .if 1
6804     @cmp     r1, #0                      @ is second operand zero?
6805     beq     common_errDivideByZero
6806     .endif
6807     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6808
6809                                @ optional op; may set condition codes
6810     bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6811     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6812     SET_VREG(r0, r9)               @ vAA<- r0
6813     GOTO_OPCODE(ip)                     @ jump to next instruction
6814     /* 10-12 instructions */
6815
6816
6817 /* ------------------------------ */
6818     .balign 64
6819 .L_OP_REM_INT_LIT8: /* 0xdc */
6820 /* File: armv5te/OP_REM_INT_LIT8.S */
6821 /* idivmod returns quotient in r0 and remainder in r1 */
6822 /* File: armv5te/binopLit8.S */
6823     /*
6824      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6825      * that specifies an instruction that performs "result = r0 op r1".
6826      * This could be an ARM instruction or a function call.  (If the result
6827      * comes back in a register other than r0, you can override "result".)
6828      *
6829      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6830      * vCC (r1).  Useful for integer division and modulus.
6831      *
6832      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6833      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6834      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6835      */
6836     /* binop/lit8 vAA, vBB, #+CC */
6837     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6838     mov     r9, rINST, lsr #8           @ r9<- AA
6839     and     r2, r3, #255                @ r2<- BB
6840     GET_VREG(r0, r2)                    @ r0<- vBB
6841     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6842     .if 1
6843     @cmp     r1, #0                      @ is second operand zero?
6844     beq     common_errDivideByZero
6845     .endif
6846     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6847
6848                                @ optional op; may set condition codes
6849     bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6850     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6851     SET_VREG(r1, r9)               @ vAA<- r1
6852     GOTO_OPCODE(ip)                     @ jump to next instruction
6853     /* 10-12 instructions */
6854
6855
6856 /* ------------------------------ */
6857     .balign 64
6858 .L_OP_AND_INT_LIT8: /* 0xdd */
6859 /* File: armv5te/OP_AND_INT_LIT8.S */
6860 /* File: armv5te/binopLit8.S */
6861     /*
6862      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6863      * that specifies an instruction that performs "result = r0 op r1".
6864      * This could be an ARM instruction or a function call.  (If the result
6865      * comes back in a register other than r0, you can override "result".)
6866      *
6867      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6868      * vCC (r1).  Useful for integer division and modulus.
6869      *
6870      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6871      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6872      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6873      */
6874     /* binop/lit8 vAA, vBB, #+CC */
6875     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6876     mov     r9, rINST, lsr #8           @ r9<- AA
6877     and     r2, r3, #255                @ r2<- BB
6878     GET_VREG(r0, r2)                    @ r0<- vBB
6879     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6880     .if 0
6881     @cmp     r1, #0                      @ is second operand zero?
6882     beq     common_errDivideByZero
6883     .endif
6884     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6885
6886                                @ optional op; may set condition codes
6887     and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6888     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6889     SET_VREG(r0, r9)               @ vAA<- r0
6890     GOTO_OPCODE(ip)                     @ jump to next instruction
6891     /* 10-12 instructions */
6892
6893
6894 /* ------------------------------ */
6895     .balign 64
6896 .L_OP_OR_INT_LIT8: /* 0xde */
6897 /* File: armv5te/OP_OR_INT_LIT8.S */
6898 /* File: armv5te/binopLit8.S */
6899     /*
6900      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6901      * that specifies an instruction that performs "result = r0 op r1".
6902      * This could be an ARM instruction or a function call.  (If the result
6903      * comes back in a register other than r0, you can override "result".)
6904      *
6905      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6906      * vCC (r1).  Useful for integer division and modulus.
6907      *
6908      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6909      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6910      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6911      */
6912     /* binop/lit8 vAA, vBB, #+CC */
6913     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6914     mov     r9, rINST, lsr #8           @ r9<- AA
6915     and     r2, r3, #255                @ r2<- BB
6916     GET_VREG(r0, r2)                    @ r0<- vBB
6917     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6918     .if 0
6919     @cmp     r1, #0                      @ is second operand zero?
6920     beq     common_errDivideByZero
6921     .endif
6922     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6923
6924                                @ optional op; may set condition codes
6925     orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6926     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6927     SET_VREG(r0, r9)               @ vAA<- r0
6928     GOTO_OPCODE(ip)                     @ jump to next instruction
6929     /* 10-12 instructions */
6930
6931
6932 /* ------------------------------ */
6933     .balign 64
6934 .L_OP_XOR_INT_LIT8: /* 0xdf */
6935 /* File: armv5te/OP_XOR_INT_LIT8.S */
6936 /* File: armv5te/binopLit8.S */
6937     /*
6938      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6939      * that specifies an instruction that performs "result = r0 op r1".
6940      * This could be an ARM instruction or a function call.  (If the result
6941      * comes back in a register other than r0, you can override "result".)
6942      *
6943      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6944      * vCC (r1).  Useful for integer division and modulus.
6945      *
6946      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6947      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6948      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6949      */
6950     /* binop/lit8 vAA, vBB, #+CC */
6951     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6952     mov     r9, rINST, lsr #8           @ r9<- AA
6953     and     r2, r3, #255                @ r2<- BB
6954     GET_VREG(r0, r2)                    @ r0<- vBB
6955     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6956     .if 0
6957     @cmp     r1, #0                      @ is second operand zero?
6958     beq     common_errDivideByZero
6959     .endif
6960     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6961
6962                                @ optional op; may set condition codes
6963     eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
6964     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6965     SET_VREG(r0, r9)               @ vAA<- r0
6966     GOTO_OPCODE(ip)                     @ jump to next instruction
6967     /* 10-12 instructions */
6968
6969
6970 /* ------------------------------ */
6971     .balign 64
6972 .L_OP_SHL_INT_LIT8: /* 0xe0 */
6973 /* File: armv5te/OP_SHL_INT_LIT8.S */
6974 /* File: armv5te/binopLit8.S */
6975     /*
6976      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6977      * that specifies an instruction that performs "result = r0 op r1".
6978      * This could be an ARM instruction or a function call.  (If the result
6979      * comes back in a register other than r0, you can override "result".)
6980      *
6981      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6982      * vCC (r1).  Useful for integer division and modulus.
6983      *
6984      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6985      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6986      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6987      */
6988     /* binop/lit8 vAA, vBB, #+CC */
6989     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6990     mov     r9, rINST, lsr #8           @ r9<- AA
6991     and     r2, r3, #255                @ r2<- BB
6992     GET_VREG(r0, r2)                    @ r0<- vBB
6993     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6994     .if 0
6995     @cmp     r1, #0                      @ is second operand zero?
6996     beq     common_errDivideByZero
6997     .endif
6998     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6999
7000     and     r1, r1, #31                           @ optional op; may set condition codes
7001     mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
7002     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7003     SET_VREG(r0, r9)               @ vAA<- r0
7004     GOTO_OPCODE(ip)                     @ jump to next instruction
7005     /* 10-12 instructions */
7006
7007
7008 /* ------------------------------ */
7009     .balign 64
7010 .L_OP_SHR_INT_LIT8: /* 0xe1 */
7011 /* File: armv5te/OP_SHR_INT_LIT8.S */
7012 /* File: armv5te/binopLit8.S */
7013     /*
7014      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7015      * that specifies an instruction that performs "result = r0 op r1".
7016      * This could be an ARM instruction or a function call.  (If the result
7017      * comes back in a register other than r0, you can override "result".)
7018      *
7019      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7020      * vCC (r1).  Useful for integer division and modulus.
7021      *
7022      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7023      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7024      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7025      */
7026     /* binop/lit8 vAA, vBB, #+CC */
7027     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7028     mov     r9, rINST, lsr #8           @ r9<- AA
7029     and     r2, r3, #255                @ r2<- BB
7030     GET_VREG(r0, r2)                    @ r0<- vBB
7031     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7032     .if 0
7033     @cmp     r1, #0                      @ is second operand zero?
7034     beq     common_errDivideByZero
7035     .endif
7036     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7037
7038     and     r1, r1, #31                           @ optional op; may set condition codes
7039     mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
7040     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7041     SET_VREG(r0, r9)               @ vAA<- r0
7042     GOTO_OPCODE(ip)                     @ jump to next instruction
7043     /* 10-12 instructions */
7044
7045
7046 /* ------------------------------ */
7047     .balign 64
7048 .L_OP_USHR_INT_LIT8: /* 0xe2 */
7049 /* File: armv5te/OP_USHR_INT_LIT8.S */
7050 /* File: armv5te/binopLit8.S */
7051     /*
7052      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7053      * that specifies an instruction that performs "result = r0 op r1".
7054      * This could be an ARM instruction or a function call.  (If the result
7055      * comes back in a register other than r0, you can override "result".)
7056      *
7057      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7058      * vCC (r1).  Useful for integer division and modulus.
7059      *
7060      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7061      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7062      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7063      */
7064     /* binop/lit8 vAA, vBB, #+CC */
7065     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7066     mov     r9, rINST, lsr #8           @ r9<- AA
7067     and     r2, r3, #255                @ r2<- BB
7068     GET_VREG(r0, r2)                    @ r0<- vBB
7069     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7070     .if 0
7071     @cmp     r1, #0                      @ is second operand zero?
7072     beq     common_errDivideByZero
7073     .endif
7074     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7075
7076     and     r1, r1, #31                           @ optional op; may set condition codes
7077     mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
7078     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7079     SET_VREG(r0, r9)               @ vAA<- r0
7080     GOTO_OPCODE(ip)                     @ jump to next instruction
7081     /* 10-12 instructions */
7082
7083
7084 /* ------------------------------ */
7085     .balign 64
7086 .L_OP_IGET_VOLATILE: /* 0xe3 */
7087 /* File: armv5te/OP_IGET_VOLATILE.S */
7088 /* File: armv5te/OP_IGET.S */
7089     /*
7090      * General 32-bit instance field get.
7091      *
7092      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
7093      */
7094     /* op vA, vB, field@CCCC */
7095     mov     r0, rINST, lsr #12          @ r0<- B
7096     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7097     FETCH(r1, 1)                        @ r1<- field ref CCCC
7098     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7099     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7100     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7101     cmp     r0, #0                      @ is resolved entry null?
7102     bne     .LOP_IGET_VOLATILE_finish          @ no, already resolved
7103 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7104     EXPORT_PC()                         @ resolve() could throw
7105     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7106     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7107     cmp     r0, #0
7108     bne     .LOP_IGET_VOLATILE_finish
7109     b       common_exceptionThrown
7110
7111
7112 /* ------------------------------ */
7113     .balign 64
7114 .L_OP_IPUT_VOLATILE: /* 0xe4 */
7115 /* File: armv5te/OP_IPUT_VOLATILE.S */
7116 /* File: armv5te/OP_IPUT.S */
7117     /*
7118      * General 32-bit instance field put.
7119      *
7120      * for: iput, iput-boolean, iput-byte, iput-char, iput-short
7121      */
7122     /* op vA, vB, field@CCCC */
7123     mov     r0, rINST, lsr #12          @ r0<- B
7124     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7125     FETCH(r1, 1)                        @ r1<- field ref CCCC
7126     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7127     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7128     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7129     cmp     r0, #0                      @ is resolved entry null?
7130     bne     .LOP_IPUT_VOLATILE_finish          @ no, already resolved
7131 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7132     EXPORT_PC()                         @ resolve() could throw
7133     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7134     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7135     cmp     r0, #0                      @ success?
7136     bne     .LOP_IPUT_VOLATILE_finish          @ yes, finish up
7137     b       common_exceptionThrown
7138
7139
7140 /* ------------------------------ */
7141     .balign 64
7142 .L_OP_SGET_VOLATILE: /* 0xe5 */
7143 /* File: armv5te/OP_SGET_VOLATILE.S */
7144 /* File: armv5te/OP_SGET.S */
7145     /*
7146      * General 32-bit SGET handler.
7147      *
7148      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
7149      */
7150     /* op vAA, field@BBBB */
7151     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7152     FETCH(r1, 1)                        @ r1<- field ref BBBB
7153     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7154     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7155     cmp     r0, #0                      @ is resolved entry null?
7156     beq     .LOP_SGET_VOLATILE_resolve         @ yes, do resolve
7157 .LOP_SGET_VOLATILE_finish: @ field ptr in r0
7158     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
7159     SMP_DMB                            @ acquiring load
7160     mov     r2, rINST, lsr #8           @ r2<- AA
7161     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7162     SET_VREG(r1, r2)                    @ fp[AA]<- r1
7163     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7164     GOTO_OPCODE(ip)                     @ jump to next instruction
7165
7166
7167 /* ------------------------------ */
7168     .balign 64
7169 .L_OP_SPUT_VOLATILE: /* 0xe6 */
7170 /* File: armv5te/OP_SPUT_VOLATILE.S */
7171 /* File: armv5te/OP_SPUT.S */
7172     /*
7173      * General 32-bit SPUT handler.
7174      *
7175      * for: sput, sput-boolean, sput-byte, sput-char, sput-short
7176      */
7177     /* op vAA, field@BBBB */
7178     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7179     FETCH(r1, 1)                        @ r1<- field ref BBBB
7180     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7181     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7182     cmp     r0, #0                      @ is resolved entry null?
7183     beq     .LOP_SPUT_VOLATILE_resolve         @ yes, do resolve
7184 .LOP_SPUT_VOLATILE_finish:   @ field ptr in r0
7185     mov     r2, rINST, lsr #8           @ r2<- AA
7186     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7187     GET_VREG(r1, r2)                    @ r1<- fp[AA]
7188     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7189     SMP_DMB                            @ releasing store
7190     str     r1, [r0, #offStaticField_value] @ field<- vAA
7191     GOTO_OPCODE(ip)                     @ jump to next instruction
7192
7193
7194 /* ------------------------------ */
7195     .balign 64
7196 .L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */
7197 /* File: armv5te/OP_IGET_OBJECT_VOLATILE.S */
7198 /* File: armv5te/OP_IGET.S */
7199     /*
7200      * General 32-bit instance field get.
7201      *
7202      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
7203      */
7204     /* op vA, vB, field@CCCC */
7205     mov     r0, rINST, lsr #12          @ r0<- B
7206     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7207     FETCH(r1, 1)                        @ r1<- field ref CCCC
7208     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7209     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7210     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7211     cmp     r0, #0                      @ is resolved entry null?
7212     bne     .LOP_IGET_OBJECT_VOLATILE_finish          @ no, already resolved
7213 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7214     EXPORT_PC()                         @ resolve() could throw
7215     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7216     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7217     cmp     r0, #0
7218     bne     .LOP_IGET_OBJECT_VOLATILE_finish
7219     b       common_exceptionThrown
7220
7221
7222 /* ------------------------------ */
7223     .balign 64
7224 .L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */
7225 /* File: armv5te/OP_IGET_WIDE_VOLATILE.S */
7226 /* File: armv5te/OP_IGET_WIDE.S */
7227     /*
7228      * Wide 32-bit instance field get.
7229      */
7230     /* iget-wide vA, vB, field@CCCC */
7231     mov     r0, rINST, lsr #12          @ r0<- B
7232     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7233     FETCH(r1, 1)                        @ r1<- field ref CCCC
7234     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
7235     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7236     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7237     cmp     r0, #0                      @ is resolved entry null?
7238     bne     .LOP_IGET_WIDE_VOLATILE_finish          @ no, already resolved
7239 8:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
7240     EXPORT_PC()                         @ resolve() could throw
7241     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7242     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7243     cmp     r0, #0
7244     bne     .LOP_IGET_WIDE_VOLATILE_finish
7245     b       common_exceptionThrown
7246
7247
7248 /* ------------------------------ */
7249     .balign 64
7250 .L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */
7251 /* File: armv5te/OP_IPUT_WIDE_VOLATILE.S */
7252 /* File: armv5te/OP_IPUT_WIDE.S */
7253     /* iput-wide vA, vB, field@CCCC */
7254     mov     r0, rINST, lsr #12          @ r0<- B
7255     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7256     FETCH(r1, 1)                        @ r1<- field ref CCCC
7257     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
7258     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7259     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7260     cmp     r0, #0                      @ is resolved entry null?
7261     bne     .LOP_IPUT_WIDE_VOLATILE_finish          @ no, already resolved
7262 8:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
7263     EXPORT_PC()                         @ resolve() could throw
7264     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7265     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7266     cmp     r0, #0                      @ success?
7267     bne     .LOP_IPUT_WIDE_VOLATILE_finish          @ yes, finish up
7268     b       common_exceptionThrown
7269
7270
7271 /* ------------------------------ */
7272     .balign 64
7273 .L_OP_SGET_WIDE_VOLATILE: /* 0xea */
7274 /* File: armv5te/OP_SGET_WIDE_VOLATILE.S */
7275 /* File: armv5te/OP_SGET_WIDE.S */
7276     /*
7277      * 64-bit SGET handler.
7278      */
7279     /* sget-wide vAA, field@BBBB */
7280     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7281     FETCH(r1, 1)                        @ r1<- field ref BBBB
7282     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7283     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7284     cmp     r0, #0                      @ is resolved entry null?
7285     beq     .LOP_SGET_WIDE_VOLATILE_resolve         @ yes, do resolve
7286 .LOP_SGET_WIDE_VOLATILE_finish:
7287     mov     r9, rINST, lsr #8           @ r9<- AA
7288     .if 1
7289     add     r0, r0, #offStaticField_value @ r0<- pointer to data
7290     bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
7291     .else
7292     ldrd    r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
7293     .endif
7294     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
7295     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7296     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
7297     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7298     GOTO_OPCODE(ip)                     @ jump to next instruction
7299
7300
7301 /* ------------------------------ */
7302     .balign 64
7303 .L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */
7304 /* File: armv5te/OP_SPUT_WIDE_VOLATILE.S */
7305 /* File: armv5te/OP_SPUT_WIDE.S */
7306     /*
7307      * 64-bit SPUT handler.
7308      */
7309     /* sput-wide vAA, field@BBBB */
7310     ldr     r0, [rGLUE, #offGlue_methodClassDex]  @ r0<- DvmDex
7311     FETCH(r1, 1)                        @ r1<- field ref BBBB
7312     ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
7313     mov     r9, rINST, lsr #8           @ r9<- AA
7314     ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
7315     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
7316     cmp     r2, #0                      @ is resolved entry null?
7317     beq     .LOP_SPUT_WIDE_VOLATILE_resolve         @ yes, do resolve
7318 .LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9
7319     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7320     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
7321     GET_INST_OPCODE(r10)                @ extract opcode from rINST
7322     .if 1
7323     add     r2, r2, #offStaticField_value @ r2<- pointer to data
7324     bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
7325     .else
7326     strd    r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
7327     .endif
7328     GOTO_OPCODE(r10)                    @ jump to next instruction
7329
7330
7331 /* ------------------------------ */
7332     .balign 64
7333 .L_OP_BREAKPOINT: /* 0xec */
7334 /* File: armv5te/OP_BREAKPOINT.S */
7335 /* File: armv5te/unused.S */
7336     bl      common_abort
7337
7338
7339 /* ------------------------------ */
7340     .balign 64
7341 .L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
7342 /* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
7343     /*
7344      * Handle a throw-verification-error instruction.  This throws an
7345      * exception for an error discovered during verification.  The
7346      * exception is indicated by AA, with some detail provided by BBBB.
7347      */
7348     /* op AA, ref@BBBB */
7349     ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7350     FETCH(r2, 1)                        @ r2<- BBBB
7351     EXPORT_PC()                         @ export the PC
7352     mov     r1, rINST, lsr #8           @ r1<- AA
7353     bl      dvmThrowVerificationError   @ always throws
7354     b       common_exceptionThrown      @ handle exception
7355
7356 /* ------------------------------ */
7357     .balign 64
7358 .L_OP_EXECUTE_INLINE: /* 0xee */
7359 /* File: armv5te/OP_EXECUTE_INLINE.S */
7360     /*
7361      * Execute a "native inline" instruction.
7362      *
7363      * We need to call an InlineOp4Func:
7364      *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7365      *
7366      * The first four args are in r0-r3, pointer to return value storage
7367      * is on the stack.  The function's return value is a flag that tells
7368      * us if an exception was thrown.
7369      */
7370     /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
7371     FETCH(r10, 1)                       @ r10<- BBBB
7372     add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7373     EXPORT_PC()                         @ can throw
7374     sub     sp, sp, #8                  @ make room for arg, +64 bit align
7375     mov     r0, rINST, lsr #12          @ r0<- B
7376     str     r1, [sp]                    @ push &glue->retval
7377     bl      .LOP_EXECUTE_INLINE_continue        @ make call; will return after
7378     add     sp, sp, #8                  @ pop stack
7379     cmp     r0, #0                      @ test boolean result of inline
7380     beq     common_exceptionThrown      @ returned false, handle exception
7381     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7382     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7383     GOTO_OPCODE(ip)                     @ jump to next instruction
7384
7385 /* ------------------------------ */
7386     .balign 64
7387 .L_OP_EXECUTE_INLINE_RANGE: /* 0xef */
7388 /* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */
7389     /*
7390      * Execute a "native inline" instruction, using "/range" semantics.
7391      * Same idea as execute-inline, but we get the args differently.
7392      *
7393      * We need to call an InlineOp4Func:
7394      *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7395      *
7396      * The first four args are in r0-r3, pointer to return value storage
7397      * is on the stack.  The function's return value is a flag that tells
7398      * us if an exception was thrown.
7399      */
7400     /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */
7401     FETCH(r10, 1)                       @ r10<- BBBB
7402     add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7403     EXPORT_PC()                         @ can throw
7404     sub     sp, sp, #8                  @ make room for arg, +64 bit align
7405     mov     r0, rINST, lsr #8           @ r0<- AA
7406     str     r1, [sp]                    @ push &glue->retval
7407     bl      .LOP_EXECUTE_INLINE_RANGE_continue        @ make call; will return after
7408     add     sp, sp, #8                  @ pop stack
7409     cmp     r0, #0                      @ test boolean result of inline
7410     beq     common_exceptionThrown      @ returned false, handle exception
7411     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7412     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7413     GOTO_OPCODE(ip)                     @ jump to next instruction
7414
7415 /* ------------------------------ */
7416     .balign 64
7417 .L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
7418 /* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
7419     /*
7420      * invoke-direct-empty is a no-op in a "standard" interpreter.
7421      */
7422     FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7423     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7424     GOTO_OPCODE(ip)                     @ execute it
7425
7426 /* ------------------------------ */
7427     .balign 64
7428 .L_OP_RETURN_VOID_BARRIER: /* 0xf1 */
7429 /* File: armv5te/OP_RETURN_VOID_BARRIER.S */
7430     SMP_DMB_ST
7431     b       common_returnFromMethod
7432
7433 /* ------------------------------ */
7434     .balign 64
7435 .L_OP_IGET_QUICK: /* 0xf2 */
7436 /* File: armv5te/OP_IGET_QUICK.S */
7437     /* For: iget-quick, iget-object-quick */
7438     /* op vA, vB, offset@CCCC */
7439     mov     r2, rINST, lsr #12          @ r2<- B
7440     GET_VREG(r3, r2)                    @ r3<- object we're operating on
7441     FETCH(r1, 1)                        @ r1<- field byte offset
7442     cmp     r3, #0                      @ check object for null
7443     mov     r2, rINST, lsr #8           @ r2<- A(+)
7444     beq     common_errNullObject        @ object was null
7445     ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7446     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7447     and     r2, r2, #15
7448     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7449     SET_VREG(r0, r2)                    @ fp[A]<- r0
7450     GOTO_OPCODE(ip)                     @ jump to next instruction
7451
7452 /* ------------------------------ */
7453     .balign 64
7454 .L_OP_IGET_WIDE_QUICK: /* 0xf3 */
7455 /* File: armv5te/OP_IGET_WIDE_QUICK.S */
7456     /* iget-wide-quick vA, vB, offset@CCCC */
7457     mov     r2, rINST, lsr #12          @ r2<- B
7458     GET_VREG(r3, r2)                    @ r3<- object we're operating on
7459     FETCH(ip, 1)                        @ ip<- field byte offset
7460     cmp     r3, #0                      @ check object for null
7461     mov     r2, rINST, lsr #8           @ r2<- A(+)
7462     beq     common_errNullObject        @ object was null
7463     ldrd    r0, [r3, ip]                @ r0<- obj.field (64 bits, aligned)
7464     and     r2, r2, #15
7465     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7466     add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
7467     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7468     stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
7469     GOTO_OPCODE(ip)                     @ jump to next instruction
7470
7471 /* ------------------------------ */
7472     .balign 64
7473 .L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
7474 /* File: armv5te/OP_IGET_OBJECT_QUICK.S */
7475 /* File: armv5te/OP_IGET_QUICK.S */
7476     /* For: iget-quick, iget-object-quick */
7477     /* op vA, vB, offset@CCCC */
7478     mov     r2, rINST, lsr #12          @ r2<- B
7479     GET_VREG(r3, r2)                    @ r3<- object we're operating on
7480     FETCH(r1, 1)                        @ r1<- field byte offset
7481     cmp     r3, #0                      @ check object for null
7482     mov     r2, rINST, lsr #8           @ r2<- A(+)
7483     beq     common_errNullObject        @ object was null
7484     ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7485     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7486     and     r2, r2, #15
7487     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7488     SET_VREG(r0, r2)                    @ fp[A]<- r0
7489     GOTO_OPCODE(ip)                     @ jump to next instruction
7490
7491
7492 /* ------------------------------ */
7493     .balign 64
7494 .L_OP_IPUT_QUICK: /* 0xf5 */
7495 /* File: armv5te/OP_IPUT_QUICK.S */
7496     /* For: iput-quick */
7497     /* op vA, vB, offset@CCCC */
7498     mov     r2, rINST, lsr #12          @ r2<- B
7499     GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7500     FETCH(r1, 1)                        @ r1<- field byte offset
7501     cmp     r3, #0                      @ check object for null
7502     mov     r2, rINST, lsr #8           @ r2<- A(+)
7503     beq     common_errNullObject        @ object was null
7504     and     r2, r2, #15
7505     GET_VREG(r0, r2)                    @ r0<- fp[A]
7506     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7507     str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7508     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7509     GOTO_OPCODE(ip)                     @ jump to next instruction
7510
7511 /* ------------------------------ */
7512     .balign 64
7513 .L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
7514 /* File: armv5te/OP_IPUT_WIDE_QUICK.S */
7515     /* iput-wide-quick vA, vB, offset@CCCC */
7516     mov     r0, rINST, lsr #8           @ r0<- A(+)
7517     mov     r1, rINST, lsr #12          @ r1<- B
7518     and     r0, r0, #15
7519     GET_VREG(r2, r1)                    @ r2<- fp[B], the object pointer
7520     add     r3, rFP, r0, lsl #2         @ r3<- &fp[A]
7521     cmp     r2, #0                      @ check object for null
7522     ldmia   r3, {r0-r1}                 @ r0/r1<- fp[A]
7523     beq     common_errNullObject        @ object was null
7524     FETCH(r3, 1)                        @ r3<- field byte offset
7525     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7526     strd    r0, [r2, r3]                @ obj.field (64 bits, aligned)<- r0/r1
7527     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7528     GOTO_OPCODE(ip)                     @ jump to next instruction
7529
7530 /* ------------------------------ */
7531     .balign 64
7532 .L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
7533 /* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
7534     /* For: iput-object-quick */
7535     /* op vA, vB, offset@CCCC */
7536     mov     r2, rINST, lsr #12          @ r2<- B
7537     GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7538     FETCH(r1, 1)                        @ r1<- field byte offset
7539     cmp     r3, #0                      @ check object for null
7540     mov     r2, rINST, lsr #8           @ r2<- A(+)
7541     beq     common_errNullObject        @ object was null
7542     and     r2, r2, #15
7543     GET_VREG(r0, r2)                    @ r0<- fp[A]
7544     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
7545     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7546     str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7547     cmp     r0, #0
7548     strneb  r2, [r2, r3, lsr #GC_CARD_SHIFT] @ mark card based on obj head
7549     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7550     GOTO_OPCODE(ip)                     @ jump to next instruction
7551
7552 /* ------------------------------ */
7553     .balign 64
7554 .L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
7555 /* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7556     /*
7557      * Handle an optimized virtual method call.
7558      *
7559      * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7560      */
7561     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7562     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7563     FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7564     FETCH(r1, 1)                        @ r1<- BBBB
7565     .if     (!0)
7566     and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7567     .endif
7568     GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7569     cmp     r2, #0                      @ is "this" null?
7570     beq     common_errNullObject        @ null "this", throw exception
7571     ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7572     ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7573     EXPORT_PC()                         @ invoke must export
7574     ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7575     bl      common_invokeMethodNoRange @ continue on
7576
7577 /* ------------------------------ */
7578     .balign 64
7579 .L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
7580 /* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
7581 /* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7582     /*
7583      * Handle an optimized virtual method call.
7584      *
7585      * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7586      */
7587     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7588     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7589     FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7590     FETCH(r1, 1)                        @ r1<- BBBB
7591     .if     (!1)
7592     and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7593     .endif
7594     GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7595     cmp     r2, #0                      @ is "this" null?
7596     beq     common_errNullObject        @ null "this", throw exception
7597     ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7598     ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7599     EXPORT_PC()                         @ invoke must export
7600     ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7601     bl      common_invokeMethodRange @ continue on
7602
7603
7604 /* ------------------------------ */
7605     .balign 64
7606 .L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
7607 /* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7608     /*
7609      * Handle an optimized "super" method call.
7610      *
7611      * for: [opt] invoke-super-quick, invoke-super-quick/range
7612      */
7613     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7614     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7615     FETCH(r10, 2)                       @ r10<- GFED or CCCC
7616     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7617     .if     (!0)
7618     and     r10, r10, #15               @ r10<- D (or stays CCCC)
7619     .endif
7620     FETCH(r1, 1)                        @ r1<- BBBB
7621     ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7622     EXPORT_PC()                         @ must export for invoke
7623     ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7624     GET_VREG(r3, r10)                   @ r3<- "this"
7625     ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7626     cmp     r3, #0                      @ null "this" ref?
7627     ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7628     beq     common_errNullObject        @ "this" is null, throw exception
7629     bl      common_invokeMethodNoRange @ continue on
7630
7631 /* ------------------------------ */
7632     .balign 64
7633 .L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
7634 /* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
7635 /* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7636     /*
7637      * Handle an optimized "super" method call.
7638      *
7639      * for: [opt] invoke-super-quick, invoke-super-quick/range
7640      */
7641     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7642     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7643     FETCH(r10, 2)                       @ r10<- GFED or CCCC
7644     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7645     .if     (!1)
7646     and     r10, r10, #15               @ r10<- D (or stays CCCC)
7647     .endif
7648     FETCH(r1, 1)                        @ r1<- BBBB
7649     ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7650     EXPORT_PC()                         @ must export for invoke
7651     ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7652     GET_VREG(r3, r10)                   @ r3<- "this"
7653     ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7654     cmp     r3, #0                      @ null "this" ref?
7655     ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7656     beq     common_errNullObject        @ "this" is null, throw exception
7657     bl      common_invokeMethodRange @ continue on
7658
7659
7660 /* ------------------------------ */
7661     .balign 64
7662 .L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */
7663 /* File: armv5te/OP_IPUT_OBJECT_VOLATILE.S */
7664 /* File: armv5te/OP_IPUT_OBJECT.S */
7665     /*
7666      * 32-bit instance field put.
7667      *
7668      * for: iput-object, iput-object-volatile
7669      */
7670     /* op vA, vB, field@CCCC */
7671     mov     r0, rINST, lsr #12          @ r0<- B
7672     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7673     FETCH(r1, 1)                        @ r1<- field ref CCCC
7674     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7675     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7676     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7677     cmp     r0, #0                      @ is resolved entry null?
7678     bne     .LOP_IPUT_OBJECT_VOLATILE_finish          @ no, already resolved
7679 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7680     EXPORT_PC()                         @ resolve() could throw
7681     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7682     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7683     cmp     r0, #0                      @ success?
7684     bne     .LOP_IPUT_OBJECT_VOLATILE_finish          @ yes, finish up
7685     b       common_exceptionThrown
7686
7687
7688 /* ------------------------------ */
7689     .balign 64
7690 .L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */
7691 /* File: armv5te/OP_SGET_OBJECT_VOLATILE.S */
7692 /* File: armv5te/OP_SGET.S */
7693     /*
7694      * General 32-bit SGET handler.
7695      *
7696      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
7697      */
7698     /* op vAA, field@BBBB */
7699     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7700     FETCH(r1, 1)                        @ r1<- field ref BBBB
7701     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7702     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7703     cmp     r0, #0                      @ is resolved entry null?
7704     beq     .LOP_SGET_OBJECT_VOLATILE_resolve         @ yes, do resolve
7705 .LOP_SGET_OBJECT_VOLATILE_finish: @ field ptr in r0
7706     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
7707     SMP_DMB                            @ acquiring load
7708     mov     r2, rINST, lsr #8           @ r2<- AA
7709     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7710     SET_VREG(r1, r2)                    @ fp[AA]<- r1
7711     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7712     GOTO_OPCODE(ip)                     @ jump to next instruction
7713
7714
7715 /* ------------------------------ */
7716     .balign 64
7717 .L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */
7718 /* File: armv5te/OP_SPUT_OBJECT_VOLATILE.S */
7719 /* File: armv5te/OP_SPUT_OBJECT.S */
7720     /*
7721      * 32-bit SPUT handler for objects
7722      *
7723      * for: sput-object, sput-object-volatile
7724      */
7725     /* op vAA, field@BBBB */
7726     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7727     FETCH(r1, 1)                        @ r1<- field ref BBBB
7728     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7729     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7730     cmp     r0, #0                      @ is resolved entry null?
7731     bne     .LOP_SPUT_OBJECT_VOLATILE_finish          @ no, continue
7732     ldr     r9, [rGLUE, #offGlue_method]    @ r9<- current method
7733     EXPORT_PC()                         @ resolve() could throw, so export now
7734     ldr     r0, [r9, #offMethod_clazz]  @ r0<- method->clazz
7735     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
7736     cmp     r0, #0                      @ success?
7737     bne     .LOP_SPUT_OBJECT_VOLATILE_finish          @ yes, finish
7738     b       common_exceptionThrown      @ no, handle exception
7739
7740
7741
7742 /* ------------------------------ */
7743     .balign 64
7744 .L_OP_DISPATCH_FF: /* 0xff */
7745 /* File: armv5te/OP_DISPATCH_FF.S */
7746 /* File: armv5te/unused.S */
7747     bl      common_abort
7748
7749
7750
7751     .balign 64
7752     .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
7753     .global dvmAsmInstructionEnd
7754 dvmAsmInstructionEnd:
7755
7756 /*
7757  * ===========================================================================
7758  *  Sister implementations
7759  * ===========================================================================
7760  */
7761     .global dvmAsmSisterStart
7762     .type   dvmAsmSisterStart, %function
7763     .text
7764     .balign 4
7765 dvmAsmSisterStart:
7766
7767 /* continuation for OP_CONST_STRING */
7768
7769     /*
7770      * Continuation if the String has not yet been resolved.
7771      *  r1: BBBB (String ref)
7772      *  r9: target register
7773      */
7774 .LOP_CONST_STRING_resolve:
7775     EXPORT_PC()
7776     ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7777     ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7778     bl      dvmResolveString            @ r0<- String reference
7779     cmp     r0, #0                      @ failed?
7780     beq     common_exceptionThrown      @ yup, handle the exception
7781     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7782     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7783     SET_VREG(r0, r9)                    @ vAA<- r0
7784     GOTO_OPCODE(ip)                     @ jump to next instruction
7785
7786 /* continuation for OP_CONST_STRING_JUMBO */
7787
7788     /*
7789      * Continuation if the String has not yet been resolved.
7790      *  r1: BBBBBBBB (String ref)
7791      *  r9: target register
7792      */
7793 .LOP_CONST_STRING_JUMBO_resolve:
7794     EXPORT_PC()
7795     ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7796     ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7797     bl      dvmResolveString            @ r0<- String reference
7798     cmp     r0, #0                      @ failed?
7799     beq     common_exceptionThrown      @ yup, handle the exception
7800     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7801     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7802     SET_VREG(r0, r9)                    @ vAA<- r0
7803     GOTO_OPCODE(ip)                     @ jump to next instruction
7804
7805 /* continuation for OP_CONST_CLASS */
7806
7807     /*
7808      * Continuation if the Class has not yet been resolved.
7809      *  r1: BBBB (Class ref)
7810      *  r9: target register
7811      */
7812 .LOP_CONST_CLASS_resolve:
7813     EXPORT_PC()
7814     ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7815     mov     r2, #1                      @ r2<- true
7816     ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7817     bl      dvmResolveClass             @ r0<- Class reference
7818     cmp     r0, #0                      @ failed?
7819     beq     common_exceptionThrown      @ yup, handle the exception
7820     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7821     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7822     SET_VREG(r0, r9)                    @ vAA<- r0
7823     GOTO_OPCODE(ip)                     @ jump to next instruction
7824
7825 /* continuation for OP_CHECK_CAST */
7826
7827     /*
7828      * Trivial test failed, need to perform full check.  This is common.
7829      *  r0 holds obj->clazz
7830      *  r1 holds desired class resolved from BBBB
7831      *  r9 holds object
7832      */
7833 .LOP_CHECK_CAST_fullcheck:
7834     mov     r10, r1                     @ avoid ClassObject getting clobbered
7835     bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7836     cmp     r0, #0                      @ failed?
7837     bne     .LOP_CHECK_CAST_okay            @ no, success
7838
7839     @ A cast has failed.  We need to throw a ClassCastException.
7840     EXPORT_PC()                         @ about to throw
7841     ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz (actual class)
7842     mov     r1, r10                     @ r1<- desired class
7843     bl      dvmThrowClassCastException
7844     b       common_exceptionThrown
7845
7846     /*
7847      * Resolution required.  This is the least-likely path.
7848      *
7849      *  r2 holds BBBB
7850      *  r9 holds object
7851      */
7852 .LOP_CHECK_CAST_resolve:
7853     EXPORT_PC()                         @ resolve() could throw
7854     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7855     mov     r1, r2                      @ r1<- BBBB
7856     mov     r2, #0                      @ r2<- false
7857     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7858     bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7859     cmp     r0, #0                      @ got null?
7860     beq     common_exceptionThrown      @ yes, handle exception
7861     mov     r1, r0                      @ r1<- class resolved from BBB
7862     ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
7863     b       .LOP_CHECK_CAST_resolved        @ pick up where we left off
7864
7865 /* continuation for OP_INSTANCE_OF */
7866
7867     /*
7868      * Trivial test failed, need to perform full check.  This is common.
7869      *  r0 holds obj->clazz
7870      *  r1 holds class resolved from BBBB
7871      *  r9 holds A
7872      */
7873 .LOP_INSTANCE_OF_fullcheck:
7874     bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7875     @ fall through to OP_INSTANCE_OF_store
7876
7877     /*
7878      * r0 holds boolean result
7879      * r9 holds A
7880      */
7881 .LOP_INSTANCE_OF_store:
7882     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7883     SET_VREG(r0, r9)                    @ vA<- r0
7884     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7885     GOTO_OPCODE(ip)                     @ jump to next instruction
7886
7887     /*
7888      * Trivial test succeeded, save and bail.
7889      *  r9 holds A
7890      */
7891 .LOP_INSTANCE_OF_trivial:
7892     mov     r0, #1                      @ indicate success
7893     @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
7894     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7895     SET_VREG(r0, r9)                    @ vA<- r0
7896     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7897     GOTO_OPCODE(ip)                     @ jump to next instruction
7898
7899     /*
7900      * Resolution required.  This is the least-likely path.
7901      *
7902      *  r3 holds BBBB
7903      *  r9 holds A
7904      */
7905 .LOP_INSTANCE_OF_resolve:
7906     EXPORT_PC()                         @ resolve() could throw
7907     ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7908     mov     r1, r3                      @ r1<- BBBB
7909     mov     r2, #1                      @ r2<- true
7910     ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7911     bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7912     cmp     r0, #0                      @ got null?
7913     beq     common_exceptionThrown      @ yes, handle exception
7914     mov     r1, r0                      @ r1<- class resolved from BBB
7915     mov     r3, rINST, lsr #12          @ r3<- B
7916     GET_VREG(r0, r3)                    @ r0<- vB (object)
7917     ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
7918     b       .LOP_INSTANCE_OF_resolved        @ pick up where we left off
7919
7920 /* continuation for OP_NEW_INSTANCE */
7921
7922     .balign 32                          @ minimize cache lines
7923 .LOP_NEW_INSTANCE_finish: @ r0=new object
7924     mov     r3, rINST, lsr #8           @ r3<- AA
7925     cmp     r0, #0                      @ failed?
7926     beq     common_exceptionThrown      @ yes, handle the exception
7927     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7928     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7929     SET_VREG(r0, r3)                    @ vAA<- r0
7930     GOTO_OPCODE(ip)                     @ jump to next instruction
7931
7932     /*
7933      * Class initialization required.
7934      *
7935      *  r0 holds class object
7936      */
7937 .LOP_NEW_INSTANCE_needinit:
7938     mov     r9, r0                      @ save r0
7939     bl      dvmInitClass                @ initialize class
7940     cmp     r0, #0                      @ check boolean result
7941     mov     r0, r9                      @ restore r0
7942     bne     .LOP_NEW_INSTANCE_initialized     @ success, continue
7943     b       common_exceptionThrown      @ failed, deal with init exception
7944
7945     /*
7946      * Resolution required.  This is the least-likely path.
7947      *
7948      *  r1 holds BBBB
7949      */
7950 .LOP_NEW_INSTANCE_resolve:
7951     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7952     mov     r2, #0                      @ r2<- false
7953     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7954     bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7955     cmp     r0, #0                      @ got null?
7956     bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
7957     b       common_exceptionThrown      @ yes, handle exception
7958
7959 .LstrInstantiationErrorPtr:
7960     .word   .LstrInstantiationError
7961
7962 /* continuation for OP_NEW_ARRAY */
7963
7964
7965     /*
7966      * Resolve class.  (This is an uncommon case.)
7967      *
7968      *  r1 holds array length
7969      *  r2 holds class ref CCCC
7970      */
7971 .LOP_NEW_ARRAY_resolve:
7972     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7973     mov     r9, r1                      @ r9<- length (save)
7974     mov     r1, r2                      @ r1<- CCCC
7975     mov     r2, #0                      @ r2<- false
7976     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7977     bl      dvmResolveClass             @ r0<- call(clazz, ref)
7978     cmp     r0, #0                      @ got null?
7979     mov     r1, r9                      @ r1<- length (restore)
7980     beq     common_exceptionThrown      @ yes, handle exception
7981     @ fall through to OP_NEW_ARRAY_finish
7982
7983     /*
7984      * Finish allocation.
7985      *
7986      *  r0 holds class
7987      *  r1 holds array length
7988      */
7989 .LOP_NEW_ARRAY_finish:
7990     mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
7991     bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
7992     cmp     r0, #0                      @ failed?
7993     mov     r2, rINST, lsr #8           @ r2<- A+
7994     beq     common_exceptionThrown      @ yes, handle the exception
7995     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7996     and     r2, r2, #15                 @ r2<- A
7997     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7998     SET_VREG(r0, r2)                    @ vA<- r0
7999     GOTO_OPCODE(ip)                     @ jump to next instruction
8000
8001 /* continuation for OP_FILLED_NEW_ARRAY */
8002
8003     /*
8004      * On entry:
8005      *  r0 holds array class
8006      *  r10 holds AA or BA
8007      */
8008 .LOP_FILLED_NEW_ARRAY_continue:
8009     ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8010     mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8011     ldrb    rINST, [r3, #1]             @ rINST<- descriptor[1]
8012     .if     0
8013     mov     r1, r10                     @ r1<- AA (length)
8014     .else
8015     mov     r1, r10, lsr #4             @ r1<- B (length)
8016     .endif
8017     cmp     rINST, #'I'                 @ array of ints?
8018     cmpne   rINST, #'L'                 @ array of objects?
8019     cmpne   rINST, #'['                 @ array of arrays?
8020     mov     r9, r1                      @ save length in r9
8021     bne     .LOP_FILLED_NEW_ARRAY_notimpl         @ no, not handled yet
8022     bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8023     cmp     r0, #0                      @ null return?
8024     beq     common_exceptionThrown      @ alloc failed, handle exception
8025
8026     FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8027     str     r0, [rGLUE, #offGlue_retval]      @ retval.l <- new array
8028     str     rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
8029     add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8030     subs    r9, r9, #1                  @ length--, check for neg
8031     FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8032     bmi     2f                          @ was zero, bail
8033
8034     @ copy values from registers into the array
8035     @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8036     .if     0
8037     add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
8038 1:  ldr     r3, [r2], #4                @ r3<- *r2++
8039     subs    r9, r9, #1                  @ count--
8040     str     r3, [r0], #4                @ *contents++ = vX
8041     bpl     1b
8042     @ continue at 2
8043     .else
8044     cmp     r9, #4                      @ length was initially 5?
8045     and     r2, r10, #15                @ r2<- A
8046     bne     1f                          @ <= 4 args, branch
8047     GET_VREG(r3, r2)                    @ r3<- vA
8048     sub     r9, r9, #1                  @ count--
8049     str     r3, [r0, #16]               @ contents[4] = vA
8050 1:  and     r2, r1, #15                 @ r2<- F/E/D/C
8051     GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8052     mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8053     subs    r9, r9, #1                  @ count--
8054     str     r3, [r0], #4                @ *contents++ = vX
8055     bpl     1b
8056     @ continue at 2
8057     .endif
8058
8059 2:
8060     ldr     r0, [rGLUE, #offGlue_retval]     @ r0<- object
8061     ldr     r1, [rGLUE, #offGlue_retval+4]   @ r1<- type
8062     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
8063     GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
8064     cmp     r1, #'I'                         @ Is int array?
8065     strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head
8066     GOTO_OPCODE(ip)                          @ execute it
8067
8068     /*
8069      * Throw an exception indicating that we have not implemented this
8070      * mode of filled-new-array.
8071      */
8072 .LOP_FILLED_NEW_ARRAY_notimpl:
8073     ldr     r0, .L_strInternalError
8074     ldr     r1, .L_strFilledNewArrayNotImpl
8075     bl      dvmThrowException
8076     b       common_exceptionThrown
8077
8078     .if     (!0)                 @ define in one or the other, not both
8079 .L_strFilledNewArrayNotImpl:
8080     .word   .LstrFilledNewArrayNotImpl
8081 .L_strInternalError:
8082     .word   .LstrInternalError
8083     .endif
8084
8085 /* continuation for OP_FILLED_NEW_ARRAY_RANGE */
8086
8087     /*
8088      * On entry:
8089      *  r0 holds array class
8090      *  r10 holds AA or BA
8091      */
8092 .LOP_FILLED_NEW_ARRAY_RANGE_continue:
8093     ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8094     mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8095     ldrb    rINST, [r3, #1]             @ rINST<- descriptor[1]
8096     .if     1
8097     mov     r1, r10                     @ r1<- AA (length)
8098     .else
8099     mov     r1, r10, lsr #4             @ r1<- B (length)
8100     .endif
8101     cmp     rINST, #'I'                 @ array of ints?
8102     cmpne   rINST, #'L'                 @ array of objects?
8103     cmpne   rINST, #'['                 @ array of arrays?
8104     mov     r9, r1                      @ save length in r9
8105     bne     .LOP_FILLED_NEW_ARRAY_RANGE_notimpl         @ no, not handled yet
8106     bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8107     cmp     r0, #0                      @ null return?
8108     beq     common_exceptionThrown      @ alloc failed, handle exception
8109
8110     FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8111     str     r0, [rGLUE, #offGlue_retval]      @ retval.l <- new array
8112     str     rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
8113     add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8114     subs    r9, r9, #1                  @ length--, check for neg
8115     FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8116     bmi     2f                          @ was zero, bail
8117
8118     @ copy values from registers into the array
8119     @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8120     .if     1
8121     add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
8122 1:  ldr     r3, [r2], #4                @ r3<- *r2++
8123     subs    r9, r9, #1                  @ count--
8124     str     r3, [r0], #4                @ *contents++ = vX
8125     bpl     1b
8126     @ continue at 2
8127     .else
8128     cmp     r9, #4                      @ length was initially 5?
8129     and     r2, r10, #15                @ r2<- A
8130     bne     1f                          @ <= 4 args, branch
8131     GET_VREG(r3, r2)                    @ r3<- vA
8132     sub     r9, r9, #1                  @ count--
8133     str     r3, [r0, #16]               @ contents[4] = vA
8134 1:  and     r2, r1, #15                 @ r2<- F/E/D/C
8135     GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8136     mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8137     subs    r9, r9, #1                  @ count--
8138     str     r3, [r0], #4                @ *contents++ = vX
8139     bpl     1b
8140     @ continue at 2
8141     .endif
8142
8143 2:
8144     ldr     r0, [rGLUE, #offGlue_retval]     @ r0<- object
8145     ldr     r1, [rGLUE, #offGlue_retval+4]   @ r1<- type
8146     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
8147     GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
8148     cmp     r1, #'I'                         @ Is int array?
8149     strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head
8150     GOTO_OPCODE(ip)                          @ execute it
8151
8152     /*
8153      * Throw an exception indicating that we have not implemented this
8154      * mode of filled-new-array.
8155      */
8156 .LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
8157     ldr     r0, .L_strInternalError
8158     ldr     r1, .L_strFilledNewArrayNotImpl
8159     bl      dvmThrowException
8160     b       common_exceptionThrown
8161
8162     .if     (!1)                 @ define in one or the other, not both
8163 .L_strFilledNewArrayNotImpl:
8164     .word   .LstrFilledNewArrayNotImpl
8165 .L_strInternalError:
8166     .word   .LstrInternalError
8167     .endif
8168
8169 /* continuation for OP_CMPL_FLOAT */
8170 .LOP_CMPL_FLOAT_finish:
8171     SET_VREG(r0, r9)                    @ vAA<- r0
8172     GOTO_OPCODE(ip)                     @ jump to next instruction
8173
8174 /* continuation for OP_CMPG_FLOAT */
8175 .LOP_CMPG_FLOAT_finish:
8176     SET_VREG(r0, r9)                    @ vAA<- r0
8177     GOTO_OPCODE(ip)                     @ jump to next instruction
8178
8179 /* continuation for OP_CMPL_DOUBLE */
8180 .LOP_CMPL_DOUBLE_finish:
8181     SET_VREG(r0, r9)                    @ vAA<- r0
8182     GOTO_OPCODE(ip)                     @ jump to next instruction
8183
8184 /* continuation for OP_CMPG_DOUBLE */
8185 .LOP_CMPG_DOUBLE_finish:
8186     SET_VREG(r0, r9)                    @ vAA<- r0
8187     GOTO_OPCODE(ip)                     @ jump to next instruction
8188
8189 /* continuation for OP_CMP_LONG */
8190
8191 .LOP_CMP_LONG_less:
8192     mvn     r1, #0                      @ r1<- -1
8193     @ Want to cond code the next mov so we can avoid branch, but don't see it;
8194     @ instead, we just replicate the tail end.
8195     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8196     SET_VREG(r1, r9)                    @ vAA<- r1
8197     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8198     GOTO_OPCODE(ip)                     @ jump to next instruction
8199
8200 .LOP_CMP_LONG_greater:
8201     mov     r1, #1                      @ r1<- 1
8202     @ fall through to _finish
8203
8204 .LOP_CMP_LONG_finish:
8205     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8206     SET_VREG(r1, r9)                    @ vAA<- r1
8207     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8208     GOTO_OPCODE(ip)                     @ jump to next instruction
8209
8210 /* continuation for OP_AGET_WIDE */
8211
8212 .LOP_AGET_WIDE_finish:
8213     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8214     ldrd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8215     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
8216     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8217     stmia   r9, {r2-r3}                 @ vAA/vAA+1<- r2/r3
8218     GOTO_OPCODE(ip)                     @ jump to next instruction
8219
8220 /* continuation for OP_APUT_WIDE */
8221
8222 .LOP_APUT_WIDE_finish:
8223     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8224     ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
8225     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8226     strd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8227     GOTO_OPCODE(ip)                     @ jump to next instruction
8228
8229 /* continuation for OP_APUT_OBJECT */
8230     /*
8231      * On entry:
8232      *  rINST = vBB (arrayObj)
8233      *  r9 = vAA (obj)
8234      *  r10 = offset into array (vBB + vCC * width)
8235      */
8236 .LOP_APUT_OBJECT_finish:
8237     cmp     r9, #0                      @ storing null reference?
8238     beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
8239     ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
8240     ldr     r1, [rINST, #offObject_clazz]  @ r1<- arrayObj->clazz
8241     bl      dvmCanPutArrayElement       @ test object type vs. array type
8242     cmp     r0, #0                      @ okay?
8243     beq     .LOP_APUT_OBJECT_throw           @ no
8244     mov     r1, rINST                   @ r1<- arrayObj
8245     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8246     ldr     r2, [rGLUE, #offGlue_cardTable]     @ get biased CT base
8247     add     r10, #offArrayObject_contents   @ r0<- pointer to slot
8248     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8249     str     r9, [r10]                   @ vBB[vCC]<- vAA
8250     strb    r2, [r2, r1, lsr #GC_CARD_SHIFT] @ mark card using object head
8251     GOTO_OPCODE(ip)                     @ jump to next instruction
8252 .LOP_APUT_OBJECT_skip_check:
8253     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8254     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8255     str     r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
8256     GOTO_OPCODE(ip)                     @ jump to next instruction
8257 .LOP_APUT_OBJECT_throw:
8258     @ The types don't match.  We need to throw an ArrayStoreException.
8259     ldr     r0, [r9, #offObject_clazz]
8260     ldr     r1, [rINST, #offObject_clazz]
8261     EXPORT_PC()
8262     bl      dvmThrowArrayStoreException
8263     b       common_exceptionThrown
8264
8265 /* continuation for OP_IGET */
8266
8267     /*
8268      * Currently:
8269      *  r0 holds resolved field
8270      *  r9 holds object
8271      */
8272 .LOP_IGET_finish:
8273     @bl      common_squeak0
8274     cmp     r9, #0                      @ check object for null
8275     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8276     beq     common_errNullObject        @ object was null
8277     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8278     @ no-op                             @ acquiring load
8279     mov     r2, rINST, lsr #8           @ r2<- A+
8280     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8281     and     r2, r2, #15                 @ r2<- A
8282     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8283     SET_VREG(r0, r2)                    @ fp[A]<- r0
8284     GOTO_OPCODE(ip)                     @ jump to next instruction
8285
8286 /* continuation for OP_IGET_WIDE */
8287
8288     /*
8289      * Currently:
8290      *  r0 holds resolved field
8291      *  r9 holds object
8292      */
8293 .LOP_IGET_WIDE_finish:
8294     cmp     r9, #0                      @ check object for null
8295     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8296     beq     common_errNullObject        @ object was null
8297     .if     0
8298     add     r0, r9, r3                  @ r0<- address of field
8299     bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
8300     .else
8301     ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
8302     .endif
8303     mov     r2, rINST, lsr #8           @ r2<- A+
8304     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8305     and     r2, r2, #15                 @ r2<- A
8306     add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
8307     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8308     stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
8309     GOTO_OPCODE(ip)                     @ jump to next instruction
8310
8311 /* continuation for OP_IGET_OBJECT */
8312
8313     /*
8314      * Currently:
8315      *  r0 holds resolved field
8316      *  r9 holds object
8317      */
8318 .LOP_IGET_OBJECT_finish:
8319     @bl      common_squeak0
8320     cmp     r9, #0                      @ check object for null
8321     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8322     beq     common_errNullObject        @ object was null
8323     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8324     @ no-op                             @ acquiring load
8325     mov     r2, rINST, lsr #8           @ r2<- A+
8326     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8327     and     r2, r2, #15                 @ r2<- A
8328     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8329     SET_VREG(r0, r2)                    @ fp[A]<- r0
8330     GOTO_OPCODE(ip)                     @ jump to next instruction
8331
8332 /* continuation for OP_IGET_BOOLEAN */
8333
8334     /*
8335      * Currently:
8336      *  r0 holds resolved field
8337      *  r9 holds object
8338      */
8339 .LOP_IGET_BOOLEAN_finish:
8340     @bl      common_squeak1
8341     cmp     r9, #0                      @ check object for null
8342     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8343     beq     common_errNullObject        @ object was null
8344     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8345     @ no-op                             @ acquiring load
8346     mov     r2, rINST, lsr #8           @ r2<- A+
8347     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8348     and     r2, r2, #15                 @ r2<- A
8349     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8350     SET_VREG(r0, r2)                    @ fp[A]<- r0
8351     GOTO_OPCODE(ip)                     @ jump to next instruction
8352
8353 /* continuation for OP_IGET_BYTE */
8354
8355     /*
8356      * Currently:
8357      *  r0 holds resolved field
8358      *  r9 holds object
8359      */
8360 .LOP_IGET_BYTE_finish:
8361     @bl      common_squeak2
8362     cmp     r9, #0                      @ check object for null
8363     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8364     beq     common_errNullObject        @ object was null
8365     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8366     @ no-op                             @ acquiring load
8367     mov     r2, rINST, lsr #8           @ r2<- A+
8368     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8369     and     r2, r2, #15                 @ r2<- A
8370     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8371     SET_VREG(r0, r2)                    @ fp[A]<- r0
8372     GOTO_OPCODE(ip)                     @ jump to next instruction
8373
8374 /* continuation for OP_IGET_CHAR */
8375
8376     /*
8377      * Currently:
8378      *  r0 holds resolved field
8379      *  r9 holds object
8380      */
8381 .LOP_IGET_CHAR_finish:
8382     @bl      common_squeak3
8383     cmp     r9, #0                      @ check object for null
8384     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8385     beq     common_errNullObject        @ object was null
8386     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8387     @ no-op                             @ acquiring load
8388     mov     r2, rINST, lsr #8           @ r2<- A+
8389     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8390     and     r2, r2, #15                 @ r2<- A
8391     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8392     SET_VREG(r0, r2)                    @ fp[A]<- r0
8393     GOTO_OPCODE(ip)                     @ jump to next instruction
8394
8395 /* continuation for OP_IGET_SHORT */
8396
8397     /*
8398      * Currently:
8399      *  r0 holds resolved field
8400      *  r9 holds object
8401      */
8402 .LOP_IGET_SHORT_finish:
8403     @bl      common_squeak4
8404     cmp     r9, #0                      @ check object for null
8405     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8406     beq     common_errNullObject        @ object was null
8407     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8408     @ no-op                             @ acquiring load
8409     mov     r2, rINST, lsr #8           @ r2<- A+
8410     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8411     and     r2, r2, #15                 @ r2<- A
8412     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8413     SET_VREG(r0, r2)                    @ fp[A]<- r0
8414     GOTO_OPCODE(ip)                     @ jump to next instruction
8415
8416 /* continuation for OP_IPUT */
8417
8418     /*
8419      * Currently:
8420      *  r0 holds resolved field
8421      *  r9 holds object
8422      */
8423 .LOP_IPUT_finish:
8424     @bl      common_squeak0
8425     mov     r1, rINST, lsr #8           @ r1<- A+
8426     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8427     and     r1, r1, #15                 @ r1<- A
8428     cmp     r9, #0                      @ check object for null
8429     GET_VREG(r0, r1)                    @ r0<- fp[A]
8430     beq     common_errNullObject        @ object was null
8431     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8432     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8433     @ no-op                             @ releasing store
8434     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8435     GOTO_OPCODE(ip)                     @ jump to next instruction
8436
8437 /* continuation for OP_IPUT_WIDE */
8438
8439     /*
8440      * Currently:
8441      *  r0 holds resolved field
8442      *  r9 holds object
8443      */
8444 .LOP_IPUT_WIDE_finish:
8445     mov     r2, rINST, lsr #8           @ r2<- A+
8446     cmp     r9, #0                      @ check object for null
8447     and     r2, r2, #15                 @ r2<- A
8448     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8449     add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
8450     beq     common_errNullObject        @ object was null
8451     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8452     ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
8453     GET_INST_OPCODE(r10)                @ extract opcode from rINST
8454     .if     0
8455     add     r2, r9, r3                  @ r2<- target address
8456     bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
8457     .else
8458     strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0/r1
8459     .endif
8460     GOTO_OPCODE(r10)                    @ jump to next instruction
8461
8462 /* continuation for OP_IPUT_OBJECT */
8463
8464     /*
8465      * Currently:
8466      *  r0 holds resolved field
8467      *  r9 holds object
8468      */
8469 .LOP_IPUT_OBJECT_finish:
8470     @bl      common_squeak0
8471     mov     r1, rINST, lsr #8           @ r1<- A+
8472     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8473     and     r1, r1, #15                 @ r1<- A
8474     cmp     r9, #0                      @ check object for null
8475     GET_VREG(r0, r1)                    @ r0<- fp[A]
8476     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
8477     beq     common_errNullObject        @ object was null
8478     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8479     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8480     @ no-op                             @ releasing store
8481     str     r0, [r9, r3]                @ obj.field (32 bits)<- r0
8482     cmp     r0, #0                      @ stored a null reference?
8483     strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
8484     GOTO_OPCODE(ip)                     @ jump to next instruction
8485
8486 /* continuation for OP_IPUT_BOOLEAN */
8487
8488     /*
8489      * Currently:
8490      *  r0 holds resolved field
8491      *  r9 holds object
8492      */
8493 .LOP_IPUT_BOOLEAN_finish:
8494     @bl      common_squeak1
8495     mov     r1, rINST, lsr #8           @ r1<- A+
8496     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8497     and     r1, r1, #15                 @ r1<- A
8498     cmp     r9, #0                      @ check object for null
8499     GET_VREG(r0, r1)                    @ r0<- fp[A]
8500     beq     common_errNullObject        @ object was null
8501     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8502     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8503     @ no-op                             @ releasing store
8504     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8505     GOTO_OPCODE(ip)                     @ jump to next instruction
8506
8507 /* continuation for OP_IPUT_BYTE */
8508
8509     /*
8510      * Currently:
8511      *  r0 holds resolved field
8512      *  r9 holds object
8513      */
8514 .LOP_IPUT_BYTE_finish:
8515     @bl      common_squeak2
8516     mov     r1, rINST, lsr #8           @ r1<- A+
8517     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8518     and     r1, r1, #15                 @ r1<- A
8519     cmp     r9, #0                      @ check object for null
8520     GET_VREG(r0, r1)                    @ r0<- fp[A]
8521     beq     common_errNullObject        @ object was null
8522     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8523     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8524     @ no-op                             @ releasing store
8525     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8526     GOTO_OPCODE(ip)                     @ jump to next instruction
8527
8528 /* continuation for OP_IPUT_CHAR */
8529
8530     /*
8531      * Currently:
8532      *  r0 holds resolved field
8533      *  r9 holds object
8534      */
8535 .LOP_IPUT_CHAR_finish:
8536     @bl      common_squeak3
8537     mov     r1, rINST, lsr #8           @ r1<- A+
8538     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8539     and     r1, r1, #15                 @ r1<- A
8540     cmp     r9, #0                      @ check object for null
8541     GET_VREG(r0, r1)                    @ r0<- fp[A]
8542     beq     common_errNullObject        @ object was null
8543     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8544     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8545     @ no-op                             @ releasing store
8546     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8547     GOTO_OPCODE(ip)                     @ jump to next instruction
8548
8549 /* continuation for OP_IPUT_SHORT */
8550
8551     /*
8552      * Currently:
8553      *  r0 holds resolved field
8554      *  r9 holds object
8555      */
8556 .LOP_IPUT_SHORT_finish:
8557     @bl      common_squeak4
8558     mov     r1, rINST, lsr #8           @ r1<- A+
8559     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8560     and     r1, r1, #15                 @ r1<- A
8561     cmp     r9, #0                      @ check object for null
8562     GET_VREG(r0, r1)                    @ r0<- fp[A]
8563     beq     common_errNullObject        @ object was null
8564     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8565     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8566     @ no-op                             @ releasing store
8567     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8568     GOTO_OPCODE(ip)                     @ jump to next instruction
8569
8570 /* continuation for OP_SGET */
8571
8572     /*
8573      * Continuation if the field has not yet been resolved.
8574      *  r1: BBBB field ref
8575      */
8576 .LOP_SGET_resolve:
8577     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8578     EXPORT_PC()                         @ resolve() could throw, so export now
8579     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8580     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8581     cmp     r0, #0                      @ success?
8582     bne     .LOP_SGET_finish          @ yes, finish
8583     b       common_exceptionThrown      @ no, handle exception
8584
8585 /* continuation for OP_SGET_WIDE */
8586
8587     /*
8588      * Continuation if the field has not yet been resolved.
8589      *  r1: BBBB field ref
8590      *
8591      * Returns StaticField pointer in r0.
8592      */
8593 .LOP_SGET_WIDE_resolve:
8594     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8595     EXPORT_PC()                         @ resolve() could throw, so export now
8596     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8597     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8598     cmp     r0, #0                      @ success?
8599     bne     .LOP_SGET_WIDE_finish          @ yes, finish
8600     b       common_exceptionThrown      @ no, handle exception
8601
8602 /* continuation for OP_SGET_OBJECT */
8603
8604     /*
8605      * Continuation if the field has not yet been resolved.
8606      *  r1: BBBB field ref
8607      */
8608 .LOP_SGET_OBJECT_resolve:
8609     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8610     EXPORT_PC()                         @ resolve() could throw, so export now
8611     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8612     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8613     cmp     r0, #0                      @ success?
8614     bne     .LOP_SGET_OBJECT_finish          @ yes, finish
8615     b       common_exceptionThrown      @ no, handle exception
8616
8617 /* continuation for OP_SGET_BOOLEAN */
8618
8619     /*
8620      * Continuation if the field has not yet been resolved.
8621      *  r1: BBBB field ref
8622      */
8623 .LOP_SGET_BOOLEAN_resolve:
8624     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8625     EXPORT_PC()                         @ resolve() could throw, so export now
8626     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8627     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8628     cmp     r0, #0                      @ success?
8629     bne     .LOP_SGET_BOOLEAN_finish          @ yes, finish
8630     b       common_exceptionThrown      @ no, handle exception
8631
8632 /* continuation for OP_SGET_BYTE */
8633
8634     /*
8635      * Continuation if the field has not yet been resolved.
8636      *  r1: BBBB field ref
8637      */
8638 .LOP_SGET_BYTE_resolve:
8639     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8640     EXPORT_PC()                         @ resolve() could throw, so export now
8641     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8642     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8643     cmp     r0, #0                      @ success?
8644     bne     .LOP_SGET_BYTE_finish          @ yes, finish
8645     b       common_exceptionThrown      @ no, handle exception
8646
8647 /* continuation for OP_SGET_CHAR */
8648
8649     /*
8650      * Continuation if the field has not yet been resolved.
8651      *  r1: BBBB field ref
8652      */
8653 .LOP_SGET_CHAR_resolve:
8654     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8655     EXPORT_PC()                         @ resolve() could throw, so export now
8656     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8657     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8658     cmp     r0, #0                      @ success?
8659     bne     .LOP_SGET_CHAR_finish          @ yes, finish
8660     b       common_exceptionThrown      @ no, handle exception
8661
8662 /* continuation for OP_SGET_SHORT */
8663
8664     /*
8665      * Continuation if the field has not yet been resolved.
8666      *  r1: BBBB field ref
8667      */
8668 .LOP_SGET_SHORT_resolve:
8669     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8670     EXPORT_PC()                         @ resolve() could throw, so export now
8671     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8672     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8673     cmp     r0, #0                      @ success?
8674     bne     .LOP_SGET_SHORT_finish          @ yes, finish
8675     b       common_exceptionThrown      @ no, handle exception
8676
8677 /* continuation for OP_SPUT */
8678
8679     /*
8680      * Continuation if the field has not yet been resolved.
8681      *  r1: BBBB field ref
8682      */
8683 .LOP_SPUT_resolve:
8684     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8685     EXPORT_PC()                         @ resolve() could throw, so export now
8686     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8687     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8688     cmp     r0, #0                      @ success?
8689     bne     .LOP_SPUT_finish          @ yes, finish
8690     b       common_exceptionThrown      @ no, handle exception
8691
8692 /* continuation for OP_SPUT_WIDE */
8693
8694     /*
8695      * Continuation if the field has not yet been resolved.
8696      *  r1: BBBB field ref
8697      *  r9: &fp[AA]
8698      *
8699      * Returns StaticField pointer in r2.
8700      */
8701 .LOP_SPUT_WIDE_resolve:
8702     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8703     EXPORT_PC()                         @ resolve() could throw, so export now
8704     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8705     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8706     cmp     r0, #0                      @ success?
8707     mov     r2, r0                      @ copy to r2
8708     bne     .LOP_SPUT_WIDE_finish          @ yes, finish
8709     b       common_exceptionThrown      @ no, handle exception
8710
8711 /* continuation for OP_SPUT_OBJECT */
8712 .LOP_SPUT_OBJECT_finish:   @ field ptr in r0
8713     mov     r2, rINST, lsr #8           @ r2<- AA
8714     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8715     GET_VREG(r1, r2)                    @ r1<- fp[AA]
8716     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
8717     ldr     r9, [r0, #offField_clazz]   @ r9<- field->clazz
8718     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8719     @ no-op                             @ releasing store
8720     str     r1, [r0, #offStaticField_value]  @ field<- vAA
8721     cmp     r1, #0                      @ stored a null object?
8722     strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card based on obj head
8723     GOTO_OPCODE(ip)                     @ jump to next instruction
8724
8725 /* continuation for OP_SPUT_BOOLEAN */
8726
8727     /*
8728      * Continuation if the field has not yet been resolved.
8729      *  r1: BBBB field ref
8730      */
8731 .LOP_SPUT_BOOLEAN_resolve:
8732     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8733     EXPORT_PC()                         @ resolve() could throw, so export now
8734     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8735     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8736     cmp     r0, #0                      @ success?
8737     bne     .LOP_SPUT_BOOLEAN_finish          @ yes, finish
8738     b       common_exceptionThrown      @ no, handle exception
8739
8740 /* continuation for OP_SPUT_BYTE */
8741
8742     /*
8743      * Continuation if the field has not yet been resolved.
8744      *  r1: BBBB field ref
8745      */
8746 .LOP_SPUT_BYTE_resolve:
8747     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8748     EXPORT_PC()                         @ resolve() could throw, so export now
8749     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8750     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8751     cmp     r0, #0                      @ success?
8752     bne     .LOP_SPUT_BYTE_finish          @ yes, finish
8753     b       common_exceptionThrown      @ no, handle exception
8754
8755 /* continuation for OP_SPUT_CHAR */
8756
8757     /*
8758      * Continuation if the field has not yet been resolved.
8759      *  r1: BBBB field ref
8760      */
8761 .LOP_SPUT_CHAR_resolve:
8762     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8763     EXPORT_PC()                         @ resolve() could throw, so export now
8764     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8765     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8766     cmp     r0, #0                      @ success?
8767     bne     .LOP_SPUT_CHAR_finish          @ yes, finish
8768     b       common_exceptionThrown      @ no, handle exception
8769
8770 /* continuation for OP_SPUT_SHORT */
8771
8772     /*
8773      * Continuation if the field has not yet been resolved.
8774      *  r1: BBBB field ref
8775      */
8776 .LOP_SPUT_SHORT_resolve:
8777     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8778     EXPORT_PC()                         @ resolve() could throw, so export now
8779     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8780     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8781     cmp     r0, #0                      @ success?
8782     bne     .LOP_SPUT_SHORT_finish          @ yes, finish
8783     b       common_exceptionThrown      @ no, handle exception
8784
8785 /* continuation for OP_INVOKE_VIRTUAL */
8786
8787     /*
8788      * At this point:
8789      *  r0 = resolved base method
8790      *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8791      */
8792 .LOP_INVOKE_VIRTUAL_continue:
8793     GET_VREG(r1, r10)                   @ r1<- "this" ptr
8794     ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8795     cmp     r1, #0                      @ is "this" null?
8796     beq     common_errNullObject        @ null "this", throw exception
8797     ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8798     ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8799     ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8800     bl      common_invokeMethodNoRange @ continue on
8801
8802 /* continuation for OP_INVOKE_SUPER */
8803
8804     /*
8805      * At this point:
8806      *  r0 = resolved base method
8807      *  r9 = method->clazz
8808      */
8809 .LOP_INVOKE_SUPER_continue:
8810     ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8811     ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8812     ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8813     EXPORT_PC()                         @ must export for invoke
8814     cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8815     bcs     .LOP_INVOKE_SUPER_nsm             @ method not present in superclass
8816     ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8817     ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8818     bl      common_invokeMethodNoRange @ continue on
8819
8820 .LOP_INVOKE_SUPER_resolve:
8821     mov     r0, r9                      @ r0<- method->clazz
8822     mov     r2, #METHOD_VIRTUAL         @ resolver method type
8823     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8824     cmp     r0, #0                      @ got null?
8825     bne     .LOP_INVOKE_SUPER_continue        @ no, continue
8826     b       common_exceptionThrown      @ yes, handle exception
8827
8828     /*
8829      * Throw a NoSuchMethodError with the method name as the message.
8830      *  r0 = resolved base method
8831      */
8832 .LOP_INVOKE_SUPER_nsm:
8833     ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8834     b       common_errNoSuchMethod
8835
8836 /* continuation for OP_INVOKE_DIRECT */
8837
8838     /*
8839      * On entry:
8840      *  r1 = reference (BBBB or CCCC)
8841      *  r10 = "this" register
8842      */
8843 .LOP_INVOKE_DIRECT_resolve:
8844     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8845     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8846     mov     r2, #METHOD_DIRECT          @ resolver method type
8847     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8848     cmp     r0, #0                      @ got null?
8849     GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8850     bne     .LOP_INVOKE_DIRECT_finish          @ no, continue
8851     b       common_exceptionThrown      @ yes, handle exception
8852
8853 /* continuation for OP_INVOKE_VIRTUAL_RANGE */
8854
8855     /*
8856      * At this point:
8857      *  r0 = resolved base method
8858      *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8859      */
8860 .LOP_INVOKE_VIRTUAL_RANGE_continue:
8861     GET_VREG(r1, r10)                   @ r1<- "this" ptr
8862     ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8863     cmp     r1, #0                      @ is "this" null?
8864     beq     common_errNullObject        @ null "this", throw exception
8865     ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8866     ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8867     ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8868     bl      common_invokeMethodRange @ continue on
8869
8870 /* continuation for OP_INVOKE_SUPER_RANGE */
8871
8872     /*
8873      * At this point:
8874      *  r0 = resolved base method
8875      *  r9 = method->clazz
8876      */
8877 .LOP_INVOKE_SUPER_RANGE_continue:
8878     ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8879     ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8880     ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8881     EXPORT_PC()                         @ must export for invoke
8882     cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8883     bcs     .LOP_INVOKE_SUPER_RANGE_nsm             @ method not present in superclass
8884     ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8885     ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8886     bl      common_invokeMethodRange @ continue on
8887
8888 .LOP_INVOKE_SUPER_RANGE_resolve:
8889     mov     r0, r9                      @ r0<- method->clazz
8890     mov     r2, #METHOD_VIRTUAL         @ resolver method type
8891     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8892     cmp     r0, #0                      @ got null?
8893     bne     .LOP_INVOKE_SUPER_RANGE_continue        @ no, continue
8894     b       common_exceptionThrown      @ yes, handle exception
8895
8896     /*
8897      * Throw a NoSuchMethodError with the method name as the message.
8898      *  r0 = resolved base method
8899      */
8900 .LOP_INVOKE_SUPER_RANGE_nsm:
8901     ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8902     b       common_errNoSuchMethod
8903
8904 /* continuation for OP_INVOKE_DIRECT_RANGE */
8905
8906     /*
8907      * On entry:
8908      *  r1 = reference (BBBB or CCCC)
8909      *  r10 = "this" register
8910      */
8911 .LOP_INVOKE_DIRECT_RANGE_resolve:
8912     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8913     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8914     mov     r2, #METHOD_DIRECT          @ resolver method type
8915     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8916     cmp     r0, #0                      @ got null?
8917     GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8918     bne     .LOP_INVOKE_DIRECT_RANGE_finish          @ no, continue
8919     b       common_exceptionThrown      @ yes, handle exception
8920
8921 /* continuation for OP_FLOAT_TO_LONG */
8922 /*
8923  * Convert the float in r0 to a long in r0/r1.
8924  *
8925  * We have to clip values to long min/max per the specification.  The
8926  * expected common case is a "reasonable" value that converts directly
8927  * to modest integer.  The EABI convert function isn't doing this for us.
8928  */
8929 f2l_doconv:
8930     stmfd   sp!, {r4, lr}
8931     mov     r1, #0x5f000000             @ (float)maxlong
8932     mov     r4, r0
8933     bl      __aeabi_fcmpge              @ is arg >= maxlong?
8934     cmp     r0, #0                      @ nonzero == yes
8935     mvnne   r0, #0                      @ return maxlong (7fffffff)
8936     mvnne   r1, #0x80000000
8937     ldmnefd sp!, {r4, pc}
8938
8939     mov     r0, r4                      @ recover arg
8940     mov     r1, #0xdf000000             @ (float)minlong
8941     bl      __aeabi_fcmple              @ is arg <= minlong?
8942     cmp     r0, #0                      @ nonzero == yes
8943     movne   r0, #0                      @ return minlong (80000000)
8944     movne   r1, #0x80000000
8945     ldmnefd sp!, {r4, pc}
8946
8947     mov     r0, r4                      @ recover arg
8948     mov     r1, r4
8949     bl      __aeabi_fcmpeq              @ is arg == self?
8950     cmp     r0, #0                      @ zero == no
8951     moveq   r1, #0                      @ return zero for NaN
8952     ldmeqfd sp!, {r4, pc}
8953
8954     mov     r0, r4                      @ recover arg
8955     bl      __aeabi_f2lz                @ convert float to long
8956     ldmfd   sp!, {r4, pc}
8957
8958 /* continuation for OP_DOUBLE_TO_LONG */
8959 /*
8960  * Convert the double in r0/r1 to a long in r0/r1.
8961  *
8962  * We have to clip values to long min/max per the specification.  The
8963  * expected common case is a "reasonable" value that converts directly
8964  * to modest integer.  The EABI convert function isn't doing this for us.
8965  */
8966 d2l_doconv:
8967     stmfd   sp!, {r4, r5, lr}           @ save regs
8968     mov     r3, #0x43000000             @ maxlong, as a double (high word)
8969     add     r3, #0x00e00000             @  0x43e00000
8970     mov     r2, #0                      @ maxlong, as a double (low word)
8971     sub     sp, sp, #4                  @ align for EABI
8972     mov     r4, r0                      @ save a copy of r0
8973     mov     r5, r1                      @  and r1
8974     bl      __aeabi_dcmpge              @ is arg >= maxlong?
8975     cmp     r0, #0                      @ nonzero == yes
8976     mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
8977     mvnne   r1, #0x80000000
8978     bne     1f
8979
8980     mov     r0, r4                      @ recover arg
8981     mov     r1, r5
8982     mov     r3, #0xc3000000             @ minlong, as a double (high word)
8983     add     r3, #0x00e00000             @  0xc3e00000
8984     mov     r2, #0                      @ minlong, as a double (low word)
8985     bl      __aeabi_dcmple              @ is arg <= minlong?
8986     cmp     r0, #0                      @ nonzero == yes
8987     movne   r0, #0                      @ return minlong (8000000000000000)
8988     movne   r1, #0x80000000
8989     bne     1f
8990
8991     mov     r0, r4                      @ recover arg
8992     mov     r1, r5
8993     mov     r2, r4                      @ compare against self
8994     mov     r3, r5
8995     bl      __aeabi_dcmpeq              @ is arg == self?
8996     cmp     r0, #0                      @ zero == no
8997     moveq   r1, #0                      @ return zero for NaN
8998     beq     1f
8999
9000     mov     r0, r4                      @ recover arg
9001     mov     r1, r5
9002     bl      __aeabi_d2lz                @ convert double to long
9003
9004 1:
9005     add     sp, sp, #4
9006     ldmfd   sp!, {r4, r5, pc}
9007
9008 /* continuation for OP_MUL_LONG */
9009
9010 .LOP_MUL_LONG_finish:
9011     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9012     stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
9013     GOTO_OPCODE(ip)                     @ jump to next instruction
9014
9015 /* continuation for OP_SHL_LONG */
9016
9017 .LOP_SHL_LONG_finish:
9018     mov     r0, r0, asl r2              @  r0<- r0 << r2
9019     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9020     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9021     GOTO_OPCODE(ip)                     @ jump to next instruction
9022
9023 /* continuation for OP_SHR_LONG */
9024
9025 .LOP_SHR_LONG_finish:
9026     mov     r1, r1, asr r2              @  r1<- r1 >> r2
9027     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9028     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9029     GOTO_OPCODE(ip)                     @ jump to next instruction
9030
9031 /* continuation for OP_USHR_LONG */
9032
9033 .LOP_USHR_LONG_finish:
9034     mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
9035     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9036     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9037     GOTO_OPCODE(ip)                     @ jump to next instruction
9038
9039 /* continuation for OP_SHL_LONG_2ADDR */
9040
9041 .LOP_SHL_LONG_2ADDR_finish:
9042     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9043     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9044     GOTO_OPCODE(ip)                     @ jump to next instruction
9045
9046 /* continuation for OP_SHR_LONG_2ADDR */
9047
9048 .LOP_SHR_LONG_2ADDR_finish:
9049     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9050     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9051     GOTO_OPCODE(ip)                     @ jump to next instruction
9052
9053 /* continuation for OP_USHR_LONG_2ADDR */
9054
9055 .LOP_USHR_LONG_2ADDR_finish:
9056     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9057     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9058     GOTO_OPCODE(ip)                     @ jump to next instruction
9059
9060 /* continuation for OP_IGET_VOLATILE */
9061
9062     /*
9063      * Currently:
9064      *  r0 holds resolved field
9065      *  r9 holds object
9066      */
9067 .LOP_IGET_VOLATILE_finish:
9068     @bl      common_squeak0
9069     cmp     r9, #0                      @ check object for null
9070     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9071     beq     common_errNullObject        @ object was null
9072     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
9073     SMP_DMB                            @ acquiring load
9074     mov     r2, rINST, lsr #8           @ r2<- A+
9075     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9076     and     r2, r2, #15                 @ r2<- A
9077     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9078     SET_VREG(r0, r2)                    @ fp[A]<- r0
9079     GOTO_OPCODE(ip)                     @ jump to next instruction
9080
9081 /* continuation for OP_IPUT_VOLATILE */
9082
9083     /*
9084      * Currently:
9085      *  r0 holds resolved field
9086      *  r9 holds object
9087      */
9088 .LOP_IPUT_VOLATILE_finish:
9089     @bl      common_squeak0
9090     mov     r1, rINST, lsr #8           @ r1<- A+
9091     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9092     and     r1, r1, #15                 @ r1<- A
9093     cmp     r9, #0                      @ check object for null
9094     GET_VREG(r0, r1)                    @ r0<- fp[A]
9095     beq     common_errNullObject        @ object was null
9096     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9097     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9098     SMP_DMB                            @ releasing store
9099     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
9100     GOTO_OPCODE(ip)                     @ jump to next instruction
9101
9102 /* continuation for OP_SGET_VOLATILE */
9103
9104     /*
9105      * Continuation if the field has not yet been resolved.
9106      *  r1: BBBB field ref
9107      */
9108 .LOP_SGET_VOLATILE_resolve:
9109     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9110     EXPORT_PC()                         @ resolve() could throw, so export now
9111     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9112     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9113     cmp     r0, #0                      @ success?
9114     bne     .LOP_SGET_VOLATILE_finish          @ yes, finish
9115     b       common_exceptionThrown      @ no, handle exception
9116
9117 /* continuation for OP_SPUT_VOLATILE */
9118
9119     /*
9120      * Continuation if the field has not yet been resolved.
9121      *  r1: BBBB field ref
9122      */
9123 .LOP_SPUT_VOLATILE_resolve:
9124     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9125     EXPORT_PC()                         @ resolve() could throw, so export now
9126     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9127     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9128     cmp     r0, #0                      @ success?
9129     bne     .LOP_SPUT_VOLATILE_finish          @ yes, finish
9130     b       common_exceptionThrown      @ no, handle exception
9131
9132 /* continuation for OP_IGET_OBJECT_VOLATILE */
9133
9134     /*
9135      * Currently:
9136      *  r0 holds resolved field
9137      *  r9 holds object
9138      */
9139 .LOP_IGET_OBJECT_VOLATILE_finish:
9140     @bl      common_squeak0
9141     cmp     r9, #0                      @ check object for null
9142     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9143     beq     common_errNullObject        @ object was null
9144     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
9145     SMP_DMB                            @ acquiring load
9146     mov     r2, rINST, lsr #8           @ r2<- A+
9147     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9148     and     r2, r2, #15                 @ r2<- A
9149     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9150     SET_VREG(r0, r2)                    @ fp[A]<- r0
9151     GOTO_OPCODE(ip)                     @ jump to next instruction
9152
9153 /* continuation for OP_IGET_WIDE_VOLATILE */
9154
9155     /*
9156      * Currently:
9157      *  r0 holds resolved field
9158      *  r9 holds object
9159      */
9160 .LOP_IGET_WIDE_VOLATILE_finish:
9161     cmp     r9, #0                      @ check object for null
9162     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9163     beq     common_errNullObject        @ object was null
9164     .if     1
9165     add     r0, r9, r3                  @ r0<- address of field
9166     bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
9167     .else
9168     ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
9169     .endif
9170     mov     r2, rINST, lsr #8           @ r2<- A+
9171     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9172     and     r2, r2, #15                 @ r2<- A
9173     add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
9174     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9175     stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
9176     GOTO_OPCODE(ip)                     @ jump to next instruction
9177
9178 /* continuation for OP_IPUT_WIDE_VOLATILE */
9179
9180     /*
9181      * Currently:
9182      *  r0 holds resolved field
9183      *  r9 holds object
9184      */
9185 .LOP_IPUT_WIDE_VOLATILE_finish:
9186     mov     r2, rINST, lsr #8           @ r2<- A+
9187     cmp     r9, #0                      @ check object for null
9188     and     r2, r2, #15                 @ r2<- A
9189     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9190     add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
9191     beq     common_errNullObject        @ object was null
9192     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9193     ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
9194     GET_INST_OPCODE(r10)                @ extract opcode from rINST
9195     .if     1
9196     add     r2, r9, r3                  @ r2<- target address
9197     bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
9198     .else
9199     strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0/r1
9200     .endif
9201     GOTO_OPCODE(r10)                    @ jump to next instruction
9202
9203 /* continuation for OP_SGET_WIDE_VOLATILE */
9204
9205     /*
9206      * Continuation if the field has not yet been resolved.
9207      *  r1: BBBB field ref
9208      *
9209      * Returns StaticField pointer in r0.
9210      */
9211 .LOP_SGET_WIDE_VOLATILE_resolve:
9212     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9213     EXPORT_PC()                         @ resolve() could throw, so export now
9214     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9215     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9216     cmp     r0, #0                      @ success?
9217     bne     .LOP_SGET_WIDE_VOLATILE_finish          @ yes, finish
9218     b       common_exceptionThrown      @ no, handle exception
9219
9220 /* continuation for OP_SPUT_WIDE_VOLATILE */
9221
9222     /*
9223      * Continuation if the field has not yet been resolved.
9224      *  r1: BBBB field ref
9225      *  r9: &fp[AA]
9226      *
9227      * Returns StaticField pointer in r2.
9228      */
9229 .LOP_SPUT_WIDE_VOLATILE_resolve:
9230     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9231     EXPORT_PC()                         @ resolve() could throw, so export now
9232     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9233     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9234     cmp     r0, #0                      @ success?
9235     mov     r2, r0                      @ copy to r2
9236     bne     .LOP_SPUT_WIDE_VOLATILE_finish          @ yes, finish
9237     b       common_exceptionThrown      @ no, handle exception
9238
9239 /* continuation for OP_EXECUTE_INLINE */
9240
9241     /*
9242      * Extract args, call function.
9243      *  r0 = #of args (0-4)
9244      *  r10 = call index
9245      *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
9246      *
9247      * Other ideas:
9248      * - Use a jump table from the main piece to jump directly into the
9249      *   AND/LDR pairs.  Costs a data load, saves a branch.
9250      * - Have five separate pieces that do the loading, so we can work the
9251      *   interleave a little better.  Increases code size.
9252      */
9253 .LOP_EXECUTE_INLINE_continue:
9254     rsb     r0, r0, #4                  @ r0<- 4-r0
9255     FETCH(r9, 2)                        @ r9<- FEDC
9256     add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
9257     bl      common_abort                @ (skipped due to ARM prefetch)
9258 4:  and     ip, r9, #0xf000             @ isolate F
9259     ldr     r3, [rFP, ip, lsr #10]      @ r3<- vF (shift right 12, left 2)
9260 3:  and     ip, r9, #0x0f00             @ isolate E
9261     ldr     r2, [rFP, ip, lsr #6]       @ r2<- vE
9262 2:  and     ip, r9, #0x00f0             @ isolate D
9263     ldr     r1, [rFP, ip, lsr #2]       @ r1<- vD
9264 1:  and     ip, r9, #0x000f             @ isolate C
9265     ldr     r0, [rFP, ip, lsl #2]       @ r0<- vC
9266 0:
9267     ldr     r9, .LOP_EXECUTE_INLINE_table       @ table of InlineOperation
9268     ldr     pc, [r9, r10, lsl #4]       @ sizeof=16, "func" is first entry
9269     @ (not reached)
9270
9271 .LOP_EXECUTE_INLINE_table:
9272     .word   gDvmInlineOpsTable
9273
9274 /* continuation for OP_EXECUTE_INLINE_RANGE */
9275
9276     /*
9277      * Extract args, call function.
9278      *  r0 = #of args (0-4)
9279      *  r10 = call index
9280      *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
9281      */
9282 .LOP_EXECUTE_INLINE_RANGE_continue:
9283     rsb     r0, r0, #4                  @ r0<- 4-r0
9284     FETCH(r9, 2)                        @ r9<- CCCC
9285     add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
9286     bl      common_abort                @ (skipped due to ARM prefetch)
9287 4:  add     ip, r9, #3                  @ base+3
9288     GET_VREG(r3, ip)                    @ r3<- vBase[3]
9289 3:  add     ip, r9, #2                  @ base+2
9290     GET_VREG(r2, ip)                    @ r2<- vBase[2]
9291 2:  add     ip, r9, #1                  @ base+1
9292     GET_VREG(r1, ip)                    @ r1<- vBase[1]
9293 1:  add     ip, r9, #0                  @ (nop)
9294     GET_VREG(r0, ip)                    @ r0<- vBase[0]
9295 0:
9296     ldr     r9, .LOP_EXECUTE_INLINE_RANGE_table       @ table of InlineOperation
9297     ldr     pc, [r9, r10, lsl #4]       @ sizeof=16, "func" is first entry
9298     @ (not reached)
9299
9300 .LOP_EXECUTE_INLINE_RANGE_table:
9301     .word   gDvmInlineOpsTable
9302
9303 /* continuation for OP_IPUT_OBJECT_VOLATILE */
9304
9305     /*
9306      * Currently:
9307      *  r0 holds resolved field
9308      *  r9 holds object
9309      */
9310 .LOP_IPUT_OBJECT_VOLATILE_finish:
9311     @bl      common_squeak0
9312     mov     r1, rINST, lsr #8           @ r1<- A+
9313     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9314     and     r1, r1, #15                 @ r1<- A
9315     cmp     r9, #0                      @ check object for null
9316     GET_VREG(r0, r1)                    @ r0<- fp[A]
9317     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
9318     beq     common_errNullObject        @ object was null
9319     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9320     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9321     SMP_DMB                            @ releasing store
9322     str     r0, [r9, r3]                @ obj.field (32 bits)<- r0
9323     cmp     r0, #0                      @ stored a null reference?
9324     strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
9325     GOTO_OPCODE(ip)                     @ jump to next instruction
9326
9327 /* continuation for OP_SGET_OBJECT_VOLATILE */
9328
9329     /*
9330      * Continuation if the field has not yet been resolved.
9331      *  r1: BBBB field ref
9332      */
9333 .LOP_SGET_OBJECT_VOLATILE_resolve:
9334     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9335     EXPORT_PC()                         @ resolve() could throw, so export now
9336     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9337     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9338     cmp     r0, #0                      @ success?
9339     bne     .LOP_SGET_OBJECT_VOLATILE_finish          @ yes, finish
9340     b       common_exceptionThrown      @ no, handle exception
9341
9342 /* continuation for OP_SPUT_OBJECT_VOLATILE */
9343 .LOP_SPUT_OBJECT_VOLATILE_finish:   @ field ptr in r0
9344     mov     r2, rINST, lsr #8           @ r2<- AA
9345     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9346     GET_VREG(r1, r2)                    @ r1<- fp[AA]
9347     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
9348     ldr     r9, [r0, #offField_clazz]   @ r9<- field->clazz
9349     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9350     SMP_DMB                            @ releasing store
9351     str     r1, [r0, #offStaticField_value]  @ field<- vAA
9352     cmp     r1, #0                      @ stored a null object?
9353     strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card based on obj head
9354     GOTO_OPCODE(ip)                     @ jump to next instruction
9355
9356     .size   dvmAsmSisterStart, .-dvmAsmSisterStart
9357     .global dvmAsmSisterEnd
9358 dvmAsmSisterEnd:
9359
9360 /* File: armv5te/footer.S */
9361
9362 /*
9363  * ===========================================================================
9364  *  Common subroutines and data
9365  * ===========================================================================
9366  */
9367
9368
9369
9370     .text
9371     .align  2
9372
9373 #if defined(WITH_JIT)
9374 #if defined(WITH_SELF_VERIFICATION)
9375     .global dvmJitToInterpPunt
9376 dvmJitToInterpPunt:
9377     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9378     mov    r2,#kSVSPunt                 @ r2<- interpreter entry point
9379     mov    r3, #0
9380     str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9381     b      jitSVShadowRunEnd            @ doesn't return
9382
9383     .global dvmJitToInterpSingleStep
9384 dvmJitToInterpSingleStep:
9385     str    lr,[rGLUE,#offGlue_jitResumeNPC]
9386     str    r1,[rGLUE,#offGlue_jitResumeDPC]
9387     mov    r2,#kSVSSingleStep           @ r2<- interpreter entry point
9388     b      jitSVShadowRunEnd            @ doesn't return
9389
9390     .global dvmJitToInterpNoChainNoProfile
9391 dvmJitToInterpNoChainNoProfile:
9392     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9393     mov    r0,rPC                       @ pass our target PC
9394     mov    r2,#kSVSNoProfile            @ r2<- interpreter entry point
9395     mov    r3, #0                       @ 0 means !inJitCodeCache
9396     str    r3, [r10, #offThread_inJitCodeCache] @ back to the interp land
9397     b      jitSVShadowRunEnd            @ doesn't return
9398
9399     .global dvmJitToInterpTraceSelectNoChain
9400 dvmJitToInterpTraceSelectNoChain:
9401     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9402     mov    r0,rPC                       @ pass our target PC
9403     mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
9404     mov    r3, #0                       @ 0 means !inJitCodeCache
9405     str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9406     b      jitSVShadowRunEnd            @ doesn't return
9407
9408     .global dvmJitToInterpTraceSelect
9409 dvmJitToInterpTraceSelect:
9410     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9411     ldr    r0,[lr, #-1]                 @ pass our target PC
9412     mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
9413     mov    r3, #0                       @ 0 means !inJitCodeCache
9414     str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9415     b      jitSVShadowRunEnd            @ doesn't return
9416
9417     .global dvmJitToInterpBackwardBranch
9418 dvmJitToInterpBackwardBranch:
9419     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9420     ldr    r0,[lr, #-1]                 @ pass our target PC
9421     mov    r2,#kSVSBackwardBranch       @ r2<- interpreter entry point
9422     mov    r3, #0                       @ 0 means !inJitCodeCache
9423     str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9424     b      jitSVShadowRunEnd            @ doesn't return
9425
9426     .global dvmJitToInterpNormal
9427 dvmJitToInterpNormal:
9428     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9429     ldr    r0,[lr, #-1]                 @ pass our target PC
9430     mov    r2,#kSVSNormal               @ r2<- interpreter entry point
9431     mov    r3, #0                       @ 0 means !inJitCodeCache
9432     str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9433     b      jitSVShadowRunEnd            @ doesn't return
9434
9435     .global dvmJitToInterpNoChain
9436 dvmJitToInterpNoChain:
9437     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9438     mov    r0,rPC                       @ pass our target PC
9439     mov    r2,#kSVSNoChain              @ r2<- interpreter entry point
9440     mov    r3, #0                       @ 0 means !inJitCodeCache
9441     str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9442     b      jitSVShadowRunEnd            @ doesn't return
9443 #else
9444 /*
9445  * Return from the translation cache to the interpreter when the compiler is
9446  * having issues translating/executing a Dalvik instruction. We have to skip
9447  * the code cache lookup otherwise it is possible to indefinitely bouce
9448  * between the interpreter and the code cache if the instruction that fails
9449  * to be compiled happens to be at a trace start.
9450  */
9451     .global dvmJitToInterpPunt
9452 dvmJitToInterpPunt:
9453     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9454     mov    rPC, r0
9455 #if defined(WITH_JIT_TUNING)
9456     mov    r0,lr
9457     bl     dvmBumpPunt;
9458 #endif
9459     EXPORT_PC()
9460     mov    r0, #0
9461     str    r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9462     adrl   rIBASE, dvmAsmInstructionStart
9463     FETCH_INST()
9464     GET_INST_OPCODE(ip)
9465     GOTO_OPCODE(ip)
9466
9467 /*
9468  * Return to the interpreter to handle a single instruction.
9469  * On entry:
9470  *    r0 <= PC
9471  *    r1 <= PC of resume instruction
9472  *    lr <= resume point in translation
9473  */
9474     .global dvmJitToInterpSingleStep
9475 dvmJitToInterpSingleStep:
9476     str    lr,[rGLUE,#offGlue_jitResumeNPC]
9477     str    r1,[rGLUE,#offGlue_jitResumeDPC]
9478     mov    r1,#kInterpEntryInstr
9479     @ enum is 4 byte in aapcs-EABI
9480     str    r1, [rGLUE, #offGlue_entryPoint]
9481     mov    rPC,r0
9482     EXPORT_PC()
9483
9484     adrl   rIBASE, dvmAsmInstructionStart
9485     mov    r2,#kJitSingleStep     @ Ask for single step and then revert
9486     str    r2,[rGLUE,#offGlue_jitState]
9487     mov    r1,#1                  @ set changeInterp to bail to debug interp
9488     b      common_gotoBail
9489
9490 /*
9491  * Return from the translation cache and immediately request
9492  * a translation for the exit target.  Commonly used for callees.
9493  */
9494     .global dvmJitToInterpTraceSelectNoChain
9495 dvmJitToInterpTraceSelectNoChain:
9496 #if defined(WITH_JIT_TUNING)
9497     bl     dvmBumpNoChain
9498 #endif
9499     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9500     mov    r0,rPC
9501     bl     dvmJitGetCodeAddr        @ Is there a translation?
9502     str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9503     mov    r1, rPC                  @ arg1 of translation may need this
9504     mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9505     cmp    r0,#0                    @ !0 means translation exists
9506     bxne   r0                       @ continue native execution if so
9507     b      2f                       @ branch over to use the interpreter
9508
9509 /*
9510  * Return from the translation cache and immediately request
9511  * a translation for the exit target.  Commonly used following
9512  * invokes.
9513  */
9514     .global dvmJitToInterpTraceSelect
9515 dvmJitToInterpTraceSelect:
9516     ldr    rPC,[lr, #-1]           @ get our target PC
9517     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9518     add    rINST,lr,#-5            @ save start of chain branch
9519     add    rINST, #-4              @  .. which is 9 bytes back
9520     mov    r0,rPC
9521     bl     dvmJitGetCodeAddr       @ Is there a translation?
9522     str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9523     cmp    r0,#0
9524     beq    2f
9525     mov    r1,rINST
9526     bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9527     mov    r1, rPC                  @ arg1 of translation may need this
9528     mov    lr, #0                   @ in case target is HANDLER_INTERPRET
9529     cmp    r0,#0                    @ successful chain?
9530     bxne   r0                       @ continue native execution
9531     b      toInterpreter            @ didn't chain - resume with interpreter
9532
9533 /* No translation, so request one if profiling isn't disabled*/
9534 2:
9535     adrl   rIBASE, dvmAsmInstructionStart
9536     GET_JIT_PROF_TABLE(r0)
9537     FETCH_INST()
9538     cmp    r0, #0
9539     movne  r2,#kJitTSelectRequestHot   @ ask for trace selection
9540     bne    common_selectTrace
9541     GET_INST_OPCODE(ip)
9542     GOTO_OPCODE(ip)
9543
9544 /*
9545  * Return from the translation cache to the interpreter.
9546  * The return was done with a BLX from thumb mode, and
9547  * the following 32-bit word contains the target rPC value.
9548  * Note that lr (r14) will have its low-order bit set to denote
9549  * its thumb-mode origin.
9550  *
9551  * We'll need to stash our lr origin away, recover the new
9552  * target and then check to see if there is a translation available
9553  * for our new target.  If so, we do a translation chain and
9554  * go back to native execution.  Otherwise, it's back to the
9555  * interpreter (after treating this entry as a potential
9556  * trace start).
9557  */
9558     .global dvmJitToInterpNormal
9559 dvmJitToInterpNormal:
9560     ldr    rPC,[lr, #-1]           @ get our target PC
9561     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9562     add    rINST,lr,#-5            @ save start of chain branch
9563     add    rINST,#-4               @ .. which is 9 bytes back
9564 #if defined(WITH_JIT_TUNING)
9565     bl     dvmBumpNormal
9566 #endif
9567     mov    r0,rPC
9568     bl     dvmJitGetCodeAddr        @ Is there a translation?
9569     str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9570     cmp    r0,#0
9571     beq    toInterpreter            @ go if not, otherwise do chain
9572     mov    r1,rINST
9573     bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9574     mov    r1, rPC                  @ arg1 of translation may need this
9575     mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9576     cmp    r0,#0                    @ successful chain?
9577     bxne   r0                       @ continue native execution
9578     b      toInterpreter            @ didn't chain - resume with interpreter
9579
9580 /*
9581  * Return from the translation cache to the interpreter to do method invocation.
9582  * Check if translation exists for the callee, but don't chain to it.
9583  */
9584     .global dvmJitToInterpNoChainNoProfile
9585 dvmJitToInterpNoChainNoProfile:
9586 #if defined(WITH_JIT_TUNING)
9587     bl     dvmBumpNoChain
9588 #endif
9589     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9590     mov    r0,rPC
9591     bl     dvmJitGetCodeAddr        @ Is there a translation?
9592     str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9593     mov    r1, rPC                  @ arg1 of translation may need this
9594     mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9595     cmp    r0,#0
9596     bxne   r0                       @ continue native execution if so
9597     EXPORT_PC()
9598     adrl   rIBASE, dvmAsmInstructionStart
9599     FETCH_INST()
9600     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9601     GOTO_OPCODE(ip)                     @ jump to next instruction
9602
9603 /*
9604  * Return from the translation cache to the interpreter to do method invocation.
9605  * Check if translation exists for the callee, but don't chain to it.
9606  */
9607     .global dvmJitToInterpNoChain
9608 dvmJitToInterpNoChain:
9609 #if defined(WITH_JIT_TUNING)
9610     bl     dvmBumpNoChain
9611 #endif
9612     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9613     mov    r0,rPC
9614     bl     dvmJitGetCodeAddr        @ Is there a translation?
9615     str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9616     mov    r1, rPC                  @ arg1 of translation may need this
9617     mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9618     cmp    r0,#0
9619     bxne   r0                       @ continue native execution if so
9620 #endif
9621
9622 /*
9623  * No translation, restore interpreter regs and start interpreting.
9624  * rGLUE & rFP were preserved in the translated code, and rPC has
9625  * already been restored by the time we get here.  We'll need to set
9626  * up rIBASE & rINST, and load the address of the JitTable into r0.
9627  */
9628 toInterpreter:
9629     EXPORT_PC()
9630     adrl   rIBASE, dvmAsmInstructionStart
9631     FETCH_INST()
9632     GET_JIT_PROF_TABLE(r0)
9633     @ NOTE: intended fallthrough
9634
9635 /*
9636  * Common code to update potential trace start counter, and initiate
9637  * a trace-build if appropriate.  On entry, rPC should point to the
9638  * next instruction to execute, and rINST should be already loaded with
9639  * the next opcode word, and r0 holds a pointer to the jit profile
9640  * table (pJitProfTable).
9641  */
9642 common_testUpdateProfile:
9643     cmp     r0,#0
9644     GET_INST_OPCODE(ip)
9645     GOTO_OPCODE_IFEQ(ip)       @ if not profiling, fallthrough otherwise */
9646
9647 common_updateProfile:
9648     eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
9649     lsl     r3,r3,#(32 - JIT_PROF_SIZE_LOG_2)          @ shift out excess bits
9650     ldrb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter
9651     GET_INST_OPCODE(ip)
9652     subs    r1,r1,#1           @ decrement counter
9653     strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it
9654     GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
9655
9656 /*
9657  * Here, we switch to the debug interpreter to request
9658  * trace selection.  First, though, check to see if there
9659  * is already a native translation in place (and, if so,
9660  * jump to it now).
9661  */
9662     GET_JIT_THRESHOLD(r1)
9663     ldr     r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
9664     strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter
9665     EXPORT_PC()
9666     mov     r0,rPC
9667     bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
9668     str     r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9669     mov     r1, rPC                     @ arg1 of translation may need this
9670     mov     lr, #0                      @  in case target is HANDLER_INTERPRET
9671     cmp     r0,#0
9672 #if !defined(WITH_SELF_VERIFICATION)
9673     bxne    r0                          @ jump to the translation
9674     mov     r2,#kJitTSelectRequest      @ ask for trace selection
9675     @ fall-through to common_selectTrace
9676 #else
9677     moveq   r2,#kJitTSelectRequest      @ ask for trace selection
9678     beq     common_selectTrace
9679     /*
9680      * At this point, we have a target translation.  However, if
9681      * that translation is actually the interpret-only pseudo-translation
9682      * we want to treat it the same as no translation.
9683      */
9684     mov     r10, r0                     @ save target
9685     bl      dvmCompilerGetInterpretTemplate
9686     cmp     r0, r10                     @ special case?
9687     bne     jitSVShadowRunStart         @ set up self verification shadow space
9688     @ Need to clear the inJitCodeCache flag
9689     ldr    r10, [rGLUE, #offGlue_self]  @ r10 <- glue->self
9690     mov    r3, #0                       @ 0 means not in the JIT code cache
9691     str    r3, [r10, #offThread_inJitCodeCache] @ back to the interp land
9692     GET_INST_OPCODE(ip)
9693     GOTO_OPCODE(ip)
9694     /* no return */
9695 #endif
9696
9697 /*
9698  * On entry:
9699  *  r2 is jit state, e.g. kJitTSelectRequest or kJitTSelectRequestHot
9700  */
9701 common_selectTrace:
9702     str     r2,[rGLUE,#offGlue_jitState]
9703     mov     r2,#kInterpEntryInstr       @ normal entry reason
9704     str     r2,[rGLUE,#offGlue_entryPoint]
9705     mov     r1,#1                       @ set changeInterp
9706     b       common_gotoBail
9707
9708 #if defined(WITH_SELF_VERIFICATION)
9709 /*
9710  * Save PC and registers to shadow memory for self verification mode
9711  * before jumping to native translation.
9712  * On entry:
9713  *    rPC, rFP, rGLUE: the values that they should contain
9714  *    r10: the address of the target translation.
9715  */
9716 jitSVShadowRunStart:
9717     mov     r0,rPC                      @ r0<- program counter
9718     mov     r1,rFP                      @ r1<- frame pointer
9719     mov     r2,rGLUE                    @ r2<- InterpState pointer
9720     mov     r3,r10                      @ r3<- target translation
9721     bl      dvmSelfVerificationSaveState @ save registers to shadow space
9722     ldr     rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
9723     add     rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
9724     bx      r10                         @ jump to the translation
9725
9726 /*
9727  * Restore PC, registers, and interpState to original values
9728  * before jumping back to the interpreter.
9729  */
9730 jitSVShadowRunEnd:
9731     mov    r1,rFP                        @ pass ending fp
9732     bl     dvmSelfVerificationRestoreState @ restore pc and fp values
9733     ldr    rPC,[r0,#offShadowSpace_startPC] @ restore PC
9734     ldr    rFP,[r0,#offShadowSpace_fp]   @ restore FP
9735     ldr    rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
9736     ldr    r1,[r0,#offShadowSpace_svState] @ get self verification state
9737     cmp    r1,#0                         @ check for punt condition
9738     beq    1f
9739     mov    r2,#kJitSelfVerification      @ ask for self verification
9740     str    r2,[rGLUE,#offGlue_jitState]
9741     mov    r2,#kInterpEntryInstr         @ normal entry reason
9742     str    r2,[rGLUE,#offGlue_entryPoint]
9743     mov    r1,#1                         @ set changeInterp
9744     b      common_gotoBail
9745
9746 1:                                       @ exit to interpreter without check
9747     EXPORT_PC()
9748     adrl   rIBASE, dvmAsmInstructionStart
9749     FETCH_INST()
9750     GET_INST_OPCODE(ip)
9751     GOTO_OPCODE(ip)
9752 #endif
9753
9754 #endif
9755
9756 /*
9757  * Common code when a backward branch is taken.
9758  *
9759  * TODO: we could avoid a branch by just setting r0 and falling through
9760  * into the common_periodicChecks code, and having a test on r0 at the
9761  * end determine if we should return to the caller or update & branch to
9762  * the next instr.
9763  *
9764  * On entry:
9765  *  r9 is PC adjustment *in bytes*
9766  */
9767 common_backwardBranch:
9768     mov     r0, #kInterpEntryInstr
9769     bl      common_periodicChecks
9770 #if defined(WITH_JIT)
9771     GET_JIT_PROF_TABLE(r0)
9772     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9773     cmp     r0,#0
9774     bne     common_updateProfile
9775     GET_INST_OPCODE(ip)
9776     GOTO_OPCODE(ip)
9777 #else
9778     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9779     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9780     GOTO_OPCODE(ip)                     @ jump to next instruction
9781 #endif
9782
9783
9784 /*
9785  * Need to see if the thread needs to be suspended or debugger/profiler
9786  * activity has begun.  If so, we suspend the thread or side-exit to
9787  * the debug interpreter as appropriate.
9788  *
9789  * The common case is no activity on any of these, so we want to figure
9790  * that out quickly.  If something is up, we can then sort out what.
9791  *
9792  * We want to be fast if the VM was built without debugger or profiler
9793  * support, but we also need to recognize that the system is usually
9794  * shipped with both of these enabled.
9795  *
9796  * TODO: reduce this so we're just checking a single location.
9797  *
9798  * On entry:
9799  *  r0 is reentry type, e.g. kInterpEntryInstr (for debugger/profiling)
9800  *  r9 is trampoline PC adjustment *in bytes*
9801  */
9802 common_periodicChecks:
9803     ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
9804
9805     ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9806     ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9807
9808     ldr     ip, [r3]                    @ ip<- suspendCount (int)
9809
9810     cmp     r1, #0                      @ debugger enabled?
9811 #if defined(WORKAROUND_CORTEX_A9_745320)
9812     /* Don't use conditional loads if the HW defect exists */
9813     beq     101f
9814     ldrb    r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
9815 101:
9816 #else
9817     ldrneb  r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
9818 #endif
9819     ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9820     orrnes  ip, ip, r1                  @ ip<- suspendCount | debuggerActive
9821     /*
9822      * Don't switch the interpreter in the libdvm_traceview build even if the
9823      * profiler is active.
9824      * The code here is opted for less intrusion instead of performance.
9825      * That is, *pActiveProfilers is still loaded into r2 even though it is not
9826      * used when WITH_INLINE_PROFILING is defined.
9827      */
9828 #if !defined(WITH_INLINE_PROFILING)
9829     orrs    ip, ip, r2                  @ ip<- suspend|debugger|profiler; set Z
9830 #endif
9831
9832
9833     bxeq    lr                          @ all zero, return
9834
9835     /*
9836      * One or more interesting events have happened.  Figure out what.
9837      *
9838      * If debugging or profiling are compiled in, we need to disambiguate.
9839      *
9840      * r0 still holds the reentry type.
9841      */
9842     ldr     ip, [r3]                    @ ip<- suspendCount (int)
9843     cmp     ip, #0                      @ want suspend?
9844     beq     1f                          @ no, must be debugger/profiler
9845
9846     stmfd   sp!, {r0, lr}               @ preserve r0 and lr
9847 #if defined(WITH_JIT)
9848     /*
9849      * Refresh the Jit's cached copy of profile table pointer.  This pointer
9850      * doubles as the Jit's on/off switch.
9851      */
9852     ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ r3<-&gDvmJit.pJitProfTable
9853     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9854     ldr     r3, [r3] @ r3 <- pJitProfTable
9855     EXPORT_PC()                         @ need for precise GC
9856     str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch
9857 #else
9858     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9859     EXPORT_PC()                         @ need for precise GC
9860 #endif
9861     bl      dvmCheckSuspendPending      @ do full check, suspend if necessary
9862     ldmfd   sp!, {r0, lr}               @ restore r0 and lr
9863
9864     /*
9865      * Reload the debugger/profiler enable flags.  We're checking to see
9866      * if either of these got set while we were suspended.
9867      *
9868      * If WITH_INLINE_PROFILING is configured, don't check whether the profiler
9869      * is enabled or not as the profiling will be done inline.
9870      */
9871     ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9872     cmp     r1, #0                      @ debugger enabled?
9873 #if defined(WORKAROUND_CORTEX_A9_745320)
9874     /* Don't use conditional loads if the HW defect exists */
9875     beq     101f
9876     ldrb    r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
9877 101:
9878 #else
9879     ldrneb  r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
9880 #endif
9881
9882 #if !defined(WITH_INLINE_PROFILING)
9883     ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9884     ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9885     orrs    r1, r1, r2
9886 #else
9887     cmp     r1, #0                      @ only consult the debuggerActive flag
9888 #endif
9889
9890     beq     2f
9891
9892 1:  @ debugger/profiler enabled, bail out; glue->entryPoint was set above
9893     str     r0, [rGLUE, #offGlue_entryPoint]    @ store r0, need for debug/prof
9894     add     rPC, rPC, r9                @ update rPC
9895     mov     r1, #1                      @ "want switch" = true
9896     b       common_gotoBail             @ side exit
9897
9898 2:
9899     bx      lr                          @ nothing to do, return
9900
9901
9902 /*
9903  * The equivalent of "goto bail", this calls through the "bail handler".
9904  *
9905  * State registers will be saved to the "glue" area before bailing.
9906  *
9907  * On entry:
9908  *  r1 is "bool changeInterp", indicating if we want to switch to the
9909  *     other interpreter or just bail all the way out
9910  */
9911 common_gotoBail:
9912     SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9913     mov     r0, rGLUE                   @ r0<- glue ptr
9914     b       dvmMterpStdBail             @ call(glue, changeInterp)
9915
9916     @add     r1, r1, #1                  @ using (boolean+1)
9917     @add     r0, rGLUE, #offGlue_jmpBuf  @ r0<- &glue->jmpBuf
9918     @bl      _longjmp                    @ does not return
9919     @bl      common_abort
9920
9921
9922 /*
9923  * Common code for method invocation with range.
9924  *
9925  * On entry:
9926  *  r0 is "Method* methodToCall", the method we're trying to call
9927  */
9928 common_invokeMethodRange:
9929 .LinvokeNewRange:
9930     @ prepare to copy args to "outs" area of current frame
9931     movs    r2, rINST, lsr #8           @ r2<- AA (arg count) -- test for zero
9932     SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9933     beq     .LinvokeArgsDone            @ if no args, skip the rest
9934     FETCH(r1, 2)                        @ r1<- CCCC
9935
9936     @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
9937     @ (very few methods have > 10 args; could unroll for common cases)
9938     add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
9939     sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
9940     ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
9941 1:  ldr     r1, [r3], #4                @ val = *fp++
9942     subs    r2, r2, #1                  @ count--
9943     str     r1, [r10], #4               @ *outs++ = val
9944     bne     1b                          @ ...while count != 0
9945     ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
9946     b       .LinvokeArgsDone
9947
9948 /*
9949  * Common code for method invocation without range.
9950  *
9951  * On entry:
9952  *  r0 is "Method* methodToCall", the method we're trying to call
9953  */
9954 common_invokeMethodNoRange:
9955 .LinvokeNewNoRange:
9956     @ prepare to copy args to "outs" area of current frame
9957     movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
9958     SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9959     FETCH(r1, 2)                        @ r1<- GFED (load here to hide latency)
9960     ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
9961     ldrh    r3, [r0, #offMethod_outsSize]  @ r3<- methodToCall->outsSize
9962     beq     .LinvokeArgsDone
9963
9964     @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
9965 .LinvokeNonRange:
9966     rsb     r2, r2, #5                  @ r2<- 5-r2
9967     add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
9968     bl      common_abort                @ (skipped due to ARM prefetch)
9969 5:  and     ip, rINST, #0x0f00          @ isolate A
9970     ldr     r2, [rFP, ip, lsr #6]       @ r2<- vA (shift right 8, left 2)
9971     mov     r0, r0                      @ nop
9972     str     r2, [r10, #-4]!             @ *--outs = vA
9973 4:  and     ip, r1, #0xf000             @ isolate G
9974     ldr     r2, [rFP, ip, lsr #10]      @ r2<- vG (shift right 12, left 2)
9975     mov     r0, r0                      @ nop
9976     str     r2, [r10, #-4]!             @ *--outs = vG
9977 3:  and     ip, r1, #0x0f00             @ isolate F
9978     ldr     r2, [rFP, ip, lsr #6]       @ r2<- vF
9979     mov     r0, r0                      @ nop
9980     str     r2, [r10, #-4]!             @ *--outs = vF
9981 2:  and     ip, r1, #0x00f0             @ isolate E
9982     ldr     r2, [rFP, ip, lsr #2]       @ r2<- vE
9983     mov     r0, r0                      @ nop
9984     str     r2, [r10, #-4]!             @ *--outs = vE
9985 1:  and     ip, r1, #0x000f             @ isolate D
9986     ldr     r2, [rFP, ip, lsl #2]       @ r2<- vD
9987     mov     r0, r0                      @ nop
9988     str     r2, [r10, #-4]!             @ *--outs = vD
9989 0:  @ fall through to .LinvokeArgsDone
9990
9991 .LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
9992     ldr     r2, [r0, #offMethod_insns]  @ r2<- method->insns
9993     ldr     rINST, [r0, #offMethod_clazz]  @ rINST<- method->clazz
9994     @ find space for the new stack frame, check for overflow
9995     SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
9996     sub     r1, r1, r9, lsl #2          @ r1<- newFp (old savearea - regsSize)
9997     SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
9998 @    bl      common_dumpRegs
9999     ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
10000     sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
10001     cmp     r3, r9                      @ bottom < interpStackEnd?
10002     ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
10003     blo     .LstackOverflow             @ yes, this frame will overflow stack
10004
10005     @ set up newSaveArea
10006 #ifdef EASY_GDB
10007     SAVEAREA_FROM_FP(ip, rFP)           @ ip<- stack save area
10008     str     ip, [r10, #offStackSaveArea_prevSave]
10009 #endif
10010     str     rFP, [r10, #offStackSaveArea_prevFrame]
10011     str     rPC, [r10, #offStackSaveArea_savedPc]
10012 #if defined(WITH_JIT)
10013     mov     r9, #0
10014     str     r9, [r10, #offStackSaveArea_returnAddr]
10015 #endif
10016 #if defined(WITH_INLINE_PROFILING)
10017     stmfd   sp!, {r0-r3}                @ preserve r0-r3
10018     mov     r1, r6
10019     @ r0=methodToCall, r1=rGlue
10020     bl      dvmFastMethodTraceEnter
10021     ldmfd   sp!, {r0-r3}                @ restore r0-r3
10022 #endif
10023     str     r0, [r10, #offStackSaveArea_method]
10024     tst     r3, #ACC_NATIVE
10025     bne     .LinvokeNative
10026
10027     /*
10028     stmfd   sp!, {r0-r3}
10029     bl      common_printNewline
10030     mov     r0, rFP
10031     mov     r1, #0
10032     bl      dvmDumpFp
10033     ldmfd   sp!, {r0-r3}
10034     stmfd   sp!, {r0-r3}
10035     mov     r0, r1
10036     mov     r1, r10
10037     bl      dvmDumpFp
10038     bl      common_printNewline
10039     ldmfd   sp!, {r0-r3}
10040     */
10041
10042     ldrh    r9, [r2]                        @ r9 <- load INST from new PC
10043     ldr     r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
10044     mov     rPC, r2                         @ publish new rPC
10045     ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
10046
10047     @ Update "glue" values for the new method
10048     @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
10049     str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
10050     str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
10051 #if defined(WITH_JIT)
10052     GET_JIT_PROF_TABLE(r0)
10053     mov     rFP, r1                         @ fp = newFp
10054     GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
10055     mov     rINST, r9                       @ publish new rINST
10056     str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
10057     cmp     r0,#0
10058     bne     common_updateProfile
10059     GOTO_OPCODE(ip)                         @ jump to next instruction
10060 #else
10061     mov     rFP, r1                         @ fp = newFp
10062     GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
10063     mov     rINST, r9                       @ publish new rINST
10064     str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
10065     GOTO_OPCODE(ip)                         @ jump to next instruction
10066 #endif
10067
10068 .LinvokeNative:
10069     @ Prep for the native call
10070     @ r0=methodToCall, r1=newFp, r10=newSaveArea
10071     ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
10072     ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
10073     str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
10074     str     r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
10075     mov     r9, r3                      @ r9<- glue->self (preserve)
10076
10077     mov     r2, r0                      @ r2<- methodToCall
10078     mov     r0, r1                      @ r0<- newFp (points to args)
10079     add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
10080
10081 #ifdef ASSIST_DEBUGGER
10082     /* insert fake function header to help gdb find the stack frame */
10083     b       .Lskip
10084     .type   dalvik_mterp, %function
10085 dalvik_mterp:
10086     .fnstart
10087     MTERP_ENTRY1
10088     MTERP_ENTRY2
10089 .Lskip:
10090 #endif
10091
10092 #if defined(WITH_INLINE_PROFILING)
10093     @ r2=JNIMethod, r6=rGLUE
10094     stmfd   sp!, {r2,r6}
10095 #endif
10096
10097     mov     lr, pc                      @ set return addr
10098     ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
10099
10100 #if defined(WITH_INLINE_PROFILING)
10101     @ r0=JNIMethod, r1=rGLUE
10102     ldmfd   sp!, {r0-r1}
10103     bl      dvmFastNativeMethodTraceExit
10104 #endif
10105
10106 #if defined(WITH_JIT)
10107     ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status
10108 #endif
10109
10110     @ native return; r9=self, r10=newSaveArea
10111     @ equivalent to dvmPopJniLocals
10112     ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
10113     ldr     r1, [r9, #offThread_exception] @ check for exception
10114 #if defined(WITH_JIT)
10115     ldr     r3, [r3]                    @ r3 <- gDvmJit.pProfTable
10116 #endif
10117     str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
10118     cmp     r1, #0                      @ null?
10119     str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
10120 #if defined(WITH_JIT)
10121     str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch
10122 #endif
10123     bne     common_exceptionThrown      @ no, handle exception
10124
10125     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
10126     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10127     GOTO_OPCODE(ip)                     @ jump to next instruction
10128
10129 .LstackOverflow:    @ r0=methodToCall
10130     mov     r1, r0                      @ r1<- methodToCall
10131     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
10132     bl      dvmHandleStackOverflow
10133     b       common_exceptionThrown
10134 #ifdef ASSIST_DEBUGGER
10135     .fnend
10136 #endif
10137
10138
10139     /*
10140      * Common code for method invocation, calling through "glue code".
10141      *
10142      * TODO: now that we have range and non-range invoke handlers, this
10143      *       needs to be split into two.  Maybe just create entry points
10144      *       that set r9 and jump here?
10145      *
10146      * On entry:
10147      *  r0 is "Method* methodToCall", the method we're trying to call
10148      *  r9 is "bool methodCallRange", indicating if this is a /range variant
10149      */
10150      .if    0
10151 .LinvokeOld:
10152     sub     sp, sp, #8                  @ space for args + pad
10153     FETCH(ip, 2)                        @ ip<- FEDC or CCCC
10154     mov     r2, r0                      @ A2<- methodToCall
10155     mov     r0, rGLUE                   @ A0<- glue
10156     SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
10157     mov     r1, r9                      @ A1<- methodCallRange
10158     mov     r3, rINST, lsr #8           @ A3<- AA
10159     str     ip, [sp, #0]                @ A4<- ip
10160     bl      dvmMterp_invokeMethod       @ call the C invokeMethod
10161     add     sp, sp, #8                  @ remove arg area
10162     b       common_resumeAfterGlueCall  @ continue to next instruction
10163     .endif
10164
10165
10166
10167 /*
10168  * Common code for handling a return instruction.
10169  *
10170  * This does not return.
10171  */
10172 common_returnFromMethod:
10173 .LreturnNew:
10174     mov     r0, #kInterpEntryReturn
10175     mov     r9, #0
10176     bl      common_periodicChecks
10177
10178 #if defined(WITH_INLINE_PROFILING)
10179     stmfd   sp!, {r0-r3}                @ preserve r0-r3
10180     mov     r0, r6
10181     @ r0=rGlue
10182     bl      dvmFastJavaMethodTraceExit
10183     ldmfd   sp!, {r0-r3}                @ restore r0-r3
10184 #endif
10185     SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
10186     ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
10187     ldr     r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
10188     ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
10189                                         @ r2<- method we're returning to
10190     ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
10191     cmp     r2, #0                      @ is this a break frame?
10192 #if defined(WORKAROUND_CORTEX_A9_745320)
10193     /* Don't use conditional loads if the HW defect exists */
10194     beq     101f
10195     ldr     r10, [r2, #offMethod_clazz] @ r10<- method->clazz
10196 101:
10197 #else
10198     ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
10199 #endif
10200     mov     r1, #0                      @ "want switch" = false
10201     beq     common_gotoBail             @ break frame, bail out completely
10202
10203     PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
10204     str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
10205     ldr     r1, [r10, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
10206     str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
10207 #if defined(WITH_JIT)
10208     ldr     r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr
10209     mov     rPC, r9                     @ publish new rPC
10210     str     r1, [rGLUE, #offGlue_methodClassDex]
10211     str     r10, [r3, #offThread_inJitCodeCache]  @ may return to JIT'ed land
10212     cmp     r10, #0                      @ caller is compiled code
10213     blxne   r10
10214     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10215     GOTO_OPCODE(ip)                     @ jump to next instruction
10216 #else
10217     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10218     mov     rPC, r9                     @ publish new rPC
10219     str     r1, [rGLUE, #offGlue_methodClassDex]
10220     GOTO_OPCODE(ip)                     @ jump to next instruction
10221 #endif
10222
10223     /*
10224      * Return handling, calls through "glue code".
10225      */
10226      .if    0
10227 .LreturnOld:
10228     SAVE_PC_FP_TO_GLUE()                @ export state
10229     mov     r0, rGLUE                   @ arg to function
10230     bl      dvmMterp_returnFromMethod
10231     b       common_resumeAfterGlueCall
10232     .endif
10233
10234
10235 /*
10236  * Somebody has thrown an exception.  Handle it.
10237  *
10238  * If the exception processing code returns to us (instead of falling
10239  * out of the interpreter), continue with whatever the next instruction
10240  * now happens to be.
10241  *
10242  * This does not return.
10243  */
10244      .global dvmMterpCommonExceptionThrown
10245 dvmMterpCommonExceptionThrown:
10246 common_exceptionThrown:
10247 .LexceptionNew:
10248     mov     r0, #kInterpEntryThrow
10249     mov     r9, #0
10250     bl      common_periodicChecks
10251
10252     ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
10253     ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
10254     mov     r1, r10                     @ r1<- self
10255     mov     r0, r9                      @ r0<- exception
10256     bl      dvmAddTrackedAlloc          @ don't let the exception be GCed
10257     mov     r3, #0                      @ r3<- NULL
10258     str     r3, [r10, #offThread_exception] @ self->exception = NULL
10259
10260     /* set up args and a local for "&fp" */
10261     /* (str sp, [sp, #-4]!  would be perfect here, but is discouraged) */
10262     str     rFP, [sp, #-4]!             @ *--sp = fp
10263     mov     ip, sp                      @ ip<- &fp
10264     mov     r3, #0                      @ r3<- false
10265     str     ip, [sp, #-4]!              @ *--sp = &fp
10266     ldr     r1, [rGLUE, #offGlue_method] @ r1<- glue->method
10267     mov     r0, r10                     @ r0<- self
10268     ldr     r1, [r1, #offMethod_insns]  @ r1<- method->insns
10269     mov     r2, r9                      @ r2<- exception
10270     sub     r1, rPC, r1                 @ r1<- pc - method->insns
10271     mov     r1, r1, asr #1              @ r1<- offset in code units
10272
10273     /* call, r0 gets catchRelPc (a code-unit offset) */
10274     bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
10275
10276     /* fix earlier stack overflow if necessary; may trash rFP */
10277     ldrb    r1, [r10, #offThread_stackOverflowed]
10278     cmp     r1, #0                      @ did we overflow earlier?
10279     beq     1f                          @ no, skip ahead
10280     mov     rFP, r0                     @ save relPc result in rFP
10281     mov     r0, r10                     @ r0<- self
10282     mov     r1, r9                      @ r1<- exception
10283     bl      dvmCleanupStackOverflow     @ call(self)
10284     mov     r0, rFP                     @ restore result
10285 1:
10286
10287     /* update frame pointer and check result from dvmFindCatchBlock */
10288     ldr     rFP, [sp, #4]               @ retrieve the updated rFP
10289     cmp     r0, #0                      @ is catchRelPc < 0?
10290     add     sp, sp, #8                  @ restore stack
10291     bmi     .LnotCaughtLocally
10292
10293     /* adjust locals to match self->curFrame and updated PC */
10294     SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
10295     ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
10296     str     r1, [rGLUE, #offGlue_method]    @ glue->method = new method
10297     ldr     r2, [r1, #offMethod_clazz]      @ r2<- method->clazz
10298     ldr     r3, [r1, #offMethod_insns]      @ r3<- method->insns
10299     ldr     r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
10300     add     rPC, r3, r0, asl #1             @ rPC<- method->insns + catchRelPc
10301     str     r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
10302
10303     /* release the tracked alloc on the exception */
10304     mov     r0, r9                      @ r0<- exception
10305     mov     r1, r10                     @ r1<- self
10306     bl      dvmReleaseTrackedAlloc      @ release the exception
10307
10308     /* restore the exception if the handler wants it */
10309     FETCH_INST()                        @ load rINST from rPC
10310     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10311     cmp     ip, #OP_MOVE_EXCEPTION      @ is it "move-exception"?
10312     streq   r9, [r10, #offThread_exception] @ yes, restore the exception
10313     GOTO_OPCODE(ip)                     @ jump to next instruction
10314
10315 .LnotCaughtLocally: @ r9=exception, r10=self
10316     /* fix stack overflow if necessary */
10317     ldrb    r1, [r10, #offThread_stackOverflowed]
10318     cmp     r1, #0                      @ did we overflow earlier?
10319     movne   r0, r10                     @ if yes: r0<- self
10320     movne   r1, r9                      @ if yes: r1<- exception
10321     blne    dvmCleanupStackOverflow     @ if yes: call(self)
10322
10323     @ may want to show "not caught locally" debug messages here
10324 #if DVM_SHOW_EXCEPTION >= 2
10325     /* call __android_log_print(prio, tag, format, ...) */
10326     /* "Exception %s from %s:%d not caught locally" */
10327     @ dvmLineNumFromPC(method, pc - method->insns)
10328     ldr     r0, [rGLUE, #offGlue_method]
10329     ldr     r1, [r0, #offMethod_insns]
10330     sub     r1, rPC, r1
10331     asr     r1, r1, #1
10332     bl      dvmLineNumFromPC
10333     str     r0, [sp, #-4]!
10334     @ dvmGetMethodSourceFile(method)
10335     ldr     r0, [rGLUE, #offGlue_method]
10336     bl      dvmGetMethodSourceFile
10337     str     r0, [sp, #-4]!
10338     @ exception->clazz->descriptor
10339     ldr     r3, [r9, #offObject_clazz]
10340     ldr     r3, [r3, #offClassObject_descriptor]
10341     @
10342     ldr     r2, strExceptionNotCaughtLocally
10343     ldr     r1, strLogTag
10344     mov     r0, #3                      @ LOG_DEBUG
10345     bl      __android_log_print
10346 #endif
10347     str     r9, [r10, #offThread_exception] @ restore exception
10348     mov     r0, r9                      @ r0<- exception
10349     mov     r1, r10                     @ r1<- self
10350     bl      dvmReleaseTrackedAlloc      @ release the exception
10351     mov     r1, #0                      @ "want switch" = false
10352     b       common_gotoBail             @ bail out
10353
10354
10355     /*
10356      * Exception handling, calls through "glue code".
10357      */
10358     .if     0
10359 .LexceptionOld:
10360     SAVE_PC_FP_TO_GLUE()                @ export state
10361     mov     r0, rGLUE                   @ arg to function
10362     bl      dvmMterp_exceptionThrown
10363     b       common_resumeAfterGlueCall
10364     .endif
10365
10366
10367 /*
10368  * After returning from a "glued" function, pull out the updated
10369  * values and start executing at the next instruction.
10370  */
10371 common_resumeAfterGlueCall:
10372     LOAD_PC_FP_FROM_GLUE()              @ pull rPC and rFP out of glue
10373     FETCH_INST()                        @ load rINST from rPC
10374     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10375     GOTO_OPCODE(ip)                     @ jump to next instruction
10376
10377 /*
10378  * Invalid array index. Note that our calling convention is strange; we use r1
10379  * and r3 because those just happen to be the registers all our callers are
10380  * using. We shuffle them here before calling the C function.
10381  * r1: index
10382  * r3: size
10383  */
10384 common_errArrayIndex:
10385     EXPORT_PC()
10386     mov     r0, r1
10387     mov     r1, r3
10388     bl      dvmThrowAIOOBE
10389     b       common_exceptionThrown
10390
10391 /*
10392  * Integer divide or mod by zero.
10393  */
10394 common_errDivideByZero:
10395     EXPORT_PC()
10396     ldr     r0, strArithmeticException
10397     ldr     r1, strDivideByZero
10398     bl      dvmThrowException
10399     b       common_exceptionThrown
10400
10401 /*
10402  * Attempt to allocate an array with a negative size.
10403  */
10404 common_errNegativeArraySize:
10405     EXPORT_PC()
10406     ldr     r0, strNegativeArraySizeException
10407     mov     r1, #0
10408     bl      dvmThrowException
10409     b       common_exceptionThrown
10410
10411 /*
10412  * Invocation of a non-existent method.
10413  */
10414 common_errNoSuchMethod:
10415     EXPORT_PC()
10416     ldr     r0, strNoSuchMethodError
10417     mov     r1, #0
10418     bl      dvmThrowException
10419     b       common_exceptionThrown
10420
10421 /*
10422  * We encountered a null object when we weren't expecting one.  We
10423  * export the PC, throw a NullPointerException, and goto the exception
10424  * processing code.
10425  */
10426 common_errNullObject:
10427     EXPORT_PC()
10428     ldr     r0, strNullPointerException
10429     mov     r1, #0
10430     bl      dvmThrowException
10431     b       common_exceptionThrown
10432
10433 /*
10434  * For debugging, cause an immediate fault.  The source address will
10435  * be in lr (use a bl instruction to jump here).
10436  */
10437 common_abort:
10438     ldr     pc, .LdeadFood
10439 .LdeadFood:
10440     .word   0xdeadf00d
10441
10442 /*
10443  * Spit out a "we were here", preserving all registers.  (The attempt
10444  * to save ip won't work, but we need to save an even number of
10445  * registers for EABI 64-bit stack alignment.)
10446  */
10447     .macro  SQUEAK num
10448 common_squeak\num:
10449     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10450     ldr     r0, strSqueak
10451     mov     r1, #\num
10452     bl      printf
10453     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10454     bx      lr
10455     .endm
10456
10457     SQUEAK  0
10458     SQUEAK  1
10459     SQUEAK  2
10460     SQUEAK  3
10461     SQUEAK  4
10462     SQUEAK  5
10463
10464 /*
10465  * Spit out the number in r0, preserving registers.
10466  */
10467 common_printNum:
10468     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10469     mov     r1, r0
10470     ldr     r0, strSqueak
10471     bl      printf
10472     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10473     bx      lr
10474
10475 /*
10476  * Print a newline, preserving registers.
10477  */
10478 common_printNewline:
10479     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10480     ldr     r0, strNewline
10481     bl      printf
10482     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10483     bx      lr
10484
10485     /*
10486      * Print the 32-bit quantity in r0 as a hex value, preserving registers.
10487      */
10488 common_printHex:
10489     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10490     mov     r1, r0
10491     ldr     r0, strPrintHex
10492     bl      printf
10493     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10494     bx      lr
10495
10496 /*
10497  * Print the 64-bit quantity in r0-r1, preserving registers.
10498  */
10499 common_printLong:
10500     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10501     mov     r3, r1
10502     mov     r2, r0
10503     ldr     r0, strPrintLong
10504     bl      printf
10505     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10506     bx      lr
10507
10508 /*
10509  * Print full method info.  Pass the Method* in r0.  Preserves regs.
10510  */
10511 common_printMethod:
10512     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10513     bl      dvmMterpPrintMethod
10514     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10515     bx      lr
10516
10517 /*
10518  * Call a C helper function that dumps regs and possibly some
10519  * additional info.  Requires the C function to be compiled in.
10520  */
10521     .if     0
10522 common_dumpRegs:
10523     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10524     bl      dvmMterpDumpArmRegs
10525     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10526     bx      lr
10527     .endif
10528
10529 #if 0
10530 /*
10531  * Experiment on VFP mode.
10532  *
10533  * uint32_t setFPSCR(uint32_t val, uint32_t mask)
10534  *
10535  * Updates the bits specified by "mask", setting them to the values in "val".
10536  */
10537 setFPSCR:
10538     and     r0, r0, r1                  @ make sure no stray bits are set
10539     fmrx    r2, fpscr                   @ get VFP reg
10540     mvn     r1, r1                      @ bit-invert mask
10541     and     r2, r2, r1                  @ clear masked bits
10542     orr     r2, r2, r0                  @ set specified bits
10543     fmxr    fpscr, r2                   @ set VFP reg
10544     mov     r0, r2                      @ return new value
10545     bx      lr
10546
10547     .align  2
10548     .global dvmConfigureFP
10549     .type   dvmConfigureFP, %function
10550 dvmConfigureFP:
10551     stmfd   sp!, {ip, lr}
10552     /* 0x03000000 sets DN/FZ */
10553     /* 0x00009f00 clears the six exception enable flags */
10554     bl      common_squeak0
10555     mov     r0, #0x03000000             @ r0<- 0x03000000
10556     add     r1, r0, #0x9f00             @ r1<- 0x03009f00
10557     bl      setFPSCR
10558     ldmfd   sp!, {ip, pc}
10559 #endif
10560
10561
10562 /*
10563  * String references, must be close to the code that uses them.
10564  */
10565     .align  2
10566 strArithmeticException:
10567     .word   .LstrArithmeticException
10568 strDivideByZero:
10569     .word   .LstrDivideByZero
10570 strNegativeArraySizeException:
10571     .word   .LstrNegativeArraySizeException
10572 strNoSuchMethodError:
10573     .word   .LstrNoSuchMethodError
10574 strNullPointerException:
10575     .word   .LstrNullPointerException
10576
10577 strLogTag:
10578     .word   .LstrLogTag
10579 strExceptionNotCaughtLocally:
10580     .word   .LstrExceptionNotCaughtLocally
10581
10582 strNewline:
10583     .word   .LstrNewline
10584 strSqueak:
10585     .word   .LstrSqueak
10586 strPrintHex:
10587     .word   .LstrPrintHex
10588 strPrintLong:
10589     .word   .LstrPrintLong
10590
10591 /*
10592  * Zero-terminated ASCII string data.
10593  *
10594  * On ARM we have two choices: do like gcc does, and LDR from a .word
10595  * with the address, or use an ADR pseudo-op to get the address
10596  * directly.  ADR saves 4 bytes and an indirection, but it's using a
10597  * PC-relative addressing mode and hence has a limited range, which
10598  * makes it not work well with mergeable string sections.
10599  */
10600     .section .rodata.str1.4,"aMS",%progbits,1
10601
10602 .LstrBadEntryPoint:
10603     .asciz  "Bad entry point %d\n"
10604 .LstrArithmeticException:
10605     .asciz  "Ljava/lang/ArithmeticException;"
10606 .LstrDivideByZero:
10607     .asciz  "divide by zero"
10608 .LstrFilledNewArrayNotImpl:
10609     .asciz  "filled-new-array only implemented for objects and 'int'"
10610 .LstrInternalError:
10611     .asciz  "Ljava/lang/InternalError;"
10612 .LstrInstantiationError:
10613     .asciz  "Ljava/lang/InstantiationError;"
10614 .LstrNegativeArraySizeException:
10615     .asciz  "Ljava/lang/NegativeArraySizeException;"
10616 .LstrNoSuchMethodError:
10617     .asciz  "Ljava/lang/NoSuchMethodError;"
10618 .LstrNullPointerException:
10619     .asciz  "Ljava/lang/NullPointerException;"
10620
10621 .LstrLogTag:
10622     .asciz  "mterp"
10623 .LstrExceptionNotCaughtLocally:
10624     .asciz  "Exception %s from %s:%d not caught locally\n"
10625
10626 .LstrNewline:
10627     .asciz  "\n"
10628 .LstrSqueak:
10629     .asciz  "<%d>"
10630 .LstrPrintHex:
10631     .asciz  "<0x%x>"
10632 .LstrPrintLong:
10633     .asciz  "<%lld>"
10634