OSDN Git Service

3c896ae98a29fbfff84fb6e0972caf7f3e0c13da
[android-x86/dalvik.git] / vm / mterp / out / InterpAsm-armv7-a.S
1 /*
2  * This file was generated automatically by gen-mterp.py for 'armv7-a'.
3  *
4  * --> DO NOT EDIT <--
5  */
6
7 /* File: armv5te/header.S */
8 /*
9  * Copyright (C) 2008 The Android Open Source Project
10  *
11  * Licensed under the Apache License, Version 2.0 (the "License");
12  * you may not use this file except in compliance with the License.
13  * You may obtain a copy of the License at
14  *
15  *      http://www.apache.org/licenses/LICENSE-2.0
16  *
17  * Unless required by applicable law or agreed to in writing, software
18  * distributed under the License is distributed on an "AS IS" BASIS,
19  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  * See the License for the specific language governing permissions and
21  * limitations under the License.
22  */
23 /*
24  * ARMv5 definitions and declarations.
25  */
26
27 /*
28 ARM EABI general notes:
29
30 r0-r3 hold first 4 args to a method; they are not preserved across method calls
31 r4-r8 are available for general use
32 r9 is given special treatment in some situations, but not for us
33 r10 (sl) seems to be generally available
34 r11 (fp) is used by gcc (unless -fomit-frame-pointer is set)
35 r12 (ip) is scratch -- not preserved across method calls
36 r13 (sp) should be managed carefully in case a signal arrives
37 r14 (lr) must be preserved
38 r15 (pc) can be tinkered with directly
39
40 r0 holds returns of <= 4 bytes
41 r0-r1 hold returns of 8 bytes, low word in r0
42
43 Callee must save/restore r4+ (except r12) if it modifies them.  If VFP
44 is present, registers s16-s31 (a/k/a d8-d15, a/k/a q4-q7) must be preserved,
45 s0-s15 (d0-d7, q0-a3) do not need to be.
46
47 Stack is "full descending".  Only the arguments that don't fit in the first 4
48 registers are placed on the stack.  "sp" points at the first stacked argument
49 (i.e. the 5th arg).
50
51 VFP: single-precision results in s0, double-precision results in d0.
52
53 In the EABI, "sp" must be 64-bit aligned on entry to a function, and any
54 64-bit quantities (long long, double) must be 64-bit aligned.
55 */
56
57 /*
58 Mterp and ARM notes:
59
60 The following registers have fixed assignments:
61
62   reg nick      purpose
63   r4  rPC       interpreted program counter, used for fetching instructions
64   r5  rFP       interpreted frame pointer, used for accessing locals and args
65   r6  rGLUE     MterpGlue pointer
66   r7  rINST     first 16-bit code unit of current instruction
67   r8  rIBASE    interpreted instruction base pointer, used for computed goto
68
69 Macros are provided for common operations.  Each macro MUST emit only
70 one instruction to make instruction-counting easier.  They MUST NOT alter
71 unspecified registers or condition codes.
72 */
73
74 /* single-purpose registers, given names for clarity */
75 #define rPC     r4
76 #define rFP     r5
77 #define rGLUE   r6
78 #define rINST   r7
79 #define rIBASE  r8
80
81 /* save/restore the PC and/or FP from the glue struct */
82 #define LOAD_PC_FROM_GLUE()     ldr     rPC, [rGLUE, #offGlue_pc]
83 #define SAVE_PC_TO_GLUE()       str     rPC, [rGLUE, #offGlue_pc]
84 #define LOAD_FP_FROM_GLUE()     ldr     rFP, [rGLUE, #offGlue_fp]
85 #define SAVE_FP_TO_GLUE()       str     rFP, [rGLUE, #offGlue_fp]
86 #define LOAD_PC_FP_FROM_GLUE()  ldmia   rGLUE, {rPC, rFP}
87 #define SAVE_PC_FP_TO_GLUE()    stmia   rGLUE, {rPC, rFP}
88
89 /*
90  * "export" the PC to the stack frame, f/b/o future exception objects.  Must
91  * be done *before* something calls dvmThrowException.
92  *
93  * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e.
94  * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc)
95  *
96  * It's okay to do this more than once.
97  */
98 #define EXPORT_PC() \
99     str     rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)]
100
101 /*
102  * Given a frame pointer, find the stack save area.
103  *
104  * In C this is "((StackSaveArea*)(_fp) -1)".
105  */
106 #define SAVEAREA_FROM_FP(_reg, _fpreg) \
107     sub     _reg, _fpreg, #sizeofStackSaveArea
108
109 /*
110  * Fetch the next instruction from rPC into rINST.  Does not advance rPC.
111  */
112 #define FETCH_INST()            ldrh    rINST, [rPC]
113
114 /*
115  * Fetch the next instruction from the specified offset.  Advances rPC
116  * to point to the next instruction.  "_count" is in 16-bit code units.
117  *
118  * Because of the limited size of immediate constants on ARM, this is only
119  * suitable for small forward movements (i.e. don't try to implement "goto"
120  * with this).
121  *
122  * This must come AFTER anything that can throw an exception, or the
123  * exception catch may miss.  (This also implies that it must come after
124  * EXPORT_PC().)
125  */
126 #define FETCH_ADVANCE_INST(_count) ldrh    rINST, [rPC, #(_count*2)]!
127
128 /*
129  * The operation performed here is similar to FETCH_ADVANCE_INST, except the
130  * src and dest registers are parameterized (not hard-wired to rPC and rINST).
131  */
132 #define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \
133         ldrh    _dreg, [_sreg, #(_count*2)]!
134
135 /*
136  * Fetch the next instruction from an offset specified by _reg.  Updates
137  * rPC to point to the next instruction.  "_reg" must specify the distance
138  * in bytes, *not* 16-bit code units, and may be a signed value.
139  *
140  * We want to write "ldrh rINST, [rPC, _reg, lsl #2]!", but some of the
141  * bits that hold the shift distance are used for the half/byte/sign flags.
142  * In some cases we can pre-double _reg for free, so we require a byte offset
143  * here.
144  */
145 #define FETCH_ADVANCE_INST_RB(_reg) ldrh    rINST, [rPC, _reg]!
146
147 /*
148  * Fetch a half-word code unit from an offset past the current PC.  The
149  * "_count" value is in 16-bit code units.  Does not advance rPC.
150  *
151  * The "_S" variant works the same but treats the value as signed.
152  */
153 #define FETCH(_reg, _count)     ldrh    _reg, [rPC, #(_count*2)]
154 #define FETCH_S(_reg, _count)   ldrsh   _reg, [rPC, #(_count*2)]
155
156 /*
157  * Fetch one byte from an offset past the current PC.  Pass in the same
158  * "_count" as you would for FETCH, and an additional 0/1 indicating which
159  * byte of the halfword you want (lo/hi).
160  */
161 #define FETCH_B(_reg, _count, _byte) ldrb     _reg, [rPC, #(_count*2+_byte)]
162
163 /*
164  * Put the instruction's opcode field into the specified register.
165  */
166 #define GET_INST_OPCODE(_reg)   and     _reg, rINST, #255
167
168 /*
169  * Put the prefetched instruction's opcode field into the specified register.
170  */
171 #define GET_PREFETCHED_OPCODE(_oreg, _ireg)   and     _oreg, _ireg, #255
172
173 /*
174  * Begin executing the opcode in _reg.  Because this only jumps within the
175  * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork.
176  */
177 #define GOTO_OPCODE(_reg)       add     pc, rIBASE, _reg, lsl #6
178 #define GOTO_OPCODE_IFEQ(_reg)  addeq   pc, rIBASE, _reg, lsl #6
179 #define GOTO_OPCODE_IFNE(_reg)  addne   pc, rIBASE, _reg, lsl #6
180
181 /*
182  * Get/set the 32-bit value from a Dalvik register.
183  */
184 #define GET_VREG(_reg, _vreg)   ldr     _reg, [rFP, _vreg, lsl #2]
185 #define SET_VREG(_reg, _vreg)   str     _reg, [rFP, _vreg, lsl #2]
186
187 #if defined(WITH_JIT)
188 #define GET_JIT_ENABLED(_reg)       ldr     _reg,[rGLUE,#offGlue_jitEnabled]
189 #define GET_JIT_PROF_TABLE(_reg)    ldr     _reg,[rGLUE,#offGlue_pJitProfTable]
190 #endif
191
192 /*
193  * Convert a virtual register index into an address.
194  */
195 #define VREG_INDEX_TO_ADDR(_reg, _vreg) \
196         add     _reg, rFP, _vreg, lsl #2
197
198 /*
199  * This is a #include, not a %include, because we want the C pre-processor
200  * to expand the macros into assembler assignment statements.
201  */
202 #include "../common/asm-constants.h"
203
204
205 /* File: armv5te/platform.S */
206 /*
207  * ===========================================================================
208  *  CPU-version-specific defines
209  * ===========================================================================
210  */
211
212 /*
213  * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5.  Essentially a
214  * one-way branch.
215  *
216  * May modify IP.  Does not modify LR.
217  */
218 .macro  LDR_PC source
219     ldr     pc, \source
220 .endm
221
222 /*
223  * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5.
224  * Jump to subroutine.
225  *
226  * May modify IP and LR.
227  */
228 .macro  LDR_PC_LR source
229     mov     lr, pc
230     ldr     pc, \source
231 .endm
232
233 /*
234  * Macro for "LDMFD SP!, {...regs...,PC}".
235  *
236  * May modify IP and LR.
237  */
238 .macro  LDMFD_PC regs
239     ldmfd   sp!, {\regs,pc}
240 .endm
241
242
243 /* File: armv5te/entry.S */
244 /*
245  * Copyright (C) 2008 The Android Open Source Project
246  *
247  * Licensed under the Apache License, Version 2.0 (the "License");
248  * you may not use this file except in compliance with the License.
249  * You may obtain a copy of the License at
250  *
251  *      http://www.apache.org/licenses/LICENSE-2.0
252  *
253  * Unless required by applicable law or agreed to in writing, software
254  * distributed under the License is distributed on an "AS IS" BASIS,
255  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
256  * See the License for the specific language governing permissions and
257  * limitations under the License.
258  */
259 /*
260  * Interpreter entry point.
261  */
262
263 /*
264  * We don't have formal stack frames, so gdb scans upward in the code
265  * to find the start of the function (a label with the %function type),
266  * and then looks at the next few instructions to figure out what
267  * got pushed onto the stack.  From this it figures out how to restore
268  * the registers, including PC, for the previous stack frame.  If gdb
269  * sees a non-function label, it stops scanning, so either we need to
270  * have nothing but assembler-local labels between the entry point and
271  * the break, or we need to fake it out.
272  *
273  * When this is defined, we add some stuff to make gdb less confused.
274  */
275 #define ASSIST_DEBUGGER 1
276
277     .text
278     .align  2
279     .global dvmMterpStdRun
280     .type   dvmMterpStdRun, %function
281
282 /*
283  * On entry:
284  *  r0  MterpGlue* glue
285  *
286  * This function returns a boolean "changeInterp" value.  The return comes
287  * via a call to dvmMterpStdBail().
288  */
289 dvmMterpStdRun:
290 #define MTERP_ENTRY1 \
291     .save {r4-r10,fp,lr}; \
292     stmfd   sp!, {r4-r10,fp,lr}         @ save 9 regs
293 #define MTERP_ENTRY2 \
294     .pad    #4; \
295     sub     sp, sp, #4                  @ align 64
296
297     .fnstart
298     MTERP_ENTRY1
299     MTERP_ENTRY2
300
301     /* save stack pointer, add magic word for debuggerd */
302     str     sp, [r0, #offGlue_bailPtr]  @ save SP for eventual return
303
304     /* set up "named" registers, figure out entry point */
305     mov     rGLUE, r0                   @ set rGLUE
306     ldrb    r1, [r0, #offGlue_entryPoint]   @ InterpEntry enum is char
307     LOAD_PC_FP_FROM_GLUE()              @ load rPC and rFP from "glue"
308     adr     rIBASE, dvmAsmInstructionStart  @ set rIBASE
309     cmp     r1, #kInterpEntryInstr      @ usual case?
310     bne     .Lnot_instr                 @ no, handle it
311
312 #if defined(WITH_JIT)
313 .Lno_singleStep:
314     /* Entry is always a possible trace start */
315     GET_JIT_PROF_TABLE(r0)
316     FETCH_INST()
317     cmp    r0,#0
318     bne    common_updateProfile
319     GET_INST_OPCODE(ip)
320     GOTO_OPCODE(ip)
321 #else
322     /* start executing the instruction at rPC */
323     FETCH_INST()                        @ load rINST from rPC
324     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
325     GOTO_OPCODE(ip)                     @ jump to next instruction
326 #endif
327
328 .Lnot_instr:
329     cmp     r1, #kInterpEntryReturn     @ were we returning from a method?
330     beq     common_returnFromMethod
331
332 .Lnot_return:
333     cmp     r1, #kInterpEntryThrow      @ were we throwing an exception?
334     beq     common_exceptionThrown
335
336 #if defined(WITH_JIT)
337 .Lnot_throw:
338     ldr     r0,[rGLUE, #offGlue_jitResume]
339     ldr     r2,[rGLUE, #offGlue_jitResumePC]
340     cmp     r1, #kInterpEntryResume     @ resuming after Jit single-step?
341     bne     .Lbad_arg
342     cmp     rPC,r2
343     bne     .Lno_singleStep             @ must have branched, don't resume
344     mov     r1, #kInterpEntryInstr
345     strb    r1, [rGLUE, #offGlue_entryPoint]
346     ldr     rINST, .LdvmCompilerTemplate
347     bx      r0                          @ re-enter the translation
348 .LdvmCompilerTemplate:
349     .word   dvmCompilerTemplateStart
350 #endif
351
352 .Lbad_arg:
353     ldr     r0, strBadEntryPoint
354     @ r1 holds value of entryPoint
355     bl      printf
356     bl      dvmAbort
357     .fnend
358
359
360     .global dvmMterpStdBail
361     .type   dvmMterpStdBail, %function
362
363 /*
364  * Restore the stack pointer and PC from the save point established on entry.
365  * This is essentially the same as a longjmp, but should be cheaper.  The
366  * last instruction causes us to return to whoever called dvmMterpStdRun.
367  *
368  * We pushed some registers on the stack in dvmMterpStdRun, then saved
369  * SP and LR.  Here we restore SP, restore the registers, and then restore
370  * LR to PC.
371  *
372  * On entry:
373  *  r0  MterpGlue* glue
374  *  r1  bool changeInterp
375  */
376 dvmMterpStdBail:
377     ldr     sp, [r0, #offGlue_bailPtr]      @ sp<- saved SP
378     mov     r0, r1                          @ return the changeInterp value
379     add     sp, sp, #4                      @ un-align 64
380     LDMFD_PC "r4-r10,fp"                    @ restore 9 regs and return
381
382
383 /*
384  * String references.
385  */
386 strBadEntryPoint:
387     .word   .LstrBadEntryPoint
388
389
390
391     .global dvmAsmInstructionStart
392     .type   dvmAsmInstructionStart, %function
393 dvmAsmInstructionStart = .L_OP_NOP
394     .text
395
396 /* ------------------------------ */
397     .balign 64
398 .L_OP_NOP: /* 0x00 */
399 /* File: armv5te/OP_NOP.S */
400     FETCH_ADVANCE_INST(1)               @ advance to next instr, load rINST
401     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
402     GOTO_OPCODE(ip)                     @ execute it
403
404 #ifdef ASSIST_DEBUGGER
405     /* insert fake function header to help gdb find the stack frame */
406     .type   dalvik_inst, %function
407 dalvik_inst:
408     .fnstart
409     MTERP_ENTRY1
410     MTERP_ENTRY2
411     .fnend
412 #endif
413
414
415 /* ------------------------------ */
416     .balign 64
417 .L_OP_MOVE: /* 0x01 */
418 /* File: armv6t2/OP_MOVE.S */
419     /* for move, move-object, long-to-int */
420     /* op vA, vB */
421     mov     r1, rINST, lsr #12          @ r1<- B from 15:12
422     ubfx    r0, rINST, #8, #4           @ r0<- A from 11:8
423     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
424     GET_VREG(r2, r1)                    @ r2<- fp[B]
425     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
426     SET_VREG(r2, r0)                    @ fp[A]<- r2
427     GOTO_OPCODE(ip)                     @ execute next instruction
428
429
430 /* ------------------------------ */
431     .balign 64
432 .L_OP_MOVE_FROM16: /* 0x02 */
433 /* File: armv5te/OP_MOVE_FROM16.S */
434     /* for: move/from16, move-object/from16 */
435     /* op vAA, vBBBB */
436     FETCH(r1, 1)                        @ r1<- BBBB
437     mov     r0, rINST, lsr #8           @ r0<- AA
438     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
439     GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
440     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
441     SET_VREG(r2, r0)                    @ fp[AA]<- r2
442     GOTO_OPCODE(ip)                     @ jump to next instruction
443
444
445 /* ------------------------------ */
446     .balign 64
447 .L_OP_MOVE_16: /* 0x03 */
448 /* File: armv5te/OP_MOVE_16.S */
449     /* for: move/16, move-object/16 */
450     /* op vAAAA, vBBBB */
451     FETCH(r1, 2)                        @ r1<- BBBB
452     FETCH(r0, 1)                        @ r0<- AAAA
453     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
454     GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
455     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
456     SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
457     GOTO_OPCODE(ip)                     @ jump to next instruction
458
459
460 /* ------------------------------ */
461     .balign 64
462 .L_OP_MOVE_WIDE: /* 0x04 */
463 /* File: armv6t2/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     r3, rINST, lsr #12          @ r3<- B
467     ubfx    r2, rINST, #8, #4           @ r2<- A
468     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
469     add     r2, rFP, r2, lsl #2         @ r2<- &fp[A]
470     ldmia   r3, {r0-r1}                 @ r0/r1<- fp[B]
471     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
472     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
473     stmia   r2, {r0-r1}                 @ fp[A]<- r0/r1
474     GOTO_OPCODE(ip)                     @ jump to next instruction
475
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 /* ------------------------------ */
495     .balign 64
496 .L_OP_MOVE_WIDE_16: /* 0x06 */
497 /* File: armv5te/OP_MOVE_WIDE_16.S */
498     /* move-wide/16 vAAAA, vBBBB */
499     /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
500     FETCH(r3, 2)                        @ r3<- BBBB
501     FETCH(r2, 1)                        @ r2<- AAAA
502     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
503     add     r2, rFP, r2, lsl #2         @ r2<- &fp[AAAA]
504     ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
505     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
506     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
507     stmia   r2, {r0-r1}                 @ fp[AAAA]<- r0/r1
508     GOTO_OPCODE(ip)                     @ jump to next instruction
509
510
511 /* ------------------------------ */
512     .balign 64
513 .L_OP_MOVE_OBJECT: /* 0x07 */
514 /* File: armv5te/OP_MOVE_OBJECT.S */
515 /* File: armv5te/OP_MOVE.S */
516     /* for move, move-object, long-to-int */
517     /* op vA, vB */
518     mov     r1, rINST, lsr #12          @ r1<- B from 15:12
519     mov     r0, rINST, lsr #8           @ r0<- A from 11:8
520     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
521     GET_VREG(r2, r1)                    @ r2<- fp[B]
522     and     r0, r0, #15
523     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
524     SET_VREG(r2, r0)                    @ fp[A]<- r2
525     GOTO_OPCODE(ip)                     @ execute next instruction
526
527
528
529 /* ------------------------------ */
530     .balign 64
531 .L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
532 /* File: armv5te/OP_MOVE_OBJECT_FROM16.S */
533 /* File: armv5te/OP_MOVE_FROM16.S */
534     /* for: move/from16, move-object/from16 */
535     /* op vAA, vBBBB */
536     FETCH(r1, 1)                        @ r1<- BBBB
537     mov     r0, rINST, lsr #8           @ r0<- AA
538     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
539     GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
540     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
541     SET_VREG(r2, r0)                    @ fp[AA]<- r2
542     GOTO_OPCODE(ip)                     @ jump to next instruction
543
544
545
546 /* ------------------------------ */
547     .balign 64
548 .L_OP_MOVE_OBJECT_16: /* 0x09 */
549 /* File: armv5te/OP_MOVE_OBJECT_16.S */
550 /* File: armv5te/OP_MOVE_16.S */
551     /* for: move/16, move-object/16 */
552     /* op vAAAA, vBBBB */
553     FETCH(r1, 2)                        @ r1<- BBBB
554     FETCH(r0, 1)                        @ r0<- AAAA
555     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
556     GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
557     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
558     SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
559     GOTO_OPCODE(ip)                     @ jump to next instruction
560
561
562
563 /* ------------------------------ */
564     .balign 64
565 .L_OP_MOVE_RESULT: /* 0x0a */
566 /* File: armv5te/OP_MOVE_RESULT.S */
567     /* for: move-result, move-result-object */
568     /* op vAA */
569     mov     r2, rINST, lsr #8           @ r2<- AA
570     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
571     ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
572     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
573     SET_VREG(r0, r2)                    @ fp[AA]<- r0
574     GOTO_OPCODE(ip)                     @ jump to next instruction
575
576
577 /* ------------------------------ */
578     .balign 64
579 .L_OP_MOVE_RESULT_WIDE: /* 0x0b */
580 /* File: armv5te/OP_MOVE_RESULT_WIDE.S */
581     /* move-result-wide vAA */
582     mov     r2, rINST, lsr #8           @ r2<- AA
583     add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
584     add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
585     ldmia   r3, {r0-r1}                 @ r0/r1<- retval.j
586     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
587     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
588     stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
589     GOTO_OPCODE(ip)                     @ jump to next instruction
590
591
592 /* ------------------------------ */
593     .balign 64
594 .L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
595 /* File: armv5te/OP_MOVE_RESULT_OBJECT.S */
596 /* File: armv5te/OP_MOVE_RESULT.S */
597     /* for: move-result, move-result-object */
598     /* op vAA */
599     mov     r2, rINST, lsr #8           @ r2<- AA
600     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
601     ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
602     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
603     SET_VREG(r0, r2)                    @ fp[AA]<- r0
604     GOTO_OPCODE(ip)                     @ jump to next instruction
605
606
607
608 /* ------------------------------ */
609     .balign 64
610 .L_OP_MOVE_EXCEPTION: /* 0x0d */
611 /* File: armv5te/OP_MOVE_EXCEPTION.S */
612     /* move-exception vAA */
613     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
614     mov     r2, rINST, lsr #8           @ r2<- AA
615     ldr     r3, [r0, #offThread_exception]  @ r3<- dvmGetException bypass
616     mov     r1, #0                      @ r1<- 0
617     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
618     SET_VREG(r3, r2)                    @ fp[AA]<- exception obj
619     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
620     str     r1, [r0, #offThread_exception]  @ dvmClearException bypass
621     GOTO_OPCODE(ip)                     @ jump to next instruction
622
623
624 /* ------------------------------ */
625     .balign 64
626 .L_OP_RETURN_VOID: /* 0x0e */
627 /* File: armv5te/OP_RETURN_VOID.S */
628     b       common_returnFromMethod
629
630
631 /* ------------------------------ */
632     .balign 64
633 .L_OP_RETURN: /* 0x0f */
634 /* File: armv5te/OP_RETURN.S */
635     /*
636      * Return a 32-bit value.  Copies the return value into the "glue"
637      * structure, then jumps to the return handler.
638      *
639      * for: return, return-object
640      */
641     /* op vAA */
642     mov     r2, rINST, lsr #8           @ r2<- AA
643     GET_VREG(r0, r2)                    @ r0<- vAA
644     str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
645     b       common_returnFromMethod
646
647
648 /* ------------------------------ */
649     .balign 64
650 .L_OP_RETURN_WIDE: /* 0x10 */
651 /* File: armv5te/OP_RETURN_WIDE.S */
652     /*
653      * Return a 64-bit value.  Copies the return value into the "glue"
654      * structure, then jumps to the return handler.
655      */
656     /* return-wide vAA */
657     mov     r2, rINST, lsr #8           @ r2<- AA
658     add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
659     add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
660     ldmia   r2, {r0-r1}                 @ r0/r1 <- vAA/vAA+1
661     stmia   r3, {r0-r1}                 @ retval<- r0/r1
662     b       common_returnFromMethod
663
664
665 /* ------------------------------ */
666     .balign 64
667 .L_OP_RETURN_OBJECT: /* 0x11 */
668 /* File: armv5te/OP_RETURN_OBJECT.S */
669 /* File: armv5te/OP_RETURN.S */
670     /*
671      * Return a 32-bit value.  Copies the return value into the "glue"
672      * structure, then jumps to the return handler.
673      *
674      * for: return, return-object
675      */
676     /* op vAA */
677     mov     r2, rINST, lsr #8           @ r2<- AA
678     GET_VREG(r0, r2)                    @ r0<- vAA
679     str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
680     b       common_returnFromMethod
681
682
683
684 /* ------------------------------ */
685     .balign 64
686 .L_OP_CONST_4: /* 0x12 */
687 /* File: armv6t2/OP_CONST_4.S */
688     /* const/4 vA, #+B */
689     mov     r1, rINST, lsl #16          @ r1<- Bxxx0000
690     ubfx    r0, rINST, #8, #4           @ r0<- A
691     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
692     mov     r1, r1, asr #28             @ r1<- sssssssB (sign-extended)
693     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
694     SET_VREG(r1, r0)                    @ fp[A]<- r1
695     GOTO_OPCODE(ip)                     @ execute next instruction
696
697
698 /* ------------------------------ */
699     .balign 64
700 .L_OP_CONST_16: /* 0x13 */
701 /* File: armv5te/OP_CONST_16.S */
702     /* const/16 vAA, #+BBBB */
703     FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
704     mov     r3, rINST, lsr #8           @ r3<- AA
705     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
706     SET_VREG(r0, r3)                    @ vAA<- r0
707     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
708     GOTO_OPCODE(ip)                     @ jump to next instruction
709
710
711 /* ------------------------------ */
712     .balign 64
713 .L_OP_CONST: /* 0x14 */
714 /* File: armv5te/OP_CONST.S */
715     /* const vAA, #+BBBBbbbb */
716     mov     r3, rINST, lsr #8           @ r3<- AA
717     FETCH(r0, 1)                        @ r0<- bbbb (low)
718     FETCH(r1, 2)                        @ r1<- BBBB (high)
719     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
720     orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
721     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
722     SET_VREG(r0, r3)                    @ vAA<- r0
723     GOTO_OPCODE(ip)                     @ jump to next instruction
724
725
726 /* ------------------------------ */
727     .balign 64
728 .L_OP_CONST_HIGH16: /* 0x15 */
729 /* File: armv5te/OP_CONST_HIGH16.S */
730     /* const/high16 vAA, #+BBBB0000 */
731     FETCH(r0, 1)                        @ r0<- 0000BBBB (zero-extended)
732     mov     r3, rINST, lsr #8           @ r3<- AA
733     mov     r0, r0, lsl #16             @ r0<- BBBB0000
734     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
735     SET_VREG(r0, r3)                    @ vAA<- r0
736     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
737     GOTO_OPCODE(ip)                     @ jump to next instruction
738
739
740 /* ------------------------------ */
741     .balign 64
742 .L_OP_CONST_WIDE_16: /* 0x16 */
743 /* File: armv5te/OP_CONST_WIDE_16.S */
744     /* const-wide/16 vAA, #+BBBB */
745     FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
746     mov     r3, rINST, lsr #8           @ r3<- AA
747     mov     r1, r0, asr #31             @ r1<- ssssssss
748     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
749     add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
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 /* ------------------------------ */
756     .balign 64
757 .L_OP_CONST_WIDE_32: /* 0x17 */
758 /* File: armv5te/OP_CONST_WIDE_32.S */
759     /* const-wide/32 vAA, #+BBBBbbbb */
760     FETCH(r0, 1)                        @ r0<- 0000bbbb (low)
761     mov     r3, rINST, lsr #8           @ r3<- AA
762     FETCH_S(r2, 2)                      @ r2<- ssssBBBB (high)
763     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
764     orr     r0, r0, r2, lsl #16         @ r0<- BBBBbbbb
765     add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
766     mov     r1, r0, asr #31             @ r1<- ssssssss
767     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
768     stmia   r3, {r0-r1}                 @ vAA<- r0/r1
769     GOTO_OPCODE(ip)                     @ jump to next instruction
770
771
772 /* ------------------------------ */
773     .balign 64
774 .L_OP_CONST_WIDE: /* 0x18 */
775 /* File: armv5te/OP_CONST_WIDE.S */
776     /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
777     FETCH(r0, 1)                        @ r0<- bbbb (low)
778     FETCH(r1, 2)                        @ r1<- BBBB (low middle)
779     FETCH(r2, 3)                        @ r2<- hhhh (high middle)
780     orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb (low word)
781     FETCH(r3, 4)                        @ r3<- HHHH (high)
782     mov     r9, rINST, lsr #8           @ r9<- AA
783     orr     r1, r2, r3, lsl #16         @ r1<- HHHHhhhh (high word)
784     FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
785     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
786     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
787     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
788     GOTO_OPCODE(ip)                     @ jump to next instruction
789
790
791 /* ------------------------------ */
792     .balign 64
793 .L_OP_CONST_WIDE_HIGH16: /* 0x19 */
794 /* File: armv5te/OP_CONST_WIDE_HIGH16.S */
795     /* const-wide/high16 vAA, #+BBBB000000000000 */
796     FETCH(r1, 1)                        @ r1<- 0000BBBB (zero-extended)
797     mov     r3, rINST, lsr #8           @ r3<- AA
798     mov     r0, #0                      @ r0<- 00000000
799     mov     r1, r1, lsl #16             @ r1<- BBBB0000
800     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
801     add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
802     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
803     stmia   r3, {r0-r1}                 @ vAA<- r0/r1
804     GOTO_OPCODE(ip)                     @ jump to next instruction
805
806
807 /* ------------------------------ */
808     .balign 64
809 .L_OP_CONST_STRING: /* 0x1a */
810 /* File: armv5te/OP_CONST_STRING.S */
811     /* const/string vAA, String@BBBB */
812     FETCH(r1, 1)                        @ r1<- BBBB
813     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
814     mov     r9, rINST, lsr #8           @ r9<- AA
815     ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
816     ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
817     cmp     r0, #0                      @ not yet resolved?
818     beq     .LOP_CONST_STRING_resolve
819     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
820     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
821     SET_VREG(r0, r9)                    @ vAA<- r0
822     GOTO_OPCODE(ip)                     @ jump to next instruction
823
824 /* ------------------------------ */
825     .balign 64
826 .L_OP_CONST_STRING_JUMBO: /* 0x1b */
827 /* File: armv5te/OP_CONST_STRING_JUMBO.S */
828     /* const/string vAA, String@BBBBBBBB */
829     FETCH(r0, 1)                        @ r0<- bbbb (low)
830     FETCH(r1, 2)                        @ r1<- BBBB (high)
831     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
832     mov     r9, rINST, lsr #8           @ r9<- AA
833     ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
834     orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
835     ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
836     cmp     r0, #0
837     beq     .LOP_CONST_STRING_JUMBO_resolve
838     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
839     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
840     SET_VREG(r0, r9)                    @ vAA<- r0
841     GOTO_OPCODE(ip)                     @ jump to next instruction
842
843 /* ------------------------------ */
844     .balign 64
845 .L_OP_CONST_CLASS: /* 0x1c */
846 /* File: armv5te/OP_CONST_CLASS.S */
847     /* const/class vAA, Class@BBBB */
848     FETCH(r1, 1)                        @ r1<- BBBB
849     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
850     mov     r9, rINST, lsr #8           @ r9<- AA
851     ldr     r2, [r2, #offDvmDex_pResClasses]   @ r2<- dvmDex->pResClasses
852     ldr     r0, [r2, r1, lsl #2]        @ r0<- pResClasses[BBBB]
853     cmp     r0, #0                      @ not yet resolved?
854     beq     .LOP_CONST_CLASS_resolve
855     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
856     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
857     SET_VREG(r0, r9)                    @ vAA<- r0
858     GOTO_OPCODE(ip)                     @ jump to next instruction
859
860 /* ------------------------------ */
861     .balign 64
862 .L_OP_MONITOR_ENTER: /* 0x1d */
863 /* File: armv5te/OP_MONITOR_ENTER.S */
864     /*
865      * Synchronize on an object.
866      */
867     /* monitor-enter vAA */
868     mov     r2, rINST, lsr #8           @ r2<- AA
869     GET_VREG(r1, r2)                    @ r1<- vAA (object)
870     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
871     cmp     r1, #0                      @ null object?
872     EXPORT_PC()                         @ need for precise GC, MONITOR_TRACKING
873     beq     common_errNullObject        @ null object, throw an exception
874     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
875     bl      dvmLockObject               @ call(self, obj)
876 #ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */
877     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
878     ldr     r1, [r0, #offThread_exception] @ check for exception
879     cmp     r1, #0
880     bne     common_exceptionThrown      @ exception raised, bail out
881 #endif
882     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
883     GOTO_OPCODE(ip)                     @ jump to next instruction
884
885
886 /* ------------------------------ */
887     .balign 64
888 .L_OP_MONITOR_EXIT: /* 0x1e */
889 /* File: armv5te/OP_MONITOR_EXIT.S */
890     /*
891      * Unlock an object.
892      *
893      * Exceptions that occur when unlocking a monitor need to appear as
894      * if they happened at the following instruction.  See the Dalvik
895      * instruction spec.
896      */
897     /* monitor-exit vAA */
898     mov     r2, rINST, lsr #8           @ r2<- AA
899     EXPORT_PC()                         @ before fetch: export the PC
900     GET_VREG(r1, r2)                    @ r1<- vAA (object)
901     cmp     r1, #0                      @ null object?
902     beq     common_errNullObject        @ yes
903     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
904     bl      dvmUnlockObject             @ r0<- success for unlock(self, obj)
905     cmp     r0, #0                      @ failed?
906     beq     common_exceptionThrown      @ yes, exception is pending
907     FETCH_ADVANCE_INST(1)               @ before throw: advance rPC, load rINST
908     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
909     GOTO_OPCODE(ip)                     @ jump to next instruction
910
911
912 /* ------------------------------ */
913     .balign 64
914 .L_OP_CHECK_CAST: /* 0x1f */
915 /* File: armv5te/OP_CHECK_CAST.S */
916     /*
917      * Check to see if a cast from one class to another is allowed.
918      */
919     /* check-cast vAA, class@BBBB */
920     mov     r3, rINST, lsr #8           @ r3<- AA
921     FETCH(r2, 1)                        @ r2<- BBBB
922     GET_VREG(r9, r3)                    @ r9<- object
923     ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- pDvmDex
924     cmp     r9, #0                      @ is object null?
925     ldr     r0, [r0, #offDvmDex_pResClasses]    @ r0<- pDvmDex->pResClasses
926     beq     .LOP_CHECK_CAST_okay            @ null obj, cast always succeeds
927     ldr     r1, [r0, r2, lsl #2]        @ r1<- resolved class
928     ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
929     cmp     r1, #0                      @ have we resolved this before?
930     beq     .LOP_CHECK_CAST_resolve         @ not resolved, do it now
931 .LOP_CHECK_CAST_resolved:
932     cmp     r0, r1                      @ same class (trivial success)?
933     bne     .LOP_CHECK_CAST_fullcheck       @ no, do full check
934 .LOP_CHECK_CAST_okay:
935     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
936     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
937     GOTO_OPCODE(ip)                     @ jump to next instruction
938
939 /* ------------------------------ */
940     .balign 64
941 .L_OP_INSTANCE_OF: /* 0x20 */
942 /* File: armv5te/OP_INSTANCE_OF.S */
943     /*
944      * Check to see if an object reference is an instance of a class.
945      *
946      * Most common situation is a non-null object, being compared against
947      * an already-resolved class.
948      */
949     /* instance-of vA, vB, class@CCCC */
950     mov     r3, rINST, lsr #12          @ r3<- B
951     mov     r9, rINST, lsr #8           @ r9<- A+
952     GET_VREG(r0, r3)                    @ r0<- vB (object)
953     and     r9, r9, #15                 @ r9<- A
954     cmp     r0, #0                      @ is object null?
955     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- pDvmDex
956     beq     .LOP_INSTANCE_OF_store           @ null obj, not an instance, store r0
957     FETCH(r3, 1)                        @ r3<- CCCC
958     ldr     r2, [r2, #offDvmDex_pResClasses]    @ r2<- pDvmDex->pResClasses
959     ldr     r1, [r2, r3, lsl #2]        @ r1<- resolved class
960     ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
961     cmp     r1, #0                      @ have we resolved this before?
962     beq     .LOP_INSTANCE_OF_resolve         @ not resolved, do it now
963 .LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class
964     cmp     r0, r1                      @ same class (trivial success)?
965     beq     .LOP_INSTANCE_OF_trivial         @ yes, trivial finish
966     b       .LOP_INSTANCE_OF_fullcheck       @ no, do full check
967
968 /* ------------------------------ */
969     .balign 64
970 .L_OP_ARRAY_LENGTH: /* 0x21 */
971 /* File: armv6t2/OP_ARRAY_LENGTH.S */
972     /*
973      * Return the length of an array.
974      */
975     mov     r1, rINST, lsr #12          @ r1<- B
976     ubfx    r2, rINST, #8, #4           @ r2<- A
977     GET_VREG(r0, r1)                    @ r0<- vB (object ref)
978     cmp     r0, #0                      @ is object null?
979     beq     common_errNullObject        @ yup, fail
980     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
981     ldr     r3, [r0, #offArrayObject_length]    @ r3<- array length
982     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
983     SET_VREG(r3, r2)                    @ vB<- length
984     GOTO_OPCODE(ip)                     @ jump to next instruction
985
986
987 /* ------------------------------ */
988     .balign 64
989 .L_OP_NEW_INSTANCE: /* 0x22 */
990 /* File: armv5te/OP_NEW_INSTANCE.S */
991     /*
992      * Create a new instance of a class.
993      */
994     /* new-instance vAA, class@BBBB */
995     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
996     FETCH(r1, 1)                        @ r1<- BBBB
997     ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
998     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
999     EXPORT_PC()                         @ req'd for init, resolve, alloc
1000     cmp     r0, #0                      @ already resolved?
1001     beq     .LOP_NEW_INSTANCE_resolve         @ no, resolve it now
1002 .LOP_NEW_INSTANCE_resolved:   @ r0=class
1003     ldrb    r1, [r0, #offClassObject_status]    @ r1<- ClassStatus enum
1004     cmp     r1, #CLASS_INITIALIZED      @ has class been initialized?
1005     bne     .LOP_NEW_INSTANCE_needinit        @ no, init class now
1006 .LOP_NEW_INSTANCE_initialized: @ r0=class
1007     mov     r1, #ALLOC_DONT_TRACK       @ flags for alloc call
1008     bl      dvmAllocObject              @ r0<- new object
1009     b       .LOP_NEW_INSTANCE_finish          @ continue
1010
1011 /* ------------------------------ */
1012     .balign 64
1013 .L_OP_NEW_ARRAY: /* 0x23 */
1014 /* File: armv5te/OP_NEW_ARRAY.S */
1015     /*
1016      * Allocate an array of objects, specified with the array class
1017      * and a count.
1018      *
1019      * The verifier guarantees that this is an array class, so we don't
1020      * check for it here.
1021      */
1022     /* new-array vA, vB, class@CCCC */
1023     mov     r0, rINST, lsr #12          @ r0<- B
1024     FETCH(r2, 1)                        @ r2<- CCCC
1025     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1026     GET_VREG(r1, r0)                    @ r1<- vB (array length)
1027     ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1028     cmp     r1, #0                      @ check length
1029     ldr     r0, [r3, r2, lsl #2]        @ r0<- resolved class
1030     bmi     common_errNegativeArraySize @ negative length, bail
1031     cmp     r0, #0                      @ already resolved?
1032     EXPORT_PC()                         @ req'd for resolve, alloc
1033     bne     .LOP_NEW_ARRAY_finish          @ resolved, continue
1034     b       .LOP_NEW_ARRAY_resolve         @ do resolve now
1035
1036 /* ------------------------------ */
1037     .balign 64
1038 .L_OP_FILLED_NEW_ARRAY: /* 0x24 */
1039 /* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1040     /*
1041      * Create a new array with elements filled from registers.
1042      *
1043      * for: filled-new-array, filled-new-array/range
1044      */
1045     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1046     /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1047     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1048     FETCH(r1, 1)                        @ r1<- BBBB
1049     ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1050     EXPORT_PC()                         @ need for resolve and alloc
1051     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1052     mov     r10, rINST, lsr #8          @ r10<- AA or BA
1053     cmp     r0, #0                      @ already resolved?
1054     bne     .LOP_FILLED_NEW_ARRAY_continue        @ yes, continue on
1055 8:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1056     mov     r2, #0                      @ r2<- false
1057     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1058     bl      dvmResolveClass             @ r0<- call(clazz, ref)
1059     cmp     r0, #0                      @ got null?
1060     beq     common_exceptionThrown      @ yes, handle exception
1061     b       .LOP_FILLED_NEW_ARRAY_continue
1062
1063 /* ------------------------------ */
1064     .balign 64
1065 .L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
1066 /* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */
1067 /* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1068     /*
1069      * Create a new array with elements filled from registers.
1070      *
1071      * for: filled-new-array, filled-new-array/range
1072      */
1073     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1074     /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1075     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1076     FETCH(r1, 1)                        @ r1<- BBBB
1077     ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1078     EXPORT_PC()                         @ need for resolve and alloc
1079     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1080     mov     r10, rINST, lsr #8          @ r10<- AA or BA
1081     cmp     r0, #0                      @ already resolved?
1082     bne     .LOP_FILLED_NEW_ARRAY_RANGE_continue        @ yes, continue on
1083 8:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1084     mov     r2, #0                      @ r2<- false
1085     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1086     bl      dvmResolveClass             @ r0<- call(clazz, ref)
1087     cmp     r0, #0                      @ got null?
1088     beq     common_exceptionThrown      @ yes, handle exception
1089     b       .LOP_FILLED_NEW_ARRAY_RANGE_continue
1090
1091
1092 /* ------------------------------ */
1093     .balign 64
1094 .L_OP_FILL_ARRAY_DATA: /* 0x26 */
1095 /* File: armv5te/OP_FILL_ARRAY_DATA.S */
1096     /* fill-array-data vAA, +BBBBBBBB */
1097     FETCH(r0, 1)                        @ r0<- bbbb (lo)
1098     FETCH(r1, 2)                        @ r1<- BBBB (hi)
1099     mov     r3, rINST, lsr #8           @ r3<- AA
1100     orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
1101     GET_VREG(r0, r3)                    @ r0<- vAA (array object)
1102     add     r1, rPC, r1, lsl #1         @ r1<- PC + BBBBbbbb*2 (array data off.)
1103     EXPORT_PC();
1104     bl      dvmInterpHandleFillArrayData@ fill the array with predefined data
1105     cmp     r0, #0                      @ 0 means an exception is thrown
1106     beq     common_exceptionThrown      @ has exception
1107     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
1108     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1109     GOTO_OPCODE(ip)                     @ jump to next instruction
1110
1111 /* ------------------------------ */
1112     .balign 64
1113 .L_OP_THROW: /* 0x27 */
1114 /* File: armv5te/OP_THROW.S */
1115     /*
1116      * Throw an exception object in the current thread.
1117      */
1118     /* throw vAA */
1119     mov     r2, rINST, lsr #8           @ r2<- AA
1120     GET_VREG(r1, r2)                    @ r1<- vAA (exception object)
1121     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
1122     cmp     r1, #0                      @ null object?
1123     beq     common_errNullObject        @ yes, throw an NPE instead
1124     @ bypass dvmSetException, just store it
1125     str     r1, [r0, #offThread_exception]  @ thread->exception<- obj
1126     b       common_exceptionThrown
1127
1128
1129 /* ------------------------------ */
1130     .balign 64
1131 .L_OP_GOTO: /* 0x28 */
1132 /* File: armv5te/OP_GOTO.S */
1133     /*
1134      * Unconditional branch, 8-bit offset.
1135      *
1136      * The branch distance is a signed code-unit offset, which we need to
1137      * double to get a byte offset.
1138      */
1139     /* goto +AA */
1140     mov     r0, rINST, lsl #16          @ r0<- AAxx0000
1141     movs    r9, r0, asr #24             @ r9<- ssssssAA (sign-extended)
1142     mov     r9, r9, lsl #1              @ r9<- byte offset
1143     bmi     common_backwardBranch       @ backward branch, do periodic checks
1144 #if defined(WITH_JIT)
1145     GET_JIT_PROF_TABLE(r0)
1146     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1147     cmp     r0,#0
1148     bne     common_updateProfile
1149     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1150     GOTO_OPCODE(ip)                     @ jump to next instruction
1151 #else
1152     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1153     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1154     GOTO_OPCODE(ip)                     @ jump to next instruction
1155 #endif
1156
1157 /* ------------------------------ */
1158     .balign 64
1159 .L_OP_GOTO_16: /* 0x29 */
1160 /* File: armv5te/OP_GOTO_16.S */
1161     /*
1162      * Unconditional branch, 16-bit offset.
1163      *
1164      * The branch distance is a signed code-unit offset, which we need to
1165      * double to get a byte offset.
1166      */
1167     /* goto/16 +AAAA */
1168     FETCH_S(r0, 1)                      @ r0<- ssssAAAA (sign-extended)
1169     movs    r9, r0, asl #1              @ r9<- byte offset, check sign
1170     bmi     common_backwardBranch       @ backward branch, do periodic checks
1171 #if defined(WITH_JIT)
1172     GET_JIT_PROF_TABLE(r0)
1173     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1174     cmp     r0,#0
1175     bne     common_updateProfile
1176     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1177     GOTO_OPCODE(ip)                     @ jump to next instruction
1178 #else
1179     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1180     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1181     GOTO_OPCODE(ip)                     @ jump to next instruction
1182 #endif
1183
1184
1185 /* ------------------------------ */
1186     .balign 64
1187 .L_OP_GOTO_32: /* 0x2a */
1188 /* File: armv5te/OP_GOTO_32.S */
1189     /*
1190      * Unconditional branch, 32-bit offset.
1191      *
1192      * The branch distance is a signed code-unit offset, which we need to
1193      * double to get a byte offset.
1194      *
1195      * Unlike most opcodes, this one is allowed to branch to itself, so
1196      * our "backward branch" test must be "<=0" instead of "<0".  The ORRS
1197      * instruction doesn't affect the V flag, so we need to clear it
1198      * explicitly.
1199      */
1200     /* goto/32 +AAAAAAAA */
1201     FETCH(r0, 1)                        @ r0<- aaaa (lo)
1202     FETCH(r1, 2)                        @ r1<- AAAA (hi)
1203     cmp     ip, ip                      @ (clear V flag during stall)
1204     orrs    r0, r0, r1, lsl #16         @ r0<- AAAAaaaa, check sign
1205     mov     r9, r0, asl #1              @ r9<- byte offset
1206     ble     common_backwardBranch       @ backward branch, do periodic checks
1207 #if defined(WITH_JIT)
1208     GET_JIT_PROF_TABLE(r0)
1209     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1210     cmp     r0,#0
1211     bne     common_updateProfile
1212     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1213     GOTO_OPCODE(ip)                     @ jump to next instruction
1214 #else
1215     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1216     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1217     GOTO_OPCODE(ip)                     @ jump to next instruction
1218 #endif
1219
1220 /* ------------------------------ */
1221     .balign 64
1222 .L_OP_PACKED_SWITCH: /* 0x2b */
1223 /* File: armv5te/OP_PACKED_SWITCH.S */
1224     /*
1225      * Handle a packed-switch or sparse-switch instruction.  In both cases
1226      * we decode it and hand it off to a helper function.
1227      *
1228      * We don't really expect backward branches in a switch statement, but
1229      * they're perfectly legal, so we check for them here.
1230      *
1231      * for: packed-switch, sparse-switch
1232      */
1233     /* op vAA, +BBBB */
1234     FETCH(r0, 1)                        @ r0<- bbbb (lo)
1235     FETCH(r1, 2)                        @ r1<- BBBB (hi)
1236     mov     r3, rINST, lsr #8           @ r3<- AA
1237     orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1238     GET_VREG(r1, r3)                    @ r1<- vAA
1239     add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1240     bl      dvmInterpHandlePackedSwitch                       @ r0<- code-unit branch offset
1241     movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1242     bmi     common_backwardBranch       @ backward branch, do periodic checks
1243     beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1244 #if defined(WITH_JIT)
1245     GET_JIT_PROF_TABLE(r0)
1246     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1247     cmp     r0,#0
1248     bne     common_updateProfile
1249     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1250     GOTO_OPCODE(ip)                     @ jump to next instruction
1251 #else
1252     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1253     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1254     GOTO_OPCODE(ip)                     @ jump to next instruction
1255 #endif
1256
1257
1258 /* ------------------------------ */
1259     .balign 64
1260 .L_OP_SPARSE_SWITCH: /* 0x2c */
1261 /* File: armv5te/OP_SPARSE_SWITCH.S */
1262 /* File: armv5te/OP_PACKED_SWITCH.S */
1263     /*
1264      * Handle a packed-switch or sparse-switch instruction.  In both cases
1265      * we decode it and hand it off to a helper function.
1266      *
1267      * We don't really expect backward branches in a switch statement, but
1268      * they're perfectly legal, so we check for them here.
1269      *
1270      * for: packed-switch, sparse-switch
1271      */
1272     /* op vAA, +BBBB */
1273     FETCH(r0, 1)                        @ r0<- bbbb (lo)
1274     FETCH(r1, 2)                        @ r1<- BBBB (hi)
1275     mov     r3, rINST, lsr #8           @ r3<- AA
1276     orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1277     GET_VREG(r1, r3)                    @ r1<- vAA
1278     add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1279     bl      dvmInterpHandleSparseSwitch                       @ r0<- code-unit branch offset
1280     movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1281     bmi     common_backwardBranch       @ backward branch, do periodic checks
1282     beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1283 #if defined(WITH_JIT)
1284     GET_JIT_PROF_TABLE(r0)
1285     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1286     cmp     r0,#0
1287     bne     common_updateProfile
1288     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1289     GOTO_OPCODE(ip)                     @ jump to next instruction
1290 #else
1291     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1292     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1293     GOTO_OPCODE(ip)                     @ jump to next instruction
1294 #endif
1295
1296
1297
1298 /* ------------------------------ */
1299     .balign 64
1300 .L_OP_CMPL_FLOAT: /* 0x2d */
1301 /* File: arm-vfp/OP_CMPL_FLOAT.S */
1302     /*
1303      * Compare two floating-point values.  Puts 0, 1, or -1 into the
1304      * destination register based on the results of the comparison.
1305      *
1306      * int compare(x, y) {
1307      *     if (x == y) {
1308      *         return 0;
1309      *     } else if (x > y) {
1310      *         return 1;
1311      *     } else if (x < y) {
1312      *         return -1;
1313      *     } else {
1314      *         return -1;
1315      *     }
1316      * }
1317      */
1318     /* op vAA, vBB, vCC */
1319     FETCH(r0, 1)                        @ r0<- CCBB
1320     mov     r9, rINST, lsr #8           @ r9<- AA
1321     and     r2, r0, #255                @ r2<- BB
1322     mov     r3, r0, lsr #8              @ r3<- CC
1323     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1324     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1325     flds    s0, [r2]                    @ s0<- vBB
1326     flds    s1, [r3]                    @ s1<- vCC
1327     fcmpes  s0, s1                      @ compare (vBB, vCC)
1328     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1329     mvn     r0, #0                      @ r0<- -1 (default)
1330     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1331     fmstat                              @ export status flags
1332     movgt   r0, #1                      @ (greater than) r1<- 1
1333     moveq   r0, #0                      @ (equal) r1<- 0
1334     b       .LOP_CMPL_FLOAT_finish          @ argh
1335
1336
1337 /* ------------------------------ */
1338     .balign 64
1339 .L_OP_CMPG_FLOAT: /* 0x2e */
1340 /* File: arm-vfp/OP_CMPG_FLOAT.S */
1341     /*
1342      * Compare two floating-point values.  Puts 0, 1, or -1 into the
1343      * destination register based on the results of the comparison.
1344      *
1345      * int compare(x, y) {
1346      *     if (x == y) {
1347      *         return 0;
1348      *     } else if (x < y) {
1349      *         return -1;
1350      *     } else if (x > y) {
1351      *         return 1;
1352      *     } else {
1353      *         return 1;
1354      *     }
1355      * }
1356      */
1357     /* op vAA, vBB, vCC */
1358     FETCH(r0, 1)                        @ r0<- CCBB
1359     mov     r9, rINST, lsr #8           @ r9<- AA
1360     and     r2, r0, #255                @ r2<- BB
1361     mov     r3, r0, lsr #8              @ r3<- CC
1362     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1363     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1364     flds    s0, [r2]                    @ s0<- vBB
1365     flds    s1, [r3]                    @ s1<- vCC
1366     fcmpes  s0, s1                      @ compare (vBB, vCC)
1367     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1368     mov     r0, #1                      @ r0<- 1 (default)
1369     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1370     fmstat                              @ export status flags
1371     mvnmi   r0, #0                      @ (less than) r1<- -1
1372     moveq   r0, #0                      @ (equal) r1<- 0
1373     b       .LOP_CMPG_FLOAT_finish          @ argh
1374
1375
1376 /* ------------------------------ */
1377     .balign 64
1378 .L_OP_CMPL_DOUBLE: /* 0x2f */
1379 /* File: arm-vfp/OP_CMPL_DOUBLE.S */
1380     /*
1381      * Compare two floating-point values.  Puts 0, 1, or -1 into the
1382      * destination register based on the results of the comparison.
1383      *
1384      * int compare(x, y) {
1385      *     if (x == y) {
1386      *         return 0;
1387      *     } else if (x > y) {
1388      *         return 1;
1389      *     } else if (x < y) {
1390      *         return -1;
1391      *     } else {
1392      *         return -1;
1393      *     }
1394      * }
1395      */
1396     /* op vAA, vBB, vCC */
1397     FETCH(r0, 1)                        @ r0<- CCBB
1398     mov     r9, rINST, lsr #8           @ r9<- AA
1399     and     r2, r0, #255                @ r2<- BB
1400     mov     r3, r0, lsr #8              @ r3<- CC
1401     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1402     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1403     fldd    d0, [r2]                    @ d0<- vBB
1404     fldd    d1, [r3]                    @ d1<- vCC
1405     fcmped  d0, d1                      @ compare (vBB, vCC)
1406     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1407     mvn     r0, #0                      @ r0<- -1 (default)
1408     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1409     fmstat                              @ export status flags
1410     movgt   r0, #1                      @ (greater than) r1<- 1
1411     moveq   r0, #0                      @ (equal) r1<- 0
1412     b       .LOP_CMPL_DOUBLE_finish          @ argh
1413
1414
1415 /* ------------------------------ */
1416     .balign 64
1417 .L_OP_CMPG_DOUBLE: /* 0x30 */
1418 /* File: arm-vfp/OP_CMPG_DOUBLE.S */
1419     /*
1420      * Compare two floating-point values.  Puts 0, 1, or -1 into the
1421      * destination register based on the results of the comparison.
1422      *
1423      * int compare(x, y) {
1424      *     if (x == y) {
1425      *         return 0;
1426      *     } else if (x < y) {
1427      *         return -1;
1428      *     } else if (x > y) {
1429      *         return 1;
1430      *     } else {
1431      *         return 1;
1432      *     }
1433      * }
1434      */
1435     /* op vAA, vBB, vCC */
1436     FETCH(r0, 1)                        @ r0<- CCBB
1437     mov     r9, rINST, lsr #8           @ r9<- AA
1438     and     r2, r0, #255                @ r2<- BB
1439     mov     r3, r0, lsr #8              @ r3<- CC
1440     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1441     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1442     fldd    d0, [r2]                    @ d0<- vBB
1443     fldd    d1, [r3]                    @ d1<- vCC
1444     fcmped  d0, d1                      @ compare (vBB, vCC)
1445     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1446     mov     r0, #1                      @ r0<- 1 (default)
1447     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1448     fmstat                              @ export status flags
1449     mvnmi   r0, #0                      @ (less than) r1<- -1
1450     moveq   r0, #0                      @ (equal) r1<- 0
1451     b       .LOP_CMPG_DOUBLE_finish          @ argh
1452
1453
1454 /* ------------------------------ */
1455     .balign 64
1456 .L_OP_CMP_LONG: /* 0x31 */
1457 /* File: armv5te/OP_CMP_LONG.S */
1458     /*
1459      * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
1460      * register based on the results of the comparison.
1461      *
1462      * We load the full values with LDM, but in practice many values could
1463      * be resolved by only looking at the high word.  This could be made
1464      * faster or slower by splitting the LDM into a pair of LDRs.
1465      *
1466      * If we just wanted to set condition flags, we could do this:
1467      *  subs    ip, r0, r2
1468      *  sbcs    ip, r1, r3
1469      *  subeqs  ip, r0, r2
1470      * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
1471      * integer value, which we can do with 2 conditional mov/mvn instructions
1472      * (set 1, set -1; if they're equal we already have 0 in ip), giving
1473      * us a constant 5-cycle path plus a branch at the end to the
1474      * instruction epilogue code.  The multi-compare approach below needs
1475      * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
1476      * in the worst case (the 64-bit values are equal).
1477      */
1478     /* cmp-long vAA, vBB, vCC */
1479     FETCH(r0, 1)                        @ r0<- CCBB
1480     mov     r9, rINST, lsr #8           @ r9<- AA
1481     and     r2, r0, #255                @ r2<- BB
1482     mov     r3, r0, lsr #8              @ r3<- CC
1483     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
1484     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
1485     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1486     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
1487     cmp     r1, r3                      @ compare (vBB+1, vCC+1)
1488     blt     .LOP_CMP_LONG_less            @ signed compare on high part
1489     bgt     .LOP_CMP_LONG_greater
1490     subs    r1, r0, r2                  @ r1<- r0 - r2
1491     bhi     .LOP_CMP_LONG_greater         @ unsigned compare on low part
1492     bne     .LOP_CMP_LONG_less
1493     b       .LOP_CMP_LONG_finish          @ equal; r1 already holds 0
1494
1495 /* ------------------------------ */
1496     .balign 64
1497 .L_OP_IF_EQ: /* 0x32 */
1498 /* File: armv6t2/OP_IF_EQ.S */
1499 /* File: armv6t2/bincmp.S */
1500     /*
1501      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1502      * fragment that specifies the *reverse* comparison to perform, e.g.
1503      * for "if-le" you would use "gt".
1504      *
1505      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1506      */
1507     /* if-cmp vA, vB, +CCCC */
1508     mov     r1, rINST, lsr #12          @ r1<- B
1509     ubfx    r0, rINST, #8, #4           @ r0<- A
1510     GET_VREG(r3, r1)                    @ r3<- vB
1511     GET_VREG(r2, r0)                    @ r2<- vA
1512     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1513     cmp     r2, r3                      @ compare (vA, vB)
1514     bne  1f                      @ branch to 1 if comparison failed
1515     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1516     movs    r9, r9, asl #1              @ convert to bytes, check sign
1517     bmi     common_backwardBranch       @ yes, do periodic checks
1518 1:
1519 #if defined(WITH_JIT)
1520     GET_JIT_PROF_TABLE(r0)
1521     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1522     b        common_testUpdateProfile
1523 #else
1524     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1525     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1526     GOTO_OPCODE(ip)                     @ jump to next instruction
1527 #endif
1528
1529
1530
1531 /* ------------------------------ */
1532     .balign 64
1533 .L_OP_IF_NE: /* 0x33 */
1534 /* File: armv6t2/OP_IF_NE.S */
1535 /* File: armv6t2/bincmp.S */
1536     /*
1537      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1538      * fragment that specifies the *reverse* comparison to perform, e.g.
1539      * for "if-le" you would use "gt".
1540      *
1541      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1542      */
1543     /* if-cmp vA, vB, +CCCC */
1544     mov     r1, rINST, lsr #12          @ r1<- B
1545     ubfx    r0, rINST, #8, #4           @ r0<- A
1546     GET_VREG(r3, r1)                    @ r3<- vB
1547     GET_VREG(r2, r0)                    @ r2<- vA
1548     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1549     cmp     r2, r3                      @ compare (vA, vB)
1550     beq  1f                      @ branch to 1 if comparison failed
1551     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1552     movs    r9, r9, asl #1              @ convert to bytes, check sign
1553     bmi     common_backwardBranch       @ yes, do periodic checks
1554 1:
1555 #if defined(WITH_JIT)
1556     GET_JIT_PROF_TABLE(r0)
1557     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1558     b        common_testUpdateProfile
1559 #else
1560     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1561     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1562     GOTO_OPCODE(ip)                     @ jump to next instruction
1563 #endif
1564
1565
1566
1567 /* ------------------------------ */
1568     .balign 64
1569 .L_OP_IF_LT: /* 0x34 */
1570 /* File: armv6t2/OP_IF_LT.S */
1571 /* File: armv6t2/bincmp.S */
1572     /*
1573      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1574      * fragment that specifies the *reverse* comparison to perform, e.g.
1575      * for "if-le" you would use "gt".
1576      *
1577      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1578      */
1579     /* if-cmp vA, vB, +CCCC */
1580     mov     r1, rINST, lsr #12          @ r1<- B
1581     ubfx    r0, rINST, #8, #4           @ r0<- A
1582     GET_VREG(r3, r1)                    @ r3<- vB
1583     GET_VREG(r2, r0)                    @ r2<- vA
1584     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1585     cmp     r2, r3                      @ compare (vA, vB)
1586     bge  1f                      @ branch to 1 if comparison failed
1587     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1588     movs    r9, r9, asl #1              @ convert to bytes, check sign
1589     bmi     common_backwardBranch       @ yes, do periodic checks
1590 1:
1591 #if defined(WITH_JIT)
1592     GET_JIT_PROF_TABLE(r0)
1593     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1594     b        common_testUpdateProfile
1595 #else
1596     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1597     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1598     GOTO_OPCODE(ip)                     @ jump to next instruction
1599 #endif
1600
1601
1602
1603 /* ------------------------------ */
1604     .balign 64
1605 .L_OP_IF_GE: /* 0x35 */
1606 /* File: armv6t2/OP_IF_GE.S */
1607 /* File: armv6t2/bincmp.S */
1608     /*
1609      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1610      * fragment that specifies the *reverse* comparison to perform, e.g.
1611      * for "if-le" you would use "gt".
1612      *
1613      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1614      */
1615     /* if-cmp vA, vB, +CCCC */
1616     mov     r1, rINST, lsr #12          @ r1<- B
1617     ubfx    r0, rINST, #8, #4           @ r0<- A
1618     GET_VREG(r3, r1)                    @ r3<- vB
1619     GET_VREG(r2, r0)                    @ r2<- vA
1620     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1621     cmp     r2, r3                      @ compare (vA, vB)
1622     blt  1f                      @ branch to 1 if comparison failed
1623     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1624     movs    r9, r9, asl #1              @ convert to bytes, check sign
1625     bmi     common_backwardBranch       @ yes, do periodic checks
1626 1:
1627 #if defined(WITH_JIT)
1628     GET_JIT_PROF_TABLE(r0)
1629     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1630     b        common_testUpdateProfile
1631 #else
1632     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1633     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1634     GOTO_OPCODE(ip)                     @ jump to next instruction
1635 #endif
1636
1637
1638
1639 /* ------------------------------ */
1640     .balign 64
1641 .L_OP_IF_GT: /* 0x36 */
1642 /* File: armv6t2/OP_IF_GT.S */
1643 /* File: armv6t2/bincmp.S */
1644     /*
1645      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1646      * fragment that specifies the *reverse* comparison to perform, e.g.
1647      * for "if-le" you would use "gt".
1648      *
1649      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1650      */
1651     /* if-cmp vA, vB, +CCCC */
1652     mov     r1, rINST, lsr #12          @ r1<- B
1653     ubfx    r0, rINST, #8, #4           @ r0<- A
1654     GET_VREG(r3, r1)                    @ r3<- vB
1655     GET_VREG(r2, r0)                    @ r2<- vA
1656     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1657     cmp     r2, r3                      @ compare (vA, vB)
1658     ble  1f                      @ branch to 1 if comparison failed
1659     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1660     movs    r9, r9, asl #1              @ convert to bytes, check sign
1661     bmi     common_backwardBranch       @ yes, do periodic checks
1662 1:
1663 #if defined(WITH_JIT)
1664     GET_JIT_PROF_TABLE(r0)
1665     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1666     b        common_testUpdateProfile
1667 #else
1668     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1669     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1670     GOTO_OPCODE(ip)                     @ jump to next instruction
1671 #endif
1672
1673
1674
1675 /* ------------------------------ */
1676     .balign 64
1677 .L_OP_IF_LE: /* 0x37 */
1678 /* File: armv6t2/OP_IF_LE.S */
1679 /* File: armv6t2/bincmp.S */
1680     /*
1681      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1682      * fragment that specifies the *reverse* comparison to perform, e.g.
1683      * for "if-le" you would use "gt".
1684      *
1685      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1686      */
1687     /* if-cmp vA, vB, +CCCC */
1688     mov     r1, rINST, lsr #12          @ r1<- B
1689     ubfx    r0, rINST, #8, #4           @ r0<- A
1690     GET_VREG(r3, r1)                    @ r3<- vB
1691     GET_VREG(r2, r0)                    @ r2<- vA
1692     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1693     cmp     r2, r3                      @ compare (vA, vB)
1694     bgt  1f                      @ branch to 1 if comparison failed
1695     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1696     movs    r9, r9, asl #1              @ convert to bytes, check sign
1697     bmi     common_backwardBranch       @ yes, do periodic checks
1698 1:
1699 #if defined(WITH_JIT)
1700     GET_JIT_PROF_TABLE(r0)
1701     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1702     b        common_testUpdateProfile
1703 #else
1704     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1705     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1706     GOTO_OPCODE(ip)                     @ jump to next instruction
1707 #endif
1708
1709
1710
1711 /* ------------------------------ */
1712     .balign 64
1713 .L_OP_IF_EQZ: /* 0x38 */
1714 /* File: armv5te/OP_IF_EQZ.S */
1715 /* File: armv5te/zcmp.S */
1716     /*
1717      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1718      * fragment that specifies the *reverse* comparison to perform, e.g.
1719      * for "if-le" you would use "gt".
1720      *
1721      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1722      */
1723     /* if-cmp vAA, +BBBB */
1724     mov     r0, rINST, lsr #8           @ r0<- AA
1725     GET_VREG(r2, r0)                    @ r2<- vAA
1726     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1727     cmp     r2, #0                      @ compare (vA, 0)
1728     bne  1f                      @ branch to 1 if comparison failed
1729     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1730     movs    r9, r9, asl #1              @ convert to bytes, check sign
1731     bmi     common_backwardBranch       @ backward branch, do periodic checks
1732 1:
1733 #if defined(WITH_JIT)
1734     GET_JIT_PROF_TABLE(r0)
1735     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1736     cmp     r0,#0
1737     bne     common_updateProfile
1738     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1739     GOTO_OPCODE(ip)                     @ jump to next instruction
1740 #else
1741     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1742     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1743     GOTO_OPCODE(ip)                     @ jump to next instruction
1744 #endif
1745
1746
1747
1748 /* ------------------------------ */
1749     .balign 64
1750 .L_OP_IF_NEZ: /* 0x39 */
1751 /* File: armv5te/OP_IF_NEZ.S */
1752 /* File: armv5te/zcmp.S */
1753     /*
1754      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1755      * fragment that specifies the *reverse* comparison to perform, e.g.
1756      * for "if-le" you would use "gt".
1757      *
1758      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1759      */
1760     /* if-cmp vAA, +BBBB */
1761     mov     r0, rINST, lsr #8           @ r0<- AA
1762     GET_VREG(r2, r0)                    @ r2<- vAA
1763     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1764     cmp     r2, #0                      @ compare (vA, 0)
1765     beq  1f                      @ branch to 1 if comparison failed
1766     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1767     movs    r9, r9, asl #1              @ convert to bytes, check sign
1768     bmi     common_backwardBranch       @ backward branch, do periodic checks
1769 1:
1770 #if defined(WITH_JIT)
1771     GET_JIT_PROF_TABLE(r0)
1772     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1773     cmp     r0,#0
1774     bne     common_updateProfile
1775     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1776     GOTO_OPCODE(ip)                     @ jump to next instruction
1777 #else
1778     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1779     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1780     GOTO_OPCODE(ip)                     @ jump to next instruction
1781 #endif
1782
1783
1784
1785 /* ------------------------------ */
1786     .balign 64
1787 .L_OP_IF_LTZ: /* 0x3a */
1788 /* File: armv5te/OP_IF_LTZ.S */
1789 /* File: armv5te/zcmp.S */
1790     /*
1791      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1792      * fragment that specifies the *reverse* comparison to perform, e.g.
1793      * for "if-le" you would use "gt".
1794      *
1795      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1796      */
1797     /* if-cmp vAA, +BBBB */
1798     mov     r0, rINST, lsr #8           @ r0<- AA
1799     GET_VREG(r2, r0)                    @ r2<- vAA
1800     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1801     cmp     r2, #0                      @ compare (vA, 0)
1802     bge  1f                      @ branch to 1 if comparison failed
1803     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1804     movs    r9, r9, asl #1              @ convert to bytes, check sign
1805     bmi     common_backwardBranch       @ backward branch, do periodic checks
1806 1:
1807 #if defined(WITH_JIT)
1808     GET_JIT_PROF_TABLE(r0)
1809     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1810     cmp     r0,#0
1811     bne     common_updateProfile
1812     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1813     GOTO_OPCODE(ip)                     @ jump to next instruction
1814 #else
1815     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1816     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1817     GOTO_OPCODE(ip)                     @ jump to next instruction
1818 #endif
1819
1820
1821
1822 /* ------------------------------ */
1823     .balign 64
1824 .L_OP_IF_GEZ: /* 0x3b */
1825 /* File: armv5te/OP_IF_GEZ.S */
1826 /* File: armv5te/zcmp.S */
1827     /*
1828      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1829      * fragment that specifies the *reverse* comparison to perform, e.g.
1830      * for "if-le" you would use "gt".
1831      *
1832      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1833      */
1834     /* if-cmp vAA, +BBBB */
1835     mov     r0, rINST, lsr #8           @ r0<- AA
1836     GET_VREG(r2, r0)                    @ r2<- vAA
1837     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1838     cmp     r2, #0                      @ compare (vA, 0)
1839     blt  1f                      @ branch to 1 if comparison failed
1840     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1841     movs    r9, r9, asl #1              @ convert to bytes, check sign
1842     bmi     common_backwardBranch       @ backward branch, do periodic checks
1843 1:
1844 #if defined(WITH_JIT)
1845     GET_JIT_PROF_TABLE(r0)
1846     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1847     cmp     r0,#0
1848     bne     common_updateProfile
1849     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1850     GOTO_OPCODE(ip)                     @ jump to next instruction
1851 #else
1852     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1853     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1854     GOTO_OPCODE(ip)                     @ jump to next instruction
1855 #endif
1856
1857
1858
1859 /* ------------------------------ */
1860     .balign 64
1861 .L_OP_IF_GTZ: /* 0x3c */
1862 /* File: armv5te/OP_IF_GTZ.S */
1863 /* File: armv5te/zcmp.S */
1864     /*
1865      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1866      * fragment that specifies the *reverse* comparison to perform, e.g.
1867      * for "if-le" you would use "gt".
1868      *
1869      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1870      */
1871     /* if-cmp vAA, +BBBB */
1872     mov     r0, rINST, lsr #8           @ r0<- AA
1873     GET_VREG(r2, r0)                    @ r2<- vAA
1874     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1875     cmp     r2, #0                      @ compare (vA, 0)
1876     ble  1f                      @ branch to 1 if comparison failed
1877     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1878     movs    r9, r9, asl #1              @ convert to bytes, check sign
1879     bmi     common_backwardBranch       @ backward branch, do periodic checks
1880 1:
1881 #if defined(WITH_JIT)
1882     GET_JIT_PROF_TABLE(r0)
1883     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1884     cmp     r0,#0
1885     bne     common_updateProfile
1886     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1887     GOTO_OPCODE(ip)                     @ jump to next instruction
1888 #else
1889     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1890     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1891     GOTO_OPCODE(ip)                     @ jump to next instruction
1892 #endif
1893
1894
1895
1896 /* ------------------------------ */
1897     .balign 64
1898 .L_OP_IF_LEZ: /* 0x3d */
1899 /* File: armv5te/OP_IF_LEZ.S */
1900 /* File: armv5te/zcmp.S */
1901     /*
1902      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1903      * fragment that specifies the *reverse* comparison to perform, e.g.
1904      * for "if-le" you would use "gt".
1905      *
1906      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1907      */
1908     /* if-cmp vAA, +BBBB */
1909     mov     r0, rINST, lsr #8           @ r0<- AA
1910     GET_VREG(r2, r0)                    @ r2<- vAA
1911     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1912     cmp     r2, #0                      @ compare (vA, 0)
1913     bgt  1f                      @ branch to 1 if comparison failed
1914     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1915     movs    r9, r9, asl #1              @ convert to bytes, check sign
1916     bmi     common_backwardBranch       @ backward branch, do periodic checks
1917 1:
1918 #if defined(WITH_JIT)
1919     GET_JIT_PROF_TABLE(r0)
1920     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1921     cmp     r0,#0
1922     bne     common_updateProfile
1923     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1924     GOTO_OPCODE(ip)                     @ jump to next instruction
1925 #else
1926     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1927     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1928     GOTO_OPCODE(ip)                     @ jump to next instruction
1929 #endif
1930
1931
1932
1933 /* ------------------------------ */
1934     .balign 64
1935 .L_OP_UNUSED_3E: /* 0x3e */
1936 /* File: armv5te/OP_UNUSED_3E.S */
1937 /* File: armv5te/unused.S */
1938     bl      common_abort
1939
1940
1941
1942 /* ------------------------------ */
1943     .balign 64
1944 .L_OP_UNUSED_3F: /* 0x3f */
1945 /* File: armv5te/OP_UNUSED_3F.S */
1946 /* File: armv5te/unused.S */
1947     bl      common_abort
1948
1949
1950
1951 /* ------------------------------ */
1952     .balign 64
1953 .L_OP_UNUSED_40: /* 0x40 */
1954 /* File: armv5te/OP_UNUSED_40.S */
1955 /* File: armv5te/unused.S */
1956     bl      common_abort
1957
1958
1959
1960 /* ------------------------------ */
1961     .balign 64
1962 .L_OP_UNUSED_41: /* 0x41 */
1963 /* File: armv5te/OP_UNUSED_41.S */
1964 /* File: armv5te/unused.S */
1965     bl      common_abort
1966
1967
1968
1969 /* ------------------------------ */
1970     .balign 64
1971 .L_OP_UNUSED_42: /* 0x42 */
1972 /* File: armv5te/OP_UNUSED_42.S */
1973 /* File: armv5te/unused.S */
1974     bl      common_abort
1975
1976
1977
1978 /* ------------------------------ */
1979     .balign 64
1980 .L_OP_UNUSED_43: /* 0x43 */
1981 /* File: armv5te/OP_UNUSED_43.S */
1982 /* File: armv5te/unused.S */
1983     bl      common_abort
1984
1985
1986
1987 /* ------------------------------ */
1988     .balign 64
1989 .L_OP_AGET: /* 0x44 */
1990 /* File: armv5te/OP_AGET.S */
1991     /*
1992      * Array get, 32 bits or less.  vAA <- vBB[vCC].
1993      *
1994      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
1995      * instructions.  We use a pair of FETCH_Bs instead.
1996      *
1997      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1998      */
1999     /* op vAA, vBB, vCC */
2000     FETCH_B(r2, 1, 0)                   @ r2<- BB
2001     mov     r9, rINST, lsr #8           @ r9<- AA
2002     FETCH_B(r3, 1, 1)                   @ r3<- CC
2003     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2004     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2005     cmp     r0, #0                      @ null array object?
2006     beq     common_errNullObject        @ yes, bail
2007     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2008     add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2009     cmp     r1, r3                      @ compare unsigned index, length
2010     bcs     common_errArrayIndex        @ index >= length, bail
2011     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2012     ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2013     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2014     SET_VREG(r2, r9)                    @ vAA<- r2
2015     GOTO_OPCODE(ip)                     @ jump to next instruction
2016
2017
2018 /* ------------------------------ */
2019     .balign 64
2020 .L_OP_AGET_WIDE: /* 0x45 */
2021 /* File: armv5te/OP_AGET_WIDE.S */
2022     /*
2023      * Array get, 64 bits.  vAA <- vBB[vCC].
2024      *
2025      * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD.
2026      */
2027     /* aget-wide vAA, vBB, vCC */
2028     FETCH(r0, 1)                        @ r0<- CCBB
2029     mov     r9, rINST, lsr #8           @ r9<- AA
2030     and     r2, r0, #255                @ r2<- BB
2031     mov     r3, r0, lsr #8              @ r3<- CC
2032     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2033     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2034     cmp     r0, #0                      @ null array object?
2035     beq     common_errNullObject        @ yes, bail
2036     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2037     add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2038     cmp     r1, r3                      @ compare unsigned index, length
2039     bcc     .LOP_AGET_WIDE_finish          @ okay, continue below
2040     b       common_errArrayIndex        @ index >= length, bail
2041     @ May want to swap the order of these two branches depending on how the
2042     @ branch prediction (if any) handles conditional forward branches vs.
2043     @ unconditional forward branches.
2044
2045 /* ------------------------------ */
2046     .balign 64
2047 .L_OP_AGET_OBJECT: /* 0x46 */
2048 /* File: armv5te/OP_AGET_OBJECT.S */
2049 /* File: armv5te/OP_AGET.S */
2050     /*
2051      * Array get, 32 bits or less.  vAA <- vBB[vCC].
2052      *
2053      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2054      * instructions.  We use a pair of FETCH_Bs instead.
2055      *
2056      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2057      */
2058     /* op vAA, vBB, vCC */
2059     FETCH_B(r2, 1, 0)                   @ r2<- BB
2060     mov     r9, rINST, lsr #8           @ r9<- AA
2061     FETCH_B(r3, 1, 1)                   @ r3<- CC
2062     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2063     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2064     cmp     r0, #0                      @ null array object?
2065     beq     common_errNullObject        @ yes, bail
2066     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2067     add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2068     cmp     r1, r3                      @ compare unsigned index, length
2069     bcs     common_errArrayIndex        @ index >= length, bail
2070     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2071     ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2072     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2073     SET_VREG(r2, r9)                    @ vAA<- r2
2074     GOTO_OPCODE(ip)                     @ jump to next instruction
2075
2076
2077
2078 /* ------------------------------ */
2079     .balign 64
2080 .L_OP_AGET_BOOLEAN: /* 0x47 */
2081 /* File: armv5te/OP_AGET_BOOLEAN.S */
2082 /* File: armv5te/OP_AGET.S */
2083     /*
2084      * Array get, 32 bits or less.  vAA <- vBB[vCC].
2085      *
2086      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2087      * instructions.  We use a pair of FETCH_Bs instead.
2088      *
2089      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2090      */
2091     /* op vAA, vBB, vCC */
2092     FETCH_B(r2, 1, 0)                   @ r2<- BB
2093     mov     r9, rINST, lsr #8           @ r9<- AA
2094     FETCH_B(r3, 1, 1)                   @ r3<- CC
2095     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2096     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2097     cmp     r0, #0                      @ null array object?
2098     beq     common_errNullObject        @ yes, bail
2099     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2100     add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2101     cmp     r1, r3                      @ compare unsigned index, length
2102     bcs     common_errArrayIndex        @ index >= length, bail
2103     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2104     ldrb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2105     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2106     SET_VREG(r2, r9)                    @ vAA<- r2
2107     GOTO_OPCODE(ip)                     @ jump to next instruction
2108
2109
2110
2111 /* ------------------------------ */
2112     .balign 64
2113 .L_OP_AGET_BYTE: /* 0x48 */
2114 /* File: armv5te/OP_AGET_BYTE.S */
2115 /* File: armv5te/OP_AGET.S */
2116     /*
2117      * Array get, 32 bits or less.  vAA <- vBB[vCC].
2118      *
2119      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2120      * instructions.  We use a pair of FETCH_Bs instead.
2121      *
2122      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2123      */
2124     /* op vAA, vBB, vCC */
2125     FETCH_B(r2, 1, 0)                   @ r2<- BB
2126     mov     r9, rINST, lsr #8           @ r9<- AA
2127     FETCH_B(r3, 1, 1)                   @ r3<- CC
2128     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2129     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2130     cmp     r0, #0                      @ null array object?
2131     beq     common_errNullObject        @ yes, bail
2132     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2133     add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2134     cmp     r1, r3                      @ compare unsigned index, length
2135     bcs     common_errArrayIndex        @ index >= length, bail
2136     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2137     ldrsb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2138     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2139     SET_VREG(r2, r9)                    @ vAA<- r2
2140     GOTO_OPCODE(ip)                     @ jump to next instruction
2141
2142
2143
2144 /* ------------------------------ */
2145     .balign 64
2146 .L_OP_AGET_CHAR: /* 0x49 */
2147 /* File: armv5te/OP_AGET_CHAR.S */
2148 /* File: armv5te/OP_AGET.S */
2149     /*
2150      * Array get, 32 bits or less.  vAA <- vBB[vCC].
2151      *
2152      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2153      * instructions.  We use a pair of FETCH_Bs instead.
2154      *
2155      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2156      */
2157     /* op vAA, vBB, vCC */
2158     FETCH_B(r2, 1, 0)                   @ r2<- BB
2159     mov     r9, rINST, lsr #8           @ r9<- AA
2160     FETCH_B(r3, 1, 1)                   @ r3<- CC
2161     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2162     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2163     cmp     r0, #0                      @ null array object?
2164     beq     common_errNullObject        @ yes, bail
2165     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2166     add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2167     cmp     r1, r3                      @ compare unsigned index, length
2168     bcs     common_errArrayIndex        @ index >= length, bail
2169     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2170     ldrh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2171     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2172     SET_VREG(r2, r9)                    @ vAA<- r2
2173     GOTO_OPCODE(ip)                     @ jump to next instruction
2174
2175
2176
2177 /* ------------------------------ */
2178     .balign 64
2179 .L_OP_AGET_SHORT: /* 0x4a */
2180 /* File: armv5te/OP_AGET_SHORT.S */
2181 /* File: armv5te/OP_AGET.S */
2182     /*
2183      * Array get, 32 bits or less.  vAA <- vBB[vCC].
2184      *
2185      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2186      * instructions.  We use a pair of FETCH_Bs instead.
2187      *
2188      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2189      */
2190     /* op vAA, vBB, vCC */
2191     FETCH_B(r2, 1, 0)                   @ r2<- BB
2192     mov     r9, rINST, lsr #8           @ r9<- AA
2193     FETCH_B(r3, 1, 1)                   @ r3<- CC
2194     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2195     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2196     cmp     r0, #0                      @ null array object?
2197     beq     common_errNullObject        @ yes, bail
2198     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2199     add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2200     cmp     r1, r3                      @ compare unsigned index, length
2201     bcs     common_errArrayIndex        @ index >= length, bail
2202     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2203     ldrsh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2204     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2205     SET_VREG(r2, r9)                    @ vAA<- r2
2206     GOTO_OPCODE(ip)                     @ jump to next instruction
2207
2208
2209
2210 /* ------------------------------ */
2211     .balign 64
2212 .L_OP_APUT: /* 0x4b */
2213 /* File: armv5te/OP_APUT.S */
2214     /*
2215      * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2216      *
2217      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2218      * instructions.  We use a pair of FETCH_Bs instead.
2219      *
2220      * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2221      */
2222     /* op vAA, vBB, vCC */
2223     FETCH_B(r2, 1, 0)                   @ r2<- BB
2224     mov     r9, rINST, lsr #8           @ r9<- AA
2225     FETCH_B(r3, 1, 1)                   @ r3<- CC
2226     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2227     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2228     cmp     r0, #0                      @ null array object?
2229     beq     common_errNullObject        @ yes, bail
2230     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2231     add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2232     cmp     r1, r3                      @ compare unsigned index, length
2233     bcs     common_errArrayIndex        @ index >= length, bail
2234     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2235     GET_VREG(r2, r9)                    @ r2<- vAA
2236     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2237     str  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2238     GOTO_OPCODE(ip)                     @ jump to next instruction
2239
2240
2241 /* ------------------------------ */
2242     .balign 64
2243 .L_OP_APUT_WIDE: /* 0x4c */
2244 /* File: armv5te/OP_APUT_WIDE.S */
2245     /*
2246      * Array put, 64 bits.  vBB[vCC] <- vAA.
2247      *
2248      * Arrays of long/double are 64-bit aligned, so it's okay to use STRD.
2249      */
2250     /* aput-wide vAA, vBB, vCC */
2251     FETCH(r0, 1)                        @ r0<- CCBB
2252     mov     r9, rINST, lsr #8           @ r9<- AA
2253     and     r2, r0, #255                @ r2<- BB
2254     mov     r3, r0, lsr #8              @ r3<- CC
2255     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2256     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2257     cmp     r0, #0                      @ null array object?
2258     beq     common_errNullObject        @ yes, bail
2259     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2260     add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2261     cmp     r1, r3                      @ compare unsigned index, length
2262     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2263     bcc     .LOP_APUT_WIDE_finish          @ okay, continue below
2264     b       common_errArrayIndex        @ index >= length, bail
2265     @ May want to swap the order of these two branches depending on how the
2266     @ branch prediction (if any) handles conditional forward branches vs.
2267     @ unconditional forward branches.
2268
2269 /* ------------------------------ */
2270     .balign 64
2271 .L_OP_APUT_OBJECT: /* 0x4d */
2272 /* File: armv5te/OP_APUT_OBJECT.S */
2273     /*
2274      * Store an object into an array.  vBB[vCC] <- vAA.
2275      *
2276      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2277      * instructions.  We use a pair of FETCH_Bs instead.
2278      */
2279     /* op vAA, vBB, vCC */
2280     FETCH(r0, 1)                        @ r0<- CCBB
2281     mov     r9, rINST, lsr #8           @ r9<- AA
2282     and     r2, r0, #255                @ r2<- BB
2283     mov     r3, r0, lsr #8              @ r3<- CC
2284     GET_VREG(r1, r2)                    @ r1<- vBB (array object)
2285     GET_VREG(r0, r3)                    @ r0<- vCC (requested index)
2286     cmp     r1, #0                      @ null array object?
2287     GET_VREG(r9, r9)                    @ r9<- vAA
2288     beq     common_errNullObject        @ yes, bail
2289     ldr     r3, [r1, #offArrayObject_length]    @ r3<- arrayObj->length
2290     add     r10, r1, r0, lsl #2         @ r10<- arrayObj + index*width
2291     cmp     r0, r3                      @ compare unsigned index, length
2292     bcc     .LOP_APUT_OBJECT_finish          @ we're okay, continue on
2293     b       common_errArrayIndex        @ index >= length, bail
2294
2295
2296 /* ------------------------------ */
2297     .balign 64
2298 .L_OP_APUT_BOOLEAN: /* 0x4e */
2299 /* File: armv5te/OP_APUT_BOOLEAN.S */
2300 /* File: armv5te/OP_APUT.S */
2301     /*
2302      * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2303      *
2304      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2305      * instructions.  We use a pair of FETCH_Bs instead.
2306      *
2307      * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2308      */
2309     /* op vAA, vBB, vCC */
2310     FETCH_B(r2, 1, 0)                   @ r2<- BB
2311     mov     r9, rINST, lsr #8           @ r9<- AA
2312     FETCH_B(r3, 1, 1)                   @ r3<- CC
2313     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2314     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2315     cmp     r0, #0                      @ null array object?
2316     beq     common_errNullObject        @ yes, bail
2317     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2318     add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2319     cmp     r1, r3                      @ compare unsigned index, length
2320     bcs     common_errArrayIndex        @ index >= length, bail
2321     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2322     GET_VREG(r2, r9)                    @ r2<- vAA
2323     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2324     strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2325     GOTO_OPCODE(ip)                     @ jump to next instruction
2326
2327
2328
2329 /* ------------------------------ */
2330     .balign 64
2331 .L_OP_APUT_BYTE: /* 0x4f */
2332 /* File: armv5te/OP_APUT_BYTE.S */
2333 /* File: armv5te/OP_APUT.S */
2334     /*
2335      * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2336      *
2337      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2338      * instructions.  We use a pair of FETCH_Bs instead.
2339      *
2340      * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2341      */
2342     /* op vAA, vBB, vCC */
2343     FETCH_B(r2, 1, 0)                   @ r2<- BB
2344     mov     r9, rINST, lsr #8           @ r9<- AA
2345     FETCH_B(r3, 1, 1)                   @ r3<- CC
2346     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2347     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2348     cmp     r0, #0                      @ null array object?
2349     beq     common_errNullObject        @ yes, bail
2350     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2351     add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2352     cmp     r1, r3                      @ compare unsigned index, length
2353     bcs     common_errArrayIndex        @ index >= length, bail
2354     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2355     GET_VREG(r2, r9)                    @ r2<- vAA
2356     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2357     strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2358     GOTO_OPCODE(ip)                     @ jump to next instruction
2359
2360
2361
2362 /* ------------------------------ */
2363     .balign 64
2364 .L_OP_APUT_CHAR: /* 0x50 */
2365 /* File: armv5te/OP_APUT_CHAR.S */
2366 /* File: armv5te/OP_APUT.S */
2367     /*
2368      * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2369      *
2370      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2371      * instructions.  We use a pair of FETCH_Bs instead.
2372      *
2373      * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2374      */
2375     /* op vAA, vBB, vCC */
2376     FETCH_B(r2, 1, 0)                   @ r2<- BB
2377     mov     r9, rINST, lsr #8           @ r9<- AA
2378     FETCH_B(r3, 1, 1)                   @ r3<- CC
2379     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2380     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2381     cmp     r0, #0                      @ null array object?
2382     beq     common_errNullObject        @ yes, bail
2383     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2384     add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2385     cmp     r1, r3                      @ compare unsigned index, length
2386     bcs     common_errArrayIndex        @ index >= length, bail
2387     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2388     GET_VREG(r2, r9)                    @ r2<- vAA
2389     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2390     strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2391     GOTO_OPCODE(ip)                     @ jump to next instruction
2392
2393
2394
2395 /* ------------------------------ */
2396     .balign 64
2397 .L_OP_APUT_SHORT: /* 0x51 */
2398 /* File: armv5te/OP_APUT_SHORT.S */
2399 /* File: armv5te/OP_APUT.S */
2400     /*
2401      * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2402      *
2403      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2404      * instructions.  We use a pair of FETCH_Bs instead.
2405      *
2406      * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2407      */
2408     /* op vAA, vBB, vCC */
2409     FETCH_B(r2, 1, 0)                   @ r2<- BB
2410     mov     r9, rINST, lsr #8           @ r9<- AA
2411     FETCH_B(r3, 1, 1)                   @ r3<- CC
2412     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2413     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2414     cmp     r0, #0                      @ null array object?
2415     beq     common_errNullObject        @ yes, bail
2416     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2417     add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2418     cmp     r1, r3                      @ compare unsigned index, length
2419     bcs     common_errArrayIndex        @ index >= length, bail
2420     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2421     GET_VREG(r2, r9)                    @ r2<- vAA
2422     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2423     strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2424     GOTO_OPCODE(ip)                     @ jump to next instruction
2425
2426
2427
2428 /* ------------------------------ */
2429     .balign 64
2430 .L_OP_IGET: /* 0x52 */
2431 /* File: armv6t2/OP_IGET.S */
2432     /*
2433      * General 32-bit instance field get.
2434      *
2435      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2436      */
2437     /* op vA, vB, field@CCCC */
2438     mov     r0, rINST, lsr #12          @ r0<- B
2439     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2440     FETCH(r1, 1)                        @ r1<- field ref CCCC
2441     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2442     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2443     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2444     cmp     r0, #0                      @ is resolved entry null?
2445     bne     .LOP_IGET_finish          @ no, already resolved
2446 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2447     EXPORT_PC()                         @ resolve() could throw
2448     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2449     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2450     cmp     r0, #0
2451     bne     .LOP_IGET_finish
2452     b       common_exceptionThrown
2453
2454 /* ------------------------------ */
2455     .balign 64
2456 .L_OP_IGET_WIDE: /* 0x53 */
2457 /* File: armv6t2/OP_IGET_WIDE.S */
2458     /*
2459      * Wide 32-bit instance field get.
2460      */
2461     /* iget-wide vA, vB, field@CCCC */
2462     mov     r0, rINST, lsr #12          @ r0<- B
2463     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2464     FETCH(r1, 1)                        @ r1<- field ref CCCC
2465     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2466     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2467     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2468     cmp     r0, #0                      @ is resolved entry null?
2469     bne     .LOP_IGET_WIDE_finish          @ no, already resolved
2470 8:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2471     EXPORT_PC()                         @ resolve() could throw
2472     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2473     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2474     cmp     r0, #0
2475     bne     .LOP_IGET_WIDE_finish
2476     b       common_exceptionThrown
2477
2478 /* ------------------------------ */
2479     .balign 64
2480 .L_OP_IGET_OBJECT: /* 0x54 */
2481 /* File: armv5te/OP_IGET_OBJECT.S */
2482 /* File: armv5te/OP_IGET.S */
2483     /*
2484      * General 32-bit instance field get.
2485      *
2486      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2487      */
2488     /* op vA, vB, field@CCCC */
2489     mov     r0, rINST, lsr #12          @ r0<- B
2490     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2491     FETCH(r1, 1)                        @ r1<- field ref CCCC
2492     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2493     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2494     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2495     cmp     r0, #0                      @ is resolved entry null?
2496     bne     .LOP_IGET_OBJECT_finish          @ no, already resolved
2497 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2498     EXPORT_PC()                         @ resolve() could throw
2499     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2500     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2501     cmp     r0, #0
2502     bne     .LOP_IGET_OBJECT_finish
2503     b       common_exceptionThrown
2504
2505
2506 /* ------------------------------ */
2507     .balign 64
2508 .L_OP_IGET_BOOLEAN: /* 0x55 */
2509 /* File: armv5te/OP_IGET_BOOLEAN.S */
2510 @include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" }
2511 /* File: armv5te/OP_IGET.S */
2512     /*
2513      * General 32-bit instance field get.
2514      *
2515      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2516      */
2517     /* op vA, vB, field@CCCC */
2518     mov     r0, rINST, lsr #12          @ r0<- B
2519     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2520     FETCH(r1, 1)                        @ r1<- field ref CCCC
2521     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2522     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2523     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2524     cmp     r0, #0                      @ is resolved entry null?
2525     bne     .LOP_IGET_BOOLEAN_finish          @ no, already resolved
2526 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2527     EXPORT_PC()                         @ resolve() could throw
2528     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2529     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2530     cmp     r0, #0
2531     bne     .LOP_IGET_BOOLEAN_finish
2532     b       common_exceptionThrown
2533
2534
2535 /* ------------------------------ */
2536     .balign 64
2537 .L_OP_IGET_BYTE: /* 0x56 */
2538 /* File: armv5te/OP_IGET_BYTE.S */
2539 @include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" }
2540 /* File: armv5te/OP_IGET.S */
2541     /*
2542      * General 32-bit instance field get.
2543      *
2544      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2545      */
2546     /* op vA, vB, field@CCCC */
2547     mov     r0, rINST, lsr #12          @ r0<- B
2548     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2549     FETCH(r1, 1)                        @ r1<- field ref CCCC
2550     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2551     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2552     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2553     cmp     r0, #0                      @ is resolved entry null?
2554     bne     .LOP_IGET_BYTE_finish          @ no, already resolved
2555 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2556     EXPORT_PC()                         @ resolve() could throw
2557     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2558     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2559     cmp     r0, #0
2560     bne     .LOP_IGET_BYTE_finish
2561     b       common_exceptionThrown
2562
2563
2564 /* ------------------------------ */
2565     .balign 64
2566 .L_OP_IGET_CHAR: /* 0x57 */
2567 /* File: armv5te/OP_IGET_CHAR.S */
2568 @include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" }
2569 /* File: armv5te/OP_IGET.S */
2570     /*
2571      * General 32-bit instance field get.
2572      *
2573      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2574      */
2575     /* op vA, vB, field@CCCC */
2576     mov     r0, rINST, lsr #12          @ r0<- B
2577     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2578     FETCH(r1, 1)                        @ r1<- field ref CCCC
2579     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2580     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2581     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2582     cmp     r0, #0                      @ is resolved entry null?
2583     bne     .LOP_IGET_CHAR_finish          @ no, already resolved
2584 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2585     EXPORT_PC()                         @ resolve() could throw
2586     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2587     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2588     cmp     r0, #0
2589     bne     .LOP_IGET_CHAR_finish
2590     b       common_exceptionThrown
2591
2592
2593 /* ------------------------------ */
2594     .balign 64
2595 .L_OP_IGET_SHORT: /* 0x58 */
2596 /* File: armv5te/OP_IGET_SHORT.S */
2597 @include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" }
2598 /* File: armv5te/OP_IGET.S */
2599     /*
2600      * General 32-bit instance field get.
2601      *
2602      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2603      */
2604     /* op 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<- pDvmDex->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_IGET_SHORT_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
2618     bne     .LOP_IGET_SHORT_finish
2619     b       common_exceptionThrown
2620
2621
2622 /* ------------------------------ */
2623     .balign 64
2624 .L_OP_IPUT: /* 0x59 */
2625 /* File: armv6t2/OP_IPUT.S */
2626     /*
2627      * General 32-bit instance field put.
2628      *
2629      * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2630      */
2631     /* op vA, vB, field@CCCC */
2632     mov     r0, rINST, lsr #12          @ r0<- B
2633     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2634     FETCH(r1, 1)                        @ r1<- field ref CCCC
2635     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2636     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2637     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2638     cmp     r0, #0                      @ is resolved entry null?
2639     bne     .LOP_IPUT_finish          @ no, already resolved
2640 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2641     EXPORT_PC()                         @ resolve() could throw
2642     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2643     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2644     cmp     r0, #0                      @ success?
2645     bne     .LOP_IPUT_finish          @ yes, finish up
2646     b       common_exceptionThrown
2647
2648 /* ------------------------------ */
2649     .balign 64
2650 .L_OP_IPUT_WIDE: /* 0x5a */
2651 /* File: armv6t2/OP_IPUT_WIDE.S */
2652     /* iput-wide vA, vB, field@CCCC */
2653     mov     r0, rINST, lsr #12          @ r0<- B
2654     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2655     FETCH(r1, 1)                        @ r1<- field ref CCCC
2656     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2657     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2658     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2659     cmp     r0, #0                      @ is resolved entry null?
2660     bne     .LOP_IPUT_WIDE_finish          @ no, already resolved
2661 8:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2662     EXPORT_PC()                         @ resolve() could throw
2663     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2664     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2665     cmp     r0, #0                      @ success?
2666     bne     .LOP_IPUT_WIDE_finish          @ yes, finish up
2667     b       common_exceptionThrown
2668
2669 /* ------------------------------ */
2670     .balign 64
2671 .L_OP_IPUT_OBJECT: /* 0x5b */
2672 /* File: armv5te/OP_IPUT_OBJECT.S */
2673 /* File: armv5te/OP_IPUT.S */
2674     /*
2675      * General 32-bit instance field put.
2676      *
2677      * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2678      */
2679     /* op vA, vB, field@CCCC */
2680     mov     r0, rINST, lsr #12          @ r0<- B
2681     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2682     FETCH(r1, 1)                        @ r1<- field ref CCCC
2683     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2684     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2685     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2686     cmp     r0, #0                      @ is resolved entry null?
2687     bne     .LOP_IPUT_OBJECT_finish          @ no, already resolved
2688 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2689     EXPORT_PC()                         @ resolve() could throw
2690     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2691     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2692     cmp     r0, #0                      @ success?
2693     bne     .LOP_IPUT_OBJECT_finish          @ yes, finish up
2694     b       common_exceptionThrown
2695
2696
2697 /* ------------------------------ */
2698     .balign 64
2699 .L_OP_IPUT_BOOLEAN: /* 0x5c */
2700 /* File: armv5te/OP_IPUT_BOOLEAN.S */
2701 @include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" }
2702 /* File: armv5te/OP_IPUT.S */
2703     /*
2704      * General 32-bit instance field put.
2705      *
2706      * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2707      */
2708     /* op vA, vB, field@CCCC */
2709     mov     r0, rINST, lsr #12          @ r0<- B
2710     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2711     FETCH(r1, 1)                        @ r1<- field ref CCCC
2712     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2713     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2714     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2715     cmp     r0, #0                      @ is resolved entry null?
2716     bne     .LOP_IPUT_BOOLEAN_finish          @ no, already resolved
2717 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2718     EXPORT_PC()                         @ resolve() could throw
2719     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2720     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2721     cmp     r0, #0                      @ success?
2722     bne     .LOP_IPUT_BOOLEAN_finish          @ yes, finish up
2723     b       common_exceptionThrown
2724
2725
2726 /* ------------------------------ */
2727     .balign 64
2728 .L_OP_IPUT_BYTE: /* 0x5d */
2729 /* File: armv5te/OP_IPUT_BYTE.S */
2730 @include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" }
2731 /* File: armv5te/OP_IPUT.S */
2732     /*
2733      * General 32-bit instance field put.
2734      *
2735      * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2736      */
2737     /* op vA, vB, field@CCCC */
2738     mov     r0, rINST, lsr #12          @ r0<- B
2739     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2740     FETCH(r1, 1)                        @ r1<- field ref CCCC
2741     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2742     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2743     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2744     cmp     r0, #0                      @ is resolved entry null?
2745     bne     .LOP_IPUT_BYTE_finish          @ no, already resolved
2746 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2747     EXPORT_PC()                         @ resolve() could throw
2748     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2749     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2750     cmp     r0, #0                      @ success?
2751     bne     .LOP_IPUT_BYTE_finish          @ yes, finish up
2752     b       common_exceptionThrown
2753
2754
2755 /* ------------------------------ */
2756     .balign 64
2757 .L_OP_IPUT_CHAR: /* 0x5e */
2758 /* File: armv5te/OP_IPUT_CHAR.S */
2759 @include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" }
2760 /* File: armv5te/OP_IPUT.S */
2761     /*
2762      * General 32-bit instance field put.
2763      *
2764      * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2765      */
2766     /* op vA, vB, field@CCCC */
2767     mov     r0, rINST, lsr #12          @ r0<- B
2768     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2769     FETCH(r1, 1)                        @ r1<- field ref CCCC
2770     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2771     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2772     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2773     cmp     r0, #0                      @ is resolved entry null?
2774     bne     .LOP_IPUT_CHAR_finish          @ no, already resolved
2775 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2776     EXPORT_PC()                         @ resolve() could throw
2777     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2778     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2779     cmp     r0, #0                      @ success?
2780     bne     .LOP_IPUT_CHAR_finish          @ yes, finish up
2781     b       common_exceptionThrown
2782
2783
2784 /* ------------------------------ */
2785     .balign 64
2786 .L_OP_IPUT_SHORT: /* 0x5f */
2787 /* File: armv5te/OP_IPUT_SHORT.S */
2788 @include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" }
2789 /* File: armv5te/OP_IPUT.S */
2790     /*
2791      * General 32-bit instance field put.
2792      *
2793      * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2794      */
2795     /* op vA, vB, field@CCCC */
2796     mov     r0, rINST, lsr #12          @ r0<- B
2797     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2798     FETCH(r1, 1)                        @ r1<- field ref CCCC
2799     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2800     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2801     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2802     cmp     r0, #0                      @ is resolved entry null?
2803     bne     .LOP_IPUT_SHORT_finish          @ no, already resolved
2804 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2805     EXPORT_PC()                         @ resolve() could throw
2806     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2807     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2808     cmp     r0, #0                      @ success?
2809     bne     .LOP_IPUT_SHORT_finish          @ yes, finish up
2810     b       common_exceptionThrown
2811
2812
2813 /* ------------------------------ */
2814     .balign 64
2815 .L_OP_SGET: /* 0x60 */
2816 /* File: armv5te/OP_SGET.S */
2817     /*
2818      * General 32-bit SGET handler.
2819      *
2820      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2821      */
2822     /* op vAA, field@BBBB */
2823     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2824     FETCH(r1, 1)                        @ r1<- field ref BBBB
2825     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2826     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2827     cmp     r0, #0                      @ is resolved entry null?
2828     beq     .LOP_SGET_resolve         @ yes, do resolve
2829 .LOP_SGET_finish: @ field ptr in r0
2830     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2831     mov     r2, rINST, lsr #8           @ r2<- AA
2832     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2833     SET_VREG(r1, r2)                    @ fp[AA]<- r1
2834     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2835     GOTO_OPCODE(ip)                     @ jump to next instruction
2836
2837 /* ------------------------------ */
2838     .balign 64
2839 .L_OP_SGET_WIDE: /* 0x61 */
2840 /* File: armv5te/OP_SGET_WIDE.S */
2841     /*
2842      * 64-bit SGET handler.
2843      */
2844     /* sget-wide vAA, field@BBBB */
2845     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2846     FETCH(r1, 1)                        @ r1<- field ref BBBB
2847     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2848     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2849     cmp     r0, #0                      @ is resolved entry null?
2850     beq     .LOP_SGET_WIDE_resolve         @ yes, do resolve
2851 .LOP_SGET_WIDE_finish:
2852     mov     r1, rINST, lsr #8           @ r1<- AA
2853     ldrd    r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned)
2854     add     r1, rFP, r1, lsl #2         @ r1<- &fp[AA]
2855     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2856     stmia   r1, {r2-r3}                 @ vAA/vAA+1<- r2/r3
2857     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2858     GOTO_OPCODE(ip)                     @ jump to next instruction
2859
2860 /* ------------------------------ */
2861     .balign 64
2862 .L_OP_SGET_OBJECT: /* 0x62 */
2863 /* File: armv5te/OP_SGET_OBJECT.S */
2864 /* File: armv5te/OP_SGET.S */
2865     /*
2866      * General 32-bit SGET handler.
2867      *
2868      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2869      */
2870     /* op vAA, field@BBBB */
2871     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2872     FETCH(r1, 1)                        @ r1<- field ref BBBB
2873     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2874     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2875     cmp     r0, #0                      @ is resolved entry null?
2876     beq     .LOP_SGET_OBJECT_resolve         @ yes, do resolve
2877 .LOP_SGET_OBJECT_finish: @ field ptr in r0
2878     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2879     mov     r2, rINST, lsr #8           @ r2<- AA
2880     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2881     SET_VREG(r1, r2)                    @ fp[AA]<- r1
2882     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2883     GOTO_OPCODE(ip)                     @ jump to next instruction
2884
2885
2886 /* ------------------------------ */
2887     .balign 64
2888 .L_OP_SGET_BOOLEAN: /* 0x63 */
2889 /* File: armv5te/OP_SGET_BOOLEAN.S */
2890 /* File: armv5te/OP_SGET.S */
2891     /*
2892      * General 32-bit SGET handler.
2893      *
2894      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2895      */
2896     /* op vAA, field@BBBB */
2897     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2898     FETCH(r1, 1)                        @ r1<- field ref BBBB
2899     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2900     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2901     cmp     r0, #0                      @ is resolved entry null?
2902     beq     .LOP_SGET_BOOLEAN_resolve         @ yes, do resolve
2903 .LOP_SGET_BOOLEAN_finish: @ field ptr in r0
2904     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2905     mov     r2, rINST, lsr #8           @ r2<- AA
2906     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2907     SET_VREG(r1, r2)                    @ fp[AA]<- r1
2908     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2909     GOTO_OPCODE(ip)                     @ jump to next instruction
2910
2911
2912 /* ------------------------------ */
2913     .balign 64
2914 .L_OP_SGET_BYTE: /* 0x64 */
2915 /* File: armv5te/OP_SGET_BYTE.S */
2916 /* File: armv5te/OP_SGET.S */
2917     /*
2918      * General 32-bit SGET handler.
2919      *
2920      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2921      */
2922     /* op vAA, field@BBBB */
2923     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2924     FETCH(r1, 1)                        @ r1<- field ref BBBB
2925     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2926     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2927     cmp     r0, #0                      @ is resolved entry null?
2928     beq     .LOP_SGET_BYTE_resolve         @ yes, do resolve
2929 .LOP_SGET_BYTE_finish: @ field ptr in r0
2930     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2931     mov     r2, rINST, lsr #8           @ r2<- AA
2932     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2933     SET_VREG(r1, r2)                    @ fp[AA]<- r1
2934     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2935     GOTO_OPCODE(ip)                     @ jump to next instruction
2936
2937
2938 /* ------------------------------ */
2939     .balign 64
2940 .L_OP_SGET_CHAR: /* 0x65 */
2941 /* File: armv5te/OP_SGET_CHAR.S */
2942 /* File: armv5te/OP_SGET.S */
2943     /*
2944      * General 32-bit SGET handler.
2945      *
2946      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2947      */
2948     /* op vAA, field@BBBB */
2949     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2950     FETCH(r1, 1)                        @ r1<- field ref BBBB
2951     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2952     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2953     cmp     r0, #0                      @ is resolved entry null?
2954     beq     .LOP_SGET_CHAR_resolve         @ yes, do resolve
2955 .LOP_SGET_CHAR_finish: @ field ptr in r0
2956     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2957     mov     r2, rINST, lsr #8           @ r2<- AA
2958     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2959     SET_VREG(r1, r2)                    @ fp[AA]<- r1
2960     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2961     GOTO_OPCODE(ip)                     @ jump to next instruction
2962
2963
2964 /* ------------------------------ */
2965     .balign 64
2966 .L_OP_SGET_SHORT: /* 0x66 */
2967 /* File: armv5te/OP_SGET_SHORT.S */
2968 /* File: armv5te/OP_SGET.S */
2969     /*
2970      * General 32-bit SGET handler.
2971      *
2972      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2973      */
2974     /* op vAA, field@BBBB */
2975     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2976     FETCH(r1, 1)                        @ r1<- field ref BBBB
2977     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2978     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2979     cmp     r0, #0                      @ is resolved entry null?
2980     beq     .LOP_SGET_SHORT_resolve         @ yes, do resolve
2981 .LOP_SGET_SHORT_finish: @ field ptr in r0
2982     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2983     mov     r2, rINST, lsr #8           @ r2<- AA
2984     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2985     SET_VREG(r1, r2)                    @ fp[AA]<- r1
2986     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2987     GOTO_OPCODE(ip)                     @ jump to next instruction
2988
2989
2990 /* ------------------------------ */
2991     .balign 64
2992 .L_OP_SPUT: /* 0x67 */
2993 /* File: armv5te/OP_SPUT.S */
2994     /*
2995      * General 32-bit SPUT handler.
2996      *
2997      * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2998      */
2999     /* op vAA, field@BBBB */
3000     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3001     FETCH(r1, 1)                        @ r1<- field ref BBBB
3002     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3003     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3004     cmp     r0, #0                      @ is resolved entry null?
3005     beq     .LOP_SPUT_resolve         @ yes, do resolve
3006 .LOP_SPUT_finish:   @ field ptr in r0
3007     mov     r2, rINST, lsr #8           @ r2<- AA
3008     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3009     GET_VREG(r1, r2)                    @ r1<- fp[AA]
3010     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3011     str     r1, [r0, #offStaticField_value] @ field<- vAA
3012     GOTO_OPCODE(ip)                     @ jump to next instruction
3013
3014 /* ------------------------------ */
3015     .balign 64
3016 .L_OP_SPUT_WIDE: /* 0x68 */
3017 /* File: armv5te/OP_SPUT_WIDE.S */
3018     /*
3019      * 64-bit SPUT handler.
3020      */
3021     /* sput-wide vAA, field@BBBB */
3022     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3023     FETCH(r1, 1)                        @ r1<- field ref BBBB
3024     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3025     mov     r9, rINST, lsr #8           @ r9<- AA
3026     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3027     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
3028     cmp     r0, #0                      @ is resolved entry null?
3029     beq     .LOP_SPUT_WIDE_resolve         @ yes, do resolve
3030 .LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9
3031     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3032     ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
3033     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3034     strd    r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1
3035     GOTO_OPCODE(ip)                     @ jump to next instruction
3036
3037 /* ------------------------------ */
3038     .balign 64
3039 .L_OP_SPUT_OBJECT: /* 0x69 */
3040 /* File: armv5te/OP_SPUT_OBJECT.S */
3041 /* File: armv5te/OP_SPUT.S */
3042     /*
3043      * General 32-bit SPUT handler.
3044      *
3045      * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3046      */
3047     /* op vAA, field@BBBB */
3048     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3049     FETCH(r1, 1)                        @ r1<- field ref BBBB
3050     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3051     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3052     cmp     r0, #0                      @ is resolved entry null?
3053     beq     .LOP_SPUT_OBJECT_resolve         @ yes, do resolve
3054 .LOP_SPUT_OBJECT_finish:   @ field ptr in r0
3055     mov     r2, rINST, lsr #8           @ r2<- AA
3056     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3057     GET_VREG(r1, r2)                    @ r1<- fp[AA]
3058     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3059     str     r1, [r0, #offStaticField_value] @ field<- vAA
3060     GOTO_OPCODE(ip)                     @ jump to next instruction
3061
3062
3063 /* ------------------------------ */
3064     .balign 64
3065 .L_OP_SPUT_BOOLEAN: /* 0x6a */
3066 /* File: armv5te/OP_SPUT_BOOLEAN.S */
3067 /* File: armv5te/OP_SPUT.S */
3068     /*
3069      * General 32-bit SPUT handler.
3070      *
3071      * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3072      */
3073     /* op vAA, field@BBBB */
3074     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3075     FETCH(r1, 1)                        @ r1<- field ref BBBB
3076     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3077     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3078     cmp     r0, #0                      @ is resolved entry null?
3079     beq     .LOP_SPUT_BOOLEAN_resolve         @ yes, do resolve
3080 .LOP_SPUT_BOOLEAN_finish:   @ field ptr in r0
3081     mov     r2, rINST, lsr #8           @ r2<- AA
3082     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3083     GET_VREG(r1, r2)                    @ r1<- fp[AA]
3084     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3085     str     r1, [r0, #offStaticField_value] @ field<- vAA
3086     GOTO_OPCODE(ip)                     @ jump to next instruction
3087
3088
3089 /* ------------------------------ */
3090     .balign 64
3091 .L_OP_SPUT_BYTE: /* 0x6b */
3092 /* File: armv5te/OP_SPUT_BYTE.S */
3093 /* File: armv5te/OP_SPUT.S */
3094     /*
3095      * General 32-bit SPUT handler.
3096      *
3097      * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3098      */
3099     /* op vAA, field@BBBB */
3100     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3101     FETCH(r1, 1)                        @ r1<- field ref BBBB
3102     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3103     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3104     cmp     r0, #0                      @ is resolved entry null?
3105     beq     .LOP_SPUT_BYTE_resolve         @ yes, do resolve
3106 .LOP_SPUT_BYTE_finish:   @ field ptr in r0
3107     mov     r2, rINST, lsr #8           @ r2<- AA
3108     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3109     GET_VREG(r1, r2)                    @ r1<- fp[AA]
3110     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3111     str     r1, [r0, #offStaticField_value] @ field<- vAA
3112     GOTO_OPCODE(ip)                     @ jump to next instruction
3113
3114
3115 /* ------------------------------ */
3116     .balign 64
3117 .L_OP_SPUT_CHAR: /* 0x6c */
3118 /* File: armv5te/OP_SPUT_CHAR.S */
3119 /* File: armv5te/OP_SPUT.S */
3120     /*
3121      * General 32-bit SPUT handler.
3122      *
3123      * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3124      */
3125     /* op vAA, field@BBBB */
3126     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3127     FETCH(r1, 1)                        @ r1<- field ref BBBB
3128     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3129     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3130     cmp     r0, #0                      @ is resolved entry null?
3131     beq     .LOP_SPUT_CHAR_resolve         @ yes, do resolve
3132 .LOP_SPUT_CHAR_finish:   @ field ptr in r0
3133     mov     r2, rINST, lsr #8           @ r2<- AA
3134     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3135     GET_VREG(r1, r2)                    @ r1<- fp[AA]
3136     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3137     str     r1, [r0, #offStaticField_value] @ field<- vAA
3138     GOTO_OPCODE(ip)                     @ jump to next instruction
3139
3140
3141 /* ------------------------------ */
3142     .balign 64
3143 .L_OP_SPUT_SHORT: /* 0x6d */
3144 /* File: armv5te/OP_SPUT_SHORT.S */
3145 /* File: armv5te/OP_SPUT.S */
3146     /*
3147      * General 32-bit SPUT handler.
3148      *
3149      * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3150      */
3151     /* op vAA, field@BBBB */
3152     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3153     FETCH(r1, 1)                        @ r1<- field ref BBBB
3154     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3155     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3156     cmp     r0, #0                      @ is resolved entry null?
3157     beq     .LOP_SPUT_SHORT_resolve         @ yes, do resolve
3158 .LOP_SPUT_SHORT_finish:   @ field ptr in r0
3159     mov     r2, rINST, lsr #8           @ r2<- AA
3160     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3161     GET_VREG(r1, r2)                    @ r1<- fp[AA]
3162     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3163     str     r1, [r0, #offStaticField_value] @ field<- vAA
3164     GOTO_OPCODE(ip)                     @ jump to next instruction
3165
3166
3167 /* ------------------------------ */
3168     .balign 64
3169 .L_OP_INVOKE_VIRTUAL: /* 0x6e */
3170 /* File: armv5te/OP_INVOKE_VIRTUAL.S */
3171     /*
3172      * Handle a virtual method call.
3173      *
3174      * for: invoke-virtual, invoke-virtual/range
3175      */
3176     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3177     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3178     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3179     FETCH(r1, 1)                        @ r1<- BBBB
3180     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3181     FETCH(r10, 2)                       @ r10<- GFED or CCCC
3182     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3183     .if     (!0)
3184     and     r10, r10, #15               @ r10<- D (or stays CCCC)
3185     .endif
3186     cmp     r0, #0                      @ already resolved?
3187     EXPORT_PC()                         @ must export for invoke
3188     bne     .LOP_INVOKE_VIRTUAL_continue        @ yes, continue on
3189     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3190     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3191     mov     r2, #METHOD_VIRTUAL         @ resolver method type
3192     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3193     cmp     r0, #0                      @ got null?
3194     bne     .LOP_INVOKE_VIRTUAL_continue        @ no, continue
3195     b       common_exceptionThrown      @ yes, handle exception
3196
3197 /* ------------------------------ */
3198     .balign 64
3199 .L_OP_INVOKE_SUPER: /* 0x6f */
3200 /* File: armv5te/OP_INVOKE_SUPER.S */
3201     /*
3202      * Handle a "super" method call.
3203      *
3204      * for: invoke-super, invoke-super/range
3205      */
3206     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3207     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3208     FETCH(r10, 2)                       @ r10<- GFED or CCCC
3209     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3210     .if     (!0)
3211     and     r10, r10, #15               @ r10<- D (or stays CCCC)
3212     .endif
3213     FETCH(r1, 1)                        @ r1<- BBBB
3214     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3215     GET_VREG(r2, r10)                   @ r2<- "this" ptr
3216     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3217     cmp     r2, #0                      @ null "this"?
3218     ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3219     beq     common_errNullObject        @ null "this", throw exception
3220     cmp     r0, #0                      @ already resolved?
3221     ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3222     EXPORT_PC()                         @ must export for invoke
3223     bne     .LOP_INVOKE_SUPER_continue        @ resolved, continue on
3224     b       .LOP_INVOKE_SUPER_resolve         @ do resolve now
3225
3226 /* ------------------------------ */
3227     .balign 64
3228 .L_OP_INVOKE_DIRECT: /* 0x70 */
3229 /* File: armv5te/OP_INVOKE_DIRECT.S */
3230     /*
3231      * Handle a direct method call.
3232      *
3233      * (We could defer the "is 'this' pointer null" test to the common
3234      * method invocation code, and use a flag to indicate that static
3235      * calls don't count.  If we do this as part of copying the arguments
3236      * out we could avoiding loading the first arg twice.)
3237      *
3238      * for: invoke-direct, invoke-direct/range
3239      */
3240     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3241     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3242     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3243     FETCH(r1, 1)                        @ r1<- BBBB
3244     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3245     FETCH(r10, 2)                       @ r10<- GFED or CCCC
3246     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3247     .if     (!0)
3248     and     r10, r10, #15               @ r10<- D (or stays CCCC)
3249     .endif
3250     cmp     r0, #0                      @ already resolved?
3251     EXPORT_PC()                         @ must export for invoke
3252     GET_VREG(r2, r10)                   @ r2<- "this" ptr
3253     beq     .LOP_INVOKE_DIRECT_resolve         @ not resolved, do it now
3254 .LOP_INVOKE_DIRECT_finish:
3255     cmp     r2, #0                      @ null "this" ref?
3256     bne     common_invokeMethodNoRange   @ no, continue on
3257     b       common_errNullObject        @ yes, throw exception
3258
3259 /* ------------------------------ */
3260     .balign 64
3261 .L_OP_INVOKE_STATIC: /* 0x71 */
3262 /* File: armv5te/OP_INVOKE_STATIC.S */
3263     /*
3264      * Handle a static method call.
3265      *
3266      * for: invoke-static, invoke-static/range
3267      */
3268     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3269     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3270     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3271     FETCH(r1, 1)                        @ r1<- BBBB
3272     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3273     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3274     cmp     r0, #0                      @ already resolved?
3275     EXPORT_PC()                         @ must export for invoke
3276     bne     common_invokeMethodNoRange @ yes, continue on
3277 0:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3278     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3279     mov     r2, #METHOD_STATIC          @ resolver method type
3280     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3281     cmp     r0, #0                      @ got null?
3282     bne     common_invokeMethodNoRange @ no, continue
3283     b       common_exceptionThrown      @ yes, handle exception
3284
3285
3286 /* ------------------------------ */
3287     .balign 64
3288 .L_OP_INVOKE_INTERFACE: /* 0x72 */
3289 /* File: armv5te/OP_INVOKE_INTERFACE.S */
3290     /*
3291      * Handle an interface method call.
3292      *
3293      * for: invoke-interface, invoke-interface/range
3294      */
3295     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3296     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3297     FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3298     FETCH(r1, 1)                        @ r1<- BBBB
3299     .if     (!0)
3300     and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3301     .endif
3302     EXPORT_PC()                         @ must export for invoke
3303     GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3304     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3305     cmp     r0, #0                      @ null obj?
3306     ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3307     beq     common_errNullObject        @ yes, fail
3308     ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3309     bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3310     cmp     r0, #0                      @ failed?
3311     beq     common_exceptionThrown      @ yes, handle exception
3312     b       common_invokeMethodNoRange @ jump to common handler 
3313
3314
3315 /* ------------------------------ */
3316     .balign 64
3317 .L_OP_UNUSED_73: /* 0x73 */
3318 /* File: armv5te/OP_UNUSED_73.S */
3319 /* File: armv5te/unused.S */
3320     bl      common_abort
3321
3322
3323
3324 /* ------------------------------ */
3325     .balign 64
3326 .L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
3327 /* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */
3328 /* File: armv5te/OP_INVOKE_VIRTUAL.S */
3329     /*
3330      * Handle a virtual method call.
3331      *
3332      * for: invoke-virtual, invoke-virtual/range
3333      */
3334     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3335     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3336     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3337     FETCH(r1, 1)                        @ r1<- BBBB
3338     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3339     FETCH(r10, 2)                       @ r10<- GFED or CCCC
3340     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3341     .if     (!1)
3342     and     r10, r10, #15               @ r10<- D (or stays CCCC)
3343     .endif
3344     cmp     r0, #0                      @ already resolved?
3345     EXPORT_PC()                         @ must export for invoke
3346     bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ yes, continue on
3347     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3348     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3349     mov     r2, #METHOD_VIRTUAL         @ resolver method type
3350     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3351     cmp     r0, #0                      @ got null?
3352     bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ no, continue
3353     b       common_exceptionThrown      @ yes, handle exception
3354
3355
3356 /* ------------------------------ */
3357     .balign 64
3358 .L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
3359 /* File: armv5te/OP_INVOKE_SUPER_RANGE.S */
3360 /* File: armv5te/OP_INVOKE_SUPER.S */
3361     /*
3362      * Handle a "super" method call.
3363      *
3364      * for: invoke-super, invoke-super/range
3365      */
3366     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3367     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3368     FETCH(r10, 2)                       @ r10<- GFED or CCCC
3369     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3370     .if     (!1)
3371     and     r10, r10, #15               @ r10<- D (or stays CCCC)
3372     .endif
3373     FETCH(r1, 1)                        @ r1<- BBBB
3374     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3375     GET_VREG(r2, r10)                   @ r2<- "this" ptr
3376     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3377     cmp     r2, #0                      @ null "this"?
3378     ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3379     beq     common_errNullObject        @ null "this", throw exception
3380     cmp     r0, #0                      @ already resolved?
3381     ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3382     EXPORT_PC()                         @ must export for invoke
3383     bne     .LOP_INVOKE_SUPER_RANGE_continue        @ resolved, continue on
3384     b       .LOP_INVOKE_SUPER_RANGE_resolve         @ do resolve now
3385
3386
3387 /* ------------------------------ */
3388     .balign 64
3389 .L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
3390 /* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */
3391 /* File: armv5te/OP_INVOKE_DIRECT.S */
3392     /*
3393      * Handle a direct method call.
3394      *
3395      * (We could defer the "is 'this' pointer null" test to the common
3396      * method invocation code, and use a flag to indicate that static
3397      * calls don't count.  If we do this as part of copying the arguments
3398      * out we could avoiding loading the first arg twice.)
3399      *
3400      * for: invoke-direct, invoke-direct/range
3401      */
3402     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3403     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3404     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3405     FETCH(r1, 1)                        @ r1<- BBBB
3406     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3407     FETCH(r10, 2)                       @ r10<- GFED or CCCC
3408     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3409     .if     (!1)
3410     and     r10, r10, #15               @ r10<- D (or stays CCCC)
3411     .endif
3412     cmp     r0, #0                      @ already resolved?
3413     EXPORT_PC()                         @ must export for invoke
3414     GET_VREG(r2, r10)                   @ r2<- "this" ptr
3415     beq     .LOP_INVOKE_DIRECT_RANGE_resolve         @ not resolved, do it now
3416 .LOP_INVOKE_DIRECT_RANGE_finish:
3417     cmp     r2, #0                      @ null "this" ref?
3418     bne     common_invokeMethodRange   @ no, continue on
3419     b       common_errNullObject        @ yes, throw exception
3420
3421
3422 /* ------------------------------ */
3423     .balign 64
3424 .L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
3425 /* File: armv5te/OP_INVOKE_STATIC_RANGE.S */
3426 /* File: armv5te/OP_INVOKE_STATIC.S */
3427     /*
3428      * Handle a static method call.
3429      *
3430      * for: invoke-static, invoke-static/range
3431      */
3432     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3433     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3434     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3435     FETCH(r1, 1)                        @ r1<- BBBB
3436     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3437     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3438     cmp     r0, #0                      @ already resolved?
3439     EXPORT_PC()                         @ must export for invoke
3440     bne     common_invokeMethodRange @ yes, continue on
3441 0:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3442     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3443     mov     r2, #METHOD_STATIC          @ resolver method type
3444     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3445     cmp     r0, #0                      @ got null?
3446     bne     common_invokeMethodRange @ no, continue
3447     b       common_exceptionThrown      @ yes, handle exception
3448
3449
3450
3451 /* ------------------------------ */
3452     .balign 64
3453 .L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
3454 /* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */
3455 /* File: armv5te/OP_INVOKE_INTERFACE.S */
3456     /*
3457      * Handle an interface method call.
3458      *
3459      * for: invoke-interface, invoke-interface/range
3460      */
3461     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3462     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3463     FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3464     FETCH(r1, 1)                        @ r1<- BBBB
3465     .if     (!1)
3466     and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3467     .endif
3468     EXPORT_PC()                         @ must export for invoke
3469     GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3470     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3471     cmp     r0, #0                      @ null obj?
3472     ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3473     beq     common_errNullObject        @ yes, fail
3474     ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3475     bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3476     cmp     r0, #0                      @ failed?
3477     beq     common_exceptionThrown      @ yes, handle exception
3478     b       common_invokeMethodRange @ jump to common handler 
3479
3480
3481
3482 /* ------------------------------ */
3483     .balign 64
3484 .L_OP_UNUSED_79: /* 0x79 */
3485 /* File: armv5te/OP_UNUSED_79.S */
3486 /* File: armv5te/unused.S */
3487     bl      common_abort
3488
3489
3490
3491 /* ------------------------------ */
3492     .balign 64
3493 .L_OP_UNUSED_7A: /* 0x7a */
3494 /* File: armv5te/OP_UNUSED_7A.S */
3495 /* File: armv5te/unused.S */
3496     bl      common_abort
3497
3498
3499
3500 /* ------------------------------ */
3501     .balign 64
3502 .L_OP_NEG_INT: /* 0x7b */
3503 /* File: armv6t2/OP_NEG_INT.S */
3504 /* File: armv6t2/unop.S */
3505     /*
3506      * Generic 32-bit unary operation.  Provide an "instr" line that
3507      * specifies an instruction that performs "result = op r0".
3508      * This could be an ARM instruction or a function call.
3509      *
3510      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3511      *      int-to-byte, int-to-char, int-to-short
3512      */
3513     /* unop vA, vB */
3514     mov     r3, rINST, lsr #12          @ r3<- B
3515     ubfx    r9, rINST, #8, #4           @ r9<- A
3516     GET_VREG(r0, r3)                    @ r0<- vB
3517                                @ optional op; may set condition codes
3518     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3519     rsb     r0, r0, #0                              @ r0<- op, r0-r3 changed
3520     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3521     SET_VREG(r0, r9)                    @ vAA<- r0
3522     GOTO_OPCODE(ip)                     @ jump to next instruction
3523     /* 8-9 instructions */
3524
3525
3526 /* ------------------------------ */
3527     .balign 64
3528 .L_OP_NOT_INT: /* 0x7c */
3529 /* File: armv6t2/OP_NOT_INT.S */
3530 /* File: armv6t2/unop.S */
3531     /*
3532      * Generic 32-bit unary operation.  Provide an "instr" line that
3533      * specifies an instruction that performs "result = op r0".
3534      * This could be an ARM instruction or a function call.
3535      *
3536      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3537      *      int-to-byte, int-to-char, int-to-short
3538      */
3539     /* unop vA, vB */
3540     mov     r3, rINST, lsr #12          @ r3<- B
3541     ubfx    r9, rINST, #8, #4           @ r9<- A
3542     GET_VREG(r0, r3)                    @ r0<- vB
3543                                @ optional op; may set condition codes
3544     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3545     mvn     r0, r0                              @ r0<- op, r0-r3 changed
3546     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3547     SET_VREG(r0, r9)                    @ vAA<- r0
3548     GOTO_OPCODE(ip)                     @ jump to next instruction
3549     /* 8-9 instructions */
3550
3551
3552 /* ------------------------------ */
3553     .balign 64
3554 .L_OP_NEG_LONG: /* 0x7d */
3555 /* File: armv6t2/OP_NEG_LONG.S */
3556 /* File: armv6t2/unopWide.S */
3557     /*
3558      * Generic 64-bit unary operation.  Provide an "instr" line that
3559      * specifies an instruction that performs "result = op r0/r1".
3560      * This could be an ARM instruction or a function call.
3561      *
3562      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3563      */
3564     /* unop vA, vB */
3565     mov     r3, rINST, lsr #12          @ r3<- B
3566     ubfx    r9, rINST, #8, #4           @ r9<- A
3567     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3568     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3569     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3570     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3571     rsbs    r0, r0, #0                           @ optional op; may set condition codes
3572     rsc     r1, r1, #0                              @ r0/r1<- op, r2-r3 changed
3573     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3574     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3575     GOTO_OPCODE(ip)                     @ jump to next instruction
3576     /* 10-11 instructions */
3577
3578
3579
3580 /* ------------------------------ */
3581     .balign 64
3582 .L_OP_NOT_LONG: /* 0x7e */
3583 /* File: armv6t2/OP_NOT_LONG.S */
3584 /* File: armv6t2/unopWide.S */
3585     /*
3586      * Generic 64-bit unary operation.  Provide an "instr" line that
3587      * specifies an instruction that performs "result = op r0/r1".
3588      * This could be an ARM instruction or a function call.
3589      *
3590      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3591      */
3592     /* unop vA, vB */
3593     mov     r3, rINST, lsr #12          @ r3<- B
3594     ubfx    r9, rINST, #8, #4           @ r9<- A
3595     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3596     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3597     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3598     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3599     mvn     r0, r0                           @ optional op; may set condition codes
3600     mvn     r1, r1                              @ r0/r1<- op, r2-r3 changed
3601     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3602     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3603     GOTO_OPCODE(ip)                     @ jump to next instruction
3604     /* 10-11 instructions */
3605
3606
3607
3608 /* ------------------------------ */
3609     .balign 64
3610 .L_OP_NEG_FLOAT: /* 0x7f */
3611 /* File: armv6t2/OP_NEG_FLOAT.S */
3612 /* File: armv6t2/unop.S */
3613     /*
3614      * Generic 32-bit unary operation.  Provide an "instr" line that
3615      * specifies an instruction that performs "result = op r0".
3616      * This could be an ARM instruction or a function call.
3617      *
3618      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3619      *      int-to-byte, int-to-char, int-to-short
3620      */
3621     /* unop vA, vB */
3622     mov     r3, rINST, lsr #12          @ r3<- B
3623     ubfx    r9, rINST, #8, #4           @ r9<- A
3624     GET_VREG(r0, r3)                    @ r0<- vB
3625                                @ optional op; may set condition codes
3626     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3627     add     r0, r0, #0x80000000                              @ r0<- op, r0-r3 changed
3628     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3629     SET_VREG(r0, r9)                    @ vAA<- r0
3630     GOTO_OPCODE(ip)                     @ jump to next instruction
3631     /* 8-9 instructions */
3632
3633
3634 /* ------------------------------ */
3635     .balign 64
3636 .L_OP_NEG_DOUBLE: /* 0x80 */
3637 /* File: armv6t2/OP_NEG_DOUBLE.S */
3638 /* File: armv6t2/unopWide.S */
3639     /*
3640      * Generic 64-bit unary operation.  Provide an "instr" line that
3641      * specifies an instruction that performs "result = op r0/r1".
3642      * This could be an ARM instruction or a function call.
3643      *
3644      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3645      */
3646     /* unop vA, vB */
3647     mov     r3, rINST, lsr #12          @ r3<- B
3648     ubfx    r9, rINST, #8, #4           @ r9<- A
3649     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3650     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3651     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3652     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3653                                @ optional op; may set condition codes
3654     add     r1, r1, #0x80000000                              @ r0/r1<- op, r2-r3 changed
3655     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3656     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3657     GOTO_OPCODE(ip)                     @ jump to next instruction
3658     /* 10-11 instructions */
3659
3660
3661
3662 /* ------------------------------ */
3663     .balign 64
3664 .L_OP_INT_TO_LONG: /* 0x81 */
3665 /* File: armv6t2/OP_INT_TO_LONG.S */
3666 /* File: armv6t2/unopWider.S */
3667     /*
3668      * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3669      * that specifies an instruction that performs "result = op r0", where
3670      * "result" is a 64-bit quantity in r0/r1.
3671      *
3672      * For: int-to-long, int-to-double, float-to-long, float-to-double
3673      */
3674     /* unop vA, vB */
3675     mov     r3, rINST, lsr #12          @ r3<- B
3676     ubfx    r9, rINST, #8, #4           @ r9<- A
3677     GET_VREG(r0, r3)                    @ r0<- vB
3678     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3679                                @ optional op; may set condition codes
3680     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3681     mov     r1, r0, asr #31                              @ r0<- op, r0-r3 changed
3682     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3683     stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3684     GOTO_OPCODE(ip)                     @ jump to next instruction
3685     /* 9-10 instructions */
3686
3687
3688 /* ------------------------------ */
3689     .balign 64
3690 .L_OP_INT_TO_FLOAT: /* 0x82 */
3691 /* File: arm-vfp/OP_INT_TO_FLOAT.S */
3692 /* File: arm-vfp/funop.S */
3693     /*
3694      * Generic 32-bit unary floating-point operation.  Provide an "instr"
3695      * line that specifies an instruction that performs "s1 = op s0".
3696      *
3697      * for: int-to-float, float-to-int
3698      */
3699     /* unop vA, vB */
3700     mov     r3, rINST, lsr #12          @ r3<- B
3701     mov     r9, rINST, lsr #8           @ r9<- A+
3702     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3703     flds    s0, [r3]                    @ s0<- vB
3704     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3705     and     r9, r9, #15                 @ r9<- A
3706     fsitos  s1, s0                              @ s1<- op
3707     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3708     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3709     fsts    s1, [r9]                    @ vA<- s1
3710     GOTO_OPCODE(ip)                     @ jump to next instruction
3711
3712
3713 /* ------------------------------ */
3714     .balign 64
3715 .L_OP_INT_TO_DOUBLE: /* 0x83 */
3716 /* File: arm-vfp/OP_INT_TO_DOUBLE.S */
3717 /* File: arm-vfp/funopWider.S */
3718     /*
3719      * Generic 32bit-to-64bit floating point unary operation.  Provide an
3720      * "instr" line that specifies an instruction that performs "d0 = op s0".
3721      *
3722      * For: int-to-double, float-to-double
3723      */
3724     /* unop vA, vB */
3725     mov     r3, rINST, lsr #12          @ r3<- B
3726     mov     r9, rINST, lsr #8           @ r9<- A+
3727     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3728     flds    s0, [r3]                    @ s0<- vB
3729     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3730     and     r9, r9, #15                 @ r9<- A
3731     fsitod  d0, s0                              @ d0<- op
3732     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3733     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3734     fstd    d0, [r9]                    @ vA<- d0
3735     GOTO_OPCODE(ip)                     @ jump to next instruction
3736
3737
3738 /* ------------------------------ */
3739     .balign 64
3740 .L_OP_LONG_TO_INT: /* 0x84 */
3741 /* File: armv5te/OP_LONG_TO_INT.S */
3742 /* we ignore the high word, making this equivalent to a 32-bit reg move */
3743 /* File: armv5te/OP_MOVE.S */
3744     /* for move, move-object, long-to-int */
3745     /* op vA, vB */
3746     mov     r1, rINST, lsr #12          @ r1<- B from 15:12
3747     mov     r0, rINST, lsr #8           @ r0<- A from 11:8
3748     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3749     GET_VREG(r2, r1)                    @ r2<- fp[B]
3750     and     r0, r0, #15
3751     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
3752     SET_VREG(r2, r0)                    @ fp[A]<- r2
3753     GOTO_OPCODE(ip)                     @ execute next instruction
3754
3755
3756
3757 /* ------------------------------ */
3758     .balign 64
3759 .L_OP_LONG_TO_FLOAT: /* 0x85 */
3760 /* File: armv6t2/OP_LONG_TO_FLOAT.S */
3761 /* File: armv6t2/unopNarrower.S */
3762     /*
3763      * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
3764      * that specifies an instruction that performs "result = op r0/r1", where
3765      * "result" is a 32-bit quantity in r0.
3766      *
3767      * For: long-to-float, double-to-int, double-to-float
3768      *
3769      * (This would work for long-to-int, but that instruction is actually
3770      * an exact match for OP_MOVE.)
3771      */
3772     /* unop vA, vB */
3773     mov     r3, rINST, lsr #12          @ r3<- B
3774     ubfx    r9, rINST, #8, #4           @ r9<- A
3775     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3776     ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
3777     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3778                                @ optional op; may set condition codes
3779     bl      __aeabi_l2f                              @ r0<- op, r0-r3 changed
3780     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3781     SET_VREG(r0, r9)                    @ vA<- r0
3782     GOTO_OPCODE(ip)                     @ jump to next instruction
3783     /* 9-10 instructions */
3784
3785
3786 /* ------------------------------ */
3787     .balign 64
3788 .L_OP_LONG_TO_DOUBLE: /* 0x86 */
3789 /* File: armv6t2/OP_LONG_TO_DOUBLE.S */
3790 /* File: armv6t2/unopWide.S */
3791     /*
3792      * Generic 64-bit unary operation.  Provide an "instr" line that
3793      * specifies an instruction that performs "result = op r0/r1".
3794      * This could be an ARM instruction or a function call.
3795      *
3796      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3797      */
3798     /* unop vA, vB */
3799     mov     r3, rINST, lsr #12          @ r3<- B
3800     ubfx    r9, rINST, #8, #4           @ r9<- A
3801     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3802     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3803     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3804     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3805                                @ optional op; may set condition codes
3806     bl      __aeabi_l2d                              @ r0/r1<- op, r2-r3 changed
3807     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3808     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3809     GOTO_OPCODE(ip)                     @ jump to next instruction
3810     /* 10-11 instructions */
3811
3812
3813
3814 /* ------------------------------ */
3815     .balign 64
3816 .L_OP_FLOAT_TO_INT: /* 0x87 */
3817 /* File: arm-vfp/OP_FLOAT_TO_INT.S */
3818 /* File: arm-vfp/funop.S */
3819     /*
3820      * Generic 32-bit unary floating-point operation.  Provide an "instr"
3821      * line that specifies an instruction that performs "s1 = op s0".
3822      *
3823      * for: int-to-float, float-to-int
3824      */
3825     /* unop vA, vB */
3826     mov     r3, rINST, lsr #12          @ r3<- B
3827     mov     r9, rINST, lsr #8           @ r9<- A+
3828     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3829     flds    s0, [r3]                    @ s0<- vB
3830     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3831     and     r9, r9, #15                 @ r9<- A
3832     ftosizs s1, s0                              @ s1<- op
3833     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3834     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3835     fsts    s1, [r9]                    @ vA<- s1
3836     GOTO_OPCODE(ip)                     @ jump to next instruction
3837
3838
3839 /* ------------------------------ */
3840     .balign 64
3841 .L_OP_FLOAT_TO_LONG: /* 0x88 */
3842 /* File: armv6t2/OP_FLOAT_TO_LONG.S */
3843 @include "armv6t2/unopWider.S" {"instr":"bl      __aeabi_f2lz"}
3844 /* File: armv6t2/unopWider.S */
3845     /*
3846      * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3847      * that specifies an instruction that performs "result = op r0", where
3848      * "result" is a 64-bit quantity in r0/r1.
3849      *
3850      * For: int-to-long, int-to-double, float-to-long, float-to-double
3851      */
3852     /* unop vA, vB */
3853     mov     r3, rINST, lsr #12          @ r3<- B
3854     ubfx    r9, rINST, #8, #4           @ r9<- A
3855     GET_VREG(r0, r3)                    @ r0<- vB
3856     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3857                                @ optional op; may set condition codes
3858     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3859     bl      f2l_doconv                              @ r0<- op, r0-r3 changed
3860     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3861     stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3862     GOTO_OPCODE(ip)                     @ jump to next instruction
3863     /* 9-10 instructions */
3864
3865
3866
3867 /* ------------------------------ */
3868     .balign 64
3869 .L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
3870 /* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */
3871 /* File: arm-vfp/funopWider.S */
3872     /*
3873      * Generic 32bit-to-64bit floating point unary operation.  Provide an
3874      * "instr" line that specifies an instruction that performs "d0 = op s0".
3875      *
3876      * For: int-to-double, float-to-double
3877      */
3878     /* unop vA, vB */
3879     mov     r3, rINST, lsr #12          @ r3<- B
3880     mov     r9, rINST, lsr #8           @ r9<- A+
3881     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3882     flds    s0, [r3]                    @ s0<- vB
3883     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3884     and     r9, r9, #15                 @ r9<- A
3885     fcvtds  d0, s0                              @ d0<- op
3886     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3887     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3888     fstd    d0, [r9]                    @ vA<- d0
3889     GOTO_OPCODE(ip)                     @ jump to next instruction
3890
3891
3892 /* ------------------------------ */
3893     .balign 64
3894 .L_OP_DOUBLE_TO_INT: /* 0x8a */
3895 /* File: arm-vfp/OP_DOUBLE_TO_INT.S */
3896 /* File: arm-vfp/funopNarrower.S */
3897     /*
3898      * Generic 64bit-to-32bit unary floating point operation.  Provide an
3899      * "instr" line that specifies an instruction that performs "s0 = op d0".
3900      *
3901      * For: double-to-int, double-to-float
3902      */
3903     /* unop vA, vB */
3904     mov     r3, rINST, lsr #12          @ r3<- B
3905     mov     r9, rINST, lsr #8           @ r9<- A+
3906     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3907     fldd    d0, [r3]                    @ d0<- vB
3908     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3909     and     r9, r9, #15                 @ r9<- A
3910     ftosizd  s0, d0                              @ s0<- op
3911     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3912     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3913     fsts    s0, [r9]                    @ vA<- s0
3914     GOTO_OPCODE(ip)                     @ jump to next instruction
3915
3916
3917 /* ------------------------------ */
3918     .balign 64
3919 .L_OP_DOUBLE_TO_LONG: /* 0x8b */
3920 /* File: armv6t2/OP_DOUBLE_TO_LONG.S */
3921 @include "armv6t2/unopWide.S" {"instr":"bl      __aeabi_d2lz"}
3922 /* File: armv6t2/unopWide.S */
3923     /*
3924      * Generic 64-bit unary operation.  Provide an "instr" line that
3925      * specifies an instruction that performs "result = op r0/r1".
3926      * This could be an ARM instruction or a function call.
3927      *
3928      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3929      */
3930     /* unop vA, vB */
3931     mov     r3, rINST, lsr #12          @ r3<- B
3932     ubfx    r9, rINST, #8, #4           @ r9<- A
3933     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3934     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3935     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3936     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3937                                @ optional op; may set condition codes
3938     bl      d2l_doconv                              @ r0/r1<- op, r2-r3 changed
3939     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3940     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3941     GOTO_OPCODE(ip)                     @ jump to next instruction
3942     /* 10-11 instructions */
3943
3944
3945
3946
3947 /* ------------------------------ */
3948     .balign 64
3949 .L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
3950 /* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */
3951 /* File: arm-vfp/funopNarrower.S */
3952     /*
3953      * Generic 64bit-to-32bit unary floating point operation.  Provide an
3954      * "instr" line that specifies an instruction that performs "s0 = op d0".
3955      *
3956      * For: double-to-int, double-to-float
3957      */
3958     /* unop vA, vB */
3959     mov     r3, rINST, lsr #12          @ r3<- B
3960     mov     r9, rINST, lsr #8           @ r9<- A+
3961     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3962     fldd    d0, [r3]                    @ d0<- vB
3963     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3964     and     r9, r9, #15                 @ r9<- A
3965     fcvtsd  s0, d0                              @ s0<- op
3966     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3967     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3968     fsts    s0, [r9]                    @ vA<- s0
3969     GOTO_OPCODE(ip)                     @ jump to next instruction
3970
3971
3972 /* ------------------------------ */
3973     .balign 64
3974 .L_OP_INT_TO_BYTE: /* 0x8d */
3975 /* File: armv6t2/OP_INT_TO_BYTE.S */
3976 /* File: armv6t2/unop.S */
3977     /*
3978      * Generic 32-bit unary operation.  Provide an "instr" line that
3979      * specifies an instruction that performs "result = op r0".
3980      * This could be an ARM instruction or a function call.
3981      *
3982      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3983      *      int-to-byte, int-to-char, int-to-short
3984      */
3985     /* unop vA, vB */
3986     mov     r3, rINST, lsr #12          @ r3<- B
3987     ubfx    r9, rINST, #8, #4           @ r9<- A
3988     GET_VREG(r0, r3)                    @ r0<- vB
3989                                @ optional op; may set condition codes
3990     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3991     sxtb    r0, r0                              @ r0<- op, r0-r3 changed
3992     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3993     SET_VREG(r0, r9)                    @ vAA<- r0
3994     GOTO_OPCODE(ip)                     @ jump to next instruction
3995     /* 8-9 instructions */
3996
3997
3998 /* ------------------------------ */
3999     .balign 64
4000 .L_OP_INT_TO_CHAR: /* 0x8e */
4001 /* File: armv6t2/OP_INT_TO_CHAR.S */
4002 /* File: armv6t2/unop.S */
4003     /*
4004      * Generic 32-bit unary operation.  Provide an "instr" line that
4005      * specifies an instruction that performs "result = op r0".
4006      * This could be an ARM instruction or a function call.
4007      *
4008      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4009      *      int-to-byte, int-to-char, int-to-short
4010      */
4011     /* unop vA, vB */
4012     mov     r3, rINST, lsr #12          @ r3<- B
4013     ubfx    r9, rINST, #8, #4           @ r9<- A
4014     GET_VREG(r0, r3)                    @ r0<- vB
4015                                @ optional op; may set condition codes
4016     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4017     uxth    r0, r0                              @ r0<- op, r0-r3 changed
4018     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4019     SET_VREG(r0, r9)                    @ vAA<- r0
4020     GOTO_OPCODE(ip)                     @ jump to next instruction
4021     /* 8-9 instructions */
4022
4023
4024 /* ------------------------------ */
4025     .balign 64
4026 .L_OP_INT_TO_SHORT: /* 0x8f */
4027 /* File: armv6t2/OP_INT_TO_SHORT.S */
4028 /* File: armv6t2/unop.S */
4029     /*
4030      * Generic 32-bit unary operation.  Provide an "instr" line that
4031      * specifies an instruction that performs "result = op r0".
4032      * This could be an ARM instruction or a function call.
4033      *
4034      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4035      *      int-to-byte, int-to-char, int-to-short
4036      */
4037     /* unop vA, vB */
4038     mov     r3, rINST, lsr #12          @ r3<- B
4039     ubfx    r9, rINST, #8, #4           @ r9<- A
4040     GET_VREG(r0, r3)                    @ r0<- vB
4041                                @ optional op; may set condition codes
4042     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4043     sxth    r0, r0                              @ r0<- op, r0-r3 changed
4044     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4045     SET_VREG(r0, r9)                    @ vAA<- r0
4046     GOTO_OPCODE(ip)                     @ jump to next instruction
4047     /* 8-9 instructions */
4048
4049
4050 /* ------------------------------ */
4051     .balign 64
4052 .L_OP_ADD_INT: /* 0x90 */
4053 /* File: armv5te/OP_ADD_INT.S */
4054 /* File: armv5te/binop.S */
4055     /*
4056      * Generic 32-bit binary operation.  Provide an "instr" line that
4057      * specifies an instruction that performs "result = r0 op r1".
4058      * This could be an ARM instruction or a function call.  (If the result
4059      * comes back in a register other than r0, you can override "result".)
4060      *
4061      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4062      * vCC (r1).  Useful for integer division and modulus.  Note that we
4063      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4064      * handles it correctly.
4065      *
4066      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4067      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4068      *      mul-float, div-float, rem-float
4069      */
4070     /* binop vAA, vBB, vCC */
4071     FETCH(r0, 1)                        @ r0<- CCBB
4072     mov     r9, rINST, lsr #8           @ r9<- AA
4073     mov     r3, r0, lsr #8              @ r3<- CC
4074     and     r2, r0, #255                @ r2<- BB
4075     GET_VREG(r1, r3)                    @ r1<- vCC
4076     GET_VREG(r0, r2)                    @ r0<- vBB
4077     .if 0
4078     cmp     r1, #0                      @ is second operand zero?
4079     beq     common_errDivideByZero
4080     .endif
4081
4082     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4083                                @ optional op; may set condition codes
4084     add     r0, r0, r1                              @ r0<- op, r0-r3 changed
4085     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4086     SET_VREG(r0, r9)               @ vAA<- r0
4087     GOTO_OPCODE(ip)                     @ jump to next instruction
4088     /* 11-14 instructions */
4089
4090
4091
4092 /* ------------------------------ */
4093     .balign 64
4094 .L_OP_SUB_INT: /* 0x91 */
4095 /* File: armv5te/OP_SUB_INT.S */
4096 /* File: armv5te/binop.S */
4097     /*
4098      * Generic 32-bit binary operation.  Provide an "instr" line that
4099      * specifies an instruction that performs "result = r0 op r1".
4100      * This could be an ARM instruction or a function call.  (If the result
4101      * comes back in a register other than r0, you can override "result".)
4102      *
4103      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4104      * vCC (r1).  Useful for integer division and modulus.  Note that we
4105      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4106      * handles it correctly.
4107      *
4108      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4109      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4110      *      mul-float, div-float, rem-float
4111      */
4112     /* binop vAA, vBB, vCC */
4113     FETCH(r0, 1)                        @ r0<- CCBB
4114     mov     r9, rINST, lsr #8           @ r9<- AA
4115     mov     r3, r0, lsr #8              @ r3<- CC
4116     and     r2, r0, #255                @ r2<- BB
4117     GET_VREG(r1, r3)                    @ r1<- vCC
4118     GET_VREG(r0, r2)                    @ r0<- vBB
4119     .if 0
4120     cmp     r1, #0                      @ is second operand zero?
4121     beq     common_errDivideByZero
4122     .endif
4123
4124     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4125                                @ optional op; may set condition codes
4126     sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
4127     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4128     SET_VREG(r0, r9)               @ vAA<- r0
4129     GOTO_OPCODE(ip)                     @ jump to next instruction
4130     /* 11-14 instructions */
4131
4132
4133
4134 /* ------------------------------ */
4135     .balign 64
4136 .L_OP_MUL_INT: /* 0x92 */
4137 /* File: armv5te/OP_MUL_INT.S */
4138 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
4139 /* File: armv5te/binop.S */
4140     /*
4141      * Generic 32-bit binary operation.  Provide an "instr" line that
4142      * specifies an instruction that performs "result = r0 op r1".
4143      * This could be an ARM instruction or a function call.  (If the result
4144      * comes back in a register other than r0, you can override "result".)
4145      *
4146      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4147      * vCC (r1).  Useful for integer division and modulus.  Note that we
4148      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4149      * handles it correctly.
4150      *
4151      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4152      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4153      *      mul-float, div-float, rem-float
4154      */
4155     /* binop vAA, vBB, vCC */
4156     FETCH(r0, 1)                        @ r0<- CCBB
4157     mov     r9, rINST, lsr #8           @ r9<- AA
4158     mov     r3, r0, lsr #8              @ r3<- CC
4159     and     r2, r0, #255                @ r2<- BB
4160     GET_VREG(r1, r3)                    @ r1<- vCC
4161     GET_VREG(r0, r2)                    @ r0<- vBB
4162     .if 0
4163     cmp     r1, #0                      @ is second operand zero?
4164     beq     common_errDivideByZero
4165     .endif
4166
4167     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4168                                @ optional op; may set condition codes
4169     mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
4170     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4171     SET_VREG(r0, r9)               @ vAA<- r0
4172     GOTO_OPCODE(ip)                     @ jump to next instruction
4173     /* 11-14 instructions */
4174
4175
4176
4177 /* ------------------------------ */
4178     .balign 64
4179 .L_OP_DIV_INT: /* 0x93 */
4180 /* File: armv5te/OP_DIV_INT.S */
4181 /* File: armv5te/binop.S */
4182     /*
4183      * Generic 32-bit binary operation.  Provide an "instr" line that
4184      * specifies an instruction that performs "result = r0 op r1".
4185      * This could be an ARM instruction or a function call.  (If the result
4186      * comes back in a register other than r0, you can override "result".)
4187      *
4188      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4189      * vCC (r1).  Useful for integer division and modulus.  Note that we
4190      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4191      * handles it correctly.
4192      *
4193      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4194      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4195      *      mul-float, div-float, rem-float
4196      */
4197     /* binop vAA, vBB, vCC */
4198     FETCH(r0, 1)                        @ r0<- CCBB
4199     mov     r9, rINST, lsr #8           @ r9<- AA
4200     mov     r3, r0, lsr #8              @ r3<- CC
4201     and     r2, r0, #255                @ r2<- BB
4202     GET_VREG(r1, r3)                    @ r1<- vCC
4203     GET_VREG(r0, r2)                    @ r0<- vBB
4204     .if 1
4205     cmp     r1, #0                      @ is second operand zero?
4206     beq     common_errDivideByZero
4207     .endif
4208
4209     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4210                                @ optional op; may set condition codes
4211     bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
4212     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4213     SET_VREG(r0, r9)               @ vAA<- r0
4214     GOTO_OPCODE(ip)                     @ jump to next instruction
4215     /* 11-14 instructions */
4216
4217
4218
4219 /* ------------------------------ */
4220     .balign 64
4221 .L_OP_REM_INT: /* 0x94 */
4222 /* File: armv5te/OP_REM_INT.S */
4223 /* idivmod returns quotient in r0 and remainder in r1 */
4224 /* File: armv5te/binop.S */
4225     /*
4226      * Generic 32-bit binary operation.  Provide an "instr" line that
4227      * specifies an instruction that performs "result = r0 op r1".
4228      * This could be an ARM instruction or a function call.  (If the result
4229      * comes back in a register other than r0, you can override "result".)
4230      *
4231      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4232      * vCC (r1).  Useful for integer division and modulus.  Note that we
4233      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4234      * handles it correctly.
4235      *
4236      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4237      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4238      *      mul-float, div-float, rem-float
4239      */
4240     /* binop vAA, vBB, vCC */
4241     FETCH(r0, 1)                        @ r0<- CCBB
4242     mov     r9, rINST, lsr #8           @ r9<- AA
4243     mov     r3, r0, lsr #8              @ r3<- CC
4244     and     r2, r0, #255                @ r2<- BB
4245     GET_VREG(r1, r3)                    @ r1<- vCC
4246     GET_VREG(r0, r2)                    @ r0<- vBB
4247     .if 1
4248     cmp     r1, #0                      @ is second operand zero?
4249     beq     common_errDivideByZero
4250     .endif
4251
4252     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4253                                @ optional op; may set condition codes
4254     bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
4255     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4256     SET_VREG(r1, r9)               @ vAA<- r1
4257     GOTO_OPCODE(ip)                     @ jump to next instruction
4258     /* 11-14 instructions */
4259
4260
4261
4262 /* ------------------------------ */
4263     .balign 64
4264 .L_OP_AND_INT: /* 0x95 */
4265 /* File: armv5te/OP_AND_INT.S */
4266 /* File: armv5te/binop.S */
4267     /*
4268      * Generic 32-bit binary operation.  Provide an "instr" line that
4269      * specifies an instruction that performs "result = r0 op r1".
4270      * This could be an ARM instruction or a function call.  (If the result
4271      * comes back in a register other than r0, you can override "result".)
4272      *
4273      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4274      * vCC (r1).  Useful for integer division and modulus.  Note that we
4275      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4276      * handles it correctly.
4277      *
4278      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4279      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4280      *      mul-float, div-float, rem-float
4281      */
4282     /* binop vAA, vBB, vCC */
4283     FETCH(r0, 1)                        @ r0<- CCBB
4284     mov     r9, rINST, lsr #8           @ r9<- AA
4285     mov     r3, r0, lsr #8              @ r3<- CC
4286     and     r2, r0, #255                @ r2<- BB
4287     GET_VREG(r1, r3)                    @ r1<- vCC
4288     GET_VREG(r0, r2)                    @ r0<- vBB
4289     .if 0
4290     cmp     r1, #0                      @ is second operand zero?
4291     beq     common_errDivideByZero
4292     .endif
4293
4294     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4295                                @ optional op; may set condition codes
4296     and     r0, r0, r1                              @ r0<- op, r0-r3 changed
4297     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4298     SET_VREG(r0, r9)               @ vAA<- r0
4299     GOTO_OPCODE(ip)                     @ jump to next instruction
4300     /* 11-14 instructions */
4301
4302
4303
4304 /* ------------------------------ */
4305     .balign 64
4306 .L_OP_OR_INT: /* 0x96 */
4307 /* File: armv5te/OP_OR_INT.S */
4308 /* File: armv5te/binop.S */
4309     /*
4310      * Generic 32-bit binary operation.  Provide an "instr" line that
4311      * specifies an instruction that performs "result = r0 op r1".
4312      * This could be an ARM instruction or a function call.  (If the result
4313      * comes back in a register other than r0, you can override "result".)
4314      *
4315      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4316      * vCC (r1).  Useful for integer division and modulus.  Note that we
4317      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4318      * handles it correctly.
4319      *
4320      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4321      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4322      *      mul-float, div-float, rem-float
4323      */
4324     /* binop vAA, vBB, vCC */
4325     FETCH(r0, 1)                        @ r0<- CCBB
4326     mov     r9, rINST, lsr #8           @ r9<- AA
4327     mov     r3, r0, lsr #8              @ r3<- CC
4328     and     r2, r0, #255                @ r2<- BB
4329     GET_VREG(r1, r3)                    @ r1<- vCC
4330     GET_VREG(r0, r2)                    @ r0<- vBB
4331     .if 0
4332     cmp     r1, #0                      @ is second operand zero?
4333     beq     common_errDivideByZero
4334     .endif
4335
4336     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4337                                @ optional op; may set condition codes
4338     orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
4339     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4340     SET_VREG(r0, r9)               @ vAA<- r0
4341     GOTO_OPCODE(ip)                     @ jump to next instruction
4342     /* 11-14 instructions */
4343
4344
4345
4346 /* ------------------------------ */
4347     .balign 64
4348 .L_OP_XOR_INT: /* 0x97 */
4349 /* File: armv5te/OP_XOR_INT.S */
4350 /* File: armv5te/binop.S */
4351     /*
4352      * Generic 32-bit binary operation.  Provide an "instr" line that
4353      * specifies an instruction that performs "result = r0 op r1".
4354      * This could be an ARM instruction or a function call.  (If the result
4355      * comes back in a register other than r0, you can override "result".)
4356      *
4357      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4358      * vCC (r1).  Useful for integer division and modulus.  Note that we
4359      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4360      * handles it correctly.
4361      *
4362      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4363      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4364      *      mul-float, div-float, rem-float
4365      */
4366     /* binop vAA, vBB, vCC */
4367     FETCH(r0, 1)                        @ r0<- CCBB
4368     mov     r9, rINST, lsr #8           @ r9<- AA
4369     mov     r3, r0, lsr #8              @ r3<- CC
4370     and     r2, r0, #255                @ r2<- BB
4371     GET_VREG(r1, r3)                    @ r1<- vCC
4372     GET_VREG(r0, r2)                    @ r0<- vBB
4373     .if 0
4374     cmp     r1, #0                      @ is second operand zero?
4375     beq     common_errDivideByZero
4376     .endif
4377
4378     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4379                                @ optional op; may set condition codes
4380     eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
4381     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4382     SET_VREG(r0, r9)               @ vAA<- r0
4383     GOTO_OPCODE(ip)                     @ jump to next instruction
4384     /* 11-14 instructions */
4385
4386
4387
4388 /* ------------------------------ */
4389     .balign 64
4390 .L_OP_SHL_INT: /* 0x98 */
4391 /* File: armv5te/OP_SHL_INT.S */
4392 /* File: armv5te/binop.S */
4393     /*
4394      * Generic 32-bit binary operation.  Provide an "instr" line that
4395      * specifies an instruction that performs "result = r0 op r1".
4396      * This could be an ARM instruction or a function call.  (If the result
4397      * comes back in a register other than r0, you can override "result".)
4398      *
4399      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4400      * vCC (r1).  Useful for integer division and modulus.  Note that we
4401      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4402      * handles it correctly.
4403      *
4404      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4405      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4406      *      mul-float, div-float, rem-float
4407      */
4408     /* binop vAA, vBB, vCC */
4409     FETCH(r0, 1)                        @ r0<- CCBB
4410     mov     r9, rINST, lsr #8           @ r9<- AA
4411     mov     r3, r0, lsr #8              @ r3<- CC
4412     and     r2, r0, #255                @ r2<- BB
4413     GET_VREG(r1, r3)                    @ r1<- vCC
4414     GET_VREG(r0, r2)                    @ r0<- vBB
4415     .if 0
4416     cmp     r1, #0                      @ is second operand zero?
4417     beq     common_errDivideByZero
4418     .endif
4419
4420     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4421     and     r1, r1, #31                           @ optional op; may set condition codes
4422     mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
4423     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4424     SET_VREG(r0, r9)               @ vAA<- r0
4425     GOTO_OPCODE(ip)                     @ jump to next instruction
4426     /* 11-14 instructions */
4427
4428
4429
4430 /* ------------------------------ */
4431     .balign 64
4432 .L_OP_SHR_INT: /* 0x99 */
4433 /* File: armv5te/OP_SHR_INT.S */
4434 /* File: armv5te/binop.S */
4435     /*
4436      * Generic 32-bit binary operation.  Provide an "instr" line that
4437      * specifies an instruction that performs "result = r0 op r1".
4438      * This could be an ARM instruction or a function call.  (If the result
4439      * comes back in a register other than r0, you can override "result".)
4440      *
4441      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4442      * vCC (r1).  Useful for integer division and modulus.  Note that we
4443      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4444      * handles it correctly.
4445      *
4446      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4447      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4448      *      mul-float, div-float, rem-float
4449      */
4450     /* binop vAA, vBB, vCC */
4451     FETCH(r0, 1)                        @ r0<- CCBB
4452     mov     r9, rINST, lsr #8           @ r9<- AA
4453     mov     r3, r0, lsr #8              @ r3<- CC
4454     and     r2, r0, #255                @ r2<- BB
4455     GET_VREG(r1, r3)                    @ r1<- vCC
4456     GET_VREG(r0, r2)                    @ r0<- vBB
4457     .if 0
4458     cmp     r1, #0                      @ is second operand zero?
4459     beq     common_errDivideByZero
4460     .endif
4461
4462     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4463     and     r1, r1, #31                           @ optional op; may set condition codes
4464     mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
4465     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4466     SET_VREG(r0, r9)               @ vAA<- r0
4467     GOTO_OPCODE(ip)                     @ jump to next instruction
4468     /* 11-14 instructions */
4469
4470
4471
4472 /* ------------------------------ */
4473     .balign 64
4474 .L_OP_USHR_INT: /* 0x9a */
4475 /* File: armv5te/OP_USHR_INT.S */
4476 /* File: armv5te/binop.S */
4477     /*
4478      * Generic 32-bit binary operation.  Provide an "instr" line that
4479      * specifies an instruction that performs "result = r0 op r1".
4480      * This could be an ARM instruction or a function call.  (If the result
4481      * comes back in a register other than r0, you can override "result".)
4482      *
4483      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4484      * vCC (r1).  Useful for integer division and modulus.  Note that we
4485      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4486      * handles it correctly.
4487      *
4488      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4489      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4490      *      mul-float, div-float, rem-float
4491      */
4492     /* binop vAA, vBB, vCC */
4493     FETCH(r0, 1)                        @ r0<- CCBB
4494     mov     r9, rINST, lsr #8           @ r9<- AA
4495     mov     r3, r0, lsr #8              @ r3<- CC
4496     and     r2, r0, #255                @ r2<- BB
4497     GET_VREG(r1, r3)                    @ r1<- vCC
4498     GET_VREG(r0, r2)                    @ r0<- vBB
4499     .if 0
4500     cmp     r1, #0                      @ is second operand zero?
4501     beq     common_errDivideByZero
4502     .endif
4503
4504     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4505     and     r1, r1, #31                           @ optional op; may set condition codes
4506     mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
4507     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4508     SET_VREG(r0, r9)               @ vAA<- r0
4509     GOTO_OPCODE(ip)                     @ jump to next instruction
4510     /* 11-14 instructions */
4511
4512
4513
4514 /* ------------------------------ */
4515     .balign 64
4516 .L_OP_ADD_LONG: /* 0x9b */
4517 /* File: armv5te/OP_ADD_LONG.S */
4518 /* File: armv5te/binopWide.S */
4519     /*
4520      * Generic 64-bit binary operation.  Provide an "instr" line that
4521      * specifies an instruction that performs "result = r0-r1 op r2-r3".
4522      * This could be an ARM instruction or a function call.  (If the result
4523      * comes back in a register other than r0, you can override "result".)
4524      *
4525      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4526      * vCC (r1).  Useful for integer division and modulus.
4527      *
4528      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4529      *      xor-long, add-double, sub-double, mul-double, div-double,
4530      *      rem-double
4531      *
4532      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4533      */
4534     /* binop vAA, vBB, vCC */
4535     FETCH(r0, 1)                        @ r0<- CCBB
4536     mov     r9, rINST, lsr #8           @ r9<- AA
4537     and     r2, r0, #255                @ r2<- BB
4538     mov     r3, r0, lsr #8              @ r3<- CC
4539     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4540     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4541     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4542     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4543     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4544     .if 0
4545     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4546     beq     common_errDivideByZero
4547     .endif
4548     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4549
4550     adds    r0, r0, r2                           @ optional op; may set condition codes
4551     adc     r1, r1, r3                              @ result<- op, r0-r3 changed
4552     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4553     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4554     GOTO_OPCODE(ip)                     @ jump to next instruction
4555     /* 14-17 instructions */
4556
4557
4558
4559 /* ------------------------------ */
4560     .balign 64
4561 .L_OP_SUB_LONG: /* 0x9c */
4562 /* File: armv5te/OP_SUB_LONG.S */
4563 /* File: armv5te/binopWide.S */
4564     /*
4565      * Generic 64-bit binary operation.  Provide an "instr" line that
4566      * specifies an instruction that performs "result = r0-r1 op r2-r3".
4567      * This could be an ARM instruction or a function call.  (If the result
4568      * comes back in a register other than r0, you can override "result".)
4569      *
4570      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4571      * vCC (r1).  Useful for integer division and modulus.
4572      *
4573      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4574      *      xor-long, add-double, sub-double, mul-double, div-double,
4575      *      rem-double
4576      *
4577      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4578      */
4579     /* binop vAA, vBB, vCC */
4580     FETCH(r0, 1)                        @ r0<- CCBB
4581     mov     r9, rINST, lsr #8           @ r9<- AA
4582     and     r2, r0, #255                @ r2<- BB
4583     mov     r3, r0, lsr #8              @ r3<- CC
4584     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4585     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4586     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4587     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4588     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4589     .if 0
4590     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4591     beq     common_errDivideByZero
4592     .endif
4593     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4594
4595     subs    r0, r0, r2                           @ optional op; may set condition codes
4596     sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
4597     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4598     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4599     GOTO_OPCODE(ip)                     @ jump to next instruction
4600     /* 14-17 instructions */
4601
4602
4603
4604 /* ------------------------------ */
4605     .balign 64
4606 .L_OP_MUL_LONG: /* 0x9d */
4607 /* File: armv5te/OP_MUL_LONG.S */
4608     /*
4609      * Signed 64-bit integer multiply.
4610      *
4611      * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
4612      *        WX
4613      *      x YZ
4614      *  --------
4615      *     ZW ZX
4616      *  YW YX
4617      *
4618      * The low word of the result holds ZX, the high word holds
4619      * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
4620      * it doesn't fit in the low 64 bits.
4621      *
4622      * Unlike most ARM math operations, multiply instructions have
4623      * restrictions on using the same register more than once (Rd and Rm
4624      * cannot be the same).
4625      */
4626     /* mul-long vAA, vBB, vCC */
4627     FETCH(r0, 1)                        @ r0<- CCBB
4628     and     r2, r0, #255                @ r2<- BB
4629     mov     r3, r0, lsr #8              @ r3<- CC
4630     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4631     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4632     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4633     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4634     mul     ip, r2, r1                  @  ip<- ZxW
4635     umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
4636     mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
4637     mov     r0, rINST, lsr #8           @ r0<- AA
4638     add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
4639     add     r0, rFP, r0, lsl #2         @ r0<- &fp[AA]
4640     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4641     b       .LOP_MUL_LONG_finish
4642
4643 /* ------------------------------ */
4644     .balign 64
4645 .L_OP_DIV_LONG: /* 0x9e */
4646 /* File: armv5te/OP_DIV_LONG.S */
4647 /* File: armv5te/binopWide.S */
4648     /*
4649      * Generic 64-bit binary operation.  Provide an "instr" line that
4650      * specifies an instruction that performs "result = r0-r1 op r2-r3".
4651      * This could be an ARM instruction or a function call.  (If the result
4652      * comes back in a register other than r0, you can override "result".)
4653      *
4654      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4655      * vCC (r1).  Useful for integer division and modulus.
4656      *
4657      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4658      *      xor-long, add-double, sub-double, mul-double, div-double,
4659      *      rem-double
4660      *
4661      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4662      */
4663     /* binop vAA, vBB, vCC */
4664     FETCH(r0, 1)                        @ r0<- CCBB
4665     mov     r9, rINST, lsr #8           @ r9<- AA
4666     and     r2, r0, #255                @ r2<- BB
4667     mov     r3, r0, lsr #8              @ r3<- CC
4668     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4669     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4670     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4671     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4672     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4673     .if 1
4674     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4675     beq     common_errDivideByZero
4676     .endif
4677     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4678
4679                                @ optional op; may set condition codes
4680     bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4681     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4682     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4683     GOTO_OPCODE(ip)                     @ jump to next instruction
4684     /* 14-17 instructions */
4685
4686
4687
4688 /* ------------------------------ */
4689     .balign 64
4690 .L_OP_REM_LONG: /* 0x9f */
4691 /* File: armv5te/OP_REM_LONG.S */
4692 /* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
4693 /* File: armv5te/binopWide.S */
4694     /*
4695      * Generic 64-bit binary operation.  Provide an "instr" line that
4696      * specifies an instruction that performs "result = r0-r1 op r2-r3".
4697      * This could be an ARM instruction or a function call.  (If the result
4698      * comes back in a register other than r0, you can override "result".)
4699      *
4700      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4701      * vCC (r1).  Useful for integer division and modulus.
4702      *
4703      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4704      *      xor-long, add-double, sub-double, mul-double, div-double,
4705      *      rem-double
4706      *
4707      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4708      */
4709     /* binop vAA, vBB, vCC */
4710     FETCH(r0, 1)                        @ r0<- CCBB
4711     mov     r9, rINST, lsr #8           @ r9<- AA
4712     and     r2, r0, #255                @ r2<- BB
4713     mov     r3, r0, lsr #8              @ r3<- CC
4714     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4715     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4716     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4717     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4718     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4719     .if 1
4720     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4721     beq     common_errDivideByZero
4722     .endif
4723     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4724
4725                                @ optional op; may set condition codes
4726     bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4727     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4728     stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
4729     GOTO_OPCODE(ip)                     @ jump to next instruction
4730     /* 14-17 instructions */
4731
4732
4733
4734 /* ------------------------------ */
4735     .balign 64
4736 .L_OP_AND_LONG: /* 0xa0 */
4737 /* File: armv5te/OP_AND_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     and     r0, r0, r2                           @ optional op; may set condition codes
4771     and     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 /* ------------------------------ */
4780     .balign 64
4781 .L_OP_OR_LONG: /* 0xa1 */
4782 /* File: armv5te/OP_OR_LONG.S */
4783 /* File: armv5te/binopWide.S */
4784     /*
4785      * Generic 64-bit binary operation.  Provide an "instr" line that
4786      * specifies an instruction that performs "result = r0-r1 op r2-r3".
4787      * This could be an ARM instruction or a function call.  (If the result
4788      * comes back in a register other than r0, you can override "result".)
4789      *
4790      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4791      * vCC (r1).  Useful for integer division and modulus.
4792      *
4793      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4794      *      xor-long, add-double, sub-double, mul-double, div-double,
4795      *      rem-double
4796      *
4797      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4798      */
4799     /* binop vAA, vBB, vCC */
4800     FETCH(r0, 1)                        @ r0<- CCBB
4801     mov     r9, rINST, lsr #8           @ r9<- AA
4802     and     r2, r0, #255                @ r2<- BB
4803     mov     r3, r0, lsr #8              @ r3<- CC
4804     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4805     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4806     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4807     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4808     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4809     .if 0
4810     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4811     beq     common_errDivideByZero
4812     .endif
4813     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4814
4815     orr     r0, r0, r2                           @ optional op; may set condition codes
4816     orr     r1, r1, r3                              @ result<- op, r0-r3 changed
4817     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4818     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4819     GOTO_OPCODE(ip)                     @ jump to next instruction
4820     /* 14-17 instructions */
4821
4822
4823
4824 /* ------------------------------ */
4825     .balign 64
4826 .L_OP_XOR_LONG: /* 0xa2 */
4827 /* File: armv5te/OP_XOR_LONG.S */
4828 /* File: armv5te/binopWide.S */
4829     /*
4830      * Generic 64-bit binary operation.  Provide an "instr" line that
4831      * specifies an instruction that performs "result = r0-r1 op r2-r3".
4832      * This could be an ARM instruction or a function call.  (If the result
4833      * comes back in a register other than r0, you can override "result".)
4834      *
4835      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4836      * vCC (r1).  Useful for integer division and modulus.
4837      *
4838      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4839      *      xor-long, add-double, sub-double, mul-double, div-double,
4840      *      rem-double
4841      *
4842      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4843      */
4844     /* binop vAA, vBB, vCC */
4845     FETCH(r0, 1)                        @ r0<- CCBB
4846     mov     r9, rINST, lsr #8           @ r9<- AA
4847     and     r2, r0, #255                @ r2<- BB
4848     mov     r3, r0, lsr #8              @ r3<- CC
4849     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4850     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4851     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4852     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4853     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4854     .if 0
4855     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4856     beq     common_errDivideByZero
4857     .endif
4858     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4859
4860     eor     r0, r0, r2                           @ optional op; may set condition codes
4861     eor     r1, r1, r3                              @ result<- op, r0-r3 changed
4862     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4863     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4864     GOTO_OPCODE(ip)                     @ jump to next instruction
4865     /* 14-17 instructions */
4866
4867
4868
4869 /* ------------------------------ */
4870     .balign 64
4871 .L_OP_SHL_LONG: /* 0xa3 */
4872 /* File: armv5te/OP_SHL_LONG.S */
4873     /*
4874      * Long integer shift.  This is different from the generic 32/64-bit
4875      * binary operations because vAA/vBB are 64-bit but vCC (the shift
4876      * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4877      * 6 bits of the shift distance.
4878      */
4879     /* shl-long vAA, vBB, vCC */
4880     FETCH(r0, 1)                        @ r0<- CCBB
4881     mov     r9, rINST, lsr #8           @ r9<- AA
4882     and     r3, r0, #255                @ r3<- BB
4883     mov     r0, r0, lsr #8              @ r0<- CC
4884     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4885     GET_VREG(r2, r0)                    @ r2<- vCC
4886     ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4887     and     r2, r2, #63                 @ r2<- r2 & 0x3f
4888     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4889
4890     mov     r1, r1, asl r2              @  r1<- r1 << r2
4891     rsb     r3, r2, #32                 @  r3<- 32 - r2
4892     orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
4893     subs    ip, r2, #32                 @  ip<- r2 - 32
4894     movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
4895     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4896     b       .LOP_SHL_LONG_finish
4897
4898 /* ------------------------------ */
4899     .balign 64
4900 .L_OP_SHR_LONG: /* 0xa4 */
4901 /* File: armv5te/OP_SHR_LONG.S */
4902     /*
4903      * Long integer shift.  This is different from the generic 32/64-bit
4904      * binary operations because vAA/vBB are 64-bit but vCC (the shift
4905      * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4906      * 6 bits of the shift distance.
4907      */
4908     /* shr-long vAA, vBB, vCC */
4909     FETCH(r0, 1)                        @ r0<- CCBB
4910     mov     r9, rINST, lsr #8           @ r9<- AA
4911     and     r3, r0, #255                @ r3<- BB
4912     mov     r0, r0, lsr #8              @ r0<- CC
4913     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4914     GET_VREG(r2, r0)                    @ r2<- vCC
4915     ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4916     and     r2, r2, #63                 @ r0<- r0 & 0x3f
4917     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4918
4919     mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4920     rsb     r3, r2, #32                 @  r3<- 32 - r2
4921     orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4922     subs    ip, r2, #32                 @  ip<- r2 - 32
4923     movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
4924     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4925     b       .LOP_SHR_LONG_finish
4926
4927 /* ------------------------------ */
4928     .balign 64
4929 .L_OP_USHR_LONG: /* 0xa5 */
4930 /* File: armv5te/OP_USHR_LONG.S */
4931     /*
4932      * Long integer shift.  This is different from the generic 32/64-bit
4933      * binary operations because vAA/vBB are 64-bit but vCC (the shift
4934      * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4935      * 6 bits of the shift distance.
4936      */
4937     /* ushr-long vAA, vBB, vCC */
4938     FETCH(r0, 1)                        @ r0<- CCBB
4939     mov     r9, rINST, lsr #8           @ r9<- AA
4940     and     r3, r0, #255                @ r3<- BB
4941     mov     r0, r0, lsr #8              @ r0<- CC
4942     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4943     GET_VREG(r2, r0)                    @ r2<- vCC
4944     ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4945     and     r2, r2, #63                 @ r0<- r0 & 0x3f
4946     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4947
4948     mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4949     rsb     r3, r2, #32                 @  r3<- 32 - r2
4950     orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4951     subs    ip, r2, #32                 @  ip<- r2 - 32
4952     movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
4953     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4954     b       .LOP_USHR_LONG_finish
4955
4956 /* ------------------------------ */
4957     .balign 64
4958 .L_OP_ADD_FLOAT: /* 0xa6 */
4959 /* File: arm-vfp/OP_ADD_FLOAT.S */
4960 /* File: arm-vfp/fbinop.S */
4961     /*
4962      * Generic 32-bit floating-point operation.  Provide an "instr" line that
4963      * specifies an instruction that performs "s2 = s0 op s1".  Because we
4964      * use the "softfp" ABI, this must be an instruction, not a function call.
4965      *
4966      * For: add-float, sub-float, mul-float, div-float
4967      */
4968     /* floatop vAA, vBB, vCC */
4969     FETCH(r0, 1)                        @ r0<- CCBB
4970     mov     r9, rINST, lsr #8           @ r9<- AA
4971     mov     r3, r0, lsr #8              @ r3<- CC
4972     and     r2, r0, #255                @ r2<- BB
4973     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
4974     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
4975     flds    s1, [r3]                    @ s1<- vCC
4976     flds    s0, [r2]                    @ s0<- vBB
4977
4978     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4979     fadds   s2, s0, s1                              @ s2<- op
4980     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4981     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
4982     fsts    s2, [r9]                    @ vAA<- s2
4983     GOTO_OPCODE(ip)                     @ jump to next instruction
4984
4985
4986 /* ------------------------------ */
4987     .balign 64
4988 .L_OP_SUB_FLOAT: /* 0xa7 */
4989 /* File: arm-vfp/OP_SUB_FLOAT.S */
4990 /* File: arm-vfp/fbinop.S */
4991     /*
4992      * Generic 32-bit floating-point operation.  Provide an "instr" line that
4993      * specifies an instruction that performs "s2 = s0 op s1".  Because we
4994      * use the "softfp" ABI, this must be an instruction, not a function call.
4995      *
4996      * For: add-float, sub-float, mul-float, div-float
4997      */
4998     /* floatop vAA, vBB, vCC */
4999     FETCH(r0, 1)                        @ r0<- CCBB
5000     mov     r9, rINST, lsr #8           @ r9<- AA
5001     mov     r3, r0, lsr #8              @ r3<- CC
5002     and     r2, r0, #255                @ r2<- BB
5003     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5004     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5005     flds    s1, [r3]                    @ s1<- vCC
5006     flds    s0, [r2]                    @ s0<- vBB
5007
5008     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5009     fsubs   s2, s0, s1                              @ s2<- op
5010     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5011     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5012     fsts    s2, [r9]                    @ vAA<- s2
5013     GOTO_OPCODE(ip)                     @ jump to next instruction
5014
5015
5016 /* ------------------------------ */
5017     .balign 64
5018 .L_OP_MUL_FLOAT: /* 0xa8 */
5019 /* File: arm-vfp/OP_MUL_FLOAT.S */
5020 /* File: arm-vfp/fbinop.S */
5021     /*
5022      * Generic 32-bit floating-point operation.  Provide an "instr" line that
5023      * specifies an instruction that performs "s2 = s0 op s1".  Because we
5024      * use the "softfp" ABI, this must be an instruction, not a function call.
5025      *
5026      * For: add-float, sub-float, mul-float, div-float
5027      */
5028     /* floatop vAA, vBB, vCC */
5029     FETCH(r0, 1)                        @ r0<- CCBB
5030     mov     r9, rINST, lsr #8           @ r9<- AA
5031     mov     r3, r0, lsr #8              @ r3<- CC
5032     and     r2, r0, #255                @ r2<- BB
5033     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5034     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5035     flds    s1, [r3]                    @ s1<- vCC
5036     flds    s0, [r2]                    @ s0<- vBB
5037
5038     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5039     fmuls   s2, s0, s1                              @ s2<- op
5040     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5041     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5042     fsts    s2, [r9]                    @ vAA<- s2
5043     GOTO_OPCODE(ip)                     @ jump to next instruction
5044
5045
5046 /* ------------------------------ */
5047     .balign 64
5048 .L_OP_DIV_FLOAT: /* 0xa9 */
5049 /* File: arm-vfp/OP_DIV_FLOAT.S */
5050 /* File: arm-vfp/fbinop.S */
5051     /*
5052      * Generic 32-bit floating-point operation.  Provide an "instr" line that
5053      * specifies an instruction that performs "s2 = s0 op s1".  Because we
5054      * use the "softfp" ABI, this must be an instruction, not a function call.
5055      *
5056      * For: add-float, sub-float, mul-float, div-float
5057      */
5058     /* floatop vAA, vBB, vCC */
5059     FETCH(r0, 1)                        @ r0<- CCBB
5060     mov     r9, rINST, lsr #8           @ r9<- AA
5061     mov     r3, r0, lsr #8              @ r3<- CC
5062     and     r2, r0, #255                @ r2<- BB
5063     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5064     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5065     flds    s1, [r3]                    @ s1<- vCC
5066     flds    s0, [r2]                    @ s0<- vBB
5067
5068     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5069     fdivs   s2, s0, s1                              @ s2<- op
5070     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5071     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5072     fsts    s2, [r9]                    @ vAA<- s2
5073     GOTO_OPCODE(ip)                     @ jump to next instruction
5074
5075
5076 /* ------------------------------ */
5077     .balign 64
5078 .L_OP_REM_FLOAT: /* 0xaa */
5079 /* File: armv5te/OP_REM_FLOAT.S */
5080 /* EABI doesn't define a float remainder function, but libm does */
5081 /* File: armv5te/binop.S */
5082     /*
5083      * Generic 32-bit binary operation.  Provide an "instr" line that
5084      * specifies an instruction that performs "result = r0 op r1".
5085      * This could be an ARM instruction or a function call.  (If the result
5086      * comes back in a register other than r0, you can override "result".)
5087      *
5088      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5089      * vCC (r1).  Useful for integer division and modulus.  Note that we
5090      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5091      * handles it correctly.
5092      *
5093      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5094      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5095      *      mul-float, div-float, rem-float
5096      */
5097     /* binop vAA, vBB, vCC */
5098     FETCH(r0, 1)                        @ r0<- CCBB
5099     mov     r9, rINST, lsr #8           @ r9<- AA
5100     mov     r3, r0, lsr #8              @ r3<- CC
5101     and     r2, r0, #255                @ r2<- BB
5102     GET_VREG(r1, r3)                    @ r1<- vCC
5103     GET_VREG(r0, r2)                    @ r0<- vBB
5104     .if 0
5105     cmp     r1, #0                      @ is second operand zero?
5106     beq     common_errDivideByZero
5107     .endif
5108
5109     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5110                                @ optional op; may set condition codes
5111     bl      fmodf                              @ r0<- op, r0-r3 changed
5112     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5113     SET_VREG(r0, r9)               @ vAA<- r0
5114     GOTO_OPCODE(ip)                     @ jump to next instruction
5115     /* 11-14 instructions */
5116
5117
5118
5119 /* ------------------------------ */
5120     .balign 64
5121 .L_OP_ADD_DOUBLE: /* 0xab */
5122 /* File: arm-vfp/OP_ADD_DOUBLE.S */
5123 /* File: arm-vfp/fbinopWide.S */
5124     /*
5125      * Generic 64-bit double-precision floating point binary operation.
5126      * Provide an "instr" line that specifies an instruction that performs
5127      * "d2 = d0 op d1".
5128      *
5129      * for: add-double, sub-double, mul-double, div-double
5130      */
5131     /* doubleop vAA, vBB, vCC */
5132     FETCH(r0, 1)                        @ r0<- CCBB
5133     mov     r9, rINST, lsr #8           @ r9<- AA
5134     mov     r3, r0, lsr #8              @ r3<- CC
5135     and     r2, r0, #255                @ r2<- BB
5136     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5137     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5138     fldd    d1, [r3]                    @ d1<- vCC
5139     fldd    d0, [r2]                    @ d0<- vBB
5140
5141     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5142     faddd   d2, d0, d1                              @ s2<- op
5143     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5144     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5145     fstd    d2, [r9]                    @ vAA<- d2
5146     GOTO_OPCODE(ip)                     @ jump to next instruction
5147
5148
5149 /* ------------------------------ */
5150     .balign 64
5151 .L_OP_SUB_DOUBLE: /* 0xac */
5152 /* File: arm-vfp/OP_SUB_DOUBLE.S */
5153 /* File: arm-vfp/fbinopWide.S */
5154     /*
5155      * Generic 64-bit double-precision floating point binary operation.
5156      * Provide an "instr" line that specifies an instruction that performs
5157      * "d2 = d0 op d1".
5158      *
5159      * for: add-double, sub-double, mul-double, div-double
5160      */
5161     /* doubleop vAA, vBB, vCC */
5162     FETCH(r0, 1)                        @ r0<- CCBB
5163     mov     r9, rINST, lsr #8           @ r9<- AA
5164     mov     r3, r0, lsr #8              @ r3<- CC
5165     and     r2, r0, #255                @ r2<- BB
5166     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5167     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5168     fldd    d1, [r3]                    @ d1<- vCC
5169     fldd    d0, [r2]                    @ d0<- vBB
5170
5171     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5172     fsubd   d2, d0, d1                              @ s2<- op
5173     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5174     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5175     fstd    d2, [r9]                    @ vAA<- d2
5176     GOTO_OPCODE(ip)                     @ jump to next instruction
5177
5178
5179 /* ------------------------------ */
5180     .balign 64
5181 .L_OP_MUL_DOUBLE: /* 0xad */
5182 /* File: arm-vfp/OP_MUL_DOUBLE.S */
5183 /* File: arm-vfp/fbinopWide.S */
5184     /*
5185      * Generic 64-bit double-precision floating point binary operation.
5186      * Provide an "instr" line that specifies an instruction that performs
5187      * "d2 = d0 op d1".
5188      *
5189      * for: add-double, sub-double, mul-double, div-double
5190      */
5191     /* doubleop vAA, vBB, vCC */
5192     FETCH(r0, 1)                        @ r0<- CCBB
5193     mov     r9, rINST, lsr #8           @ r9<- AA
5194     mov     r3, r0, lsr #8              @ r3<- CC
5195     and     r2, r0, #255                @ r2<- BB
5196     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5197     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5198     fldd    d1, [r3]                    @ d1<- vCC
5199     fldd    d0, [r2]                    @ d0<- vBB
5200
5201     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5202     fmuld   d2, d0, d1                              @ s2<- op
5203     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5204     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5205     fstd    d2, [r9]                    @ vAA<- d2
5206     GOTO_OPCODE(ip)                     @ jump to next instruction
5207
5208
5209 /* ------------------------------ */
5210     .balign 64
5211 .L_OP_DIV_DOUBLE: /* 0xae */
5212 /* File: arm-vfp/OP_DIV_DOUBLE.S */
5213 /* File: arm-vfp/fbinopWide.S */
5214     /*
5215      * Generic 64-bit double-precision floating point binary operation.
5216      * Provide an "instr" line that specifies an instruction that performs
5217      * "d2 = d0 op d1".
5218      *
5219      * for: add-double, sub-double, mul-double, div-double
5220      */
5221     /* doubleop vAA, vBB, vCC */
5222     FETCH(r0, 1)                        @ r0<- CCBB
5223     mov     r9, rINST, lsr #8           @ r9<- AA
5224     mov     r3, r0, lsr #8              @ r3<- CC
5225     and     r2, r0, #255                @ r2<- BB
5226     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5227     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5228     fldd    d1, [r3]                    @ d1<- vCC
5229     fldd    d0, [r2]                    @ d0<- vBB
5230
5231     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5232     fdivd   d2, d0, d1                              @ s2<- op
5233     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5234     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5235     fstd    d2, [r9]                    @ vAA<- d2
5236     GOTO_OPCODE(ip)                     @ jump to next instruction
5237
5238
5239 /* ------------------------------ */
5240     .balign 64
5241 .L_OP_REM_DOUBLE: /* 0xaf */
5242 /* File: armv5te/OP_REM_DOUBLE.S */
5243 /* EABI doesn't define a double remainder function, but libm does */
5244 /* File: armv5te/binopWide.S */
5245     /*
5246      * Generic 64-bit binary operation.  Provide an "instr" line that
5247      * specifies an instruction that performs "result = r0-r1 op r2-r3".
5248      * This could be an ARM instruction or a function call.  (If the result
5249      * comes back in a register other than r0, you can override "result".)
5250      *
5251      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5252      * vCC (r1).  Useful for integer division and modulus.
5253      *
5254      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5255      *      xor-long, add-double, sub-double, mul-double, div-double,
5256      *      rem-double
5257      *
5258      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5259      */
5260     /* binop vAA, vBB, vCC */
5261     FETCH(r0, 1)                        @ r0<- CCBB
5262     mov     r9, rINST, lsr #8           @ r9<- AA
5263     and     r2, r0, #255                @ r2<- BB
5264     mov     r3, r0, lsr #8              @ r3<- CC
5265     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5266     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5267     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5268     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5269     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5270     .if 0
5271     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5272     beq     common_errDivideByZero
5273     .endif
5274     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5275
5276                                @ optional op; may set condition codes
5277     bl      fmod                              @ result<- op, r0-r3 changed
5278     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5279     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5280     GOTO_OPCODE(ip)                     @ jump to next instruction
5281     /* 14-17 instructions */
5282
5283
5284
5285 /* ------------------------------ */
5286     .balign 64
5287 .L_OP_ADD_INT_2ADDR: /* 0xb0 */
5288 /* File: armv6t2/OP_ADD_INT_2ADDR.S */
5289 /* File: armv6t2/binop2addr.S */
5290     /*
5291      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5292      * that specifies an instruction that performs "result = r0 op r1".
5293      * This could be an ARM instruction or a function call.  (If the result
5294      * comes back in a register other than r0, you can override "result".)
5295      *
5296      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5297      * vCC (r1).  Useful for integer division and modulus.
5298      *
5299      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5300      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5301      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5302      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5303      */
5304     /* binop/2addr vA, vB */
5305     mov     r3, rINST, lsr #12          @ r3<- B
5306     ubfx    r9, rINST, #8, #4           @ r9<- A
5307     GET_VREG(r1, r3)                    @ r1<- vB
5308     GET_VREG(r0, r9)                    @ r0<- vA
5309     .if 0
5310     cmp     r1, #0                      @ is second operand zero?
5311     beq     common_errDivideByZero
5312     .endif
5313     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5314
5315                                @ optional op; may set condition codes
5316     add     r0, r0, r1                              @ r0<- op, r0-r3 changed
5317     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5318     SET_VREG(r0, r9)               @ vAA<- r0
5319     GOTO_OPCODE(ip)                     @ jump to next instruction
5320     /* 10-13 instructions */
5321
5322
5323
5324 /* ------------------------------ */
5325     .balign 64
5326 .L_OP_SUB_INT_2ADDR: /* 0xb1 */
5327 /* File: armv6t2/OP_SUB_INT_2ADDR.S */
5328 /* File: armv6t2/binop2addr.S */
5329     /*
5330      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5331      * that specifies an instruction that performs "result = r0 op r1".
5332      * This could be an ARM instruction or a function call.  (If the result
5333      * comes back in a register other than r0, you can override "result".)
5334      *
5335      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5336      * vCC (r1).  Useful for integer division and modulus.
5337      *
5338      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5339      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5340      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5341      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5342      */
5343     /* binop/2addr vA, vB */
5344     mov     r3, rINST, lsr #12          @ r3<- B
5345     ubfx    r9, rINST, #8, #4           @ r9<- A
5346     GET_VREG(r1, r3)                    @ r1<- vB
5347     GET_VREG(r0, r9)                    @ r0<- vA
5348     .if 0
5349     cmp     r1, #0                      @ is second operand zero?
5350     beq     common_errDivideByZero
5351     .endif
5352     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5353
5354                                @ optional op; may set condition codes
5355     sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
5356     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5357     SET_VREG(r0, r9)               @ vAA<- r0
5358     GOTO_OPCODE(ip)                     @ jump to next instruction
5359     /* 10-13 instructions */
5360
5361
5362
5363 /* ------------------------------ */
5364     .balign 64
5365 .L_OP_MUL_INT_2ADDR: /* 0xb2 */
5366 /* File: armv6t2/OP_MUL_INT_2ADDR.S */
5367 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
5368 /* File: armv6t2/binop2addr.S */
5369     /*
5370      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5371      * that specifies an instruction that performs "result = r0 op r1".
5372      * This could be an ARM instruction or a function call.  (If the result
5373      * comes back in a register other than r0, you can override "result".)
5374      *
5375      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5376      * vCC (r1).  Useful for integer division and modulus.
5377      *
5378      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5379      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5380      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5381      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5382      */
5383     /* binop/2addr vA, vB */
5384     mov     r3, rINST, lsr #12          @ r3<- B
5385     ubfx    r9, rINST, #8, #4           @ r9<- A
5386     GET_VREG(r1, r3)                    @ r1<- vB
5387     GET_VREG(r0, r9)                    @ r0<- vA
5388     .if 0
5389     cmp     r1, #0                      @ is second operand zero?
5390     beq     common_errDivideByZero
5391     .endif
5392     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5393
5394                                @ optional op; may set condition codes
5395     mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
5396     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5397     SET_VREG(r0, r9)               @ vAA<- r0
5398     GOTO_OPCODE(ip)                     @ jump to next instruction
5399     /* 10-13 instructions */
5400
5401
5402
5403 /* ------------------------------ */
5404     .balign 64
5405 .L_OP_DIV_INT_2ADDR: /* 0xb3 */
5406 /* File: armv6t2/OP_DIV_INT_2ADDR.S */
5407 /* File: armv6t2/binop2addr.S */
5408     /*
5409      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5410      * that specifies an instruction that performs "result = r0 op r1".
5411      * This could be an ARM instruction or a function call.  (If the result
5412      * comes back in a register other than r0, you can override "result".)
5413      *
5414      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5415      * vCC (r1).  Useful for integer division and modulus.
5416      *
5417      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5418      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5419      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5420      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5421      */
5422     /* binop/2addr vA, vB */
5423     mov     r3, rINST, lsr #12          @ r3<- B
5424     ubfx    r9, rINST, #8, #4           @ r9<- A
5425     GET_VREG(r1, r3)                    @ r1<- vB
5426     GET_VREG(r0, r9)                    @ r0<- vA
5427     .if 1
5428     cmp     r1, #0                      @ is second operand zero?
5429     beq     common_errDivideByZero
5430     .endif
5431     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5432
5433                                @ optional op; may set condition codes
5434     bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
5435     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5436     SET_VREG(r0, r9)               @ vAA<- r0
5437     GOTO_OPCODE(ip)                     @ jump to next instruction
5438     /* 10-13 instructions */
5439
5440
5441
5442 /* ------------------------------ */
5443     .balign 64
5444 .L_OP_REM_INT_2ADDR: /* 0xb4 */
5445 /* File: armv6t2/OP_REM_INT_2ADDR.S */
5446 /* idivmod returns quotient in r0 and remainder in r1 */
5447 /* File: armv6t2/binop2addr.S */
5448     /*
5449      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5450      * that specifies an instruction that performs "result = r0 op r1".
5451      * This could be an ARM instruction or a function call.  (If the result
5452      * comes back in a register other than r0, you can override "result".)
5453      *
5454      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5455      * vCC (r1).  Useful for integer division and modulus.
5456      *
5457      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5458      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5459      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5460      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5461      */
5462     /* binop/2addr vA, vB */
5463     mov     r3, rINST, lsr #12          @ r3<- B
5464     ubfx    r9, rINST, #8, #4           @ r9<- A
5465     GET_VREG(r1, r3)                    @ r1<- vB
5466     GET_VREG(r0, r9)                    @ r0<- vA
5467     .if 1
5468     cmp     r1, #0                      @ is second operand zero?
5469     beq     common_errDivideByZero
5470     .endif
5471     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5472
5473                                @ optional op; may set condition codes
5474     bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
5475     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5476     SET_VREG(r1, r9)               @ vAA<- r1
5477     GOTO_OPCODE(ip)                     @ jump to next instruction
5478     /* 10-13 instructions */
5479
5480
5481
5482 /* ------------------------------ */
5483     .balign 64
5484 .L_OP_AND_INT_2ADDR: /* 0xb5 */
5485 /* File: armv6t2/OP_AND_INT_2ADDR.S */
5486 /* File: armv6t2/binop2addr.S */
5487     /*
5488      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5489      * that specifies an instruction that performs "result = r0 op r1".
5490      * This could be an ARM instruction or a function call.  (If the result
5491      * comes back in a register other than r0, you can override "result".)
5492      *
5493      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5494      * vCC (r1).  Useful for integer division and modulus.
5495      *
5496      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5497      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5498      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5499      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5500      */
5501     /* binop/2addr vA, vB */
5502     mov     r3, rINST, lsr #12          @ r3<- B
5503     ubfx    r9, rINST, #8, #4           @ r9<- A
5504     GET_VREG(r1, r3)                    @ r1<- vB
5505     GET_VREG(r0, r9)                    @ r0<- vA
5506     .if 0
5507     cmp     r1, #0                      @ is second operand zero?
5508     beq     common_errDivideByZero
5509     .endif
5510     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5511
5512                                @ optional op; may set condition codes
5513     and     r0, r0, r1                              @ r0<- op, r0-r3 changed
5514     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5515     SET_VREG(r0, r9)               @ vAA<- r0
5516     GOTO_OPCODE(ip)                     @ jump to next instruction
5517     /* 10-13 instructions */
5518
5519
5520
5521 /* ------------------------------ */
5522     .balign 64
5523 .L_OP_OR_INT_2ADDR: /* 0xb6 */
5524 /* File: armv6t2/OP_OR_INT_2ADDR.S */
5525 /* File: armv6t2/binop2addr.S */
5526     /*
5527      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5528      * that specifies an instruction that performs "result = r0 op r1".
5529      * This could be an ARM instruction or a function call.  (If the result
5530      * comes back in a register other than r0, you can override "result".)
5531      *
5532      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5533      * vCC (r1).  Useful for integer division and modulus.
5534      *
5535      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5536      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5537      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5538      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5539      */
5540     /* binop/2addr vA, vB */
5541     mov     r3, rINST, lsr #12          @ r3<- B
5542     ubfx    r9, rINST, #8, #4           @ r9<- A
5543     GET_VREG(r1, r3)                    @ r1<- vB
5544     GET_VREG(r0, r9)                    @ r0<- vA
5545     .if 0
5546     cmp     r1, #0                      @ is second operand zero?
5547     beq     common_errDivideByZero
5548     .endif
5549     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5550
5551                                @ optional op; may set condition codes
5552     orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
5553     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5554     SET_VREG(r0, r9)               @ vAA<- r0
5555     GOTO_OPCODE(ip)                     @ jump to next instruction
5556     /* 10-13 instructions */
5557
5558
5559
5560 /* ------------------------------ */
5561     .balign 64
5562 .L_OP_XOR_INT_2ADDR: /* 0xb7 */
5563 /* File: armv6t2/OP_XOR_INT_2ADDR.S */
5564 /* File: armv6t2/binop2addr.S */
5565     /*
5566      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5567      * that specifies an instruction that performs "result = r0 op r1".
5568      * This could be an ARM instruction or a function call.  (If the result
5569      * comes back in a register other than r0, you can override "result".)
5570      *
5571      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5572      * vCC (r1).  Useful for integer division and modulus.
5573      *
5574      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5575      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5576      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5577      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5578      */
5579     /* binop/2addr vA, vB */
5580     mov     r3, rINST, lsr #12          @ r3<- B
5581     ubfx    r9, rINST, #8, #4           @ r9<- A
5582     GET_VREG(r1, r3)                    @ r1<- vB
5583     GET_VREG(r0, r9)                    @ r0<- vA
5584     .if 0
5585     cmp     r1, #0                      @ is second operand zero?
5586     beq     common_errDivideByZero
5587     .endif
5588     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5589
5590                                @ optional op; may set condition codes
5591     eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
5592     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5593     SET_VREG(r0, r9)               @ vAA<- r0
5594     GOTO_OPCODE(ip)                     @ jump to next instruction
5595     /* 10-13 instructions */
5596
5597
5598
5599 /* ------------------------------ */
5600     .balign 64
5601 .L_OP_SHL_INT_2ADDR: /* 0xb8 */
5602 /* File: armv6t2/OP_SHL_INT_2ADDR.S */
5603 /* File: armv6t2/binop2addr.S */
5604     /*
5605      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5606      * that specifies an instruction that performs "result = r0 op r1".
5607      * This could be an ARM instruction or a function call.  (If the result
5608      * comes back in a register other than r0, you can override "result".)
5609      *
5610      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5611      * vCC (r1).  Useful for integer division and modulus.
5612      *
5613      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5614      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5615      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5616      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5617      */
5618     /* binop/2addr vA, vB */
5619     mov     r3, rINST, lsr #12          @ r3<- B
5620     ubfx    r9, rINST, #8, #4           @ r9<- A
5621     GET_VREG(r1, r3)                    @ r1<- vB
5622     GET_VREG(r0, r9)                    @ r0<- vA
5623     .if 0
5624     cmp     r1, #0                      @ is second operand zero?
5625     beq     common_errDivideByZero
5626     .endif
5627     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5628
5629     and     r1, r1, #31                           @ optional op; may set condition codes
5630     mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
5631     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5632     SET_VREG(r0, r9)               @ vAA<- r0
5633     GOTO_OPCODE(ip)                     @ jump to next instruction
5634     /* 10-13 instructions */
5635
5636
5637
5638 /* ------------------------------ */
5639     .balign 64
5640 .L_OP_SHR_INT_2ADDR: /* 0xb9 */
5641 /* File: armv6t2/OP_SHR_INT_2ADDR.S */
5642 /* File: armv6t2/binop2addr.S */
5643     /*
5644      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5645      * that specifies an instruction that performs "result = r0 op r1".
5646      * This could be an ARM instruction or a function call.  (If the result
5647      * comes back in a register other than r0, you can override "result".)
5648      *
5649      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5650      * vCC (r1).  Useful for integer division and modulus.
5651      *
5652      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5653      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5654      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5655      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5656      */
5657     /* binop/2addr vA, vB */
5658     mov     r3, rINST, lsr #12          @ r3<- B
5659     ubfx    r9, rINST, #8, #4           @ r9<- A
5660     GET_VREG(r1, r3)                    @ r1<- vB
5661     GET_VREG(r0, r9)                    @ r0<- vA
5662     .if 0
5663     cmp     r1, #0                      @ is second operand zero?
5664     beq     common_errDivideByZero
5665     .endif
5666     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5667
5668     and     r1, r1, #31                           @ optional op; may set condition codes
5669     mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
5670     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5671     SET_VREG(r0, r9)               @ vAA<- r0
5672     GOTO_OPCODE(ip)                     @ jump to next instruction
5673     /* 10-13 instructions */
5674
5675
5676
5677 /* ------------------------------ */
5678     .balign 64
5679 .L_OP_USHR_INT_2ADDR: /* 0xba */
5680 /* File: armv6t2/OP_USHR_INT_2ADDR.S */
5681 /* File: armv6t2/binop2addr.S */
5682     /*
5683      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5684      * that specifies an instruction that performs "result = r0 op r1".
5685      * This could be an ARM instruction or a function call.  (If the result
5686      * comes back in a register other than r0, you can override "result".)
5687      *
5688      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5689      * vCC (r1).  Useful for integer division and modulus.
5690      *
5691      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5692      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5693      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5694      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5695      */
5696     /* binop/2addr vA, vB */
5697     mov     r3, rINST, lsr #12          @ r3<- B
5698     ubfx    r9, rINST, #8, #4           @ r9<- A
5699     GET_VREG(r1, r3)                    @ r1<- vB
5700     GET_VREG(r0, r9)                    @ r0<- vA
5701     .if 0
5702     cmp     r1, #0                      @ is second operand zero?
5703     beq     common_errDivideByZero
5704     .endif
5705     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5706
5707     and     r1, r1, #31                           @ optional op; may set condition codes
5708     mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
5709     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5710     SET_VREG(r0, r9)               @ vAA<- r0
5711     GOTO_OPCODE(ip)                     @ jump to next instruction
5712     /* 10-13 instructions */
5713
5714
5715
5716 /* ------------------------------ */
5717     .balign 64
5718 .L_OP_ADD_LONG_2ADDR: /* 0xbb */
5719 /* File: armv6t2/OP_ADD_LONG_2ADDR.S */
5720 /* File: armv6t2/binopWide2addr.S */
5721     /*
5722      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5723      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5724      * This could be an ARM instruction or a function call.  (If the result
5725      * comes back in a register other than r0, you can override "result".)
5726      *
5727      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5728      * vCC (r1).  Useful for integer division and modulus.
5729      *
5730      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5731      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5732      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5733      *      rem-double/2addr
5734      */
5735     /* binop/2addr vA, vB */
5736     mov     r1, rINST, lsr #12          @ r1<- B
5737     ubfx    r9, rINST, #8, #4           @ r9<- A
5738     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5739     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5740     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5741     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5742     .if 0
5743     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5744     beq     common_errDivideByZero
5745     .endif
5746     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5747
5748     adds    r0, r0, r2                           @ optional op; may set condition codes
5749     adc     r1, r1, r3                              @ result<- op, r0-r3 changed
5750     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5751     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5752     GOTO_OPCODE(ip)                     @ jump to next instruction
5753     /* 12-15 instructions */
5754
5755
5756
5757 /* ------------------------------ */
5758     .balign 64
5759 .L_OP_SUB_LONG_2ADDR: /* 0xbc */
5760 /* File: armv6t2/OP_SUB_LONG_2ADDR.S */
5761 /* File: armv6t2/binopWide2addr.S */
5762     /*
5763      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5764      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5765      * This could be an ARM instruction or a function call.  (If the result
5766      * comes back in a register other than r0, you can override "result".)
5767      *
5768      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5769      * vCC (r1).  Useful for integer division and modulus.
5770      *
5771      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5772      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5773      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5774      *      rem-double/2addr
5775      */
5776     /* binop/2addr vA, vB */
5777     mov     r1, rINST, lsr #12          @ r1<- B
5778     ubfx    r9, rINST, #8, #4           @ r9<- A
5779     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5780     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5781     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5782     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5783     .if 0
5784     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5785     beq     common_errDivideByZero
5786     .endif
5787     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5788
5789     subs    r0, r0, r2                           @ optional op; may set condition codes
5790     sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
5791     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5792     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5793     GOTO_OPCODE(ip)                     @ jump to next instruction
5794     /* 12-15 instructions */
5795
5796
5797
5798 /* ------------------------------ */
5799     .balign 64
5800 .L_OP_MUL_LONG_2ADDR: /* 0xbd */
5801 /* File: armv6t2/OP_MUL_LONG_2ADDR.S */
5802     /*
5803      * Signed 64-bit integer multiply, "/2addr" version.
5804      *
5805      * See OP_MUL_LONG for an explanation.
5806      *
5807      * We get a little tight on registers, so to avoid looking up &fp[A]
5808      * again we stuff it into rINST.
5809      */
5810     /* mul-long/2addr vA, vB */
5811     mov     r1, rINST, lsr #12          @ r1<- B
5812     ubfx    r9, rINST, #8, #4           @ r9<- A
5813     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5814     add     rINST, rFP, r9, lsl #2      @ rINST<- &fp[A]
5815     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5816     ldmia   rINST, {r0-r1}              @ r0/r1<- vAA/vAA+1
5817     mul     ip, r2, r1                  @  ip<- ZxW
5818     umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
5819     mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
5820     mov     r0, rINST                   @ r0<- &fp[A] (free up rINST)
5821     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5822     add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
5823     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5824     stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
5825     GOTO_OPCODE(ip)                     @ jump to next instruction
5826
5827
5828 /* ------------------------------ */
5829     .balign 64
5830 .L_OP_DIV_LONG_2ADDR: /* 0xbe */
5831 /* File: armv6t2/OP_DIV_LONG_2ADDR.S */
5832 /* File: armv6t2/binopWide2addr.S */
5833     /*
5834      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5835      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5836      * This could be an ARM instruction or a function call.  (If the result
5837      * comes back in a register other than r0, you can override "result".)
5838      *
5839      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5840      * vCC (r1).  Useful for integer division and modulus.
5841      *
5842      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5843      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5844      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5845      *      rem-double/2addr
5846      */
5847     /* binop/2addr vA, vB */
5848     mov     r1, rINST, lsr #12          @ r1<- B
5849     ubfx    r9, rINST, #8, #4           @ r9<- A
5850     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5851     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5852     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5853     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5854     .if 1
5855     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5856     beq     common_errDivideByZero
5857     .endif
5858     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5859
5860                                @ optional op; may set condition codes
5861     bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5862     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5863     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5864     GOTO_OPCODE(ip)                     @ jump to next instruction
5865     /* 12-15 instructions */
5866
5867
5868
5869 /* ------------------------------ */
5870     .balign 64
5871 .L_OP_REM_LONG_2ADDR: /* 0xbf */
5872 /* File: armv6t2/OP_REM_LONG_2ADDR.S */
5873 /* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
5874 /* File: armv6t2/binopWide2addr.S */
5875     /*
5876      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5877      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5878      * This could be an ARM instruction or a function call.  (If the result
5879      * comes back in a register other than r0, you can override "result".)
5880      *
5881      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5882      * vCC (r1).  Useful for integer division and modulus.
5883      *
5884      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5885      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5886      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5887      *      rem-double/2addr
5888      */
5889     /* binop/2addr vA, vB */
5890     mov     r1, rINST, lsr #12          @ r1<- B
5891     ubfx    r9, rINST, #8, #4           @ r9<- A
5892     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5893     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5894     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5895     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5896     .if 1
5897     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5898     beq     common_errDivideByZero
5899     .endif
5900     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5901
5902                                @ optional op; may set condition codes
5903     bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5904     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5905     stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
5906     GOTO_OPCODE(ip)                     @ jump to next instruction
5907     /* 12-15 instructions */
5908
5909
5910
5911 /* ------------------------------ */
5912     .balign 64
5913 .L_OP_AND_LONG_2ADDR: /* 0xc0 */
5914 /* File: armv6t2/OP_AND_LONG_2ADDR.S */
5915 /* File: armv6t2/binopWide2addr.S */
5916     /*
5917      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5918      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5919      * This could be an ARM instruction or a function call.  (If the result
5920      * comes back in a register other than r0, you can override "result".)
5921      *
5922      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5923      * vCC (r1).  Useful for integer division and modulus.
5924      *
5925      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5926      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5927      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5928      *      rem-double/2addr
5929      */
5930     /* binop/2addr vA, vB */
5931     mov     r1, rINST, lsr #12          @ r1<- B
5932     ubfx    r9, rINST, #8, #4           @ r9<- A
5933     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5934     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5935     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5936     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5937     .if 0
5938     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5939     beq     common_errDivideByZero
5940     .endif
5941     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5942
5943     and     r0, r0, r2                           @ optional op; may set condition codes
5944     and     r1, r1, r3                              @ result<- op, r0-r3 changed
5945     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5946     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5947     GOTO_OPCODE(ip)                     @ jump to next instruction
5948     /* 12-15 instructions */
5949
5950
5951
5952 /* ------------------------------ */
5953     .balign 64
5954 .L_OP_OR_LONG_2ADDR: /* 0xc1 */
5955 /* File: armv6t2/OP_OR_LONG_2ADDR.S */
5956 /* File: armv6t2/binopWide2addr.S */
5957     /*
5958      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5959      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5960      * This could be an ARM instruction or a function call.  (If the result
5961      * comes back in a register other than r0, you can override "result".)
5962      *
5963      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5964      * vCC (r1).  Useful for integer division and modulus.
5965      *
5966      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5967      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5968      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5969      *      rem-double/2addr
5970      */
5971     /* binop/2addr vA, vB */
5972     mov     r1, rINST, lsr #12          @ r1<- B
5973     ubfx    r9, rINST, #8, #4           @ r9<- A
5974     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5975     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5976     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5977     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5978     .if 0
5979     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5980     beq     common_errDivideByZero
5981     .endif
5982     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5983
5984     orr     r0, r0, r2                           @ optional op; may set condition codes
5985     orr     r1, r1, r3                              @ result<- op, r0-r3 changed
5986     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5987     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5988     GOTO_OPCODE(ip)                     @ jump to next instruction
5989     /* 12-15 instructions */
5990
5991
5992
5993 /* ------------------------------ */
5994     .balign 64
5995 .L_OP_XOR_LONG_2ADDR: /* 0xc2 */
5996 /* File: armv6t2/OP_XOR_LONG_2ADDR.S */
5997 /* File: armv6t2/binopWide2addr.S */
5998     /*
5999      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6000      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6001      * This could be an ARM instruction or a function call.  (If the result
6002      * comes back in a register other than r0, you can override "result".)
6003      *
6004      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6005      * vCC (r1).  Useful for integer division and modulus.
6006      *
6007      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6008      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6009      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6010      *      rem-double/2addr
6011      */
6012     /* binop/2addr vA, vB */
6013     mov     r1, rINST, lsr #12          @ r1<- B
6014     ubfx    r9, rINST, #8, #4           @ r9<- A
6015     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6016     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6017     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6018     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6019     .if 0
6020     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6021     beq     common_errDivideByZero
6022     .endif
6023     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6024
6025     eor     r0, r0, r2                           @ optional op; may set condition codes
6026     eor     r1, r1, r3                              @ result<- op, r0-r3 changed
6027     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6028     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6029     GOTO_OPCODE(ip)                     @ jump to next instruction
6030     /* 12-15 instructions */
6031
6032
6033
6034 /* ------------------------------ */
6035     .balign 64
6036 .L_OP_SHL_LONG_2ADDR: /* 0xc3 */
6037 /* File: armv6t2/OP_SHL_LONG_2ADDR.S */
6038     /*
6039      * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6040      * 32-bit shift distance.
6041      */
6042     /* shl-long/2addr vA, vB */
6043     mov     r3, rINST, lsr #12          @ r3<- B
6044     ubfx    r9, rINST, #8, #4           @ r9<- A
6045     GET_VREG(r2, r3)                    @ r2<- vB
6046     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6047     and     r2, r2, #63                 @ r2<- r2 & 0x3f
6048     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6049
6050     mov     r1, r1, asl r2              @  r1<- r1 << r2
6051     rsb     r3, r2, #32                 @  r3<- 32 - r2
6052     orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
6053     subs    ip, r2, #32                 @  ip<- r2 - 32
6054     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6055     movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
6056     mov     r0, r0, asl r2              @  r0<- r0 << r2
6057     b       .LOP_SHL_LONG_2ADDR_finish
6058
6059 /* ------------------------------ */
6060     .balign 64
6061 .L_OP_SHR_LONG_2ADDR: /* 0xc4 */
6062 /* File: armv6t2/OP_SHR_LONG_2ADDR.S */
6063     /*
6064      * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6065      * 32-bit shift distance.
6066      */
6067     /* shr-long/2addr vA, vB */
6068     mov     r3, rINST, lsr #12          @ r3<- B
6069     ubfx    r9, rINST, #8, #4           @ r9<- A
6070     GET_VREG(r2, r3)                    @ r2<- vB
6071     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6072     and     r2, r2, #63                 @ r2<- r2 & 0x3f
6073     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6074
6075     mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6076     rsb     r3, r2, #32                 @  r3<- 32 - r2
6077     orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6078     subs    ip, r2, #32                 @  ip<- r2 - 32
6079     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6080     movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
6081     mov     r1, r1, asr r2              @  r1<- r1 >> r2
6082     b       .LOP_SHR_LONG_2ADDR_finish
6083
6084 /* ------------------------------ */
6085     .balign 64
6086 .L_OP_USHR_LONG_2ADDR: /* 0xc5 */
6087 /* File: armv6t2/OP_USHR_LONG_2ADDR.S */
6088     /*
6089      * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6090      * 32-bit shift distance.
6091      */
6092     /* ushr-long/2addr vA, vB */
6093     mov     r3, rINST, lsr #12          @ r3<- B
6094     ubfx    r9, rINST, #8, #4           @ r9<- A
6095     GET_VREG(r2, r3)                    @ r2<- vB
6096     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6097     and     r2, r2, #63                 @ r2<- r2 & 0x3f
6098     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6099
6100     mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6101     rsb     r3, r2, #32                 @  r3<- 32 - r2
6102     orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6103     subs    ip, r2, #32                 @  ip<- r2 - 32
6104     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6105     movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
6106     mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
6107     b       .LOP_USHR_LONG_2ADDR_finish
6108
6109 /* ------------------------------ */
6110     .balign 64
6111 .L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
6112 /* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */
6113 /* File: arm-vfp/fbinop2addr.S */
6114     /*
6115      * Generic 32-bit floating point "/2addr" binary operation.  Provide
6116      * an "instr" line that specifies an instruction that performs
6117      * "s2 = s0 op s1".
6118      *
6119      * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6120      */
6121     /* binop/2addr vA, vB */
6122     mov     r3, rINST, lsr #12          @ r3<- B
6123     mov     r9, rINST, lsr #8           @ r9<- A+
6124     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6125     and     r9, r9, #15                 @ r9<- A
6126     flds    s1, [r3]                    @ s1<- vB
6127     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6128     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6129     flds    s0, [r9]                    @ s0<- vA
6130
6131     fadds   s2, s0, s1                              @ s2<- op
6132     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6133     fsts    s2, [r9]                    @ vAA<- s2
6134     GOTO_OPCODE(ip)                     @ jump to next instruction
6135
6136
6137 /* ------------------------------ */
6138     .balign 64
6139 .L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
6140 /* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */
6141 /* File: arm-vfp/fbinop2addr.S */
6142     /*
6143      * Generic 32-bit floating point "/2addr" binary operation.  Provide
6144      * an "instr" line that specifies an instruction that performs
6145      * "s2 = s0 op s1".
6146      *
6147      * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6148      */
6149     /* binop/2addr vA, vB */
6150     mov     r3, rINST, lsr #12          @ r3<- B
6151     mov     r9, rINST, lsr #8           @ r9<- A+
6152     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6153     and     r9, r9, #15                 @ r9<- A
6154     flds    s1, [r3]                    @ s1<- vB
6155     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6156     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6157     flds    s0, [r9]                    @ s0<- vA
6158
6159     fsubs   s2, s0, s1                              @ s2<- op
6160     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6161     fsts    s2, [r9]                    @ vAA<- s2
6162     GOTO_OPCODE(ip)                     @ jump to next instruction
6163
6164
6165 /* ------------------------------ */
6166     .balign 64
6167 .L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
6168 /* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */
6169 /* File: arm-vfp/fbinop2addr.S */
6170     /*
6171      * Generic 32-bit floating point "/2addr" binary operation.  Provide
6172      * an "instr" line that specifies an instruction that performs
6173      * "s2 = s0 op s1".
6174      *
6175      * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6176      */
6177     /* binop/2addr vA, vB */
6178     mov     r3, rINST, lsr #12          @ r3<- B
6179     mov     r9, rINST, lsr #8           @ r9<- A+
6180     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6181     and     r9, r9, #15                 @ r9<- A
6182     flds    s1, [r3]                    @ s1<- vB
6183     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6184     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6185     flds    s0, [r9]                    @ s0<- vA
6186
6187     fmuls   s2, s0, s1                              @ s2<- op
6188     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6189     fsts    s2, [r9]                    @ vAA<- s2
6190     GOTO_OPCODE(ip)                     @ jump to next instruction
6191
6192
6193 /* ------------------------------ */
6194     .balign 64
6195 .L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
6196 /* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */
6197 /* File: arm-vfp/fbinop2addr.S */
6198     /*
6199      * Generic 32-bit floating point "/2addr" binary operation.  Provide
6200      * an "instr" line that specifies an instruction that performs
6201      * "s2 = s0 op s1".
6202      *
6203      * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6204      */
6205     /* binop/2addr vA, vB */
6206     mov     r3, rINST, lsr #12          @ r3<- B
6207     mov     r9, rINST, lsr #8           @ r9<- A+
6208     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6209     and     r9, r9, #15                 @ r9<- A
6210     flds    s1, [r3]                    @ s1<- vB
6211     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6212     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6213     flds    s0, [r9]                    @ s0<- vA
6214
6215     fdivs   s2, s0, s1                              @ s2<- op
6216     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6217     fsts    s2, [r9]                    @ vAA<- s2
6218     GOTO_OPCODE(ip)                     @ jump to next instruction
6219
6220
6221 /* ------------------------------ */
6222     .balign 64
6223 .L_OP_REM_FLOAT_2ADDR: /* 0xca */
6224 /* File: armv6t2/OP_REM_FLOAT_2ADDR.S */
6225 /* EABI doesn't define a float remainder function, but libm does */
6226 /* File: armv6t2/binop2addr.S */
6227     /*
6228      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6229      * that specifies an instruction that performs "result = r0 op r1".
6230      * This could be an ARM instruction or a function call.  (If the result
6231      * comes back in a register other than r0, you can override "result".)
6232      *
6233      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6234      * vCC (r1).  Useful for integer division and modulus.
6235      *
6236      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6237      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6238      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6239      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6240      */
6241     /* binop/2addr vA, vB */
6242     mov     r3, rINST, lsr #12          @ r3<- B
6243     ubfx    r9, rINST, #8, #4           @ r9<- A
6244     GET_VREG(r1, r3)                    @ r1<- vB
6245     GET_VREG(r0, r9)                    @ r0<- vA
6246     .if 0
6247     cmp     r1, #0                      @ is second operand zero?
6248     beq     common_errDivideByZero
6249     .endif
6250     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6251
6252                                @ optional op; may set condition codes
6253     bl      fmodf                              @ r0<- op, r0-r3 changed
6254     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6255     SET_VREG(r0, r9)               @ vAA<- r0
6256     GOTO_OPCODE(ip)                     @ jump to next instruction
6257     /* 10-13 instructions */
6258
6259
6260
6261 /* ------------------------------ */
6262     .balign 64
6263 .L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
6264 /* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */
6265 /* File: arm-vfp/fbinopWide2addr.S */
6266     /*
6267      * Generic 64-bit floating point "/2addr" binary operation.  Provide
6268      * an "instr" line that specifies an instruction that performs
6269      * "d2 = d0 op d1".
6270      *
6271      * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6272      *      div-double/2addr
6273      */
6274     /* binop/2addr vA, vB */
6275     mov     r3, rINST, lsr #12          @ r3<- B
6276     mov     r9, rINST, lsr #8           @ r9<- A+
6277     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6278     and     r9, r9, #15                 @ r9<- A
6279     fldd    d1, [r3]                    @ d1<- vB
6280     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6281     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6282     fldd    d0, [r9]                    @ d0<- vA
6283
6284     faddd   d2, d0, d1                              @ d2<- op
6285     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6286     fstd    d2, [r9]                    @ vAA<- d2
6287     GOTO_OPCODE(ip)                     @ jump to next instruction
6288
6289
6290 /* ------------------------------ */
6291     .balign 64
6292 .L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
6293 /* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */
6294 /* File: arm-vfp/fbinopWide2addr.S */
6295     /*
6296      * Generic 64-bit floating point "/2addr" binary operation.  Provide
6297      * an "instr" line that specifies an instruction that performs
6298      * "d2 = d0 op d1".
6299      *
6300      * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6301      *      div-double/2addr
6302      */
6303     /* binop/2addr vA, vB */
6304     mov     r3, rINST, lsr #12          @ r3<- B
6305     mov     r9, rINST, lsr #8           @ r9<- A+
6306     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6307     and     r9, r9, #15                 @ r9<- A
6308     fldd    d1, [r3]                    @ d1<- vB
6309     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6310     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6311     fldd    d0, [r9]                    @ d0<- vA
6312
6313     fsubd   d2, d0, d1                              @ d2<- op
6314     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6315     fstd    d2, [r9]                    @ vAA<- d2
6316     GOTO_OPCODE(ip)                     @ jump to next instruction
6317
6318
6319 /* ------------------------------ */
6320     .balign 64
6321 .L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
6322 /* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */
6323 /* File: arm-vfp/fbinopWide2addr.S */
6324     /*
6325      * Generic 64-bit floating point "/2addr" binary operation.  Provide
6326      * an "instr" line that specifies an instruction that performs
6327      * "d2 = d0 op d1".
6328      *
6329      * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6330      *      div-double/2addr
6331      */
6332     /* binop/2addr vA, vB */
6333     mov     r3, rINST, lsr #12          @ r3<- B
6334     mov     r9, rINST, lsr #8           @ r9<- A+
6335     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6336     and     r9, r9, #15                 @ r9<- A
6337     fldd    d1, [r3]                    @ d1<- vB
6338     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6339     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6340     fldd    d0, [r9]                    @ d0<- vA
6341
6342     fmuld   d2, d0, d1                              @ d2<- op
6343     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6344     fstd    d2, [r9]                    @ vAA<- d2
6345     GOTO_OPCODE(ip)                     @ jump to next instruction
6346
6347
6348 /* ------------------------------ */
6349     .balign 64
6350 .L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
6351 /* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */
6352 /* File: arm-vfp/fbinopWide2addr.S */
6353     /*
6354      * Generic 64-bit floating point "/2addr" binary operation.  Provide
6355      * an "instr" line that specifies an instruction that performs
6356      * "d2 = d0 op d1".
6357      *
6358      * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6359      *      div-double/2addr
6360      */
6361     /* binop/2addr vA, vB */
6362     mov     r3, rINST, lsr #12          @ r3<- B
6363     mov     r9, rINST, lsr #8           @ r9<- A+
6364     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6365     and     r9, r9, #15                 @ r9<- A
6366     fldd    d1, [r3]                    @ d1<- vB
6367     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6368     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6369     fldd    d0, [r9]                    @ d0<- vA
6370
6371     fdivd   d2, d0, d1                              @ d2<- op
6372     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6373     fstd    d2, [r9]                    @ vAA<- d2
6374     GOTO_OPCODE(ip)                     @ jump to next instruction
6375
6376
6377 /* ------------------------------ */
6378     .balign 64
6379 .L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
6380 /* File: armv6t2/OP_REM_DOUBLE_2ADDR.S */
6381 /* EABI doesn't define a double remainder function, but libm does */
6382 /* File: armv6t2/binopWide2addr.S */
6383     /*
6384      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6385      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6386      * This could be an ARM instruction or a function call.  (If the result
6387      * comes back in a register other than r0, you can override "result".)
6388      *
6389      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6390      * vCC (r1).  Useful for integer division and modulus.
6391      *
6392      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6393      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6394      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6395      *      rem-double/2addr
6396      */
6397     /* binop/2addr vA, vB */
6398     mov     r1, rINST, lsr #12          @ r1<- B
6399     ubfx    r9, rINST, #8, #4           @ r9<- A
6400     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6401     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6402     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6403     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6404     .if 0
6405     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6406     beq     common_errDivideByZero
6407     .endif
6408     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6409
6410                                @ optional op; may set condition codes
6411     bl      fmod                              @ result<- op, r0-r3 changed
6412     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6413     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6414     GOTO_OPCODE(ip)                     @ jump to next instruction
6415     /* 12-15 instructions */
6416
6417
6418
6419 /* ------------------------------ */
6420     .balign 64
6421 .L_OP_ADD_INT_LIT16: /* 0xd0 */
6422 /* File: armv6t2/OP_ADD_INT_LIT16.S */
6423 /* File: armv6t2/binopLit16.S */
6424     /*
6425      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6426      * that specifies an instruction that performs "result = r0 op r1".
6427      * This could be an ARM instruction or a function call.  (If the result
6428      * comes back in a register other than r0, you can override "result".)
6429      *
6430      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6431      * vCC (r1).  Useful for integer division and modulus.
6432      *
6433      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6434      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6435      */
6436     /* binop/lit16 vA, vB, #+CCCC */
6437     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6438     mov     r2, rINST, lsr #12          @ r2<- B
6439     ubfx    r9, rINST, #8, #4           @ r9<- A
6440     GET_VREG(r0, r2)                    @ r0<- vB
6441     .if 0
6442     cmp     r1, #0                      @ is second operand zero?
6443     beq     common_errDivideByZero
6444     .endif
6445     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6446
6447     add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6448     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6449     SET_VREG(r0, r9)               @ vAA<- r0
6450     GOTO_OPCODE(ip)                     @ jump to next instruction
6451     /* 10-13 instructions */
6452
6453
6454
6455 /* ------------------------------ */
6456     .balign 64
6457 .L_OP_RSUB_INT: /* 0xd1 */
6458 /* File: armv6t2/OP_RSUB_INT.S */
6459 /* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
6460 /* File: armv6t2/binopLit16.S */
6461     /*
6462      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6463      * that specifies an instruction that performs "result = r0 op r1".
6464      * This could be an ARM instruction or a function call.  (If the result
6465      * comes back in a register other than r0, you can override "result".)
6466      *
6467      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6468      * vCC (r1).  Useful for integer division and modulus.
6469      *
6470      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6471      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6472      */
6473     /* binop/lit16 vA, vB, #+CCCC */
6474     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6475     mov     r2, rINST, lsr #12          @ r2<- B
6476     ubfx    r9, rINST, #8, #4           @ r9<- A
6477     GET_VREG(r0, r2)                    @ r0<- vB
6478     .if 0
6479     cmp     r1, #0                      @ is second operand zero?
6480     beq     common_errDivideByZero
6481     .endif
6482     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6483
6484     rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6485     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6486     SET_VREG(r0, r9)               @ vAA<- r0
6487     GOTO_OPCODE(ip)                     @ jump to next instruction
6488     /* 10-13 instructions */
6489
6490
6491
6492 /* ------------------------------ */
6493     .balign 64
6494 .L_OP_MUL_INT_LIT16: /* 0xd2 */
6495 /* File: armv6t2/OP_MUL_INT_LIT16.S */
6496 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6497 /* File: armv6t2/binopLit16.S */
6498     /*
6499      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6500      * that specifies an instruction that performs "result = r0 op r1".
6501      * This could be an ARM instruction or a function call.  (If the result
6502      * comes back in a register other than r0, you can override "result".)
6503      *
6504      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6505      * vCC (r1).  Useful for integer division and modulus.
6506      *
6507      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6508      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6509      */
6510     /* binop/lit16 vA, vB, #+CCCC */
6511     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6512     mov     r2, rINST, lsr #12          @ r2<- B
6513     ubfx    r9, rINST, #8, #4           @ r9<- A
6514     GET_VREG(r0, r2)                    @ r0<- vB
6515     .if 0
6516     cmp     r1, #0                      @ is second operand zero?
6517     beq     common_errDivideByZero
6518     .endif
6519     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6520
6521     mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6522     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6523     SET_VREG(r0, r9)               @ vAA<- r0
6524     GOTO_OPCODE(ip)                     @ jump to next instruction
6525     /* 10-13 instructions */
6526
6527
6528
6529 /* ------------------------------ */
6530     .balign 64
6531 .L_OP_DIV_INT_LIT16: /* 0xd3 */
6532 /* File: armv6t2/OP_DIV_INT_LIT16.S */
6533 /* File: armv6t2/binopLit16.S */
6534     /*
6535      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6536      * that specifies an instruction that performs "result = r0 op r1".
6537      * This could be an ARM instruction or a function call.  (If the result
6538      * comes back in a register other than r0, you can override "result".)
6539      *
6540      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6541      * vCC (r1).  Useful for integer division and modulus.
6542      *
6543      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6544      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6545      */
6546     /* binop/lit16 vA, vB, #+CCCC */
6547     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6548     mov     r2, rINST, lsr #12          @ r2<- B
6549     ubfx    r9, rINST, #8, #4           @ r9<- A
6550     GET_VREG(r0, r2)                    @ r0<- vB
6551     .if 1
6552     cmp     r1, #0                      @ is second operand zero?
6553     beq     common_errDivideByZero
6554     .endif
6555     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6556
6557     bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6558     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6559     SET_VREG(r0, r9)               @ vAA<- r0
6560     GOTO_OPCODE(ip)                     @ jump to next instruction
6561     /* 10-13 instructions */
6562
6563
6564
6565 /* ------------------------------ */
6566     .balign 64
6567 .L_OP_REM_INT_LIT16: /* 0xd4 */
6568 /* File: armv6t2/OP_REM_INT_LIT16.S */
6569 /* idivmod returns quotient in r0 and remainder in r1 */
6570 /* File: armv6t2/binopLit16.S */
6571     /*
6572      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6573      * that specifies an instruction that performs "result = r0 op r1".
6574      * This could be an ARM instruction or a function call.  (If the result
6575      * comes back in a register other than r0, you can override "result".)
6576      *
6577      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6578      * vCC (r1).  Useful for integer division and modulus.
6579      *
6580      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6581      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6582      */
6583     /* binop/lit16 vA, vB, #+CCCC */
6584     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6585     mov     r2, rINST, lsr #12          @ r2<- B
6586     ubfx    r9, rINST, #8, #4           @ r9<- A
6587     GET_VREG(r0, r2)                    @ r0<- vB
6588     .if 1
6589     cmp     r1, #0                      @ is second operand zero?
6590     beq     common_errDivideByZero
6591     .endif
6592     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6593
6594     bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6595     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6596     SET_VREG(r1, r9)               @ vAA<- r1
6597     GOTO_OPCODE(ip)                     @ jump to next instruction
6598     /* 10-13 instructions */
6599
6600
6601
6602 /* ------------------------------ */
6603     .balign 64
6604 .L_OP_AND_INT_LIT16: /* 0xd5 */
6605 /* File: armv6t2/OP_AND_INT_LIT16.S */
6606 /* File: armv6t2/binopLit16.S */
6607     /*
6608      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6609      * that specifies an instruction that performs "result = r0 op r1".
6610      * This could be an ARM instruction or a function call.  (If the result
6611      * comes back in a register other than r0, you can override "result".)
6612      *
6613      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6614      * vCC (r1).  Useful for integer division and modulus.
6615      *
6616      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6617      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6618      */
6619     /* binop/lit16 vA, vB, #+CCCC */
6620     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6621     mov     r2, rINST, lsr #12          @ r2<- B
6622     ubfx    r9, rINST, #8, #4           @ r9<- A
6623     GET_VREG(r0, r2)                    @ r0<- vB
6624     .if 0
6625     cmp     r1, #0                      @ is second operand zero?
6626     beq     common_errDivideByZero
6627     .endif
6628     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6629
6630     and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6631     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6632     SET_VREG(r0, r9)               @ vAA<- r0
6633     GOTO_OPCODE(ip)                     @ jump to next instruction
6634     /* 10-13 instructions */
6635
6636
6637
6638 /* ------------------------------ */
6639     .balign 64
6640 .L_OP_OR_INT_LIT16: /* 0xd6 */
6641 /* File: armv6t2/OP_OR_INT_LIT16.S */
6642 /* File: armv6t2/binopLit16.S */
6643     /*
6644      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6645      * that specifies an instruction that performs "result = r0 op r1".
6646      * This could be an ARM instruction or a function call.  (If the result
6647      * comes back in a register other than r0, you can override "result".)
6648      *
6649      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6650      * vCC (r1).  Useful for integer division and modulus.
6651      *
6652      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6653      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6654      */
6655     /* binop/lit16 vA, vB, #+CCCC */
6656     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6657     mov     r2, rINST, lsr #12          @ r2<- B
6658     ubfx    r9, rINST, #8, #4           @ r9<- A
6659     GET_VREG(r0, r2)                    @ r0<- vB
6660     .if 0
6661     cmp     r1, #0                      @ is second operand zero?
6662     beq     common_errDivideByZero
6663     .endif
6664     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6665
6666     orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6667     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6668     SET_VREG(r0, r9)               @ vAA<- r0
6669     GOTO_OPCODE(ip)                     @ jump to next instruction
6670     /* 10-13 instructions */
6671
6672
6673
6674 /* ------------------------------ */
6675     .balign 64
6676 .L_OP_XOR_INT_LIT16: /* 0xd7 */
6677 /* File: armv6t2/OP_XOR_INT_LIT16.S */
6678 /* File: armv6t2/binopLit16.S */
6679     /*
6680      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6681      * that specifies an instruction that performs "result = r0 op r1".
6682      * This could be an ARM instruction or a function call.  (If the result
6683      * comes back in a register other than r0, you can override "result".)
6684      *
6685      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6686      * vCC (r1).  Useful for integer division and modulus.
6687      *
6688      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6689      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6690      */
6691     /* binop/lit16 vA, vB, #+CCCC */
6692     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6693     mov     r2, rINST, lsr #12          @ r2<- B
6694     ubfx    r9, rINST, #8, #4           @ r9<- A
6695     GET_VREG(r0, r2)                    @ r0<- vB
6696     .if 0
6697     cmp     r1, #0                      @ is second operand zero?
6698     beq     common_errDivideByZero
6699     .endif
6700     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6701
6702     eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
6703     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6704     SET_VREG(r0, r9)               @ vAA<- r0
6705     GOTO_OPCODE(ip)                     @ jump to next instruction
6706     /* 10-13 instructions */
6707
6708
6709
6710 /* ------------------------------ */
6711     .balign 64
6712 .L_OP_ADD_INT_LIT8: /* 0xd8 */
6713 /* File: armv5te/OP_ADD_INT_LIT8.S */
6714 /* File: armv5te/binopLit8.S */
6715     /*
6716      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6717      * that specifies an instruction that performs "result = r0 op r1".
6718      * This could be an ARM instruction or a function call.  (If the result
6719      * comes back in a register other than r0, you can override "result".)
6720      *
6721      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6722      * vCC (r1).  Useful for integer division and modulus.
6723      *
6724      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6725      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6726      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6727      */
6728     /* binop/lit8 vAA, vBB, #+CC */
6729     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6730     mov     r9, rINST, lsr #8           @ r9<- AA
6731     and     r2, r3, #255                @ r2<- BB
6732     GET_VREG(r0, r2)                    @ r0<- vBB
6733     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6734     .if 0
6735     @cmp     r1, #0                      @ is second operand zero?
6736     beq     common_errDivideByZero
6737     .endif
6738     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6739
6740                                @ optional op; may set condition codes
6741     add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6742     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6743     SET_VREG(r0, r9)               @ vAA<- r0
6744     GOTO_OPCODE(ip)                     @ jump to next instruction
6745     /* 10-12 instructions */
6746
6747
6748
6749 /* ------------------------------ */
6750     .balign 64
6751 .L_OP_RSUB_INT_LIT8: /* 0xd9 */
6752 /* File: armv5te/OP_RSUB_INT_LIT8.S */
6753 /* File: armv5te/binopLit8.S */
6754     /*
6755      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6756      * that specifies an instruction that performs "result = r0 op r1".
6757      * This could be an ARM instruction or a function call.  (If the result
6758      * comes back in a register other than r0, you can override "result".)
6759      *
6760      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6761      * vCC (r1).  Useful for integer division and modulus.
6762      *
6763      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6764      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6765      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6766      */
6767     /* binop/lit8 vAA, vBB, #+CC */
6768     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6769     mov     r9, rINST, lsr #8           @ r9<- AA
6770     and     r2, r3, #255                @ r2<- BB
6771     GET_VREG(r0, r2)                    @ r0<- vBB
6772     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6773     .if 0
6774     @cmp     r1, #0                      @ is second operand zero?
6775     beq     common_errDivideByZero
6776     .endif
6777     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6778
6779                                @ optional op; may set condition codes
6780     rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6781     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6782     SET_VREG(r0, r9)               @ vAA<- r0
6783     GOTO_OPCODE(ip)                     @ jump to next instruction
6784     /* 10-12 instructions */
6785
6786
6787
6788 /* ------------------------------ */
6789     .balign 64
6790 .L_OP_MUL_INT_LIT8: /* 0xda */
6791 /* File: armv5te/OP_MUL_INT_LIT8.S */
6792 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6793 /* File: armv5te/binopLit8.S */
6794     /*
6795      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6796      * that specifies an instruction that performs "result = r0 op r1".
6797      * This could be an ARM instruction or a function call.  (If the result
6798      * comes back in a register other than r0, you can override "result".)
6799      *
6800      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6801      * vCC (r1).  Useful for integer division and modulus.
6802      *
6803      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6804      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6805      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6806      */
6807     /* binop/lit8 vAA, vBB, #+CC */
6808     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6809     mov     r9, rINST, lsr #8           @ r9<- AA
6810     and     r2, r3, #255                @ r2<- BB
6811     GET_VREG(r0, r2)                    @ r0<- vBB
6812     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6813     .if 0
6814     @cmp     r1, #0                      @ is second operand zero?
6815     beq     common_errDivideByZero
6816     .endif
6817     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6818
6819                                @ optional op; may set condition codes
6820     mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6821     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6822     SET_VREG(r0, r9)               @ vAA<- r0
6823     GOTO_OPCODE(ip)                     @ jump to next instruction
6824     /* 10-12 instructions */
6825
6826
6827
6828 /* ------------------------------ */
6829     .balign 64
6830 .L_OP_DIV_INT_LIT8: /* 0xdb */
6831 /* File: armv5te/OP_DIV_INT_LIT8.S */
6832 /* File: armv5te/binopLit8.S */
6833     /*
6834      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6835      * that specifies an instruction that performs "result = r0 op r1".
6836      * This could be an ARM instruction or a function call.  (If the result
6837      * comes back in a register other than r0, you can override "result".)
6838      *
6839      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6840      * vCC (r1).  Useful for integer division and modulus.
6841      *
6842      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6843      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6844      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6845      */
6846     /* binop/lit8 vAA, vBB, #+CC */
6847     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6848     mov     r9, rINST, lsr #8           @ r9<- AA
6849     and     r2, r3, #255                @ r2<- BB
6850     GET_VREG(r0, r2)                    @ r0<- vBB
6851     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6852     .if 1
6853     @cmp     r1, #0                      @ is second operand zero?
6854     beq     common_errDivideByZero
6855     .endif
6856     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6857
6858                                @ optional op; may set condition codes
6859     bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6860     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6861     SET_VREG(r0, r9)               @ vAA<- r0
6862     GOTO_OPCODE(ip)                     @ jump to next instruction
6863     /* 10-12 instructions */
6864
6865
6866
6867 /* ------------------------------ */
6868     .balign 64
6869 .L_OP_REM_INT_LIT8: /* 0xdc */
6870 /* File: armv5te/OP_REM_INT_LIT8.S */
6871 /* idivmod returns quotient in r0 and remainder in r1 */
6872 /* File: armv5te/binopLit8.S */
6873     /*
6874      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6875      * that specifies an instruction that performs "result = r0 op r1".
6876      * This could be an ARM instruction or a function call.  (If the result
6877      * comes back in a register other than r0, you can override "result".)
6878      *
6879      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6880      * vCC (r1).  Useful for integer division and modulus.
6881      *
6882      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6883      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6884      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6885      */
6886     /* binop/lit8 vAA, vBB, #+CC */
6887     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6888     mov     r9, rINST, lsr #8           @ r9<- AA
6889     and     r2, r3, #255                @ r2<- BB
6890     GET_VREG(r0, r2)                    @ r0<- vBB
6891     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6892     .if 1
6893     @cmp     r1, #0                      @ is second operand zero?
6894     beq     common_errDivideByZero
6895     .endif
6896     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6897
6898                                @ optional op; may set condition codes
6899     bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6900     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6901     SET_VREG(r1, r9)               @ vAA<- r1
6902     GOTO_OPCODE(ip)                     @ jump to next instruction
6903     /* 10-12 instructions */
6904
6905
6906
6907 /* ------------------------------ */
6908     .balign 64
6909 .L_OP_AND_INT_LIT8: /* 0xdd */
6910 /* File: armv5te/OP_AND_INT_LIT8.S */
6911 /* File: armv5te/binopLit8.S */
6912     /*
6913      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6914      * that specifies an instruction that performs "result = r0 op r1".
6915      * This could be an ARM instruction or a function call.  (If the result
6916      * comes back in a register other than r0, you can override "result".)
6917      *
6918      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6919      * vCC (r1).  Useful for integer division and modulus.
6920      *
6921      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6922      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6923      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6924      */
6925     /* binop/lit8 vAA, vBB, #+CC */
6926     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6927     mov     r9, rINST, lsr #8           @ r9<- AA
6928     and     r2, r3, #255                @ r2<- BB
6929     GET_VREG(r0, r2)                    @ r0<- vBB
6930     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6931     .if 0
6932     @cmp     r1, #0                      @ is second operand zero?
6933     beq     common_errDivideByZero
6934     .endif
6935     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6936
6937                                @ optional op; may set condition codes
6938     and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6939     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6940     SET_VREG(r0, r9)               @ vAA<- r0
6941     GOTO_OPCODE(ip)                     @ jump to next instruction
6942     /* 10-12 instructions */
6943
6944
6945
6946 /* ------------------------------ */
6947     .balign 64
6948 .L_OP_OR_INT_LIT8: /* 0xde */
6949 /* File: armv5te/OP_OR_INT_LIT8.S */
6950 /* File: armv5te/binopLit8.S */
6951     /*
6952      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6953      * that specifies an instruction that performs "result = r0 op r1".
6954      * This could be an ARM instruction or a function call.  (If the result
6955      * comes back in a register other than r0, you can override "result".)
6956      *
6957      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6958      * vCC (r1).  Useful for integer division and modulus.
6959      *
6960      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6961      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6962      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6963      */
6964     /* binop/lit8 vAA, vBB, #+CC */
6965     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6966     mov     r9, rINST, lsr #8           @ r9<- AA
6967     and     r2, r3, #255                @ r2<- BB
6968     GET_VREG(r0, r2)                    @ r0<- vBB
6969     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6970     .if 0
6971     @cmp     r1, #0                      @ is second operand zero?
6972     beq     common_errDivideByZero
6973     .endif
6974     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6975
6976                                @ optional op; may set condition codes
6977     orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6978     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6979     SET_VREG(r0, r9)               @ vAA<- r0
6980     GOTO_OPCODE(ip)                     @ jump to next instruction
6981     /* 10-12 instructions */
6982
6983
6984
6985 /* ------------------------------ */
6986     .balign 64
6987 .L_OP_XOR_INT_LIT8: /* 0xdf */
6988 /* File: armv5te/OP_XOR_INT_LIT8.S */
6989 /* File: armv5te/binopLit8.S */
6990     /*
6991      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6992      * that specifies an instruction that performs "result = r0 op r1".
6993      * This could be an ARM instruction or a function call.  (If the result
6994      * comes back in a register other than r0, you can override "result".)
6995      *
6996      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6997      * vCC (r1).  Useful for integer division and modulus.
6998      *
6999      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7000      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7001      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7002      */
7003     /* binop/lit8 vAA, vBB, #+CC */
7004     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7005     mov     r9, rINST, lsr #8           @ r9<- AA
7006     and     r2, r3, #255                @ r2<- BB
7007     GET_VREG(r0, r2)                    @ r0<- vBB
7008     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7009     .if 0
7010     @cmp     r1, #0                      @ is second operand zero?
7011     beq     common_errDivideByZero
7012     .endif
7013     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7014
7015                                @ optional op; may set condition codes
7016     eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
7017     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7018     SET_VREG(r0, r9)               @ vAA<- r0
7019     GOTO_OPCODE(ip)                     @ jump to next instruction
7020     /* 10-12 instructions */
7021
7022
7023
7024 /* ------------------------------ */
7025     .balign 64
7026 .L_OP_SHL_INT_LIT8: /* 0xe0 */
7027 /* File: armv5te/OP_SHL_INT_LIT8.S */
7028 /* File: armv5te/binopLit8.S */
7029     /*
7030      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7031      * that specifies an instruction that performs "result = r0 op r1".
7032      * This could be an ARM instruction or a function call.  (If the result
7033      * comes back in a register other than r0, you can override "result".)
7034      *
7035      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7036      * vCC (r1).  Useful for integer division and modulus.
7037      *
7038      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7039      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7040      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7041      */
7042     /* binop/lit8 vAA, vBB, #+CC */
7043     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7044     mov     r9, rINST, lsr #8           @ r9<- AA
7045     and     r2, r3, #255                @ r2<- BB
7046     GET_VREG(r0, r2)                    @ r0<- vBB
7047     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7048     .if 0
7049     @cmp     r1, #0                      @ is second operand zero?
7050     beq     common_errDivideByZero
7051     .endif
7052     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7053
7054     and     r1, r1, #31                           @ optional op; may set condition codes
7055     mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
7056     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7057     SET_VREG(r0, r9)               @ vAA<- r0
7058     GOTO_OPCODE(ip)                     @ jump to next instruction
7059     /* 10-12 instructions */
7060
7061
7062
7063 /* ------------------------------ */
7064     .balign 64
7065 .L_OP_SHR_INT_LIT8: /* 0xe1 */
7066 /* File: armv5te/OP_SHR_INT_LIT8.S */
7067 /* File: armv5te/binopLit8.S */
7068     /*
7069      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7070      * that specifies an instruction that performs "result = r0 op r1".
7071      * This could be an ARM instruction or a function call.  (If the result
7072      * comes back in a register other than r0, you can override "result".)
7073      *
7074      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7075      * vCC (r1).  Useful for integer division and modulus.
7076      *
7077      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7078      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7079      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7080      */
7081     /* binop/lit8 vAA, vBB, #+CC */
7082     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7083     mov     r9, rINST, lsr #8           @ r9<- AA
7084     and     r2, r3, #255                @ r2<- BB
7085     GET_VREG(r0, r2)                    @ r0<- vBB
7086     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7087     .if 0
7088     @cmp     r1, #0                      @ is second operand zero?
7089     beq     common_errDivideByZero
7090     .endif
7091     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7092
7093     and     r1, r1, #31                           @ optional op; may set condition codes
7094     mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
7095     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7096     SET_VREG(r0, r9)               @ vAA<- r0
7097     GOTO_OPCODE(ip)                     @ jump to next instruction
7098     /* 10-12 instructions */
7099
7100
7101
7102 /* ------------------------------ */
7103     .balign 64
7104 .L_OP_USHR_INT_LIT8: /* 0xe2 */
7105 /* File: armv5te/OP_USHR_INT_LIT8.S */
7106 /* File: armv5te/binopLit8.S */
7107     /*
7108      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7109      * that specifies an instruction that performs "result = r0 op r1".
7110      * This could be an ARM instruction or a function call.  (If the result
7111      * comes back in a register other than r0, you can override "result".)
7112      *
7113      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7114      * vCC (r1).  Useful for integer division and modulus.
7115      *
7116      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7117      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7118      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7119      */
7120     /* binop/lit8 vAA, vBB, #+CC */
7121     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7122     mov     r9, rINST, lsr #8           @ r9<- AA
7123     and     r2, r3, #255                @ r2<- BB
7124     GET_VREG(r0, r2)                    @ r0<- vBB
7125     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7126     .if 0
7127     @cmp     r1, #0                      @ is second operand zero?
7128     beq     common_errDivideByZero
7129     .endif
7130     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7131
7132     and     r1, r1, #31                           @ optional op; may set condition codes
7133     mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
7134     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7135     SET_VREG(r0, r9)               @ vAA<- r0
7136     GOTO_OPCODE(ip)                     @ jump to next instruction
7137     /* 10-12 instructions */
7138
7139
7140
7141 /* ------------------------------ */
7142     .balign 64
7143 .L_OP_UNUSED_E3: /* 0xe3 */
7144 /* File: armv5te/OP_UNUSED_E3.S */
7145 /* File: armv5te/unused.S */
7146     bl      common_abort
7147
7148
7149
7150 /* ------------------------------ */
7151     .balign 64
7152 .L_OP_UNUSED_E4: /* 0xe4 */
7153 /* File: armv5te/OP_UNUSED_E4.S */
7154 /* File: armv5te/unused.S */
7155     bl      common_abort
7156
7157
7158
7159 /* ------------------------------ */
7160     .balign 64
7161 .L_OP_UNUSED_E5: /* 0xe5 */
7162 /* File: armv5te/OP_UNUSED_E5.S */
7163 /* File: armv5te/unused.S */
7164     bl      common_abort
7165
7166
7167
7168 /* ------------------------------ */
7169     .balign 64
7170 .L_OP_UNUSED_E6: /* 0xe6 */
7171 /* File: armv5te/OP_UNUSED_E6.S */
7172 /* File: armv5te/unused.S */
7173     bl      common_abort
7174
7175
7176
7177 /* ------------------------------ */
7178     .balign 64
7179 .L_OP_UNUSED_E7: /* 0xe7 */
7180 /* File: armv5te/OP_UNUSED_E7.S */
7181 /* File: armv5te/unused.S */
7182     bl      common_abort
7183
7184
7185
7186 /* ------------------------------ */
7187     .balign 64
7188 .L_OP_UNUSED_E8: /* 0xe8 */
7189 /* File: armv5te/OP_UNUSED_E8.S */
7190 /* File: armv5te/unused.S */
7191     bl      common_abort
7192
7193
7194
7195 /* ------------------------------ */
7196     .balign 64
7197 .L_OP_UNUSED_E9: /* 0xe9 */
7198 /* File: armv5te/OP_UNUSED_E9.S */
7199 /* File: armv5te/unused.S */
7200     bl      common_abort
7201
7202
7203
7204 /* ------------------------------ */
7205     .balign 64
7206 .L_OP_UNUSED_EA: /* 0xea */
7207 /* File: armv5te/OP_UNUSED_EA.S */
7208 /* File: armv5te/unused.S */
7209     bl      common_abort
7210
7211
7212
7213 /* ------------------------------ */
7214     .balign 64
7215 .L_OP_UNUSED_EB: /* 0xeb */
7216 /* File: armv5te/OP_UNUSED_EB.S */
7217 /* File: armv5te/unused.S */
7218     bl      common_abort
7219
7220
7221
7222 /* ------------------------------ */
7223     .balign 64
7224 .L_OP_UNUSED_EC: /* 0xec */
7225 /* File: armv5te/OP_UNUSED_EC.S */
7226 /* File: armv5te/unused.S */
7227     bl      common_abort
7228
7229
7230
7231 /* ------------------------------ */
7232     .balign 64
7233 .L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
7234 /* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
7235     /*
7236      * Handle a throw-verification-error instruction.  This throws an
7237      * exception for an error discovered during verification.  The
7238      * exception is indicated by AA, with some detail provided by BBBB.
7239      */
7240     /* op AA, ref@BBBB */
7241     ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7242     FETCH(r2, 1)                        @ r2<- BBBB
7243     EXPORT_PC()                         @ export the PC
7244     mov     r1, rINST, lsr #8           @ r1<- AA
7245     bl      dvmThrowVerificationError   @ always throws
7246     b       common_exceptionThrown      @ handle exception
7247
7248
7249 /* ------------------------------ */
7250     .balign 64
7251 .L_OP_EXECUTE_INLINE: /* 0xee */
7252 /* File: armv5te/OP_EXECUTE_INLINE.S */
7253     /*
7254      * Execute a "native inline" instruction.
7255      *
7256      * We need to call:
7257      *  dvmPerformInlineOp4Std(arg0, arg1, arg2, arg3, &retval, ref)
7258      *
7259      * The first four args are in r0-r3, but the last two must be pushed
7260      * onto the stack.
7261      */
7262     /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
7263     FETCH(r10, 1)                       @ r10<- BBBB
7264     add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7265     EXPORT_PC()                         @ can throw
7266     sub     sp, sp, #8                  @ make room for arg(s)
7267     mov     r0, rINST, lsr #12          @ r0<- B
7268     str     r1, [sp]                    @ push &glue->retval
7269     bl      .LOP_EXECUTE_INLINE_continue        @ make call; will return after
7270     add     sp, sp, #8                  @ pop stack
7271     cmp     r0, #0                      @ test boolean result of inline
7272     beq     common_exceptionThrown      @ returned false, handle exception
7273     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7274     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7275     GOTO_OPCODE(ip)                     @ jump to next instruction
7276
7277 /* ------------------------------ */
7278     .balign 64
7279 .L_OP_UNUSED_EF: /* 0xef */
7280 /* File: armv5te/OP_UNUSED_EF.S */
7281 /* File: armv5te/unused.S */
7282     bl      common_abort
7283
7284
7285
7286 /* ------------------------------ */
7287     .balign 64
7288 .L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
7289 /* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
7290     /*
7291      * invoke-direct-empty is a no-op in a "standard" interpreter.
7292      */
7293     FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7294     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7295     GOTO_OPCODE(ip)                     @ execute it
7296
7297 /* ------------------------------ */
7298     .balign 64
7299 .L_OP_UNUSED_F1: /* 0xf1 */
7300 /* File: armv5te/OP_UNUSED_F1.S */
7301 /* File: armv5te/unused.S */
7302     bl      common_abort
7303
7304
7305
7306 /* ------------------------------ */
7307     .balign 64
7308 .L_OP_IGET_QUICK: /* 0xf2 */
7309 /* File: armv6t2/OP_IGET_QUICK.S */
7310     /* For: iget-quick, iget-object-quick */
7311     /* op vA, vB, offset@CCCC */
7312     mov     r2, rINST, lsr #12          @ r2<- B
7313     FETCH(r1, 1)                        @ r1<- field byte offset
7314     GET_VREG(r3, r2)                    @ r3<- object we're operating on
7315     ubfx    r2, rINST, #8, #4           @ r2<- A
7316     cmp     r3, #0                      @ check object for null
7317     beq     common_errNullObject        @ object was null
7318     ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7319     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7320     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7321     SET_VREG(r0, r2)                    @ fp[A]<- r0
7322     GOTO_OPCODE(ip)                     @ jump to next instruction
7323
7324
7325 /* ------------------------------ */
7326     .balign 64
7327 .L_OP_IGET_WIDE_QUICK: /* 0xf3 */
7328 /* File: armv6t2/OP_IGET_WIDE_QUICK.S */
7329     /* iget-wide-quick vA, vB, offset@CCCC */
7330     mov     r2, rINST, lsr #12          @ r2<- B
7331     FETCH(r1, 1)                        @ r1<- field byte offset
7332     GET_VREG(r3, r2)                    @ r3<- object we're operating on
7333     ubfx    r2, rINST, #8, #4           @ r2<- A
7334     cmp     r3, #0                      @ check object for null
7335     beq     common_errNullObject        @ object was null
7336     ldrd    r0, [r3, r1]                @ r0<- obj.field (64 bits, aligned)
7337     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7338     add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
7339     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7340     stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
7341     GOTO_OPCODE(ip)                     @ jump to next instruction
7342
7343
7344 /* ------------------------------ */
7345     .balign 64
7346 .L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
7347 /* File: armv5te/OP_IGET_OBJECT_QUICK.S */
7348 /* File: armv5te/OP_IGET_QUICK.S */
7349     /* For: iget-quick, iget-object-quick */
7350     /* op vA, vB, offset@CCCC */
7351     mov     r2, rINST, lsr #12          @ r2<- B
7352     GET_VREG(r3, r2)                    @ r3<- object we're operating on
7353     FETCH(r1, 1)                        @ r1<- field byte offset
7354     cmp     r3, #0                      @ check object for null
7355     mov     r2, rINST, lsr #8           @ r2<- A(+)
7356     beq     common_errNullObject        @ object was null
7357     ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7358     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7359     and     r2, r2, #15
7360     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7361     SET_VREG(r0, r2)                    @ fp[A]<- r0
7362     GOTO_OPCODE(ip)                     @ jump to next instruction
7363
7364
7365
7366 /* ------------------------------ */
7367     .balign 64
7368 .L_OP_IPUT_QUICK: /* 0xf5 */
7369 /* File: armv6t2/OP_IPUT_QUICK.S */
7370     /* For: iput-quick, iput-object-quick */
7371     /* op vA, vB, offset@CCCC */
7372     mov     r2, rINST, lsr #12          @ r2<- B
7373     FETCH(r1, 1)                        @ r1<- field byte offset
7374     GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7375     ubfx    r2, rINST, #8, #4           @ r2<- A
7376     cmp     r3, #0                      @ check object for null
7377     beq     common_errNullObject        @ object was null
7378     GET_VREG(r0, r2)                    @ r0<- fp[A]
7379     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7380     str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7381     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7382     GOTO_OPCODE(ip)                     @ jump to next instruction
7383
7384
7385 /* ------------------------------ */
7386     .balign 64
7387 .L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
7388 /* File: armv6t2/OP_IPUT_WIDE_QUICK.S */
7389     /* iput-wide-quick vA, vB, offset@CCCC */
7390     mov     r1, rINST, lsr #12          @ r1<- B
7391     ubfx    r0, rINST, #8, #4           @ r0<- A
7392     GET_VREG(r2, r1)                    @ r2<- fp[B], the object pointer
7393     add     r3, rFP, r0, lsl #2         @ r3<- &fp[A]
7394     cmp     r2, #0                      @ check object for null
7395     ldmia   r3, {r0-r1}                 @ r0/r1<- fp[A]
7396     beq     common_errNullObject        @ object was null
7397     FETCH(r3, 1)                        @ r3<- field byte offset
7398     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7399     strd    r0, [r2, r3]                @ obj.field (64 bits, aligned)<- r0/r1
7400     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7401     GOTO_OPCODE(ip)                     @ jump to next instruction
7402
7403
7404 /* ------------------------------ */
7405     .balign 64
7406 .L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
7407 /* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
7408 /* File: armv5te/OP_IPUT_QUICK.S */
7409     /* For: iput-quick, iput-object-quick */
7410     /* op vA, vB, offset@CCCC */
7411     mov     r2, rINST, lsr #12          @ r2<- B
7412     GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7413     FETCH(r1, 1)                        @ r1<- field byte offset
7414     cmp     r3, #0                      @ check object for null
7415     mov     r2, rINST, lsr #8           @ r2<- A(+)
7416     beq     common_errNullObject        @ object was null
7417     and     r2, r2, #15
7418     GET_VREG(r0, r2)                    @ r0<- fp[A]
7419     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7420     str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7421     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7422     GOTO_OPCODE(ip)                     @ jump to next instruction
7423
7424
7425
7426 /* ------------------------------ */
7427     .balign 64
7428 .L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
7429 /* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7430     /*
7431      * Handle an optimized virtual method call.
7432      *
7433      * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7434      */
7435     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7436     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7437     FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7438     FETCH(r1, 1)                        @ r1<- BBBB
7439     .if     (!0)
7440     and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7441     .endif
7442     GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7443     cmp     r2, #0                      @ is "this" null?
7444     beq     common_errNullObject        @ null "this", throw exception
7445     ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7446     ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7447     EXPORT_PC()                         @ invoke must export
7448     ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7449     bl      common_invokeMethodNoRange @ continue on
7450
7451 /* ------------------------------ */
7452     .balign 64
7453 .L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
7454 /* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
7455 /* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7456     /*
7457      * Handle an optimized virtual method call.
7458      *
7459      * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7460      */
7461     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7462     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7463     FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7464     FETCH(r1, 1)                        @ r1<- BBBB
7465     .if     (!1)
7466     and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7467     .endif
7468     GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7469     cmp     r2, #0                      @ is "this" null?
7470     beq     common_errNullObject        @ null "this", throw exception
7471     ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7472     ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7473     EXPORT_PC()                         @ invoke must export
7474     ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7475     bl      common_invokeMethodRange @ continue on
7476
7477
7478 /* ------------------------------ */
7479     .balign 64
7480 .L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
7481 /* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7482     /*
7483      * Handle an optimized "super" method call.
7484      *
7485      * for: [opt] invoke-super-quick, invoke-super-quick/range
7486      */
7487     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7488     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7489     FETCH(r10, 2)                       @ r10<- GFED or CCCC
7490     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7491     .if     (!0)
7492     and     r10, r10, #15               @ r10<- D (or stays CCCC)
7493     .endif
7494     FETCH(r1, 1)                        @ r1<- BBBB
7495     ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7496     EXPORT_PC()                         @ must export for invoke
7497     ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7498     GET_VREG(r3, r10)                   @ r3<- "this"
7499     ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7500     cmp     r3, #0                      @ null "this" ref?
7501     ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7502     beq     common_errNullObject        @ "this" is null, throw exception
7503     bl      common_invokeMethodNoRange @ continue on
7504
7505
7506 /* ------------------------------ */
7507     .balign 64
7508 .L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
7509 /* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
7510 /* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7511     /*
7512      * Handle an optimized "super" method call.
7513      *
7514      * for: [opt] invoke-super-quick, invoke-super-quick/range
7515      */
7516     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7517     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7518     FETCH(r10, 2)                       @ r10<- GFED or CCCC
7519     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7520     .if     (!1)
7521     and     r10, r10, #15               @ r10<- D (or stays CCCC)
7522     .endif
7523     FETCH(r1, 1)                        @ r1<- BBBB
7524     ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7525     EXPORT_PC()                         @ must export for invoke
7526     ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7527     GET_VREG(r3, r10)                   @ r3<- "this"
7528     ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7529     cmp     r3, #0                      @ null "this" ref?
7530     ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7531     beq     common_errNullObject        @ "this" is null, throw exception
7532     bl      common_invokeMethodRange @ continue on
7533
7534
7535
7536 /* ------------------------------ */
7537     .balign 64
7538 .L_OP_UNUSED_FC: /* 0xfc */
7539 /* File: armv5te/OP_UNUSED_FC.S */
7540 /* File: armv5te/unused.S */
7541     bl      common_abort
7542
7543
7544
7545 /* ------------------------------ */
7546     .balign 64
7547 .L_OP_UNUSED_FD: /* 0xfd */
7548 /* File: armv5te/OP_UNUSED_FD.S */
7549 /* File: armv5te/unused.S */
7550     bl      common_abort
7551
7552
7553
7554 /* ------------------------------ */
7555     .balign 64
7556 .L_OP_UNUSED_FE: /* 0xfe */
7557 /* File: armv5te/OP_UNUSED_FE.S */
7558 /* File: armv5te/unused.S */
7559     bl      common_abort
7560
7561
7562
7563 /* ------------------------------ */
7564     .balign 64
7565 .L_OP_UNUSED_FF: /* 0xff */
7566 /* File: armv5te/OP_UNUSED_FF.S */
7567 /* File: armv5te/unused.S */
7568     bl      common_abort
7569
7570
7571
7572
7573     .balign 64
7574     .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
7575     .global dvmAsmInstructionEnd
7576 dvmAsmInstructionEnd:
7577
7578 /*
7579  * ===========================================================================
7580  *  Sister implementations
7581  * ===========================================================================
7582  */
7583     .global dvmAsmSisterStart
7584     .type   dvmAsmSisterStart, %function
7585     .text
7586     .balign 4
7587 dvmAsmSisterStart:
7588
7589 /* continuation for OP_CONST_STRING */
7590
7591     /*
7592      * Continuation if the String has not yet been resolved.
7593      *  r1: BBBB (String ref)
7594      *  r9: target register
7595      */
7596 .LOP_CONST_STRING_resolve:
7597     EXPORT_PC()
7598     ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7599     ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7600     bl      dvmResolveString            @ r0<- String reference
7601     cmp     r0, #0                      @ failed?
7602     beq     common_exceptionThrown      @ yup, handle the exception
7603     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7604     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7605     SET_VREG(r0, r9)                    @ vAA<- r0
7606     GOTO_OPCODE(ip)                     @ jump to next instruction
7607
7608
7609 /* continuation for OP_CONST_STRING_JUMBO */
7610
7611     /*
7612      * Continuation if the String has not yet been resolved.
7613      *  r1: BBBBBBBB (String ref)
7614      *  r9: target register
7615      */
7616 .LOP_CONST_STRING_JUMBO_resolve:
7617     EXPORT_PC()
7618     ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7619     ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7620     bl      dvmResolveString            @ r0<- String reference
7621     cmp     r0, #0                      @ failed?
7622     beq     common_exceptionThrown      @ yup, handle the exception
7623     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7624     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7625     SET_VREG(r0, r9)                    @ vAA<- r0
7626     GOTO_OPCODE(ip)                     @ jump to next instruction
7627
7628
7629 /* continuation for OP_CONST_CLASS */
7630
7631     /*
7632      * Continuation if the Class has not yet been resolved.
7633      *  r1: BBBB (Class ref)
7634      *  r9: target register
7635      */
7636 .LOP_CONST_CLASS_resolve:
7637     EXPORT_PC()
7638     ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7639     mov     r2, #1                      @ r2<- true
7640     ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7641     bl      dvmResolveClass             @ r0<- Class reference
7642     cmp     r0, #0                      @ failed?
7643     beq     common_exceptionThrown      @ yup, handle the exception
7644     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7645     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7646     SET_VREG(r0, r9)                    @ vAA<- r0
7647     GOTO_OPCODE(ip)                     @ jump to next instruction
7648
7649
7650 /* continuation for OP_CHECK_CAST */
7651
7652     /*
7653      * Trivial test failed, need to perform full check.  This is common.
7654      *  r0 holds obj->clazz
7655      *  r1 holds class resolved from BBBB
7656      *  r9 holds object
7657      */
7658 .LOP_CHECK_CAST_fullcheck:
7659     bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7660     cmp     r0, #0                      @ failed?
7661     bne     .LOP_CHECK_CAST_okay            @ no, success
7662
7663     @ A cast has failed.  We need to throw a ClassCastException with the
7664     @ class of the object that failed to be cast.
7665     EXPORT_PC()                         @ about to throw
7666     ldr     r3, [r9, #offObject_clazz]  @ r3<- obj->clazz
7667     ldr     r0, .LstrClassCastExceptionPtr
7668     ldr     r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor
7669     bl      dvmThrowExceptionWithClassMessage
7670     b       common_exceptionThrown
7671
7672     /*
7673      * Resolution required.  This is the least-likely path.
7674      *
7675      *  r2 holds BBBB
7676      *  r9 holds object
7677      */
7678 .LOP_CHECK_CAST_resolve:
7679     EXPORT_PC()                         @ resolve() could throw
7680     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7681     mov     r1, r2                      @ r1<- BBBB
7682     mov     r2, #0                      @ r2<- false
7683     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7684     bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7685     cmp     r0, #0                      @ got null?
7686     beq     common_exceptionThrown      @ yes, handle exception
7687     mov     r1, r0                      @ r1<- class resolved from BBB
7688     ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
7689     b       .LOP_CHECK_CAST_resolved        @ pick up where we left off
7690
7691 .LstrClassCastExceptionPtr:
7692     .word   .LstrClassCastException
7693
7694
7695 /* continuation for OP_INSTANCE_OF */
7696
7697     /*
7698      * Trivial test failed, need to perform full check.  This is common.
7699      *  r0 holds obj->clazz
7700      *  r1 holds class resolved from BBBB
7701      *  r9 holds A
7702      */
7703 .LOP_INSTANCE_OF_fullcheck:
7704     bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7705     @ fall through to OP_INSTANCE_OF_store
7706
7707     /*
7708      * r0 holds boolean result
7709      * r9 holds A
7710      */
7711 .LOP_INSTANCE_OF_store:
7712     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7713     SET_VREG(r0, r9)                    @ vA<- r0
7714     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7715     GOTO_OPCODE(ip)                     @ jump to next instruction
7716
7717     /*
7718      * Trivial test succeeded, save and bail.
7719      *  r9 holds A
7720      */
7721 .LOP_INSTANCE_OF_trivial:
7722     mov     r0, #1                      @ indicate success
7723     @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
7724     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7725     SET_VREG(r0, r9)                    @ vA<- r0
7726     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7727     GOTO_OPCODE(ip)                     @ jump to next instruction
7728
7729     /*
7730      * Resolution required.  This is the least-likely path.
7731      *
7732      *  r3 holds BBBB
7733      *  r9 holds A
7734      */
7735 .LOP_INSTANCE_OF_resolve:
7736     EXPORT_PC()                         @ resolve() could throw
7737     ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7738     mov     r1, r3                      @ r1<- BBBB
7739     mov     r2, #1                      @ r2<- true
7740     ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7741     bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7742     cmp     r0, #0                      @ got null?
7743     beq     common_exceptionThrown      @ yes, handle exception
7744     mov     r1, r0                      @ r1<- class resolved from BBB
7745     mov     r3, rINST, lsr #12          @ r3<- B
7746     GET_VREG(r0, r3)                    @ r0<- vB (object)
7747     ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
7748     b       .LOP_INSTANCE_OF_resolved        @ pick up where we left off
7749
7750
7751 /* continuation for OP_NEW_INSTANCE */
7752
7753     .balign 32                          @ minimize cache lines
7754 .LOP_NEW_INSTANCE_finish: @ r0=new object
7755     mov     r3, rINST, lsr #8           @ r3<- AA
7756     cmp     r0, #0                      @ failed?
7757     beq     common_exceptionThrown      @ yes, handle the exception
7758     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7759     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7760     SET_VREG(r0, r3)                    @ vAA<- r0
7761     GOTO_OPCODE(ip)                     @ jump to next instruction
7762
7763     /*
7764      * Class initialization required.
7765      *
7766      *  r0 holds class object
7767      */
7768 .LOP_NEW_INSTANCE_needinit:
7769     mov     r9, r0                      @ save r0
7770     bl      dvmInitClass                @ initialize class
7771     cmp     r0, #0                      @ check boolean result
7772     mov     r0, r9                      @ restore r0
7773     bne     .LOP_NEW_INSTANCE_initialized     @ success, continue
7774     b       common_exceptionThrown      @ failed, deal with init exception
7775
7776     /*
7777      * Resolution required.  This is the least-likely path.
7778      *
7779      *  r1 holds BBBB
7780      */
7781 .LOP_NEW_INSTANCE_resolve:
7782     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7783     mov     r2, #0                      @ r2<- false
7784     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7785     bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7786     cmp     r0, #0                      @ got null?
7787     bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
7788     b       common_exceptionThrown      @ yes, handle exception
7789
7790 .LstrInstantiationErrorPtr:
7791     .word   .LstrInstantiationError
7792
7793
7794 /* continuation for OP_NEW_ARRAY */
7795
7796
7797     /*
7798      * Resolve class.  (This is an uncommon case.)
7799      *
7800      *  r1 holds array length
7801      *  r2 holds class ref CCCC
7802      */
7803 .LOP_NEW_ARRAY_resolve:
7804     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7805     mov     r9, r1                      @ r9<- length (save)
7806     mov     r1, r2                      @ r1<- CCCC
7807     mov     r2, #0                      @ r2<- false
7808     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7809     bl      dvmResolveClass             @ r0<- call(clazz, ref)
7810     cmp     r0, #0                      @ got null?
7811     mov     r1, r9                      @ r1<- length (restore)
7812     beq     common_exceptionThrown      @ yes, handle exception
7813     @ fall through to OP_NEW_ARRAY_finish
7814
7815     /*
7816      * Finish allocation.
7817      *
7818      *  r0 holds class
7819      *  r1 holds array length
7820      */
7821 .LOP_NEW_ARRAY_finish:
7822     mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
7823     bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
7824     cmp     r0, #0                      @ failed?
7825     mov     r2, rINST, lsr #8           @ r2<- A+
7826     beq     common_exceptionThrown      @ yes, handle the exception
7827     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7828     and     r2, r2, #15                 @ r2<- A
7829     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7830     SET_VREG(r0, r2)                    @ vA<- r0
7831     GOTO_OPCODE(ip)                     @ jump to next instruction
7832
7833
7834 /* continuation for OP_FILLED_NEW_ARRAY */
7835
7836     /*
7837      * On entry:
7838      *  r0 holds array class
7839      *  r10 holds AA or BA
7840      */
7841 .LOP_FILLED_NEW_ARRAY_continue:
7842     ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
7843     mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
7844     ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
7845     .if     0
7846     mov     r1, r10                     @ r1<- AA (length)
7847     .else
7848     mov     r1, r10, lsr #4             @ r1<- B (length)
7849     .endif
7850     cmp     r3, #'I'                    @ array of ints?
7851     cmpne   r3, #'L'                    @ array of objects?
7852     cmpne   r3, #'['                    @ array of arrays?
7853     mov     r9, r1                      @ save length in r9
7854     bne     .LOP_FILLED_NEW_ARRAY_notimpl         @ no, not handled yet
7855     bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
7856     cmp     r0, #0                      @ null return?
7857     beq     common_exceptionThrown      @ alloc failed, handle exception
7858
7859     FETCH(r1, 2)                        @ r1<- FEDC or CCCC
7860     str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
7861     add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
7862     subs    r9, r9, #1                  @ length--, check for neg
7863     FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7864     bmi     2f                          @ was zero, bail
7865
7866     @ copy values from registers into the array
7867     @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
7868     .if     0
7869     add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
7870 1:  ldr     r3, [r2], #4                @ r3<- *r2++
7871     subs    r9, r9, #1                  @ count--
7872     str     r3, [r0], #4                @ *contents++ = vX
7873     bpl     1b
7874     @ continue at 2
7875     .else
7876     cmp     r9, #4                      @ length was initially 5?
7877     and     r2, r10, #15                @ r2<- A
7878     bne     1f                          @ <= 4 args, branch
7879     GET_VREG(r3, r2)                    @ r3<- vA
7880     sub     r9, r9, #1                  @ count--
7881     str     r3, [r0, #16]               @ contents[4] = vA
7882 1:  and     r2, r1, #15                 @ r2<- F/E/D/C
7883     GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
7884     mov     r1, r1, lsr #4              @ r1<- next reg in low 4
7885     subs    r9, r9, #1                  @ count--
7886     str     r3, [r0], #4                @ *contents++ = vX
7887     bpl     1b
7888     @ continue at 2
7889     .endif
7890
7891 2:
7892     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7893     GOTO_OPCODE(ip)                     @ execute it
7894
7895     /*
7896      * Throw an exception indicating that we have not implemented this
7897      * mode of filled-new-array.
7898      */
7899 .LOP_FILLED_NEW_ARRAY_notimpl:
7900     ldr     r0, .L_strInternalError
7901     ldr     r1, .L_strFilledNewArrayNotImpl
7902     bl      dvmThrowException
7903     b       common_exceptionThrown
7904
7905     .if     (!0)                 @ define in one or the other, not both
7906 .L_strFilledNewArrayNotImpl:
7907     .word   .LstrFilledNewArrayNotImpl
7908 .L_strInternalError:
7909     .word   .LstrInternalError
7910     .endif
7911
7912
7913 /* continuation for OP_FILLED_NEW_ARRAY_RANGE */
7914
7915     /*
7916      * On entry:
7917      *  r0 holds array class
7918      *  r10 holds AA or BA
7919      */
7920 .LOP_FILLED_NEW_ARRAY_RANGE_continue:
7921     ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
7922     mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
7923     ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
7924     .if     1
7925     mov     r1, r10                     @ r1<- AA (length)
7926     .else
7927     mov     r1, r10, lsr #4             @ r1<- B (length)
7928     .endif
7929     cmp     r3, #'I'                    @ array of ints?
7930     cmpne   r3, #'L'                    @ array of objects?
7931     cmpne   r3, #'['                    @ array of arrays?
7932     mov     r9, r1                      @ save length in r9
7933     bne     .LOP_FILLED_NEW_ARRAY_RANGE_notimpl         @ no, not handled yet
7934     bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
7935     cmp     r0, #0                      @ null return?
7936     beq     common_exceptionThrown      @ alloc failed, handle exception
7937
7938     FETCH(r1, 2)                        @ r1<- FEDC or CCCC
7939     str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
7940     add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
7941     subs    r9, r9, #1                  @ length--, check for neg
7942     FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7943     bmi     2f                          @ was zero, bail
7944
7945     @ copy values from registers into the array
7946     @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
7947     .if     1
7948     add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
7949 1:  ldr     r3, [r2], #4                @ r3<- *r2++
7950     subs    r9, r9, #1                  @ count--
7951     str     r3, [r0], #4                @ *contents++ = vX
7952     bpl     1b
7953     @ continue at 2
7954     .else
7955     cmp     r9, #4                      @ length was initially 5?
7956     and     r2, r10, #15                @ r2<- A
7957     bne     1f                          @ <= 4 args, branch
7958     GET_VREG(r3, r2)                    @ r3<- vA
7959     sub     r9, r9, #1                  @ count--
7960     str     r3, [r0, #16]               @ contents[4] = vA
7961 1:  and     r2, r1, #15                 @ r2<- F/E/D/C
7962     GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
7963     mov     r1, r1, lsr #4              @ r1<- next reg in low 4
7964     subs    r9, r9, #1                  @ count--
7965     str     r3, [r0], #4                @ *contents++ = vX
7966     bpl     1b
7967     @ continue at 2
7968     .endif
7969
7970 2:
7971     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7972     GOTO_OPCODE(ip)                     @ execute it
7973
7974     /*
7975      * Throw an exception indicating that we have not implemented this
7976      * mode of filled-new-array.
7977      */
7978 .LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
7979     ldr     r0, .L_strInternalError
7980     ldr     r1, .L_strFilledNewArrayNotImpl
7981     bl      dvmThrowException
7982     b       common_exceptionThrown
7983
7984     .if     (!1)                 @ define in one or the other, not both
7985 .L_strFilledNewArrayNotImpl:
7986     .word   .LstrFilledNewArrayNotImpl
7987 .L_strInternalError:
7988     .word   .LstrInternalError
7989     .endif
7990
7991
7992 /* continuation for OP_CMPL_FLOAT */
7993 .LOP_CMPL_FLOAT_finish:
7994     SET_VREG(r0, r9)                    @ vAA<- r0
7995     GOTO_OPCODE(ip)                     @ jump to next instruction
7996
7997
7998 /* continuation for OP_CMPG_FLOAT */
7999 .LOP_CMPG_FLOAT_finish:
8000     SET_VREG(r0, r9)                    @ vAA<- r0
8001     GOTO_OPCODE(ip)                     @ jump to next instruction
8002
8003
8004 /* continuation for OP_CMPL_DOUBLE */
8005 .LOP_CMPL_DOUBLE_finish:
8006     SET_VREG(r0, r9)                    @ vAA<- r0
8007     GOTO_OPCODE(ip)                     @ jump to next instruction
8008
8009
8010 /* continuation for OP_CMPG_DOUBLE */
8011 .LOP_CMPG_DOUBLE_finish:
8012     SET_VREG(r0, r9)                    @ vAA<- r0
8013     GOTO_OPCODE(ip)                     @ jump to next instruction
8014
8015
8016 /* continuation for OP_CMP_LONG */
8017
8018 .LOP_CMP_LONG_less:
8019     mvn     r1, #0                      @ r1<- -1
8020     @ Want to cond code the next mov so we can avoid branch, but don't see it;
8021     @ instead, we just replicate the tail end.
8022     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8023     SET_VREG(r1, r9)                    @ vAA<- r1
8024     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8025     GOTO_OPCODE(ip)                     @ jump to next instruction
8026
8027 .LOP_CMP_LONG_greater:
8028     mov     r1, #1                      @ r1<- 1
8029     @ fall through to _finish
8030
8031 .LOP_CMP_LONG_finish:
8032     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8033     SET_VREG(r1, r9)                    @ vAA<- r1
8034     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8035     GOTO_OPCODE(ip)                     @ jump to next instruction
8036
8037
8038 /* continuation for OP_AGET_WIDE */
8039
8040 .LOP_AGET_WIDE_finish:
8041     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8042     ldrd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8043     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
8044     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8045     stmia   r9, {r2-r3}                 @ vAA/vAA+1<- r2/r3
8046     GOTO_OPCODE(ip)                     @ jump to next instruction
8047
8048
8049 /* continuation for OP_APUT_WIDE */
8050
8051 .LOP_APUT_WIDE_finish:
8052     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8053     ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
8054     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8055     strd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8056     GOTO_OPCODE(ip)                     @ jump to next instruction
8057
8058
8059 /* continuation for OP_APUT_OBJECT */
8060     /*
8061      * On entry:
8062      *  r1 = vBB (arrayObj)
8063      *  r9 = vAA (obj)
8064      *  r10 = offset into array (vBB + vCC * width)
8065      */
8066 .LOP_APUT_OBJECT_finish:
8067     cmp     r9, #0                      @ storing null reference?
8068     beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
8069     ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
8070     ldr     r1, [r1, #offObject_clazz]  @ r1<- arrayObj->clazz
8071     bl      dvmCanPutArrayElement       @ test object type vs. array type
8072     cmp     r0, #0                      @ okay?
8073     beq     common_errArrayStore        @ no
8074 .LOP_APUT_OBJECT_skip_check:
8075     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8076     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8077     str     r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
8078     GOTO_OPCODE(ip)                     @ jump to next instruction
8079
8080
8081 /* continuation for OP_IGET */
8082
8083     /*
8084      * Currently:
8085      *  r0 holds resolved field
8086      *  r9 holds object
8087      */
8088 .LOP_IGET_finish:
8089     @bl      common_squeak0
8090     cmp     r9, #0                      @ check object for null
8091     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8092     beq     common_errNullObject        @ object was null
8093     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8094     ubfx    r2, rINST, #8, #4           @ r2<- A
8095     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8096     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8097     SET_VREG(r0, r2)                    @ fp[A]<- r0
8098     GOTO_OPCODE(ip)                     @ jump to next instruction
8099
8100
8101 /* continuation for OP_IGET_WIDE */
8102
8103     /*
8104      * Currently:
8105      *  r0 holds resolved field
8106      *  r9 holds object
8107      */
8108 .LOP_IGET_WIDE_finish:
8109     cmp     r9, #0                      @ check object for null
8110     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8111     beq     common_errNullObject        @ object was null
8112     ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
8113     ubfx    r2, rINST, #8, #4           @ r2<- A
8114     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8115     add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
8116     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8117     stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
8118     GOTO_OPCODE(ip)                     @ jump to next instruction
8119
8120
8121 /* continuation for OP_IGET_OBJECT */
8122
8123     /*
8124      * Currently:
8125      *  r0 holds resolved field
8126      *  r9 holds object
8127      */
8128 .LOP_IGET_OBJECT_finish:
8129     @bl      common_squeak0
8130     cmp     r9, #0                      @ check object for null
8131     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8132     beq     common_errNullObject        @ object was null
8133     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8134     mov     r2, rINST, lsr #8           @ r2<- A+
8135     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8136     and     r2, r2, #15                 @ r2<- A
8137     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8138     SET_VREG(r0, r2)                    @ fp[A]<- r0
8139     GOTO_OPCODE(ip)                     @ jump to next instruction
8140
8141
8142 /* continuation for OP_IGET_BOOLEAN */
8143
8144     /*
8145      * Currently:
8146      *  r0 holds resolved field
8147      *  r9 holds object
8148      */
8149 .LOP_IGET_BOOLEAN_finish:
8150     @bl      common_squeak1
8151     cmp     r9, #0                      @ check object for null
8152     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8153     beq     common_errNullObject        @ object was null
8154     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8155     mov     r2, rINST, lsr #8           @ r2<- A+
8156     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8157     and     r2, r2, #15                 @ r2<- A
8158     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8159     SET_VREG(r0, r2)                    @ fp[A]<- r0
8160     GOTO_OPCODE(ip)                     @ jump to next instruction
8161
8162
8163 /* continuation for OP_IGET_BYTE */
8164
8165     /*
8166      * Currently:
8167      *  r0 holds resolved field
8168      *  r9 holds object
8169      */
8170 .LOP_IGET_BYTE_finish:
8171     @bl      common_squeak2
8172     cmp     r9, #0                      @ check object for null
8173     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8174     beq     common_errNullObject        @ object was null
8175     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8176     mov     r2, rINST, lsr #8           @ r2<- A+
8177     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8178     and     r2, r2, #15                 @ r2<- A
8179     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8180     SET_VREG(r0, r2)                    @ fp[A]<- r0
8181     GOTO_OPCODE(ip)                     @ jump to next instruction
8182
8183
8184 /* continuation for OP_IGET_CHAR */
8185
8186     /*
8187      * Currently:
8188      *  r0 holds resolved field
8189      *  r9 holds object
8190      */
8191 .LOP_IGET_CHAR_finish:
8192     @bl      common_squeak3
8193     cmp     r9, #0                      @ check object for null
8194     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8195     beq     common_errNullObject        @ object was null
8196     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8197     mov     r2, rINST, lsr #8           @ r2<- A+
8198     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8199     and     r2, r2, #15                 @ r2<- A
8200     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8201     SET_VREG(r0, r2)                    @ fp[A]<- r0
8202     GOTO_OPCODE(ip)                     @ jump to next instruction
8203
8204
8205 /* continuation for OP_IGET_SHORT */
8206
8207     /*
8208      * Currently:
8209      *  r0 holds resolved field
8210      *  r9 holds object
8211      */
8212 .LOP_IGET_SHORT_finish:
8213     @bl      common_squeak4
8214     cmp     r9, #0                      @ check object for null
8215     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8216     beq     common_errNullObject        @ object was null
8217     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8218     mov     r2, rINST, lsr #8           @ r2<- A+
8219     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8220     and     r2, r2, #15                 @ r2<- A
8221     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8222     SET_VREG(r0, r2)                    @ fp[A]<- r0
8223     GOTO_OPCODE(ip)                     @ jump to next instruction
8224
8225
8226 /* continuation for OP_IPUT */
8227
8228     /*
8229      * Currently:
8230      *  r0 holds resolved field
8231      *  r9 holds object
8232      */
8233 .LOP_IPUT_finish:
8234     @bl      common_squeak0
8235     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8236     ubfx    r1, rINST, #8, #4           @ r1<- A
8237     cmp     r9, #0                      @ check object for null
8238     GET_VREG(r0, r1)                    @ r0<- fp[A]
8239     beq     common_errNullObject        @ object was null
8240     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8241     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8242     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8243     GOTO_OPCODE(ip)                     @ jump to next instruction
8244
8245
8246 /* continuation for OP_IPUT_WIDE */
8247
8248     /*
8249      * Currently:
8250      *  r0 holds resolved field
8251      *  r9 holds object
8252      */
8253 .LOP_IPUT_WIDE_finish:
8254     ubfx    r2, rINST, #8, #4           @ r2<- A
8255     cmp     r9, #0                      @ check object for null
8256     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8257     add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
8258     beq     common_errNullObject        @ object was null
8259     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8260     ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
8261     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8262     strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0
8263     GOTO_OPCODE(ip)                     @ jump to next instruction
8264
8265
8266 /* continuation for OP_IPUT_OBJECT */
8267
8268     /*
8269      * Currently:
8270      *  r0 holds resolved field
8271      *  r9 holds object
8272      */
8273 .LOP_IPUT_OBJECT_finish:
8274     @bl      common_squeak0
8275     mov     r1, rINST, lsr #8           @ r1<- A+
8276     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8277     and     r1, r1, #15                 @ r1<- A
8278     cmp     r9, #0                      @ check object for null
8279     GET_VREG(r0, r1)                    @ r0<- fp[A]
8280     beq     common_errNullObject        @ object was null
8281     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8282     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8283     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8284     GOTO_OPCODE(ip)                     @ jump to next instruction
8285
8286
8287 /* continuation for OP_IPUT_BOOLEAN */
8288
8289     /*
8290      * Currently:
8291      *  r0 holds resolved field
8292      *  r9 holds object
8293      */
8294 .LOP_IPUT_BOOLEAN_finish:
8295     @bl      common_squeak1
8296     mov     r1, rINST, lsr #8           @ r1<- A+
8297     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8298     and     r1, r1, #15                 @ r1<- A
8299     cmp     r9, #0                      @ check object for null
8300     GET_VREG(r0, r1)                    @ r0<- fp[A]
8301     beq     common_errNullObject        @ object was null
8302     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8303     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8304     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8305     GOTO_OPCODE(ip)                     @ jump to next instruction
8306
8307
8308 /* continuation for OP_IPUT_BYTE */
8309
8310     /*
8311      * Currently:
8312      *  r0 holds resolved field
8313      *  r9 holds object
8314      */
8315 .LOP_IPUT_BYTE_finish:
8316     @bl      common_squeak2
8317     mov     r1, rINST, lsr #8           @ r1<- A+
8318     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8319     and     r1, r1, #15                 @ r1<- A
8320     cmp     r9, #0                      @ check object for null
8321     GET_VREG(r0, r1)                    @ r0<- fp[A]
8322     beq     common_errNullObject        @ object was null
8323     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8324     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8325     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8326     GOTO_OPCODE(ip)                     @ jump to next instruction
8327
8328
8329 /* continuation for OP_IPUT_CHAR */
8330
8331     /*
8332      * Currently:
8333      *  r0 holds resolved field
8334      *  r9 holds object
8335      */
8336 .LOP_IPUT_CHAR_finish:
8337     @bl      common_squeak3
8338     mov     r1, rINST, lsr #8           @ r1<- A+
8339     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8340     and     r1, r1, #15                 @ r1<- A
8341     cmp     r9, #0                      @ check object for null
8342     GET_VREG(r0, r1)                    @ r0<- fp[A]
8343     beq     common_errNullObject        @ object was null
8344     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8345     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8346     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8347     GOTO_OPCODE(ip)                     @ jump to next instruction
8348
8349
8350 /* continuation for OP_IPUT_SHORT */
8351
8352     /*
8353      * Currently:
8354      *  r0 holds resolved field
8355      *  r9 holds object
8356      */
8357 .LOP_IPUT_SHORT_finish:
8358     @bl      common_squeak4
8359     mov     r1, rINST, lsr #8           @ r1<- A+
8360     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8361     and     r1, r1, #15                 @ r1<- A
8362     cmp     r9, #0                      @ check object for null
8363     GET_VREG(r0, r1)                    @ r0<- fp[A]
8364     beq     common_errNullObject        @ object was null
8365     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8366     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8367     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8368     GOTO_OPCODE(ip)                     @ jump to next instruction
8369
8370
8371 /* continuation for OP_SGET */
8372
8373     /*
8374      * Continuation if the field has not yet been resolved.
8375      *  r1: BBBB field ref
8376      */
8377 .LOP_SGET_resolve:
8378     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8379     EXPORT_PC()                         @ resolve() could throw, so export now
8380     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8381     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8382     cmp     r0, #0                      @ success?
8383     bne     .LOP_SGET_finish          @ yes, finish
8384     b       common_exceptionThrown      @ no, handle exception
8385
8386
8387 /* continuation for OP_SGET_WIDE */
8388
8389     /*
8390      * Continuation if the field has not yet been resolved.
8391      *  r1: BBBB field ref
8392      */
8393 .LOP_SGET_WIDE_resolve:
8394     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8395     EXPORT_PC()                         @ resolve() could throw, so export now
8396     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8397     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8398     cmp     r0, #0                      @ success?
8399     bne     .LOP_SGET_WIDE_finish          @ yes, finish
8400     b       common_exceptionThrown      @ no, handle exception
8401
8402
8403 /* continuation for OP_SGET_OBJECT */
8404
8405     /*
8406      * Continuation if the field has not yet been resolved.
8407      *  r1: BBBB field ref
8408      */
8409 .LOP_SGET_OBJECT_resolve:
8410     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8411     EXPORT_PC()                         @ resolve() could throw, so export now
8412     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8413     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8414     cmp     r0, #0                      @ success?
8415     bne     .LOP_SGET_OBJECT_finish          @ yes, finish
8416     b       common_exceptionThrown      @ no, handle exception
8417
8418
8419 /* continuation for OP_SGET_BOOLEAN */
8420
8421     /*
8422      * Continuation if the field has not yet been resolved.
8423      *  r1: BBBB field ref
8424      */
8425 .LOP_SGET_BOOLEAN_resolve:
8426     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8427     EXPORT_PC()                         @ resolve() could throw, so export now
8428     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8429     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8430     cmp     r0, #0                      @ success?
8431     bne     .LOP_SGET_BOOLEAN_finish          @ yes, finish
8432     b       common_exceptionThrown      @ no, handle exception
8433
8434
8435 /* continuation for OP_SGET_BYTE */
8436
8437     /*
8438      * Continuation if the field has not yet been resolved.
8439      *  r1: BBBB field ref
8440      */
8441 .LOP_SGET_BYTE_resolve:
8442     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8443     EXPORT_PC()                         @ resolve() could throw, so export now
8444     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8445     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8446     cmp     r0, #0                      @ success?
8447     bne     .LOP_SGET_BYTE_finish          @ yes, finish
8448     b       common_exceptionThrown      @ no, handle exception
8449
8450
8451 /* continuation for OP_SGET_CHAR */
8452
8453     /*
8454      * Continuation if the field has not yet been resolved.
8455      *  r1: BBBB field ref
8456      */
8457 .LOP_SGET_CHAR_resolve:
8458     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8459     EXPORT_PC()                         @ resolve() could throw, so export now
8460     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8461     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8462     cmp     r0, #0                      @ success?
8463     bne     .LOP_SGET_CHAR_finish          @ yes, finish
8464     b       common_exceptionThrown      @ no, handle exception
8465
8466
8467 /* continuation for OP_SGET_SHORT */
8468
8469     /*
8470      * Continuation if the field has not yet been resolved.
8471      *  r1: BBBB field ref
8472      */
8473 .LOP_SGET_SHORT_resolve:
8474     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8475     EXPORT_PC()                         @ resolve() could throw, so export now
8476     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8477     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8478     cmp     r0, #0                      @ success?
8479     bne     .LOP_SGET_SHORT_finish          @ yes, finish
8480     b       common_exceptionThrown      @ no, handle exception
8481
8482
8483 /* continuation for OP_SPUT */
8484
8485     /*
8486      * Continuation if the field has not yet been resolved.
8487      *  r1: BBBB field ref
8488      */
8489 .LOP_SPUT_resolve:
8490     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8491     EXPORT_PC()                         @ resolve() could throw, so export now
8492     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8493     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8494     cmp     r0, #0                      @ success?
8495     bne     .LOP_SPUT_finish          @ yes, finish
8496     b       common_exceptionThrown      @ no, handle exception
8497
8498
8499 /* continuation for OP_SPUT_WIDE */
8500
8501     /*
8502      * Continuation if the field has not yet been resolved.
8503      *  r1: BBBB field ref
8504      *  r9: &fp[AA]
8505      */
8506 .LOP_SPUT_WIDE_resolve:
8507     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8508     EXPORT_PC()                         @ resolve() could throw, so export now
8509     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8510     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8511     cmp     r0, #0                      @ success?
8512     bne     .LOP_SPUT_WIDE_finish          @ yes, finish
8513     b       common_exceptionThrown      @ no, handle exception
8514
8515
8516 /* continuation for OP_SPUT_OBJECT */
8517
8518     /*
8519      * Continuation if the field has not yet been resolved.
8520      *  r1: BBBB field ref
8521      */
8522 .LOP_SPUT_OBJECT_resolve:
8523     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8524     EXPORT_PC()                         @ resolve() could throw, so export now
8525     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8526     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8527     cmp     r0, #0                      @ success?
8528     bne     .LOP_SPUT_OBJECT_finish          @ yes, finish
8529     b       common_exceptionThrown      @ no, handle exception
8530
8531
8532 /* continuation for OP_SPUT_BOOLEAN */
8533
8534     /*
8535      * Continuation if the field has not yet been resolved.
8536      *  r1: BBBB field ref
8537      */
8538 .LOP_SPUT_BOOLEAN_resolve:
8539     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8540     EXPORT_PC()                         @ resolve() could throw, so export now
8541     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8542     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8543     cmp     r0, #0                      @ success?
8544     bne     .LOP_SPUT_BOOLEAN_finish          @ yes, finish
8545     b       common_exceptionThrown      @ no, handle exception
8546
8547
8548 /* continuation for OP_SPUT_BYTE */
8549
8550     /*
8551      * Continuation if the field has not yet been resolved.
8552      *  r1: BBBB field ref
8553      */
8554 .LOP_SPUT_BYTE_resolve:
8555     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8556     EXPORT_PC()                         @ resolve() could throw, so export now
8557     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8558     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8559     cmp     r0, #0                      @ success?
8560     bne     .LOP_SPUT_BYTE_finish          @ yes, finish
8561     b       common_exceptionThrown      @ no, handle exception
8562
8563
8564 /* continuation for OP_SPUT_CHAR */
8565
8566     /*
8567      * Continuation if the field has not yet been resolved.
8568      *  r1: BBBB field ref
8569      */
8570 .LOP_SPUT_CHAR_resolve:
8571     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8572     EXPORT_PC()                         @ resolve() could throw, so export now
8573     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8574     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8575     cmp     r0, #0                      @ success?
8576     bne     .LOP_SPUT_CHAR_finish          @ yes, finish
8577     b       common_exceptionThrown      @ no, handle exception
8578
8579
8580 /* continuation for OP_SPUT_SHORT */
8581
8582     /*
8583      * Continuation if the field has not yet been resolved.
8584      *  r1: BBBB field ref
8585      */
8586 .LOP_SPUT_SHORT_resolve:
8587     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8588     EXPORT_PC()                         @ resolve() could throw, so export now
8589     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8590     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8591     cmp     r0, #0                      @ success?
8592     bne     .LOP_SPUT_SHORT_finish          @ yes, finish
8593     b       common_exceptionThrown      @ no, handle exception
8594
8595
8596 /* continuation for OP_INVOKE_VIRTUAL */
8597
8598     /*
8599      * At this point:
8600      *  r0 = resolved base method
8601      *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8602      */
8603 .LOP_INVOKE_VIRTUAL_continue:
8604     GET_VREG(r1, r10)                   @ r1<- "this" ptr
8605     ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8606     cmp     r1, #0                      @ is "this" null?
8607     beq     common_errNullObject        @ null "this", throw exception
8608     ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8609     ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8610     ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8611     bl      common_invokeMethodNoRange @ continue on
8612
8613
8614 /* continuation for OP_INVOKE_SUPER */
8615
8616     /*
8617      * At this point:
8618      *  r0 = resolved base method
8619      *  r9 = method->clazz
8620      */
8621 .LOP_INVOKE_SUPER_continue:
8622     ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8623     ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8624     ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8625     EXPORT_PC()                         @ must export for invoke
8626     cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8627     bcs     .LOP_INVOKE_SUPER_nsm             @ method not present in superclass
8628     ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8629     ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8630     bl      common_invokeMethodNoRange @ continue on
8631
8632 .LOP_INVOKE_SUPER_resolve:
8633     mov     r0, r9                      @ r0<- method->clazz
8634     mov     r2, #METHOD_VIRTUAL         @ resolver method type
8635     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8636     cmp     r0, #0                      @ got null?
8637     bne     .LOP_INVOKE_SUPER_continue        @ no, continue
8638     b       common_exceptionThrown      @ yes, handle exception
8639
8640     /*
8641      * Throw a NoSuchMethodError with the method name as the message.
8642      *  r0 = resolved base method
8643      */
8644 .LOP_INVOKE_SUPER_nsm:
8645     ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8646     b       common_errNoSuchMethod
8647
8648
8649 /* continuation for OP_INVOKE_DIRECT */
8650
8651     /*
8652      * On entry:
8653      *  r1 = reference (BBBB or CCCC)
8654      *  r10 = "this" register
8655      */
8656 .LOP_INVOKE_DIRECT_resolve:
8657     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8658     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8659     mov     r2, #METHOD_DIRECT          @ resolver method type
8660     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8661     cmp     r0, #0                      @ got null?
8662     GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8663     bne     .LOP_INVOKE_DIRECT_finish          @ no, continue
8664     b       common_exceptionThrown      @ yes, handle exception
8665
8666
8667 /* continuation for OP_INVOKE_VIRTUAL_RANGE */
8668
8669     /*
8670      * At this point:
8671      *  r0 = resolved base method
8672      *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8673      */
8674 .LOP_INVOKE_VIRTUAL_RANGE_continue:
8675     GET_VREG(r1, r10)                   @ r1<- "this" ptr
8676     ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8677     cmp     r1, #0                      @ is "this" null?
8678     beq     common_errNullObject        @ null "this", throw exception
8679     ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8680     ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8681     ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8682     bl      common_invokeMethodRange @ continue on
8683
8684
8685 /* continuation for OP_INVOKE_SUPER_RANGE */
8686
8687     /*
8688      * At this point:
8689      *  r0 = resolved base method
8690      *  r9 = method->clazz
8691      */
8692 .LOP_INVOKE_SUPER_RANGE_continue:
8693     ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8694     ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8695     ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8696     EXPORT_PC()                         @ must export for invoke
8697     cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8698     bcs     .LOP_INVOKE_SUPER_RANGE_nsm             @ method not present in superclass
8699     ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8700     ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8701     bl      common_invokeMethodRange @ continue on
8702
8703 .LOP_INVOKE_SUPER_RANGE_resolve:
8704     mov     r0, r9                      @ r0<- method->clazz
8705     mov     r2, #METHOD_VIRTUAL         @ resolver method type
8706     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8707     cmp     r0, #0                      @ got null?
8708     bne     .LOP_INVOKE_SUPER_RANGE_continue        @ no, continue
8709     b       common_exceptionThrown      @ yes, handle exception
8710
8711     /*
8712      * Throw a NoSuchMethodError with the method name as the message.
8713      *  r0 = resolved base method
8714      */
8715 .LOP_INVOKE_SUPER_RANGE_nsm:
8716     ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8717     b       common_errNoSuchMethod
8718
8719
8720 /* continuation for OP_INVOKE_DIRECT_RANGE */
8721
8722     /*
8723      * On entry:
8724      *  r1 = reference (BBBB or CCCC)
8725      *  r10 = "this" register
8726      */
8727 .LOP_INVOKE_DIRECT_RANGE_resolve:
8728     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8729     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8730     mov     r2, #METHOD_DIRECT          @ resolver method type
8731     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8732     cmp     r0, #0                      @ got null?
8733     GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8734     bne     .LOP_INVOKE_DIRECT_RANGE_finish          @ no, continue
8735     b       common_exceptionThrown      @ yes, handle exception
8736
8737
8738 /* continuation for OP_FLOAT_TO_LONG */
8739 /*
8740  * Convert the float in r0 to a long in r0/r1.
8741  *
8742  * We have to clip values to long min/max per the specification.  The
8743  * expected common case is a "reasonable" value that converts directly
8744  * to modest integer.  The EABI convert function isn't doing this for us.
8745  */
8746 f2l_doconv:
8747     stmfd   sp!, {r4, lr}
8748     mov     r1, #0x5f000000             @ (float)maxlong
8749     mov     r4, r0
8750     bl      __aeabi_fcmpge              @ is arg >= maxlong?
8751     cmp     r0, #0                      @ nonzero == yes
8752     mvnne   r0, #0                      @ return maxlong (7fffffff)
8753     mvnne   r1, #0x80000000
8754     ldmnefd sp!, {r4, pc}
8755
8756     mov     r0, r4                      @ recover arg
8757     mov     r1, #0xdf000000             @ (float)minlong
8758     bl      __aeabi_fcmple              @ is arg <= minlong?
8759     cmp     r0, #0                      @ nonzero == yes
8760     movne   r0, #0                      @ return minlong (80000000)
8761     movne   r1, #0x80000000
8762     ldmnefd sp!, {r4, pc}
8763
8764     mov     r0, r4                      @ recover arg
8765     mov     r1, r4
8766     bl      __aeabi_fcmpeq              @ is arg == self?
8767     cmp     r0, #0                      @ zero == no
8768     moveq   r1, #0                      @ return zero for NaN
8769     ldmeqfd sp!, {r4, pc}
8770
8771     mov     r0, r4                      @ recover arg
8772     bl      __aeabi_f2lz                @ convert float to long
8773     ldmfd   sp!, {r4, pc}
8774
8775
8776 /* continuation for OP_DOUBLE_TO_LONG */
8777 /*
8778  * Convert the double in r0/r1 to a long in r0/r1.
8779  *
8780  * We have to clip values to long min/max per the specification.  The
8781  * expected common case is a "reasonable" value that converts directly
8782  * to modest integer.  The EABI convert function isn't doing this for us.
8783  */
8784 d2l_doconv:
8785     stmfd   sp!, {r4, r5, lr}           @ save regs
8786     mov     r3, #0x43000000             @ maxlong, as a double (high word)
8787     add     r3, #0x00e00000             @  0x43e00000
8788     mov     r2, #0                      @ maxlong, as a double (low word)
8789     sub     sp, sp, #4                  @ align for EABI
8790     mov     r4, r0                      @ save a copy of r0
8791     mov     r5, r1                      @  and r1
8792     bl      __aeabi_dcmpge              @ is arg >= maxlong?
8793     cmp     r0, #0                      @ nonzero == yes
8794     mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
8795     mvnne   r1, #0x80000000
8796     bne     1f
8797
8798     mov     r0, r4                      @ recover arg
8799     mov     r1, r5
8800     mov     r3, #0xc3000000             @ minlong, as a double (high word)
8801     add     r3, #0x00e00000             @  0xc3e00000
8802     mov     r2, #0                      @ minlong, as a double (low word)
8803     bl      __aeabi_dcmple              @ is arg <= minlong?
8804     cmp     r0, #0                      @ nonzero == yes
8805     movne   r0, #0                      @ return minlong (8000000000000000)
8806     movne   r1, #0x80000000
8807     bne     1f
8808
8809     mov     r0, r4                      @ recover arg
8810     mov     r1, r5
8811     mov     r2, r4                      @ compare against self
8812     mov     r3, r5
8813     bl      __aeabi_dcmpeq              @ is arg == self?
8814     cmp     r0, #0                      @ zero == no
8815     moveq   r1, #0                      @ return zero for NaN
8816     beq     1f
8817
8818     mov     r0, r4                      @ recover arg
8819     mov     r1, r5
8820     bl      __aeabi_d2lz                @ convert double to long
8821
8822 1:
8823     add     sp, sp, #4
8824     ldmfd   sp!, {r4, r5, pc}
8825
8826
8827 /* continuation for OP_MUL_LONG */
8828
8829 .LOP_MUL_LONG_finish:
8830     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8831     stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
8832     GOTO_OPCODE(ip)                     @ jump to next instruction
8833
8834
8835 /* continuation for OP_SHL_LONG */
8836
8837 .LOP_SHL_LONG_finish:
8838     mov     r0, r0, asl r2              @  r0<- r0 << r2
8839     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8840     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8841     GOTO_OPCODE(ip)                     @ jump to next instruction
8842
8843
8844 /* continuation for OP_SHR_LONG */
8845
8846 .LOP_SHR_LONG_finish:
8847     mov     r1, r1, asr r2              @  r1<- r1 >> r2
8848     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8849     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8850     GOTO_OPCODE(ip)                     @ jump to next instruction
8851
8852
8853 /* continuation for OP_USHR_LONG */
8854
8855 .LOP_USHR_LONG_finish:
8856     mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
8857     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8858     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8859     GOTO_OPCODE(ip)                     @ jump to next instruction
8860
8861
8862 /* continuation for OP_SHL_LONG_2ADDR */
8863
8864 .LOP_SHL_LONG_2ADDR_finish:
8865     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8866     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8867     GOTO_OPCODE(ip)                     @ jump to next instruction
8868
8869
8870 /* continuation for OP_SHR_LONG_2ADDR */
8871
8872 .LOP_SHR_LONG_2ADDR_finish:
8873     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8874     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8875     GOTO_OPCODE(ip)                     @ jump to next instruction
8876
8877
8878 /* continuation for OP_USHR_LONG_2ADDR */
8879
8880 .LOP_USHR_LONG_2ADDR_finish:
8881     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8882     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8883     GOTO_OPCODE(ip)                     @ jump to next instruction
8884
8885
8886 /* continuation for OP_EXECUTE_INLINE */
8887
8888     /*
8889      * Extract args, call function.
8890      *  r0 = #of args (0-4)
8891      *  r10 = call index
8892      *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
8893      *
8894      * Other ideas:
8895      * - Use a jump table from the main piece to jump directly into the
8896      *   AND/LDR pairs.  Costs a data load, saves a branch.
8897      * - Have five separate pieces that do the loading, so we can work the
8898      *   interleave a little better.  Increases code size.
8899      */
8900 .LOP_EXECUTE_INLINE_continue:
8901     rsb     r0, r0, #4                  @ r0<- 4-r0
8902     FETCH(r9, 2)                        @ r9<- FEDC
8903     add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
8904     bl      common_abort                @ (skipped due to ARM prefetch)
8905 4:  and     ip, r9, #0xf000             @ isolate F
8906     ldr     r3, [rFP, ip, lsr #10]      @ r3<- vF (shift right 12, left 2)
8907 3:  and     ip, r9, #0x0f00             @ isolate E
8908     ldr     r2, [rFP, ip, lsr #6]       @ r2<- vE
8909 2:  and     ip, r9, #0x00f0             @ isolate D
8910     ldr     r1, [rFP, ip, lsr #2]       @ r1<- vD
8911 1:  and     ip, r9, #0x000f             @ isolate C
8912     ldr     r0, [rFP, ip, lsl #2]       @ r0<- vC
8913 0:
8914     ldr     r9, .LOP_EXECUTE_INLINE_table       @ table of InlineOperation
8915     LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
8916     @ (not reached)
8917
8918 .LOP_EXECUTE_INLINE_table:
8919     .word   gDvmInlineOpsTable
8920
8921
8922     .size   dvmAsmSisterStart, .-dvmAsmSisterStart
8923     .global dvmAsmSisterEnd
8924 dvmAsmSisterEnd:
8925
8926 /* File: armv5te/footer.S */
8927
8928 /*
8929  * ===========================================================================
8930  *  Common subroutines and data
8931  * ===========================================================================
8932  */
8933
8934
8935
8936     .text
8937     .align  2
8938
8939 #if defined(WITH_JIT)
8940 #if defined(WITH_SELF_VERIFICATION)
8941     .global dvmJitToInterpPunt
8942 dvmJitToInterpPunt:
8943     mov    r2,#kSVSPunt                 @ r2<- interpreter entry point
8944     b      dvmJitSelfVerificationEnd    @ doesn't return
8945
8946     .global dvmJitToInterpSingleStep
8947 dvmJitToInterpSingleStep:
8948     mov    r2,#kSVSSingleStep           @ r2<- interpreter entry point
8949     b      dvmJitSelfVerificationEnd    @ doesn't return
8950
8951     .global dvmJitToTraceSelect
8952 dvmJitToTraceSelect:
8953     ldr    r0,[r14, #-1]                @ pass our target PC
8954     mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
8955     b      dvmJitSelfVerificationEnd    @ doesn't return
8956
8957     .global dvmJitToBackwardBranch
8958 dvmJitToBackwardBranch:
8959     ldr    r0,[r14, #-1]                @ pass our target PC
8960     mov    r2,#kSVSBackwardBranch       @ r2<- interpreter entry point
8961     b      dvmJitSelfVerificationEnd    @ doesn't return
8962
8963     .global dvmJitToInterpNormal
8964 dvmJitToInterpNormal:
8965     ldr    r0,[r14, #-1]                @ pass our target PC
8966     mov    r2,#kSVSNormal               @ r2<- interpreter entry point
8967     b      dvmJitSelfVerificationEnd    @ doesn't return
8968
8969     .global dvmJitToInterpNoChain
8970 dvmJitToInterpNoChain:
8971     mov    r0,rPC                       @ pass our target PC
8972     mov    r2,#kSVSNoChain              @ r2<- interpreter entry point
8973     b      dvmJitSelfVerificationEnd    @ doesn't return
8974 #else
8975 /*
8976  * Return from the translation cache to the interpreter when the compiler is
8977  * having issues translating/executing a Dalvik instruction. We have to skip
8978  * the code cache lookup otherwise it is possible to indefinitely bouce
8979  * between the interpreter and the code cache if the instruction that fails
8980  * to be compiled happens to be at a trace start.
8981  */
8982     .global dvmJitToInterpPunt
8983 dvmJitToInterpPunt:
8984     mov    rPC, r0
8985 #ifdef EXIT_STATS
8986     mov    r0,lr
8987     bl     dvmBumpPunt;
8988 #endif
8989     EXPORT_PC()
8990     adrl   rIBASE, dvmAsmInstructionStart
8991     FETCH_INST()
8992     GET_INST_OPCODE(ip)
8993     GOTO_OPCODE(ip)
8994
8995 /*
8996  * Return to the interpreter to handle a single instruction.
8997  * On entry:
8998  *    r0 <= PC
8999  *    r1 <= PC of resume instruction
9000  *    lr <= resume point in translation
9001  */
9002     .global dvmJitToInterpSingleStep
9003 dvmJitToInterpSingleStep:
9004     str    lr,[rGLUE,#offGlue_jitResume]
9005     str    r1,[rGLUE,#offGlue_jitResumePC]
9006     mov    r1,#kInterpEntryInstr
9007     @ enum is 4 byte in aapcs-EABI
9008     str    r1, [rGLUE, #offGlue_entryPoint]
9009     mov    rPC,r0
9010     EXPORT_PC()
9011     adrl   rIBASE, dvmAsmInstructionStart
9012     mov    r2,#kJitSingleStep     @ Ask for single step and then revert
9013     str    r2,[rGLUE,#offGlue_jitState]
9014     mov    r1,#1                  @ set changeInterp to bail to debug interp
9015     b      common_gotoBail
9016
9017
9018 /*
9019  * Return from the translation cache and immediately request
9020  * a translation for the exit target.  Commonly used following
9021  * invokes.
9022  */
9023     .global dvmJitToTraceSelect
9024 dvmJitToTraceSelect:
9025     ldr    rPC,[r14, #-1]           @ get our target PC
9026     add    rINST,r14,#-5            @ save start of chain branch
9027     mov    r0,rPC
9028     bl     dvmJitGetCodeAddr        @ Is there a translation?
9029     cmp    r0,#0
9030     beq    2f
9031     mov    r1,rINST
9032     bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9033     cmp    r0,#0                    @ successful chain?
9034     bxne   r0                       @ continue native execution
9035     b      toInterpreter            @ didn't chain - resume with interpreter
9036
9037 /* No translation, so request one if profiling isn't disabled*/
9038 2:
9039     adrl   rIBASE, dvmAsmInstructionStart
9040     GET_JIT_PROF_TABLE(r0)
9041     FETCH_INST()
9042     cmp    r0, #0
9043     bne    common_selectTrace
9044     GET_INST_OPCODE(ip)
9045     GOTO_OPCODE(ip)
9046
9047 /*
9048  * Return from the translation cache to the interpreter.
9049  * The return was done with a BLX from thumb mode, and
9050  * the following 32-bit word contains the target rPC value.
9051  * Note that lr (r14) will have its low-order bit set to denote
9052  * its thumb-mode origin.
9053  *
9054  * We'll need to stash our lr origin away, recover the new
9055  * target and then check to see if there is a translation available
9056  * for our new target.  If so, we do a translation chain and
9057  * go back to native execution.  Otherwise, it's back to the
9058  * interpreter (after treating this entry as a potential
9059  * trace start).
9060  */
9061     .global dvmJitToInterpNormal
9062 dvmJitToInterpNormal:
9063     ldr    rPC,[r14, #-1]           @ get our target PC
9064     add    rINST,r14,#-5            @ save start of chain branch
9065 #ifdef EXIT_STATS
9066     bl     dvmBumpNormal
9067 #endif
9068     mov    r0,rPC
9069     bl     dvmJitGetCodeAddr        @ Is there a translation?
9070     cmp    r0,#0
9071     beq    toInterpreter            @ go if not, otherwise do chain
9072     mov    r1,rINST
9073     bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9074     cmp    r0,#0                    @ successful chain?
9075     bxne   r0                       @ continue native execution
9076     b      toInterpreter            @ didn't chain - resume with interpreter
9077
9078 /*
9079  * Return from the translation cache to the interpreter to do method invocation.
9080  * Check if translation exists for the callee, but don't chain to it.
9081  */
9082     .global dvmJitToInterpNoChain
9083 dvmJitToInterpNoChain:
9084 #ifdef EXIT_STATS
9085     bl     dvmBumpNoChain
9086 #endif
9087     mov    r0,rPC
9088     bl     dvmJitGetCodeAddr        @ Is there a translation?
9089     cmp    r0,#0
9090     bxne   r0                       @ continue native execution if so
9091 #endif
9092
9093 /*
9094  * No translation, restore interpreter regs and start interpreting.
9095  * rGLUE & rFP were preserved in the translated code, and rPC has
9096  * already been restored by the time we get here.  We'll need to set
9097  * up rIBASE & rINST, and load the address of the JitTable into r0.
9098  */
9099 toInterpreter:
9100     EXPORT_PC()
9101     adrl   rIBASE, dvmAsmInstructionStart
9102     FETCH_INST()
9103     GET_JIT_PROF_TABLE(r0)
9104     @ NOTE: intended fallthrough
9105 /*
9106  * Common code to update potential trace start counter, and initiate
9107  * a trace-build if appropriate.  On entry, rPC should point to the
9108  * next instruction to execute, and rINST should be already loaded with
9109  * the next opcode word, and r0 holds a pointer to the jit profile
9110  * table (pJitProfTable).
9111  */
9112 common_testUpdateProfile:
9113     cmp     r0,#0
9114     GET_INST_OPCODE(ip)
9115     GOTO_OPCODE_IFEQ(ip)       @ if not profiling, fallthrough otherwise */
9116
9117 common_updateProfile:
9118     eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
9119     lsl     r3,r3,#23          @ shift out excess 511
9120     ldrb    r1,[r0,r3,lsr #23] @ get counter
9121     GET_INST_OPCODE(ip)
9122     subs    r1,r1,#1           @ decrement counter
9123     strb    r1,[r0,r3,lsr #23] @ and store it
9124     GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
9125
9126 /*
9127  * Here, we switch to the debug interpreter to request
9128  * trace selection.  First, though, check to see if there
9129  * is already a native translation in place (and, if so,
9130  * jump to it now).
9131  */
9132     mov     r1,#255
9133     strb    r1,[r0,r3,lsr #23] @ reset counter
9134     EXPORT_PC()
9135     mov     r0,rPC
9136     bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
9137     cmp     r0,#0
9138     beq     common_selectTrace
9139 #if !defined(WITH_SELF_VERIFICATION)
9140     bxne    r0                          @ jump to the translation
9141 #else
9142     bne     dvmJitSelfVerificationStart @ set up self verification
9143 #endif
9144 common_selectTrace:
9145     mov     r2,#kJitTSelectRequest      @ ask for trace selection
9146     str     r2,[rGLUE,#offGlue_jitState]
9147     mov     r2,#kInterpEntryInstr       @ normal entry reason
9148     str     r2,[rGLUE,#offGlue_entryPoint]
9149     mov     r1,#1                       @ set changeInterp
9150     b       common_gotoBail
9151
9152 #if defined(WITH_SELF_VERIFICATION)
9153 /*
9154  * Save PC and registers to shadow memory for self verification mode
9155  * before jumping to native translation.
9156  */
9157 dvmJitSelfVerificationStart:
9158     sub     sp,sp,#4                    @ allocate stack space
9159     str     r0,[sp,#0]                  @ save out dvmJitGetCodeAddr(rPC)
9160     mov     r0,rPC                      @ r0<- program counter
9161     mov     r1,rFP                      @ r1<- frame pointer
9162     mov     r2,rGLUE                    @ r2<- InterpState pointer
9163     bl      dvmSelfVerificationSaveState @ save registers to shadow space
9164     ldr     rFP,[r0,#20]                @ rFP<- fp in shadow space
9165     add     rGLUE,r0,#24                @ rGLUE<- pointer in shadow space
9166     ldr     r0,[sp,#0]                  @ r0<- dvmJitGetCodeAddr(rPC)
9167     add     sp,sp,#4                    @ restore stack
9168     bx      r0                          @ jump to the translation
9169
9170 /*
9171  * Restore PC, registers, and interpState to original values
9172  * before jumping back to the interpreter.
9173  */
9174 dvmJitSelfVerificationEnd:
9175     mov    r1,rFP                        @ pass ending fp
9176     bl     dvmSelfVerificationRestoreState @ restore pc and fp values
9177     ldr    rPC,[r0,#0]                   @ restore PC
9178     ldr    rFP,[r0,#4]                   @ restore FP
9179     ldr    rGLUE,[r0,#8]                 @ restore InterpState
9180     ldr    r1,[r0,#12]                   @ get exitPoint
9181     cmp    r1,#0                         @ check for punt condition
9182     beq    1f
9183     mov    r2,#kJitSelfVerification      @ ask for self verification
9184     str    r2,[rGLUE,#offGlue_jitState]
9185     mov    r2,#kInterpEntryInstr         @ normal entry reason
9186     str    r2,[rGLUE,#offGlue_entryPoint]
9187     mov    r1,#1                         @ set changeInterp
9188     b      common_gotoBail
9189
9190 1:                                       @ exit to interpreter without check
9191     EXPORT_PC()
9192     adrl   rIBASE, dvmAsmInstructionStart
9193     FETCH_INST()
9194     GET_INST_OPCODE(ip)
9195     GOTO_OPCODE(ip)
9196 #endif
9197
9198 #endif
9199
9200 /*
9201  * Common code when a backward branch is taken.
9202  *
9203  * On entry:
9204  *  r9 is PC adjustment *in bytes*
9205  */
9206 common_backwardBranch:
9207     mov     r0, #kInterpEntryInstr
9208     bl      common_periodicChecks
9209 #if defined(WITH_JIT)
9210     GET_JIT_PROF_TABLE(r0)
9211     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9212     cmp     r0,#0
9213     bne     common_updateProfile
9214     GET_INST_OPCODE(ip)
9215     GOTO_OPCODE(ip)
9216 #else
9217     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9218     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9219     GOTO_OPCODE(ip)                     @ jump to next instruction
9220 #endif
9221
9222
9223 /*
9224  * Need to see if the thread needs to be suspended or debugger/profiler
9225  * activity has begun.
9226  *
9227  * TODO: if JDWP isn't running, zero out pDebuggerActive pointer so we don't
9228  * have to do the second ldr.
9229  *
9230  * TODO: reduce this so we're just checking a single location.
9231  *
9232  * On entry:
9233  *  r0 is reentry type, e.g. kInterpEntryInstr
9234  *  r9 is trampoline PC adjustment *in bytes*
9235  */
9236 common_periodicChecks:
9237     ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
9238
9239     @ speculatively store r0 before it is clobbered by dvmCheckSuspendPending
9240     str     r0, [rGLUE, #offGlue_entryPoint]
9241
9242 #if defined(WITH_DEBUGGER)
9243     ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9244 #endif
9245 #if defined(WITH_PROFILER)
9246     ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9247 #endif
9248
9249     ldr     r3, [r3]                    @ r3<- suspendCount (int)
9250
9251 #if defined(WITH_DEBUGGER)
9252     ldrb    r1, [r1]                    @ r1<- debuggerActive (boolean)
9253 #endif
9254 #if defined (WITH_PROFILER)
9255     ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9256 #endif
9257
9258     cmp     r3, #0                      @ suspend pending?
9259     bne     2f                          @ yes, do full suspension check
9260
9261 #if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
9262 # if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
9263     orrs    r1, r1, r2                  @ r1<- r1 | r2
9264     cmp     r1, #0                      @ debugger attached or profiler started?
9265 # elif defined(WITH_DEBUGGER)
9266     cmp     r1, #0                      @ debugger attached?
9267 # elif defined(WITH_PROFILER)
9268     cmp     r2, #0                      @ profiler started?
9269 # endif
9270     bne     3f                          @ debugger/profiler, switch interp
9271 #endif
9272
9273     bx      lr                          @ nothing to do, return
9274
9275 2:  @ check suspend
9276     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9277     EXPORT_PC()                         @ need for precise GC
9278     b       dvmCheckSuspendPending      @ suspend if necessary, then return
9279
9280 3:  @ debugger/profiler enabled, bail out
9281     add     rPC, rPC, r9                @ update rPC
9282     mov     r1, #1                      @ "want switch" = true
9283     b       common_gotoBail
9284
9285
9286 /*
9287  * The equivalent of "goto bail", this calls through the "bail handler".
9288  *
9289  * State registers will be saved to the "glue" area before bailing.
9290  *
9291  * On entry:
9292  *  r1 is "bool changeInterp", indicating if we want to switch to the
9293  *     other interpreter or just bail all the way out
9294  */
9295 common_gotoBail:
9296     SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9297     mov     r0, rGLUE                   @ r0<- glue ptr
9298     b       dvmMterpStdBail             @ call(glue, changeInterp)
9299
9300     @add     r1, r1, #1                  @ using (boolean+1)
9301     @add     r0, rGLUE, #offGlue_jmpBuf  @ r0<- &glue->jmpBuf
9302     @bl      _longjmp                    @ does not return
9303     @bl      common_abort
9304
9305
9306 /*
9307  * Common code for method invocation with range.
9308  *
9309  * On entry:
9310  *  r0 is "Method* methodToCall", the method we're trying to call
9311  */
9312 common_invokeMethodRange:
9313 .LinvokeNewRange:
9314     @ prepare to copy args to "outs" area of current frame
9315     movs    r2, rINST, lsr #8           @ r2<- AA (arg count) -- test for zero
9316     SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9317     beq     .LinvokeArgsDone            @ if no args, skip the rest
9318     FETCH(r1, 2)                        @ r1<- CCCC
9319
9320     @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
9321     @ (very few methods have > 10 args; could unroll for common cases)
9322     add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
9323     sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
9324     ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
9325 1:  ldr     r1, [r3], #4                @ val = *fp++
9326     subs    r2, r2, #1                  @ count--
9327     str     r1, [r10], #4               @ *outs++ = val
9328     bne     1b                          @ ...while count != 0
9329     ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
9330     b       .LinvokeArgsDone
9331
9332 /*
9333  * Common code for method invocation without range.
9334  *
9335  * On entry:
9336  *  r0 is "Method* methodToCall", the method we're trying to call
9337  */
9338 common_invokeMethodNoRange:
9339 .LinvokeNewNoRange:
9340     @ prepare to copy args to "outs" area of current frame
9341     movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
9342     SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9343     FETCH(r1, 2)                        @ r1<- GFED (load here to hide latency)
9344     ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
9345     ldrh    r3, [r0, #offMethod_outsSize]  @ r3<- methodToCall->outsSize
9346     beq     .LinvokeArgsDone
9347
9348     @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
9349 .LinvokeNonRange:
9350     rsb     r2, r2, #5                  @ r2<- 5-r2
9351     add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
9352     bl      common_abort                @ (skipped due to ARM prefetch)
9353 5:  and     ip, rINST, #0x0f00          @ isolate A
9354     ldr     r2, [rFP, ip, lsr #6]       @ r2<- vA (shift right 8, left 2)
9355     mov     r0, r0                      @ nop
9356     str     r2, [r10, #-4]!             @ *--outs = vA
9357 4:  and     ip, r1, #0xf000             @ isolate G
9358     ldr     r2, [rFP, ip, lsr #10]      @ r2<- vG (shift right 12, left 2)
9359     mov     r0, r0                      @ nop
9360     str     r2, [r10, #-4]!             @ *--outs = vG
9361 3:  and     ip, r1, #0x0f00             @ isolate F
9362     ldr     r2, [rFP, ip, lsr #6]       @ r2<- vF
9363     mov     r0, r0                      @ nop
9364     str     r2, [r10, #-4]!             @ *--outs = vF
9365 2:  and     ip, r1, #0x00f0             @ isolate E
9366     ldr     r2, [rFP, ip, lsr #2]       @ r2<- vE
9367     mov     r0, r0                      @ nop
9368     str     r2, [r10, #-4]!             @ *--outs = vE
9369 1:  and     ip, r1, #0x000f             @ isolate D
9370     ldr     r2, [rFP, ip, lsl #2]       @ r2<- vD
9371     mov     r0, r0                      @ nop
9372     str     r2, [r10, #-4]!             @ *--outs = vD
9373 0:  @ fall through to .LinvokeArgsDone
9374
9375 .LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
9376     ldr     r2, [r0, #offMethod_insns]  @ r2<- method->insns
9377     ldr     rINST, [r0, #offMethod_clazz]  @ rINST<- method->clazz
9378     @ find space for the new stack frame, check for overflow
9379     SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
9380     sub     r1, r1, r9, lsl #2          @ r1<- newFp (old savearea - regsSize)
9381     SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
9382 @    bl      common_dumpRegs
9383     ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
9384     sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
9385     cmp     r3, r9                      @ bottom < interpStackEnd?
9386     ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
9387     blt     .LstackOverflow             @ yes, this frame will overflow stack
9388
9389     @ set up newSaveArea
9390 #ifdef EASY_GDB
9391     SAVEAREA_FROM_FP(ip, rFP)           @ ip<- stack save area
9392     str     ip, [r10, #offStackSaveArea_prevSave]
9393 #endif
9394     str     rFP, [r10, #offStackSaveArea_prevFrame]
9395     str     rPC, [r10, #offStackSaveArea_savedPc]
9396 #if defined(WITH_JIT)
9397     mov     r9, #0
9398     str     r9, [r10, #offStackSaveArea_returnAddr]
9399 #endif
9400     str     r0, [r10, #offStackSaveArea_method]
9401     tst     r3, #ACC_NATIVE
9402     bne     .LinvokeNative
9403
9404     /*
9405     stmfd   sp!, {r0-r3}
9406     bl      common_printNewline
9407     mov     r0, rFP
9408     mov     r1, #0
9409     bl      dvmDumpFp
9410     ldmfd   sp!, {r0-r3}
9411     stmfd   sp!, {r0-r3}
9412     mov     r0, r1
9413     mov     r1, r10
9414     bl      dvmDumpFp
9415     bl      common_printNewline
9416     ldmfd   sp!, {r0-r3}
9417     */
9418
9419     ldrh    r9, [r2]                        @ r9 <- load INST from new PC
9420     ldr     r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
9421     mov     rPC, r2                         @ publish new rPC
9422     ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
9423
9424     @ Update "glue" values for the new method
9425     @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
9426     str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
9427     str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
9428 #if defined(WITH_JIT)
9429     GET_JIT_PROF_TABLE(r0)
9430     mov     rFP, r1                         @ fp = newFp
9431     GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
9432     mov     rINST, r9                       @ publish new rINST
9433     str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
9434     cmp     r0,#0
9435     bne     common_updateProfile
9436     GOTO_OPCODE(ip)                         @ jump to next instruction
9437 #else
9438     mov     rFP, r1                         @ fp = newFp
9439     GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
9440     mov     rINST, r9                       @ publish new rINST
9441     str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
9442     GOTO_OPCODE(ip)                         @ jump to next instruction
9443 #endif
9444
9445 .LinvokeNative:
9446     @ Prep for the native call
9447     @ r0=methodToCall, r1=newFp, r10=newSaveArea
9448     ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
9449     ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
9450     str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
9451     str     r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
9452     mov     r9, r3                      @ r9<- glue->self (preserve)
9453
9454     mov     r2, r0                      @ r2<- methodToCall
9455     mov     r0, r1                      @ r0<- newFp (points to args)
9456     add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
9457
9458 #ifdef ASSIST_DEBUGGER
9459     /* insert fake function header to help gdb find the stack frame */
9460     b       .Lskip
9461     .type   dalvik_mterp, %function
9462 dalvik_mterp:
9463     .fnstart
9464     MTERP_ENTRY1
9465     MTERP_ENTRY2
9466 .Lskip:
9467 #endif
9468
9469     @mov     lr, pc                      @ set return addr
9470     @ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
9471     LDR_PC_LR "[r2, #offMethod_nativeFunc]"
9472
9473     @ native return; r9=self, r10=newSaveArea
9474     @ equivalent to dvmPopJniLocals
9475     ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
9476     ldr     r1, [r9, #offThread_exception] @ check for exception
9477     str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
9478     cmp     r1, #0                      @ null?
9479     str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
9480     bne     common_exceptionThrown      @ no, handle exception
9481
9482     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
9483     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9484     GOTO_OPCODE(ip)                     @ jump to next instruction
9485
9486 .LstackOverflow:    @ r0=methodToCall
9487     mov     r1, r0                      @ r1<- methodToCall
9488     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
9489     bl      dvmHandleStackOverflow
9490     b       common_exceptionThrown
9491 #ifdef ASSIST_DEBUGGER
9492     .fnend
9493 #endif
9494
9495
9496     /*
9497      * Common code for method invocation, calling through "glue code".
9498      *
9499      * TODO: now that we have range and non-range invoke handlers, this
9500      *       needs to be split into two.  Maybe just create entry points
9501      *       that set r9 and jump here?
9502      *
9503      * On entry:
9504      *  r0 is "Method* methodToCall", the method we're trying to call
9505      *  r9 is "bool methodCallRange", indicating if this is a /range variant
9506      */
9507      .if    0
9508 .LinvokeOld:
9509     sub     sp, sp, #8                  @ space for args + pad
9510     FETCH(ip, 2)                        @ ip<- FEDC or CCCC
9511     mov     r2, r0                      @ A2<- methodToCall
9512     mov     r0, rGLUE                   @ A0<- glue
9513     SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9514     mov     r1, r9                      @ A1<- methodCallRange
9515     mov     r3, rINST, lsr #8           @ A3<- AA
9516     str     ip, [sp, #0]                @ A4<- ip
9517     bl      dvmMterp_invokeMethod       @ call the C invokeMethod
9518     add     sp, sp, #8                  @ remove arg area
9519     b       common_resumeAfterGlueCall  @ continue to next instruction
9520     .endif
9521
9522
9523
9524 /*
9525  * Common code for handling a return instruction.
9526  *
9527  * This does not return.
9528  */
9529 common_returnFromMethod:
9530 .LreturnNew:
9531     mov     r0, #kInterpEntryReturn
9532     mov     r9, #0
9533     bl      common_periodicChecks
9534
9535     SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
9536     ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
9537     ldr     r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
9538     ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
9539                                         @ r2<- method we're returning to
9540     ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
9541     cmp     r2, #0                      @ is this a break frame?
9542     ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
9543     mov     r1, #0                      @ "want switch" = false
9544     beq     common_gotoBail             @ break frame, bail out completely
9545
9546     PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
9547     str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
9548     ldr     r1, [r10, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
9549     str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
9550 #if defined(WITH_JIT)
9551     ldr     r3, [r0, #offStackSaveArea_returnAddr] @ r3 = saveArea->returnAddr
9552     GET_JIT_PROF_TABLE(r0)
9553     mov     rPC, r9                     @ publish new rPC
9554     str     r1, [rGLUE, #offGlue_methodClassDex]
9555     cmp     r3, #0                      @ caller is compiled code
9556     blxne   r3
9557     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9558     cmp     r0,#0
9559     bne     common_updateProfile
9560     GOTO_OPCODE(ip)                     @ jump to next instruction
9561 #else
9562     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9563     mov     rPC, r9                     @ publish new rPC
9564     str     r1, [rGLUE, #offGlue_methodClassDex]
9565     GOTO_OPCODE(ip)                     @ jump to next instruction
9566 #endif
9567
9568     /*
9569      * Return handling, calls through "glue code".
9570      */
9571      .if    0
9572 .LreturnOld:
9573     SAVE_PC_FP_TO_GLUE()                @ export state
9574     mov     r0, rGLUE                   @ arg to function
9575     bl      dvmMterp_returnFromMethod
9576     b       common_resumeAfterGlueCall
9577     .endif
9578
9579
9580 /*
9581  * Somebody has thrown an exception.  Handle it.
9582  *
9583  * If the exception processing code returns to us (instead of falling
9584  * out of the interpreter), continue with whatever the next instruction
9585  * now happens to be.
9586  *
9587  * This does not return.
9588  */
9589      .global dvmMterpCommonExceptionThrown
9590 dvmMterpCommonExceptionThrown:
9591 common_exceptionThrown:
9592 .LexceptionNew:
9593     mov     r0, #kInterpEntryThrow
9594     mov     r9, #0
9595     bl      common_periodicChecks
9596
9597 #if defined(WITH_JIT)
9598     mov     r2,#kJitTSelectAbort        @ abandon trace selection in progress
9599     str     r2,[rGLUE,#offGlue_jitState]
9600 #endif
9601
9602     ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
9603     ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
9604     mov     r1, r10                     @ r1<- self
9605     mov     r0, r9                      @ r0<- exception
9606     bl      dvmAddTrackedAlloc          @ don't let the exception be GCed
9607     mov     r3, #0                      @ r3<- NULL
9608     str     r3, [r10, #offThread_exception] @ self->exception = NULL
9609
9610     /* set up args and a local for "&fp" */
9611     /* (str sp, [sp, #-4]!  would be perfect here, but is discouraged) */
9612     str     rFP, [sp, #-4]!             @ *--sp = fp
9613     mov     ip, sp                      @ ip<- &fp
9614     mov     r3, #0                      @ r3<- false
9615     str     ip, [sp, #-4]!              @ *--sp = &fp
9616     ldr     r1, [rGLUE, #offGlue_method] @ r1<- glue->method
9617     mov     r0, r10                     @ r0<- self
9618     ldr     r1, [r1, #offMethod_insns]  @ r1<- method->insns
9619     mov     r2, r9                      @ r2<- exception
9620     sub     r1, rPC, r1                 @ r1<- pc - method->insns
9621     mov     r1, r1, asr #1              @ r1<- offset in code units
9622
9623     /* call, r0 gets catchRelPc (a code-unit offset) */
9624     bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
9625
9626     /* fix earlier stack overflow if necessary; may trash rFP */
9627     ldrb    r1, [r10, #offThread_stackOverflowed]
9628     cmp     r1, #0                      @ did we overflow earlier?
9629     beq     1f                          @ no, skip ahead
9630     mov     rFP, r0                     @ save relPc result in rFP
9631     mov     r0, r10                     @ r0<- self
9632     bl      dvmCleanupStackOverflow     @ call(self)
9633     mov     r0, rFP                     @ restore result
9634 1:
9635
9636     /* update frame pointer and check result from dvmFindCatchBlock */
9637     ldr     rFP, [sp, #4]               @ retrieve the updated rFP
9638     cmp     r0, #0                      @ is catchRelPc < 0?
9639     add     sp, sp, #8                  @ restore stack
9640     bmi     .LnotCaughtLocally
9641
9642     /* adjust locals to match self->curFrame and updated PC */
9643     SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
9644     ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
9645     str     r1, [rGLUE, #offGlue_method]    @ glue->method = new method
9646     ldr     r2, [r1, #offMethod_clazz]      @ r2<- method->clazz
9647     ldr     r3, [r1, #offMethod_insns]      @ r3<- method->insns
9648     ldr     r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
9649     add     rPC, r3, r0, asl #1             @ rPC<- method->insns + catchRelPc
9650     str     r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
9651
9652     /* release the tracked alloc on the exception */
9653     mov     r0, r9                      @ r0<- exception
9654     mov     r1, r10                     @ r1<- self
9655     bl      dvmReleaseTrackedAlloc      @ release the exception
9656
9657     /* restore the exception if the handler wants it */
9658     FETCH_INST()                        @ load rINST from rPC
9659     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9660     cmp     ip, #OP_MOVE_EXCEPTION      @ is it "move-exception"?
9661     streq   r9, [r10, #offThread_exception] @ yes, restore the exception
9662     GOTO_OPCODE(ip)                     @ jump to next instruction
9663
9664 .LnotCaughtLocally: @ r9=exception, r10=self
9665     /* fix stack overflow if necessary */
9666     ldrb    r1, [r10, #offThread_stackOverflowed]
9667     cmp     r1, #0                      @ did we overflow earlier?
9668     movne   r0, r10                     @ if yes: r0<- self
9669     blne    dvmCleanupStackOverflow     @ if yes: call(self)
9670
9671     @ may want to show "not caught locally" debug messages here
9672 #if DVM_SHOW_EXCEPTION >= 2
9673     /* call __android_log_print(prio, tag, format, ...) */
9674     /* "Exception %s from %s:%d not caught locally" */
9675     @ dvmLineNumFromPC(method, pc - method->insns)
9676     ldr     r0, [rGLUE, #offGlue_method]
9677     ldr     r1, [r0, #offMethod_insns]
9678     sub     r1, rPC, r1
9679     asr     r1, r1, #1
9680     bl      dvmLineNumFromPC
9681     str     r0, [sp, #-4]!
9682     @ dvmGetMethodSourceFile(method)
9683     ldr     r0, [rGLUE, #offGlue_method]
9684     bl      dvmGetMethodSourceFile
9685     str     r0, [sp, #-4]!
9686     @ exception->clazz->descriptor
9687     ldr     r3, [r9, #offObject_clazz]
9688     ldr     r3, [r3, #offClassObject_descriptor]
9689     @
9690     ldr     r2, strExceptionNotCaughtLocally
9691     ldr     r1, strLogTag
9692     mov     r0, #3                      @ LOG_DEBUG
9693     bl      __android_log_print
9694 #endif
9695     str     r9, [r10, #offThread_exception] @ restore exception
9696     mov     r0, r9                      @ r0<- exception
9697     mov     r1, r10                     @ r1<- self
9698     bl      dvmReleaseTrackedAlloc      @ release the exception
9699     mov     r1, #0                      @ "want switch" = false
9700     b       common_gotoBail             @ bail out
9701
9702
9703     /*
9704      * Exception handling, calls through "glue code".
9705      */
9706     .if     0
9707 .LexceptionOld:
9708     SAVE_PC_FP_TO_GLUE()                @ export state
9709     mov     r0, rGLUE                   @ arg to function
9710     bl      dvmMterp_exceptionThrown
9711     b       common_resumeAfterGlueCall
9712     .endif
9713
9714
9715 /*
9716  * After returning from a "glued" function, pull out the updated
9717  * values and start executing at the next instruction.
9718  */
9719 common_resumeAfterGlueCall:
9720     LOAD_PC_FP_FROM_GLUE()              @ pull rPC and rFP out of glue
9721     FETCH_INST()                        @ load rINST from rPC
9722     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9723     GOTO_OPCODE(ip)                     @ jump to next instruction
9724
9725 /*
9726  * Invalid array index.
9727  */
9728 common_errArrayIndex:
9729     EXPORT_PC()
9730     ldr     r0, strArrayIndexException
9731     mov     r1, #0
9732     bl      dvmThrowException
9733     b       common_exceptionThrown
9734
9735 /*
9736  * Invalid array value.
9737  */
9738 common_errArrayStore:
9739     EXPORT_PC()
9740     ldr     r0, strArrayStoreException
9741     mov     r1, #0
9742     bl      dvmThrowException
9743     b       common_exceptionThrown
9744
9745 /*
9746  * Integer divide or mod by zero.
9747  */
9748 common_errDivideByZero:
9749     EXPORT_PC()
9750     ldr     r0, strArithmeticException
9751     ldr     r1, strDivideByZero
9752     bl      dvmThrowException
9753     b       common_exceptionThrown
9754
9755 /*
9756  * Attempt to allocate an array with a negative size.
9757  */
9758 common_errNegativeArraySize:
9759     EXPORT_PC()
9760     ldr     r0, strNegativeArraySizeException
9761     mov     r1, #0
9762     bl      dvmThrowException
9763     b       common_exceptionThrown
9764
9765 /*
9766  * Invocation of a non-existent method.
9767  */
9768 common_errNoSuchMethod:
9769     EXPORT_PC()
9770     ldr     r0, strNoSuchMethodError
9771     mov     r1, #0
9772     bl      dvmThrowException
9773     b       common_exceptionThrown
9774
9775 /*
9776  * We encountered a null object when we weren't expecting one.  We
9777  * export the PC, throw a NullPointerException, and goto the exception
9778  * processing code.
9779  */
9780 common_errNullObject:
9781     EXPORT_PC()
9782     ldr     r0, strNullPointerException
9783     mov     r1, #0
9784     bl      dvmThrowException
9785     b       common_exceptionThrown
9786
9787 /*
9788  * For debugging, cause an immediate fault.  The source address will
9789  * be in lr (use a bl instruction to jump here).
9790  */
9791 common_abort:
9792     ldr     pc, .LdeadFood
9793 .LdeadFood:
9794     .word   0xdeadf00d
9795
9796 /*
9797  * Spit out a "we were here", preserving all registers.  (The attempt
9798  * to save ip won't work, but we need to save an even number of
9799  * registers for EABI 64-bit stack alignment.)
9800  */
9801     .macro  SQUEAK num
9802 common_squeak\num:
9803     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9804     ldr     r0, strSqueak
9805     mov     r1, #\num
9806     bl      printf
9807     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9808     bx      lr
9809     .endm
9810
9811     SQUEAK  0
9812     SQUEAK  1
9813     SQUEAK  2
9814     SQUEAK  3
9815     SQUEAK  4
9816     SQUEAK  5
9817
9818 /*
9819  * Spit out the number in r0, preserving registers.
9820  */
9821 common_printNum:
9822     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9823     mov     r1, r0
9824     ldr     r0, strSqueak
9825     bl      printf
9826     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9827     bx      lr
9828
9829 /*
9830  * Print a newline, preserving registers.
9831  */
9832 common_printNewline:
9833     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9834     ldr     r0, strNewline
9835     bl      printf
9836     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9837     bx      lr
9838
9839     /*
9840      * Print the 32-bit quantity in r0 as a hex value, preserving registers.
9841      */
9842 common_printHex:
9843     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9844     mov     r1, r0
9845     ldr     r0, strPrintHex
9846     bl      printf
9847     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9848     bx      lr
9849
9850 /*
9851  * Print the 64-bit quantity in r0-r1, preserving registers.
9852  */
9853 common_printLong:
9854     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9855     mov     r3, r1
9856     mov     r2, r0
9857     ldr     r0, strPrintLong
9858     bl      printf
9859     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9860     bx      lr
9861
9862 /*
9863  * Print full method info.  Pass the Method* in r0.  Preserves regs.
9864  */
9865 common_printMethod:
9866     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9867     bl      dvmMterpPrintMethod
9868     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9869     bx      lr
9870
9871 /*
9872  * Call a C helper function that dumps regs and possibly some
9873  * additional info.  Requires the C function to be compiled in.
9874  */
9875     .if     0
9876 common_dumpRegs:
9877     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9878     bl      dvmMterpDumpArmRegs
9879     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9880     bx      lr
9881     .endif
9882
9883 #if 0
9884 /*
9885  * Experiment on VFP mode.
9886  *
9887  * uint32_t setFPSCR(uint32_t val, uint32_t mask)
9888  *
9889  * Updates the bits specified by "mask", setting them to the values in "val".
9890  */
9891 setFPSCR:
9892     and     r0, r0, r1                  @ make sure no stray bits are set
9893     fmrx    r2, fpscr                   @ get VFP reg
9894     mvn     r1, r1                      @ bit-invert mask
9895     and     r2, r2, r1                  @ clear masked bits
9896     orr     r2, r2, r0                  @ set specified bits
9897     fmxr    fpscr, r2                   @ set VFP reg
9898     mov     r0, r2                      @ return new value
9899     bx      lr
9900
9901     .align  2
9902     .global dvmConfigureFP
9903     .type   dvmConfigureFP, %function
9904 dvmConfigureFP:
9905     stmfd   sp!, {ip, lr}
9906     /* 0x03000000 sets DN/FZ */
9907     /* 0x00009f00 clears the six exception enable flags */
9908     bl      common_squeak0
9909     mov     r0, #0x03000000             @ r0<- 0x03000000
9910     add     r1, r0, #0x9f00             @ r1<- 0x03009f00
9911     bl      setFPSCR
9912     ldmfd   sp!, {ip, pc}
9913 #endif
9914
9915
9916 /*
9917  * String references, must be close to the code that uses them.
9918  */
9919     .align  2
9920 strArithmeticException:
9921     .word   .LstrArithmeticException
9922 strArrayIndexException:
9923     .word   .LstrArrayIndexException
9924 strArrayStoreException:
9925     .word   .LstrArrayStoreException
9926 strDivideByZero:
9927     .word   .LstrDivideByZero
9928 strNegativeArraySizeException:
9929     .word   .LstrNegativeArraySizeException
9930 strNoSuchMethodError:
9931     .word   .LstrNoSuchMethodError
9932 strNullPointerException:
9933     .word   .LstrNullPointerException
9934
9935 strLogTag:
9936     .word   .LstrLogTag
9937 strExceptionNotCaughtLocally:
9938     .word   .LstrExceptionNotCaughtLocally
9939
9940 strNewline:
9941     .word   .LstrNewline
9942 strSqueak:
9943     .word   .LstrSqueak
9944 strPrintHex:
9945     .word   .LstrPrintHex
9946 strPrintLong:
9947     .word   .LstrPrintLong
9948
9949 /*
9950  * Zero-terminated ASCII string data.
9951  *
9952  * On ARM we have two choices: do like gcc does, and LDR from a .word
9953  * with the address, or use an ADR pseudo-op to get the address
9954  * directly.  ADR saves 4 bytes and an indirection, but it's using a
9955  * PC-relative addressing mode and hence has a limited range, which
9956  * makes it not work well with mergeable string sections.
9957  */
9958     .section .rodata.str1.4,"aMS",%progbits,1
9959
9960 .LstrBadEntryPoint:
9961     .asciz  "Bad entry point %d\n"
9962 .LstrArithmeticException:
9963     .asciz  "Ljava/lang/ArithmeticException;"
9964 .LstrArrayIndexException:
9965     .asciz  "Ljava/lang/ArrayIndexOutOfBoundsException;"
9966 .LstrArrayStoreException:
9967     .asciz  "Ljava/lang/ArrayStoreException;"
9968 .LstrClassCastException:
9969     .asciz  "Ljava/lang/ClassCastException;"
9970 .LstrDivideByZero:
9971     .asciz  "divide by zero"
9972 .LstrFilledNewArrayNotImpl:
9973     .asciz  "filled-new-array only implemented for objects and 'int'"
9974 .LstrInternalError:
9975     .asciz  "Ljava/lang/InternalError;"
9976 .LstrInstantiationError:
9977     .asciz  "Ljava/lang/InstantiationError;"
9978 .LstrNegativeArraySizeException:
9979     .asciz  "Ljava/lang/NegativeArraySizeException;"
9980 .LstrNoSuchMethodError:
9981     .asciz  "Ljava/lang/NoSuchMethodError;"
9982 .LstrNullPointerException:
9983     .asciz  "Ljava/lang/NullPointerException;"
9984
9985 .LstrLogTag:
9986     .asciz  "mterp"
9987 .LstrExceptionNotCaughtLocally:
9988     .asciz  "Exception %s from %s:%d not caught locally\n"
9989
9990 .LstrNewline:
9991     .asciz  "\n"
9992 .LstrSqueak:
9993     .asciz  "<%d>"
9994 .LstrPrintHex:
9995     .asciz  "<0x%x>"
9996 .LstrPrintLong:
9997     .asciz  "<%lld>"
9998
9999