OSDN Git Service

Set the debug interpreter entry point properly on the self-verification path.
[android-x86/dalvik.git] / vm / mterp / out / InterpAsm-armv5te.S
1 /*
2  * This file was generated automatically by gen-mterp.py for 'armv5te'.
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: armv5te/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     mov     r0, rINST, lsr #8           @ r0<- A from 11:8
423     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
424     GET_VREG(r2, r1)                    @ r2<- fp[B]
425     and     r0, r0, #15
426     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
427     SET_VREG(r2, r0)                    @ fp[A]<- r2
428     GOTO_OPCODE(ip)                     @ execute next instruction
429
430
431 /* ------------------------------ */
432     .balign 64
433 .L_OP_MOVE_FROM16: /* 0x02 */
434 /* File: armv5te/OP_MOVE_FROM16.S */
435     /* for: move/from16, move-object/from16 */
436     /* op vAA, vBBBB */
437     FETCH(r1, 1)                        @ r1<- BBBB
438     mov     r0, rINST, lsr #8           @ r0<- AA
439     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
440     GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
441     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
442     SET_VREG(r2, r0)                    @ fp[AA]<- r2
443     GOTO_OPCODE(ip)                     @ jump to next instruction
444
445
446 /* ------------------------------ */
447     .balign 64
448 .L_OP_MOVE_16: /* 0x03 */
449 /* File: armv5te/OP_MOVE_16.S */
450     /* for: move/16, move-object/16 */
451     /* op vAAAA, vBBBB */
452     FETCH(r1, 2)                        @ r1<- BBBB
453     FETCH(r0, 1)                        @ r0<- AAAA
454     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
455     GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
456     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
457     SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
458     GOTO_OPCODE(ip)                     @ jump to next instruction
459
460
461 /* ------------------------------ */
462     .balign 64
463 .L_OP_MOVE_WIDE: /* 0x04 */
464 /* File: armv5te/OP_MOVE_WIDE.S */
465     /* move-wide vA, vB */
466     /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
467     mov     r2, rINST, lsr #8           @ r2<- A(+)
468     mov     r3, rINST, lsr #12          @ r3<- B
469     and     r2, r2, #15
470     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
471     add     r2, rFP, r2, lsl #2         @ r2<- &fp[A]
472     ldmia   r3, {r0-r1}                 @ r0/r1<- fp[B]
473     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
474     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
475     stmia   r2, {r0-r1}                 @ fp[A]<- r0/r1
476     GOTO_OPCODE(ip)                     @ jump to next instruction
477
478
479 /* ------------------------------ */
480     .balign 64
481 .L_OP_MOVE_WIDE_FROM16: /* 0x05 */
482 /* File: armv5te/OP_MOVE_WIDE_FROM16.S */
483     /* move-wide/from16 vAA, vBBBB */
484     /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
485     FETCH(r3, 1)                        @ r3<- BBBB
486     mov     r2, rINST, lsr #8           @ r2<- AA
487     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
488     add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
489     ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
490     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
491     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
492     stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
493     GOTO_OPCODE(ip)                     @ jump to next instruction
494
495
496 /* ------------------------------ */
497     .balign 64
498 .L_OP_MOVE_WIDE_16: /* 0x06 */
499 /* File: armv5te/OP_MOVE_WIDE_16.S */
500     /* move-wide/16 vAAAA, vBBBB */
501     /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
502     FETCH(r3, 2)                        @ r3<- BBBB
503     FETCH(r2, 1)                        @ r2<- AAAA
504     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
505     add     r2, rFP, r2, lsl #2         @ r2<- &fp[AAAA]
506     ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
507     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
508     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
509     stmia   r2, {r0-r1}                 @ fp[AAAA]<- r0/r1
510     GOTO_OPCODE(ip)                     @ jump to next instruction
511
512
513 /* ------------------------------ */
514     .balign 64
515 .L_OP_MOVE_OBJECT: /* 0x07 */
516 /* File: armv5te/OP_MOVE_OBJECT.S */
517 /* File: armv5te/OP_MOVE.S */
518     /* for move, move-object, long-to-int */
519     /* op vA, vB */
520     mov     r1, rINST, lsr #12          @ r1<- B from 15:12
521     mov     r0, rINST, lsr #8           @ r0<- A from 11:8
522     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
523     GET_VREG(r2, r1)                    @ r2<- fp[B]
524     and     r0, r0, #15
525     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
526     SET_VREG(r2, r0)                    @ fp[A]<- r2
527     GOTO_OPCODE(ip)                     @ execute next instruction
528
529
530
531 /* ------------------------------ */
532     .balign 64
533 .L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
534 /* File: armv5te/OP_MOVE_OBJECT_FROM16.S */
535 /* File: armv5te/OP_MOVE_FROM16.S */
536     /* for: move/from16, move-object/from16 */
537     /* op vAA, vBBBB */
538     FETCH(r1, 1)                        @ r1<- BBBB
539     mov     r0, rINST, lsr #8           @ r0<- AA
540     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
541     GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
542     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
543     SET_VREG(r2, r0)                    @ fp[AA]<- r2
544     GOTO_OPCODE(ip)                     @ jump to next instruction
545
546
547
548 /* ------------------------------ */
549     .balign 64
550 .L_OP_MOVE_OBJECT_16: /* 0x09 */
551 /* File: armv5te/OP_MOVE_OBJECT_16.S */
552 /* File: armv5te/OP_MOVE_16.S */
553     /* for: move/16, move-object/16 */
554     /* op vAAAA, vBBBB */
555     FETCH(r1, 2)                        @ r1<- BBBB
556     FETCH(r0, 1)                        @ r0<- AAAA
557     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
558     GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
559     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
560     SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
561     GOTO_OPCODE(ip)                     @ jump to next instruction
562
563
564
565 /* ------------------------------ */
566     .balign 64
567 .L_OP_MOVE_RESULT: /* 0x0a */
568 /* File: armv5te/OP_MOVE_RESULT.S */
569     /* for: move-result, move-result-object */
570     /* op vAA */
571     mov     r2, rINST, lsr #8           @ r2<- AA
572     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
573     ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
574     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
575     SET_VREG(r0, r2)                    @ fp[AA]<- r0
576     GOTO_OPCODE(ip)                     @ jump to next instruction
577
578
579 /* ------------------------------ */
580     .balign 64
581 .L_OP_MOVE_RESULT_WIDE: /* 0x0b */
582 /* File: armv5te/OP_MOVE_RESULT_WIDE.S */
583     /* move-result-wide vAA */
584     mov     r2, rINST, lsr #8           @ r2<- AA
585     add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
586     add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
587     ldmia   r3, {r0-r1}                 @ r0/r1<- retval.j
588     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
589     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
590     stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
591     GOTO_OPCODE(ip)                     @ jump to next instruction
592
593
594 /* ------------------------------ */
595     .balign 64
596 .L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
597 /* File: armv5te/OP_MOVE_RESULT_OBJECT.S */
598 /* File: armv5te/OP_MOVE_RESULT.S */
599     /* for: move-result, move-result-object */
600     /* op vAA */
601     mov     r2, rINST, lsr #8           @ r2<- AA
602     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
603     ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
604     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
605     SET_VREG(r0, r2)                    @ fp[AA]<- r0
606     GOTO_OPCODE(ip)                     @ jump to next instruction
607
608
609
610 /* ------------------------------ */
611     .balign 64
612 .L_OP_MOVE_EXCEPTION: /* 0x0d */
613 /* File: armv5te/OP_MOVE_EXCEPTION.S */
614     /* move-exception vAA */
615     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
616     mov     r2, rINST, lsr #8           @ r2<- AA
617     ldr     r3, [r0, #offThread_exception]  @ r3<- dvmGetException bypass
618     mov     r1, #0                      @ r1<- 0
619     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
620     SET_VREG(r3, r2)                    @ fp[AA]<- exception obj
621     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
622     str     r1, [r0, #offThread_exception]  @ dvmClearException bypass
623     GOTO_OPCODE(ip)                     @ jump to next instruction
624
625
626 /* ------------------------------ */
627     .balign 64
628 .L_OP_RETURN_VOID: /* 0x0e */
629 /* File: armv5te/OP_RETURN_VOID.S */
630     b       common_returnFromMethod
631
632
633 /* ------------------------------ */
634     .balign 64
635 .L_OP_RETURN: /* 0x0f */
636 /* File: armv5te/OP_RETURN.S */
637     /*
638      * Return a 32-bit value.  Copies the return value into the "glue"
639      * structure, then jumps to the return handler.
640      *
641      * for: return, return-object
642      */
643     /* op vAA */
644     mov     r2, rINST, lsr #8           @ r2<- AA
645     GET_VREG(r0, r2)                    @ r0<- vAA
646     str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
647     b       common_returnFromMethod
648
649
650 /* ------------------------------ */
651     .balign 64
652 .L_OP_RETURN_WIDE: /* 0x10 */
653 /* File: armv5te/OP_RETURN_WIDE.S */
654     /*
655      * Return a 64-bit value.  Copies the return value into the "glue"
656      * structure, then jumps to the return handler.
657      */
658     /* return-wide vAA */
659     mov     r2, rINST, lsr #8           @ r2<- AA
660     add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
661     add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
662     ldmia   r2, {r0-r1}                 @ r0/r1 <- vAA/vAA+1
663     stmia   r3, {r0-r1}                 @ retval<- r0/r1
664     b       common_returnFromMethod
665
666
667 /* ------------------------------ */
668     .balign 64
669 .L_OP_RETURN_OBJECT: /* 0x11 */
670 /* File: armv5te/OP_RETURN_OBJECT.S */
671 /* File: armv5te/OP_RETURN.S */
672     /*
673      * Return a 32-bit value.  Copies the return value into the "glue"
674      * structure, then jumps to the return handler.
675      *
676      * for: return, return-object
677      */
678     /* op vAA */
679     mov     r2, rINST, lsr #8           @ r2<- AA
680     GET_VREG(r0, r2)                    @ r0<- vAA
681     str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
682     b       common_returnFromMethod
683
684
685
686 /* ------------------------------ */
687     .balign 64
688 .L_OP_CONST_4: /* 0x12 */
689 /* File: armv5te/OP_CONST_4.S */
690     /* const/4 vA, #+B */
691     mov     r1, rINST, lsl #16          @ r1<- Bxxx0000
692     mov     r0, rINST, lsr #8           @ r0<- A+
693     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
694     mov     r1, r1, asr #28             @ r1<- sssssssB (sign-extended)
695     and     r0, r0, #15
696     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
697     SET_VREG(r1, r0)                    @ fp[A]<- r1
698     GOTO_OPCODE(ip)                     @ execute next instruction
699
700
701 /* ------------------------------ */
702     .balign 64
703 .L_OP_CONST_16: /* 0x13 */
704 /* File: armv5te/OP_CONST_16.S */
705     /* const/16 vAA, #+BBBB */
706     FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
707     mov     r3, rINST, lsr #8           @ r3<- AA
708     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
709     SET_VREG(r0, r3)                    @ vAA<- r0
710     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
711     GOTO_OPCODE(ip)                     @ jump to next instruction
712
713
714 /* ------------------------------ */
715     .balign 64
716 .L_OP_CONST: /* 0x14 */
717 /* File: armv5te/OP_CONST.S */
718     /* const vAA, #+BBBBbbbb */
719     mov     r3, rINST, lsr #8           @ r3<- AA
720     FETCH(r0, 1)                        @ r0<- bbbb (low)
721     FETCH(r1, 2)                        @ r1<- BBBB (high)
722     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
723     orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
724     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
725     SET_VREG(r0, r3)                    @ vAA<- r0
726     GOTO_OPCODE(ip)                     @ jump to next instruction
727
728
729 /* ------------------------------ */
730     .balign 64
731 .L_OP_CONST_HIGH16: /* 0x15 */
732 /* File: armv5te/OP_CONST_HIGH16.S */
733     /* const/high16 vAA, #+BBBB0000 */
734     FETCH(r0, 1)                        @ r0<- 0000BBBB (zero-extended)
735     mov     r3, rINST, lsr #8           @ r3<- AA
736     mov     r0, r0, lsl #16             @ r0<- BBBB0000
737     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
738     SET_VREG(r0, r3)                    @ vAA<- r0
739     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
740     GOTO_OPCODE(ip)                     @ jump to next instruction
741
742
743 /* ------------------------------ */
744     .balign 64
745 .L_OP_CONST_WIDE_16: /* 0x16 */
746 /* File: armv5te/OP_CONST_WIDE_16.S */
747     /* const-wide/16 vAA, #+BBBB */
748     FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
749     mov     r3, rINST, lsr #8           @ r3<- AA
750     mov     r1, r0, asr #31             @ r1<- ssssssss
751     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
752     add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
753     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
754     stmia   r3, {r0-r1}                 @ vAA<- r0/r1
755     GOTO_OPCODE(ip)                     @ jump to next instruction
756
757
758 /* ------------------------------ */
759     .balign 64
760 .L_OP_CONST_WIDE_32: /* 0x17 */
761 /* File: armv5te/OP_CONST_WIDE_32.S */
762     /* const-wide/32 vAA, #+BBBBbbbb */
763     FETCH(r0, 1)                        @ r0<- 0000bbbb (low)
764     mov     r3, rINST, lsr #8           @ r3<- AA
765     FETCH_S(r2, 2)                      @ r2<- ssssBBBB (high)
766     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
767     orr     r0, r0, r2, lsl #16         @ r0<- BBBBbbbb
768     add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
769     mov     r1, r0, asr #31             @ r1<- ssssssss
770     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
771     stmia   r3, {r0-r1}                 @ vAA<- r0/r1
772     GOTO_OPCODE(ip)                     @ jump to next instruction
773
774
775 /* ------------------------------ */
776     .balign 64
777 .L_OP_CONST_WIDE: /* 0x18 */
778 /* File: armv5te/OP_CONST_WIDE.S */
779     /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
780     FETCH(r0, 1)                        @ r0<- bbbb (low)
781     FETCH(r1, 2)                        @ r1<- BBBB (low middle)
782     FETCH(r2, 3)                        @ r2<- hhhh (high middle)
783     orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb (low word)
784     FETCH(r3, 4)                        @ r3<- HHHH (high)
785     mov     r9, rINST, lsr #8           @ r9<- AA
786     orr     r1, r2, r3, lsl #16         @ r1<- HHHHhhhh (high word)
787     FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
788     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
789     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
790     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
791     GOTO_OPCODE(ip)                     @ jump to next instruction
792
793
794 /* ------------------------------ */
795     .balign 64
796 .L_OP_CONST_WIDE_HIGH16: /* 0x19 */
797 /* File: armv5te/OP_CONST_WIDE_HIGH16.S */
798     /* const-wide/high16 vAA, #+BBBB000000000000 */
799     FETCH(r1, 1)                        @ r1<- 0000BBBB (zero-extended)
800     mov     r3, rINST, lsr #8           @ r3<- AA
801     mov     r0, #0                      @ r0<- 00000000
802     mov     r1, r1, lsl #16             @ r1<- BBBB0000
803     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
804     add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
805     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
806     stmia   r3, {r0-r1}                 @ vAA<- r0/r1
807     GOTO_OPCODE(ip)                     @ jump to next instruction
808
809
810 /* ------------------------------ */
811     .balign 64
812 .L_OP_CONST_STRING: /* 0x1a */
813 /* File: armv5te/OP_CONST_STRING.S */
814     /* const/string vAA, String@BBBB */
815     FETCH(r1, 1)                        @ r1<- BBBB
816     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
817     mov     r9, rINST, lsr #8           @ r9<- AA
818     ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
819     ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
820     cmp     r0, #0                      @ not yet resolved?
821     beq     .LOP_CONST_STRING_resolve
822     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
823     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
824     SET_VREG(r0, r9)                    @ vAA<- r0
825     GOTO_OPCODE(ip)                     @ jump to next instruction
826
827 /* ------------------------------ */
828     .balign 64
829 .L_OP_CONST_STRING_JUMBO: /* 0x1b */
830 /* File: armv5te/OP_CONST_STRING_JUMBO.S */
831     /* const/string vAA, String@BBBBBBBB */
832     FETCH(r0, 1)                        @ r0<- bbbb (low)
833     FETCH(r1, 2)                        @ r1<- BBBB (high)
834     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
835     mov     r9, rINST, lsr #8           @ r9<- AA
836     ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
837     orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
838     ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
839     cmp     r0, #0
840     beq     .LOP_CONST_STRING_JUMBO_resolve
841     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
842     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
843     SET_VREG(r0, r9)                    @ vAA<- r0
844     GOTO_OPCODE(ip)                     @ jump to next instruction
845
846 /* ------------------------------ */
847     .balign 64
848 .L_OP_CONST_CLASS: /* 0x1c */
849 /* File: armv5te/OP_CONST_CLASS.S */
850     /* const/class vAA, Class@BBBB */
851     FETCH(r1, 1)                        @ r1<- BBBB
852     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
853     mov     r9, rINST, lsr #8           @ r9<- AA
854     ldr     r2, [r2, #offDvmDex_pResClasses]   @ r2<- dvmDex->pResClasses
855     ldr     r0, [r2, r1, lsl #2]        @ r0<- pResClasses[BBBB]
856     cmp     r0, #0                      @ not yet resolved?
857     beq     .LOP_CONST_CLASS_resolve
858     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
859     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
860     SET_VREG(r0, r9)                    @ vAA<- r0
861     GOTO_OPCODE(ip)                     @ jump to next instruction
862
863 /* ------------------------------ */
864     .balign 64
865 .L_OP_MONITOR_ENTER: /* 0x1d */
866 /* File: armv5te/OP_MONITOR_ENTER.S */
867     /*
868      * Synchronize on an object.
869      */
870     /* monitor-enter vAA */
871     mov     r2, rINST, lsr #8           @ r2<- AA
872     GET_VREG(r1, r2)                    @ r1<- vAA (object)
873     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
874     cmp     r1, #0                      @ null object?
875     EXPORT_PC()                         @ need for precise GC, MONITOR_TRACKING
876     beq     common_errNullObject        @ null object, throw an exception
877     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
878     bl      dvmLockObject               @ call(self, obj)
879 #ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */
880     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
881     ldr     r1, [r0, #offThread_exception] @ check for exception
882     cmp     r1, #0
883     bne     common_exceptionThrown      @ exception raised, bail out
884 #endif
885     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
886     GOTO_OPCODE(ip)                     @ jump to next instruction
887
888
889 /* ------------------------------ */
890     .balign 64
891 .L_OP_MONITOR_EXIT: /* 0x1e */
892 /* File: armv5te/OP_MONITOR_EXIT.S */
893     /*
894      * Unlock an object.
895      *
896      * Exceptions that occur when unlocking a monitor need to appear as
897      * if they happened at the following instruction.  See the Dalvik
898      * instruction spec.
899      */
900     /* monitor-exit vAA */
901     mov     r2, rINST, lsr #8           @ r2<- AA
902     EXPORT_PC()                         @ before fetch: export the PC
903     GET_VREG(r1, r2)                    @ r1<- vAA (object)
904     cmp     r1, #0                      @ null object?
905     beq     common_errNullObject        @ yes
906     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
907     bl      dvmUnlockObject             @ r0<- success for unlock(self, obj)
908     cmp     r0, #0                      @ failed?
909     beq     common_exceptionThrown      @ yes, exception is pending
910     FETCH_ADVANCE_INST(1)               @ before throw: advance rPC, load rINST
911     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
912     GOTO_OPCODE(ip)                     @ jump to next instruction
913
914
915 /* ------------------------------ */
916     .balign 64
917 .L_OP_CHECK_CAST: /* 0x1f */
918 /* File: armv5te/OP_CHECK_CAST.S */
919     /*
920      * Check to see if a cast from one class to another is allowed.
921      */
922     /* check-cast vAA, class@BBBB */
923     mov     r3, rINST, lsr #8           @ r3<- AA
924     FETCH(r2, 1)                        @ r2<- BBBB
925     GET_VREG(r9, r3)                    @ r9<- object
926     ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- pDvmDex
927     cmp     r9, #0                      @ is object null?
928     ldr     r0, [r0, #offDvmDex_pResClasses]    @ r0<- pDvmDex->pResClasses
929     beq     .LOP_CHECK_CAST_okay            @ null obj, cast always succeeds
930     ldr     r1, [r0, r2, lsl #2]        @ r1<- resolved class
931     ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
932     cmp     r1, #0                      @ have we resolved this before?
933     beq     .LOP_CHECK_CAST_resolve         @ not resolved, do it now
934 .LOP_CHECK_CAST_resolved:
935     cmp     r0, r1                      @ same class (trivial success)?
936     bne     .LOP_CHECK_CAST_fullcheck       @ no, do full check
937 .LOP_CHECK_CAST_okay:
938     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
939     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
940     GOTO_OPCODE(ip)                     @ jump to next instruction
941
942 /* ------------------------------ */
943     .balign 64
944 .L_OP_INSTANCE_OF: /* 0x20 */
945 /* File: armv5te/OP_INSTANCE_OF.S */
946     /*
947      * Check to see if an object reference is an instance of a class.
948      *
949      * Most common situation is a non-null object, being compared against
950      * an already-resolved class.
951      */
952     /* instance-of vA, vB, class@CCCC */
953     mov     r3, rINST, lsr #12          @ r3<- B
954     mov     r9, rINST, lsr #8           @ r9<- A+
955     GET_VREG(r0, r3)                    @ r0<- vB (object)
956     and     r9, r9, #15                 @ r9<- A
957     cmp     r0, #0                      @ is object null?
958     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- pDvmDex
959     beq     .LOP_INSTANCE_OF_store           @ null obj, not an instance, store r0
960     FETCH(r3, 1)                        @ r3<- CCCC
961     ldr     r2, [r2, #offDvmDex_pResClasses]    @ r2<- pDvmDex->pResClasses
962     ldr     r1, [r2, r3, lsl #2]        @ r1<- resolved class
963     ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
964     cmp     r1, #0                      @ have we resolved this before?
965     beq     .LOP_INSTANCE_OF_resolve         @ not resolved, do it now
966 .LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class
967     cmp     r0, r1                      @ same class (trivial success)?
968     beq     .LOP_INSTANCE_OF_trivial         @ yes, trivial finish
969     b       .LOP_INSTANCE_OF_fullcheck       @ no, do full check
970
971 /* ------------------------------ */
972     .balign 64
973 .L_OP_ARRAY_LENGTH: /* 0x21 */
974 /* File: armv5te/OP_ARRAY_LENGTH.S */
975     /*
976      * Return the length of an array.
977      */
978     mov     r1, rINST, lsr #12          @ r1<- B
979     mov     r2, rINST, lsr #8           @ r2<- A+
980     GET_VREG(r0, r1)                    @ r0<- vB (object ref)
981     and     r2, r2, #15                 @ r2<- A
982     cmp     r0, #0                      @ is object null?
983     beq     common_errNullObject        @ yup, fail
984     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
985     ldr     r3, [r0, #offArrayObject_length]    @ r3<- array length
986     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
987     SET_VREG(r3, r2)                    @ vB<- length
988     GOTO_OPCODE(ip)                     @ jump to next instruction
989
990
991 /* ------------------------------ */
992     .balign 64
993 .L_OP_NEW_INSTANCE: /* 0x22 */
994 /* File: armv5te/OP_NEW_INSTANCE.S */
995     /*
996      * Create a new instance of a class.
997      */
998     /* new-instance vAA, class@BBBB */
999     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1000     FETCH(r1, 1)                        @ r1<- BBBB
1001     ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1002     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1003     EXPORT_PC()                         @ req'd for init, resolve, alloc
1004     cmp     r0, #0                      @ already resolved?
1005     beq     .LOP_NEW_INSTANCE_resolve         @ no, resolve it now
1006 .LOP_NEW_INSTANCE_resolved:   @ r0=class
1007     ldrb    r1, [r0, #offClassObject_status]    @ r1<- ClassStatus enum
1008     cmp     r1, #CLASS_INITIALIZED      @ has class been initialized?
1009     bne     .LOP_NEW_INSTANCE_needinit        @ no, init class now
1010 .LOP_NEW_INSTANCE_initialized: @ r0=class
1011     mov     r1, #ALLOC_DONT_TRACK       @ flags for alloc call
1012     bl      dvmAllocObject              @ r0<- new object
1013     b       .LOP_NEW_INSTANCE_finish          @ continue
1014
1015 /* ------------------------------ */
1016     .balign 64
1017 .L_OP_NEW_ARRAY: /* 0x23 */
1018 /* File: armv5te/OP_NEW_ARRAY.S */
1019     /*
1020      * Allocate an array of objects, specified with the array class
1021      * and a count.
1022      *
1023      * The verifier guarantees that this is an array class, so we don't
1024      * check for it here.
1025      */
1026     /* new-array vA, vB, class@CCCC */
1027     mov     r0, rINST, lsr #12          @ r0<- B
1028     FETCH(r2, 1)                        @ r2<- CCCC
1029     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1030     GET_VREG(r1, r0)                    @ r1<- vB (array length)
1031     ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1032     cmp     r1, #0                      @ check length
1033     ldr     r0, [r3, r2, lsl #2]        @ r0<- resolved class
1034     bmi     common_errNegativeArraySize @ negative length, bail
1035     cmp     r0, #0                      @ already resolved?
1036     EXPORT_PC()                         @ req'd for resolve, alloc
1037     bne     .LOP_NEW_ARRAY_finish          @ resolved, continue
1038     b       .LOP_NEW_ARRAY_resolve         @ do resolve now
1039
1040 /* ------------------------------ */
1041     .balign 64
1042 .L_OP_FILLED_NEW_ARRAY: /* 0x24 */
1043 /* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1044     /*
1045      * Create a new array with elements filled from registers.
1046      *
1047      * for: filled-new-array, filled-new-array/range
1048      */
1049     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1050     /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1051     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1052     FETCH(r1, 1)                        @ r1<- BBBB
1053     ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1054     EXPORT_PC()                         @ need for resolve and alloc
1055     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1056     mov     r10, rINST, lsr #8          @ r10<- AA or BA
1057     cmp     r0, #0                      @ already resolved?
1058     bne     .LOP_FILLED_NEW_ARRAY_continue        @ yes, continue on
1059 8:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1060     mov     r2, #0                      @ r2<- false
1061     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1062     bl      dvmResolveClass             @ r0<- call(clazz, ref)
1063     cmp     r0, #0                      @ got null?
1064     beq     common_exceptionThrown      @ yes, handle exception
1065     b       .LOP_FILLED_NEW_ARRAY_continue
1066
1067 /* ------------------------------ */
1068     .balign 64
1069 .L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
1070 /* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */
1071 /* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1072     /*
1073      * Create a new array with elements filled from registers.
1074      *
1075      * for: filled-new-array, filled-new-array/range
1076      */
1077     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1078     /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1079     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1080     FETCH(r1, 1)                        @ r1<- BBBB
1081     ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1082     EXPORT_PC()                         @ need for resolve and alloc
1083     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1084     mov     r10, rINST, lsr #8          @ r10<- AA or BA
1085     cmp     r0, #0                      @ already resolved?
1086     bne     .LOP_FILLED_NEW_ARRAY_RANGE_continue        @ yes, continue on
1087 8:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1088     mov     r2, #0                      @ r2<- false
1089     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1090     bl      dvmResolveClass             @ r0<- call(clazz, ref)
1091     cmp     r0, #0                      @ got null?
1092     beq     common_exceptionThrown      @ yes, handle exception
1093     b       .LOP_FILLED_NEW_ARRAY_RANGE_continue
1094
1095
1096 /* ------------------------------ */
1097     .balign 64
1098 .L_OP_FILL_ARRAY_DATA: /* 0x26 */
1099 /* File: armv5te/OP_FILL_ARRAY_DATA.S */
1100     /* fill-array-data vAA, +BBBBBBBB */
1101     FETCH(r0, 1)                        @ r0<- bbbb (lo)
1102     FETCH(r1, 2)                        @ r1<- BBBB (hi)
1103     mov     r3, rINST, lsr #8           @ r3<- AA
1104     orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
1105     GET_VREG(r0, r3)                    @ r0<- vAA (array object)
1106     add     r1, rPC, r1, lsl #1         @ r1<- PC + BBBBbbbb*2 (array data off.)
1107     EXPORT_PC();
1108     bl      dvmInterpHandleFillArrayData@ fill the array with predefined data
1109     cmp     r0, #0                      @ 0 means an exception is thrown
1110     beq     common_exceptionThrown      @ has exception
1111     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
1112     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1113     GOTO_OPCODE(ip)                     @ jump to next instruction
1114
1115 /* ------------------------------ */
1116     .balign 64
1117 .L_OP_THROW: /* 0x27 */
1118 /* File: armv5te/OP_THROW.S */
1119     /*
1120      * Throw an exception object in the current thread.
1121      */
1122     /* throw vAA */
1123     mov     r2, rINST, lsr #8           @ r2<- AA
1124     GET_VREG(r1, r2)                    @ r1<- vAA (exception object)
1125     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
1126     cmp     r1, #0                      @ null object?
1127     beq     common_errNullObject        @ yes, throw an NPE instead
1128     @ bypass dvmSetException, just store it
1129     str     r1, [r0, #offThread_exception]  @ thread->exception<- obj
1130     b       common_exceptionThrown
1131
1132
1133 /* ------------------------------ */
1134     .balign 64
1135 .L_OP_GOTO: /* 0x28 */
1136 /* File: armv5te/OP_GOTO.S */
1137     /*
1138      * Unconditional branch, 8-bit offset.
1139      *
1140      * The branch distance is a signed code-unit offset, which we need to
1141      * double to get a byte offset.
1142      */
1143     /* goto +AA */
1144     mov     r0, rINST, lsl #16          @ r0<- AAxx0000
1145     movs    r9, r0, asr #24             @ r9<- ssssssAA (sign-extended)
1146     mov     r9, r9, lsl #1              @ r9<- byte offset
1147     bmi     common_backwardBranch       @ backward branch, do periodic checks
1148 #if defined(WITH_JIT)
1149     GET_JIT_PROF_TABLE(r0)
1150     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1151     cmp     r0,#0
1152     bne     common_updateProfile
1153     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1154     GOTO_OPCODE(ip)                     @ jump to next instruction
1155 #else
1156     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1157     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1158     GOTO_OPCODE(ip)                     @ jump to next instruction
1159 #endif
1160
1161 /* ------------------------------ */
1162     .balign 64
1163 .L_OP_GOTO_16: /* 0x29 */
1164 /* File: armv5te/OP_GOTO_16.S */
1165     /*
1166      * Unconditional branch, 16-bit offset.
1167      *
1168      * The branch distance is a signed code-unit offset, which we need to
1169      * double to get a byte offset.
1170      */
1171     /* goto/16 +AAAA */
1172     FETCH_S(r0, 1)                      @ r0<- ssssAAAA (sign-extended)
1173     movs    r9, r0, asl #1              @ r9<- byte offset, check sign
1174     bmi     common_backwardBranch       @ backward branch, do periodic checks
1175 #if defined(WITH_JIT)
1176     GET_JIT_PROF_TABLE(r0)
1177     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1178     cmp     r0,#0
1179     bne     common_updateProfile
1180     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1181     GOTO_OPCODE(ip)                     @ jump to next instruction
1182 #else
1183     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1184     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1185     GOTO_OPCODE(ip)                     @ jump to next instruction
1186 #endif
1187
1188
1189 /* ------------------------------ */
1190     .balign 64
1191 .L_OP_GOTO_32: /* 0x2a */
1192 /* File: armv5te/OP_GOTO_32.S */
1193     /*
1194      * Unconditional branch, 32-bit offset.
1195      *
1196      * The branch distance is a signed code-unit offset, which we need to
1197      * double to get a byte offset.
1198      *
1199      * Unlike most opcodes, this one is allowed to branch to itself, so
1200      * our "backward branch" test must be "<=0" instead of "<0".  The ORRS
1201      * instruction doesn't affect the V flag, so we need to clear it
1202      * explicitly.
1203      */
1204     /* goto/32 +AAAAAAAA */
1205     FETCH(r0, 1)                        @ r0<- aaaa (lo)
1206     FETCH(r1, 2)                        @ r1<- AAAA (hi)
1207     cmp     ip, ip                      @ (clear V flag during stall)
1208     orrs    r0, r0, r1, lsl #16         @ r0<- AAAAaaaa, check sign
1209     mov     r9, r0, asl #1              @ r9<- byte offset
1210     ble     common_backwardBranch       @ backward branch, do periodic checks
1211 #if defined(WITH_JIT)
1212     GET_JIT_PROF_TABLE(r0)
1213     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1214     cmp     r0,#0
1215     bne     common_updateProfile
1216     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1217     GOTO_OPCODE(ip)                     @ jump to next instruction
1218 #else
1219     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1220     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1221     GOTO_OPCODE(ip)                     @ jump to next instruction
1222 #endif
1223
1224 /* ------------------------------ */
1225     .balign 64
1226 .L_OP_PACKED_SWITCH: /* 0x2b */
1227 /* File: armv5te/OP_PACKED_SWITCH.S */
1228     /*
1229      * Handle a packed-switch or sparse-switch instruction.  In both cases
1230      * we decode it and hand it off to a helper function.
1231      *
1232      * We don't really expect backward branches in a switch statement, but
1233      * they're perfectly legal, so we check for them here.
1234      *
1235      * for: packed-switch, sparse-switch
1236      */
1237     /* op vAA, +BBBB */
1238     FETCH(r0, 1)                        @ r0<- bbbb (lo)
1239     FETCH(r1, 2)                        @ r1<- BBBB (hi)
1240     mov     r3, rINST, lsr #8           @ r3<- AA
1241     orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1242     GET_VREG(r1, r3)                    @ r1<- vAA
1243     add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1244     bl      dvmInterpHandlePackedSwitch                       @ r0<- code-unit branch offset
1245     movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1246     bmi     common_backwardBranch       @ backward branch, do periodic checks
1247     beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1248 #if defined(WITH_JIT)
1249     GET_JIT_PROF_TABLE(r0)
1250     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1251     cmp     r0,#0
1252     bne     common_updateProfile
1253     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1254     GOTO_OPCODE(ip)                     @ jump to next instruction
1255 #else
1256     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1257     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1258     GOTO_OPCODE(ip)                     @ jump to next instruction
1259 #endif
1260
1261
1262 /* ------------------------------ */
1263     .balign 64
1264 .L_OP_SPARSE_SWITCH: /* 0x2c */
1265 /* File: armv5te/OP_SPARSE_SWITCH.S */
1266 /* File: armv5te/OP_PACKED_SWITCH.S */
1267     /*
1268      * Handle a packed-switch or sparse-switch instruction.  In both cases
1269      * we decode it and hand it off to a helper function.
1270      *
1271      * We don't really expect backward branches in a switch statement, but
1272      * they're perfectly legal, so we check for them here.
1273      *
1274      * for: packed-switch, sparse-switch
1275      */
1276     /* op vAA, +BBBB */
1277     FETCH(r0, 1)                        @ r0<- bbbb (lo)
1278     FETCH(r1, 2)                        @ r1<- BBBB (hi)
1279     mov     r3, rINST, lsr #8           @ r3<- AA
1280     orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1281     GET_VREG(r1, r3)                    @ r1<- vAA
1282     add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1283     bl      dvmInterpHandleSparseSwitch                       @ r0<- code-unit branch offset
1284     movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1285     bmi     common_backwardBranch       @ backward branch, do periodic checks
1286     beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1287 #if defined(WITH_JIT)
1288     GET_JIT_PROF_TABLE(r0)
1289     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1290     cmp     r0,#0
1291     bne     common_updateProfile
1292     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1293     GOTO_OPCODE(ip)                     @ jump to next instruction
1294 #else
1295     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1296     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1297     GOTO_OPCODE(ip)                     @ jump to next instruction
1298 #endif
1299
1300
1301
1302 /* ------------------------------ */
1303     .balign 64
1304 .L_OP_CMPL_FLOAT: /* 0x2d */
1305 /* File: armv5te/OP_CMPL_FLOAT.S */
1306     /*
1307      * Compare two floating-point values.  Puts 0, 1, or -1 into the
1308      * destination register based on the results of the comparison.
1309      *
1310      * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1311      * on what value we'd like to return when one of the operands is NaN.
1312      *
1313      * The operation we're implementing is:
1314      *   if (x == y)
1315      *     return 0;
1316      *   else if (x < y)
1317      *     return -1;
1318      *   else if (x > y)
1319      *     return 1;
1320      *   else
1321      *     return {-1,1};  // one or both operands was NaN
1322      *
1323      * The straightforward implementation requires 3 calls to functions
1324      * that return a result in r0.  We can do it with two calls if our
1325      * EABI library supports __aeabi_cfcmple (only one if we want to check
1326      * for NaN directly):
1327      *   check x <= y
1328      *     if <, return -1
1329      *     if ==, return 0
1330      *   check y <= x
1331      *     if <, return 1
1332      *   return {-1,1}
1333      *
1334      * for: cmpl-float, cmpg-float
1335      */
1336     /* op vAA, vBB, vCC */
1337     FETCH(r0, 1)                        @ r0<- CCBB
1338     and     r2, r0, #255                @ r2<- BB
1339     mov     r3, r0, lsr #8              @ r3<- CC
1340     GET_VREG(r9, r2)                    @ r9<- vBB
1341     GET_VREG(r10, r3)                   @ r10<- vCC
1342     mov     r0, r9                      @ copy to arg registers
1343     mov     r1, r10
1344     bl      __aeabi_cfcmple             @ cmp <=: C clear if <, Z set if eq
1345     bhi     .LOP_CMPL_FLOAT_gt_or_nan       @ C set and Z clear, disambiguate
1346     mvncc   r1, #0                      @ (less than) r1<- -1
1347     moveq   r1, #0                      @ (equal) r1<- 0, trumps less than
1348 .LOP_CMPL_FLOAT_finish:
1349     mov     r3, rINST, lsr #8           @ r3<- AA
1350     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1351     SET_VREG(r1, r3)                    @ vAA<- r1
1352     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1353     GOTO_OPCODE(ip)                     @ jump to next instruction
1354
1355 /* ------------------------------ */
1356     .balign 64
1357 .L_OP_CMPG_FLOAT: /* 0x2e */
1358 /* File: armv5te/OP_CMPG_FLOAT.S */
1359 /* File: armv5te/OP_CMPL_FLOAT.S */
1360     /*
1361      * Compare two floating-point values.  Puts 0, 1, or -1 into the
1362      * destination register based on the results of the comparison.
1363      *
1364      * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1365      * on what value we'd like to return when one of the operands is NaN.
1366      *
1367      * The operation we're implementing is:
1368      *   if (x == y)
1369      *     return 0;
1370      *   else if (x < y)
1371      *     return -1;
1372      *   else if (x > y)
1373      *     return 1;
1374      *   else
1375      *     return {-1,1};  // one or both operands was NaN
1376      *
1377      * The straightforward implementation requires 3 calls to functions
1378      * that return a result in r0.  We can do it with two calls if our
1379      * EABI library supports __aeabi_cfcmple (only one if we want to check
1380      * for NaN directly):
1381      *   check x <= y
1382      *     if <, return -1
1383      *     if ==, return 0
1384      *   check y <= x
1385      *     if <, return 1
1386      *   return {-1,1}
1387      *
1388      * for: cmpl-float, cmpg-float
1389      */
1390     /* op vAA, vBB, vCC */
1391     FETCH(r0, 1)                        @ r0<- CCBB
1392     and     r2, r0, #255                @ r2<- BB
1393     mov     r3, r0, lsr #8              @ r3<- CC
1394     GET_VREG(r9, r2)                    @ r9<- vBB
1395     GET_VREG(r10, r3)                   @ r10<- vCC
1396     mov     r0, r9                      @ copy to arg registers
1397     mov     r1, r10
1398     bl      __aeabi_cfcmple             @ cmp <=: C clear if <, Z set if eq
1399     bhi     .LOP_CMPG_FLOAT_gt_or_nan       @ C set and Z clear, disambiguate
1400     mvncc   r1, #0                      @ (less than) r1<- -1
1401     moveq   r1, #0                      @ (equal) r1<- 0, trumps less than
1402 .LOP_CMPG_FLOAT_finish:
1403     mov     r3, rINST, lsr #8           @ r3<- AA
1404     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1405     SET_VREG(r1, r3)                    @ vAA<- r1
1406     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1407     GOTO_OPCODE(ip)                     @ jump to next instruction
1408
1409
1410 /* ------------------------------ */
1411     .balign 64
1412 .L_OP_CMPL_DOUBLE: /* 0x2f */
1413 /* File: armv5te/OP_CMPL_DOUBLE.S */
1414     /*
1415      * Compare two floating-point values.  Puts 0, 1, or -1 into the
1416      * destination register based on the results of the comparison.
1417      *
1418      * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1419      * on what value we'd like to return when one of the operands is NaN.
1420      *
1421      * See OP_CMPL_FLOAT for an explanation.
1422      *
1423      * For: cmpl-double, cmpg-double
1424      */
1425     /* op vAA, vBB, vCC */
1426     FETCH(r0, 1)                        @ r0<- CCBB
1427     and     r9, r0, #255                @ r9<- BB
1428     mov     r10, r0, lsr #8             @ r10<- CC
1429     add     r9, rFP, r9, lsl #2         @ r9<- &fp[BB]
1430     add     r10, rFP, r10, lsl #2       @ r10<- &fp[CC]
1431     ldmia   r9, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1432     ldmia   r10, {r2-r3}                @ r2/r3<- vCC/vCC+1
1433     bl      __aeabi_cdcmple             @ cmp <=: C clear if <, Z set if eq
1434     bhi     .LOP_CMPL_DOUBLE_gt_or_nan       @ C set and Z clear, disambiguate
1435     mvncc   r1, #0                      @ (less than) r1<- -1
1436     moveq   r1, #0                      @ (equal) r1<- 0, trumps less than
1437 .LOP_CMPL_DOUBLE_finish:
1438     mov     r3, rINST, lsr #8           @ r3<- AA
1439     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1440     SET_VREG(r1, r3)                    @ vAA<- r1
1441     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1442     GOTO_OPCODE(ip)                     @ jump to next instruction
1443
1444 /* ------------------------------ */
1445     .balign 64
1446 .L_OP_CMPG_DOUBLE: /* 0x30 */
1447 /* File: armv5te/OP_CMPG_DOUBLE.S */
1448 /* File: armv5te/OP_CMPL_DOUBLE.S */
1449     /*
1450      * Compare two floating-point values.  Puts 0, 1, or -1 into the
1451      * destination register based on the results of the comparison.
1452      *
1453      * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1454      * on what value we'd like to return when one of the operands is NaN.
1455      *
1456      * See OP_CMPL_FLOAT for an explanation.
1457      *
1458      * For: cmpl-double, cmpg-double
1459      */
1460     /* op vAA, vBB, vCC */
1461     FETCH(r0, 1)                        @ r0<- CCBB
1462     and     r9, r0, #255                @ r9<- BB
1463     mov     r10, r0, lsr #8             @ r10<- CC
1464     add     r9, rFP, r9, lsl #2         @ r9<- &fp[BB]
1465     add     r10, rFP, r10, lsl #2       @ r10<- &fp[CC]
1466     ldmia   r9, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1467     ldmia   r10, {r2-r3}                @ r2/r3<- vCC/vCC+1
1468     bl      __aeabi_cdcmple             @ cmp <=: C clear if <, Z set if eq
1469     bhi     .LOP_CMPG_DOUBLE_gt_or_nan       @ C set and Z clear, disambiguate
1470     mvncc   r1, #0                      @ (less than) r1<- -1
1471     moveq   r1, #0                      @ (equal) r1<- 0, trumps less than
1472 .LOP_CMPG_DOUBLE_finish:
1473     mov     r3, rINST, lsr #8           @ r3<- AA
1474     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1475     SET_VREG(r1, r3)                    @ vAA<- r1
1476     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1477     GOTO_OPCODE(ip)                     @ jump to next instruction
1478
1479
1480 /* ------------------------------ */
1481     .balign 64
1482 .L_OP_CMP_LONG: /* 0x31 */
1483 /* File: armv5te/OP_CMP_LONG.S */
1484     /*
1485      * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
1486      * register based on the results of the comparison.
1487      *
1488      * We load the full values with LDM, but in practice many values could
1489      * be resolved by only looking at the high word.  This could be made
1490      * faster or slower by splitting the LDM into a pair of LDRs.
1491      *
1492      * If we just wanted to set condition flags, we could do this:
1493      *  subs    ip, r0, r2
1494      *  sbcs    ip, r1, r3
1495      *  subeqs  ip, r0, r2
1496      * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
1497      * integer value, which we can do with 2 conditional mov/mvn instructions
1498      * (set 1, set -1; if they're equal we already have 0 in ip), giving
1499      * us a constant 5-cycle path plus a branch at the end to the
1500      * instruction epilogue code.  The multi-compare approach below needs
1501      * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
1502      * in the worst case (the 64-bit values are equal).
1503      */
1504     /* cmp-long vAA, vBB, vCC */
1505     FETCH(r0, 1)                        @ r0<- CCBB
1506     mov     r9, rINST, lsr #8           @ r9<- AA
1507     and     r2, r0, #255                @ r2<- BB
1508     mov     r3, r0, lsr #8              @ r3<- CC
1509     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
1510     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
1511     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1512     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
1513     cmp     r1, r3                      @ compare (vBB+1, vCC+1)
1514     blt     .LOP_CMP_LONG_less            @ signed compare on high part
1515     bgt     .LOP_CMP_LONG_greater
1516     subs    r1, r0, r2                  @ r1<- r0 - r2
1517     bhi     .LOP_CMP_LONG_greater         @ unsigned compare on low part
1518     bne     .LOP_CMP_LONG_less
1519     b       .LOP_CMP_LONG_finish          @ equal; r1 already holds 0
1520
1521 /* ------------------------------ */
1522     .balign 64
1523 .L_OP_IF_EQ: /* 0x32 */
1524 /* File: armv5te/OP_IF_EQ.S */
1525 /* File: armv5te/bincmp.S */
1526     /*
1527      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1528      * fragment that specifies the *reverse* comparison to perform, e.g.
1529      * for "if-le" you would use "gt".
1530      *
1531      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1532      */
1533     /* if-cmp vA, vB, +CCCC */
1534     mov     r0, rINST, lsr #8           @ r0<- A+
1535     mov     r1, rINST, lsr #12          @ r1<- B
1536     and     r0, r0, #15
1537     GET_VREG(r3, r1)                    @ r3<- vB
1538     GET_VREG(r2, r0)                    @ r2<- vA
1539     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1540     cmp     r2, r3                      @ compare (vA, vB)
1541     bne  1f                      @ branch to 1 if comparison failed
1542     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1543     movs    r9, r9, asl #1              @ convert to bytes, check sign
1544     bmi     common_backwardBranch       @ yes, do periodic checks
1545 1:
1546 #if defined(WITH_JIT)
1547     GET_JIT_PROF_TABLE(r0)
1548     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1549     b        common_testUpdateProfile
1550 #else
1551     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1552     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1553     GOTO_OPCODE(ip)                     @ jump to next instruction
1554 #endif
1555
1556
1557
1558 /* ------------------------------ */
1559     .balign 64
1560 .L_OP_IF_NE: /* 0x33 */
1561 /* File: armv5te/OP_IF_NE.S */
1562 /* File: armv5te/bincmp.S */
1563     /*
1564      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1565      * fragment that specifies the *reverse* comparison to perform, e.g.
1566      * for "if-le" you would use "gt".
1567      *
1568      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1569      */
1570     /* if-cmp vA, vB, +CCCC */
1571     mov     r0, rINST, lsr #8           @ r0<- A+
1572     mov     r1, rINST, lsr #12          @ r1<- B
1573     and     r0, r0, #15
1574     GET_VREG(r3, r1)                    @ r3<- vB
1575     GET_VREG(r2, r0)                    @ r2<- vA
1576     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1577     cmp     r2, r3                      @ compare (vA, vB)
1578     beq  1f                      @ branch to 1 if comparison failed
1579     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1580     movs    r9, r9, asl #1              @ convert to bytes, check sign
1581     bmi     common_backwardBranch       @ yes, do periodic checks
1582 1:
1583 #if defined(WITH_JIT)
1584     GET_JIT_PROF_TABLE(r0)
1585     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1586     b        common_testUpdateProfile
1587 #else
1588     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1589     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1590     GOTO_OPCODE(ip)                     @ jump to next instruction
1591 #endif
1592
1593
1594
1595 /* ------------------------------ */
1596     .balign 64
1597 .L_OP_IF_LT: /* 0x34 */
1598 /* File: armv5te/OP_IF_LT.S */
1599 /* File: armv5te/bincmp.S */
1600     /*
1601      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1602      * fragment that specifies the *reverse* comparison to perform, e.g.
1603      * for "if-le" you would use "gt".
1604      *
1605      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1606      */
1607     /* if-cmp vA, vB, +CCCC */
1608     mov     r0, rINST, lsr #8           @ r0<- A+
1609     mov     r1, rINST, lsr #12          @ r1<- B
1610     and     r0, r0, #15
1611     GET_VREG(r3, r1)                    @ r3<- vB
1612     GET_VREG(r2, r0)                    @ r2<- vA
1613     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1614     cmp     r2, r3                      @ compare (vA, vB)
1615     bge  1f                      @ branch to 1 if comparison failed
1616     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1617     movs    r9, r9, asl #1              @ convert to bytes, check sign
1618     bmi     common_backwardBranch       @ yes, do periodic checks
1619 1:
1620 #if defined(WITH_JIT)
1621     GET_JIT_PROF_TABLE(r0)
1622     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1623     b        common_testUpdateProfile
1624 #else
1625     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1626     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1627     GOTO_OPCODE(ip)                     @ jump to next instruction
1628 #endif
1629
1630
1631
1632 /* ------------------------------ */
1633     .balign 64
1634 .L_OP_IF_GE: /* 0x35 */
1635 /* File: armv5te/OP_IF_GE.S */
1636 /* File: armv5te/bincmp.S */
1637     /*
1638      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1639      * fragment that specifies the *reverse* comparison to perform, e.g.
1640      * for "if-le" you would use "gt".
1641      *
1642      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1643      */
1644     /* if-cmp vA, vB, +CCCC */
1645     mov     r0, rINST, lsr #8           @ r0<- A+
1646     mov     r1, rINST, lsr #12          @ r1<- B
1647     and     r0, r0, #15
1648     GET_VREG(r3, r1)                    @ r3<- vB
1649     GET_VREG(r2, r0)                    @ r2<- vA
1650     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1651     cmp     r2, r3                      @ compare (vA, vB)
1652     blt  1f                      @ branch to 1 if comparison failed
1653     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1654     movs    r9, r9, asl #1              @ convert to bytes, check sign
1655     bmi     common_backwardBranch       @ yes, do periodic checks
1656 1:
1657 #if defined(WITH_JIT)
1658     GET_JIT_PROF_TABLE(r0)
1659     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1660     b        common_testUpdateProfile
1661 #else
1662     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1663     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1664     GOTO_OPCODE(ip)                     @ jump to next instruction
1665 #endif
1666
1667
1668
1669 /* ------------------------------ */
1670     .balign 64
1671 .L_OP_IF_GT: /* 0x36 */
1672 /* File: armv5te/OP_IF_GT.S */
1673 /* File: armv5te/bincmp.S */
1674     /*
1675      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1676      * fragment that specifies the *reverse* comparison to perform, e.g.
1677      * for "if-le" you would use "gt".
1678      *
1679      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1680      */
1681     /* if-cmp vA, vB, +CCCC */
1682     mov     r0, rINST, lsr #8           @ r0<- A+
1683     mov     r1, rINST, lsr #12          @ r1<- B
1684     and     r0, r0, #15
1685     GET_VREG(r3, r1)                    @ r3<- vB
1686     GET_VREG(r2, r0)                    @ r2<- vA
1687     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1688     cmp     r2, r3                      @ compare (vA, vB)
1689     ble  1f                      @ branch to 1 if comparison failed
1690     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1691     movs    r9, r9, asl #1              @ convert to bytes, check sign
1692     bmi     common_backwardBranch       @ yes, do periodic checks
1693 1:
1694 #if defined(WITH_JIT)
1695     GET_JIT_PROF_TABLE(r0)
1696     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1697     b        common_testUpdateProfile
1698 #else
1699     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1700     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1701     GOTO_OPCODE(ip)                     @ jump to next instruction
1702 #endif
1703
1704
1705
1706 /* ------------------------------ */
1707     .balign 64
1708 .L_OP_IF_LE: /* 0x37 */
1709 /* File: armv5te/OP_IF_LE.S */
1710 /* File: armv5te/bincmp.S */
1711     /*
1712      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1713      * fragment that specifies the *reverse* comparison to perform, e.g.
1714      * for "if-le" you would use "gt".
1715      *
1716      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1717      */
1718     /* if-cmp vA, vB, +CCCC */
1719     mov     r0, rINST, lsr #8           @ r0<- A+
1720     mov     r1, rINST, lsr #12          @ r1<- B
1721     and     r0, r0, #15
1722     GET_VREG(r3, r1)                    @ r3<- vB
1723     GET_VREG(r2, r0)                    @ r2<- vA
1724     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1725     cmp     r2, r3                      @ compare (vA, vB)
1726     bgt  1f                      @ branch to 1 if comparison failed
1727     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1728     movs    r9, r9, asl #1              @ convert to bytes, check sign
1729     bmi     common_backwardBranch       @ yes, do periodic checks
1730 1:
1731 #if defined(WITH_JIT)
1732     GET_JIT_PROF_TABLE(r0)
1733     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1734     b        common_testUpdateProfile
1735 #else
1736     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1737     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1738     GOTO_OPCODE(ip)                     @ jump to next instruction
1739 #endif
1740
1741
1742
1743 /* ------------------------------ */
1744     .balign 64
1745 .L_OP_IF_EQZ: /* 0x38 */
1746 /* File: armv5te/OP_IF_EQZ.S */
1747 /* File: armv5te/zcmp.S */
1748     /*
1749      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1750      * fragment that specifies the *reverse* comparison to perform, e.g.
1751      * for "if-le" you would use "gt".
1752      *
1753      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1754      */
1755     /* if-cmp vAA, +BBBB */
1756     mov     r0, rINST, lsr #8           @ r0<- AA
1757     GET_VREG(r2, r0)                    @ r2<- vAA
1758     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1759     cmp     r2, #0                      @ compare (vA, 0)
1760     bne  1f                      @ branch to 1 if comparison failed
1761     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1762     movs    r9, r9, asl #1              @ convert to bytes, check sign
1763     bmi     common_backwardBranch       @ backward branch, do periodic checks
1764 1:
1765 #if defined(WITH_JIT)
1766     GET_JIT_PROF_TABLE(r0)
1767     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1768     cmp     r0,#0
1769     bne     common_updateProfile
1770     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1771     GOTO_OPCODE(ip)                     @ jump to next instruction
1772 #else
1773     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1774     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1775     GOTO_OPCODE(ip)                     @ jump to next instruction
1776 #endif
1777
1778
1779
1780 /* ------------------------------ */
1781     .balign 64
1782 .L_OP_IF_NEZ: /* 0x39 */
1783 /* File: armv5te/OP_IF_NEZ.S */
1784 /* File: armv5te/zcmp.S */
1785     /*
1786      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1787      * fragment that specifies the *reverse* comparison to perform, e.g.
1788      * for "if-le" you would use "gt".
1789      *
1790      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1791      */
1792     /* if-cmp vAA, +BBBB */
1793     mov     r0, rINST, lsr #8           @ r0<- AA
1794     GET_VREG(r2, r0)                    @ r2<- vAA
1795     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1796     cmp     r2, #0                      @ compare (vA, 0)
1797     beq  1f                      @ branch to 1 if comparison failed
1798     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1799     movs    r9, r9, asl #1              @ convert to bytes, check sign
1800     bmi     common_backwardBranch       @ backward branch, do periodic checks
1801 1:
1802 #if defined(WITH_JIT)
1803     GET_JIT_PROF_TABLE(r0)
1804     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1805     cmp     r0,#0
1806     bne     common_updateProfile
1807     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1808     GOTO_OPCODE(ip)                     @ jump to next instruction
1809 #else
1810     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1811     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1812     GOTO_OPCODE(ip)                     @ jump to next instruction
1813 #endif
1814
1815
1816
1817 /* ------------------------------ */
1818     .balign 64
1819 .L_OP_IF_LTZ: /* 0x3a */
1820 /* File: armv5te/OP_IF_LTZ.S */
1821 /* File: armv5te/zcmp.S */
1822     /*
1823      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1824      * fragment that specifies the *reverse* comparison to perform, e.g.
1825      * for "if-le" you would use "gt".
1826      *
1827      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1828      */
1829     /* if-cmp vAA, +BBBB */
1830     mov     r0, rINST, lsr #8           @ r0<- AA
1831     GET_VREG(r2, r0)                    @ r2<- vAA
1832     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1833     cmp     r2, #0                      @ compare (vA, 0)
1834     bge  1f                      @ branch to 1 if comparison failed
1835     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1836     movs    r9, r9, asl #1              @ convert to bytes, check sign
1837     bmi     common_backwardBranch       @ backward branch, do periodic checks
1838 1:
1839 #if defined(WITH_JIT)
1840     GET_JIT_PROF_TABLE(r0)
1841     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1842     cmp     r0,#0
1843     bne     common_updateProfile
1844     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1845     GOTO_OPCODE(ip)                     @ jump to next instruction
1846 #else
1847     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1848     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1849     GOTO_OPCODE(ip)                     @ jump to next instruction
1850 #endif
1851
1852
1853
1854 /* ------------------------------ */
1855     .balign 64
1856 .L_OP_IF_GEZ: /* 0x3b */
1857 /* File: armv5te/OP_IF_GEZ.S */
1858 /* File: armv5te/zcmp.S */
1859     /*
1860      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1861      * fragment that specifies the *reverse* comparison to perform, e.g.
1862      * for "if-le" you would use "gt".
1863      *
1864      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1865      */
1866     /* if-cmp vAA, +BBBB */
1867     mov     r0, rINST, lsr #8           @ r0<- AA
1868     GET_VREG(r2, r0)                    @ r2<- vAA
1869     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1870     cmp     r2, #0                      @ compare (vA, 0)
1871     blt  1f                      @ branch to 1 if comparison failed
1872     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1873     movs    r9, r9, asl #1              @ convert to bytes, check sign
1874     bmi     common_backwardBranch       @ backward branch, do periodic checks
1875 1:
1876 #if defined(WITH_JIT)
1877     GET_JIT_PROF_TABLE(r0)
1878     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1879     cmp     r0,#0
1880     bne     common_updateProfile
1881     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1882     GOTO_OPCODE(ip)                     @ jump to next instruction
1883 #else
1884     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1885     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1886     GOTO_OPCODE(ip)                     @ jump to next instruction
1887 #endif
1888
1889
1890
1891 /* ------------------------------ */
1892     .balign 64
1893 .L_OP_IF_GTZ: /* 0x3c */
1894 /* File: armv5te/OP_IF_GTZ.S */
1895 /* File: armv5te/zcmp.S */
1896     /*
1897      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1898      * fragment that specifies the *reverse* comparison to perform, e.g.
1899      * for "if-le" you would use "gt".
1900      *
1901      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1902      */
1903     /* if-cmp vAA, +BBBB */
1904     mov     r0, rINST, lsr #8           @ r0<- AA
1905     GET_VREG(r2, r0)                    @ r2<- vAA
1906     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1907     cmp     r2, #0                      @ compare (vA, 0)
1908     ble  1f                      @ branch to 1 if comparison failed
1909     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1910     movs    r9, r9, asl #1              @ convert to bytes, check sign
1911     bmi     common_backwardBranch       @ backward branch, do periodic checks
1912 1:
1913 #if defined(WITH_JIT)
1914     GET_JIT_PROF_TABLE(r0)
1915     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1916     cmp     r0,#0
1917     bne     common_updateProfile
1918     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1919     GOTO_OPCODE(ip)                     @ jump to next instruction
1920 #else
1921     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1922     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1923     GOTO_OPCODE(ip)                     @ jump to next instruction
1924 #endif
1925
1926
1927
1928 /* ------------------------------ */
1929     .balign 64
1930 .L_OP_IF_LEZ: /* 0x3d */
1931 /* File: armv5te/OP_IF_LEZ.S */
1932 /* File: armv5te/zcmp.S */
1933     /*
1934      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1935      * fragment that specifies the *reverse* comparison to perform, e.g.
1936      * for "if-le" you would use "gt".
1937      *
1938      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1939      */
1940     /* if-cmp vAA, +BBBB */
1941     mov     r0, rINST, lsr #8           @ r0<- AA
1942     GET_VREG(r2, r0)                    @ r2<- vAA
1943     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1944     cmp     r2, #0                      @ compare (vA, 0)
1945     bgt  1f                      @ branch to 1 if comparison failed
1946     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1947     movs    r9, r9, asl #1              @ convert to bytes, check sign
1948     bmi     common_backwardBranch       @ backward branch, do periodic checks
1949 1:
1950 #if defined(WITH_JIT)
1951     GET_JIT_PROF_TABLE(r0)
1952     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1953     cmp     r0,#0
1954     bne     common_updateProfile
1955     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1956     GOTO_OPCODE(ip)                     @ jump to next instruction
1957 #else
1958     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1959     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1960     GOTO_OPCODE(ip)                     @ jump to next instruction
1961 #endif
1962
1963
1964
1965 /* ------------------------------ */
1966     .balign 64
1967 .L_OP_UNUSED_3E: /* 0x3e */
1968 /* File: armv5te/OP_UNUSED_3E.S */
1969 /* File: armv5te/unused.S */
1970     bl      common_abort
1971
1972
1973
1974 /* ------------------------------ */
1975     .balign 64
1976 .L_OP_UNUSED_3F: /* 0x3f */
1977 /* File: armv5te/OP_UNUSED_3F.S */
1978 /* File: armv5te/unused.S */
1979     bl      common_abort
1980
1981
1982
1983 /* ------------------------------ */
1984     .balign 64
1985 .L_OP_UNUSED_40: /* 0x40 */
1986 /* File: armv5te/OP_UNUSED_40.S */
1987 /* File: armv5te/unused.S */
1988     bl      common_abort
1989
1990
1991
1992 /* ------------------------------ */
1993     .balign 64
1994 .L_OP_UNUSED_41: /* 0x41 */
1995 /* File: armv5te/OP_UNUSED_41.S */
1996 /* File: armv5te/unused.S */
1997     bl      common_abort
1998
1999
2000
2001 /* ------------------------------ */
2002     .balign 64
2003 .L_OP_UNUSED_42: /* 0x42 */
2004 /* File: armv5te/OP_UNUSED_42.S */
2005 /* File: armv5te/unused.S */
2006     bl      common_abort
2007
2008
2009
2010 /* ------------------------------ */
2011     .balign 64
2012 .L_OP_UNUSED_43: /* 0x43 */
2013 /* File: armv5te/OP_UNUSED_43.S */
2014 /* File: armv5te/unused.S */
2015     bl      common_abort
2016
2017
2018
2019 /* ------------------------------ */
2020     .balign 64
2021 .L_OP_AGET: /* 0x44 */
2022 /* File: armv5te/OP_AGET.S */
2023     /*
2024      * Array get, 32 bits or less.  vAA <- vBB[vCC].
2025      *
2026      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2027      * instructions.  We use a pair of FETCH_Bs instead.
2028      *
2029      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2030      */
2031     /* op vAA, vBB, vCC */
2032     FETCH_B(r2, 1, 0)                   @ r2<- BB
2033     mov     r9, rINST, lsr #8           @ r9<- AA
2034     FETCH_B(r3, 1, 1)                   @ r3<- CC
2035     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2036     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2037     cmp     r0, #0                      @ null array object?
2038     beq     common_errNullObject        @ yes, bail
2039     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2040     add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2041     cmp     r1, r3                      @ compare unsigned index, length
2042     bcs     common_errArrayIndex        @ index >= length, bail
2043     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2044     ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2045     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2046     SET_VREG(r2, r9)                    @ vAA<- r2
2047     GOTO_OPCODE(ip)                     @ jump to next instruction
2048
2049
2050 /* ------------------------------ */
2051     .balign 64
2052 .L_OP_AGET_WIDE: /* 0x45 */
2053 /* File: armv5te/OP_AGET_WIDE.S */
2054     /*
2055      * Array get, 64 bits.  vAA <- vBB[vCC].
2056      *
2057      * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD.
2058      */
2059     /* aget-wide vAA, vBB, vCC */
2060     FETCH(r0, 1)                        @ r0<- CCBB
2061     mov     r9, rINST, lsr #8           @ r9<- AA
2062     and     r2, r0, #255                @ r2<- BB
2063     mov     r3, r0, lsr #8              @ r3<- CC
2064     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2065     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2066     cmp     r0, #0                      @ null array object?
2067     beq     common_errNullObject        @ yes, bail
2068     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2069     add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2070     cmp     r1, r3                      @ compare unsigned index, length
2071     bcc     .LOP_AGET_WIDE_finish          @ okay, continue below
2072     b       common_errArrayIndex        @ index >= length, bail
2073     @ May want to swap the order of these two branches depending on how the
2074     @ branch prediction (if any) handles conditional forward branches vs.
2075     @ unconditional forward branches.
2076
2077 /* ------------------------------ */
2078     .balign 64
2079 .L_OP_AGET_OBJECT: /* 0x46 */
2080 /* File: armv5te/OP_AGET_OBJECT.S */
2081 /* File: armv5te/OP_AGET.S */
2082     /*
2083      * Array get, 32 bits or less.  vAA <- vBB[vCC].
2084      *
2085      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2086      * instructions.  We use a pair of FETCH_Bs instead.
2087      *
2088      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2089      */
2090     /* op vAA, vBB, vCC */
2091     FETCH_B(r2, 1, 0)                   @ r2<- BB
2092     mov     r9, rINST, lsr #8           @ r9<- AA
2093     FETCH_B(r3, 1, 1)                   @ r3<- CC
2094     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2095     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2096     cmp     r0, #0                      @ null array object?
2097     beq     common_errNullObject        @ yes, bail
2098     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2099     add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2100     cmp     r1, r3                      @ compare unsigned index, length
2101     bcs     common_errArrayIndex        @ index >= length, bail
2102     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2103     ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2104     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2105     SET_VREG(r2, r9)                    @ vAA<- r2
2106     GOTO_OPCODE(ip)                     @ jump to next instruction
2107
2108
2109
2110 /* ------------------------------ */
2111     .balign 64
2112 .L_OP_AGET_BOOLEAN: /* 0x47 */
2113 /* File: armv5te/OP_AGET_BOOLEAN.S */
2114 /* File: armv5te/OP_AGET.S */
2115     /*
2116      * Array get, 32 bits or less.  vAA <- vBB[vCC].
2117      *
2118      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2119      * instructions.  We use a pair of FETCH_Bs instead.
2120      *
2121      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2122      */
2123     /* op vAA, vBB, vCC */
2124     FETCH_B(r2, 1, 0)                   @ r2<- BB
2125     mov     r9, rINST, lsr #8           @ r9<- AA
2126     FETCH_B(r3, 1, 1)                   @ r3<- CC
2127     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2128     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2129     cmp     r0, #0                      @ null array object?
2130     beq     common_errNullObject        @ yes, bail
2131     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2132     add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2133     cmp     r1, r3                      @ compare unsigned index, length
2134     bcs     common_errArrayIndex        @ index >= length, bail
2135     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2136     ldrb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2137     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2138     SET_VREG(r2, r9)                    @ vAA<- r2
2139     GOTO_OPCODE(ip)                     @ jump to next instruction
2140
2141
2142
2143 /* ------------------------------ */
2144     .balign 64
2145 .L_OP_AGET_BYTE: /* 0x48 */
2146 /* File: armv5te/OP_AGET_BYTE.S */
2147 /* File: armv5te/OP_AGET.S */
2148     /*
2149      * Array get, 32 bits or less.  vAA <- vBB[vCC].
2150      *
2151      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2152      * instructions.  We use a pair of FETCH_Bs instead.
2153      *
2154      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2155      */
2156     /* op vAA, vBB, vCC */
2157     FETCH_B(r2, 1, 0)                   @ r2<- BB
2158     mov     r9, rINST, lsr #8           @ r9<- AA
2159     FETCH_B(r3, 1, 1)                   @ r3<- CC
2160     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2161     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2162     cmp     r0, #0                      @ null array object?
2163     beq     common_errNullObject        @ yes, bail
2164     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2165     add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2166     cmp     r1, r3                      @ compare unsigned index, length
2167     bcs     common_errArrayIndex        @ index >= length, bail
2168     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2169     ldrsb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2170     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2171     SET_VREG(r2, r9)                    @ vAA<- r2
2172     GOTO_OPCODE(ip)                     @ jump to next instruction
2173
2174
2175
2176 /* ------------------------------ */
2177     .balign 64
2178 .L_OP_AGET_CHAR: /* 0x49 */
2179 /* File: armv5te/OP_AGET_CHAR.S */
2180 /* File: armv5te/OP_AGET.S */
2181     /*
2182      * Array get, 32 bits or less.  vAA <- vBB[vCC].
2183      *
2184      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2185      * instructions.  We use a pair of FETCH_Bs instead.
2186      *
2187      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2188      */
2189     /* op vAA, vBB, vCC */
2190     FETCH_B(r2, 1, 0)                   @ r2<- BB
2191     mov     r9, rINST, lsr #8           @ r9<- AA
2192     FETCH_B(r3, 1, 1)                   @ r3<- CC
2193     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2194     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2195     cmp     r0, #0                      @ null array object?
2196     beq     common_errNullObject        @ yes, bail
2197     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2198     add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2199     cmp     r1, r3                      @ compare unsigned index, length
2200     bcs     common_errArrayIndex        @ index >= length, bail
2201     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2202     ldrh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2203     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2204     SET_VREG(r2, r9)                    @ vAA<- r2
2205     GOTO_OPCODE(ip)                     @ jump to next instruction
2206
2207
2208
2209 /* ------------------------------ */
2210     .balign 64
2211 .L_OP_AGET_SHORT: /* 0x4a */
2212 /* File: armv5te/OP_AGET_SHORT.S */
2213 /* File: armv5te/OP_AGET.S */
2214     /*
2215      * Array get, 32 bits or less.  vAA <- vBB[vCC].
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: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-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 #1     @ 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     ldrsh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2236     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2237     SET_VREG(r2, r9)                    @ vAA<- r2
2238     GOTO_OPCODE(ip)                     @ jump to next instruction
2239
2240
2241
2242 /* ------------------------------ */
2243     .balign 64
2244 .L_OP_APUT: /* 0x4b */
2245 /* File: armv5te/OP_APUT.S */
2246     /*
2247      * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2248      *
2249      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2250      * instructions.  We use a pair of FETCH_Bs instead.
2251      *
2252      * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2253      */
2254     /* op vAA, vBB, vCC */
2255     FETCH_B(r2, 1, 0)                   @ r2<- BB
2256     mov     r9, rINST, lsr #8           @ r9<- AA
2257     FETCH_B(r3, 1, 1)                   @ r3<- CC
2258     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2259     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2260     cmp     r0, #0                      @ null array object?
2261     beq     common_errNullObject        @ yes, bail
2262     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2263     add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2264     cmp     r1, r3                      @ compare unsigned index, length
2265     bcs     common_errArrayIndex        @ index >= length, bail
2266     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2267     GET_VREG(r2, r9)                    @ r2<- vAA
2268     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2269     str  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2270     GOTO_OPCODE(ip)                     @ jump to next instruction
2271
2272
2273 /* ------------------------------ */
2274     .balign 64
2275 .L_OP_APUT_WIDE: /* 0x4c */
2276 /* File: armv5te/OP_APUT_WIDE.S */
2277     /*
2278      * Array put, 64 bits.  vBB[vCC] <- vAA.
2279      *
2280      * Arrays of long/double are 64-bit aligned, so it's okay to use STRD.
2281      */
2282     /* aput-wide vAA, vBB, vCC */
2283     FETCH(r0, 1)                        @ r0<- CCBB
2284     mov     r9, rINST, lsr #8           @ r9<- AA
2285     and     r2, r0, #255                @ r2<- BB
2286     mov     r3, r0, lsr #8              @ r3<- CC
2287     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2288     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2289     cmp     r0, #0                      @ null array object?
2290     beq     common_errNullObject        @ yes, bail
2291     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2292     add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2293     cmp     r1, r3                      @ compare unsigned index, length
2294     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2295     bcc     .LOP_APUT_WIDE_finish          @ okay, continue below
2296     b       common_errArrayIndex        @ index >= length, bail
2297     @ May want to swap the order of these two branches depending on how the
2298     @ branch prediction (if any) handles conditional forward branches vs.
2299     @ unconditional forward branches.
2300
2301 /* ------------------------------ */
2302     .balign 64
2303 .L_OP_APUT_OBJECT: /* 0x4d */
2304 /* File: armv5te/OP_APUT_OBJECT.S */
2305     /*
2306      * Store an object into an array.  vBB[vCC] <- vAA.
2307      *
2308      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2309      * instructions.  We use a pair of FETCH_Bs instead.
2310      */
2311     /* op vAA, vBB, vCC */
2312     FETCH(r0, 1)                        @ r0<- CCBB
2313     mov     r9, rINST, lsr #8           @ r9<- AA
2314     and     r2, r0, #255                @ r2<- BB
2315     mov     r3, r0, lsr #8              @ r3<- CC
2316     GET_VREG(r1, r2)                    @ r1<- vBB (array object)
2317     GET_VREG(r0, r3)                    @ r0<- vCC (requested index)
2318     cmp     r1, #0                      @ null array object?
2319     GET_VREG(r9, r9)                    @ r9<- vAA
2320     beq     common_errNullObject        @ yes, bail
2321     ldr     r3, [r1, #offArrayObject_length]    @ r3<- arrayObj->length
2322     add     r10, r1, r0, lsl #2         @ r10<- arrayObj + index*width
2323     cmp     r0, r3                      @ compare unsigned index, length
2324     bcc     .LOP_APUT_OBJECT_finish          @ we're okay, continue on
2325     b       common_errArrayIndex        @ index >= length, bail
2326
2327
2328 /* ------------------------------ */
2329     .balign 64
2330 .L_OP_APUT_BOOLEAN: /* 0x4e */
2331 /* File: armv5te/OP_APUT_BOOLEAN.S */
2332 /* File: armv5te/OP_APUT.S */
2333     /*
2334      * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2335      *
2336      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2337      * instructions.  We use a pair of FETCH_Bs instead.
2338      *
2339      * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2340      */
2341     /* op vAA, vBB, vCC */
2342     FETCH_B(r2, 1, 0)                   @ r2<- BB
2343     mov     r9, rINST, lsr #8           @ r9<- AA
2344     FETCH_B(r3, 1, 1)                   @ r3<- CC
2345     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2346     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2347     cmp     r0, #0                      @ null array object?
2348     beq     common_errNullObject        @ yes, bail
2349     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2350     add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2351     cmp     r1, r3                      @ compare unsigned index, length
2352     bcs     common_errArrayIndex        @ index >= length, bail
2353     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2354     GET_VREG(r2, r9)                    @ r2<- vAA
2355     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2356     strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2357     GOTO_OPCODE(ip)                     @ jump to next instruction
2358
2359
2360
2361 /* ------------------------------ */
2362     .balign 64
2363 .L_OP_APUT_BYTE: /* 0x4f */
2364 /* File: armv5te/OP_APUT_BYTE.S */
2365 /* File: armv5te/OP_APUT.S */
2366     /*
2367      * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2368      *
2369      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2370      * instructions.  We use a pair of FETCH_Bs instead.
2371      *
2372      * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2373      */
2374     /* op vAA, vBB, vCC */
2375     FETCH_B(r2, 1, 0)                   @ r2<- BB
2376     mov     r9, rINST, lsr #8           @ r9<- AA
2377     FETCH_B(r3, 1, 1)                   @ r3<- CC
2378     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2379     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2380     cmp     r0, #0                      @ null array object?
2381     beq     common_errNullObject        @ yes, bail
2382     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2383     add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2384     cmp     r1, r3                      @ compare unsigned index, length
2385     bcs     common_errArrayIndex        @ index >= length, bail
2386     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2387     GET_VREG(r2, r9)                    @ r2<- vAA
2388     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2389     strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2390     GOTO_OPCODE(ip)                     @ jump to next instruction
2391
2392
2393
2394 /* ------------------------------ */
2395     .balign 64
2396 .L_OP_APUT_CHAR: /* 0x50 */
2397 /* File: armv5te/OP_APUT_CHAR.S */
2398 /* File: armv5te/OP_APUT.S */
2399     /*
2400      * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2401      *
2402      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2403      * instructions.  We use a pair of FETCH_Bs instead.
2404      *
2405      * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2406      */
2407     /* op vAA, vBB, vCC */
2408     FETCH_B(r2, 1, 0)                   @ r2<- BB
2409     mov     r9, rINST, lsr #8           @ r9<- AA
2410     FETCH_B(r3, 1, 1)                   @ r3<- CC
2411     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2412     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2413     cmp     r0, #0                      @ null array object?
2414     beq     common_errNullObject        @ yes, bail
2415     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2416     add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2417     cmp     r1, r3                      @ compare unsigned index, length
2418     bcs     common_errArrayIndex        @ index >= length, bail
2419     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2420     GET_VREG(r2, r9)                    @ r2<- vAA
2421     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2422     strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2423     GOTO_OPCODE(ip)                     @ jump to next instruction
2424
2425
2426
2427 /* ------------------------------ */
2428     .balign 64
2429 .L_OP_APUT_SHORT: /* 0x51 */
2430 /* File: armv5te/OP_APUT_SHORT.S */
2431 /* File: armv5te/OP_APUT.S */
2432     /*
2433      * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2434      *
2435      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2436      * instructions.  We use a pair of FETCH_Bs instead.
2437      *
2438      * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2439      */
2440     /* op vAA, vBB, vCC */
2441     FETCH_B(r2, 1, 0)                   @ r2<- BB
2442     mov     r9, rINST, lsr #8           @ r9<- AA
2443     FETCH_B(r3, 1, 1)                   @ r3<- CC
2444     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2445     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2446     cmp     r0, #0                      @ null array object?
2447     beq     common_errNullObject        @ yes, bail
2448     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2449     add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2450     cmp     r1, r3                      @ compare unsigned index, length
2451     bcs     common_errArrayIndex        @ index >= length, bail
2452     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2453     GET_VREG(r2, r9)                    @ r2<- vAA
2454     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2455     strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2456     GOTO_OPCODE(ip)                     @ jump to next instruction
2457
2458
2459
2460 /* ------------------------------ */
2461     .balign 64
2462 .L_OP_IGET: /* 0x52 */
2463 /* File: armv5te/OP_IGET.S */
2464     /*
2465      * General 32-bit instance field get.
2466      *
2467      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2468      */
2469     /* op vA, vB, field@CCCC */
2470     mov     r0, rINST, lsr #12          @ r0<- B
2471     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2472     FETCH(r1, 1)                        @ r1<- field ref CCCC
2473     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2474     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2475     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2476     cmp     r0, #0                      @ is resolved entry null?
2477     bne     .LOP_IGET_finish          @ no, already resolved
2478 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2479     EXPORT_PC()                         @ resolve() could throw
2480     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2481     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2482     cmp     r0, #0
2483     bne     .LOP_IGET_finish
2484     b       common_exceptionThrown
2485
2486 /* ------------------------------ */
2487     .balign 64
2488 .L_OP_IGET_WIDE: /* 0x53 */
2489 /* File: armv5te/OP_IGET_WIDE.S */
2490     /*
2491      * Wide 32-bit instance field get.
2492      */
2493     /* iget-wide vA, vB, field@CCCC */
2494     mov     r0, rINST, lsr #12          @ r0<- B
2495     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2496     FETCH(r1, 1)                        @ r1<- field ref CCCC
2497     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2498     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2499     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2500     cmp     r0, #0                      @ is resolved entry null?
2501     bne     .LOP_IGET_WIDE_finish          @ no, already resolved
2502 8:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2503     EXPORT_PC()                         @ resolve() could throw
2504     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2505     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2506     cmp     r0, #0
2507     bne     .LOP_IGET_WIDE_finish
2508     b       common_exceptionThrown
2509
2510 /* ------------------------------ */
2511     .balign 64
2512 .L_OP_IGET_OBJECT: /* 0x54 */
2513 /* File: armv5te/OP_IGET_OBJECT.S */
2514 /* File: armv5te/OP_IGET.S */
2515     /*
2516      * General 32-bit instance field get.
2517      *
2518      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2519      */
2520     /* op vA, vB, field@CCCC */
2521     mov     r0, rINST, lsr #12          @ r0<- B
2522     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2523     FETCH(r1, 1)                        @ r1<- field ref CCCC
2524     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2525     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2526     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2527     cmp     r0, #0                      @ is resolved entry null?
2528     bne     .LOP_IGET_OBJECT_finish          @ no, already resolved
2529 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2530     EXPORT_PC()                         @ resolve() could throw
2531     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2532     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2533     cmp     r0, #0
2534     bne     .LOP_IGET_OBJECT_finish
2535     b       common_exceptionThrown
2536
2537
2538 /* ------------------------------ */
2539     .balign 64
2540 .L_OP_IGET_BOOLEAN: /* 0x55 */
2541 /* File: armv5te/OP_IGET_BOOLEAN.S */
2542 @include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" }
2543 /* File: armv5te/OP_IGET.S */
2544     /*
2545      * General 32-bit instance field get.
2546      *
2547      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2548      */
2549     /* op vA, vB, field@CCCC */
2550     mov     r0, rINST, lsr #12          @ r0<- B
2551     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2552     FETCH(r1, 1)                        @ r1<- field ref CCCC
2553     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2554     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2555     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2556     cmp     r0, #0                      @ is resolved entry null?
2557     bne     .LOP_IGET_BOOLEAN_finish          @ no, already resolved
2558 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2559     EXPORT_PC()                         @ resolve() could throw
2560     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2561     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2562     cmp     r0, #0
2563     bne     .LOP_IGET_BOOLEAN_finish
2564     b       common_exceptionThrown
2565
2566
2567 /* ------------------------------ */
2568     .balign 64
2569 .L_OP_IGET_BYTE: /* 0x56 */
2570 /* File: armv5te/OP_IGET_BYTE.S */
2571 @include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" }
2572 /* File: armv5te/OP_IGET.S */
2573     /*
2574      * General 32-bit instance field get.
2575      *
2576      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2577      */
2578     /* op vA, vB, field@CCCC */
2579     mov     r0, rINST, lsr #12          @ r0<- B
2580     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2581     FETCH(r1, 1)                        @ r1<- field ref CCCC
2582     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2583     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2584     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2585     cmp     r0, #0                      @ is resolved entry null?
2586     bne     .LOP_IGET_BYTE_finish          @ no, already resolved
2587 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2588     EXPORT_PC()                         @ resolve() could throw
2589     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2590     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2591     cmp     r0, #0
2592     bne     .LOP_IGET_BYTE_finish
2593     b       common_exceptionThrown
2594
2595
2596 /* ------------------------------ */
2597     .balign 64
2598 .L_OP_IGET_CHAR: /* 0x57 */
2599 /* File: armv5te/OP_IGET_CHAR.S */
2600 @include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" }
2601 /* File: armv5te/OP_IGET.S */
2602     /*
2603      * General 32-bit instance field get.
2604      *
2605      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2606      */
2607     /* op vA, vB, field@CCCC */
2608     mov     r0, rINST, lsr #12          @ r0<- B
2609     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2610     FETCH(r1, 1)                        @ r1<- field ref CCCC
2611     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2612     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2613     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2614     cmp     r0, #0                      @ is resolved entry null?
2615     bne     .LOP_IGET_CHAR_finish          @ no, already resolved
2616 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2617     EXPORT_PC()                         @ resolve() could throw
2618     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2619     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2620     cmp     r0, #0
2621     bne     .LOP_IGET_CHAR_finish
2622     b       common_exceptionThrown
2623
2624
2625 /* ------------------------------ */
2626     .balign 64
2627 .L_OP_IGET_SHORT: /* 0x58 */
2628 /* File: armv5te/OP_IGET_SHORT.S */
2629 @include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" }
2630 /* File: armv5te/OP_IGET.S */
2631     /*
2632      * General 32-bit instance field get.
2633      *
2634      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2635      */
2636     /* op vA, vB, field@CCCC */
2637     mov     r0, rINST, lsr #12          @ r0<- B
2638     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2639     FETCH(r1, 1)                        @ r1<- field ref CCCC
2640     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2641     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2642     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2643     cmp     r0, #0                      @ is resolved entry null?
2644     bne     .LOP_IGET_SHORT_finish          @ no, already resolved
2645 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2646     EXPORT_PC()                         @ resolve() could throw
2647     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2648     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2649     cmp     r0, #0
2650     bne     .LOP_IGET_SHORT_finish
2651     b       common_exceptionThrown
2652
2653
2654 /* ------------------------------ */
2655     .balign 64
2656 .L_OP_IPUT: /* 0x59 */
2657 /* File: armv5te/OP_IPUT.S */
2658     /*
2659      * General 32-bit instance field put.
2660      *
2661      * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2662      */
2663     /* op vA, vB, field@CCCC */
2664     mov     r0, rINST, lsr #12          @ r0<- B
2665     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2666     FETCH(r1, 1)                        @ r1<- field ref CCCC
2667     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2668     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2669     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2670     cmp     r0, #0                      @ is resolved entry null?
2671     bne     .LOP_IPUT_finish          @ no, already resolved
2672 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2673     EXPORT_PC()                         @ resolve() could throw
2674     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2675     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2676     cmp     r0, #0                      @ success?
2677     bne     .LOP_IPUT_finish          @ yes, finish up
2678     b       common_exceptionThrown
2679
2680 /* ------------------------------ */
2681     .balign 64
2682 .L_OP_IPUT_WIDE: /* 0x5a */
2683 /* File: armv5te/OP_IPUT_WIDE.S */
2684     /* iput-wide vA, vB, field@CCCC */
2685     mov     r0, rINST, lsr #12          @ r0<- B
2686     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2687     FETCH(r1, 1)                        @ r1<- field ref CCCC
2688     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2689     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2690     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2691     cmp     r0, #0                      @ is resolved entry null?
2692     bne     .LOP_IPUT_WIDE_finish          @ no, already resolved
2693 8:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2694     EXPORT_PC()                         @ resolve() could throw
2695     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2696     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2697     cmp     r0, #0                      @ success?
2698     bne     .LOP_IPUT_WIDE_finish          @ yes, finish up
2699     b       common_exceptionThrown
2700
2701 /* ------------------------------ */
2702     .balign 64
2703 .L_OP_IPUT_OBJECT: /* 0x5b */
2704 /* File: armv5te/OP_IPUT_OBJECT.S */
2705 /* File: armv5te/OP_IPUT.S */
2706     /*
2707      * General 32-bit instance field put.
2708      *
2709      * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2710      */
2711     /* op vA, vB, field@CCCC */
2712     mov     r0, rINST, lsr #12          @ r0<- B
2713     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2714     FETCH(r1, 1)                        @ r1<- field ref CCCC
2715     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2716     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2717     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2718     cmp     r0, #0                      @ is resolved entry null?
2719     bne     .LOP_IPUT_OBJECT_finish          @ no, already resolved
2720 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2721     EXPORT_PC()                         @ resolve() could throw
2722     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2723     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2724     cmp     r0, #0                      @ success?
2725     bne     .LOP_IPUT_OBJECT_finish          @ yes, finish up
2726     b       common_exceptionThrown
2727
2728
2729 /* ------------------------------ */
2730     .balign 64
2731 .L_OP_IPUT_BOOLEAN: /* 0x5c */
2732 /* File: armv5te/OP_IPUT_BOOLEAN.S */
2733 @include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" }
2734 /* File: armv5te/OP_IPUT.S */
2735     /*
2736      * General 32-bit instance field put.
2737      *
2738      * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2739      */
2740     /* op vA, vB, field@CCCC */
2741     mov     r0, rINST, lsr #12          @ r0<- B
2742     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2743     FETCH(r1, 1)                        @ r1<- field ref CCCC
2744     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2745     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2746     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2747     cmp     r0, #0                      @ is resolved entry null?
2748     bne     .LOP_IPUT_BOOLEAN_finish          @ no, already resolved
2749 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2750     EXPORT_PC()                         @ resolve() could throw
2751     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2752     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2753     cmp     r0, #0                      @ success?
2754     bne     .LOP_IPUT_BOOLEAN_finish          @ yes, finish up
2755     b       common_exceptionThrown
2756
2757
2758 /* ------------------------------ */
2759     .balign 64
2760 .L_OP_IPUT_BYTE: /* 0x5d */
2761 /* File: armv5te/OP_IPUT_BYTE.S */
2762 @include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" }
2763 /* File: armv5te/OP_IPUT.S */
2764     /*
2765      * General 32-bit instance field put.
2766      *
2767      * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2768      */
2769     /* op vA, vB, field@CCCC */
2770     mov     r0, rINST, lsr #12          @ r0<- B
2771     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2772     FETCH(r1, 1)                        @ r1<- field ref CCCC
2773     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2774     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2775     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2776     cmp     r0, #0                      @ is resolved entry null?
2777     bne     .LOP_IPUT_BYTE_finish          @ no, already resolved
2778 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2779     EXPORT_PC()                         @ resolve() could throw
2780     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2781     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2782     cmp     r0, #0                      @ success?
2783     bne     .LOP_IPUT_BYTE_finish          @ yes, finish up
2784     b       common_exceptionThrown
2785
2786
2787 /* ------------------------------ */
2788     .balign 64
2789 .L_OP_IPUT_CHAR: /* 0x5e */
2790 /* File: armv5te/OP_IPUT_CHAR.S */
2791 @include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" }
2792 /* File: armv5te/OP_IPUT.S */
2793     /*
2794      * General 32-bit instance field put.
2795      *
2796      * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2797      */
2798     /* op vA, vB, field@CCCC */
2799     mov     r0, rINST, lsr #12          @ r0<- B
2800     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2801     FETCH(r1, 1)                        @ r1<- field ref CCCC
2802     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2803     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2804     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2805     cmp     r0, #0                      @ is resolved entry null?
2806     bne     .LOP_IPUT_CHAR_finish          @ no, already resolved
2807 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2808     EXPORT_PC()                         @ resolve() could throw
2809     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2810     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2811     cmp     r0, #0                      @ success?
2812     bne     .LOP_IPUT_CHAR_finish          @ yes, finish up
2813     b       common_exceptionThrown
2814
2815
2816 /* ------------------------------ */
2817     .balign 64
2818 .L_OP_IPUT_SHORT: /* 0x5f */
2819 /* File: armv5te/OP_IPUT_SHORT.S */
2820 @include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" }
2821 /* File: armv5te/OP_IPUT.S */
2822     /*
2823      * General 32-bit instance field put.
2824      *
2825      * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2826      */
2827     /* op vA, vB, field@CCCC */
2828     mov     r0, rINST, lsr #12          @ r0<- B
2829     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2830     FETCH(r1, 1)                        @ r1<- field ref CCCC
2831     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2832     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2833     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2834     cmp     r0, #0                      @ is resolved entry null?
2835     bne     .LOP_IPUT_SHORT_finish          @ no, already resolved
2836 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2837     EXPORT_PC()                         @ resolve() could throw
2838     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2839     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2840     cmp     r0, #0                      @ success?
2841     bne     .LOP_IPUT_SHORT_finish          @ yes, finish up
2842     b       common_exceptionThrown
2843
2844
2845 /* ------------------------------ */
2846     .balign 64
2847 .L_OP_SGET: /* 0x60 */
2848 /* File: armv5te/OP_SGET.S */
2849     /*
2850      * General 32-bit SGET handler.
2851      *
2852      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2853      */
2854     /* op vAA, field@BBBB */
2855     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2856     FETCH(r1, 1)                        @ r1<- field ref BBBB
2857     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2858     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2859     cmp     r0, #0                      @ is resolved entry null?
2860     beq     .LOP_SGET_resolve         @ yes, do resolve
2861 .LOP_SGET_finish: @ field ptr in r0
2862     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2863     mov     r2, rINST, lsr #8           @ r2<- AA
2864     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2865     SET_VREG(r1, r2)                    @ fp[AA]<- r1
2866     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2867     GOTO_OPCODE(ip)                     @ jump to next instruction
2868
2869 /* ------------------------------ */
2870     .balign 64
2871 .L_OP_SGET_WIDE: /* 0x61 */
2872 /* File: armv5te/OP_SGET_WIDE.S */
2873     /*
2874      * 64-bit SGET handler.
2875      */
2876     /* sget-wide vAA, field@BBBB */
2877     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2878     FETCH(r1, 1)                        @ r1<- field ref BBBB
2879     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2880     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2881     cmp     r0, #0                      @ is resolved entry null?
2882     beq     .LOP_SGET_WIDE_resolve         @ yes, do resolve
2883 .LOP_SGET_WIDE_finish:
2884     mov     r1, rINST, lsr #8           @ r1<- AA
2885     ldrd    r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned)
2886     add     r1, rFP, r1, lsl #2         @ r1<- &fp[AA]
2887     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2888     stmia   r1, {r2-r3}                 @ vAA/vAA+1<- r2/r3
2889     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2890     GOTO_OPCODE(ip)                     @ jump to next instruction
2891
2892 /* ------------------------------ */
2893     .balign 64
2894 .L_OP_SGET_OBJECT: /* 0x62 */
2895 /* File: armv5te/OP_SGET_OBJECT.S */
2896 /* File: armv5te/OP_SGET.S */
2897     /*
2898      * General 32-bit SGET handler.
2899      *
2900      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2901      */
2902     /* op vAA, field@BBBB */
2903     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2904     FETCH(r1, 1)                        @ r1<- field ref BBBB
2905     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2906     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2907     cmp     r0, #0                      @ is resolved entry null?
2908     beq     .LOP_SGET_OBJECT_resolve         @ yes, do resolve
2909 .LOP_SGET_OBJECT_finish: @ field ptr in r0
2910     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2911     mov     r2, rINST, lsr #8           @ r2<- AA
2912     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2913     SET_VREG(r1, r2)                    @ fp[AA]<- r1
2914     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2915     GOTO_OPCODE(ip)                     @ jump to next instruction
2916
2917
2918 /* ------------------------------ */
2919     .balign 64
2920 .L_OP_SGET_BOOLEAN: /* 0x63 */
2921 /* File: armv5te/OP_SGET_BOOLEAN.S */
2922 /* File: armv5te/OP_SGET.S */
2923     /*
2924      * General 32-bit SGET handler.
2925      *
2926      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2927      */
2928     /* op vAA, field@BBBB */
2929     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2930     FETCH(r1, 1)                        @ r1<- field ref BBBB
2931     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2932     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2933     cmp     r0, #0                      @ is resolved entry null?
2934     beq     .LOP_SGET_BOOLEAN_resolve         @ yes, do resolve
2935 .LOP_SGET_BOOLEAN_finish: @ field ptr in r0
2936     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2937     mov     r2, rINST, lsr #8           @ r2<- AA
2938     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2939     SET_VREG(r1, r2)                    @ fp[AA]<- r1
2940     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2941     GOTO_OPCODE(ip)                     @ jump to next instruction
2942
2943
2944 /* ------------------------------ */
2945     .balign 64
2946 .L_OP_SGET_BYTE: /* 0x64 */
2947 /* File: armv5te/OP_SGET_BYTE.S */
2948 /* File: armv5te/OP_SGET.S */
2949     /*
2950      * General 32-bit SGET handler.
2951      *
2952      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2953      */
2954     /* op vAA, field@BBBB */
2955     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2956     FETCH(r1, 1)                        @ r1<- field ref BBBB
2957     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2958     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2959     cmp     r0, #0                      @ is resolved entry null?
2960     beq     .LOP_SGET_BYTE_resolve         @ yes, do resolve
2961 .LOP_SGET_BYTE_finish: @ field ptr in r0
2962     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2963     mov     r2, rINST, lsr #8           @ r2<- AA
2964     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2965     SET_VREG(r1, r2)                    @ fp[AA]<- r1
2966     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2967     GOTO_OPCODE(ip)                     @ jump to next instruction
2968
2969
2970 /* ------------------------------ */
2971     .balign 64
2972 .L_OP_SGET_CHAR: /* 0x65 */
2973 /* File: armv5te/OP_SGET_CHAR.S */
2974 /* File: armv5te/OP_SGET.S */
2975     /*
2976      * General 32-bit SGET handler.
2977      *
2978      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2979      */
2980     /* op vAA, field@BBBB */
2981     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2982     FETCH(r1, 1)                        @ r1<- field ref BBBB
2983     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2984     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2985     cmp     r0, #0                      @ is resolved entry null?
2986     beq     .LOP_SGET_CHAR_resolve         @ yes, do resolve
2987 .LOP_SGET_CHAR_finish: @ field ptr in r0
2988     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2989     mov     r2, rINST, lsr #8           @ r2<- AA
2990     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2991     SET_VREG(r1, r2)                    @ fp[AA]<- r1
2992     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2993     GOTO_OPCODE(ip)                     @ jump to next instruction
2994
2995
2996 /* ------------------------------ */
2997     .balign 64
2998 .L_OP_SGET_SHORT: /* 0x66 */
2999 /* File: armv5te/OP_SGET_SHORT.S */
3000 /* File: armv5te/OP_SGET.S */
3001     /*
3002      * General 32-bit SGET handler.
3003      *
3004      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
3005      */
3006     /* op vAA, field@BBBB */
3007     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3008     FETCH(r1, 1)                        @ r1<- field ref BBBB
3009     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3010     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3011     cmp     r0, #0                      @ is resolved entry null?
3012     beq     .LOP_SGET_SHORT_resolve         @ yes, do resolve
3013 .LOP_SGET_SHORT_finish: @ field ptr in r0
3014     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
3015     mov     r2, rINST, lsr #8           @ r2<- AA
3016     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3017     SET_VREG(r1, r2)                    @ fp[AA]<- r1
3018     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3019     GOTO_OPCODE(ip)                     @ jump to next instruction
3020
3021
3022 /* ------------------------------ */
3023     .balign 64
3024 .L_OP_SPUT: /* 0x67 */
3025 /* File: armv5te/OP_SPUT.S */
3026     /*
3027      * General 32-bit SPUT handler.
3028      *
3029      * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3030      */
3031     /* op vAA, field@BBBB */
3032     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3033     FETCH(r1, 1)                        @ r1<- field ref BBBB
3034     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3035     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3036     cmp     r0, #0                      @ is resolved entry null?
3037     beq     .LOP_SPUT_resolve         @ yes, do resolve
3038 .LOP_SPUT_finish:   @ field ptr in r0
3039     mov     r2, rINST, lsr #8           @ r2<- AA
3040     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3041     GET_VREG(r1, r2)                    @ r1<- fp[AA]
3042     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3043     str     r1, [r0, #offStaticField_value] @ field<- vAA
3044     GOTO_OPCODE(ip)                     @ jump to next instruction
3045
3046 /* ------------------------------ */
3047     .balign 64
3048 .L_OP_SPUT_WIDE: /* 0x68 */
3049 /* File: armv5te/OP_SPUT_WIDE.S */
3050     /*
3051      * 64-bit SPUT handler.
3052      */
3053     /* sput-wide vAA, field@BBBB */
3054     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3055     FETCH(r1, 1)                        @ r1<- field ref BBBB
3056     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3057     mov     r9, rINST, lsr #8           @ r9<- AA
3058     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3059     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
3060     cmp     r0, #0                      @ is resolved entry null?
3061     beq     .LOP_SPUT_WIDE_resolve         @ yes, do resolve
3062 .LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9
3063     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3064     ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
3065     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3066     strd    r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1
3067     GOTO_OPCODE(ip)                     @ jump to next instruction
3068
3069 /* ------------------------------ */
3070     .balign 64
3071 .L_OP_SPUT_OBJECT: /* 0x69 */
3072 /* File: armv5te/OP_SPUT_OBJECT.S */
3073 /* File: armv5te/OP_SPUT.S */
3074     /*
3075      * General 32-bit SPUT handler.
3076      *
3077      * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3078      */
3079     /* op vAA, field@BBBB */
3080     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3081     FETCH(r1, 1)                        @ r1<- field ref BBBB
3082     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3083     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3084     cmp     r0, #0                      @ is resolved entry null?
3085     beq     .LOP_SPUT_OBJECT_resolve         @ yes, do resolve
3086 .LOP_SPUT_OBJECT_finish:   @ field ptr in r0
3087     mov     r2, rINST, lsr #8           @ r2<- AA
3088     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3089     GET_VREG(r1, r2)                    @ r1<- fp[AA]
3090     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3091     str     r1, [r0, #offStaticField_value] @ field<- vAA
3092     GOTO_OPCODE(ip)                     @ jump to next instruction
3093
3094
3095 /* ------------------------------ */
3096     .balign 64
3097 .L_OP_SPUT_BOOLEAN: /* 0x6a */
3098 /* File: armv5te/OP_SPUT_BOOLEAN.S */
3099 /* File: armv5te/OP_SPUT.S */
3100     /*
3101      * General 32-bit SPUT handler.
3102      *
3103      * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3104      */
3105     /* op vAA, field@BBBB */
3106     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3107     FETCH(r1, 1)                        @ r1<- field ref BBBB
3108     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3109     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3110     cmp     r0, #0                      @ is resolved entry null?
3111     beq     .LOP_SPUT_BOOLEAN_resolve         @ yes, do resolve
3112 .LOP_SPUT_BOOLEAN_finish:   @ field ptr in r0
3113     mov     r2, rINST, lsr #8           @ r2<- AA
3114     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3115     GET_VREG(r1, r2)                    @ r1<- fp[AA]
3116     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3117     str     r1, [r0, #offStaticField_value] @ field<- vAA
3118     GOTO_OPCODE(ip)                     @ jump to next instruction
3119
3120
3121 /* ------------------------------ */
3122     .balign 64
3123 .L_OP_SPUT_BYTE: /* 0x6b */
3124 /* File: armv5te/OP_SPUT_BYTE.S */
3125 /* File: armv5te/OP_SPUT.S */
3126     /*
3127      * General 32-bit SPUT handler.
3128      *
3129      * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3130      */
3131     /* op vAA, field@BBBB */
3132     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3133     FETCH(r1, 1)                        @ r1<- field ref BBBB
3134     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3135     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3136     cmp     r0, #0                      @ is resolved entry null?
3137     beq     .LOP_SPUT_BYTE_resolve         @ yes, do resolve
3138 .LOP_SPUT_BYTE_finish:   @ field ptr in r0
3139     mov     r2, rINST, lsr #8           @ r2<- AA
3140     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3141     GET_VREG(r1, r2)                    @ r1<- fp[AA]
3142     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3143     str     r1, [r0, #offStaticField_value] @ field<- vAA
3144     GOTO_OPCODE(ip)                     @ jump to next instruction
3145
3146
3147 /* ------------------------------ */
3148     .balign 64
3149 .L_OP_SPUT_CHAR: /* 0x6c */
3150 /* File: armv5te/OP_SPUT_CHAR.S */
3151 /* File: armv5te/OP_SPUT.S */
3152     /*
3153      * General 32-bit SPUT handler.
3154      *
3155      * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3156      */
3157     /* op vAA, field@BBBB */
3158     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3159     FETCH(r1, 1)                        @ r1<- field ref BBBB
3160     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3161     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3162     cmp     r0, #0                      @ is resolved entry null?
3163     beq     .LOP_SPUT_CHAR_resolve         @ yes, do resolve
3164 .LOP_SPUT_CHAR_finish:   @ field ptr in r0
3165     mov     r2, rINST, lsr #8           @ r2<- AA
3166     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3167     GET_VREG(r1, r2)                    @ r1<- fp[AA]
3168     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3169     str     r1, [r0, #offStaticField_value] @ field<- vAA
3170     GOTO_OPCODE(ip)                     @ jump to next instruction
3171
3172
3173 /* ------------------------------ */
3174     .balign 64
3175 .L_OP_SPUT_SHORT: /* 0x6d */
3176 /* File: armv5te/OP_SPUT_SHORT.S */
3177 /* File: armv5te/OP_SPUT.S */
3178     /*
3179      * General 32-bit SPUT handler.
3180      *
3181      * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3182      */
3183     /* op vAA, field@BBBB */
3184     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3185     FETCH(r1, 1)                        @ r1<- field ref BBBB
3186     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3187     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3188     cmp     r0, #0                      @ is resolved entry null?
3189     beq     .LOP_SPUT_SHORT_resolve         @ yes, do resolve
3190 .LOP_SPUT_SHORT_finish:   @ field ptr in r0
3191     mov     r2, rINST, lsr #8           @ r2<- AA
3192     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3193     GET_VREG(r1, r2)                    @ r1<- fp[AA]
3194     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3195     str     r1, [r0, #offStaticField_value] @ field<- vAA
3196     GOTO_OPCODE(ip)                     @ jump to next instruction
3197
3198
3199 /* ------------------------------ */
3200     .balign 64
3201 .L_OP_INVOKE_VIRTUAL: /* 0x6e */
3202 /* File: armv5te/OP_INVOKE_VIRTUAL.S */
3203     /*
3204      * Handle a virtual method call.
3205      *
3206      * for: invoke-virtual, invoke-virtual/range
3207      */
3208     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3209     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3210     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3211     FETCH(r1, 1)                        @ r1<- BBBB
3212     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3213     FETCH(r10, 2)                       @ r10<- GFED or CCCC
3214     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3215     .if     (!0)
3216     and     r10, r10, #15               @ r10<- D (or stays CCCC)
3217     .endif
3218     cmp     r0, #0                      @ already resolved?
3219     EXPORT_PC()                         @ must export for invoke
3220     bne     .LOP_INVOKE_VIRTUAL_continue        @ yes, continue on
3221     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3222     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3223     mov     r2, #METHOD_VIRTUAL         @ resolver method type
3224     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3225     cmp     r0, #0                      @ got null?
3226     bne     .LOP_INVOKE_VIRTUAL_continue        @ no, continue
3227     b       common_exceptionThrown      @ yes, handle exception
3228
3229 /* ------------------------------ */
3230     .balign 64
3231 .L_OP_INVOKE_SUPER: /* 0x6f */
3232 /* File: armv5te/OP_INVOKE_SUPER.S */
3233     /*
3234      * Handle a "super" method call.
3235      *
3236      * for: invoke-super, invoke-super/range
3237      */
3238     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3239     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3240     FETCH(r10, 2)                       @ r10<- GFED or CCCC
3241     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3242     .if     (!0)
3243     and     r10, r10, #15               @ r10<- D (or stays CCCC)
3244     .endif
3245     FETCH(r1, 1)                        @ r1<- BBBB
3246     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3247     GET_VREG(r2, r10)                   @ r2<- "this" ptr
3248     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3249     cmp     r2, #0                      @ null "this"?
3250     ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3251     beq     common_errNullObject        @ null "this", throw exception
3252     cmp     r0, #0                      @ already resolved?
3253     ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3254     EXPORT_PC()                         @ must export for invoke
3255     bne     .LOP_INVOKE_SUPER_continue        @ resolved, continue on
3256     b       .LOP_INVOKE_SUPER_resolve         @ do resolve now
3257
3258 /* ------------------------------ */
3259     .balign 64
3260 .L_OP_INVOKE_DIRECT: /* 0x70 */
3261 /* File: armv5te/OP_INVOKE_DIRECT.S */
3262     /*
3263      * Handle a direct method call.
3264      *
3265      * (We could defer the "is 'this' pointer null" test to the common
3266      * method invocation code, and use a flag to indicate that static
3267      * calls don't count.  If we do this as part of copying the arguments
3268      * out we could avoiding loading the first arg twice.)
3269      *
3270      * for: invoke-direct, invoke-direct/range
3271      */
3272     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3273     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3274     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3275     FETCH(r1, 1)                        @ r1<- BBBB
3276     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3277     FETCH(r10, 2)                       @ r10<- GFED or CCCC
3278     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3279     .if     (!0)
3280     and     r10, r10, #15               @ r10<- D (or stays CCCC)
3281     .endif
3282     cmp     r0, #0                      @ already resolved?
3283     EXPORT_PC()                         @ must export for invoke
3284     GET_VREG(r2, r10)                   @ r2<- "this" ptr
3285     beq     .LOP_INVOKE_DIRECT_resolve         @ not resolved, do it now
3286 .LOP_INVOKE_DIRECT_finish:
3287     cmp     r2, #0                      @ null "this" ref?
3288     bne     common_invokeMethodNoRange   @ no, continue on
3289     b       common_errNullObject        @ yes, throw exception
3290
3291 /* ------------------------------ */
3292     .balign 64
3293 .L_OP_INVOKE_STATIC: /* 0x71 */
3294 /* File: armv5te/OP_INVOKE_STATIC.S */
3295     /*
3296      * Handle a static method call.
3297      *
3298      * for: invoke-static, invoke-static/range
3299      */
3300     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3301     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3302     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3303     FETCH(r1, 1)                        @ r1<- BBBB
3304     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3305     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3306     cmp     r0, #0                      @ already resolved?
3307     EXPORT_PC()                         @ must export for invoke
3308     bne     common_invokeMethodNoRange @ yes, continue on
3309 0:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3310     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3311     mov     r2, #METHOD_STATIC          @ resolver method type
3312     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3313     cmp     r0, #0                      @ got null?
3314     bne     common_invokeMethodNoRange @ no, continue
3315     b       common_exceptionThrown      @ yes, handle exception
3316
3317
3318 /* ------------------------------ */
3319     .balign 64
3320 .L_OP_INVOKE_INTERFACE: /* 0x72 */
3321 /* File: armv5te/OP_INVOKE_INTERFACE.S */
3322     /*
3323      * Handle an interface method call.
3324      *
3325      * for: invoke-interface, invoke-interface/range
3326      */
3327     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3328     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3329     FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3330     FETCH(r1, 1)                        @ r1<- BBBB
3331     .if     (!0)
3332     and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3333     .endif
3334     EXPORT_PC()                         @ must export for invoke
3335     GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3336     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3337     cmp     r0, #0                      @ null obj?
3338     ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3339     beq     common_errNullObject        @ yes, fail
3340     ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3341     bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3342     cmp     r0, #0                      @ failed?
3343     beq     common_exceptionThrown      @ yes, handle exception
3344     b       common_invokeMethodNoRange @ jump to common handler 
3345
3346
3347 /* ------------------------------ */
3348     .balign 64
3349 .L_OP_UNUSED_73: /* 0x73 */
3350 /* File: armv5te/OP_UNUSED_73.S */
3351 /* File: armv5te/unused.S */
3352     bl      common_abort
3353
3354
3355
3356 /* ------------------------------ */
3357     .balign 64
3358 .L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
3359 /* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */
3360 /* File: armv5te/OP_INVOKE_VIRTUAL.S */
3361     /*
3362      * Handle a virtual method call.
3363      *
3364      * for: invoke-virtual, invoke-virtual/range
3365      */
3366     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3367     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3368     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3369     FETCH(r1, 1)                        @ r1<- BBBB
3370     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3371     FETCH(r10, 2)                       @ r10<- GFED or CCCC
3372     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3373     .if     (!1)
3374     and     r10, r10, #15               @ r10<- D (or stays CCCC)
3375     .endif
3376     cmp     r0, #0                      @ already resolved?
3377     EXPORT_PC()                         @ must export for invoke
3378     bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ yes, continue on
3379     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3380     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3381     mov     r2, #METHOD_VIRTUAL         @ resolver method type
3382     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3383     cmp     r0, #0                      @ got null?
3384     bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ no, continue
3385     b       common_exceptionThrown      @ yes, handle exception
3386
3387
3388 /* ------------------------------ */
3389     .balign 64
3390 .L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
3391 /* File: armv5te/OP_INVOKE_SUPER_RANGE.S */
3392 /* File: armv5te/OP_INVOKE_SUPER.S */
3393     /*
3394      * Handle a "super" method call.
3395      *
3396      * for: invoke-super, invoke-super/range
3397      */
3398     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3399     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3400     FETCH(r10, 2)                       @ r10<- GFED or CCCC
3401     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3402     .if     (!1)
3403     and     r10, r10, #15               @ r10<- D (or stays CCCC)
3404     .endif
3405     FETCH(r1, 1)                        @ r1<- BBBB
3406     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3407     GET_VREG(r2, r10)                   @ r2<- "this" ptr
3408     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3409     cmp     r2, #0                      @ null "this"?
3410     ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3411     beq     common_errNullObject        @ null "this", throw exception
3412     cmp     r0, #0                      @ already resolved?
3413     ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3414     EXPORT_PC()                         @ must export for invoke
3415     bne     .LOP_INVOKE_SUPER_RANGE_continue        @ resolved, continue on
3416     b       .LOP_INVOKE_SUPER_RANGE_resolve         @ do resolve now
3417
3418
3419 /* ------------------------------ */
3420     .balign 64
3421 .L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
3422 /* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */
3423 /* File: armv5te/OP_INVOKE_DIRECT.S */
3424     /*
3425      * Handle a direct method call.
3426      *
3427      * (We could defer the "is 'this' pointer null" test to the common
3428      * method invocation code, and use a flag to indicate that static
3429      * calls don't count.  If we do this as part of copying the arguments
3430      * out we could avoiding loading the first arg twice.)
3431      *
3432      * for: invoke-direct, invoke-direct/range
3433      */
3434     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3435     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3436     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3437     FETCH(r1, 1)                        @ r1<- BBBB
3438     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3439     FETCH(r10, 2)                       @ r10<- GFED or CCCC
3440     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3441     .if     (!1)
3442     and     r10, r10, #15               @ r10<- D (or stays CCCC)
3443     .endif
3444     cmp     r0, #0                      @ already resolved?
3445     EXPORT_PC()                         @ must export for invoke
3446     GET_VREG(r2, r10)                   @ r2<- "this" ptr
3447     beq     .LOP_INVOKE_DIRECT_RANGE_resolve         @ not resolved, do it now
3448 .LOP_INVOKE_DIRECT_RANGE_finish:
3449     cmp     r2, #0                      @ null "this" ref?
3450     bne     common_invokeMethodRange   @ no, continue on
3451     b       common_errNullObject        @ yes, throw exception
3452
3453
3454 /* ------------------------------ */
3455     .balign 64
3456 .L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
3457 /* File: armv5te/OP_INVOKE_STATIC_RANGE.S */
3458 /* File: armv5te/OP_INVOKE_STATIC.S */
3459     /*
3460      * Handle a static method call.
3461      *
3462      * for: invoke-static, invoke-static/range
3463      */
3464     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3465     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3466     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3467     FETCH(r1, 1)                        @ r1<- BBBB
3468     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3469     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3470     cmp     r0, #0                      @ already resolved?
3471     EXPORT_PC()                         @ must export for invoke
3472     bne     common_invokeMethodRange @ yes, continue on
3473 0:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3474     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3475     mov     r2, #METHOD_STATIC          @ resolver method type
3476     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3477     cmp     r0, #0                      @ got null?
3478     bne     common_invokeMethodRange @ no, continue
3479     b       common_exceptionThrown      @ yes, handle exception
3480
3481
3482
3483 /* ------------------------------ */
3484     .balign 64
3485 .L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
3486 /* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */
3487 /* File: armv5te/OP_INVOKE_INTERFACE.S */
3488     /*
3489      * Handle an interface method call.
3490      *
3491      * for: invoke-interface, invoke-interface/range
3492      */
3493     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3494     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3495     FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3496     FETCH(r1, 1)                        @ r1<- BBBB
3497     .if     (!1)
3498     and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3499     .endif
3500     EXPORT_PC()                         @ must export for invoke
3501     GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3502     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3503     cmp     r0, #0                      @ null obj?
3504     ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3505     beq     common_errNullObject        @ yes, fail
3506     ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3507     bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3508     cmp     r0, #0                      @ failed?
3509     beq     common_exceptionThrown      @ yes, handle exception
3510     b       common_invokeMethodRange @ jump to common handler 
3511
3512
3513
3514 /* ------------------------------ */
3515     .balign 64
3516 .L_OP_UNUSED_79: /* 0x79 */
3517 /* File: armv5te/OP_UNUSED_79.S */
3518 /* File: armv5te/unused.S */
3519     bl      common_abort
3520
3521
3522
3523 /* ------------------------------ */
3524     .balign 64
3525 .L_OP_UNUSED_7A: /* 0x7a */
3526 /* File: armv5te/OP_UNUSED_7A.S */
3527 /* File: armv5te/unused.S */
3528     bl      common_abort
3529
3530
3531
3532 /* ------------------------------ */
3533     .balign 64
3534 .L_OP_NEG_INT: /* 0x7b */
3535 /* File: armv5te/OP_NEG_INT.S */
3536 /* File: armv5te/unop.S */
3537     /*
3538      * Generic 32-bit unary operation.  Provide an "instr" line that
3539      * specifies an instruction that performs "result = op r0".
3540      * This could be an ARM instruction or a function call.
3541      *
3542      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3543      *      int-to-byte, int-to-char, int-to-short
3544      */
3545     /* unop vA, vB */
3546     mov     r3, rINST, lsr #12          @ r3<- B
3547     mov     r9, rINST, lsr #8           @ r9<- A+
3548     GET_VREG(r0, r3)                    @ r0<- vB
3549     and     r9, r9, #15
3550                                @ optional op; may set condition codes
3551     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3552     rsb     r0, r0, #0                              @ r0<- op, r0-r3 changed
3553     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3554     SET_VREG(r0, r9)                    @ vAA<- r0
3555     GOTO_OPCODE(ip)                     @ jump to next instruction
3556     /* 9-10 instructions */
3557
3558
3559 /* ------------------------------ */
3560     .balign 64
3561 .L_OP_NOT_INT: /* 0x7c */
3562 /* File: armv5te/OP_NOT_INT.S */
3563 /* File: armv5te/unop.S */
3564     /*
3565      * Generic 32-bit unary operation.  Provide an "instr" line that
3566      * specifies an instruction that performs "result = op r0".
3567      * This could be an ARM instruction or a function call.
3568      *
3569      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3570      *      int-to-byte, int-to-char, int-to-short
3571      */
3572     /* unop vA, vB */
3573     mov     r3, rINST, lsr #12          @ r3<- B
3574     mov     r9, rINST, lsr #8           @ r9<- A+
3575     GET_VREG(r0, r3)                    @ r0<- vB
3576     and     r9, r9, #15
3577                                @ optional op; may set condition codes
3578     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3579     mvn     r0, r0                              @ r0<- op, r0-r3 changed
3580     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3581     SET_VREG(r0, r9)                    @ vAA<- r0
3582     GOTO_OPCODE(ip)                     @ jump to next instruction
3583     /* 9-10 instructions */
3584
3585
3586 /* ------------------------------ */
3587     .balign 64
3588 .L_OP_NEG_LONG: /* 0x7d */
3589 /* File: armv5te/OP_NEG_LONG.S */
3590 /* File: armv5te/unopWide.S */
3591     /*
3592      * Generic 64-bit unary operation.  Provide an "instr" line that
3593      * specifies an instruction that performs "result = op r0/r1".
3594      * This could be an ARM instruction or a function call.
3595      *
3596      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3597      */
3598     /* unop vA, vB */
3599     mov     r9, rINST, lsr #8           @ r9<- A+
3600     mov     r3, rINST, lsr #12          @ r3<- B
3601     and     r9, r9, #15
3602     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3603     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3604     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3605     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3606     rsbs    r0, r0, #0                           @ optional op; may set condition codes
3607     rsc     r1, r1, #0                              @ r0/r1<- op, r2-r3 changed
3608     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3609     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3610     GOTO_OPCODE(ip)                     @ jump to next instruction
3611     /* 12-13 instructions */
3612
3613
3614
3615 /* ------------------------------ */
3616     .balign 64
3617 .L_OP_NOT_LONG: /* 0x7e */
3618 /* File: armv5te/OP_NOT_LONG.S */
3619 /* File: armv5te/unopWide.S */
3620     /*
3621      * Generic 64-bit unary operation.  Provide an "instr" line that
3622      * specifies an instruction that performs "result = op r0/r1".
3623      * This could be an ARM instruction or a function call.
3624      *
3625      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3626      */
3627     /* unop vA, vB */
3628     mov     r9, rINST, lsr #8           @ r9<- A+
3629     mov     r3, rINST, lsr #12          @ r3<- B
3630     and     r9, r9, #15
3631     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3632     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3633     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3634     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3635     mvn     r0, r0                           @ optional op; may set condition codes
3636     mvn     r1, r1                              @ r0/r1<- op, r2-r3 changed
3637     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3638     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3639     GOTO_OPCODE(ip)                     @ jump to next instruction
3640     /* 12-13 instructions */
3641
3642
3643
3644 /* ------------------------------ */
3645     .balign 64
3646 .L_OP_NEG_FLOAT: /* 0x7f */
3647 /* File: armv5te/OP_NEG_FLOAT.S */
3648 /* File: armv5te/unop.S */
3649     /*
3650      * Generic 32-bit unary operation.  Provide an "instr" line that
3651      * specifies an instruction that performs "result = op r0".
3652      * This could be an ARM instruction or a function call.
3653      *
3654      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3655      *      int-to-byte, int-to-char, int-to-short
3656      */
3657     /* unop vA, vB */
3658     mov     r3, rINST, lsr #12          @ r3<- B
3659     mov     r9, rINST, lsr #8           @ r9<- A+
3660     GET_VREG(r0, r3)                    @ r0<- vB
3661     and     r9, r9, #15
3662                                @ optional op; may set condition codes
3663     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3664     add     r0, r0, #0x80000000                              @ r0<- op, r0-r3 changed
3665     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3666     SET_VREG(r0, r9)                    @ vAA<- r0
3667     GOTO_OPCODE(ip)                     @ jump to next instruction
3668     /* 9-10 instructions */
3669
3670
3671 /* ------------------------------ */
3672     .balign 64
3673 .L_OP_NEG_DOUBLE: /* 0x80 */
3674 /* File: armv5te/OP_NEG_DOUBLE.S */
3675 /* File: armv5te/unopWide.S */
3676     /*
3677      * Generic 64-bit unary operation.  Provide an "instr" line that
3678      * specifies an instruction that performs "result = op r0/r1".
3679      * This could be an ARM instruction or a function call.
3680      *
3681      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3682      */
3683     /* unop vA, vB */
3684     mov     r9, rINST, lsr #8           @ r9<- A+
3685     mov     r3, rINST, lsr #12          @ r3<- B
3686     and     r9, r9, #15
3687     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3688     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3689     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3690     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3691                                @ optional op; may set condition codes
3692     add     r1, r1, #0x80000000                              @ r0/r1<- op, r2-r3 changed
3693     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3694     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3695     GOTO_OPCODE(ip)                     @ jump to next instruction
3696     /* 12-13 instructions */
3697
3698
3699
3700 /* ------------------------------ */
3701     .balign 64
3702 .L_OP_INT_TO_LONG: /* 0x81 */
3703 /* File: armv5te/OP_INT_TO_LONG.S */
3704 /* File: armv5te/unopWider.S */
3705     /*
3706      * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3707      * that specifies an instruction that performs "result = op r0", where
3708      * "result" is a 64-bit quantity in r0/r1.
3709      *
3710      * For: int-to-long, int-to-double, float-to-long, float-to-double
3711      */
3712     /* unop vA, vB */
3713     mov     r9, rINST, lsr #8           @ r9<- A+
3714     mov     r3, rINST, lsr #12          @ r3<- B
3715     and     r9, r9, #15
3716     GET_VREG(r0, r3)                    @ r0<- vB
3717     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3718                                @ optional op; may set condition codes
3719     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3720     mov     r1, r0, asr #31                              @ r0<- op, r0-r3 changed
3721     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3722     stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3723     GOTO_OPCODE(ip)                     @ jump to next instruction
3724     /* 10-11 instructions */
3725
3726
3727 /* ------------------------------ */
3728     .balign 64
3729 .L_OP_INT_TO_FLOAT: /* 0x82 */
3730 /* File: armv5te/OP_INT_TO_FLOAT.S */
3731 /* File: armv5te/unop.S */
3732     /*
3733      * Generic 32-bit unary operation.  Provide an "instr" line that
3734      * specifies an instruction that performs "result = op r0".
3735      * This could be an ARM instruction or a function call.
3736      *
3737      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3738      *      int-to-byte, int-to-char, int-to-short
3739      */
3740     /* unop vA, vB */
3741     mov     r3, rINST, lsr #12          @ r3<- B
3742     mov     r9, rINST, lsr #8           @ r9<- A+
3743     GET_VREG(r0, r3)                    @ r0<- vB
3744     and     r9, r9, #15
3745                                @ optional op; may set condition codes
3746     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3747     bl      __aeabi_i2f                              @ r0<- op, r0-r3 changed
3748     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3749     SET_VREG(r0, r9)                    @ vAA<- r0
3750     GOTO_OPCODE(ip)                     @ jump to next instruction
3751     /* 9-10 instructions */
3752
3753
3754 /* ------------------------------ */
3755     .balign 64
3756 .L_OP_INT_TO_DOUBLE: /* 0x83 */
3757 /* File: armv5te/OP_INT_TO_DOUBLE.S */
3758 /* File: armv5te/unopWider.S */
3759     /*
3760      * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3761      * that specifies an instruction that performs "result = op r0", where
3762      * "result" is a 64-bit quantity in r0/r1.
3763      *
3764      * For: int-to-long, int-to-double, float-to-long, float-to-double
3765      */
3766     /* unop vA, vB */
3767     mov     r9, rINST, lsr #8           @ r9<- A+
3768     mov     r3, rINST, lsr #12          @ r3<- B
3769     and     r9, r9, #15
3770     GET_VREG(r0, r3)                    @ r0<- vB
3771     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3772                                @ optional op; may set condition codes
3773     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3774     bl      __aeabi_i2d                              @ r0<- op, r0-r3 changed
3775     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3776     stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3777     GOTO_OPCODE(ip)                     @ jump to next instruction
3778     /* 10-11 instructions */
3779
3780
3781 /* ------------------------------ */
3782     .balign 64
3783 .L_OP_LONG_TO_INT: /* 0x84 */
3784 /* File: armv5te/OP_LONG_TO_INT.S */
3785 /* we ignore the high word, making this equivalent to a 32-bit reg move */
3786 /* File: armv5te/OP_MOVE.S */
3787     /* for move, move-object, long-to-int */
3788     /* op vA, vB */
3789     mov     r1, rINST, lsr #12          @ r1<- B from 15:12
3790     mov     r0, rINST, lsr #8           @ r0<- A from 11:8
3791     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3792     GET_VREG(r2, r1)                    @ r2<- fp[B]
3793     and     r0, r0, #15
3794     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
3795     SET_VREG(r2, r0)                    @ fp[A]<- r2
3796     GOTO_OPCODE(ip)                     @ execute next instruction
3797
3798
3799
3800 /* ------------------------------ */
3801     .balign 64
3802 .L_OP_LONG_TO_FLOAT: /* 0x85 */
3803 /* File: armv5te/OP_LONG_TO_FLOAT.S */
3804 /* File: armv5te/unopNarrower.S */
3805     /*
3806      * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
3807      * that specifies an instruction that performs "result = op r0/r1", where
3808      * "result" is a 32-bit quantity in r0.
3809      *
3810      * For: long-to-float, double-to-int, double-to-float
3811      *
3812      * (This would work for long-to-int, but that instruction is actually
3813      * an exact match for OP_MOVE.)
3814      */
3815     /* unop vA, vB */
3816     mov     r3, rINST, lsr #12          @ r3<- B
3817     mov     r9, rINST, lsr #8           @ r9<- A+
3818     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3819     and     r9, r9, #15
3820     ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
3821     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3822                                @ optional op; may set condition codes
3823     bl      __aeabi_l2f                              @ r0<- op, r0-r3 changed
3824     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3825     SET_VREG(r0, r9)                    @ vA<- r0
3826     GOTO_OPCODE(ip)                     @ jump to next instruction
3827     /* 10-11 instructions */
3828
3829
3830 /* ------------------------------ */
3831     .balign 64
3832 .L_OP_LONG_TO_DOUBLE: /* 0x86 */
3833 /* File: armv5te/OP_LONG_TO_DOUBLE.S */
3834 /* File: armv5te/unopWide.S */
3835     /*
3836      * Generic 64-bit unary operation.  Provide an "instr" line that
3837      * specifies an instruction that performs "result = op r0/r1".
3838      * This could be an ARM instruction or a function call.
3839      *
3840      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3841      */
3842     /* unop vA, vB */
3843     mov     r9, rINST, lsr #8           @ r9<- A+
3844     mov     r3, rINST, lsr #12          @ r3<- B
3845     and     r9, r9, #15
3846     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3847     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3848     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3849     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3850                                @ optional op; may set condition codes
3851     bl      __aeabi_l2d                              @ r0/r1<- op, r2-r3 changed
3852     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3853     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3854     GOTO_OPCODE(ip)                     @ jump to next instruction
3855     /* 12-13 instructions */
3856
3857
3858
3859 /* ------------------------------ */
3860     .balign 64
3861 .L_OP_FLOAT_TO_INT: /* 0x87 */
3862 /* File: armv5te/OP_FLOAT_TO_INT.S */
3863 /* EABI appears to have Java-style conversions of +inf/-inf/NaN */
3864 /* File: armv5te/unop.S */
3865     /*
3866      * Generic 32-bit unary operation.  Provide an "instr" line that
3867      * specifies an instruction that performs "result = op r0".
3868      * This could be an ARM instruction or a function call.
3869      *
3870      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3871      *      int-to-byte, int-to-char, int-to-short
3872      */
3873     /* unop vA, vB */
3874     mov     r3, rINST, lsr #12          @ r3<- B
3875     mov     r9, rINST, lsr #8           @ r9<- A+
3876     GET_VREG(r0, r3)                    @ r0<- vB
3877     and     r9, r9, #15
3878                                @ optional op; may set condition codes
3879     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3880     bl      __aeabi_f2iz                              @ r0<- op, r0-r3 changed
3881     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3882     SET_VREG(r0, r9)                    @ vAA<- r0
3883     GOTO_OPCODE(ip)                     @ jump to next instruction
3884     /* 9-10 instructions */
3885
3886
3887 #if 0
3888 @include "armv5te/unop.S" {"instr":"bl      f2i_doconv"}
3889 @break
3890 /*
3891  * Convert the float in r0 to an int in r0.
3892  *
3893  * We have to clip values to int min/max per the specification.  The
3894  * expected common case is a "reasonable" value that converts directly
3895  * to modest integer.  The EABI convert function isn't doing this for us.
3896  */
3897 f2i_doconv:
3898     stmfd   sp!, {r4, lr}
3899     mov     r1, #0x4f000000             @ (float)maxint
3900     mov     r4, r0
3901     bl      __aeabi_fcmpge              @ is arg >= maxint?
3902     cmp     r0, #0                      @ nonzero == yes
3903     mvnne   r0, #0x80000000             @ return maxint (7fffffff)
3904     ldmnefd sp!, {r4, pc}
3905
3906     mov     r0, r4                      @ recover arg
3907     mov     r1, #0xcf000000             @ (float)minint
3908     bl      __aeabi_fcmple              @ is arg <= minint?
3909     cmp     r0, #0                      @ nonzero == yes
3910     movne   r0, #0x80000000             @ return minint (80000000)
3911     ldmnefd sp!, {r4, pc}
3912
3913     mov     r0, r4                      @ recover arg
3914     mov     r1, r4
3915     bl      __aeabi_fcmpeq              @ is arg == self?
3916     cmp     r0, #0                      @ zero == no
3917     ldmeqfd sp!, {r4, pc}               @ return zero for NaN
3918
3919     mov     r0, r4                      @ recover arg
3920     bl      __aeabi_f2iz                @ convert float to int
3921     ldmfd   sp!, {r4, pc}
3922 #endif
3923
3924
3925 /* ------------------------------ */
3926     .balign 64
3927 .L_OP_FLOAT_TO_LONG: /* 0x88 */
3928 /* File: armv5te/OP_FLOAT_TO_LONG.S */
3929 @include "armv5te/unopWider.S" {"instr":"bl      __aeabi_f2lz"}
3930 /* File: armv5te/unopWider.S */
3931     /*
3932      * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3933      * that specifies an instruction that performs "result = op r0", where
3934      * "result" is a 64-bit quantity in r0/r1.
3935      *
3936      * For: int-to-long, int-to-double, float-to-long, float-to-double
3937      */
3938     /* unop vA, vB */
3939     mov     r9, rINST, lsr #8           @ r9<- A+
3940     mov     r3, rINST, lsr #12          @ r3<- B
3941     and     r9, r9, #15
3942     GET_VREG(r0, r3)                    @ r0<- vB
3943     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3944                                @ optional op; may set condition codes
3945     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3946     bl      f2l_doconv                              @ r0<- op, r0-r3 changed
3947     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3948     stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3949     GOTO_OPCODE(ip)                     @ jump to next instruction
3950     /* 10-11 instructions */
3951
3952
3953
3954 /* ------------------------------ */
3955     .balign 64
3956 .L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
3957 /* File: armv5te/OP_FLOAT_TO_DOUBLE.S */
3958 /* File: armv5te/unopWider.S */
3959     /*
3960      * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3961      * that specifies an instruction that performs "result = op r0", where
3962      * "result" is a 64-bit quantity in r0/r1.
3963      *
3964      * For: int-to-long, int-to-double, float-to-long, float-to-double
3965      */
3966     /* unop vA, vB */
3967     mov     r9, rINST, lsr #8           @ r9<- A+
3968     mov     r3, rINST, lsr #12          @ r3<- B
3969     and     r9, r9, #15
3970     GET_VREG(r0, r3)                    @ r0<- vB
3971     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3972                                @ optional op; may set condition codes
3973     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3974     bl      __aeabi_f2d                              @ r0<- op, r0-r3 changed
3975     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3976     stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3977     GOTO_OPCODE(ip)                     @ jump to next instruction
3978     /* 10-11 instructions */
3979
3980
3981 /* ------------------------------ */
3982     .balign 64
3983 .L_OP_DOUBLE_TO_INT: /* 0x8a */
3984 /* File: armv5te/OP_DOUBLE_TO_INT.S */
3985 /* EABI appears to have Java-style conversions of +inf/-inf/NaN */
3986 /* File: armv5te/unopNarrower.S */
3987     /*
3988      * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
3989      * that specifies an instruction that performs "result = op r0/r1", where
3990      * "result" is a 32-bit quantity in r0.
3991      *
3992      * For: long-to-float, double-to-int, double-to-float
3993      *
3994      * (This would work for long-to-int, but that instruction is actually
3995      * an exact match for OP_MOVE.)
3996      */
3997     /* unop vA, vB */
3998     mov     r3, rINST, lsr #12          @ r3<- B
3999     mov     r9, rINST, lsr #8           @ r9<- A+
4000     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
4001     and     r9, r9, #15
4002     ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
4003     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4004                                @ optional op; may set condition codes
4005     bl      __aeabi_d2iz                              @ r0<- op, r0-r3 changed
4006     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4007     SET_VREG(r0, r9)                    @ vA<- r0
4008     GOTO_OPCODE(ip)                     @ jump to next instruction
4009     /* 10-11 instructions */
4010
4011
4012 #if 0
4013 @include "armv5te/unopNarrower.S" {"instr":"bl      d2i_doconv"}
4014 @break
4015 /*
4016  * Convert the double in r0/r1 to an int in r0.
4017  *
4018  * We have to clip values to int min/max per the specification.  The
4019  * expected common case is a "reasonable" value that converts directly
4020  * to modest integer.  The EABI convert function isn't doing this for us.
4021  */
4022 d2i_doconv:
4023     stmfd   sp!, {r4, r5, lr}           @ save regs
4024     mov     r2, #0x80000000             @ maxint, as a double (low word)
4025     mov     r2, r2, asr #9              @  0xffc00000
4026     sub     sp, sp, #4                  @ align for EABI
4027     mvn     r3, #0xbe000000             @ maxint, as a double (high word)
4028     sub     r3, r3, #0x00200000         @  0x41dfffff
4029     mov     r4, r0                      @ save a copy of r0
4030     mov     r5, r1                      @  and r1
4031     bl      __aeabi_dcmpge              @ is arg >= maxint?
4032     cmp     r0, #0                      @ nonzero == yes
4033     mvnne   r0, #0x80000000             @ return maxint (0x7fffffff)
4034     bne     1f
4035
4036     mov     r0, r4                      @ recover arg
4037     mov     r1, r5
4038     mov     r3, #0xc1000000             @ minint, as a double (high word)
4039     add     r3, r3, #0x00e00000         @  0xc1e00000
4040     mov     r2, #0                      @ minint, as a double (low word)
4041     bl      __aeabi_dcmple              @ is arg <= minint?
4042     cmp     r0, #0                      @ nonzero == yes
4043     movne   r0, #0x80000000             @ return minint (80000000)
4044     bne     1f
4045
4046     mov     r0, r4                      @ recover arg
4047     mov     r1, r5
4048     mov     r2, r4                      @ compare against self
4049     mov     r3, r5
4050     bl      __aeabi_dcmpeq              @ is arg == self?
4051     cmp     r0, #0                      @ zero == no
4052     beq     1f                          @ return zero for NaN
4053
4054     mov     r0, r4                      @ recover arg
4055     mov     r1, r5
4056     bl      __aeabi_d2iz                @ convert double to int
4057
4058 1:
4059     add     sp, sp, #4
4060     ldmfd   sp!, {r4, r5, pc}
4061 #endif
4062
4063
4064 /* ------------------------------ */
4065     .balign 64
4066 .L_OP_DOUBLE_TO_LONG: /* 0x8b */
4067 /* File: armv5te/OP_DOUBLE_TO_LONG.S */
4068 @include "armv5te/unopWide.S" {"instr":"bl      __aeabi_d2lz"}
4069 /* File: armv5te/unopWide.S */
4070     /*
4071      * Generic 64-bit unary operation.  Provide an "instr" line that
4072      * specifies an instruction that performs "result = op r0/r1".
4073      * This could be an ARM instruction or a function call.
4074      *
4075      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
4076      */
4077     /* unop vA, vB */
4078     mov     r9, rINST, lsr #8           @ r9<- A+
4079     mov     r3, rINST, lsr #12          @ r3<- B
4080     and     r9, r9, #15
4081     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
4082     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
4083     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
4084     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4085                                @ optional op; may set condition codes
4086     bl      d2l_doconv                              @ r0/r1<- op, r2-r3 changed
4087     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4088     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
4089     GOTO_OPCODE(ip)                     @ jump to next instruction
4090     /* 12-13 instructions */
4091
4092
4093
4094
4095 /* ------------------------------ */
4096     .balign 64
4097 .L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
4098 /* File: armv5te/OP_DOUBLE_TO_FLOAT.S */
4099 /* File: armv5te/unopNarrower.S */
4100     /*
4101      * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
4102      * that specifies an instruction that performs "result = op r0/r1", where
4103      * "result" is a 32-bit quantity in r0.
4104      *
4105      * For: long-to-float, double-to-int, double-to-float
4106      *
4107      * (This would work for long-to-int, but that instruction is actually
4108      * an exact match for OP_MOVE.)
4109      */
4110     /* unop vA, vB */
4111     mov     r3, rINST, lsr #12          @ r3<- B
4112     mov     r9, rINST, lsr #8           @ r9<- A+
4113     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
4114     and     r9, r9, #15
4115     ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
4116     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4117                                @ optional op; may set condition codes
4118     bl      __aeabi_d2f                              @ r0<- op, r0-r3 changed
4119     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4120     SET_VREG(r0, r9)                    @ vA<- r0
4121     GOTO_OPCODE(ip)                     @ jump to next instruction
4122     /* 10-11 instructions */
4123
4124
4125 /* ------------------------------ */
4126     .balign 64
4127 .L_OP_INT_TO_BYTE: /* 0x8d */
4128 /* File: armv5te/OP_INT_TO_BYTE.S */
4129 /* File: armv5te/unop.S */
4130     /*
4131      * Generic 32-bit unary operation.  Provide an "instr" line that
4132      * specifies an instruction that performs "result = op r0".
4133      * This could be an ARM instruction or a function call.
4134      *
4135      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4136      *      int-to-byte, int-to-char, int-to-short
4137      */
4138     /* unop vA, vB */
4139     mov     r3, rINST, lsr #12          @ r3<- B
4140     mov     r9, rINST, lsr #8           @ r9<- A+
4141     GET_VREG(r0, r3)                    @ r0<- vB
4142     and     r9, r9, #15
4143     mov     r0, r0, asl #24                           @ optional op; may set condition codes
4144     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4145     mov     r0, r0, asr #24                              @ r0<- op, r0-r3 changed
4146     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4147     SET_VREG(r0, r9)                    @ vAA<- r0
4148     GOTO_OPCODE(ip)                     @ jump to next instruction
4149     /* 9-10 instructions */
4150
4151
4152 /* ------------------------------ */
4153     .balign 64
4154 .L_OP_INT_TO_CHAR: /* 0x8e */
4155 /* File: armv5te/OP_INT_TO_CHAR.S */
4156 /* File: armv5te/unop.S */
4157     /*
4158      * Generic 32-bit unary operation.  Provide an "instr" line that
4159      * specifies an instruction that performs "result = op r0".
4160      * This could be an ARM instruction or a function call.
4161      *
4162      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4163      *      int-to-byte, int-to-char, int-to-short
4164      */
4165     /* unop vA, vB */
4166     mov     r3, rINST, lsr #12          @ r3<- B
4167     mov     r9, rINST, lsr #8           @ r9<- A+
4168     GET_VREG(r0, r3)                    @ r0<- vB
4169     and     r9, r9, #15
4170     mov     r0, r0, asl #16                           @ optional op; may set condition codes
4171     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4172     mov     r0, r0, lsr #16                              @ r0<- op, r0-r3 changed
4173     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4174     SET_VREG(r0, r9)                    @ vAA<- r0
4175     GOTO_OPCODE(ip)                     @ jump to next instruction
4176     /* 9-10 instructions */
4177
4178
4179 /* ------------------------------ */
4180     .balign 64
4181 .L_OP_INT_TO_SHORT: /* 0x8f */
4182 /* File: armv5te/OP_INT_TO_SHORT.S */
4183 /* File: armv5te/unop.S */
4184     /*
4185      * Generic 32-bit unary operation.  Provide an "instr" line that
4186      * specifies an instruction that performs "result = op r0".
4187      * This could be an ARM instruction or a function call.
4188      *
4189      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4190      *      int-to-byte, int-to-char, int-to-short
4191      */
4192     /* unop vA, vB */
4193     mov     r3, rINST, lsr #12          @ r3<- B
4194     mov     r9, rINST, lsr #8           @ r9<- A+
4195     GET_VREG(r0, r3)                    @ r0<- vB
4196     and     r9, r9, #15
4197     mov     r0, r0, asl #16                           @ optional op; may set condition codes
4198     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4199     mov     r0, r0, asr #16                              @ r0<- op, r0-r3 changed
4200     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4201     SET_VREG(r0, r9)                    @ vAA<- r0
4202     GOTO_OPCODE(ip)                     @ jump to next instruction
4203     /* 9-10 instructions */
4204
4205
4206 /* ------------------------------ */
4207     .balign 64
4208 .L_OP_ADD_INT: /* 0x90 */
4209 /* File: armv5te/OP_ADD_INT.S */
4210 /* File: armv5te/binop.S */
4211     /*
4212      * Generic 32-bit binary operation.  Provide an "instr" line that
4213      * specifies an instruction that performs "result = r0 op r1".
4214      * This could be an ARM instruction or a function call.  (If the result
4215      * comes back in a register other than r0, you can override "result".)
4216      *
4217      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4218      * vCC (r1).  Useful for integer division and modulus.  Note that we
4219      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4220      * handles it correctly.
4221      *
4222      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4223      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4224      *      mul-float, div-float, rem-float
4225      */
4226     /* binop vAA, vBB, vCC */
4227     FETCH(r0, 1)                        @ r0<- CCBB
4228     mov     r9, rINST, lsr #8           @ r9<- AA
4229     mov     r3, r0, lsr #8              @ r3<- CC
4230     and     r2, r0, #255                @ r2<- BB
4231     GET_VREG(r1, r3)                    @ r1<- vCC
4232     GET_VREG(r0, r2)                    @ r0<- vBB
4233     .if 0
4234     cmp     r1, #0                      @ is second operand zero?
4235     beq     common_errDivideByZero
4236     .endif
4237
4238     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4239                                @ optional op; may set condition codes
4240     add     r0, r0, r1                              @ r0<- op, r0-r3 changed
4241     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4242     SET_VREG(r0, r9)               @ vAA<- r0
4243     GOTO_OPCODE(ip)                     @ jump to next instruction
4244     /* 11-14 instructions */
4245
4246
4247
4248 /* ------------------------------ */
4249     .balign 64
4250 .L_OP_SUB_INT: /* 0x91 */
4251 /* File: armv5te/OP_SUB_INT.S */
4252 /* File: armv5te/binop.S */
4253     /*
4254      * Generic 32-bit binary operation.  Provide an "instr" line that
4255      * specifies an instruction that performs "result = r0 op r1".
4256      * This could be an ARM instruction or a function call.  (If the result
4257      * comes back in a register other than r0, you can override "result".)
4258      *
4259      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4260      * vCC (r1).  Useful for integer division and modulus.  Note that we
4261      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4262      * handles it correctly.
4263      *
4264      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4265      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4266      *      mul-float, div-float, rem-float
4267      */
4268     /* binop vAA, vBB, vCC */
4269     FETCH(r0, 1)                        @ r0<- CCBB
4270     mov     r9, rINST, lsr #8           @ r9<- AA
4271     mov     r3, r0, lsr #8              @ r3<- CC
4272     and     r2, r0, #255                @ r2<- BB
4273     GET_VREG(r1, r3)                    @ r1<- vCC
4274     GET_VREG(r0, r2)                    @ r0<- vBB
4275     .if 0
4276     cmp     r1, #0                      @ is second operand zero?
4277     beq     common_errDivideByZero
4278     .endif
4279
4280     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4281                                @ optional op; may set condition codes
4282     sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
4283     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4284     SET_VREG(r0, r9)               @ vAA<- r0
4285     GOTO_OPCODE(ip)                     @ jump to next instruction
4286     /* 11-14 instructions */
4287
4288
4289
4290 /* ------------------------------ */
4291     .balign 64
4292 .L_OP_MUL_INT: /* 0x92 */
4293 /* File: armv5te/OP_MUL_INT.S */
4294 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
4295 /* File: armv5te/binop.S */
4296     /*
4297      * Generic 32-bit binary operation.  Provide an "instr" line that
4298      * specifies an instruction that performs "result = r0 op r1".
4299      * This could be an ARM instruction or a function call.  (If the result
4300      * comes back in a register other than r0, you can override "result".)
4301      *
4302      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4303      * vCC (r1).  Useful for integer division and modulus.  Note that we
4304      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4305      * handles it correctly.
4306      *
4307      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4308      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4309      *      mul-float, div-float, rem-float
4310      */
4311     /* binop vAA, vBB, vCC */
4312     FETCH(r0, 1)                        @ r0<- CCBB
4313     mov     r9, rINST, lsr #8           @ r9<- AA
4314     mov     r3, r0, lsr #8              @ r3<- CC
4315     and     r2, r0, #255                @ r2<- BB
4316     GET_VREG(r1, r3)                    @ r1<- vCC
4317     GET_VREG(r0, r2)                    @ r0<- vBB
4318     .if 0
4319     cmp     r1, #0                      @ is second operand zero?
4320     beq     common_errDivideByZero
4321     .endif
4322
4323     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4324                                @ optional op; may set condition codes
4325     mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
4326     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4327     SET_VREG(r0, r9)               @ vAA<- r0
4328     GOTO_OPCODE(ip)                     @ jump to next instruction
4329     /* 11-14 instructions */
4330
4331
4332
4333 /* ------------------------------ */
4334     .balign 64
4335 .L_OP_DIV_INT: /* 0x93 */
4336 /* File: armv5te/OP_DIV_INT.S */
4337 /* File: armv5te/binop.S */
4338     /*
4339      * Generic 32-bit binary operation.  Provide an "instr" line that
4340      * specifies an instruction that performs "result = r0 op r1".
4341      * This could be an ARM instruction or a function call.  (If the result
4342      * comes back in a register other than r0, you can override "result".)
4343      *
4344      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4345      * vCC (r1).  Useful for integer division and modulus.  Note that we
4346      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4347      * handles it correctly.
4348      *
4349      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4350      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4351      *      mul-float, div-float, rem-float
4352      */
4353     /* binop vAA, vBB, vCC */
4354     FETCH(r0, 1)                        @ r0<- CCBB
4355     mov     r9, rINST, lsr #8           @ r9<- AA
4356     mov     r3, r0, lsr #8              @ r3<- CC
4357     and     r2, r0, #255                @ r2<- BB
4358     GET_VREG(r1, r3)                    @ r1<- vCC
4359     GET_VREG(r0, r2)                    @ r0<- vBB
4360     .if 1
4361     cmp     r1, #0                      @ is second operand zero?
4362     beq     common_errDivideByZero
4363     .endif
4364
4365     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4366                                @ optional op; may set condition codes
4367     bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
4368     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4369     SET_VREG(r0, r9)               @ vAA<- r0
4370     GOTO_OPCODE(ip)                     @ jump to next instruction
4371     /* 11-14 instructions */
4372
4373
4374
4375 /* ------------------------------ */
4376     .balign 64
4377 .L_OP_REM_INT: /* 0x94 */
4378 /* File: armv5te/OP_REM_INT.S */
4379 /* idivmod returns quotient in r0 and remainder in r1 */
4380 /* File: armv5te/binop.S */
4381     /*
4382      * Generic 32-bit binary operation.  Provide an "instr" line that
4383      * specifies an instruction that performs "result = r0 op r1".
4384      * This could be an ARM instruction or a function call.  (If the result
4385      * comes back in a register other than r0, you can override "result".)
4386      *
4387      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4388      * vCC (r1).  Useful for integer division and modulus.  Note that we
4389      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4390      * handles it correctly.
4391      *
4392      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4393      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4394      *      mul-float, div-float, rem-float
4395      */
4396     /* binop vAA, vBB, vCC */
4397     FETCH(r0, 1)                        @ r0<- CCBB
4398     mov     r9, rINST, lsr #8           @ r9<- AA
4399     mov     r3, r0, lsr #8              @ r3<- CC
4400     and     r2, r0, #255                @ r2<- BB
4401     GET_VREG(r1, r3)                    @ r1<- vCC
4402     GET_VREG(r0, r2)                    @ r0<- vBB
4403     .if 1
4404     cmp     r1, #0                      @ is second operand zero?
4405     beq     common_errDivideByZero
4406     .endif
4407
4408     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4409                                @ optional op; may set condition codes
4410     bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
4411     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4412     SET_VREG(r1, r9)               @ vAA<- r1
4413     GOTO_OPCODE(ip)                     @ jump to next instruction
4414     /* 11-14 instructions */
4415
4416
4417
4418 /* ------------------------------ */
4419     .balign 64
4420 .L_OP_AND_INT: /* 0x95 */
4421 /* File: armv5te/OP_AND_INT.S */
4422 /* File: armv5te/binop.S */
4423     /*
4424      * Generic 32-bit binary operation.  Provide an "instr" line that
4425      * specifies an instruction that performs "result = r0 op r1".
4426      * This could be an ARM instruction or a function call.  (If the result
4427      * comes back in a register other than r0, you can override "result".)
4428      *
4429      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4430      * vCC (r1).  Useful for integer division and modulus.  Note that we
4431      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4432      * handles it correctly.
4433      *
4434      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4435      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4436      *      mul-float, div-float, rem-float
4437      */
4438     /* binop vAA, vBB, vCC */
4439     FETCH(r0, 1)                        @ r0<- CCBB
4440     mov     r9, rINST, lsr #8           @ r9<- AA
4441     mov     r3, r0, lsr #8              @ r3<- CC
4442     and     r2, r0, #255                @ r2<- BB
4443     GET_VREG(r1, r3)                    @ r1<- vCC
4444     GET_VREG(r0, r2)                    @ r0<- vBB
4445     .if 0
4446     cmp     r1, #0                      @ is second operand zero?
4447     beq     common_errDivideByZero
4448     .endif
4449
4450     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4451                                @ optional op; may set condition codes
4452     and     r0, r0, r1                              @ r0<- op, r0-r3 changed
4453     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4454     SET_VREG(r0, r9)               @ vAA<- r0
4455     GOTO_OPCODE(ip)                     @ jump to next instruction
4456     /* 11-14 instructions */
4457
4458
4459
4460 /* ------------------------------ */
4461     .balign 64
4462 .L_OP_OR_INT: /* 0x96 */
4463 /* File: armv5te/OP_OR_INT.S */
4464 /* File: armv5te/binop.S */
4465     /*
4466      * Generic 32-bit binary operation.  Provide an "instr" line that
4467      * specifies an instruction that performs "result = r0 op r1".
4468      * This could be an ARM instruction or a function call.  (If the result
4469      * comes back in a register other than r0, you can override "result".)
4470      *
4471      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4472      * vCC (r1).  Useful for integer division and modulus.  Note that we
4473      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4474      * handles it correctly.
4475      *
4476      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4477      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4478      *      mul-float, div-float, rem-float
4479      */
4480     /* binop vAA, vBB, vCC */
4481     FETCH(r0, 1)                        @ r0<- CCBB
4482     mov     r9, rINST, lsr #8           @ r9<- AA
4483     mov     r3, r0, lsr #8              @ r3<- CC
4484     and     r2, r0, #255                @ r2<- BB
4485     GET_VREG(r1, r3)                    @ r1<- vCC
4486     GET_VREG(r0, r2)                    @ r0<- vBB
4487     .if 0
4488     cmp     r1, #0                      @ is second operand zero?
4489     beq     common_errDivideByZero
4490     .endif
4491
4492     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4493                                @ optional op; may set condition codes
4494     orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
4495     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4496     SET_VREG(r0, r9)               @ vAA<- r0
4497     GOTO_OPCODE(ip)                     @ jump to next instruction
4498     /* 11-14 instructions */
4499
4500
4501
4502 /* ------------------------------ */
4503     .balign 64
4504 .L_OP_XOR_INT: /* 0x97 */
4505 /* File: armv5te/OP_XOR_INT.S */
4506 /* File: armv5te/binop.S */
4507     /*
4508      * Generic 32-bit binary operation.  Provide an "instr" line that
4509      * specifies an instruction that performs "result = r0 op r1".
4510      * This could be an ARM instruction or a function call.  (If the result
4511      * comes back in a register other than r0, you can override "result".)
4512      *
4513      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4514      * vCC (r1).  Useful for integer division and modulus.  Note that we
4515      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4516      * handles it correctly.
4517      *
4518      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4519      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4520      *      mul-float, div-float, rem-float
4521      */
4522     /* binop vAA, vBB, vCC */
4523     FETCH(r0, 1)                        @ r0<- CCBB
4524     mov     r9, rINST, lsr #8           @ r9<- AA
4525     mov     r3, r0, lsr #8              @ r3<- CC
4526     and     r2, r0, #255                @ r2<- BB
4527     GET_VREG(r1, r3)                    @ r1<- vCC
4528     GET_VREG(r0, r2)                    @ r0<- vBB
4529     .if 0
4530     cmp     r1, #0                      @ is second operand zero?
4531     beq     common_errDivideByZero
4532     .endif
4533
4534     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4535                                @ optional op; may set condition codes
4536     eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
4537     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4538     SET_VREG(r0, r9)               @ vAA<- r0
4539     GOTO_OPCODE(ip)                     @ jump to next instruction
4540     /* 11-14 instructions */
4541
4542
4543
4544 /* ------------------------------ */
4545     .balign 64
4546 .L_OP_SHL_INT: /* 0x98 */
4547 /* File: armv5te/OP_SHL_INT.S */
4548 /* File: armv5te/binop.S */
4549     /*
4550      * Generic 32-bit binary operation.  Provide an "instr" line that
4551      * specifies an instruction that performs "result = r0 op r1".
4552      * This could be an ARM instruction or a function call.  (If the result
4553      * comes back in a register other than r0, you can override "result".)
4554      *
4555      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4556      * vCC (r1).  Useful for integer division and modulus.  Note that we
4557      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4558      * handles it correctly.
4559      *
4560      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4561      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4562      *      mul-float, div-float, rem-float
4563      */
4564     /* binop vAA, vBB, vCC */
4565     FETCH(r0, 1)                        @ r0<- CCBB
4566     mov     r9, rINST, lsr #8           @ r9<- AA
4567     mov     r3, r0, lsr #8              @ r3<- CC
4568     and     r2, r0, #255                @ r2<- BB
4569     GET_VREG(r1, r3)                    @ r1<- vCC
4570     GET_VREG(r0, r2)                    @ r0<- vBB
4571     .if 0
4572     cmp     r1, #0                      @ is second operand zero?
4573     beq     common_errDivideByZero
4574     .endif
4575
4576     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4577     and     r1, r1, #31                           @ optional op; may set condition codes
4578     mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
4579     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4580     SET_VREG(r0, r9)               @ vAA<- r0
4581     GOTO_OPCODE(ip)                     @ jump to next instruction
4582     /* 11-14 instructions */
4583
4584
4585
4586 /* ------------------------------ */
4587     .balign 64
4588 .L_OP_SHR_INT: /* 0x99 */
4589 /* File: armv5te/OP_SHR_INT.S */
4590 /* File: armv5te/binop.S */
4591     /*
4592      * Generic 32-bit binary operation.  Provide an "instr" line that
4593      * specifies an instruction that performs "result = r0 op r1".
4594      * This could be an ARM instruction or a function call.  (If the result
4595      * comes back in a register other than r0, you can override "result".)
4596      *
4597      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4598      * vCC (r1).  Useful for integer division and modulus.  Note that we
4599      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4600      * handles it correctly.
4601      *
4602      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4603      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4604      *      mul-float, div-float, rem-float
4605      */
4606     /* binop vAA, vBB, vCC */
4607     FETCH(r0, 1)                        @ r0<- CCBB
4608     mov     r9, rINST, lsr #8           @ r9<- AA
4609     mov     r3, r0, lsr #8              @ r3<- CC
4610     and     r2, r0, #255                @ r2<- BB
4611     GET_VREG(r1, r3)                    @ r1<- vCC
4612     GET_VREG(r0, r2)                    @ r0<- vBB
4613     .if 0
4614     cmp     r1, #0                      @ is second operand zero?
4615     beq     common_errDivideByZero
4616     .endif
4617
4618     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4619     and     r1, r1, #31                           @ optional op; may set condition codes
4620     mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
4621     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4622     SET_VREG(r0, r9)               @ vAA<- r0
4623     GOTO_OPCODE(ip)                     @ jump to next instruction
4624     /* 11-14 instructions */
4625
4626
4627
4628 /* ------------------------------ */
4629     .balign 64
4630 .L_OP_USHR_INT: /* 0x9a */
4631 /* File: armv5te/OP_USHR_INT.S */
4632 /* File: armv5te/binop.S */
4633     /*
4634      * Generic 32-bit binary operation.  Provide an "instr" line that
4635      * specifies an instruction that performs "result = r0 op r1".
4636      * This could be an ARM instruction or a function call.  (If the result
4637      * comes back in a register other than r0, you can override "result".)
4638      *
4639      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4640      * vCC (r1).  Useful for integer division and modulus.  Note that we
4641      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4642      * handles it correctly.
4643      *
4644      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4645      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4646      *      mul-float, div-float, rem-float
4647      */
4648     /* binop vAA, vBB, vCC */
4649     FETCH(r0, 1)                        @ r0<- CCBB
4650     mov     r9, rINST, lsr #8           @ r9<- AA
4651     mov     r3, r0, lsr #8              @ r3<- CC
4652     and     r2, r0, #255                @ r2<- BB
4653     GET_VREG(r1, r3)                    @ r1<- vCC
4654     GET_VREG(r0, r2)                    @ r0<- vBB
4655     .if 0
4656     cmp     r1, #0                      @ is second operand zero?
4657     beq     common_errDivideByZero
4658     .endif
4659
4660     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4661     and     r1, r1, #31                           @ optional op; may set condition codes
4662     mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
4663     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4664     SET_VREG(r0, r9)               @ vAA<- r0
4665     GOTO_OPCODE(ip)                     @ jump to next instruction
4666     /* 11-14 instructions */
4667
4668
4669
4670 /* ------------------------------ */
4671     .balign 64
4672 .L_OP_ADD_LONG: /* 0x9b */
4673 /* File: armv5te/OP_ADD_LONG.S */
4674 /* File: armv5te/binopWide.S */
4675     /*
4676      * Generic 64-bit binary operation.  Provide an "instr" line that
4677      * specifies an instruction that performs "result = r0-r1 op r2-r3".
4678      * This could be an ARM instruction or a function call.  (If the result
4679      * comes back in a register other than r0, you can override "result".)
4680      *
4681      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4682      * vCC (r1).  Useful for integer division and modulus.
4683      *
4684      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4685      *      xor-long, add-double, sub-double, mul-double, div-double,
4686      *      rem-double
4687      *
4688      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4689      */
4690     /* binop vAA, vBB, vCC */
4691     FETCH(r0, 1)                        @ r0<- CCBB
4692     mov     r9, rINST, lsr #8           @ r9<- AA
4693     and     r2, r0, #255                @ r2<- BB
4694     mov     r3, r0, lsr #8              @ r3<- CC
4695     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4696     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4697     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4698     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4699     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4700     .if 0
4701     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4702     beq     common_errDivideByZero
4703     .endif
4704     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4705
4706     adds    r0, r0, r2                           @ optional op; may set condition codes
4707     adc     r1, r1, r3                              @ result<- op, r0-r3 changed
4708     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4709     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4710     GOTO_OPCODE(ip)                     @ jump to next instruction
4711     /* 14-17 instructions */
4712
4713
4714
4715 /* ------------------------------ */
4716     .balign 64
4717 .L_OP_SUB_LONG: /* 0x9c */
4718 /* File: armv5te/OP_SUB_LONG.S */
4719 /* File: armv5te/binopWide.S */
4720     /*
4721      * Generic 64-bit binary operation.  Provide an "instr" line that
4722      * specifies an instruction that performs "result = r0-r1 op r2-r3".
4723      * This could be an ARM instruction or a function call.  (If the result
4724      * comes back in a register other than r0, you can override "result".)
4725      *
4726      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4727      * vCC (r1).  Useful for integer division and modulus.
4728      *
4729      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4730      *      xor-long, add-double, sub-double, mul-double, div-double,
4731      *      rem-double
4732      *
4733      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4734      */
4735     /* binop vAA, vBB, vCC */
4736     FETCH(r0, 1)                        @ r0<- CCBB
4737     mov     r9, rINST, lsr #8           @ r9<- AA
4738     and     r2, r0, #255                @ r2<- BB
4739     mov     r3, r0, lsr #8              @ r3<- CC
4740     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4741     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4742     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4743     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4744     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4745     .if 0
4746     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4747     beq     common_errDivideByZero
4748     .endif
4749     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4750
4751     subs    r0, r0, r2                           @ optional op; may set condition codes
4752     sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
4753     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4754     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4755     GOTO_OPCODE(ip)                     @ jump to next instruction
4756     /* 14-17 instructions */
4757
4758
4759
4760 /* ------------------------------ */
4761     .balign 64
4762 .L_OP_MUL_LONG: /* 0x9d */
4763 /* File: armv5te/OP_MUL_LONG.S */
4764     /*
4765      * Signed 64-bit integer multiply.
4766      *
4767      * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
4768      *        WX
4769      *      x YZ
4770      *  --------
4771      *     ZW ZX
4772      *  YW YX
4773      *
4774      * The low word of the result holds ZX, the high word holds
4775      * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
4776      * it doesn't fit in the low 64 bits.
4777      *
4778      * Unlike most ARM math operations, multiply instructions have
4779      * restrictions on using the same register more than once (Rd and Rm
4780      * cannot be the same).
4781      */
4782     /* mul-long vAA, vBB, vCC */
4783     FETCH(r0, 1)                        @ r0<- CCBB
4784     and     r2, r0, #255                @ r2<- BB
4785     mov     r3, r0, lsr #8              @ r3<- CC
4786     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4787     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4788     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4789     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4790     mul     ip, r2, r1                  @  ip<- ZxW
4791     umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
4792     mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
4793     mov     r0, rINST, lsr #8           @ r0<- AA
4794     add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
4795     add     r0, rFP, r0, lsl #2         @ r0<- &fp[AA]
4796     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4797     b       .LOP_MUL_LONG_finish
4798
4799 /* ------------------------------ */
4800     .balign 64
4801 .L_OP_DIV_LONG: /* 0x9e */
4802 /* File: armv5te/OP_DIV_LONG.S */
4803 /* File: armv5te/binopWide.S */
4804     /*
4805      * Generic 64-bit binary operation.  Provide an "instr" line that
4806      * specifies an instruction that performs "result = r0-r1 op r2-r3".
4807      * This could be an ARM instruction or a function call.  (If the result
4808      * comes back in a register other than r0, you can override "result".)
4809      *
4810      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4811      * vCC (r1).  Useful for integer division and modulus.
4812      *
4813      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4814      *      xor-long, add-double, sub-double, mul-double, div-double,
4815      *      rem-double
4816      *
4817      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4818      */
4819     /* binop vAA, vBB, vCC */
4820     FETCH(r0, 1)                        @ r0<- CCBB
4821     mov     r9, rINST, lsr #8           @ r9<- AA
4822     and     r2, r0, #255                @ r2<- BB
4823     mov     r3, r0, lsr #8              @ r3<- CC
4824     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4825     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4826     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4827     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4828     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4829     .if 1
4830     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4831     beq     common_errDivideByZero
4832     .endif
4833     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4834
4835                                @ optional op; may set condition codes
4836     bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4837     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4838     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4839     GOTO_OPCODE(ip)                     @ jump to next instruction
4840     /* 14-17 instructions */
4841
4842
4843
4844 /* ------------------------------ */
4845     .balign 64
4846 .L_OP_REM_LONG: /* 0x9f */
4847 /* File: armv5te/OP_REM_LONG.S */
4848 /* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
4849 /* File: armv5te/binopWide.S */
4850     /*
4851      * Generic 64-bit binary operation.  Provide an "instr" line that
4852      * specifies an instruction that performs "result = r0-r1 op r2-r3".
4853      * This could be an ARM instruction or a function call.  (If the result
4854      * comes back in a register other than r0, you can override "result".)
4855      *
4856      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4857      * vCC (r1).  Useful for integer division and modulus.
4858      *
4859      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4860      *      xor-long, add-double, sub-double, mul-double, div-double,
4861      *      rem-double
4862      *
4863      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4864      */
4865     /* binop vAA, vBB, vCC */
4866     FETCH(r0, 1)                        @ r0<- CCBB
4867     mov     r9, rINST, lsr #8           @ r9<- AA
4868     and     r2, r0, #255                @ r2<- BB
4869     mov     r3, r0, lsr #8              @ r3<- CC
4870     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4871     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4872     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4873     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4874     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4875     .if 1
4876     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4877     beq     common_errDivideByZero
4878     .endif
4879     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4880
4881                                @ optional op; may set condition codes
4882     bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4883     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4884     stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
4885     GOTO_OPCODE(ip)                     @ jump to next instruction
4886     /* 14-17 instructions */
4887
4888
4889
4890 /* ------------------------------ */
4891     .balign 64
4892 .L_OP_AND_LONG: /* 0xa0 */
4893 /* File: armv5te/OP_AND_LONG.S */
4894 /* File: armv5te/binopWide.S */
4895     /*
4896      * Generic 64-bit binary operation.  Provide an "instr" line that
4897      * specifies an instruction that performs "result = r0-r1 op r2-r3".
4898      * This could be an ARM instruction or a function call.  (If the result
4899      * comes back in a register other than r0, you can override "result".)
4900      *
4901      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4902      * vCC (r1).  Useful for integer division and modulus.
4903      *
4904      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4905      *      xor-long, add-double, sub-double, mul-double, div-double,
4906      *      rem-double
4907      *
4908      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4909      */
4910     /* binop vAA, vBB, vCC */
4911     FETCH(r0, 1)                        @ r0<- CCBB
4912     mov     r9, rINST, lsr #8           @ r9<- AA
4913     and     r2, r0, #255                @ r2<- BB
4914     mov     r3, r0, lsr #8              @ r3<- CC
4915     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4916     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4917     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4918     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4919     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4920     .if 0
4921     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4922     beq     common_errDivideByZero
4923     .endif
4924     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4925
4926     and     r0, r0, r2                           @ optional op; may set condition codes
4927     and     r1, r1, r3                              @ result<- op, r0-r3 changed
4928     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4929     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4930     GOTO_OPCODE(ip)                     @ jump to next instruction
4931     /* 14-17 instructions */
4932
4933
4934
4935 /* ------------------------------ */
4936     .balign 64
4937 .L_OP_OR_LONG: /* 0xa1 */
4938 /* File: armv5te/OP_OR_LONG.S */
4939 /* File: armv5te/binopWide.S */
4940     /*
4941      * Generic 64-bit binary operation.  Provide an "instr" line that
4942      * specifies an instruction that performs "result = r0-r1 op r2-r3".
4943      * This could be an ARM instruction or a function call.  (If the result
4944      * comes back in a register other than r0, you can override "result".)
4945      *
4946      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4947      * vCC (r1).  Useful for integer division and modulus.
4948      *
4949      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4950      *      xor-long, add-double, sub-double, mul-double, div-double,
4951      *      rem-double
4952      *
4953      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4954      */
4955     /* binop vAA, vBB, vCC */
4956     FETCH(r0, 1)                        @ r0<- CCBB
4957     mov     r9, rINST, lsr #8           @ r9<- AA
4958     and     r2, r0, #255                @ r2<- BB
4959     mov     r3, r0, lsr #8              @ r3<- CC
4960     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4961     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4962     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4963     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4964     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4965     .if 0
4966     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4967     beq     common_errDivideByZero
4968     .endif
4969     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4970
4971     orr     r0, r0, r2                           @ optional op; may set condition codes
4972     orr     r1, r1, r3                              @ result<- op, r0-r3 changed
4973     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4974     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4975     GOTO_OPCODE(ip)                     @ jump to next instruction
4976     /* 14-17 instructions */
4977
4978
4979
4980 /* ------------------------------ */
4981     .balign 64
4982 .L_OP_XOR_LONG: /* 0xa2 */
4983 /* File: armv5te/OP_XOR_LONG.S */
4984 /* File: armv5te/binopWide.S */
4985     /*
4986      * Generic 64-bit binary operation.  Provide an "instr" line that
4987      * specifies an instruction that performs "result = r0-r1 op r2-r3".
4988      * This could be an ARM instruction or a function call.  (If the result
4989      * comes back in a register other than r0, you can override "result".)
4990      *
4991      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4992      * vCC (r1).  Useful for integer division and modulus.
4993      *
4994      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4995      *      xor-long, add-double, sub-double, mul-double, div-double,
4996      *      rem-double
4997      *
4998      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4999      */
5000     /* binop vAA, vBB, vCC */
5001     FETCH(r0, 1)                        @ r0<- CCBB
5002     mov     r9, rINST, lsr #8           @ r9<- AA
5003     and     r2, r0, #255                @ r2<- BB
5004     mov     r3, r0, lsr #8              @ r3<- CC
5005     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5006     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5007     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5008     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5009     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5010     .if 0
5011     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5012     beq     common_errDivideByZero
5013     .endif
5014     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5015
5016     eor     r0, r0, r2                           @ optional op; may set condition codes
5017     eor     r1, r1, r3                              @ result<- op, r0-r3 changed
5018     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5019     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5020     GOTO_OPCODE(ip)                     @ jump to next instruction
5021     /* 14-17 instructions */
5022
5023
5024
5025 /* ------------------------------ */
5026     .balign 64
5027 .L_OP_SHL_LONG: /* 0xa3 */
5028 /* File: armv5te/OP_SHL_LONG.S */
5029     /*
5030      * Long integer shift.  This is different from the generic 32/64-bit
5031      * binary operations because vAA/vBB are 64-bit but vCC (the shift
5032      * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
5033      * 6 bits of the shift distance.
5034      */
5035     /* shl-long vAA, vBB, vCC */
5036     FETCH(r0, 1)                        @ r0<- CCBB
5037     mov     r9, rINST, lsr #8           @ r9<- AA
5038     and     r3, r0, #255                @ r3<- BB
5039     mov     r0, r0, lsr #8              @ r0<- CC
5040     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
5041     GET_VREG(r2, r0)                    @ r2<- vCC
5042     ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5043     and     r2, r2, #63                 @ r2<- r2 & 0x3f
5044     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5045
5046     mov     r1, r1, asl r2              @  r1<- r1 << r2
5047     rsb     r3, r2, #32                 @  r3<- 32 - r2
5048     orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
5049     subs    ip, r2, #32                 @  ip<- r2 - 32
5050     movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
5051     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5052     b       .LOP_SHL_LONG_finish
5053
5054 /* ------------------------------ */
5055     .balign 64
5056 .L_OP_SHR_LONG: /* 0xa4 */
5057 /* File: armv5te/OP_SHR_LONG.S */
5058     /*
5059      * Long integer shift.  This is different from the generic 32/64-bit
5060      * binary operations because vAA/vBB are 64-bit but vCC (the shift
5061      * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
5062      * 6 bits of the shift distance.
5063      */
5064     /* shr-long vAA, vBB, vCC */
5065     FETCH(r0, 1)                        @ r0<- CCBB
5066     mov     r9, rINST, lsr #8           @ r9<- AA
5067     and     r3, r0, #255                @ r3<- BB
5068     mov     r0, r0, lsr #8              @ r0<- CC
5069     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
5070     GET_VREG(r2, r0)                    @ r2<- vCC
5071     ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5072     and     r2, r2, #63                 @ r0<- r0 & 0x3f
5073     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5074
5075     mov     r0, r0, lsr r2              @  r0<- r2 >> r2
5076     rsb     r3, r2, #32                 @  r3<- 32 - r2
5077     orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
5078     subs    ip, r2, #32                 @  ip<- r2 - 32
5079     movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
5080     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5081     b       .LOP_SHR_LONG_finish
5082
5083 /* ------------------------------ */
5084     .balign 64
5085 .L_OP_USHR_LONG: /* 0xa5 */
5086 /* File: armv5te/OP_USHR_LONG.S */
5087     /*
5088      * Long integer shift.  This is different from the generic 32/64-bit
5089      * binary operations because vAA/vBB are 64-bit but vCC (the shift
5090      * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
5091      * 6 bits of the shift distance.
5092      */
5093     /* ushr-long vAA, vBB, vCC */
5094     FETCH(r0, 1)                        @ r0<- CCBB
5095     mov     r9, rINST, lsr #8           @ r9<- AA
5096     and     r3, r0, #255                @ r3<- BB
5097     mov     r0, r0, lsr #8              @ r0<- CC
5098     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
5099     GET_VREG(r2, r0)                    @ r2<- vCC
5100     ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5101     and     r2, r2, #63                 @ r0<- r0 & 0x3f
5102     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5103
5104     mov     r0, r0, lsr r2              @  r0<- r2 >> r2
5105     rsb     r3, r2, #32                 @  r3<- 32 - r2
5106     orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
5107     subs    ip, r2, #32                 @  ip<- r2 - 32
5108     movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
5109     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5110     b       .LOP_USHR_LONG_finish
5111
5112 /* ------------------------------ */
5113     .balign 64
5114 .L_OP_ADD_FLOAT: /* 0xa6 */
5115 /* File: armv5te/OP_ADD_FLOAT.S */
5116 /* File: armv5te/binop.S */
5117     /*
5118      * Generic 32-bit binary operation.  Provide an "instr" line that
5119      * specifies an instruction that performs "result = r0 op r1".
5120      * This could be an ARM instruction or a function call.  (If the result
5121      * comes back in a register other than r0, you can override "result".)
5122      *
5123      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5124      * vCC (r1).  Useful for integer division and modulus.  Note that we
5125      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5126      * handles it correctly.
5127      *
5128      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5129      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5130      *      mul-float, div-float, rem-float
5131      */
5132     /* binop vAA, vBB, vCC */
5133     FETCH(r0, 1)                        @ r0<- CCBB
5134     mov     r9, rINST, lsr #8           @ r9<- AA
5135     mov     r3, r0, lsr #8              @ r3<- CC
5136     and     r2, r0, #255                @ r2<- BB
5137     GET_VREG(r1, r3)                    @ r1<- vCC
5138     GET_VREG(r0, r2)                    @ r0<- vBB
5139     .if 0
5140     cmp     r1, #0                      @ is second operand zero?
5141     beq     common_errDivideByZero
5142     .endif
5143
5144     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5145                                @ optional op; may set condition codes
5146     bl      __aeabi_fadd                              @ r0<- op, r0-r3 changed
5147     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5148     SET_VREG(r0, r9)               @ vAA<- r0
5149     GOTO_OPCODE(ip)                     @ jump to next instruction
5150     /* 11-14 instructions */
5151
5152
5153
5154 /* ------------------------------ */
5155     .balign 64
5156 .L_OP_SUB_FLOAT: /* 0xa7 */
5157 /* File: armv5te/OP_SUB_FLOAT.S */
5158 /* File: armv5te/binop.S */
5159     /*
5160      * Generic 32-bit binary operation.  Provide an "instr" line that
5161      * specifies an instruction that performs "result = r0 op r1".
5162      * This could be an ARM instruction or a function call.  (If the result
5163      * comes back in a register other than r0, you can override "result".)
5164      *
5165      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5166      * vCC (r1).  Useful for integer division and modulus.  Note that we
5167      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5168      * handles it correctly.
5169      *
5170      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5171      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5172      *      mul-float, div-float, rem-float
5173      */
5174     /* binop vAA, vBB, vCC */
5175     FETCH(r0, 1)                        @ r0<- CCBB
5176     mov     r9, rINST, lsr #8           @ r9<- AA
5177     mov     r3, r0, lsr #8              @ r3<- CC
5178     and     r2, r0, #255                @ r2<- BB
5179     GET_VREG(r1, r3)                    @ r1<- vCC
5180     GET_VREG(r0, r2)                    @ r0<- vBB
5181     .if 0
5182     cmp     r1, #0                      @ is second operand zero?
5183     beq     common_errDivideByZero
5184     .endif
5185
5186     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5187                                @ optional op; may set condition codes
5188     bl      __aeabi_fsub                              @ r0<- op, r0-r3 changed
5189     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5190     SET_VREG(r0, r9)               @ vAA<- r0
5191     GOTO_OPCODE(ip)                     @ jump to next instruction
5192     /* 11-14 instructions */
5193
5194
5195
5196 /* ------------------------------ */
5197     .balign 64
5198 .L_OP_MUL_FLOAT: /* 0xa8 */
5199 /* File: armv5te/OP_MUL_FLOAT.S */
5200 /* File: armv5te/binop.S */
5201     /*
5202      * Generic 32-bit binary operation.  Provide an "instr" line that
5203      * specifies an instruction that performs "result = r0 op r1".
5204      * This could be an ARM instruction or a function call.  (If the result
5205      * comes back in a register other than r0, you can override "result".)
5206      *
5207      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5208      * vCC (r1).  Useful for integer division and modulus.  Note that we
5209      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5210      * handles it correctly.
5211      *
5212      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5213      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5214      *      mul-float, div-float, rem-float
5215      */
5216     /* binop vAA, vBB, vCC */
5217     FETCH(r0, 1)                        @ r0<- CCBB
5218     mov     r9, rINST, lsr #8           @ r9<- AA
5219     mov     r3, r0, lsr #8              @ r3<- CC
5220     and     r2, r0, #255                @ r2<- BB
5221     GET_VREG(r1, r3)                    @ r1<- vCC
5222     GET_VREG(r0, r2)                    @ r0<- vBB
5223     .if 0
5224     cmp     r1, #0                      @ is second operand zero?
5225     beq     common_errDivideByZero
5226     .endif
5227
5228     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5229                                @ optional op; may set condition codes
5230     bl      __aeabi_fmul                              @ r0<- op, r0-r3 changed
5231     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5232     SET_VREG(r0, r9)               @ vAA<- r0
5233     GOTO_OPCODE(ip)                     @ jump to next instruction
5234     /* 11-14 instructions */
5235
5236
5237
5238 /* ------------------------------ */
5239     .balign 64
5240 .L_OP_DIV_FLOAT: /* 0xa9 */
5241 /* File: armv5te/OP_DIV_FLOAT.S */
5242 /* File: armv5te/binop.S */
5243     /*
5244      * Generic 32-bit binary operation.  Provide an "instr" line that
5245      * specifies an instruction that performs "result = r0 op r1".
5246      * This could be an ARM instruction or a function call.  (If the result
5247      * comes back in a register other than r0, you can override "result".)
5248      *
5249      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5250      * vCC (r1).  Useful for integer division and modulus.  Note that we
5251      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5252      * handles it correctly.
5253      *
5254      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5255      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5256      *      mul-float, div-float, rem-float
5257      */
5258     /* binop vAA, vBB, vCC */
5259     FETCH(r0, 1)                        @ r0<- CCBB
5260     mov     r9, rINST, lsr #8           @ r9<- AA
5261     mov     r3, r0, lsr #8              @ r3<- CC
5262     and     r2, r0, #255                @ r2<- BB
5263     GET_VREG(r1, r3)                    @ r1<- vCC
5264     GET_VREG(r0, r2)                    @ r0<- vBB
5265     .if 0
5266     cmp     r1, #0                      @ is second operand zero?
5267     beq     common_errDivideByZero
5268     .endif
5269
5270     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5271                                @ optional op; may set condition codes
5272     bl      __aeabi_fdiv                              @ r0<- op, r0-r3 changed
5273     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5274     SET_VREG(r0, r9)               @ vAA<- r0
5275     GOTO_OPCODE(ip)                     @ jump to next instruction
5276     /* 11-14 instructions */
5277
5278
5279
5280 /* ------------------------------ */
5281     .balign 64
5282 .L_OP_REM_FLOAT: /* 0xaa */
5283 /* File: armv5te/OP_REM_FLOAT.S */
5284 /* EABI doesn't define a float remainder function, but libm does */
5285 /* File: armv5te/binop.S */
5286     /*
5287      * Generic 32-bit binary operation.  Provide an "instr" line that
5288      * specifies an instruction that performs "result = r0 op r1".
5289      * This could be an ARM instruction or a function call.  (If the result
5290      * comes back in a register other than r0, you can override "result".)
5291      *
5292      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5293      * vCC (r1).  Useful for integer division and modulus.  Note that we
5294      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5295      * handles it correctly.
5296      *
5297      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5298      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5299      *      mul-float, div-float, rem-float
5300      */
5301     /* binop vAA, vBB, vCC */
5302     FETCH(r0, 1)                        @ r0<- CCBB
5303     mov     r9, rINST, lsr #8           @ r9<- AA
5304     mov     r3, r0, lsr #8              @ r3<- CC
5305     and     r2, r0, #255                @ r2<- BB
5306     GET_VREG(r1, r3)                    @ r1<- vCC
5307     GET_VREG(r0, r2)                    @ r0<- vBB
5308     .if 0
5309     cmp     r1, #0                      @ is second operand zero?
5310     beq     common_errDivideByZero
5311     .endif
5312
5313     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5314                                @ optional op; may set condition codes
5315     bl      fmodf                              @ r0<- op, r0-r3 changed
5316     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5317     SET_VREG(r0, r9)               @ vAA<- r0
5318     GOTO_OPCODE(ip)                     @ jump to next instruction
5319     /* 11-14 instructions */
5320
5321
5322
5323 /* ------------------------------ */
5324     .balign 64
5325 .L_OP_ADD_DOUBLE: /* 0xab */
5326 /* File: armv5te/OP_ADD_DOUBLE.S */
5327 /* File: armv5te/binopWide.S */
5328     /*
5329      * Generic 64-bit binary operation.  Provide an "instr" line that
5330      * specifies an instruction that performs "result = r0-r1 op r2-r3".
5331      * This could be an ARM instruction or a function call.  (If the result
5332      * comes back in a register other than r0, you can override "result".)
5333      *
5334      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5335      * vCC (r1).  Useful for integer division and modulus.
5336      *
5337      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5338      *      xor-long, add-double, sub-double, mul-double, div-double,
5339      *      rem-double
5340      *
5341      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5342      */
5343     /* binop vAA, vBB, vCC */
5344     FETCH(r0, 1)                        @ r0<- CCBB
5345     mov     r9, rINST, lsr #8           @ r9<- AA
5346     and     r2, r0, #255                @ r2<- BB
5347     mov     r3, r0, lsr #8              @ r3<- CC
5348     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5349     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5350     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5351     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5352     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5353     .if 0
5354     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5355     beq     common_errDivideByZero
5356     .endif
5357     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5358
5359                                @ optional op; may set condition codes
5360     bl      __aeabi_dadd                              @ result<- op, r0-r3 changed
5361     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5362     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5363     GOTO_OPCODE(ip)                     @ jump to next instruction
5364     /* 14-17 instructions */
5365
5366
5367
5368 /* ------------------------------ */
5369     .balign 64
5370 .L_OP_SUB_DOUBLE: /* 0xac */
5371 /* File: armv5te/OP_SUB_DOUBLE.S */
5372 /* File: armv5te/binopWide.S */
5373     /*
5374      * Generic 64-bit binary operation.  Provide an "instr" line that
5375      * specifies an instruction that performs "result = r0-r1 op r2-r3".
5376      * This could be an ARM instruction or a function call.  (If the result
5377      * comes back in a register other than r0, you can override "result".)
5378      *
5379      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5380      * vCC (r1).  Useful for integer division and modulus.
5381      *
5382      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5383      *      xor-long, add-double, sub-double, mul-double, div-double,
5384      *      rem-double
5385      *
5386      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5387      */
5388     /* binop vAA, vBB, vCC */
5389     FETCH(r0, 1)                        @ r0<- CCBB
5390     mov     r9, rINST, lsr #8           @ r9<- AA
5391     and     r2, r0, #255                @ r2<- BB
5392     mov     r3, r0, lsr #8              @ r3<- CC
5393     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5394     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5395     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5396     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5397     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5398     .if 0
5399     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5400     beq     common_errDivideByZero
5401     .endif
5402     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5403
5404                                @ optional op; may set condition codes
5405     bl      __aeabi_dsub                              @ result<- op, r0-r3 changed
5406     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5407     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5408     GOTO_OPCODE(ip)                     @ jump to next instruction
5409     /* 14-17 instructions */
5410
5411
5412
5413 /* ------------------------------ */
5414     .balign 64
5415 .L_OP_MUL_DOUBLE: /* 0xad */
5416 /* File: armv5te/OP_MUL_DOUBLE.S */
5417 /* File: armv5te/binopWide.S */
5418     /*
5419      * Generic 64-bit binary operation.  Provide an "instr" line that
5420      * specifies an instruction that performs "result = r0-r1 op r2-r3".
5421      * This could be an ARM instruction or a function call.  (If the result
5422      * comes back in a register other than r0, you can override "result".)
5423      *
5424      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5425      * vCC (r1).  Useful for integer division and modulus.
5426      *
5427      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5428      *      xor-long, add-double, sub-double, mul-double, div-double,
5429      *      rem-double
5430      *
5431      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5432      */
5433     /* binop vAA, vBB, vCC */
5434     FETCH(r0, 1)                        @ r0<- CCBB
5435     mov     r9, rINST, lsr #8           @ r9<- AA
5436     and     r2, r0, #255                @ r2<- BB
5437     mov     r3, r0, lsr #8              @ r3<- CC
5438     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5439     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5440     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5441     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5442     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5443     .if 0
5444     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5445     beq     common_errDivideByZero
5446     .endif
5447     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5448
5449                                @ optional op; may set condition codes
5450     bl      __aeabi_dmul                              @ result<- op, r0-r3 changed
5451     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5452     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5453     GOTO_OPCODE(ip)                     @ jump to next instruction
5454     /* 14-17 instructions */
5455
5456
5457
5458 /* ------------------------------ */
5459     .balign 64
5460 .L_OP_DIV_DOUBLE: /* 0xae */
5461 /* File: armv5te/OP_DIV_DOUBLE.S */
5462 /* File: armv5te/binopWide.S */
5463     /*
5464      * Generic 64-bit binary operation.  Provide an "instr" line that
5465      * specifies an instruction that performs "result = r0-r1 op r2-r3".
5466      * This could be an ARM instruction or a function call.  (If the result
5467      * comes back in a register other than r0, you can override "result".)
5468      *
5469      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5470      * vCC (r1).  Useful for integer division and modulus.
5471      *
5472      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5473      *      xor-long, add-double, sub-double, mul-double, div-double,
5474      *      rem-double
5475      *
5476      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5477      */
5478     /* binop vAA, vBB, vCC */
5479     FETCH(r0, 1)                        @ r0<- CCBB
5480     mov     r9, rINST, lsr #8           @ r9<- AA
5481     and     r2, r0, #255                @ r2<- BB
5482     mov     r3, r0, lsr #8              @ r3<- CC
5483     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5484     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5485     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5486     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5487     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5488     .if 0
5489     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5490     beq     common_errDivideByZero
5491     .endif
5492     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5493
5494                                @ optional op; may set condition codes
5495     bl      __aeabi_ddiv                              @ result<- op, r0-r3 changed
5496     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5497     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5498     GOTO_OPCODE(ip)                     @ jump to next instruction
5499     /* 14-17 instructions */
5500
5501
5502
5503 /* ------------------------------ */
5504     .balign 64
5505 .L_OP_REM_DOUBLE: /* 0xaf */
5506 /* File: armv5te/OP_REM_DOUBLE.S */
5507 /* EABI doesn't define a double remainder function, but libm does */
5508 /* File: armv5te/binopWide.S */
5509     /*
5510      * Generic 64-bit binary operation.  Provide an "instr" line that
5511      * specifies an instruction that performs "result = r0-r1 op r2-r3".
5512      * This could be an ARM instruction or a function call.  (If the result
5513      * comes back in a register other than r0, you can override "result".)
5514      *
5515      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5516      * vCC (r1).  Useful for integer division and modulus.
5517      *
5518      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5519      *      xor-long, add-double, sub-double, mul-double, div-double,
5520      *      rem-double
5521      *
5522      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5523      */
5524     /* binop vAA, vBB, vCC */
5525     FETCH(r0, 1)                        @ r0<- CCBB
5526     mov     r9, rINST, lsr #8           @ r9<- AA
5527     and     r2, r0, #255                @ r2<- BB
5528     mov     r3, r0, lsr #8              @ r3<- CC
5529     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5530     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5531     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5532     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5533     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5534     .if 0
5535     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5536     beq     common_errDivideByZero
5537     .endif
5538     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5539
5540                                @ optional op; may set condition codes
5541     bl      fmod                              @ result<- op, r0-r3 changed
5542     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5543     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5544     GOTO_OPCODE(ip)                     @ jump to next instruction
5545     /* 14-17 instructions */
5546
5547
5548
5549 /* ------------------------------ */
5550     .balign 64
5551 .L_OP_ADD_INT_2ADDR: /* 0xb0 */
5552 /* File: armv5te/OP_ADD_INT_2ADDR.S */
5553 /* File: armv5te/binop2addr.S */
5554     /*
5555      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5556      * that specifies an instruction that performs "result = r0 op r1".
5557      * This could be an ARM instruction or a function call.  (If the result
5558      * comes back in a register other than r0, you can override "result".)
5559      *
5560      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5561      * vCC (r1).  Useful for integer division and modulus.
5562      *
5563      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5564      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5565      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5566      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5567      */
5568     /* binop/2addr vA, vB */
5569     mov     r9, rINST, lsr #8           @ r9<- A+
5570     mov     r3, rINST, lsr #12          @ r3<- B
5571     and     r9, r9, #15
5572     GET_VREG(r1, r3)                    @ r1<- vB
5573     GET_VREG(r0, r9)                    @ r0<- vA
5574     .if 0
5575     cmp     r1, #0                      @ is second operand zero?
5576     beq     common_errDivideByZero
5577     .endif
5578     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5579
5580                                @ optional op; may set condition codes
5581     add     r0, r0, r1                              @ r0<- op, r0-r3 changed
5582     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5583     SET_VREG(r0, r9)               @ vAA<- r0
5584     GOTO_OPCODE(ip)                     @ jump to next instruction
5585     /* 10-13 instructions */
5586
5587
5588
5589 /* ------------------------------ */
5590     .balign 64
5591 .L_OP_SUB_INT_2ADDR: /* 0xb1 */
5592 /* File: armv5te/OP_SUB_INT_2ADDR.S */
5593 /* File: armv5te/binop2addr.S */
5594     /*
5595      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5596      * that specifies an instruction that performs "result = r0 op r1".
5597      * This could be an ARM instruction or a function call.  (If the result
5598      * comes back in a register other than r0, you can override "result".)
5599      *
5600      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5601      * vCC (r1).  Useful for integer division and modulus.
5602      *
5603      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5604      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5605      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5606      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5607      */
5608     /* binop/2addr vA, vB */
5609     mov     r9, rINST, lsr #8           @ r9<- A+
5610     mov     r3, rINST, lsr #12          @ r3<- B
5611     and     r9, r9, #15
5612     GET_VREG(r1, r3)                    @ r1<- vB
5613     GET_VREG(r0, r9)                    @ r0<- vA
5614     .if 0
5615     cmp     r1, #0                      @ is second operand zero?
5616     beq     common_errDivideByZero
5617     .endif
5618     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5619
5620                                @ optional op; may set condition codes
5621     sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
5622     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5623     SET_VREG(r0, r9)               @ vAA<- r0
5624     GOTO_OPCODE(ip)                     @ jump to next instruction
5625     /* 10-13 instructions */
5626
5627
5628
5629 /* ------------------------------ */
5630     .balign 64
5631 .L_OP_MUL_INT_2ADDR: /* 0xb2 */
5632 /* File: armv5te/OP_MUL_INT_2ADDR.S */
5633 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
5634 /* File: armv5te/binop2addr.S */
5635     /*
5636      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5637      * that specifies an instruction that performs "result = r0 op r1".
5638      * This could be an ARM instruction or a function call.  (If the result
5639      * comes back in a register other than r0, you can override "result".)
5640      *
5641      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5642      * vCC (r1).  Useful for integer division and modulus.
5643      *
5644      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5645      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5646      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5647      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5648      */
5649     /* binop/2addr vA, vB */
5650     mov     r9, rINST, lsr #8           @ r9<- A+
5651     mov     r3, rINST, lsr #12          @ r3<- B
5652     and     r9, r9, #15
5653     GET_VREG(r1, r3)                    @ r1<- vB
5654     GET_VREG(r0, r9)                    @ r0<- vA
5655     .if 0
5656     cmp     r1, #0                      @ is second operand zero?
5657     beq     common_errDivideByZero
5658     .endif
5659     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5660
5661                                @ optional op; may set condition codes
5662     mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
5663     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5664     SET_VREG(r0, r9)               @ vAA<- r0
5665     GOTO_OPCODE(ip)                     @ jump to next instruction
5666     /* 10-13 instructions */
5667
5668
5669
5670 /* ------------------------------ */
5671     .balign 64
5672 .L_OP_DIV_INT_2ADDR: /* 0xb3 */
5673 /* File: armv5te/OP_DIV_INT_2ADDR.S */
5674 /* File: armv5te/binop2addr.S */
5675     /*
5676      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5677      * that specifies an instruction that performs "result = r0 op r1".
5678      * This could be an ARM instruction or a function call.  (If the result
5679      * comes back in a register other than r0, you can override "result".)
5680      *
5681      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5682      * vCC (r1).  Useful for integer division and modulus.
5683      *
5684      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5685      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5686      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5687      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5688      */
5689     /* binop/2addr vA, vB */
5690     mov     r9, rINST, lsr #8           @ r9<- A+
5691     mov     r3, rINST, lsr #12          @ r3<- B
5692     and     r9, r9, #15
5693     GET_VREG(r1, r3)                    @ r1<- vB
5694     GET_VREG(r0, r9)                    @ r0<- vA
5695     .if 1
5696     cmp     r1, #0                      @ is second operand zero?
5697     beq     common_errDivideByZero
5698     .endif
5699     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5700
5701                                @ optional op; may set condition codes
5702     bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
5703     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5704     SET_VREG(r0, r9)               @ vAA<- r0
5705     GOTO_OPCODE(ip)                     @ jump to next instruction
5706     /* 10-13 instructions */
5707
5708
5709
5710 /* ------------------------------ */
5711     .balign 64
5712 .L_OP_REM_INT_2ADDR: /* 0xb4 */
5713 /* File: armv5te/OP_REM_INT_2ADDR.S */
5714 /* idivmod returns quotient in r0 and remainder in r1 */
5715 /* File: armv5te/binop2addr.S */
5716     /*
5717      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5718      * that specifies an instruction that performs "result = r0 op r1".
5719      * This could be an ARM instruction or a function call.  (If the result
5720      * comes back in a register other than r0, you can override "result".)
5721      *
5722      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5723      * vCC (r1).  Useful for integer division and modulus.
5724      *
5725      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5726      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5727      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5728      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5729      */
5730     /* binop/2addr vA, vB */
5731     mov     r9, rINST, lsr #8           @ r9<- A+
5732     mov     r3, rINST, lsr #12          @ r3<- B
5733     and     r9, r9, #15
5734     GET_VREG(r1, r3)                    @ r1<- vB
5735     GET_VREG(r0, r9)                    @ r0<- vA
5736     .if 1
5737     cmp     r1, #0                      @ is second operand zero?
5738     beq     common_errDivideByZero
5739     .endif
5740     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5741
5742                                @ optional op; may set condition codes
5743     bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
5744     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5745     SET_VREG(r1, r9)               @ vAA<- r1
5746     GOTO_OPCODE(ip)                     @ jump to next instruction
5747     /* 10-13 instructions */
5748
5749
5750
5751 /* ------------------------------ */
5752     .balign 64
5753 .L_OP_AND_INT_2ADDR: /* 0xb5 */
5754 /* File: armv5te/OP_AND_INT_2ADDR.S */
5755 /* File: armv5te/binop2addr.S */
5756     /*
5757      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5758      * that specifies an instruction that performs "result = r0 op r1".
5759      * This could be an ARM instruction or a function call.  (If the result
5760      * comes back in a register other than r0, you can override "result".)
5761      *
5762      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5763      * vCC (r1).  Useful for integer division and modulus.
5764      *
5765      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5766      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5767      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5768      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5769      */
5770     /* binop/2addr vA, vB */
5771     mov     r9, rINST, lsr #8           @ r9<- A+
5772     mov     r3, rINST, lsr #12          @ r3<- B
5773     and     r9, r9, #15
5774     GET_VREG(r1, r3)                    @ r1<- vB
5775     GET_VREG(r0, r9)                    @ r0<- vA
5776     .if 0
5777     cmp     r1, #0                      @ is second operand zero?
5778     beq     common_errDivideByZero
5779     .endif
5780     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5781
5782                                @ optional op; may set condition codes
5783     and     r0, r0, r1                              @ r0<- op, r0-r3 changed
5784     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5785     SET_VREG(r0, r9)               @ vAA<- r0
5786     GOTO_OPCODE(ip)                     @ jump to next instruction
5787     /* 10-13 instructions */
5788
5789
5790
5791 /* ------------------------------ */
5792     .balign 64
5793 .L_OP_OR_INT_2ADDR: /* 0xb6 */
5794 /* File: armv5te/OP_OR_INT_2ADDR.S */
5795 /* File: armv5te/binop2addr.S */
5796     /*
5797      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5798      * that specifies an instruction that performs "result = r0 op r1".
5799      * This could be an ARM instruction or a function call.  (If the result
5800      * comes back in a register other than r0, you can override "result".)
5801      *
5802      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5803      * vCC (r1).  Useful for integer division and modulus.
5804      *
5805      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5806      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5807      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5808      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5809      */
5810     /* binop/2addr vA, vB */
5811     mov     r9, rINST, lsr #8           @ r9<- A+
5812     mov     r3, rINST, lsr #12          @ r3<- B
5813     and     r9, r9, #15
5814     GET_VREG(r1, r3)                    @ r1<- vB
5815     GET_VREG(r0, r9)                    @ r0<- vA
5816     .if 0
5817     cmp     r1, #0                      @ is second operand zero?
5818     beq     common_errDivideByZero
5819     .endif
5820     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5821
5822                                @ optional op; may set condition codes
5823     orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
5824     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5825     SET_VREG(r0, r9)               @ vAA<- r0
5826     GOTO_OPCODE(ip)                     @ jump to next instruction
5827     /* 10-13 instructions */
5828
5829
5830
5831 /* ------------------------------ */
5832     .balign 64
5833 .L_OP_XOR_INT_2ADDR: /* 0xb7 */
5834 /* File: armv5te/OP_XOR_INT_2ADDR.S */
5835 /* File: armv5te/binop2addr.S */
5836     /*
5837      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5838      * that specifies an instruction that performs "result = r0 op r1".
5839      * This could be an ARM instruction or a function call.  (If the result
5840      * comes back in a register other than r0, you can override "result".)
5841      *
5842      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5843      * vCC (r1).  Useful for integer division and modulus.
5844      *
5845      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5846      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5847      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5848      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5849      */
5850     /* binop/2addr vA, vB */
5851     mov     r9, rINST, lsr #8           @ r9<- A+
5852     mov     r3, rINST, lsr #12          @ r3<- B
5853     and     r9, r9, #15
5854     GET_VREG(r1, r3)                    @ r1<- vB
5855     GET_VREG(r0, r9)                    @ r0<- vA
5856     .if 0
5857     cmp     r1, #0                      @ is second operand zero?
5858     beq     common_errDivideByZero
5859     .endif
5860     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5861
5862                                @ optional op; may set condition codes
5863     eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
5864     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5865     SET_VREG(r0, r9)               @ vAA<- r0
5866     GOTO_OPCODE(ip)                     @ jump to next instruction
5867     /* 10-13 instructions */
5868
5869
5870
5871 /* ------------------------------ */
5872     .balign 64
5873 .L_OP_SHL_INT_2ADDR: /* 0xb8 */
5874 /* File: armv5te/OP_SHL_INT_2ADDR.S */
5875 /* File: armv5te/binop2addr.S */
5876     /*
5877      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5878      * that specifies an instruction that performs "result = r0 op r1".
5879      * This could be an ARM instruction or a function call.  (If the result
5880      * comes back in a register other than r0, you can override "result".)
5881      *
5882      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5883      * vCC (r1).  Useful for integer division and modulus.
5884      *
5885      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5886      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5887      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5888      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5889      */
5890     /* binop/2addr vA, vB */
5891     mov     r9, rINST, lsr #8           @ r9<- A+
5892     mov     r3, rINST, lsr #12          @ r3<- B
5893     and     r9, r9, #15
5894     GET_VREG(r1, r3)                    @ r1<- vB
5895     GET_VREG(r0, r9)                    @ r0<- vA
5896     .if 0
5897     cmp     r1, #0                      @ is second operand zero?
5898     beq     common_errDivideByZero
5899     .endif
5900     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5901
5902     and     r1, r1, #31                           @ optional op; may set condition codes
5903     mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
5904     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5905     SET_VREG(r0, r9)               @ vAA<- r0
5906     GOTO_OPCODE(ip)                     @ jump to next instruction
5907     /* 10-13 instructions */
5908
5909
5910
5911 /* ------------------------------ */
5912     .balign 64
5913 .L_OP_SHR_INT_2ADDR: /* 0xb9 */
5914 /* File: armv5te/OP_SHR_INT_2ADDR.S */
5915 /* File: armv5te/binop2addr.S */
5916     /*
5917      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5918      * that specifies an instruction that performs "result = r0 op r1".
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-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5926      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5927      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5928      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5929      */
5930     /* binop/2addr vA, vB */
5931     mov     r9, rINST, lsr #8           @ r9<- A+
5932     mov     r3, rINST, lsr #12          @ r3<- B
5933     and     r9, r9, #15
5934     GET_VREG(r1, r3)                    @ r1<- vB
5935     GET_VREG(r0, r9)                    @ r0<- vA
5936     .if 0
5937     cmp     r1, #0                      @ is second operand zero?
5938     beq     common_errDivideByZero
5939     .endif
5940     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5941
5942     and     r1, r1, #31                           @ optional op; may set condition codes
5943     mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
5944     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5945     SET_VREG(r0, r9)               @ vAA<- r0
5946     GOTO_OPCODE(ip)                     @ jump to next instruction
5947     /* 10-13 instructions */
5948
5949
5950
5951 /* ------------------------------ */
5952     .balign 64
5953 .L_OP_USHR_INT_2ADDR: /* 0xba */
5954 /* File: armv5te/OP_USHR_INT_2ADDR.S */
5955 /* File: armv5te/binop2addr.S */
5956     /*
5957      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5958      * that specifies an instruction that performs "result = r0 op r1".
5959      * This could be an ARM instruction or a function call.  (If the result
5960      * comes back in a register other than r0, you can override "result".)
5961      *
5962      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5963      * vCC (r1).  Useful for integer division and modulus.
5964      *
5965      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5966      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5967      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5968      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5969      */
5970     /* binop/2addr vA, vB */
5971     mov     r9, rINST, lsr #8           @ r9<- A+
5972     mov     r3, rINST, lsr #12          @ r3<- B
5973     and     r9, r9, #15
5974     GET_VREG(r1, r3)                    @ r1<- vB
5975     GET_VREG(r0, r9)                    @ r0<- vA
5976     .if 0
5977     cmp     r1, #0                      @ is second operand zero?
5978     beq     common_errDivideByZero
5979     .endif
5980     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5981
5982     and     r1, r1, #31                           @ optional op; may set condition codes
5983     mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
5984     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5985     SET_VREG(r0, r9)               @ vAA<- r0
5986     GOTO_OPCODE(ip)                     @ jump to next instruction
5987     /* 10-13 instructions */
5988
5989
5990
5991 /* ------------------------------ */
5992     .balign 64
5993 .L_OP_ADD_LONG_2ADDR: /* 0xbb */
5994 /* File: armv5te/OP_ADD_LONG_2ADDR.S */
5995 /* File: armv5te/binopWide2addr.S */
5996     /*
5997      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5998      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5999      * This could be an ARM instruction or a function call.  (If the result
6000      * comes back in a register other than r0, you can override "result".)
6001      *
6002      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6003      * vCC (r1).  Useful for integer division and modulus.
6004      *
6005      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6006      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6007      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6008      *      rem-double/2addr
6009      */
6010     /* binop/2addr vA, vB */
6011     mov     r9, rINST, lsr #8           @ r9<- A+
6012     mov     r1, rINST, lsr #12          @ r1<- B
6013     and     r9, r9, #15
6014     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6015     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6016     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6017     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6018     .if 0
6019     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6020     beq     common_errDivideByZero
6021     .endif
6022     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6023
6024     adds    r0, r0, r2                           @ optional op; may set condition codes
6025     adc     r1, r1, r3                              @ result<- op, r0-r3 changed
6026     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6027     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6028     GOTO_OPCODE(ip)                     @ jump to next instruction
6029     /* 12-15 instructions */
6030
6031
6032
6033 /* ------------------------------ */
6034     .balign 64
6035 .L_OP_SUB_LONG_2ADDR: /* 0xbc */
6036 /* File: armv5te/OP_SUB_LONG_2ADDR.S */
6037 /* File: armv5te/binopWide2addr.S */
6038     /*
6039      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6040      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6041      * This could be an ARM instruction or a function call.  (If the result
6042      * comes back in a register other than r0, you can override "result".)
6043      *
6044      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6045      * vCC (r1).  Useful for integer division and modulus.
6046      *
6047      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6048      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6049      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6050      *      rem-double/2addr
6051      */
6052     /* binop/2addr vA, vB */
6053     mov     r9, rINST, lsr #8           @ r9<- A+
6054     mov     r1, rINST, lsr #12          @ r1<- B
6055     and     r9, r9, #15
6056     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6057     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6058     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6059     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6060     .if 0
6061     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6062     beq     common_errDivideByZero
6063     .endif
6064     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6065
6066     subs    r0, r0, r2                           @ optional op; may set condition codes
6067     sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
6068     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6069     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6070     GOTO_OPCODE(ip)                     @ jump to next instruction
6071     /* 12-15 instructions */
6072
6073
6074
6075 /* ------------------------------ */
6076     .balign 64
6077 .L_OP_MUL_LONG_2ADDR: /* 0xbd */
6078 /* File: armv5te/OP_MUL_LONG_2ADDR.S */
6079     /*
6080      * Signed 64-bit integer multiply, "/2addr" version.
6081      *
6082      * See OP_MUL_LONG for an explanation.
6083      *
6084      * We get a little tight on registers, so to avoid looking up &fp[A]
6085      * again we stuff it into rINST.
6086      */
6087     /* mul-long/2addr vA, vB */
6088     mov     r9, rINST, lsr #8           @ r9<- A+
6089     mov     r1, rINST, lsr #12          @ r1<- B
6090     and     r9, r9, #15
6091     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6092     add     rINST, rFP, r9, lsl #2      @ rINST<- &fp[A]
6093     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6094     ldmia   rINST, {r0-r1}              @ r0/r1<- vAA/vAA+1
6095     mul     ip, r2, r1                  @  ip<- ZxW
6096     umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
6097     mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
6098     mov     r0, rINST                   @ r0<- &fp[A] (free up rINST)
6099     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6100     add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
6101     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6102     stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
6103     GOTO_OPCODE(ip)                     @ jump to next instruction
6104
6105
6106 /* ------------------------------ */
6107     .balign 64
6108 .L_OP_DIV_LONG_2ADDR: /* 0xbe */
6109 /* File: armv5te/OP_DIV_LONG_2ADDR.S */
6110 /* File: armv5te/binopWide2addr.S */
6111     /*
6112      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6113      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6114      * This could be an ARM instruction or a function call.  (If the result
6115      * comes back in a register other than r0, you can override "result".)
6116      *
6117      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6118      * vCC (r1).  Useful for integer division and modulus.
6119      *
6120      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6121      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6122      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6123      *      rem-double/2addr
6124      */
6125     /* binop/2addr vA, vB */
6126     mov     r9, rINST, lsr #8           @ r9<- A+
6127     mov     r1, rINST, lsr #12          @ r1<- B
6128     and     r9, r9, #15
6129     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6130     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6131     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6132     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6133     .if 1
6134     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6135     beq     common_errDivideByZero
6136     .endif
6137     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6138
6139                                @ optional op; may set condition codes
6140     bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
6141     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6142     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6143     GOTO_OPCODE(ip)                     @ jump to next instruction
6144     /* 12-15 instructions */
6145
6146
6147
6148 /* ------------------------------ */
6149     .balign 64
6150 .L_OP_REM_LONG_2ADDR: /* 0xbf */
6151 /* File: armv5te/OP_REM_LONG_2ADDR.S */
6152 /* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
6153 /* File: armv5te/binopWide2addr.S */
6154     /*
6155      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6156      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6157      * This could be an ARM instruction or a function call.  (If the result
6158      * comes back in a register other than r0, you can override "result".)
6159      *
6160      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6161      * vCC (r1).  Useful for integer division and modulus.
6162      *
6163      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6164      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6165      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6166      *      rem-double/2addr
6167      */
6168     /* binop/2addr vA, vB */
6169     mov     r9, rINST, lsr #8           @ r9<- A+
6170     mov     r1, rINST, lsr #12          @ r1<- B
6171     and     r9, r9, #15
6172     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6173     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6174     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6175     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6176     .if 1
6177     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6178     beq     common_errDivideByZero
6179     .endif
6180     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6181
6182                                @ optional op; may set condition codes
6183     bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
6184     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6185     stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
6186     GOTO_OPCODE(ip)                     @ jump to next instruction
6187     /* 12-15 instructions */
6188
6189
6190
6191 /* ------------------------------ */
6192     .balign 64
6193 .L_OP_AND_LONG_2ADDR: /* 0xc0 */
6194 /* File: armv5te/OP_AND_LONG_2ADDR.S */
6195 /* File: armv5te/binopWide2addr.S */
6196     /*
6197      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6198      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6199      * This could be an ARM instruction or a function call.  (If the result
6200      * comes back in a register other than r0, you can override "result".)
6201      *
6202      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6203      * vCC (r1).  Useful for integer division and modulus.
6204      *
6205      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6206      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6207      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6208      *      rem-double/2addr
6209      */
6210     /* binop/2addr vA, vB */
6211     mov     r9, rINST, lsr #8           @ r9<- A+
6212     mov     r1, rINST, lsr #12          @ r1<- B
6213     and     r9, r9, #15
6214     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6215     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6216     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6217     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6218     .if 0
6219     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6220     beq     common_errDivideByZero
6221     .endif
6222     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6223
6224     and     r0, r0, r2                           @ optional op; may set condition codes
6225     and     r1, r1, r3                              @ result<- op, r0-r3 changed
6226     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6227     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6228     GOTO_OPCODE(ip)                     @ jump to next instruction
6229     /* 12-15 instructions */
6230
6231
6232
6233 /* ------------------------------ */
6234     .balign 64
6235 .L_OP_OR_LONG_2ADDR: /* 0xc1 */
6236 /* File: armv5te/OP_OR_LONG_2ADDR.S */
6237 /* File: armv5te/binopWide2addr.S */
6238     /*
6239      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6240      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6241      * This could be an ARM instruction or a function call.  (If the result
6242      * comes back in a register other than r0, you can override "result".)
6243      *
6244      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6245      * vCC (r1).  Useful for integer division and modulus.
6246      *
6247      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6248      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6249      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6250      *      rem-double/2addr
6251      */
6252     /* binop/2addr vA, vB */
6253     mov     r9, rINST, lsr #8           @ r9<- A+
6254     mov     r1, rINST, lsr #12          @ r1<- B
6255     and     r9, r9, #15
6256     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6257     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6258     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6259     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6260     .if 0
6261     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6262     beq     common_errDivideByZero
6263     .endif
6264     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6265
6266     orr     r0, r0, r2                           @ optional op; may set condition codes
6267     orr     r1, r1, r3                              @ result<- op, r0-r3 changed
6268     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6269     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6270     GOTO_OPCODE(ip)                     @ jump to next instruction
6271     /* 12-15 instructions */
6272
6273
6274
6275 /* ------------------------------ */
6276     .balign 64
6277 .L_OP_XOR_LONG_2ADDR: /* 0xc2 */
6278 /* File: armv5te/OP_XOR_LONG_2ADDR.S */
6279 /* File: armv5te/binopWide2addr.S */
6280     /*
6281      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6282      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6283      * This could be an ARM instruction or a function call.  (If the result
6284      * comes back in a register other than r0, you can override "result".)
6285      *
6286      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6287      * vCC (r1).  Useful for integer division and modulus.
6288      *
6289      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6290      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6291      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6292      *      rem-double/2addr
6293      */
6294     /* binop/2addr vA, vB */
6295     mov     r9, rINST, lsr #8           @ r9<- A+
6296     mov     r1, rINST, lsr #12          @ r1<- B
6297     and     r9, r9, #15
6298     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6299     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6300     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6301     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6302     .if 0
6303     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6304     beq     common_errDivideByZero
6305     .endif
6306     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6307
6308     eor     r0, r0, r2                           @ optional op; may set condition codes
6309     eor     r1, r1, r3                              @ result<- op, r0-r3 changed
6310     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6311     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6312     GOTO_OPCODE(ip)                     @ jump to next instruction
6313     /* 12-15 instructions */
6314
6315
6316
6317 /* ------------------------------ */
6318     .balign 64
6319 .L_OP_SHL_LONG_2ADDR: /* 0xc3 */
6320 /* File: armv5te/OP_SHL_LONG_2ADDR.S */
6321     /*
6322      * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6323      * 32-bit shift distance.
6324      */
6325     /* shl-long/2addr vA, vB */
6326     mov     r9, rINST, lsr #8           @ r9<- A+
6327     mov     r3, rINST, lsr #12          @ r3<- B
6328     and     r9, r9, #15
6329     GET_VREG(r2, r3)                    @ r2<- vB
6330     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6331     and     r2, r2, #63                 @ r2<- r2 & 0x3f
6332     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6333
6334     mov     r1, r1, asl r2              @  r1<- r1 << r2
6335     rsb     r3, r2, #32                 @  r3<- 32 - r2
6336     orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
6337     subs    ip, r2, #32                 @  ip<- r2 - 32
6338     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6339     movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
6340     mov     r0, r0, asl r2              @  r0<- r0 << r2
6341     b       .LOP_SHL_LONG_2ADDR_finish
6342
6343 /* ------------------------------ */
6344     .balign 64
6345 .L_OP_SHR_LONG_2ADDR: /* 0xc4 */
6346 /* File: armv5te/OP_SHR_LONG_2ADDR.S */
6347     /*
6348      * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6349      * 32-bit shift distance.
6350      */
6351     /* shr-long/2addr vA, vB */
6352     mov     r9, rINST, lsr #8           @ r9<- A+
6353     mov     r3, rINST, lsr #12          @ r3<- B
6354     and     r9, r9, #15
6355     GET_VREG(r2, r3)                    @ r2<- vB
6356     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6357     and     r2, r2, #63                 @ r2<- r2 & 0x3f
6358     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6359
6360     mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6361     rsb     r3, r2, #32                 @  r3<- 32 - r2
6362     orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6363     subs    ip, r2, #32                 @  ip<- r2 - 32
6364     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6365     movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
6366     mov     r1, r1, asr r2              @  r1<- r1 >> r2
6367     b       .LOP_SHR_LONG_2ADDR_finish
6368
6369 /* ------------------------------ */
6370     .balign 64
6371 .L_OP_USHR_LONG_2ADDR: /* 0xc5 */
6372 /* File: armv5te/OP_USHR_LONG_2ADDR.S */
6373     /*
6374      * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6375      * 32-bit shift distance.
6376      */
6377     /* ushr-long/2addr vA, vB */
6378     mov     r9, rINST, lsr #8           @ r9<- A+
6379     mov     r3, rINST, lsr #12          @ r3<- B
6380     and     r9, r9, #15
6381     GET_VREG(r2, r3)                    @ r2<- vB
6382     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6383     and     r2, r2, #63                 @ r2<- r2 & 0x3f
6384     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6385
6386     mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6387     rsb     r3, r2, #32                 @  r3<- 32 - r2
6388     orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6389     subs    ip, r2, #32                 @  ip<- r2 - 32
6390     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6391     movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
6392     mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
6393     b       .LOP_USHR_LONG_2ADDR_finish
6394
6395 /* ------------------------------ */
6396     .balign 64
6397 .L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
6398 /* File: armv5te/OP_ADD_FLOAT_2ADDR.S */
6399 /* File: armv5te/binop2addr.S */
6400     /*
6401      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6402      * that specifies an instruction that performs "result = r0 op r1".
6403      * This could be an ARM instruction or a function call.  (If the result
6404      * comes back in a register other than r0, you can override "result".)
6405      *
6406      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6407      * vCC (r1).  Useful for integer division and modulus.
6408      *
6409      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6410      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6411      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6412      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6413      */
6414     /* binop/2addr vA, vB */
6415     mov     r9, rINST, lsr #8           @ r9<- A+
6416     mov     r3, rINST, lsr #12          @ r3<- B
6417     and     r9, r9, #15
6418     GET_VREG(r1, r3)                    @ r1<- vB
6419     GET_VREG(r0, r9)                    @ r0<- vA
6420     .if 0
6421     cmp     r1, #0                      @ is second operand zero?
6422     beq     common_errDivideByZero
6423     .endif
6424     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6425
6426                                @ optional op; may set condition codes
6427     bl      __aeabi_fadd                              @ r0<- op, r0-r3 changed
6428     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6429     SET_VREG(r0, r9)               @ vAA<- r0
6430     GOTO_OPCODE(ip)                     @ jump to next instruction
6431     /* 10-13 instructions */
6432
6433
6434
6435 /* ------------------------------ */
6436     .balign 64
6437 .L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
6438 /* File: armv5te/OP_SUB_FLOAT_2ADDR.S */
6439 /* File: armv5te/binop2addr.S */
6440     /*
6441      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6442      * that specifies an instruction that performs "result = r0 op r1".
6443      * This could be an ARM instruction or a function call.  (If the result
6444      * comes back in a register other than r0, you can override "result".)
6445      *
6446      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6447      * vCC (r1).  Useful for integer division and modulus.
6448      *
6449      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6450      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6451      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6452      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6453      */
6454     /* binop/2addr vA, vB */
6455     mov     r9, rINST, lsr #8           @ r9<- A+
6456     mov     r3, rINST, lsr #12          @ r3<- B
6457     and     r9, r9, #15
6458     GET_VREG(r1, r3)                    @ r1<- vB
6459     GET_VREG(r0, r9)                    @ r0<- vA
6460     .if 0
6461     cmp     r1, #0                      @ is second operand zero?
6462     beq     common_errDivideByZero
6463     .endif
6464     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6465
6466                                @ optional op; may set condition codes
6467     bl      __aeabi_fsub                              @ r0<- op, r0-r3 changed
6468     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6469     SET_VREG(r0, r9)               @ vAA<- r0
6470     GOTO_OPCODE(ip)                     @ jump to next instruction
6471     /* 10-13 instructions */
6472
6473
6474
6475 /* ------------------------------ */
6476     .balign 64
6477 .L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
6478 /* File: armv5te/OP_MUL_FLOAT_2ADDR.S */
6479 /* File: armv5te/binop2addr.S */
6480     /*
6481      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6482      * that specifies an instruction that performs "result = r0 op r1".
6483      * This could be an ARM instruction or a function call.  (If the result
6484      * comes back in a register other than r0, you can override "result".)
6485      *
6486      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6487      * vCC (r1).  Useful for integer division and modulus.
6488      *
6489      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6490      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6491      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6492      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6493      */
6494     /* binop/2addr vA, vB */
6495     mov     r9, rINST, lsr #8           @ r9<- A+
6496     mov     r3, rINST, lsr #12          @ r3<- B
6497     and     r9, r9, #15
6498     GET_VREG(r1, r3)                    @ r1<- vB
6499     GET_VREG(r0, r9)                    @ r0<- vA
6500     .if 0
6501     cmp     r1, #0                      @ is second operand zero?
6502     beq     common_errDivideByZero
6503     .endif
6504     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6505
6506                                @ optional op; may set condition codes
6507     bl      __aeabi_fmul                              @ r0<- op, r0-r3 changed
6508     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6509     SET_VREG(r0, r9)               @ vAA<- r0
6510     GOTO_OPCODE(ip)                     @ jump to next instruction
6511     /* 10-13 instructions */
6512
6513
6514
6515 /* ------------------------------ */
6516     .balign 64
6517 .L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
6518 /* File: armv5te/OP_DIV_FLOAT_2ADDR.S */
6519 /* File: armv5te/binop2addr.S */
6520     /*
6521      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6522      * that specifies an instruction that performs "result = r0 op r1".
6523      * This could be an ARM instruction or a function call.  (If the result
6524      * comes back in a register other than r0, you can override "result".)
6525      *
6526      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6527      * vCC (r1).  Useful for integer division and modulus.
6528      *
6529      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6530      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6531      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6532      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6533      */
6534     /* binop/2addr vA, vB */
6535     mov     r9, rINST, lsr #8           @ r9<- A+
6536     mov     r3, rINST, lsr #12          @ r3<- B
6537     and     r9, r9, #15
6538     GET_VREG(r1, r3)                    @ r1<- vB
6539     GET_VREG(r0, r9)                    @ r0<- vA
6540     .if 0
6541     cmp     r1, #0                      @ is second operand zero?
6542     beq     common_errDivideByZero
6543     .endif
6544     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6545
6546                                @ optional op; may set condition codes
6547     bl      __aeabi_fdiv                              @ r0<- op, r0-r3 changed
6548     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6549     SET_VREG(r0, r9)               @ vAA<- r0
6550     GOTO_OPCODE(ip)                     @ jump to next instruction
6551     /* 10-13 instructions */
6552
6553
6554
6555 /* ------------------------------ */
6556     .balign 64
6557 .L_OP_REM_FLOAT_2ADDR: /* 0xca */
6558 /* File: armv5te/OP_REM_FLOAT_2ADDR.S */
6559 /* EABI doesn't define a float remainder function, but libm does */
6560 /* File: armv5te/binop2addr.S */
6561     /*
6562      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6563      * that specifies an instruction that performs "result = r0 op r1".
6564      * This could be an ARM instruction or a function call.  (If the result
6565      * comes back in a register other than r0, you can override "result".)
6566      *
6567      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6568      * vCC (r1).  Useful for integer division and modulus.
6569      *
6570      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6571      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6572      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6573      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6574      */
6575     /* binop/2addr vA, vB */
6576     mov     r9, rINST, lsr #8           @ r9<- A+
6577     mov     r3, rINST, lsr #12          @ r3<- B
6578     and     r9, r9, #15
6579     GET_VREG(r1, r3)                    @ r1<- vB
6580     GET_VREG(r0, r9)                    @ r0<- vA
6581     .if 0
6582     cmp     r1, #0                      @ is second operand zero?
6583     beq     common_errDivideByZero
6584     .endif
6585     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6586
6587                                @ optional op; may set condition codes
6588     bl      fmodf                              @ r0<- op, r0-r3 changed
6589     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6590     SET_VREG(r0, r9)               @ vAA<- r0
6591     GOTO_OPCODE(ip)                     @ jump to next instruction
6592     /* 10-13 instructions */
6593
6594
6595
6596 /* ------------------------------ */
6597     .balign 64
6598 .L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
6599 /* File: armv5te/OP_ADD_DOUBLE_2ADDR.S */
6600 /* File: armv5te/binopWide2addr.S */
6601     /*
6602      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6603      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6604      * This could be an ARM instruction or a function call.  (If the result
6605      * comes back in a register other than r0, you can override "result".)
6606      *
6607      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6608      * vCC (r1).  Useful for integer division and modulus.
6609      *
6610      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6611      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6612      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6613      *      rem-double/2addr
6614      */
6615     /* binop/2addr vA, vB */
6616     mov     r9, rINST, lsr #8           @ r9<- A+
6617     mov     r1, rINST, lsr #12          @ r1<- B
6618     and     r9, r9, #15
6619     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6620     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6621     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6622     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6623     .if 0
6624     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6625     beq     common_errDivideByZero
6626     .endif
6627     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6628
6629                                @ optional op; may set condition codes
6630     bl      __aeabi_dadd                              @ result<- op, r0-r3 changed
6631     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6632     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6633     GOTO_OPCODE(ip)                     @ jump to next instruction
6634     /* 12-15 instructions */
6635
6636
6637
6638 /* ------------------------------ */
6639     .balign 64
6640 .L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
6641 /* File: armv5te/OP_SUB_DOUBLE_2ADDR.S */
6642 /* File: armv5te/binopWide2addr.S */
6643     /*
6644      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6645      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
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-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6653      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6654      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6655      *      rem-double/2addr
6656      */
6657     /* binop/2addr vA, vB */
6658     mov     r9, rINST, lsr #8           @ r9<- A+
6659     mov     r1, rINST, lsr #12          @ r1<- B
6660     and     r9, r9, #15
6661     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6662     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6663     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6664     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6665     .if 0
6666     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6667     beq     common_errDivideByZero
6668     .endif
6669     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6670
6671                                @ optional op; may set condition codes
6672     bl      __aeabi_dsub                              @ result<- op, r0-r3 changed
6673     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6674     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6675     GOTO_OPCODE(ip)                     @ jump to next instruction
6676     /* 12-15 instructions */
6677
6678
6679
6680 /* ------------------------------ */
6681     .balign 64
6682 .L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
6683 /* File: armv5te/OP_MUL_DOUBLE_2ADDR.S */
6684 /* File: armv5te/binopWide2addr.S */
6685     /*
6686      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6687      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6688      * This could be an ARM instruction or a function call.  (If the result
6689      * comes back in a register other than r0, you can override "result".)
6690      *
6691      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6692      * vCC (r1).  Useful for integer division and modulus.
6693      *
6694      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6695      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6696      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6697      *      rem-double/2addr
6698      */
6699     /* binop/2addr vA, vB */
6700     mov     r9, rINST, lsr #8           @ r9<- A+
6701     mov     r1, rINST, lsr #12          @ r1<- B
6702     and     r9, r9, #15
6703     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6704     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6705     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6706     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6707     .if 0
6708     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6709     beq     common_errDivideByZero
6710     .endif
6711     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6712
6713                                @ optional op; may set condition codes
6714     bl      __aeabi_dmul                              @ result<- op, r0-r3 changed
6715     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6716     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6717     GOTO_OPCODE(ip)                     @ jump to next instruction
6718     /* 12-15 instructions */
6719
6720
6721
6722 /* ------------------------------ */
6723     .balign 64
6724 .L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
6725 /* File: armv5te/OP_DIV_DOUBLE_2ADDR.S */
6726 /* File: armv5te/binopWide2addr.S */
6727     /*
6728      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6729      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6730      * This could be an ARM instruction or a function call.  (If the result
6731      * comes back in a register other than r0, you can override "result".)
6732      *
6733      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6734      * vCC (r1).  Useful for integer division and modulus.
6735      *
6736      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6737      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6738      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6739      *      rem-double/2addr
6740      */
6741     /* binop/2addr vA, vB */
6742     mov     r9, rINST, lsr #8           @ r9<- A+
6743     mov     r1, rINST, lsr #12          @ r1<- B
6744     and     r9, r9, #15
6745     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6746     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6747     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6748     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6749     .if 0
6750     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6751     beq     common_errDivideByZero
6752     .endif
6753     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6754
6755                                @ optional op; may set condition codes
6756     bl      __aeabi_ddiv                              @ result<- op, r0-r3 changed
6757     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6758     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6759     GOTO_OPCODE(ip)                     @ jump to next instruction
6760     /* 12-15 instructions */
6761
6762
6763
6764 /* ------------------------------ */
6765     .balign 64
6766 .L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
6767 /* File: armv5te/OP_REM_DOUBLE_2ADDR.S */
6768 /* EABI doesn't define a double remainder function, but libm does */
6769 /* File: armv5te/binopWide2addr.S */
6770     /*
6771      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6772      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6773      * This could be an ARM instruction or a function call.  (If the result
6774      * comes back in a register other than r0, you can override "result".)
6775      *
6776      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6777      * vCC (r1).  Useful for integer division and modulus.
6778      *
6779      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6780      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6781      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6782      *      rem-double/2addr
6783      */
6784     /* binop/2addr vA, vB */
6785     mov     r9, rINST, lsr #8           @ r9<- A+
6786     mov     r1, rINST, lsr #12          @ r1<- B
6787     and     r9, r9, #15
6788     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6789     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6790     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6791     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6792     .if 0
6793     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6794     beq     common_errDivideByZero
6795     .endif
6796     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6797
6798                                @ optional op; may set condition codes
6799     bl      fmod                              @ result<- op, r0-r3 changed
6800     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6801     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6802     GOTO_OPCODE(ip)                     @ jump to next instruction
6803     /* 12-15 instructions */
6804
6805
6806
6807 /* ------------------------------ */
6808     .balign 64
6809 .L_OP_ADD_INT_LIT16: /* 0xd0 */
6810 /* File: armv5te/OP_ADD_INT_LIT16.S */
6811 /* File: armv5te/binopLit16.S */
6812     /*
6813      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6814      * that specifies an instruction that performs "result = r0 op r1".
6815      * This could be an ARM instruction or a function call.  (If the result
6816      * comes back in a register other than r0, you can override "result".)
6817      *
6818      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6819      * vCC (r1).  Useful for integer division and modulus.
6820      *
6821      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6822      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6823      */
6824     /* binop/lit16 vA, vB, #+CCCC */
6825     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6826     mov     r2, rINST, lsr #12          @ r2<- B
6827     mov     r9, rINST, lsr #8           @ r9<- A+
6828     GET_VREG(r0, r2)                    @ r0<- vB
6829     and     r9, r9, #15
6830     .if 0
6831     cmp     r1, #0                      @ is second operand zero?
6832     beq     common_errDivideByZero
6833     .endif
6834     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6835
6836     add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6837     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6838     SET_VREG(r0, r9)               @ vAA<- r0
6839     GOTO_OPCODE(ip)                     @ jump to next instruction
6840     /* 10-13 instructions */
6841
6842
6843
6844 /* ------------------------------ */
6845     .balign 64
6846 .L_OP_RSUB_INT: /* 0xd1 */
6847 /* File: armv5te/OP_RSUB_INT.S */
6848 /* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
6849 /* File: armv5te/binopLit16.S */
6850     /*
6851      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6852      * that specifies an instruction that performs "result = r0 op r1".
6853      * This could be an ARM instruction or a function call.  (If the result
6854      * comes back in a register other than r0, you can override "result".)
6855      *
6856      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6857      * vCC (r1).  Useful for integer division and modulus.
6858      *
6859      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6860      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6861      */
6862     /* binop/lit16 vA, vB, #+CCCC */
6863     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6864     mov     r2, rINST, lsr #12          @ r2<- B
6865     mov     r9, rINST, lsr #8           @ r9<- A+
6866     GET_VREG(r0, r2)                    @ r0<- vB
6867     and     r9, r9, #15
6868     .if 0
6869     cmp     r1, #0                      @ is second operand zero?
6870     beq     common_errDivideByZero
6871     .endif
6872     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6873
6874     rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6875     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6876     SET_VREG(r0, r9)               @ vAA<- r0
6877     GOTO_OPCODE(ip)                     @ jump to next instruction
6878     /* 10-13 instructions */
6879
6880
6881
6882 /* ------------------------------ */
6883     .balign 64
6884 .L_OP_MUL_INT_LIT16: /* 0xd2 */
6885 /* File: armv5te/OP_MUL_INT_LIT16.S */
6886 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6887 /* File: armv5te/binopLit16.S */
6888     /*
6889      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6890      * that specifies an instruction that performs "result = r0 op r1".
6891      * This could be an ARM instruction or a function call.  (If the result
6892      * comes back in a register other than r0, you can override "result".)
6893      *
6894      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6895      * vCC (r1).  Useful for integer division and modulus.
6896      *
6897      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6898      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6899      */
6900     /* binop/lit16 vA, vB, #+CCCC */
6901     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6902     mov     r2, rINST, lsr #12          @ r2<- B
6903     mov     r9, rINST, lsr #8           @ r9<- A+
6904     GET_VREG(r0, r2)                    @ r0<- vB
6905     and     r9, r9, #15
6906     .if 0
6907     cmp     r1, #0                      @ is second operand zero?
6908     beq     common_errDivideByZero
6909     .endif
6910     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6911
6912     mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6913     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6914     SET_VREG(r0, r9)               @ vAA<- r0
6915     GOTO_OPCODE(ip)                     @ jump to next instruction
6916     /* 10-13 instructions */
6917
6918
6919
6920 /* ------------------------------ */
6921     .balign 64
6922 .L_OP_DIV_INT_LIT16: /* 0xd3 */
6923 /* File: armv5te/OP_DIV_INT_LIT16.S */
6924 /* File: armv5te/binopLit16.S */
6925     /*
6926      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6927      * that specifies an instruction that performs "result = r0 op r1".
6928      * This could be an ARM instruction or a function call.  (If the result
6929      * comes back in a register other than r0, you can override "result".)
6930      *
6931      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6932      * vCC (r1).  Useful for integer division and modulus.
6933      *
6934      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6935      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6936      */
6937     /* binop/lit16 vA, vB, #+CCCC */
6938     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6939     mov     r2, rINST, lsr #12          @ r2<- B
6940     mov     r9, rINST, lsr #8           @ r9<- A+
6941     GET_VREG(r0, r2)                    @ r0<- vB
6942     and     r9, r9, #15
6943     .if 1
6944     cmp     r1, #0                      @ is second operand zero?
6945     beq     common_errDivideByZero
6946     .endif
6947     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6948
6949     bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6950     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6951     SET_VREG(r0, r9)               @ vAA<- r0
6952     GOTO_OPCODE(ip)                     @ jump to next instruction
6953     /* 10-13 instructions */
6954
6955
6956
6957 /* ------------------------------ */
6958     .balign 64
6959 .L_OP_REM_INT_LIT16: /* 0xd4 */
6960 /* File: armv5te/OP_REM_INT_LIT16.S */
6961 /* idivmod returns quotient in r0 and remainder in r1 */
6962 /* File: armv5te/binopLit16.S */
6963     /*
6964      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6965      * that specifies an instruction that performs "result = r0 op r1".
6966      * This could be an ARM instruction or a function call.  (If the result
6967      * comes back in a register other than r0, you can override "result".)
6968      *
6969      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6970      * vCC (r1).  Useful for integer division and modulus.
6971      *
6972      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6973      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6974      */
6975     /* binop/lit16 vA, vB, #+CCCC */
6976     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6977     mov     r2, rINST, lsr #12          @ r2<- B
6978     mov     r9, rINST, lsr #8           @ r9<- A+
6979     GET_VREG(r0, r2)                    @ r0<- vB
6980     and     r9, r9, #15
6981     .if 1
6982     cmp     r1, #0                      @ is second operand zero?
6983     beq     common_errDivideByZero
6984     .endif
6985     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6986
6987     bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6988     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6989     SET_VREG(r1, r9)               @ vAA<- r1
6990     GOTO_OPCODE(ip)                     @ jump to next instruction
6991     /* 10-13 instructions */
6992
6993
6994
6995 /* ------------------------------ */
6996     .balign 64
6997 .L_OP_AND_INT_LIT16: /* 0xd5 */
6998 /* File: armv5te/OP_AND_INT_LIT16.S */
6999 /* File: armv5te/binopLit16.S */
7000     /*
7001      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
7002      * that specifies an instruction that performs "result = r0 op r1".
7003      * This could be an ARM instruction or a function call.  (If the result
7004      * comes back in a register other than r0, you can override "result".)
7005      *
7006      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7007      * vCC (r1).  Useful for integer division and modulus.
7008      *
7009      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
7010      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
7011      */
7012     /* binop/lit16 vA, vB, #+CCCC */
7013     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
7014     mov     r2, rINST, lsr #12          @ r2<- B
7015     mov     r9, rINST, lsr #8           @ r9<- A+
7016     GET_VREG(r0, r2)                    @ r0<- vB
7017     and     r9, r9, #15
7018     .if 0
7019     cmp     r1, #0                      @ is second operand zero?
7020     beq     common_errDivideByZero
7021     .endif
7022     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7023
7024     and     r0, r0, r1                              @ r0<- op, r0-r3 changed
7025     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7026     SET_VREG(r0, r9)               @ vAA<- r0
7027     GOTO_OPCODE(ip)                     @ jump to next instruction
7028     /* 10-13 instructions */
7029
7030
7031
7032 /* ------------------------------ */
7033     .balign 64
7034 .L_OP_OR_INT_LIT16: /* 0xd6 */
7035 /* File: armv5te/OP_OR_INT_LIT16.S */
7036 /* File: armv5te/binopLit16.S */
7037     /*
7038      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
7039      * that specifies an instruction that performs "result = r0 op r1".
7040      * This could be an ARM instruction or a function call.  (If the result
7041      * comes back in a register other than r0, you can override "result".)
7042      *
7043      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7044      * vCC (r1).  Useful for integer division and modulus.
7045      *
7046      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
7047      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
7048      */
7049     /* binop/lit16 vA, vB, #+CCCC */
7050     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
7051     mov     r2, rINST, lsr #12          @ r2<- B
7052     mov     r9, rINST, lsr #8           @ r9<- A+
7053     GET_VREG(r0, r2)                    @ r0<- vB
7054     and     r9, r9, #15
7055     .if 0
7056     cmp     r1, #0                      @ is second operand zero?
7057     beq     common_errDivideByZero
7058     .endif
7059     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7060
7061     orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
7062     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7063     SET_VREG(r0, r9)               @ vAA<- r0
7064     GOTO_OPCODE(ip)                     @ jump to next instruction
7065     /* 10-13 instructions */
7066
7067
7068
7069 /* ------------------------------ */
7070     .balign 64
7071 .L_OP_XOR_INT_LIT16: /* 0xd7 */
7072 /* File: armv5te/OP_XOR_INT_LIT16.S */
7073 /* File: armv5te/binopLit16.S */
7074     /*
7075      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
7076      * that specifies an instruction that performs "result = r0 op r1".
7077      * This could be an ARM instruction or a function call.  (If the result
7078      * comes back in a register other than r0, you can override "result".)
7079      *
7080      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7081      * vCC (r1).  Useful for integer division and modulus.
7082      *
7083      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
7084      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
7085      */
7086     /* binop/lit16 vA, vB, #+CCCC */
7087     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
7088     mov     r2, rINST, lsr #12          @ r2<- B
7089     mov     r9, rINST, lsr #8           @ r9<- A+
7090     GET_VREG(r0, r2)                    @ r0<- vB
7091     and     r9, r9, #15
7092     .if 0
7093     cmp     r1, #0                      @ is second operand zero?
7094     beq     common_errDivideByZero
7095     .endif
7096     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7097
7098     eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
7099     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7100     SET_VREG(r0, r9)               @ vAA<- r0
7101     GOTO_OPCODE(ip)                     @ jump to next instruction
7102     /* 10-13 instructions */
7103
7104
7105
7106 /* ------------------------------ */
7107     .balign 64
7108 .L_OP_ADD_INT_LIT8: /* 0xd8 */
7109 /* File: armv5te/OP_ADD_INT_LIT8.S */
7110 /* File: armv5te/binopLit8.S */
7111     /*
7112      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7113      * that specifies an instruction that performs "result = r0 op r1".
7114      * This could be an ARM instruction or a function call.  (If the result
7115      * comes back in a register other than r0, you can override "result".)
7116      *
7117      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7118      * vCC (r1).  Useful for integer division and modulus.
7119      *
7120      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7121      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7122      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7123      */
7124     /* binop/lit8 vAA, vBB, #+CC */
7125     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7126     mov     r9, rINST, lsr #8           @ r9<- AA
7127     and     r2, r3, #255                @ r2<- BB
7128     GET_VREG(r0, r2)                    @ r0<- vBB
7129     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7130     .if 0
7131     @cmp     r1, #0                      @ is second operand zero?
7132     beq     common_errDivideByZero
7133     .endif
7134     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7135
7136                                @ optional op; may set condition codes
7137     add     r0, r0, r1                              @ r0<- op, r0-r3 changed
7138     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7139     SET_VREG(r0, r9)               @ vAA<- r0
7140     GOTO_OPCODE(ip)                     @ jump to next instruction
7141     /* 10-12 instructions */
7142
7143
7144
7145 /* ------------------------------ */
7146     .balign 64
7147 .L_OP_RSUB_INT_LIT8: /* 0xd9 */
7148 /* File: armv5te/OP_RSUB_INT_LIT8.S */
7149 /* File: armv5te/binopLit8.S */
7150     /*
7151      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7152      * that specifies an instruction that performs "result = r0 op r1".
7153      * This could be an ARM instruction or a function call.  (If the result
7154      * comes back in a register other than r0, you can override "result".)
7155      *
7156      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7157      * vCC (r1).  Useful for integer division and modulus.
7158      *
7159      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7160      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7161      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7162      */
7163     /* binop/lit8 vAA, vBB, #+CC */
7164     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7165     mov     r9, rINST, lsr #8           @ r9<- AA
7166     and     r2, r3, #255                @ r2<- BB
7167     GET_VREG(r0, r2)                    @ r0<- vBB
7168     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7169     .if 0
7170     @cmp     r1, #0                      @ is second operand zero?
7171     beq     common_errDivideByZero
7172     .endif
7173     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7174
7175                                @ optional op; may set condition codes
7176     rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
7177     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7178     SET_VREG(r0, r9)               @ vAA<- r0
7179     GOTO_OPCODE(ip)                     @ jump to next instruction
7180     /* 10-12 instructions */
7181
7182
7183
7184 /* ------------------------------ */
7185     .balign 64
7186 .L_OP_MUL_INT_LIT8: /* 0xda */
7187 /* File: armv5te/OP_MUL_INT_LIT8.S */
7188 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
7189 /* File: armv5te/binopLit8.S */
7190     /*
7191      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7192      * that specifies an instruction that performs "result = r0 op r1".
7193      * This could be an ARM instruction or a function call.  (If the result
7194      * comes back in a register other than r0, you can override "result".)
7195      *
7196      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7197      * vCC (r1).  Useful for integer division and modulus.
7198      *
7199      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7200      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7201      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7202      */
7203     /* binop/lit8 vAA, vBB, #+CC */
7204     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7205     mov     r9, rINST, lsr #8           @ r9<- AA
7206     and     r2, r3, #255                @ r2<- BB
7207     GET_VREG(r0, r2)                    @ r0<- vBB
7208     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7209     .if 0
7210     @cmp     r1, #0                      @ is second operand zero?
7211     beq     common_errDivideByZero
7212     .endif
7213     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7214
7215                                @ optional op; may set condition codes
7216     mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
7217     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7218     SET_VREG(r0, r9)               @ vAA<- r0
7219     GOTO_OPCODE(ip)                     @ jump to next instruction
7220     /* 10-12 instructions */
7221
7222
7223
7224 /* ------------------------------ */
7225     .balign 64
7226 .L_OP_DIV_INT_LIT8: /* 0xdb */
7227 /* File: armv5te/OP_DIV_INT_LIT8.S */
7228 /* File: armv5te/binopLit8.S */
7229     /*
7230      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7231      * that specifies an instruction that performs "result = r0 op r1".
7232      * This could be an ARM instruction or a function call.  (If the result
7233      * comes back in a register other than r0, you can override "result".)
7234      *
7235      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7236      * vCC (r1).  Useful for integer division and modulus.
7237      *
7238      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7239      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7240      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7241      */
7242     /* binop/lit8 vAA, vBB, #+CC */
7243     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7244     mov     r9, rINST, lsr #8           @ r9<- AA
7245     and     r2, r3, #255                @ r2<- BB
7246     GET_VREG(r0, r2)                    @ r0<- vBB
7247     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7248     .if 1
7249     @cmp     r1, #0                      @ is second operand zero?
7250     beq     common_errDivideByZero
7251     .endif
7252     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7253
7254                                @ optional op; may set condition codes
7255     bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
7256     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7257     SET_VREG(r0, r9)               @ vAA<- r0
7258     GOTO_OPCODE(ip)                     @ jump to next instruction
7259     /* 10-12 instructions */
7260
7261
7262
7263 /* ------------------------------ */
7264     .balign 64
7265 .L_OP_REM_INT_LIT8: /* 0xdc */
7266 /* File: armv5te/OP_REM_INT_LIT8.S */
7267 /* idivmod returns quotient in r0 and remainder in r1 */
7268 /* File: armv5te/binopLit8.S */
7269     /*
7270      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7271      * that specifies an instruction that performs "result = r0 op r1".
7272      * This could be an ARM instruction or a function call.  (If the result
7273      * comes back in a register other than r0, you can override "result".)
7274      *
7275      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7276      * vCC (r1).  Useful for integer division and modulus.
7277      *
7278      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7279      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7280      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7281      */
7282     /* binop/lit8 vAA, vBB, #+CC */
7283     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7284     mov     r9, rINST, lsr #8           @ r9<- AA
7285     and     r2, r3, #255                @ r2<- BB
7286     GET_VREG(r0, r2)                    @ r0<- vBB
7287     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7288     .if 1
7289     @cmp     r1, #0                      @ is second operand zero?
7290     beq     common_errDivideByZero
7291     .endif
7292     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7293
7294                                @ optional op; may set condition codes
7295     bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
7296     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7297     SET_VREG(r1, r9)               @ vAA<- r1
7298     GOTO_OPCODE(ip)                     @ jump to next instruction
7299     /* 10-12 instructions */
7300
7301
7302
7303 /* ------------------------------ */
7304     .balign 64
7305 .L_OP_AND_INT_LIT8: /* 0xdd */
7306 /* File: armv5te/OP_AND_INT_LIT8.S */
7307 /* File: armv5te/binopLit8.S */
7308     /*
7309      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7310      * that specifies an instruction that performs "result = r0 op r1".
7311      * This could be an ARM instruction or a function call.  (If the result
7312      * comes back in a register other than r0, you can override "result".)
7313      *
7314      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7315      * vCC (r1).  Useful for integer division and modulus.
7316      *
7317      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7318      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7319      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7320      */
7321     /* binop/lit8 vAA, vBB, #+CC */
7322     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7323     mov     r9, rINST, lsr #8           @ r9<- AA
7324     and     r2, r3, #255                @ r2<- BB
7325     GET_VREG(r0, r2)                    @ r0<- vBB
7326     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7327     .if 0
7328     @cmp     r1, #0                      @ is second operand zero?
7329     beq     common_errDivideByZero
7330     .endif
7331     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7332
7333                                @ optional op; may set condition codes
7334     and     r0, r0, r1                              @ r0<- op, r0-r3 changed
7335     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7336     SET_VREG(r0, r9)               @ vAA<- r0
7337     GOTO_OPCODE(ip)                     @ jump to next instruction
7338     /* 10-12 instructions */
7339
7340
7341
7342 /* ------------------------------ */
7343     .balign 64
7344 .L_OP_OR_INT_LIT8: /* 0xde */
7345 /* File: armv5te/OP_OR_INT_LIT8.S */
7346 /* File: armv5te/binopLit8.S */
7347     /*
7348      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7349      * that specifies an instruction that performs "result = r0 op r1".
7350      * This could be an ARM instruction or a function call.  (If the result
7351      * comes back in a register other than r0, you can override "result".)
7352      *
7353      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7354      * vCC (r1).  Useful for integer division and modulus.
7355      *
7356      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7357      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7358      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7359      */
7360     /* binop/lit8 vAA, vBB, #+CC */
7361     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7362     mov     r9, rINST, lsr #8           @ r9<- AA
7363     and     r2, r3, #255                @ r2<- BB
7364     GET_VREG(r0, r2)                    @ r0<- vBB
7365     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7366     .if 0
7367     @cmp     r1, #0                      @ is second operand zero?
7368     beq     common_errDivideByZero
7369     .endif
7370     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7371
7372                                @ optional op; may set condition codes
7373     orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
7374     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7375     SET_VREG(r0, r9)               @ vAA<- r0
7376     GOTO_OPCODE(ip)                     @ jump to next instruction
7377     /* 10-12 instructions */
7378
7379
7380
7381 /* ------------------------------ */
7382     .balign 64
7383 .L_OP_XOR_INT_LIT8: /* 0xdf */
7384 /* File: armv5te/OP_XOR_INT_LIT8.S */
7385 /* File: armv5te/binopLit8.S */
7386     /*
7387      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7388      * that specifies an instruction that performs "result = r0 op r1".
7389      * This could be an ARM instruction or a function call.  (If the result
7390      * comes back in a register other than r0, you can override "result".)
7391      *
7392      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7393      * vCC (r1).  Useful for integer division and modulus.
7394      *
7395      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7396      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7397      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7398      */
7399     /* binop/lit8 vAA, vBB, #+CC */
7400     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7401     mov     r9, rINST, lsr #8           @ r9<- AA
7402     and     r2, r3, #255                @ r2<- BB
7403     GET_VREG(r0, r2)                    @ r0<- vBB
7404     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7405     .if 0
7406     @cmp     r1, #0                      @ is second operand zero?
7407     beq     common_errDivideByZero
7408     .endif
7409     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7410
7411                                @ optional op; may set condition codes
7412     eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
7413     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7414     SET_VREG(r0, r9)               @ vAA<- r0
7415     GOTO_OPCODE(ip)                     @ jump to next instruction
7416     /* 10-12 instructions */
7417
7418
7419
7420 /* ------------------------------ */
7421     .balign 64
7422 .L_OP_SHL_INT_LIT8: /* 0xe0 */
7423 /* File: armv5te/OP_SHL_INT_LIT8.S */
7424 /* File: armv5te/binopLit8.S */
7425     /*
7426      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7427      * that specifies an instruction that performs "result = r0 op r1".
7428      * This could be an ARM instruction or a function call.  (If the result
7429      * comes back in a register other than r0, you can override "result".)
7430      *
7431      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7432      * vCC (r1).  Useful for integer division and modulus.
7433      *
7434      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7435      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7436      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7437      */
7438     /* binop/lit8 vAA, vBB, #+CC */
7439     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7440     mov     r9, rINST, lsr #8           @ r9<- AA
7441     and     r2, r3, #255                @ r2<- BB
7442     GET_VREG(r0, r2)                    @ r0<- vBB
7443     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7444     .if 0
7445     @cmp     r1, #0                      @ is second operand zero?
7446     beq     common_errDivideByZero
7447     .endif
7448     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7449
7450     and     r1, r1, #31                           @ optional op; may set condition codes
7451     mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
7452     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7453     SET_VREG(r0, r9)               @ vAA<- r0
7454     GOTO_OPCODE(ip)                     @ jump to next instruction
7455     /* 10-12 instructions */
7456
7457
7458
7459 /* ------------------------------ */
7460     .balign 64
7461 .L_OP_SHR_INT_LIT8: /* 0xe1 */
7462 /* File: armv5te/OP_SHR_INT_LIT8.S */
7463 /* File: armv5te/binopLit8.S */
7464     /*
7465      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7466      * that specifies an instruction that performs "result = r0 op r1".
7467      * This could be an ARM instruction or a function call.  (If the result
7468      * comes back in a register other than r0, you can override "result".)
7469      *
7470      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7471      * vCC (r1).  Useful for integer division and modulus.
7472      *
7473      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7474      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7475      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7476      */
7477     /* binop/lit8 vAA, vBB, #+CC */
7478     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7479     mov     r9, rINST, lsr #8           @ r9<- AA
7480     and     r2, r3, #255                @ r2<- BB
7481     GET_VREG(r0, r2)                    @ r0<- vBB
7482     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7483     .if 0
7484     @cmp     r1, #0                      @ is second operand zero?
7485     beq     common_errDivideByZero
7486     .endif
7487     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7488
7489     and     r1, r1, #31                           @ optional op; may set condition codes
7490     mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
7491     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7492     SET_VREG(r0, r9)               @ vAA<- r0
7493     GOTO_OPCODE(ip)                     @ jump to next instruction
7494     /* 10-12 instructions */
7495
7496
7497
7498 /* ------------------------------ */
7499     .balign 64
7500 .L_OP_USHR_INT_LIT8: /* 0xe2 */
7501 /* File: armv5te/OP_USHR_INT_LIT8.S */
7502 /* File: armv5te/binopLit8.S */
7503     /*
7504      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7505      * that specifies an instruction that performs "result = r0 op r1".
7506      * This could be an ARM instruction or a function call.  (If the result
7507      * comes back in a register other than r0, you can override "result".)
7508      *
7509      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7510      * vCC (r1).  Useful for integer division and modulus.
7511      *
7512      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7513      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7514      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7515      */
7516     /* binop/lit8 vAA, vBB, #+CC */
7517     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7518     mov     r9, rINST, lsr #8           @ r9<- AA
7519     and     r2, r3, #255                @ r2<- BB
7520     GET_VREG(r0, r2)                    @ r0<- vBB
7521     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7522     .if 0
7523     @cmp     r1, #0                      @ is second operand zero?
7524     beq     common_errDivideByZero
7525     .endif
7526     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7527
7528     and     r1, r1, #31                           @ optional op; may set condition codes
7529     mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
7530     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7531     SET_VREG(r0, r9)               @ vAA<- r0
7532     GOTO_OPCODE(ip)                     @ jump to next instruction
7533     /* 10-12 instructions */
7534
7535
7536
7537 /* ------------------------------ */
7538     .balign 64
7539 .L_OP_UNUSED_E3: /* 0xe3 */
7540 /* File: armv5te/OP_UNUSED_E3.S */
7541 /* File: armv5te/unused.S */
7542     bl      common_abort
7543
7544
7545
7546 /* ------------------------------ */
7547     .balign 64
7548 .L_OP_UNUSED_E4: /* 0xe4 */
7549 /* File: armv5te/OP_UNUSED_E4.S */
7550 /* File: armv5te/unused.S */
7551     bl      common_abort
7552
7553
7554
7555 /* ------------------------------ */
7556     .balign 64
7557 .L_OP_UNUSED_E5: /* 0xe5 */
7558 /* File: armv5te/OP_UNUSED_E5.S */
7559 /* File: armv5te/unused.S */
7560     bl      common_abort
7561
7562
7563
7564 /* ------------------------------ */
7565     .balign 64
7566 .L_OP_UNUSED_E6: /* 0xe6 */
7567 /* File: armv5te/OP_UNUSED_E6.S */
7568 /* File: armv5te/unused.S */
7569     bl      common_abort
7570
7571
7572
7573 /* ------------------------------ */
7574     .balign 64
7575 .L_OP_UNUSED_E7: /* 0xe7 */
7576 /* File: armv5te/OP_UNUSED_E7.S */
7577 /* File: armv5te/unused.S */
7578     bl      common_abort
7579
7580
7581
7582 /* ------------------------------ */
7583     .balign 64
7584 .L_OP_UNUSED_E8: /* 0xe8 */
7585 /* File: armv5te/OP_UNUSED_E8.S */
7586 /* File: armv5te/unused.S */
7587     bl      common_abort
7588
7589
7590
7591 /* ------------------------------ */
7592     .balign 64
7593 .L_OP_UNUSED_E9: /* 0xe9 */
7594 /* File: armv5te/OP_UNUSED_E9.S */
7595 /* File: armv5te/unused.S */
7596     bl      common_abort
7597
7598
7599
7600 /* ------------------------------ */
7601     .balign 64
7602 .L_OP_UNUSED_EA: /* 0xea */
7603 /* File: armv5te/OP_UNUSED_EA.S */
7604 /* File: armv5te/unused.S */
7605     bl      common_abort
7606
7607
7608
7609 /* ------------------------------ */
7610     .balign 64
7611 .L_OP_UNUSED_EB: /* 0xeb */
7612 /* File: armv5te/OP_UNUSED_EB.S */
7613 /* File: armv5te/unused.S */
7614     bl      common_abort
7615
7616
7617
7618 /* ------------------------------ */
7619     .balign 64
7620 .L_OP_UNUSED_EC: /* 0xec */
7621 /* File: armv5te/OP_UNUSED_EC.S */
7622 /* File: armv5te/unused.S */
7623     bl      common_abort
7624
7625
7626
7627 /* ------------------------------ */
7628     .balign 64
7629 .L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
7630 /* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
7631     /*
7632      * Handle a throw-verification-error instruction.  This throws an
7633      * exception for an error discovered during verification.  The
7634      * exception is indicated by AA, with some detail provided by BBBB.
7635      */
7636     /* op AA, ref@BBBB */
7637     ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7638     FETCH(r2, 1)                        @ r2<- BBBB
7639     EXPORT_PC()                         @ export the PC
7640     mov     r1, rINST, lsr #8           @ r1<- AA
7641     bl      dvmThrowVerificationError   @ always throws
7642     b       common_exceptionThrown      @ handle exception
7643
7644
7645 /* ------------------------------ */
7646     .balign 64
7647 .L_OP_EXECUTE_INLINE: /* 0xee */
7648 /* File: armv5te/OP_EXECUTE_INLINE.S */
7649     /*
7650      * Execute a "native inline" instruction.
7651      *
7652      * We need to call:
7653      *  dvmPerformInlineOp4Std(arg0, arg1, arg2, arg3, &retval, ref)
7654      *
7655      * The first four args are in r0-r3, but the last two must be pushed
7656      * onto the stack.
7657      */
7658     /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
7659     FETCH(r10, 1)                       @ r10<- BBBB
7660     add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7661     EXPORT_PC()                         @ can throw
7662     sub     sp, sp, #8                  @ make room for arg(s)
7663     mov     r0, rINST, lsr #12          @ r0<- B
7664     str     r1, [sp]                    @ push &glue->retval
7665     bl      .LOP_EXECUTE_INLINE_continue        @ make call; will return after
7666     add     sp, sp, #8                  @ pop stack
7667     cmp     r0, #0                      @ test boolean result of inline
7668     beq     common_exceptionThrown      @ returned false, handle exception
7669     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7670     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7671     GOTO_OPCODE(ip)                     @ jump to next instruction
7672
7673 /* ------------------------------ */
7674     .balign 64
7675 .L_OP_UNUSED_EF: /* 0xef */
7676 /* File: armv5te/OP_UNUSED_EF.S */
7677 /* File: armv5te/unused.S */
7678     bl      common_abort
7679
7680
7681
7682 /* ------------------------------ */
7683     .balign 64
7684 .L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
7685 /* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
7686     /*
7687      * invoke-direct-empty is a no-op in a "standard" interpreter.
7688      */
7689     FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7690     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7691     GOTO_OPCODE(ip)                     @ execute it
7692
7693 /* ------------------------------ */
7694     .balign 64
7695 .L_OP_UNUSED_F1: /* 0xf1 */
7696 /* File: armv5te/OP_UNUSED_F1.S */
7697 /* File: armv5te/unused.S */
7698     bl      common_abort
7699
7700
7701
7702 /* ------------------------------ */
7703     .balign 64
7704 .L_OP_IGET_QUICK: /* 0xf2 */
7705 /* File: armv5te/OP_IGET_QUICK.S */
7706     /* For: iget-quick, iget-object-quick */
7707     /* op vA, vB, offset@CCCC */
7708     mov     r2, rINST, lsr #12          @ r2<- B
7709     GET_VREG(r3, r2)                    @ r3<- object we're operating on
7710     FETCH(r1, 1)                        @ r1<- field byte offset
7711     cmp     r3, #0                      @ check object for null
7712     mov     r2, rINST, lsr #8           @ r2<- A(+)
7713     beq     common_errNullObject        @ object was null
7714     ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7715     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7716     and     r2, r2, #15
7717     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7718     SET_VREG(r0, r2)                    @ fp[A]<- r0
7719     GOTO_OPCODE(ip)                     @ jump to next instruction
7720
7721
7722 /* ------------------------------ */
7723     .balign 64
7724 .L_OP_IGET_WIDE_QUICK: /* 0xf3 */
7725 /* File: armv5te/OP_IGET_WIDE_QUICK.S */
7726     /* iget-wide-quick vA, vB, offset@CCCC */
7727     mov     r2, rINST, lsr #12          @ r2<- B
7728     GET_VREG(r3, r2)                    @ r3<- object we're operating on
7729     FETCH(r1, 1)                        @ r1<- field byte offset
7730     cmp     r3, #0                      @ check object for null
7731     mov     r2, rINST, lsr #8           @ r2<- A(+)
7732     beq     common_errNullObject        @ object was null
7733     ldrd    r0, [r3, r1]                @ r0<- obj.field (64 bits, aligned)
7734     and     r2, r2, #15
7735     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7736     add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
7737     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7738     stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
7739     GOTO_OPCODE(ip)                     @ jump to next instruction
7740
7741
7742 /* ------------------------------ */
7743     .balign 64
7744 .L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
7745 /* File: armv5te/OP_IGET_OBJECT_QUICK.S */
7746 /* File: armv5te/OP_IGET_QUICK.S */
7747     /* For: iget-quick, iget-object-quick */
7748     /* op vA, vB, offset@CCCC */
7749     mov     r2, rINST, lsr #12          @ r2<- B
7750     GET_VREG(r3, r2)                    @ r3<- object we're operating on
7751     FETCH(r1, 1)                        @ r1<- field byte offset
7752     cmp     r3, #0                      @ check object for null
7753     mov     r2, rINST, lsr #8           @ r2<- A(+)
7754     beq     common_errNullObject        @ object was null
7755     ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7756     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7757     and     r2, r2, #15
7758     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7759     SET_VREG(r0, r2)                    @ fp[A]<- r0
7760     GOTO_OPCODE(ip)                     @ jump to next instruction
7761
7762
7763
7764 /* ------------------------------ */
7765     .balign 64
7766 .L_OP_IPUT_QUICK: /* 0xf5 */
7767 /* File: armv5te/OP_IPUT_QUICK.S */
7768     /* For: iput-quick, iput-object-quick */
7769     /* op vA, vB, offset@CCCC */
7770     mov     r2, rINST, lsr #12          @ r2<- B
7771     GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7772     FETCH(r1, 1)                        @ r1<- field byte offset
7773     cmp     r3, #0                      @ check object for null
7774     mov     r2, rINST, lsr #8           @ r2<- A(+)
7775     beq     common_errNullObject        @ object was null
7776     and     r2, r2, #15
7777     GET_VREG(r0, r2)                    @ r0<- fp[A]
7778     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7779     str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7780     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7781     GOTO_OPCODE(ip)                     @ jump to next instruction
7782
7783
7784 /* ------------------------------ */
7785     .balign 64
7786 .L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
7787 /* File: armv5te/OP_IPUT_WIDE_QUICK.S */
7788     /* iput-wide-quick vA, vB, offset@CCCC */
7789     mov     r0, rINST, lsr #8           @ r0<- A(+)
7790     mov     r1, rINST, lsr #12          @ r1<- B
7791     and     r0, r0, #15
7792     GET_VREG(r2, r1)                    @ r2<- fp[B], the object pointer
7793     add     r3, rFP, r0, lsl #2         @ r3<- &fp[A]
7794     cmp     r2, #0                      @ check object for null
7795     ldmia   r3, {r0-r1}                 @ r0/r1<- fp[A]
7796     beq     common_errNullObject        @ object was null
7797     FETCH(r3, 1)                        @ r3<- field byte offset
7798     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7799     strd    r0, [r2, r3]                @ obj.field (64 bits, aligned)<- r0/r1
7800     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7801     GOTO_OPCODE(ip)                     @ jump to next instruction
7802
7803
7804 /* ------------------------------ */
7805     .balign 64
7806 .L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
7807 /* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
7808 /* File: armv5te/OP_IPUT_QUICK.S */
7809     /* For: iput-quick, iput-object-quick */
7810     /* op vA, vB, offset@CCCC */
7811     mov     r2, rINST, lsr #12          @ r2<- B
7812     GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7813     FETCH(r1, 1)                        @ r1<- field byte offset
7814     cmp     r3, #0                      @ check object for null
7815     mov     r2, rINST, lsr #8           @ r2<- A(+)
7816     beq     common_errNullObject        @ object was null
7817     and     r2, r2, #15
7818     GET_VREG(r0, r2)                    @ r0<- fp[A]
7819     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7820     str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7821     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7822     GOTO_OPCODE(ip)                     @ jump to next instruction
7823
7824
7825
7826 /* ------------------------------ */
7827     .balign 64
7828 .L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
7829 /* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7830     /*
7831      * Handle an optimized virtual method call.
7832      *
7833      * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7834      */
7835     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7836     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7837     FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7838     FETCH(r1, 1)                        @ r1<- BBBB
7839     .if     (!0)
7840     and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7841     .endif
7842     GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7843     cmp     r2, #0                      @ is "this" null?
7844     beq     common_errNullObject        @ null "this", throw exception
7845     ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7846     ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7847     EXPORT_PC()                         @ invoke must export
7848     ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7849     bl      common_invokeMethodNoRange @ continue on
7850
7851 /* ------------------------------ */
7852     .balign 64
7853 .L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
7854 /* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
7855 /* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7856     /*
7857      * Handle an optimized virtual method call.
7858      *
7859      * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7860      */
7861     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7862     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7863     FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7864     FETCH(r1, 1)                        @ r1<- BBBB
7865     .if     (!1)
7866     and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7867     .endif
7868     GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7869     cmp     r2, #0                      @ is "this" null?
7870     beq     common_errNullObject        @ null "this", throw exception
7871     ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7872     ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7873     EXPORT_PC()                         @ invoke must export
7874     ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7875     bl      common_invokeMethodRange @ continue on
7876
7877
7878 /* ------------------------------ */
7879     .balign 64
7880 .L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
7881 /* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7882     /*
7883      * Handle an optimized "super" method call.
7884      *
7885      * for: [opt] invoke-super-quick, invoke-super-quick/range
7886      */
7887     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7888     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7889     FETCH(r10, 2)                       @ r10<- GFED or CCCC
7890     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7891     .if     (!0)
7892     and     r10, r10, #15               @ r10<- D (or stays CCCC)
7893     .endif
7894     FETCH(r1, 1)                        @ r1<- BBBB
7895     ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7896     EXPORT_PC()                         @ must export for invoke
7897     ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7898     GET_VREG(r3, r10)                   @ r3<- "this"
7899     ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7900     cmp     r3, #0                      @ null "this" ref?
7901     ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7902     beq     common_errNullObject        @ "this" is null, throw exception
7903     bl      common_invokeMethodNoRange @ continue on
7904
7905
7906 /* ------------------------------ */
7907     .balign 64
7908 .L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
7909 /* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
7910 /* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7911     /*
7912      * Handle an optimized "super" method call.
7913      *
7914      * for: [opt] invoke-super-quick, invoke-super-quick/range
7915      */
7916     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7917     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7918     FETCH(r10, 2)                       @ r10<- GFED or CCCC
7919     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7920     .if     (!1)
7921     and     r10, r10, #15               @ r10<- D (or stays CCCC)
7922     .endif
7923     FETCH(r1, 1)                        @ r1<- BBBB
7924     ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7925     EXPORT_PC()                         @ must export for invoke
7926     ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7927     GET_VREG(r3, r10)                   @ r3<- "this"
7928     ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7929     cmp     r3, #0                      @ null "this" ref?
7930     ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7931     beq     common_errNullObject        @ "this" is null, throw exception
7932     bl      common_invokeMethodRange @ continue on
7933
7934
7935
7936 /* ------------------------------ */
7937     .balign 64
7938 .L_OP_UNUSED_FC: /* 0xfc */
7939 /* File: armv5te/OP_UNUSED_FC.S */
7940 /* File: armv5te/unused.S */
7941     bl      common_abort
7942
7943
7944
7945 /* ------------------------------ */
7946     .balign 64
7947 .L_OP_UNUSED_FD: /* 0xfd */
7948 /* File: armv5te/OP_UNUSED_FD.S */
7949 /* File: armv5te/unused.S */
7950     bl      common_abort
7951
7952
7953
7954 /* ------------------------------ */
7955     .balign 64
7956 .L_OP_UNUSED_FE: /* 0xfe */
7957 /* File: armv5te/OP_UNUSED_FE.S */
7958 /* File: armv5te/unused.S */
7959     bl      common_abort
7960
7961
7962
7963 /* ------------------------------ */
7964     .balign 64
7965 .L_OP_UNUSED_FF: /* 0xff */
7966 /* File: armv5te/OP_UNUSED_FF.S */
7967 /* File: armv5te/unused.S */
7968     bl      common_abort
7969
7970
7971
7972
7973     .balign 64
7974     .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
7975     .global dvmAsmInstructionEnd
7976 dvmAsmInstructionEnd:
7977
7978 /*
7979  * ===========================================================================
7980  *  Sister implementations
7981  * ===========================================================================
7982  */
7983     .global dvmAsmSisterStart
7984     .type   dvmAsmSisterStart, %function
7985     .text
7986     .balign 4
7987 dvmAsmSisterStart:
7988
7989 /* continuation for OP_CONST_STRING */
7990
7991     /*
7992      * Continuation if the String has not yet been resolved.
7993      *  r1: BBBB (String ref)
7994      *  r9: target register
7995      */
7996 .LOP_CONST_STRING_resolve:
7997     EXPORT_PC()
7998     ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7999     ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
8000     bl      dvmResolveString            @ r0<- String reference
8001     cmp     r0, #0                      @ failed?
8002     beq     common_exceptionThrown      @ yup, handle the exception
8003     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8004     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8005     SET_VREG(r0, r9)                    @ vAA<- r0
8006     GOTO_OPCODE(ip)                     @ jump to next instruction
8007
8008
8009 /* continuation for OP_CONST_STRING_JUMBO */
8010
8011     /*
8012      * Continuation if the String has not yet been resolved.
8013      *  r1: BBBBBBBB (String ref)
8014      *  r9: target register
8015      */
8016 .LOP_CONST_STRING_JUMBO_resolve:
8017     EXPORT_PC()
8018     ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
8019     ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
8020     bl      dvmResolveString            @ r0<- String reference
8021     cmp     r0, #0                      @ failed?
8022     beq     common_exceptionThrown      @ yup, handle the exception
8023     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
8024     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8025     SET_VREG(r0, r9)                    @ vAA<- r0
8026     GOTO_OPCODE(ip)                     @ jump to next instruction
8027
8028
8029 /* continuation for OP_CONST_CLASS */
8030
8031     /*
8032      * Continuation if the Class has not yet been resolved.
8033      *  r1: BBBB (Class ref)
8034      *  r9: target register
8035      */
8036 .LOP_CONST_CLASS_resolve:
8037     EXPORT_PC()
8038     ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
8039     mov     r2, #1                      @ r2<- true
8040     ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
8041     bl      dvmResolveClass             @ r0<- Class reference
8042     cmp     r0, #0                      @ failed?
8043     beq     common_exceptionThrown      @ yup, handle the exception
8044     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8045     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8046     SET_VREG(r0, r9)                    @ vAA<- r0
8047     GOTO_OPCODE(ip)                     @ jump to next instruction
8048
8049
8050 /* continuation for OP_CHECK_CAST */
8051
8052     /*
8053      * Trivial test failed, need to perform full check.  This is common.
8054      *  r0 holds obj->clazz
8055      *  r1 holds class resolved from BBBB
8056      *  r9 holds object
8057      */
8058 .LOP_CHECK_CAST_fullcheck:
8059     bl      dvmInstanceofNonTrivial     @ r0<- boolean result
8060     cmp     r0, #0                      @ failed?
8061     bne     .LOP_CHECK_CAST_okay            @ no, success
8062
8063     @ A cast has failed.  We need to throw a ClassCastException with the
8064     @ class of the object that failed to be cast.
8065     EXPORT_PC()                         @ about to throw
8066     ldr     r3, [r9, #offObject_clazz]  @ r3<- obj->clazz
8067     ldr     r0, .LstrClassCastExceptionPtr
8068     ldr     r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor
8069     bl      dvmThrowExceptionWithClassMessage
8070     b       common_exceptionThrown
8071
8072     /*
8073      * Resolution required.  This is the least-likely path.
8074      *
8075      *  r2 holds BBBB
8076      *  r9 holds object
8077      */
8078 .LOP_CHECK_CAST_resolve:
8079     EXPORT_PC()                         @ resolve() could throw
8080     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8081     mov     r1, r2                      @ r1<- BBBB
8082     mov     r2, #0                      @ r2<- false
8083     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8084     bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
8085     cmp     r0, #0                      @ got null?
8086     beq     common_exceptionThrown      @ yes, handle exception
8087     mov     r1, r0                      @ r1<- class resolved from BBB
8088     ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
8089     b       .LOP_CHECK_CAST_resolved        @ pick up where we left off
8090
8091 .LstrClassCastExceptionPtr:
8092     .word   .LstrClassCastException
8093
8094
8095 /* continuation for OP_INSTANCE_OF */
8096
8097     /*
8098      * Trivial test failed, need to perform full check.  This is common.
8099      *  r0 holds obj->clazz
8100      *  r1 holds class resolved from BBBB
8101      *  r9 holds A
8102      */
8103 .LOP_INSTANCE_OF_fullcheck:
8104     bl      dvmInstanceofNonTrivial     @ r0<- boolean result
8105     @ fall through to OP_INSTANCE_OF_store
8106
8107     /*
8108      * r0 holds boolean result
8109      * r9 holds A
8110      */
8111 .LOP_INSTANCE_OF_store:
8112     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8113     SET_VREG(r0, r9)                    @ vA<- r0
8114     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8115     GOTO_OPCODE(ip)                     @ jump to next instruction
8116
8117     /*
8118      * Trivial test succeeded, save and bail.
8119      *  r9 holds A
8120      */
8121 .LOP_INSTANCE_OF_trivial:
8122     mov     r0, #1                      @ indicate success
8123     @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
8124     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8125     SET_VREG(r0, r9)                    @ vA<- r0
8126     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8127     GOTO_OPCODE(ip)                     @ jump to next instruction
8128
8129     /*
8130      * Resolution required.  This is the least-likely path.
8131      *
8132      *  r3 holds BBBB
8133      *  r9 holds A
8134      */
8135 .LOP_INSTANCE_OF_resolve:
8136     EXPORT_PC()                         @ resolve() could throw
8137     ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
8138     mov     r1, r3                      @ r1<- BBBB
8139     mov     r2, #1                      @ r2<- true
8140     ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
8141     bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
8142     cmp     r0, #0                      @ got null?
8143     beq     common_exceptionThrown      @ yes, handle exception
8144     mov     r1, r0                      @ r1<- class resolved from BBB
8145     mov     r3, rINST, lsr #12          @ r3<- B
8146     GET_VREG(r0, r3)                    @ r0<- vB (object)
8147     ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
8148     b       .LOP_INSTANCE_OF_resolved        @ pick up where we left off
8149
8150
8151 /* continuation for OP_NEW_INSTANCE */
8152
8153     .balign 32                          @ minimize cache lines
8154 .LOP_NEW_INSTANCE_finish: @ r0=new object
8155     mov     r3, rINST, lsr #8           @ r3<- AA
8156     cmp     r0, #0                      @ failed?
8157     beq     common_exceptionThrown      @ yes, handle the exception
8158     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8159     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8160     SET_VREG(r0, r3)                    @ vAA<- r0
8161     GOTO_OPCODE(ip)                     @ jump to next instruction
8162
8163     /*
8164      * Class initialization required.
8165      *
8166      *  r0 holds class object
8167      */
8168 .LOP_NEW_INSTANCE_needinit:
8169     mov     r9, r0                      @ save r0
8170     bl      dvmInitClass                @ initialize class
8171     cmp     r0, #0                      @ check boolean result
8172     mov     r0, r9                      @ restore r0
8173     bne     .LOP_NEW_INSTANCE_initialized     @ success, continue
8174     b       common_exceptionThrown      @ failed, deal with init exception
8175
8176     /*
8177      * Resolution required.  This is the least-likely path.
8178      *
8179      *  r1 holds BBBB
8180      */
8181 .LOP_NEW_INSTANCE_resolve:
8182     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8183     mov     r2, #0                      @ r2<- false
8184     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8185     bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
8186     cmp     r0, #0                      @ got null?
8187     bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
8188     b       common_exceptionThrown      @ yes, handle exception
8189
8190 .LstrInstantiationErrorPtr:
8191     .word   .LstrInstantiationError
8192
8193
8194 /* continuation for OP_NEW_ARRAY */
8195
8196
8197     /*
8198      * Resolve class.  (This is an uncommon case.)
8199      *
8200      *  r1 holds array length
8201      *  r2 holds class ref CCCC
8202      */
8203 .LOP_NEW_ARRAY_resolve:
8204     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8205     mov     r9, r1                      @ r9<- length (save)
8206     mov     r1, r2                      @ r1<- CCCC
8207     mov     r2, #0                      @ r2<- false
8208     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8209     bl      dvmResolveClass             @ r0<- call(clazz, ref)
8210     cmp     r0, #0                      @ got null?
8211     mov     r1, r9                      @ r1<- length (restore)
8212     beq     common_exceptionThrown      @ yes, handle exception
8213     @ fall through to OP_NEW_ARRAY_finish
8214
8215     /*
8216      * Finish allocation.
8217      *
8218      *  r0 holds class
8219      *  r1 holds array length
8220      */
8221 .LOP_NEW_ARRAY_finish:
8222     mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
8223     bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
8224     cmp     r0, #0                      @ failed?
8225     mov     r2, rINST, lsr #8           @ r2<- A+
8226     beq     common_exceptionThrown      @ yes, handle the exception
8227     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8228     and     r2, r2, #15                 @ r2<- A
8229     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8230     SET_VREG(r0, r2)                    @ vA<- r0
8231     GOTO_OPCODE(ip)                     @ jump to next instruction
8232
8233
8234 /* continuation for OP_FILLED_NEW_ARRAY */
8235
8236     /*
8237      * On entry:
8238      *  r0 holds array class
8239      *  r10 holds AA or BA
8240      */
8241 .LOP_FILLED_NEW_ARRAY_continue:
8242     ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8243     mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8244     ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
8245     .if     0
8246     mov     r1, r10                     @ r1<- AA (length)
8247     .else
8248     mov     r1, r10, lsr #4             @ r1<- B (length)
8249     .endif
8250     cmp     r3, #'I'                    @ array of ints?
8251     cmpne   r3, #'L'                    @ array of objects?
8252     cmpne   r3, #'['                    @ array of arrays?
8253     mov     r9, r1                      @ save length in r9
8254     bne     .LOP_FILLED_NEW_ARRAY_notimpl         @ no, not handled yet
8255     bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8256     cmp     r0, #0                      @ null return?
8257     beq     common_exceptionThrown      @ alloc failed, handle exception
8258
8259     FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8260     str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
8261     add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8262     subs    r9, r9, #1                  @ length--, check for neg
8263     FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8264     bmi     2f                          @ was zero, bail
8265
8266     @ copy values from registers into the array
8267     @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8268     .if     0
8269     add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
8270 1:  ldr     r3, [r2], #4                @ r3<- *r2++
8271     subs    r9, r9, #1                  @ count--
8272     str     r3, [r0], #4                @ *contents++ = vX
8273     bpl     1b
8274     @ continue at 2
8275     .else
8276     cmp     r9, #4                      @ length was initially 5?
8277     and     r2, r10, #15                @ r2<- A
8278     bne     1f                          @ <= 4 args, branch
8279     GET_VREG(r3, r2)                    @ r3<- vA
8280     sub     r9, r9, #1                  @ count--
8281     str     r3, [r0, #16]               @ contents[4] = vA
8282 1:  and     r2, r1, #15                 @ r2<- F/E/D/C
8283     GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8284     mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8285     subs    r9, r9, #1                  @ count--
8286     str     r3, [r0], #4                @ *contents++ = vX
8287     bpl     1b
8288     @ continue at 2
8289     .endif
8290
8291 2:
8292     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
8293     GOTO_OPCODE(ip)                     @ execute it
8294
8295     /*
8296      * Throw an exception indicating that we have not implemented this
8297      * mode of filled-new-array.
8298      */
8299 .LOP_FILLED_NEW_ARRAY_notimpl:
8300     ldr     r0, .L_strInternalError
8301     ldr     r1, .L_strFilledNewArrayNotImpl
8302     bl      dvmThrowException
8303     b       common_exceptionThrown
8304
8305     .if     (!0)                 @ define in one or the other, not both
8306 .L_strFilledNewArrayNotImpl:
8307     .word   .LstrFilledNewArrayNotImpl
8308 .L_strInternalError:
8309     .word   .LstrInternalError
8310     .endif
8311
8312
8313 /* continuation for OP_FILLED_NEW_ARRAY_RANGE */
8314
8315     /*
8316      * On entry:
8317      *  r0 holds array class
8318      *  r10 holds AA or BA
8319      */
8320 .LOP_FILLED_NEW_ARRAY_RANGE_continue:
8321     ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8322     mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8323     ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
8324     .if     1
8325     mov     r1, r10                     @ r1<- AA (length)
8326     .else
8327     mov     r1, r10, lsr #4             @ r1<- B (length)
8328     .endif
8329     cmp     r3, #'I'                    @ array of ints?
8330     cmpne   r3, #'L'                    @ array of objects?
8331     cmpne   r3, #'['                    @ array of arrays?
8332     mov     r9, r1                      @ save length in r9
8333     bne     .LOP_FILLED_NEW_ARRAY_RANGE_notimpl         @ no, not handled yet
8334     bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8335     cmp     r0, #0                      @ null return?
8336     beq     common_exceptionThrown      @ alloc failed, handle exception
8337
8338     FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8339     str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
8340     add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8341     subs    r9, r9, #1                  @ length--, check for neg
8342     FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8343     bmi     2f                          @ was zero, bail
8344
8345     @ copy values from registers into the array
8346     @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8347     .if     1
8348     add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
8349 1:  ldr     r3, [r2], #4                @ r3<- *r2++
8350     subs    r9, r9, #1                  @ count--
8351     str     r3, [r0], #4                @ *contents++ = vX
8352     bpl     1b
8353     @ continue at 2
8354     .else
8355     cmp     r9, #4                      @ length was initially 5?
8356     and     r2, r10, #15                @ r2<- A
8357     bne     1f                          @ <= 4 args, branch
8358     GET_VREG(r3, r2)                    @ r3<- vA
8359     sub     r9, r9, #1                  @ count--
8360     str     r3, [r0, #16]               @ contents[4] = vA
8361 1:  and     r2, r1, #15                 @ r2<- F/E/D/C
8362     GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8363     mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8364     subs    r9, r9, #1                  @ count--
8365     str     r3, [r0], #4                @ *contents++ = vX
8366     bpl     1b
8367     @ continue at 2
8368     .endif
8369
8370 2:
8371     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
8372     GOTO_OPCODE(ip)                     @ execute it
8373
8374     /*
8375      * Throw an exception indicating that we have not implemented this
8376      * mode of filled-new-array.
8377      */
8378 .LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
8379     ldr     r0, .L_strInternalError
8380     ldr     r1, .L_strFilledNewArrayNotImpl
8381     bl      dvmThrowException
8382     b       common_exceptionThrown
8383
8384     .if     (!1)                 @ define in one or the other, not both
8385 .L_strFilledNewArrayNotImpl:
8386     .word   .LstrFilledNewArrayNotImpl
8387 .L_strInternalError:
8388     .word   .LstrInternalError
8389     .endif
8390
8391
8392 /* continuation for OP_CMPL_FLOAT */
8393
8394     @ Test for NaN with a second comparison.  EABI forbids testing bit
8395     @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8396     @ make the library call.
8397 .LOP_CMPL_FLOAT_gt_or_nan:
8398     mov     r1, r9                      @ reverse order
8399     mov     r0, r10
8400     bl      __aeabi_cfcmple             @ r0<- Z set if eq, C clear if <
8401     @bleq    common_abort
8402     movcc   r1, #1                      @ (greater than) r1<- 1
8403     bcc     .LOP_CMPL_FLOAT_finish
8404     mvn     r1, #0                            @ r1<- 1 or -1 for NaN
8405     b       .LOP_CMPL_FLOAT_finish
8406
8407
8408 #if 0       /* "clasic" form */
8409     FETCH(r0, 1)                        @ r0<- CCBB
8410     and     r2, r0, #255                @ r2<- BB
8411     mov     r3, r0, lsr #8              @ r3<- CC
8412     GET_VREG(r9, r2)                    @ r9<- vBB
8413     GET_VREG(r10, r3)                   @ r10<- vCC
8414     mov     r0, r9                      @ r0<- vBB
8415     mov     r1, r10                     @ r1<- vCC
8416     bl      __aeabi_fcmpeq              @ r0<- (vBB == vCC)
8417     cmp     r0, #0                      @ equal?
8418     movne   r1, #0                      @ yes, result is 0
8419     bne     OP_CMPL_FLOAT_finish
8420     mov     r0, r9                      @ r0<- vBB
8421     mov     r1, r10                     @ r1<- vCC
8422     bl      __aeabi_fcmplt              @ r0<- (vBB < vCC)
8423     cmp     r0, #0                      @ less than?
8424     b       OP_CMPL_FLOAT_continue
8425 @%break
8426
8427 OP_CMPL_FLOAT_continue:
8428     mvnne   r1, #0                      @ yes, result is -1
8429     bne     OP_CMPL_FLOAT_finish
8430     mov     r0, r9                      @ r0<- vBB
8431     mov     r1, r10                     @ r1<- vCC
8432     bl      __aeabi_fcmpgt              @ r0<- (vBB > vCC)
8433     cmp     r0, #0                      @ greater than?
8434     beq     OP_CMPL_FLOAT_nan               @ no, must be NaN
8435     mov     r1, #1                      @ yes, result is 1
8436     @ fall through to _finish
8437
8438 OP_CMPL_FLOAT_finish:
8439     mov     r3, rINST, lsr #8           @ r3<- AA
8440     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8441     SET_VREG(r1, r3)                    @ vAA<- r1
8442     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8443     GOTO_OPCODE(ip)                     @ jump to next instruction
8444
8445     /*
8446      * This is expected to be uncommon, so we double-branch (once to here,
8447      * again back to _finish).
8448      */
8449 OP_CMPL_FLOAT_nan:
8450     mvn     r1, #0                            @ r1<- 1 or -1 for NaN
8451     b       OP_CMPL_FLOAT_finish
8452
8453 #endif
8454
8455
8456 /* continuation for OP_CMPG_FLOAT */
8457
8458     @ Test for NaN with a second comparison.  EABI forbids testing bit
8459     @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8460     @ make the library call.
8461 .LOP_CMPG_FLOAT_gt_or_nan:
8462     mov     r1, r9                      @ reverse order
8463     mov     r0, r10
8464     bl      __aeabi_cfcmple             @ r0<- Z set if eq, C clear if <
8465     @bleq    common_abort
8466     movcc   r1, #1                      @ (greater than) r1<- 1
8467     bcc     .LOP_CMPG_FLOAT_finish
8468     mov     r1, #1                            @ r1<- 1 or -1 for NaN
8469     b       .LOP_CMPG_FLOAT_finish
8470
8471
8472 #if 0       /* "clasic" form */
8473     FETCH(r0, 1)                        @ r0<- CCBB
8474     and     r2, r0, #255                @ r2<- BB
8475     mov     r3, r0, lsr #8              @ r3<- CC
8476     GET_VREG(r9, r2)                    @ r9<- vBB
8477     GET_VREG(r10, r3)                   @ r10<- vCC
8478     mov     r0, r9                      @ r0<- vBB
8479     mov     r1, r10                     @ r1<- vCC
8480     bl      __aeabi_fcmpeq              @ r0<- (vBB == vCC)
8481     cmp     r0, #0                      @ equal?
8482     movne   r1, #0                      @ yes, result is 0
8483     bne     OP_CMPG_FLOAT_finish
8484     mov     r0, r9                      @ r0<- vBB
8485     mov     r1, r10                     @ r1<- vCC
8486     bl      __aeabi_fcmplt              @ r0<- (vBB < vCC)
8487     cmp     r0, #0                      @ less than?
8488     b       OP_CMPG_FLOAT_continue
8489 @%break
8490
8491 OP_CMPG_FLOAT_continue:
8492     mvnne   r1, #0                      @ yes, result is -1
8493     bne     OP_CMPG_FLOAT_finish
8494     mov     r0, r9                      @ r0<- vBB
8495     mov     r1, r10                     @ r1<- vCC
8496     bl      __aeabi_fcmpgt              @ r0<- (vBB > vCC)
8497     cmp     r0, #0                      @ greater than?
8498     beq     OP_CMPG_FLOAT_nan               @ no, must be NaN
8499     mov     r1, #1                      @ yes, result is 1
8500     @ fall through to _finish
8501
8502 OP_CMPG_FLOAT_finish:
8503     mov     r3, rINST, lsr #8           @ r3<- AA
8504     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8505     SET_VREG(r1, r3)                    @ vAA<- r1
8506     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8507     GOTO_OPCODE(ip)                     @ jump to next instruction
8508
8509     /*
8510      * This is expected to be uncommon, so we double-branch (once to here,
8511      * again back to _finish).
8512      */
8513 OP_CMPG_FLOAT_nan:
8514     mov     r1, #1                            @ r1<- 1 or -1 for NaN
8515     b       OP_CMPG_FLOAT_finish
8516
8517 #endif
8518
8519
8520 /* continuation for OP_CMPL_DOUBLE */
8521
8522     @ Test for NaN with a second comparison.  EABI forbids testing bit
8523     @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8524     @ make the library call.
8525 .LOP_CMPL_DOUBLE_gt_or_nan:
8526     ldmia   r10, {r0-r1}                @ reverse order
8527     ldmia   r9, {r2-r3}
8528     bl      __aeabi_cdcmple             @ r0<- Z set if eq, C clear if <
8529     @bleq    common_abort
8530     movcc   r1, #1                      @ (greater than) r1<- 1
8531     bcc     .LOP_CMPL_DOUBLE_finish
8532     mvn     r1, #0                            @ r1<- 1 or -1 for NaN
8533     b       .LOP_CMPL_DOUBLE_finish
8534
8535
8536 /* continuation for OP_CMPG_DOUBLE */
8537
8538     @ Test for NaN with a second comparison.  EABI forbids testing bit
8539     @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8540     @ make the library call.
8541 .LOP_CMPG_DOUBLE_gt_or_nan:
8542     ldmia   r10, {r0-r1}                @ reverse order
8543     ldmia   r9, {r2-r3}
8544     bl      __aeabi_cdcmple             @ r0<- Z set if eq, C clear if <
8545     @bleq    common_abort
8546     movcc   r1, #1                      @ (greater than) r1<- 1
8547     bcc     .LOP_CMPG_DOUBLE_finish
8548     mov     r1, #1                            @ r1<- 1 or -1 for NaN
8549     b       .LOP_CMPG_DOUBLE_finish
8550
8551
8552 /* continuation for OP_CMP_LONG */
8553
8554 .LOP_CMP_LONG_less:
8555     mvn     r1, #0                      @ r1<- -1
8556     @ Want to cond code the next mov so we can avoid branch, but don't see it;
8557     @ instead, we just replicate the tail end.
8558     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8559     SET_VREG(r1, r9)                    @ vAA<- r1
8560     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8561     GOTO_OPCODE(ip)                     @ jump to next instruction
8562
8563 .LOP_CMP_LONG_greater:
8564     mov     r1, #1                      @ r1<- 1
8565     @ fall through to _finish
8566
8567 .LOP_CMP_LONG_finish:
8568     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8569     SET_VREG(r1, r9)                    @ vAA<- r1
8570     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8571     GOTO_OPCODE(ip)                     @ jump to next instruction
8572
8573
8574 /* continuation for OP_AGET_WIDE */
8575
8576 .LOP_AGET_WIDE_finish:
8577     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8578     ldrd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8579     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
8580     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8581     stmia   r9, {r2-r3}                 @ vAA/vAA+1<- r2/r3
8582     GOTO_OPCODE(ip)                     @ jump to next instruction
8583
8584
8585 /* continuation for OP_APUT_WIDE */
8586
8587 .LOP_APUT_WIDE_finish:
8588     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8589     ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
8590     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8591     strd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8592     GOTO_OPCODE(ip)                     @ jump to next instruction
8593
8594
8595 /* continuation for OP_APUT_OBJECT */
8596     /*
8597      * On entry:
8598      *  r1 = vBB (arrayObj)
8599      *  r9 = vAA (obj)
8600      *  r10 = offset into array (vBB + vCC * width)
8601      */
8602 .LOP_APUT_OBJECT_finish:
8603     cmp     r9, #0                      @ storing null reference?
8604     beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
8605     ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
8606     ldr     r1, [r1, #offObject_clazz]  @ r1<- arrayObj->clazz
8607     bl      dvmCanPutArrayElement       @ test object type vs. array type
8608     cmp     r0, #0                      @ okay?
8609     beq     common_errArrayStore        @ no
8610 .LOP_APUT_OBJECT_skip_check:
8611     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8612     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8613     str     r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
8614     GOTO_OPCODE(ip)                     @ jump to next instruction
8615
8616
8617 /* continuation for OP_IGET */
8618
8619     /*
8620      * Currently:
8621      *  r0 holds resolved field
8622      *  r9 holds object
8623      */
8624 .LOP_IGET_finish:
8625     @bl      common_squeak0
8626     cmp     r9, #0                      @ check object for null
8627     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8628     beq     common_errNullObject        @ object was null
8629     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8630     mov     r2, rINST, lsr #8           @ r2<- A+
8631     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8632     and     r2, r2, #15                 @ r2<- A
8633     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8634     SET_VREG(r0, r2)                    @ fp[A]<- r0
8635     GOTO_OPCODE(ip)                     @ jump to next instruction
8636
8637
8638 /* continuation for OP_IGET_WIDE */
8639
8640     /*
8641      * Currently:
8642      *  r0 holds resolved field
8643      *  r9 holds object
8644      */
8645 .LOP_IGET_WIDE_finish:
8646     cmp     r9, #0                      @ check object for null
8647     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8648     beq     common_errNullObject        @ object was null
8649     mov     r2, rINST, lsr #8           @ r2<- A+
8650     ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
8651     and     r2, r2, #15                 @ r2<- A
8652     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8653     add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
8654     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8655     stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
8656     GOTO_OPCODE(ip)                     @ jump to next instruction
8657
8658
8659 /* continuation for OP_IGET_OBJECT */
8660
8661     /*
8662      * Currently:
8663      *  r0 holds resolved field
8664      *  r9 holds object
8665      */
8666 .LOP_IGET_OBJECT_finish:
8667     @bl      common_squeak0
8668     cmp     r9, #0                      @ check object for null
8669     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8670     beq     common_errNullObject        @ object was null
8671     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8672     mov     r2, rINST, lsr #8           @ r2<- A+
8673     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8674     and     r2, r2, #15                 @ r2<- A
8675     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8676     SET_VREG(r0, r2)                    @ fp[A]<- r0
8677     GOTO_OPCODE(ip)                     @ jump to next instruction
8678
8679
8680 /* continuation for OP_IGET_BOOLEAN */
8681
8682     /*
8683      * Currently:
8684      *  r0 holds resolved field
8685      *  r9 holds object
8686      */
8687 .LOP_IGET_BOOLEAN_finish:
8688     @bl      common_squeak1
8689     cmp     r9, #0                      @ check object for null
8690     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8691     beq     common_errNullObject        @ object was null
8692     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8693     mov     r2, rINST, lsr #8           @ r2<- A+
8694     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8695     and     r2, r2, #15                 @ r2<- A
8696     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8697     SET_VREG(r0, r2)                    @ fp[A]<- r0
8698     GOTO_OPCODE(ip)                     @ jump to next instruction
8699
8700
8701 /* continuation for OP_IGET_BYTE */
8702
8703     /*
8704      * Currently:
8705      *  r0 holds resolved field
8706      *  r9 holds object
8707      */
8708 .LOP_IGET_BYTE_finish:
8709     @bl      common_squeak2
8710     cmp     r9, #0                      @ check object for null
8711     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8712     beq     common_errNullObject        @ object was null
8713     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8714     mov     r2, rINST, lsr #8           @ r2<- A+
8715     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8716     and     r2, r2, #15                 @ r2<- A
8717     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8718     SET_VREG(r0, r2)                    @ fp[A]<- r0
8719     GOTO_OPCODE(ip)                     @ jump to next instruction
8720
8721
8722 /* continuation for OP_IGET_CHAR */
8723
8724     /*
8725      * Currently:
8726      *  r0 holds resolved field
8727      *  r9 holds object
8728      */
8729 .LOP_IGET_CHAR_finish:
8730     @bl      common_squeak3
8731     cmp     r9, #0                      @ check object for null
8732     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8733     beq     common_errNullObject        @ object was null
8734     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8735     mov     r2, rINST, lsr #8           @ r2<- A+
8736     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8737     and     r2, r2, #15                 @ r2<- A
8738     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8739     SET_VREG(r0, r2)                    @ fp[A]<- r0
8740     GOTO_OPCODE(ip)                     @ jump to next instruction
8741
8742
8743 /* continuation for OP_IGET_SHORT */
8744
8745     /*
8746      * Currently:
8747      *  r0 holds resolved field
8748      *  r9 holds object
8749      */
8750 .LOP_IGET_SHORT_finish:
8751     @bl      common_squeak4
8752     cmp     r9, #0                      @ check object for null
8753     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8754     beq     common_errNullObject        @ object was null
8755     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8756     mov     r2, rINST, lsr #8           @ r2<- A+
8757     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8758     and     r2, r2, #15                 @ r2<- A
8759     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8760     SET_VREG(r0, r2)                    @ fp[A]<- r0
8761     GOTO_OPCODE(ip)                     @ jump to next instruction
8762
8763
8764 /* continuation for OP_IPUT */
8765
8766     /*
8767      * Currently:
8768      *  r0 holds resolved field
8769      *  r9 holds object
8770      */
8771 .LOP_IPUT_finish:
8772     @bl      common_squeak0
8773     mov     r1, rINST, lsr #8           @ r1<- A+
8774     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8775     and     r1, r1, #15                 @ r1<- A
8776     cmp     r9, #0                      @ check object for null
8777     GET_VREG(r0, r1)                    @ r0<- fp[A]
8778     beq     common_errNullObject        @ object was null
8779     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8780     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8781     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8782     GOTO_OPCODE(ip)                     @ jump to next instruction
8783
8784
8785 /* continuation for OP_IPUT_WIDE */
8786
8787     /*
8788      * Currently:
8789      *  r0 holds resolved field
8790      *  r9 holds object
8791      */
8792 .LOP_IPUT_WIDE_finish:
8793     mov     r2, rINST, lsr #8           @ r2<- A+
8794     cmp     r9, #0                      @ check object for null
8795     and     r2, r2, #15                 @ r2<- A
8796     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8797     add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
8798     beq     common_errNullObject        @ object was null
8799     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8800     ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
8801     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8802     strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0
8803     GOTO_OPCODE(ip)                     @ jump to next instruction
8804
8805
8806 /* continuation for OP_IPUT_OBJECT */
8807
8808     /*
8809      * Currently:
8810      *  r0 holds resolved field
8811      *  r9 holds object
8812      */
8813 .LOP_IPUT_OBJECT_finish:
8814     @bl      common_squeak0
8815     mov     r1, rINST, lsr #8           @ r1<- A+
8816     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8817     and     r1, r1, #15                 @ r1<- A
8818     cmp     r9, #0                      @ check object for null
8819     GET_VREG(r0, r1)                    @ r0<- fp[A]
8820     beq     common_errNullObject        @ object was null
8821     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8822     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8823     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8824     GOTO_OPCODE(ip)                     @ jump to next instruction
8825
8826
8827 /* continuation for OP_IPUT_BOOLEAN */
8828
8829     /*
8830      * Currently:
8831      *  r0 holds resolved field
8832      *  r9 holds object
8833      */
8834 .LOP_IPUT_BOOLEAN_finish:
8835     @bl      common_squeak1
8836     mov     r1, rINST, lsr #8           @ r1<- A+
8837     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8838     and     r1, r1, #15                 @ r1<- A
8839     cmp     r9, #0                      @ check object for null
8840     GET_VREG(r0, r1)                    @ r0<- fp[A]
8841     beq     common_errNullObject        @ object was null
8842     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8843     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8844     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8845     GOTO_OPCODE(ip)                     @ jump to next instruction
8846
8847
8848 /* continuation for OP_IPUT_BYTE */
8849
8850     /*
8851      * Currently:
8852      *  r0 holds resolved field
8853      *  r9 holds object
8854      */
8855 .LOP_IPUT_BYTE_finish:
8856     @bl      common_squeak2
8857     mov     r1, rINST, lsr #8           @ r1<- A+
8858     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8859     and     r1, r1, #15                 @ r1<- A
8860     cmp     r9, #0                      @ check object for null
8861     GET_VREG(r0, r1)                    @ r0<- fp[A]
8862     beq     common_errNullObject        @ object was null
8863     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8864     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8865     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8866     GOTO_OPCODE(ip)                     @ jump to next instruction
8867
8868
8869 /* continuation for OP_IPUT_CHAR */
8870
8871     /*
8872      * Currently:
8873      *  r0 holds resolved field
8874      *  r9 holds object
8875      */
8876 .LOP_IPUT_CHAR_finish:
8877     @bl      common_squeak3
8878     mov     r1, rINST, lsr #8           @ r1<- A+
8879     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8880     and     r1, r1, #15                 @ r1<- A
8881     cmp     r9, #0                      @ check object for null
8882     GET_VREG(r0, r1)                    @ r0<- fp[A]
8883     beq     common_errNullObject        @ object was null
8884     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8885     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8886     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8887     GOTO_OPCODE(ip)                     @ jump to next instruction
8888
8889
8890 /* continuation for OP_IPUT_SHORT */
8891
8892     /*
8893      * Currently:
8894      *  r0 holds resolved field
8895      *  r9 holds object
8896      */
8897 .LOP_IPUT_SHORT_finish:
8898     @bl      common_squeak4
8899     mov     r1, rINST, lsr #8           @ r1<- A+
8900     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8901     and     r1, r1, #15                 @ r1<- A
8902     cmp     r9, #0                      @ check object for null
8903     GET_VREG(r0, r1)                    @ r0<- fp[A]
8904     beq     common_errNullObject        @ object was null
8905     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8906     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8907     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8908     GOTO_OPCODE(ip)                     @ jump to next instruction
8909
8910
8911 /* continuation for OP_SGET */
8912
8913     /*
8914      * Continuation if the field has not yet been resolved.
8915      *  r1: BBBB field ref
8916      */
8917 .LOP_SGET_resolve:
8918     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8919     EXPORT_PC()                         @ resolve() could throw, so export now
8920     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8921     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8922     cmp     r0, #0                      @ success?
8923     bne     .LOP_SGET_finish          @ yes, finish
8924     b       common_exceptionThrown      @ no, handle exception
8925
8926
8927 /* continuation for OP_SGET_WIDE */
8928
8929     /*
8930      * Continuation if the field has not yet been resolved.
8931      *  r1: BBBB field ref
8932      */
8933 .LOP_SGET_WIDE_resolve:
8934     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8935     EXPORT_PC()                         @ resolve() could throw, so export now
8936     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8937     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8938     cmp     r0, #0                      @ success?
8939     bne     .LOP_SGET_WIDE_finish          @ yes, finish
8940     b       common_exceptionThrown      @ no, handle exception
8941
8942
8943 /* continuation for OP_SGET_OBJECT */
8944
8945     /*
8946      * Continuation if the field has not yet been resolved.
8947      *  r1: BBBB field ref
8948      */
8949 .LOP_SGET_OBJECT_resolve:
8950     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8951     EXPORT_PC()                         @ resolve() could throw, so export now
8952     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8953     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8954     cmp     r0, #0                      @ success?
8955     bne     .LOP_SGET_OBJECT_finish          @ yes, finish
8956     b       common_exceptionThrown      @ no, handle exception
8957
8958
8959 /* continuation for OP_SGET_BOOLEAN */
8960
8961     /*
8962      * Continuation if the field has not yet been resolved.
8963      *  r1: BBBB field ref
8964      */
8965 .LOP_SGET_BOOLEAN_resolve:
8966     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8967     EXPORT_PC()                         @ resolve() could throw, so export now
8968     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8969     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8970     cmp     r0, #0                      @ success?
8971     bne     .LOP_SGET_BOOLEAN_finish          @ yes, finish
8972     b       common_exceptionThrown      @ no, handle exception
8973
8974
8975 /* continuation for OP_SGET_BYTE */
8976
8977     /*
8978      * Continuation if the field has not yet been resolved.
8979      *  r1: BBBB field ref
8980      */
8981 .LOP_SGET_BYTE_resolve:
8982     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8983     EXPORT_PC()                         @ resolve() could throw, so export now
8984     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8985     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8986     cmp     r0, #0                      @ success?
8987     bne     .LOP_SGET_BYTE_finish          @ yes, finish
8988     b       common_exceptionThrown      @ no, handle exception
8989
8990
8991 /* continuation for OP_SGET_CHAR */
8992
8993     /*
8994      * Continuation if the field has not yet been resolved.
8995      *  r1: BBBB field ref
8996      */
8997 .LOP_SGET_CHAR_resolve:
8998     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8999     EXPORT_PC()                         @ resolve() could throw, so export now
9000     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9001     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9002     cmp     r0, #0                      @ success?
9003     bne     .LOP_SGET_CHAR_finish          @ yes, finish
9004     b       common_exceptionThrown      @ no, handle exception
9005
9006
9007 /* continuation for OP_SGET_SHORT */
9008
9009     /*
9010      * Continuation if the field has not yet been resolved.
9011      *  r1: BBBB field ref
9012      */
9013 .LOP_SGET_SHORT_resolve:
9014     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9015     EXPORT_PC()                         @ resolve() could throw, so export now
9016     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9017     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9018     cmp     r0, #0                      @ success?
9019     bne     .LOP_SGET_SHORT_finish          @ yes, finish
9020     b       common_exceptionThrown      @ no, handle exception
9021
9022
9023 /* continuation for OP_SPUT */
9024
9025     /*
9026      * Continuation if the field has not yet been resolved.
9027      *  r1: BBBB field ref
9028      */
9029 .LOP_SPUT_resolve:
9030     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9031     EXPORT_PC()                         @ resolve() could throw, so export now
9032     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9033     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9034     cmp     r0, #0                      @ success?
9035     bne     .LOP_SPUT_finish          @ yes, finish
9036     b       common_exceptionThrown      @ no, handle exception
9037
9038
9039 /* continuation for OP_SPUT_WIDE */
9040
9041     /*
9042      * Continuation if the field has not yet been resolved.
9043      *  r1: BBBB field ref
9044      *  r9: &fp[AA]
9045      */
9046 .LOP_SPUT_WIDE_resolve:
9047     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9048     EXPORT_PC()                         @ resolve() could throw, so export now
9049     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9050     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9051     cmp     r0, #0                      @ success?
9052     bne     .LOP_SPUT_WIDE_finish          @ yes, finish
9053     b       common_exceptionThrown      @ no, handle exception
9054
9055
9056 /* continuation for OP_SPUT_OBJECT */
9057
9058     /*
9059      * Continuation if the field has not yet been resolved.
9060      *  r1: BBBB field ref
9061      */
9062 .LOP_SPUT_OBJECT_resolve:
9063     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9064     EXPORT_PC()                         @ resolve() could throw, so export now
9065     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9066     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9067     cmp     r0, #0                      @ success?
9068     bne     .LOP_SPUT_OBJECT_finish          @ yes, finish
9069     b       common_exceptionThrown      @ no, handle exception
9070
9071
9072 /* continuation for OP_SPUT_BOOLEAN */
9073
9074     /*
9075      * Continuation if the field has not yet been resolved.
9076      *  r1: BBBB field ref
9077      */
9078 .LOP_SPUT_BOOLEAN_resolve:
9079     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9080     EXPORT_PC()                         @ resolve() could throw, so export now
9081     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9082     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9083     cmp     r0, #0                      @ success?
9084     bne     .LOP_SPUT_BOOLEAN_finish          @ yes, finish
9085     b       common_exceptionThrown      @ no, handle exception
9086
9087
9088 /* continuation for OP_SPUT_BYTE */
9089
9090     /*
9091      * Continuation if the field has not yet been resolved.
9092      *  r1: BBBB field ref
9093      */
9094 .LOP_SPUT_BYTE_resolve:
9095     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9096     EXPORT_PC()                         @ resolve() could throw, so export now
9097     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9098     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9099     cmp     r0, #0                      @ success?
9100     bne     .LOP_SPUT_BYTE_finish          @ yes, finish
9101     b       common_exceptionThrown      @ no, handle exception
9102
9103
9104 /* continuation for OP_SPUT_CHAR */
9105
9106     /*
9107      * Continuation if the field has not yet been resolved.
9108      *  r1: BBBB field ref
9109      */
9110 .LOP_SPUT_CHAR_resolve:
9111     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9112     EXPORT_PC()                         @ resolve() could throw, so export now
9113     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9114     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9115     cmp     r0, #0                      @ success?
9116     bne     .LOP_SPUT_CHAR_finish          @ yes, finish
9117     b       common_exceptionThrown      @ no, handle exception
9118
9119
9120 /* continuation for OP_SPUT_SHORT */
9121
9122     /*
9123      * Continuation if the field has not yet been resolved.
9124      *  r1: BBBB field ref
9125      */
9126 .LOP_SPUT_SHORT_resolve:
9127     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9128     EXPORT_PC()                         @ resolve() could throw, so export now
9129     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9130     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9131     cmp     r0, #0                      @ success?
9132     bne     .LOP_SPUT_SHORT_finish          @ yes, finish
9133     b       common_exceptionThrown      @ no, handle exception
9134
9135
9136 /* continuation for OP_INVOKE_VIRTUAL */
9137
9138     /*
9139      * At this point:
9140      *  r0 = resolved base method
9141      *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
9142      */
9143 .LOP_INVOKE_VIRTUAL_continue:
9144     GET_VREG(r1, r10)                   @ r1<- "this" ptr
9145     ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
9146     cmp     r1, #0                      @ is "this" null?
9147     beq     common_errNullObject        @ null "this", throw exception
9148     ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
9149     ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
9150     ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
9151     bl      common_invokeMethodNoRange @ continue on
9152
9153
9154 /* continuation for OP_INVOKE_SUPER */
9155
9156     /*
9157      * At this point:
9158      *  r0 = resolved base method
9159      *  r9 = method->clazz
9160      */
9161 .LOP_INVOKE_SUPER_continue:
9162     ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
9163     ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
9164     ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
9165     EXPORT_PC()                         @ must export for invoke
9166     cmp     r2, r3                      @ compare (methodIndex, vtableCount)
9167     bcs     .LOP_INVOKE_SUPER_nsm             @ method not present in superclass
9168     ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
9169     ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
9170     bl      common_invokeMethodNoRange @ continue on
9171
9172 .LOP_INVOKE_SUPER_resolve:
9173     mov     r0, r9                      @ r0<- method->clazz
9174     mov     r2, #METHOD_VIRTUAL         @ resolver method type
9175     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
9176     cmp     r0, #0                      @ got null?
9177     bne     .LOP_INVOKE_SUPER_continue        @ no, continue
9178     b       common_exceptionThrown      @ yes, handle exception
9179
9180     /*
9181      * Throw a NoSuchMethodError with the method name as the message.
9182      *  r0 = resolved base method
9183      */
9184 .LOP_INVOKE_SUPER_nsm:
9185     ldr     r1, [r0, #offMethod_name]   @ r1<- method name
9186     b       common_errNoSuchMethod
9187
9188
9189 /* continuation for OP_INVOKE_DIRECT */
9190
9191     /*
9192      * On entry:
9193      *  r1 = reference (BBBB or CCCC)
9194      *  r10 = "this" register
9195      */
9196 .LOP_INVOKE_DIRECT_resolve:
9197     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
9198     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
9199     mov     r2, #METHOD_DIRECT          @ resolver method type
9200     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
9201     cmp     r0, #0                      @ got null?
9202     GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
9203     bne     .LOP_INVOKE_DIRECT_finish          @ no, continue
9204     b       common_exceptionThrown      @ yes, handle exception
9205
9206
9207 /* continuation for OP_INVOKE_VIRTUAL_RANGE */
9208
9209     /*
9210      * At this point:
9211      *  r0 = resolved base method
9212      *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
9213      */
9214 .LOP_INVOKE_VIRTUAL_RANGE_continue:
9215     GET_VREG(r1, r10)                   @ r1<- "this" ptr
9216     ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
9217     cmp     r1, #0                      @ is "this" null?
9218     beq     common_errNullObject        @ null "this", throw exception
9219     ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
9220     ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
9221     ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
9222     bl      common_invokeMethodRange @ continue on
9223
9224
9225 /* continuation for OP_INVOKE_SUPER_RANGE */
9226
9227     /*
9228      * At this point:
9229      *  r0 = resolved base method
9230      *  r9 = method->clazz
9231      */
9232 .LOP_INVOKE_SUPER_RANGE_continue:
9233     ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
9234     ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
9235     ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
9236     EXPORT_PC()                         @ must export for invoke
9237     cmp     r2, r3                      @ compare (methodIndex, vtableCount)
9238     bcs     .LOP_INVOKE_SUPER_RANGE_nsm             @ method not present in superclass
9239     ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
9240     ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
9241     bl      common_invokeMethodRange @ continue on
9242
9243 .LOP_INVOKE_SUPER_RANGE_resolve:
9244     mov     r0, r9                      @ r0<- method->clazz
9245     mov     r2, #METHOD_VIRTUAL         @ resolver method type
9246     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
9247     cmp     r0, #0                      @ got null?
9248     bne     .LOP_INVOKE_SUPER_RANGE_continue        @ no, continue
9249     b       common_exceptionThrown      @ yes, handle exception
9250
9251     /*
9252      * Throw a NoSuchMethodError with the method name as the message.
9253      *  r0 = resolved base method
9254      */
9255 .LOP_INVOKE_SUPER_RANGE_nsm:
9256     ldr     r1, [r0, #offMethod_name]   @ r1<- method name
9257     b       common_errNoSuchMethod
9258
9259
9260 /* continuation for OP_INVOKE_DIRECT_RANGE */
9261
9262     /*
9263      * On entry:
9264      *  r1 = reference (BBBB or CCCC)
9265      *  r10 = "this" register
9266      */
9267 .LOP_INVOKE_DIRECT_RANGE_resolve:
9268     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
9269     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
9270     mov     r2, #METHOD_DIRECT          @ resolver method type
9271     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
9272     cmp     r0, #0                      @ got null?
9273     GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
9274     bne     .LOP_INVOKE_DIRECT_RANGE_finish          @ no, continue
9275     b       common_exceptionThrown      @ yes, handle exception
9276
9277
9278 /* continuation for OP_FLOAT_TO_LONG */
9279 /*
9280  * Convert the float in r0 to a long in r0/r1.
9281  *
9282  * We have to clip values to long min/max per the specification.  The
9283  * expected common case is a "reasonable" value that converts directly
9284  * to modest integer.  The EABI convert function isn't doing this for us.
9285  */
9286 f2l_doconv:
9287     stmfd   sp!, {r4, lr}
9288     mov     r1, #0x5f000000             @ (float)maxlong
9289     mov     r4, r0
9290     bl      __aeabi_fcmpge              @ is arg >= maxlong?
9291     cmp     r0, #0                      @ nonzero == yes
9292     mvnne   r0, #0                      @ return maxlong (7fffffff)
9293     mvnne   r1, #0x80000000
9294     ldmnefd sp!, {r4, pc}
9295
9296     mov     r0, r4                      @ recover arg
9297     mov     r1, #0xdf000000             @ (float)minlong
9298     bl      __aeabi_fcmple              @ is arg <= minlong?
9299     cmp     r0, #0                      @ nonzero == yes
9300     movne   r0, #0                      @ return minlong (80000000)
9301     movne   r1, #0x80000000
9302     ldmnefd sp!, {r4, pc}
9303
9304     mov     r0, r4                      @ recover arg
9305     mov     r1, r4
9306     bl      __aeabi_fcmpeq              @ is arg == self?
9307     cmp     r0, #0                      @ zero == no
9308     moveq   r1, #0                      @ return zero for NaN
9309     ldmeqfd sp!, {r4, pc}
9310
9311     mov     r0, r4                      @ recover arg
9312     bl      __aeabi_f2lz                @ convert float to long
9313     ldmfd   sp!, {r4, pc}
9314
9315
9316 /* continuation for OP_DOUBLE_TO_LONG */
9317 /*
9318  * Convert the double in r0/r1 to a long in r0/r1.
9319  *
9320  * We have to clip values to long min/max per the specification.  The
9321  * expected common case is a "reasonable" value that converts directly
9322  * to modest integer.  The EABI convert function isn't doing this for us.
9323  */
9324 d2l_doconv:
9325     stmfd   sp!, {r4, r5, lr}           @ save regs
9326     mov     r3, #0x43000000             @ maxlong, as a double (high word)
9327     add     r3, #0x00e00000             @  0x43e00000
9328     mov     r2, #0                      @ maxlong, as a double (low word)
9329     sub     sp, sp, #4                  @ align for EABI
9330     mov     r4, r0                      @ save a copy of r0
9331     mov     r5, r1                      @  and r1
9332     bl      __aeabi_dcmpge              @ is arg >= maxlong?
9333     cmp     r0, #0                      @ nonzero == yes
9334     mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
9335     mvnne   r1, #0x80000000
9336     bne     1f
9337
9338     mov     r0, r4                      @ recover arg
9339     mov     r1, r5
9340     mov     r3, #0xc3000000             @ minlong, as a double (high word)
9341     add     r3, #0x00e00000             @  0xc3e00000
9342     mov     r2, #0                      @ minlong, as a double (low word)
9343     bl      __aeabi_dcmple              @ is arg <= minlong?
9344     cmp     r0, #0                      @ nonzero == yes
9345     movne   r0, #0                      @ return minlong (8000000000000000)
9346     movne   r1, #0x80000000
9347     bne     1f
9348
9349     mov     r0, r4                      @ recover arg
9350     mov     r1, r5
9351     mov     r2, r4                      @ compare against self
9352     mov     r3, r5
9353     bl      __aeabi_dcmpeq              @ is arg == self?
9354     cmp     r0, #0                      @ zero == no
9355     moveq   r1, #0                      @ return zero for NaN
9356     beq     1f
9357
9358     mov     r0, r4                      @ recover arg
9359     mov     r1, r5
9360     bl      __aeabi_d2lz                @ convert double to long
9361
9362 1:
9363     add     sp, sp, #4
9364     ldmfd   sp!, {r4, r5, pc}
9365
9366
9367 /* continuation for OP_MUL_LONG */
9368
9369 .LOP_MUL_LONG_finish:
9370     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9371     stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
9372     GOTO_OPCODE(ip)                     @ jump to next instruction
9373
9374
9375 /* continuation for OP_SHL_LONG */
9376
9377 .LOP_SHL_LONG_finish:
9378     mov     r0, r0, asl r2              @  r0<- r0 << r2
9379     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9380     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9381     GOTO_OPCODE(ip)                     @ jump to next instruction
9382
9383
9384 /* continuation for OP_SHR_LONG */
9385
9386 .LOP_SHR_LONG_finish:
9387     mov     r1, r1, asr r2              @  r1<- r1 >> r2
9388     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9389     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9390     GOTO_OPCODE(ip)                     @ jump to next instruction
9391
9392
9393 /* continuation for OP_USHR_LONG */
9394
9395 .LOP_USHR_LONG_finish:
9396     mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
9397     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9398     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9399     GOTO_OPCODE(ip)                     @ jump to next instruction
9400
9401
9402 /* continuation for OP_SHL_LONG_2ADDR */
9403
9404 .LOP_SHL_LONG_2ADDR_finish:
9405     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9406     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9407     GOTO_OPCODE(ip)                     @ jump to next instruction
9408
9409
9410 /* continuation for OP_SHR_LONG_2ADDR */
9411
9412 .LOP_SHR_LONG_2ADDR_finish:
9413     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9414     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9415     GOTO_OPCODE(ip)                     @ jump to next instruction
9416
9417
9418 /* continuation for OP_USHR_LONG_2ADDR */
9419
9420 .LOP_USHR_LONG_2ADDR_finish:
9421     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9422     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9423     GOTO_OPCODE(ip)                     @ jump to next instruction
9424
9425
9426 /* continuation for OP_EXECUTE_INLINE */
9427
9428     /*
9429      * Extract args, call function.
9430      *  r0 = #of args (0-4)
9431      *  r10 = call index
9432      *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
9433      *
9434      * Other ideas:
9435      * - Use a jump table from the main piece to jump directly into the
9436      *   AND/LDR pairs.  Costs a data load, saves a branch.
9437      * - Have five separate pieces that do the loading, so we can work the
9438      *   interleave a little better.  Increases code size.
9439      */
9440 .LOP_EXECUTE_INLINE_continue:
9441     rsb     r0, r0, #4                  @ r0<- 4-r0
9442     FETCH(r9, 2)                        @ r9<- FEDC
9443     add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
9444     bl      common_abort                @ (skipped due to ARM prefetch)
9445 4:  and     ip, r9, #0xf000             @ isolate F
9446     ldr     r3, [rFP, ip, lsr #10]      @ r3<- vF (shift right 12, left 2)
9447 3:  and     ip, r9, #0x0f00             @ isolate E
9448     ldr     r2, [rFP, ip, lsr #6]       @ r2<- vE
9449 2:  and     ip, r9, #0x00f0             @ isolate D
9450     ldr     r1, [rFP, ip, lsr #2]       @ r1<- vD
9451 1:  and     ip, r9, #0x000f             @ isolate C
9452     ldr     r0, [rFP, ip, lsl #2]       @ r0<- vC
9453 0:
9454     ldr     r9, .LOP_EXECUTE_INLINE_table       @ table of InlineOperation
9455     LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
9456     @ (not reached)
9457
9458 .LOP_EXECUTE_INLINE_table:
9459     .word   gDvmInlineOpsTable
9460
9461
9462     .size   dvmAsmSisterStart, .-dvmAsmSisterStart
9463     .global dvmAsmSisterEnd
9464 dvmAsmSisterEnd:
9465
9466 /* File: armv5te/footer.S */
9467
9468 /*
9469  * ===========================================================================
9470  *  Common subroutines and data
9471  * ===========================================================================
9472  */
9473
9474
9475
9476     .text
9477     .align  2
9478
9479 #if defined(WITH_JIT)
9480 #if defined(WITH_SELF_VERIFICATION)
9481     .global dvmJitToInterpPunt
9482 dvmJitToInterpPunt:
9483     mov    r2,#kSVSPunt                 @ r2<- interpreter entry point
9484     b      dvmJitSelfVerificationEnd    @ doesn't return
9485
9486     .global dvmJitToInterpSingleStep
9487 dvmJitToInterpSingleStep:
9488     mov    r2,#kSVSSingleStep           @ r2<- interpreter entry point
9489     b      dvmJitSelfVerificationEnd    @ doesn't return
9490
9491     .global dvmJitToTraceSelect
9492 dvmJitToTraceSelect:
9493     ldr    r0,[r14, #-1]                @ pass our target PC
9494     mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
9495     b      dvmJitSelfVerificationEnd    @ doesn't return
9496
9497     .global dvmJitToBackwardBranch
9498 dvmJitToBackwardBranch:
9499     ldr    r0,[r14, #-1]                @ pass our target PC
9500     mov    r2,#kSVSBackwardBranch       @ r2<- interpreter entry point
9501     b      dvmJitSelfVerificationEnd    @ doesn't return
9502
9503     .global dvmJitToInterpNormal
9504 dvmJitToInterpNormal:
9505     ldr    r0,[r14, #-1]                @ pass our target PC
9506     mov    r2,#kSVSNormal               @ r2<- interpreter entry point
9507     b      dvmJitSelfVerificationEnd    @ doesn't return
9508
9509     .global dvmJitToInterpNoChain
9510 dvmJitToInterpNoChain:
9511     mov    r0,rPC                       @ pass our target PC
9512     mov    r2,#kSVSNoChain              @ r2<- interpreter entry point
9513     b      dvmJitSelfVerificationEnd    @ doesn't return
9514 #else
9515 /*
9516  * Return from the translation cache to the interpreter when the compiler is
9517  * having issues translating/executing a Dalvik instruction. We have to skip
9518  * the code cache lookup otherwise it is possible to indefinitely bouce
9519  * between the interpreter and the code cache if the instruction that fails
9520  * to be compiled happens to be at a trace start.
9521  */
9522     .global dvmJitToInterpPunt
9523 dvmJitToInterpPunt:
9524     mov    rPC, r0
9525 #ifdef EXIT_STATS
9526     mov    r0,lr
9527     bl     dvmBumpPunt;
9528 #endif
9529     EXPORT_PC()
9530     adrl   rIBASE, dvmAsmInstructionStart
9531     FETCH_INST()
9532     GET_INST_OPCODE(ip)
9533     GOTO_OPCODE(ip)
9534
9535 /*
9536  * Return to the interpreter to handle a single instruction.
9537  * On entry:
9538  *    r0 <= PC
9539  *    r1 <= PC of resume instruction
9540  *    lr <= resume point in translation
9541  */
9542     .global dvmJitToInterpSingleStep
9543 dvmJitToInterpSingleStep:
9544     str    lr,[rGLUE,#offGlue_jitResume]
9545     str    r1,[rGLUE,#offGlue_jitResumePC]
9546     mov    r1,#kInterpEntryInstr
9547     @ enum is 4 byte in aapcs-EABI
9548     str    r1, [rGLUE, #offGlue_entryPoint]
9549     mov    rPC,r0
9550     EXPORT_PC()
9551     adrl   rIBASE, dvmAsmInstructionStart
9552     mov    r2,#kJitSingleStep     @ Ask for single step and then revert
9553     str    r2,[rGLUE,#offGlue_jitState]
9554     mov    r1,#1                  @ set changeInterp to bail to debug interp
9555     b      common_gotoBail
9556
9557
9558 /*
9559  * Return from the translation cache and immediately request
9560  * a translation for the exit target.  Commonly used following
9561  * invokes.
9562  */
9563     .global dvmJitToTraceSelect
9564 dvmJitToTraceSelect:
9565     ldr    rPC,[r14, #-1]           @ get our target PC
9566     add    rINST,r14,#-5            @ save start of chain branch
9567     mov    r0,rPC
9568     bl     dvmJitGetCodeAddr        @ Is there a translation?
9569     cmp    r0,#0
9570     beq    2f
9571     mov    r1,rINST
9572     bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9573     cmp    r0,#0                    @ successful chain?
9574     bxne   r0                       @ continue native execution
9575     b      toInterpreter            @ didn't chain - resume with interpreter
9576
9577 /* No translation, so request one if profiling isn't disabled*/
9578 2:
9579     adrl   rIBASE, dvmAsmInstructionStart
9580     GET_JIT_PROF_TABLE(r0)
9581     FETCH_INST()
9582     cmp    r0, #0
9583     bne    common_selectTrace
9584     GET_INST_OPCODE(ip)
9585     GOTO_OPCODE(ip)
9586
9587 /*
9588  * Return from the translation cache to the interpreter.
9589  * The return was done with a BLX from thumb mode, and
9590  * the following 32-bit word contains the target rPC value.
9591  * Note that lr (r14) will have its low-order bit set to denote
9592  * its thumb-mode origin.
9593  *
9594  * We'll need to stash our lr origin away, recover the new
9595  * target and then check to see if there is a translation available
9596  * for our new target.  If so, we do a translation chain and
9597  * go back to native execution.  Otherwise, it's back to the
9598  * interpreter (after treating this entry as a potential
9599  * trace start).
9600  */
9601     .global dvmJitToInterpNormal
9602 dvmJitToInterpNormal:
9603     ldr    rPC,[r14, #-1]           @ get our target PC
9604     add    rINST,r14,#-5            @ save start of chain branch
9605 #ifdef EXIT_STATS
9606     bl     dvmBumpNormal
9607 #endif
9608     mov    r0,rPC
9609     bl     dvmJitGetCodeAddr        @ Is there a translation?
9610     cmp    r0,#0
9611     beq    toInterpreter            @ go if not, otherwise do chain
9612     mov    r1,rINST
9613     bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9614     cmp    r0,#0                    @ successful chain?
9615     bxne   r0                       @ continue native execution
9616     b      toInterpreter            @ didn't chain - resume with interpreter
9617
9618 /*
9619  * Return from the translation cache to the interpreter to do method invocation.
9620  * Check if translation exists for the callee, but don't chain to it.
9621  */
9622     .global dvmJitToInterpNoChain
9623 dvmJitToInterpNoChain:
9624 #ifdef EXIT_STATS
9625     bl     dvmBumpNoChain
9626 #endif
9627     mov    r0,rPC
9628     bl     dvmJitGetCodeAddr        @ Is there a translation?
9629     cmp    r0,#0
9630     bxne   r0                       @ continue native execution if so
9631 #endif
9632
9633 /*
9634  * No translation, restore interpreter regs and start interpreting.
9635  * rGLUE & rFP were preserved in the translated code, and rPC has
9636  * already been restored by the time we get here.  We'll need to set
9637  * up rIBASE & rINST, and load the address of the JitTable into r0.
9638  */
9639 toInterpreter:
9640     EXPORT_PC()
9641     adrl   rIBASE, dvmAsmInstructionStart
9642     FETCH_INST()
9643     GET_JIT_PROF_TABLE(r0)
9644     @ NOTE: intended fallthrough
9645 /*
9646  * Common code to update potential trace start counter, and initiate
9647  * a trace-build if appropriate.  On entry, rPC should point to the
9648  * next instruction to execute, and rINST should be already loaded with
9649  * the next opcode word, and r0 holds a pointer to the jit profile
9650  * table (pJitProfTable).
9651  */
9652 common_testUpdateProfile:
9653     cmp     r0,#0
9654     GET_INST_OPCODE(ip)
9655     GOTO_OPCODE_IFEQ(ip)       @ if not profiling, fallthrough otherwise */
9656
9657 common_updateProfile:
9658     eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
9659     lsl     r3,r3,#23          @ shift out excess 511
9660     ldrb    r1,[r0,r3,lsr #23] @ get counter
9661     GET_INST_OPCODE(ip)
9662     subs    r1,r1,#1           @ decrement counter
9663     strb    r1,[r0,r3,lsr #23] @ and store it
9664     GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
9665
9666 /*
9667  * Here, we switch to the debug interpreter to request
9668  * trace selection.  First, though, check to see if there
9669  * is already a native translation in place (and, if so,
9670  * jump to it now).
9671  */
9672     mov     r1,#255
9673     strb    r1,[r0,r3,lsr #23] @ reset counter
9674     EXPORT_PC()
9675     mov     r0,rPC
9676     bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
9677     cmp     r0,#0
9678     beq     common_selectTrace
9679 #if !defined(WITH_SELF_VERIFICATION)
9680     bxne    r0                          @ jump to the translation
9681 #else
9682     bne     dvmJitSelfVerificationStart @ set up self verification
9683 #endif
9684 common_selectTrace:
9685     mov     r2,#kJitTSelectRequest      @ ask for trace selection
9686     str     r2,[rGLUE,#offGlue_jitState]
9687     mov     r2,#kInterpEntryInstr       @ normal entry reason
9688     str     r2,[rGLUE,#offGlue_entryPoint]
9689     mov     r1,#1                       @ set changeInterp
9690     b       common_gotoBail
9691
9692 #if defined(WITH_SELF_VERIFICATION)
9693 /*
9694  * Save PC and registers to shadow memory for self verification mode
9695  * before jumping to native translation.
9696  */
9697 dvmJitSelfVerificationStart:
9698     sub     sp,sp,#4                    @ allocate stack space
9699     str     r0,[sp,#0]                  @ save out dvmJitGetCodeAddr(rPC)
9700     mov     r0,rPC                      @ r0<- program counter
9701     mov     r1,rFP                      @ r1<- frame pointer
9702     mov     r2,rGLUE                    @ r2<- InterpState pointer
9703     bl      dvmSelfVerificationSaveState @ save registers to shadow space
9704     ldr     rFP,[r0,#20]                @ rFP<- fp in shadow space
9705     add     rGLUE,r0,#24                @ rGLUE<- pointer in shadow space
9706     ldr     r0,[sp,#0]                  @ r0<- dvmJitGetCodeAddr(rPC)
9707     add     sp,sp,#4                    @ restore stack
9708     bx      r0                          @ jump to the translation
9709
9710 /*
9711  * Restore PC, registers, and interpState to original values
9712  * before jumping back to the interpreter.
9713  */
9714 dvmJitSelfVerificationEnd:
9715     mov    r1,rFP                        @ pass ending fp
9716     bl     dvmSelfVerificationRestoreState @ restore pc and fp values
9717     ldr    rPC,[r0,#0]                   @ restore PC
9718     ldr    rFP,[r0,#4]                   @ restore FP
9719     ldr    rGLUE,[r0,#8]                 @ restore InterpState
9720     ldr    r1,[r0,#12]                   @ get exitPoint
9721     cmp    r1,#0                         @ check for punt condition
9722     beq    1f
9723     mov    r2,#kJitSelfVerification      @ ask for self verification
9724     str    r2,[rGLUE,#offGlue_jitState]
9725     mov    r2,#kInterpEntryInstr         @ normal entry reason
9726     str    r2,[rGLUE,#offGlue_entryPoint]
9727     mov    r1,#1                         @ set changeInterp
9728     b      common_gotoBail
9729
9730 1:                                       @ exit to interpreter without check
9731     EXPORT_PC()
9732     adrl   rIBASE, dvmAsmInstructionStart
9733     FETCH_INST()
9734     GET_INST_OPCODE(ip)
9735     GOTO_OPCODE(ip)
9736 #endif
9737
9738 #endif
9739
9740 /*
9741  * Common code when a backward branch is taken.
9742  *
9743  * On entry:
9744  *  r9 is PC adjustment *in bytes*
9745  */
9746 common_backwardBranch:
9747     mov     r0, #kInterpEntryInstr
9748     bl      common_periodicChecks
9749 #if defined(WITH_JIT)
9750     GET_JIT_PROF_TABLE(r0)
9751     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9752     cmp     r0,#0
9753     bne     common_updateProfile
9754     GET_INST_OPCODE(ip)
9755     GOTO_OPCODE(ip)
9756 #else
9757     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9758     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9759     GOTO_OPCODE(ip)                     @ jump to next instruction
9760 #endif
9761
9762
9763 /*
9764  * Need to see if the thread needs to be suspended or debugger/profiler
9765  * activity has begun.
9766  *
9767  * TODO: if JDWP isn't running, zero out pDebuggerActive pointer so we don't
9768  * have to do the second ldr.
9769  *
9770  * TODO: reduce this so we're just checking a single location.
9771  *
9772  * On entry:
9773  *  r0 is reentry type, e.g. kInterpEntryInstr
9774  *  r9 is trampoline PC adjustment *in bytes*
9775  */
9776 common_periodicChecks:
9777     ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
9778
9779     @ speculatively store r0 before it is clobbered by dvmCheckSuspendPending
9780     str     r0, [rGLUE, #offGlue_entryPoint]
9781
9782 #if defined(WITH_DEBUGGER)
9783     ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9784 #endif
9785 #if defined(WITH_PROFILER)
9786     ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9787 #endif
9788
9789     ldr     r3, [r3]                    @ r3<- suspendCount (int)
9790
9791 #if defined(WITH_DEBUGGER)
9792     ldrb    r1, [r1]                    @ r1<- debuggerActive (boolean)
9793 #endif
9794 #if defined (WITH_PROFILER)
9795     ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9796 #endif
9797
9798     cmp     r3, #0                      @ suspend pending?
9799     bne     2f                          @ yes, do full suspension check
9800
9801 #if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
9802 # if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
9803     orrs    r1, r1, r2                  @ r1<- r1 | r2
9804     cmp     r1, #0                      @ debugger attached or profiler started?
9805 # elif defined(WITH_DEBUGGER)
9806     cmp     r1, #0                      @ debugger attached?
9807 # elif defined(WITH_PROFILER)
9808     cmp     r2, #0                      @ profiler started?
9809 # endif
9810     bne     3f                          @ debugger/profiler, switch interp
9811 #endif
9812
9813     bx      lr                          @ nothing to do, return
9814
9815 2:  @ check suspend
9816     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9817     EXPORT_PC()                         @ need for precise GC
9818     b       dvmCheckSuspendPending      @ suspend if necessary, then return
9819
9820 3:  @ debugger/profiler enabled, bail out
9821     add     rPC, rPC, r9                @ update rPC
9822     mov     r1, #1                      @ "want switch" = true
9823     b       common_gotoBail
9824
9825
9826 /*
9827  * The equivalent of "goto bail", this calls through the "bail handler".
9828  *
9829  * State registers will be saved to the "glue" area before bailing.
9830  *
9831  * On entry:
9832  *  r1 is "bool changeInterp", indicating if we want to switch to the
9833  *     other interpreter or just bail all the way out
9834  */
9835 common_gotoBail:
9836     SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9837     mov     r0, rGLUE                   @ r0<- glue ptr
9838     b       dvmMterpStdBail             @ call(glue, changeInterp)
9839
9840     @add     r1, r1, #1                  @ using (boolean+1)
9841     @add     r0, rGLUE, #offGlue_jmpBuf  @ r0<- &glue->jmpBuf
9842     @bl      _longjmp                    @ does not return
9843     @bl      common_abort
9844
9845
9846 /*
9847  * Common code for method invocation with range.
9848  *
9849  * On entry:
9850  *  r0 is "Method* methodToCall", the method we're trying to call
9851  */
9852 common_invokeMethodRange:
9853 .LinvokeNewRange:
9854     @ prepare to copy args to "outs" area of current frame
9855     movs    r2, rINST, lsr #8           @ r2<- AA (arg count) -- test for zero
9856     SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9857     beq     .LinvokeArgsDone            @ if no args, skip the rest
9858     FETCH(r1, 2)                        @ r1<- CCCC
9859
9860     @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
9861     @ (very few methods have > 10 args; could unroll for common cases)
9862     add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
9863     sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
9864     ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
9865 1:  ldr     r1, [r3], #4                @ val = *fp++
9866     subs    r2, r2, #1                  @ count--
9867     str     r1, [r10], #4               @ *outs++ = val
9868     bne     1b                          @ ...while count != 0
9869     ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
9870     b       .LinvokeArgsDone
9871
9872 /*
9873  * Common code for method invocation without range.
9874  *
9875  * On entry:
9876  *  r0 is "Method* methodToCall", the method we're trying to call
9877  */
9878 common_invokeMethodNoRange:
9879 .LinvokeNewNoRange:
9880     @ prepare to copy args to "outs" area of current frame
9881     movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
9882     SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9883     FETCH(r1, 2)                        @ r1<- GFED (load here to hide latency)
9884     ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
9885     ldrh    r3, [r0, #offMethod_outsSize]  @ r3<- methodToCall->outsSize
9886     beq     .LinvokeArgsDone
9887
9888     @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
9889 .LinvokeNonRange:
9890     rsb     r2, r2, #5                  @ r2<- 5-r2
9891     add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
9892     bl      common_abort                @ (skipped due to ARM prefetch)
9893 5:  and     ip, rINST, #0x0f00          @ isolate A
9894     ldr     r2, [rFP, ip, lsr #6]       @ r2<- vA (shift right 8, left 2)
9895     mov     r0, r0                      @ nop
9896     str     r2, [r10, #-4]!             @ *--outs = vA
9897 4:  and     ip, r1, #0xf000             @ isolate G
9898     ldr     r2, [rFP, ip, lsr #10]      @ r2<- vG (shift right 12, left 2)
9899     mov     r0, r0                      @ nop
9900     str     r2, [r10, #-4]!             @ *--outs = vG
9901 3:  and     ip, r1, #0x0f00             @ isolate F
9902     ldr     r2, [rFP, ip, lsr #6]       @ r2<- vF
9903     mov     r0, r0                      @ nop
9904     str     r2, [r10, #-4]!             @ *--outs = vF
9905 2:  and     ip, r1, #0x00f0             @ isolate E
9906     ldr     r2, [rFP, ip, lsr #2]       @ r2<- vE
9907     mov     r0, r0                      @ nop
9908     str     r2, [r10, #-4]!             @ *--outs = vE
9909 1:  and     ip, r1, #0x000f             @ isolate D
9910     ldr     r2, [rFP, ip, lsl #2]       @ r2<- vD
9911     mov     r0, r0                      @ nop
9912     str     r2, [r10, #-4]!             @ *--outs = vD
9913 0:  @ fall through to .LinvokeArgsDone
9914
9915 .LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
9916     ldr     r2, [r0, #offMethod_insns]  @ r2<- method->insns
9917     ldr     rINST, [r0, #offMethod_clazz]  @ rINST<- method->clazz
9918     @ find space for the new stack frame, check for overflow
9919     SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
9920     sub     r1, r1, r9, lsl #2          @ r1<- newFp (old savearea - regsSize)
9921     SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
9922 @    bl      common_dumpRegs
9923     ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
9924     sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
9925     cmp     r3, r9                      @ bottom < interpStackEnd?
9926     ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
9927     blt     .LstackOverflow             @ yes, this frame will overflow stack
9928
9929     @ set up newSaveArea
9930 #ifdef EASY_GDB
9931     SAVEAREA_FROM_FP(ip, rFP)           @ ip<- stack save area
9932     str     ip, [r10, #offStackSaveArea_prevSave]
9933 #endif
9934     str     rFP, [r10, #offStackSaveArea_prevFrame]
9935     str     rPC, [r10, #offStackSaveArea_savedPc]
9936 #if defined(WITH_JIT)
9937     mov     r9, #0
9938     str     r9, [r10, #offStackSaveArea_returnAddr]
9939 #endif
9940     str     r0, [r10, #offStackSaveArea_method]
9941     tst     r3, #ACC_NATIVE
9942     bne     .LinvokeNative
9943
9944     /*
9945     stmfd   sp!, {r0-r3}
9946     bl      common_printNewline
9947     mov     r0, rFP
9948     mov     r1, #0
9949     bl      dvmDumpFp
9950     ldmfd   sp!, {r0-r3}
9951     stmfd   sp!, {r0-r3}
9952     mov     r0, r1
9953     mov     r1, r10
9954     bl      dvmDumpFp
9955     bl      common_printNewline
9956     ldmfd   sp!, {r0-r3}
9957     */
9958
9959     ldrh    r9, [r2]                        @ r9 <- load INST from new PC
9960     ldr     r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
9961     mov     rPC, r2                         @ publish new rPC
9962     ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
9963
9964     @ Update "glue" values for the new method
9965     @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
9966     str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
9967     str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
9968 #if defined(WITH_JIT)
9969     GET_JIT_PROF_TABLE(r0)
9970     mov     rFP, r1                         @ fp = newFp
9971     GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
9972     mov     rINST, r9                       @ publish new rINST
9973     str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
9974     cmp     r0,#0
9975     bne     common_updateProfile
9976     GOTO_OPCODE(ip)                         @ jump to next instruction
9977 #else
9978     mov     rFP, r1                         @ fp = newFp
9979     GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
9980     mov     rINST, r9                       @ publish new rINST
9981     str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
9982     GOTO_OPCODE(ip)                         @ jump to next instruction
9983 #endif
9984
9985 .LinvokeNative:
9986     @ Prep for the native call
9987     @ r0=methodToCall, r1=newFp, r10=newSaveArea
9988     ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
9989     ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
9990     str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
9991     str     r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
9992     mov     r9, r3                      @ r9<- glue->self (preserve)
9993
9994     mov     r2, r0                      @ r2<- methodToCall
9995     mov     r0, r1                      @ r0<- newFp (points to args)
9996     add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
9997
9998 #ifdef ASSIST_DEBUGGER
9999     /* insert fake function header to help gdb find the stack frame */
10000     b       .Lskip
10001     .type   dalvik_mterp, %function
10002 dalvik_mterp:
10003     .fnstart
10004     MTERP_ENTRY1
10005     MTERP_ENTRY2
10006 .Lskip:
10007 #endif
10008
10009     @mov     lr, pc                      @ set return addr
10010     @ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
10011     LDR_PC_LR "[r2, #offMethod_nativeFunc]"
10012
10013     @ native return; r9=self, r10=newSaveArea
10014     @ equivalent to dvmPopJniLocals
10015     ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
10016     ldr     r1, [r9, #offThread_exception] @ check for exception
10017     str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
10018     cmp     r1, #0                      @ null?
10019     str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
10020     bne     common_exceptionThrown      @ no, handle exception
10021
10022     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
10023     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10024     GOTO_OPCODE(ip)                     @ jump to next instruction
10025
10026 .LstackOverflow:    @ r0=methodToCall
10027     mov     r1, r0                      @ r1<- methodToCall
10028     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
10029     bl      dvmHandleStackOverflow
10030     b       common_exceptionThrown
10031 #ifdef ASSIST_DEBUGGER
10032     .fnend
10033 #endif
10034
10035
10036     /*
10037      * Common code for method invocation, calling through "glue code".
10038      *
10039      * TODO: now that we have range and non-range invoke handlers, this
10040      *       needs to be split into two.  Maybe just create entry points
10041      *       that set r9 and jump here?
10042      *
10043      * On entry:
10044      *  r0 is "Method* methodToCall", the method we're trying to call
10045      *  r9 is "bool methodCallRange", indicating if this is a /range variant
10046      */
10047      .if    0
10048 .LinvokeOld:
10049     sub     sp, sp, #8                  @ space for args + pad
10050     FETCH(ip, 2)                        @ ip<- FEDC or CCCC
10051     mov     r2, r0                      @ A2<- methodToCall
10052     mov     r0, rGLUE                   @ A0<- glue
10053     SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
10054     mov     r1, r9                      @ A1<- methodCallRange
10055     mov     r3, rINST, lsr #8           @ A3<- AA
10056     str     ip, [sp, #0]                @ A4<- ip
10057     bl      dvmMterp_invokeMethod       @ call the C invokeMethod
10058     add     sp, sp, #8                  @ remove arg area
10059     b       common_resumeAfterGlueCall  @ continue to next instruction
10060     .endif
10061
10062
10063
10064 /*
10065  * Common code for handling a return instruction.
10066  *
10067  * This does not return.
10068  */
10069 common_returnFromMethod:
10070 .LreturnNew:
10071     mov     r0, #kInterpEntryReturn
10072     mov     r9, #0
10073     bl      common_periodicChecks
10074
10075     SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
10076     ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
10077     ldr     r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
10078     ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
10079                                         @ r2<- method we're returning to
10080     ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
10081     cmp     r2, #0                      @ is this a break frame?
10082     ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
10083     mov     r1, #0                      @ "want switch" = false
10084     beq     common_gotoBail             @ break frame, bail out completely
10085
10086     PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
10087     str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
10088     ldr     r1, [r10, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
10089     str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
10090 #if defined(WITH_JIT)
10091     ldr     r3, [r0, #offStackSaveArea_returnAddr] @ r3 = saveArea->returnAddr
10092     GET_JIT_PROF_TABLE(r0)
10093     mov     rPC, r9                     @ publish new rPC
10094     str     r1, [rGLUE, #offGlue_methodClassDex]
10095     cmp     r3, #0                      @ caller is compiled code
10096     blxne   r3
10097     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10098     cmp     r0,#0
10099     bne     common_updateProfile
10100     GOTO_OPCODE(ip)                     @ jump to next instruction
10101 #else
10102     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10103     mov     rPC, r9                     @ publish new rPC
10104     str     r1, [rGLUE, #offGlue_methodClassDex]
10105     GOTO_OPCODE(ip)                     @ jump to next instruction
10106 #endif
10107
10108     /*
10109      * Return handling, calls through "glue code".
10110      */
10111      .if    0
10112 .LreturnOld:
10113     SAVE_PC_FP_TO_GLUE()                @ export state
10114     mov     r0, rGLUE                   @ arg to function
10115     bl      dvmMterp_returnFromMethod
10116     b       common_resumeAfterGlueCall
10117     .endif
10118
10119
10120 /*
10121  * Somebody has thrown an exception.  Handle it.
10122  *
10123  * If the exception processing code returns to us (instead of falling
10124  * out of the interpreter), continue with whatever the next instruction
10125  * now happens to be.
10126  *
10127  * This does not return.
10128  */
10129      .global dvmMterpCommonExceptionThrown
10130 dvmMterpCommonExceptionThrown:
10131 common_exceptionThrown:
10132 .LexceptionNew:
10133     mov     r0, #kInterpEntryThrow
10134     mov     r9, #0
10135     bl      common_periodicChecks
10136
10137 #if defined(WITH_JIT)
10138     mov     r2,#kJitTSelectAbort        @ abandon trace selection in progress
10139     str     r2,[rGLUE,#offGlue_jitState]
10140 #endif
10141
10142     ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
10143     ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
10144     mov     r1, r10                     @ r1<- self
10145     mov     r0, r9                      @ r0<- exception
10146     bl      dvmAddTrackedAlloc          @ don't let the exception be GCed
10147     mov     r3, #0                      @ r3<- NULL
10148     str     r3, [r10, #offThread_exception] @ self->exception = NULL
10149
10150     /* set up args and a local for "&fp" */
10151     /* (str sp, [sp, #-4]!  would be perfect here, but is discouraged) */
10152     str     rFP, [sp, #-4]!             @ *--sp = fp
10153     mov     ip, sp                      @ ip<- &fp
10154     mov     r3, #0                      @ r3<- false
10155     str     ip, [sp, #-4]!              @ *--sp = &fp
10156     ldr     r1, [rGLUE, #offGlue_method] @ r1<- glue->method
10157     mov     r0, r10                     @ r0<- self
10158     ldr     r1, [r1, #offMethod_insns]  @ r1<- method->insns
10159     mov     r2, r9                      @ r2<- exception
10160     sub     r1, rPC, r1                 @ r1<- pc - method->insns
10161     mov     r1, r1, asr #1              @ r1<- offset in code units
10162
10163     /* call, r0 gets catchRelPc (a code-unit offset) */
10164     bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
10165
10166     /* fix earlier stack overflow if necessary; may trash rFP */
10167     ldrb    r1, [r10, #offThread_stackOverflowed]
10168     cmp     r1, #0                      @ did we overflow earlier?
10169     beq     1f                          @ no, skip ahead
10170     mov     rFP, r0                     @ save relPc result in rFP
10171     mov     r0, r10                     @ r0<- self
10172     bl      dvmCleanupStackOverflow     @ call(self)
10173     mov     r0, rFP                     @ restore result
10174 1:
10175
10176     /* update frame pointer and check result from dvmFindCatchBlock */
10177     ldr     rFP, [sp, #4]               @ retrieve the updated rFP
10178     cmp     r0, #0                      @ is catchRelPc < 0?
10179     add     sp, sp, #8                  @ restore stack
10180     bmi     .LnotCaughtLocally
10181
10182     /* adjust locals to match self->curFrame and updated PC */
10183     SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
10184     ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
10185     str     r1, [rGLUE, #offGlue_method]    @ glue->method = new method
10186     ldr     r2, [r1, #offMethod_clazz]      @ r2<- method->clazz
10187     ldr     r3, [r1, #offMethod_insns]      @ r3<- method->insns
10188     ldr     r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
10189     add     rPC, r3, r0, asl #1             @ rPC<- method->insns + catchRelPc
10190     str     r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
10191
10192     /* release the tracked alloc on the exception */
10193     mov     r0, r9                      @ r0<- exception
10194     mov     r1, r10                     @ r1<- self
10195     bl      dvmReleaseTrackedAlloc      @ release the exception
10196
10197     /* restore the exception if the handler wants it */
10198     FETCH_INST()                        @ load rINST from rPC
10199     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10200     cmp     ip, #OP_MOVE_EXCEPTION      @ is it "move-exception"?
10201     streq   r9, [r10, #offThread_exception] @ yes, restore the exception
10202     GOTO_OPCODE(ip)                     @ jump to next instruction
10203
10204 .LnotCaughtLocally: @ r9=exception, r10=self
10205     /* fix stack overflow if necessary */
10206     ldrb    r1, [r10, #offThread_stackOverflowed]
10207     cmp     r1, #0                      @ did we overflow earlier?
10208     movne   r0, r10                     @ if yes: r0<- self
10209     blne    dvmCleanupStackOverflow     @ if yes: call(self)
10210
10211     @ may want to show "not caught locally" debug messages here
10212 #if DVM_SHOW_EXCEPTION >= 2
10213     /* call __android_log_print(prio, tag, format, ...) */
10214     /* "Exception %s from %s:%d not caught locally" */
10215     @ dvmLineNumFromPC(method, pc - method->insns)
10216     ldr     r0, [rGLUE, #offGlue_method]
10217     ldr     r1, [r0, #offMethod_insns]
10218     sub     r1, rPC, r1
10219     asr     r1, r1, #1
10220     bl      dvmLineNumFromPC
10221     str     r0, [sp, #-4]!
10222     @ dvmGetMethodSourceFile(method)
10223     ldr     r0, [rGLUE, #offGlue_method]
10224     bl      dvmGetMethodSourceFile
10225     str     r0, [sp, #-4]!
10226     @ exception->clazz->descriptor
10227     ldr     r3, [r9, #offObject_clazz]
10228     ldr     r3, [r3, #offClassObject_descriptor]
10229     @
10230     ldr     r2, strExceptionNotCaughtLocally
10231     ldr     r1, strLogTag
10232     mov     r0, #3                      @ LOG_DEBUG
10233     bl      __android_log_print
10234 #endif
10235     str     r9, [r10, #offThread_exception] @ restore exception
10236     mov     r0, r9                      @ r0<- exception
10237     mov     r1, r10                     @ r1<- self
10238     bl      dvmReleaseTrackedAlloc      @ release the exception
10239     mov     r1, #0                      @ "want switch" = false
10240     b       common_gotoBail             @ bail out
10241
10242
10243     /*
10244      * Exception handling, calls through "glue code".
10245      */
10246     .if     0
10247 .LexceptionOld:
10248     SAVE_PC_FP_TO_GLUE()                @ export state
10249     mov     r0, rGLUE                   @ arg to function
10250     bl      dvmMterp_exceptionThrown
10251     b       common_resumeAfterGlueCall
10252     .endif
10253
10254
10255 /*
10256  * After returning from a "glued" function, pull out the updated
10257  * values and start executing at the next instruction.
10258  */
10259 common_resumeAfterGlueCall:
10260     LOAD_PC_FP_FROM_GLUE()              @ pull rPC and rFP out of glue
10261     FETCH_INST()                        @ load rINST from rPC
10262     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10263     GOTO_OPCODE(ip)                     @ jump to next instruction
10264
10265 /*
10266  * Invalid array index.
10267  */
10268 common_errArrayIndex:
10269     EXPORT_PC()
10270     ldr     r0, strArrayIndexException
10271     mov     r1, #0
10272     bl      dvmThrowException
10273     b       common_exceptionThrown
10274
10275 /*
10276  * Invalid array value.
10277  */
10278 common_errArrayStore:
10279     EXPORT_PC()
10280     ldr     r0, strArrayStoreException
10281     mov     r1, #0
10282     bl      dvmThrowException
10283     b       common_exceptionThrown
10284
10285 /*
10286  * Integer divide or mod by zero.
10287  */
10288 common_errDivideByZero:
10289     EXPORT_PC()
10290     ldr     r0, strArithmeticException
10291     ldr     r1, strDivideByZero
10292     bl      dvmThrowException
10293     b       common_exceptionThrown
10294
10295 /*
10296  * Attempt to allocate an array with a negative size.
10297  */
10298 common_errNegativeArraySize:
10299     EXPORT_PC()
10300     ldr     r0, strNegativeArraySizeException
10301     mov     r1, #0
10302     bl      dvmThrowException
10303     b       common_exceptionThrown
10304
10305 /*
10306  * Invocation of a non-existent method.
10307  */
10308 common_errNoSuchMethod:
10309     EXPORT_PC()
10310     ldr     r0, strNoSuchMethodError
10311     mov     r1, #0
10312     bl      dvmThrowException
10313     b       common_exceptionThrown
10314
10315 /*
10316  * We encountered a null object when we weren't expecting one.  We
10317  * export the PC, throw a NullPointerException, and goto the exception
10318  * processing code.
10319  */
10320 common_errNullObject:
10321     EXPORT_PC()
10322     ldr     r0, strNullPointerException
10323     mov     r1, #0
10324     bl      dvmThrowException
10325     b       common_exceptionThrown
10326
10327 /*
10328  * For debugging, cause an immediate fault.  The source address will
10329  * be in lr (use a bl instruction to jump here).
10330  */
10331 common_abort:
10332     ldr     pc, .LdeadFood
10333 .LdeadFood:
10334     .word   0xdeadf00d
10335
10336 /*
10337  * Spit out a "we were here", preserving all registers.  (The attempt
10338  * to save ip won't work, but we need to save an even number of
10339  * registers for EABI 64-bit stack alignment.)
10340  */
10341     .macro  SQUEAK num
10342 common_squeak\num:
10343     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10344     ldr     r0, strSqueak
10345     mov     r1, #\num
10346     bl      printf
10347     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10348     bx      lr
10349     .endm
10350
10351     SQUEAK  0
10352     SQUEAK  1
10353     SQUEAK  2
10354     SQUEAK  3
10355     SQUEAK  4
10356     SQUEAK  5
10357
10358 /*
10359  * Spit out the number in r0, preserving registers.
10360  */
10361 common_printNum:
10362     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10363     mov     r1, r0
10364     ldr     r0, strSqueak
10365     bl      printf
10366     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10367     bx      lr
10368
10369 /*
10370  * Print a newline, preserving registers.
10371  */
10372 common_printNewline:
10373     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10374     ldr     r0, strNewline
10375     bl      printf
10376     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10377     bx      lr
10378
10379     /*
10380      * Print the 32-bit quantity in r0 as a hex value, preserving registers.
10381      */
10382 common_printHex:
10383     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10384     mov     r1, r0
10385     ldr     r0, strPrintHex
10386     bl      printf
10387     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10388     bx      lr
10389
10390 /*
10391  * Print the 64-bit quantity in r0-r1, preserving registers.
10392  */
10393 common_printLong:
10394     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10395     mov     r3, r1
10396     mov     r2, r0
10397     ldr     r0, strPrintLong
10398     bl      printf
10399     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10400     bx      lr
10401
10402 /*
10403  * Print full method info.  Pass the Method* in r0.  Preserves regs.
10404  */
10405 common_printMethod:
10406     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10407     bl      dvmMterpPrintMethod
10408     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10409     bx      lr
10410
10411 /*
10412  * Call a C helper function that dumps regs and possibly some
10413  * additional info.  Requires the C function to be compiled in.
10414  */
10415     .if     0
10416 common_dumpRegs:
10417     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10418     bl      dvmMterpDumpArmRegs
10419     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10420     bx      lr
10421     .endif
10422
10423 #if 0
10424 /*
10425  * Experiment on VFP mode.
10426  *
10427  * uint32_t setFPSCR(uint32_t val, uint32_t mask)
10428  *
10429  * Updates the bits specified by "mask", setting them to the values in "val".
10430  */
10431 setFPSCR:
10432     and     r0, r0, r1                  @ make sure no stray bits are set
10433     fmrx    r2, fpscr                   @ get VFP reg
10434     mvn     r1, r1                      @ bit-invert mask
10435     and     r2, r2, r1                  @ clear masked bits
10436     orr     r2, r2, r0                  @ set specified bits
10437     fmxr    fpscr, r2                   @ set VFP reg
10438     mov     r0, r2                      @ return new value
10439     bx      lr
10440
10441     .align  2
10442     .global dvmConfigureFP
10443     .type   dvmConfigureFP, %function
10444 dvmConfigureFP:
10445     stmfd   sp!, {ip, lr}
10446     /* 0x03000000 sets DN/FZ */
10447     /* 0x00009f00 clears the six exception enable flags */
10448     bl      common_squeak0
10449     mov     r0, #0x03000000             @ r0<- 0x03000000
10450     add     r1, r0, #0x9f00             @ r1<- 0x03009f00
10451     bl      setFPSCR
10452     ldmfd   sp!, {ip, pc}
10453 #endif
10454
10455
10456 /*
10457  * String references, must be close to the code that uses them.
10458  */
10459     .align  2
10460 strArithmeticException:
10461     .word   .LstrArithmeticException
10462 strArrayIndexException:
10463     .word   .LstrArrayIndexException
10464 strArrayStoreException:
10465     .word   .LstrArrayStoreException
10466 strDivideByZero:
10467     .word   .LstrDivideByZero
10468 strNegativeArraySizeException:
10469     .word   .LstrNegativeArraySizeException
10470 strNoSuchMethodError:
10471     .word   .LstrNoSuchMethodError
10472 strNullPointerException:
10473     .word   .LstrNullPointerException
10474
10475 strLogTag:
10476     .word   .LstrLogTag
10477 strExceptionNotCaughtLocally:
10478     .word   .LstrExceptionNotCaughtLocally
10479
10480 strNewline:
10481     .word   .LstrNewline
10482 strSqueak:
10483     .word   .LstrSqueak
10484 strPrintHex:
10485     .word   .LstrPrintHex
10486 strPrintLong:
10487     .word   .LstrPrintLong
10488
10489 /*
10490  * Zero-terminated ASCII string data.
10491  *
10492  * On ARM we have two choices: do like gcc does, and LDR from a .word
10493  * with the address, or use an ADR pseudo-op to get the address
10494  * directly.  ADR saves 4 bytes and an indirection, but it's using a
10495  * PC-relative addressing mode and hence has a limited range, which
10496  * makes it not work well with mergeable string sections.
10497  */
10498     .section .rodata.str1.4,"aMS",%progbits,1
10499
10500 .LstrBadEntryPoint:
10501     .asciz  "Bad entry point %d\n"
10502 .LstrArithmeticException:
10503     .asciz  "Ljava/lang/ArithmeticException;"
10504 .LstrArrayIndexException:
10505     .asciz  "Ljava/lang/ArrayIndexOutOfBoundsException;"
10506 .LstrArrayStoreException:
10507     .asciz  "Ljava/lang/ArrayStoreException;"
10508 .LstrClassCastException:
10509     .asciz  "Ljava/lang/ClassCastException;"
10510 .LstrDivideByZero:
10511     .asciz  "divide by zero"
10512 .LstrFilledNewArrayNotImpl:
10513     .asciz  "filled-new-array only implemented for objects and 'int'"
10514 .LstrInternalError:
10515     .asciz  "Ljava/lang/InternalError;"
10516 .LstrInstantiationError:
10517     .asciz  "Ljava/lang/InstantiationError;"
10518 .LstrNegativeArraySizeException:
10519     .asciz  "Ljava/lang/NegativeArraySizeException;"
10520 .LstrNoSuchMethodError:
10521     .asciz  "Ljava/lang/NoSuchMethodError;"
10522 .LstrNullPointerException:
10523     .asciz  "Ljava/lang/NullPointerException;"
10524
10525 .LstrLogTag:
10526     .asciz  "mterp"
10527 .LstrExceptionNotCaughtLocally:
10528     .asciz  "Exception %s from %s:%d not caught locally\n"
10529
10530 .LstrNewline:
10531     .asciz  "\n"
10532 .LstrSqueak:
10533     .asciz  "<%d>"
10534 .LstrPrintHex:
10535     .asciz  "<0x%x>"
10536 .LstrPrintLong:
10537     .asciz  "<%lld>"
10538
10539