OSDN Git Service

Merge "Detect system-wide safe mode and configure the VM accordingly."
[android-x86/dalvik.git] / vm / mterp / out / InterpAsm-armv4t.S
1 /*
2  * This file was generated automatically by gen-mterp.py for 'armv4t'.
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_PROF_TABLE(_reg)    ldr     _reg,[rGLUE,#offGlue_pJitProfTable]
189 #define GET_JIT_THRESHOLD(_reg)     ldr     _reg,[rGLUE,#offGlue_jitThreshold]
190 #endif
191
192 /*
193  * Convert a virtual register index into an address.
194  */
195 #define VREG_INDEX_TO_ADDR(_reg, _vreg) \
196         add     _reg, rFP, _vreg, lsl #2
197
198 /*
199  * This is a #include, not a %include, because we want the C pre-processor
200  * to expand the macros into assembler assignment statements.
201  */
202 #include "../common/asm-constants.h"
203
204 #if defined(WITH_JIT)
205 #include "../common/jit-config.h"
206 #endif
207
208 /* File: armv5te/platform.S */
209 /*
210  * ===========================================================================
211  *  CPU-version-specific defines
212  * ===========================================================================
213  */
214
215 /*
216  * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5.  Essentially a
217  * one-way branch.
218  *
219  * May modify IP.  Does not modify LR.
220  */
221 .macro  LDR_PC source
222     ldr     pc, \source
223 .endm
224
225 /*
226  * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5.
227  * Jump to subroutine.
228  *
229  * May modify IP and LR.
230  */
231 .macro  LDR_PC_LR source
232     mov     lr, pc
233     ldr     pc, \source
234 .endm
235
236 /*
237  * Macro for "LDMFD SP!, {...regs...,PC}".
238  *
239  * May modify IP and LR.
240  */
241 .macro  LDMFD_PC regs
242     ldmfd   sp!, {\regs,pc}
243 .endm
244
245
246 /* File: armv5te/entry.S */
247 /*
248  * Copyright (C) 2008 The Android Open Source Project
249  *
250  * Licensed under the Apache License, Version 2.0 (the "License");
251  * you may not use this file except in compliance with the License.
252  * You may obtain a copy of the License at
253  *
254  *      http://www.apache.org/licenses/LICENSE-2.0
255  *
256  * Unless required by applicable law or agreed to in writing, software
257  * distributed under the License is distributed on an "AS IS" BASIS,
258  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
259  * See the License for the specific language governing permissions and
260  * limitations under the License.
261  */
262 /*
263  * Interpreter entry point.
264  */
265
266 /*
267  * We don't have formal stack frames, so gdb scans upward in the code
268  * to find the start of the function (a label with the %function type),
269  * and then looks at the next few instructions to figure out what
270  * got pushed onto the stack.  From this it figures out how to restore
271  * the registers, including PC, for the previous stack frame.  If gdb
272  * sees a non-function label, it stops scanning, so either we need to
273  * have nothing but assembler-local labels between the entry point and
274  * the break, or we need to fake it out.
275  *
276  * When this is defined, we add some stuff to make gdb less confused.
277  */
278 #define ASSIST_DEBUGGER 1
279
280     .text
281     .align  2
282     .global dvmMterpStdRun
283     .type   dvmMterpStdRun, %function
284
285 /*
286  * On entry:
287  *  r0  MterpGlue* glue
288  *
289  * This function returns a boolean "changeInterp" value.  The return comes
290  * via a call to dvmMterpStdBail().
291  */
292 dvmMterpStdRun:
293 #define MTERP_ENTRY1 \
294     .save {r4-r10,fp,lr}; \
295     stmfd   sp!, {r4-r10,fp,lr}         @ save 9 regs
296 #define MTERP_ENTRY2 \
297     .pad    #4; \
298     sub     sp, sp, #4                  @ align 64
299
300     .fnstart
301     MTERP_ENTRY1
302     MTERP_ENTRY2
303
304     /* save stack pointer, add magic word for debuggerd */
305     str     sp, [r0, #offGlue_bailPtr]  @ save SP for eventual return
306
307     /* set up "named" registers, figure out entry point */
308     mov     rGLUE, r0                   @ set rGLUE
309     ldrb    r1, [r0, #offGlue_entryPoint]   @ InterpEntry enum is char
310     LOAD_PC_FP_FROM_GLUE()              @ load rPC and rFP from "glue"
311     adr     rIBASE, dvmAsmInstructionStart  @ set rIBASE
312     cmp     r1, #kInterpEntryInstr      @ usual case?
313     bne     .Lnot_instr                 @ no, handle it
314
315 #if defined(WITH_JIT)
316 .Lno_singleStep:
317     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
318     /* Entry is always a possible trace start */
319     GET_JIT_PROF_TABLE(r0)
320     FETCH_INST()
321     mov    r1, #0                       @ prepare the value for the new state
322     str    r1, [r10, #offThread_inJitCodeCache] @ back to the interp land
323     cmp    r0,#0
324     bne    common_updateProfile
325     GET_INST_OPCODE(ip)
326     GOTO_OPCODE(ip)
327 #else
328     /* start executing the instruction at rPC */
329     FETCH_INST()                        @ load rINST from rPC
330     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
331     GOTO_OPCODE(ip)                     @ jump to next instruction
332 #endif
333
334 .Lnot_instr:
335     cmp     r1, #kInterpEntryReturn     @ were we returning from a method?
336     beq     common_returnFromMethod
337
338 .Lnot_return:
339     cmp     r1, #kInterpEntryThrow      @ were we throwing an exception?
340     beq     common_exceptionThrown
341
342 #if defined(WITH_JIT)
343 .Lnot_throw:
344     ldr     r0,[rGLUE, #offGlue_jitResume]
345     ldr     r2,[rGLUE, #offGlue_jitResumePC]
346     cmp     r1, #kInterpEntryResume     @ resuming after Jit single-step?
347     bne     .Lbad_arg
348     cmp     rPC,r2
349     bne     .Lno_singleStep             @ must have branched, don't resume
350     mov     r1, #kInterpEntryInstr
351     strb    r1, [rGLUE, #offGlue_entryPoint]
352     ldr     rINST, .LdvmCompilerTemplate
353     bx      r0                          @ re-enter the translation
354 .LdvmCompilerTemplate:
355     .word   dvmCompilerTemplateStart
356 #endif
357
358 .Lbad_arg:
359     ldr     r0, strBadEntryPoint
360     @ r1 holds value of entryPoint
361     bl      printf
362     bl      dvmAbort
363     .fnend
364
365
366     .global dvmMterpStdBail
367     .type   dvmMterpStdBail, %function
368
369 /*
370  * Restore the stack pointer and PC from the save point established on entry.
371  * This is essentially the same as a longjmp, but should be cheaper.  The
372  * last instruction causes us to return to whoever called dvmMterpStdRun.
373  *
374  * We pushed some registers on the stack in dvmMterpStdRun, then saved
375  * SP and LR.  Here we restore SP, restore the registers, and then restore
376  * LR to PC.
377  *
378  * On entry:
379  *  r0  MterpGlue* glue
380  *  r1  bool changeInterp
381  */
382 dvmMterpStdBail:
383     ldr     sp, [r0, #offGlue_bailPtr]      @ sp<- saved SP
384     mov     r0, r1                          @ return the changeInterp value
385     add     sp, sp, #4                      @ un-align 64
386     LDMFD_PC "r4-r10,fp"                    @ restore 9 regs and return
387
388
389 /*
390  * String references.
391  */
392 strBadEntryPoint:
393     .word   .LstrBadEntryPoint
394
395
396
397     .global dvmAsmInstructionStart
398     .type   dvmAsmInstructionStart, %function
399 dvmAsmInstructionStart = .L_OP_NOP
400     .text
401
402 /* ------------------------------ */
403     .balign 64
404 .L_OP_NOP: /* 0x00 */
405 /* File: armv5te/OP_NOP.S */
406     FETCH_ADVANCE_INST(1)               @ advance to next instr, load rINST
407     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
408     GOTO_OPCODE(ip)                     @ execute it
409
410 #ifdef ASSIST_DEBUGGER
411     /* insert fake function header to help gdb find the stack frame */
412     .type   dalvik_inst, %function
413 dalvik_inst:
414     .fnstart
415     MTERP_ENTRY1
416     MTERP_ENTRY2
417     .fnend
418 #endif
419
420
421 /* ------------------------------ */
422     .balign 64
423 .L_OP_MOVE: /* 0x01 */
424 /* File: armv5te/OP_MOVE.S */
425     /* for move, move-object, long-to-int */
426     /* op vA, vB */
427     mov     r1, rINST, lsr #12          @ r1<- B from 15:12
428     mov     r0, rINST, lsr #8           @ r0<- A from 11:8
429     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
430     GET_VREG(r2, r1)                    @ r2<- fp[B]
431     and     r0, r0, #15
432     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
433     SET_VREG(r2, r0)                    @ fp[A]<- r2
434     GOTO_OPCODE(ip)                     @ execute next instruction
435
436
437 /* ------------------------------ */
438     .balign 64
439 .L_OP_MOVE_FROM16: /* 0x02 */
440 /* File: armv5te/OP_MOVE_FROM16.S */
441     /* for: move/from16, move-object/from16 */
442     /* op vAA, vBBBB */
443     FETCH(r1, 1)                        @ r1<- BBBB
444     mov     r0, rINST, lsr #8           @ r0<- AA
445     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
446     GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
447     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
448     SET_VREG(r2, r0)                    @ fp[AA]<- r2
449     GOTO_OPCODE(ip)                     @ jump to next instruction
450
451
452 /* ------------------------------ */
453     .balign 64
454 .L_OP_MOVE_16: /* 0x03 */
455 /* File: armv5te/OP_MOVE_16.S */
456     /* for: move/16, move-object/16 */
457     /* op vAAAA, vBBBB */
458     FETCH(r1, 2)                        @ r1<- BBBB
459     FETCH(r0, 1)                        @ r0<- AAAA
460     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
461     GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
462     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
463     SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
464     GOTO_OPCODE(ip)                     @ jump to next instruction
465
466
467 /* ------------------------------ */
468     .balign 64
469 .L_OP_MOVE_WIDE: /* 0x04 */
470 /* File: armv5te/OP_MOVE_WIDE.S */
471     /* move-wide vA, vB */
472     /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
473     mov     r2, rINST, lsr #8           @ r2<- A(+)
474     mov     r3, rINST, lsr #12          @ r3<- B
475     and     r2, r2, #15
476     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
477     add     r2, rFP, r2, lsl #2         @ r2<- &fp[A]
478     ldmia   r3, {r0-r1}                 @ r0/r1<- fp[B]
479     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
480     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
481     stmia   r2, {r0-r1}                 @ fp[A]<- r0/r1
482     GOTO_OPCODE(ip)                     @ jump to next instruction
483
484
485 /* ------------------------------ */
486     .balign 64
487 .L_OP_MOVE_WIDE_FROM16: /* 0x05 */
488 /* File: armv5te/OP_MOVE_WIDE_FROM16.S */
489     /* move-wide/from16 vAA, vBBBB */
490     /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
491     FETCH(r3, 1)                        @ r3<- BBBB
492     mov     r2, rINST, lsr #8           @ r2<- AA
493     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
494     add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
495     ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
496     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
497     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
498     stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
499     GOTO_OPCODE(ip)                     @ jump to next instruction
500
501
502 /* ------------------------------ */
503     .balign 64
504 .L_OP_MOVE_WIDE_16: /* 0x06 */
505 /* File: armv5te/OP_MOVE_WIDE_16.S */
506     /* move-wide/16 vAAAA, vBBBB */
507     /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
508     FETCH(r3, 2)                        @ r3<- BBBB
509     FETCH(r2, 1)                        @ r2<- AAAA
510     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
511     add     r2, rFP, r2, lsl #2         @ r2<- &fp[AAAA]
512     ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
513     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
514     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
515     stmia   r2, {r0-r1}                 @ fp[AAAA]<- r0/r1
516     GOTO_OPCODE(ip)                     @ jump to next instruction
517
518
519 /* ------------------------------ */
520     .balign 64
521 .L_OP_MOVE_OBJECT: /* 0x07 */
522 /* File: armv5te/OP_MOVE_OBJECT.S */
523 /* File: armv5te/OP_MOVE.S */
524     /* for move, move-object, long-to-int */
525     /* op vA, vB */
526     mov     r1, rINST, lsr #12          @ r1<- B from 15:12
527     mov     r0, rINST, lsr #8           @ r0<- A from 11:8
528     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
529     GET_VREG(r2, r1)                    @ r2<- fp[B]
530     and     r0, r0, #15
531     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
532     SET_VREG(r2, r0)                    @ fp[A]<- r2
533     GOTO_OPCODE(ip)                     @ execute next instruction
534
535
536
537 /* ------------------------------ */
538     .balign 64
539 .L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
540 /* File: armv5te/OP_MOVE_OBJECT_FROM16.S */
541 /* File: armv5te/OP_MOVE_FROM16.S */
542     /* for: move/from16, move-object/from16 */
543     /* op vAA, vBBBB */
544     FETCH(r1, 1)                        @ r1<- BBBB
545     mov     r0, rINST, lsr #8           @ r0<- AA
546     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
547     GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
548     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
549     SET_VREG(r2, r0)                    @ fp[AA]<- r2
550     GOTO_OPCODE(ip)                     @ jump to next instruction
551
552
553
554 /* ------------------------------ */
555     .balign 64
556 .L_OP_MOVE_OBJECT_16: /* 0x09 */
557 /* File: armv5te/OP_MOVE_OBJECT_16.S */
558 /* File: armv5te/OP_MOVE_16.S */
559     /* for: move/16, move-object/16 */
560     /* op vAAAA, vBBBB */
561     FETCH(r1, 2)                        @ r1<- BBBB
562     FETCH(r0, 1)                        @ r0<- AAAA
563     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
564     GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
565     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
566     SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
567     GOTO_OPCODE(ip)                     @ jump to next instruction
568
569
570
571 /* ------------------------------ */
572     .balign 64
573 .L_OP_MOVE_RESULT: /* 0x0a */
574 /* File: armv5te/OP_MOVE_RESULT.S */
575     /* for: move-result, move-result-object */
576     /* op vAA */
577     mov     r2, rINST, lsr #8           @ r2<- AA
578     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
579     ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
580     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
581     SET_VREG(r0, r2)                    @ fp[AA]<- r0
582     GOTO_OPCODE(ip)                     @ jump to next instruction
583
584
585 /* ------------------------------ */
586     .balign 64
587 .L_OP_MOVE_RESULT_WIDE: /* 0x0b */
588 /* File: armv5te/OP_MOVE_RESULT_WIDE.S */
589     /* move-result-wide vAA */
590     mov     r2, rINST, lsr #8           @ r2<- AA
591     add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
592     add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
593     ldmia   r3, {r0-r1}                 @ r0/r1<- retval.j
594     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
595     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
596     stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
597     GOTO_OPCODE(ip)                     @ jump to next instruction
598
599
600 /* ------------------------------ */
601     .balign 64
602 .L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
603 /* File: armv5te/OP_MOVE_RESULT_OBJECT.S */
604 /* File: armv5te/OP_MOVE_RESULT.S */
605     /* for: move-result, move-result-object */
606     /* op vAA */
607     mov     r2, rINST, lsr #8           @ r2<- AA
608     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
609     ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
610     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
611     SET_VREG(r0, r2)                    @ fp[AA]<- r0
612     GOTO_OPCODE(ip)                     @ jump to next instruction
613
614
615
616 /* ------------------------------ */
617     .balign 64
618 .L_OP_MOVE_EXCEPTION: /* 0x0d */
619 /* File: armv5te/OP_MOVE_EXCEPTION.S */
620     /* move-exception vAA */
621     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
622     mov     r2, rINST, lsr #8           @ r2<- AA
623     ldr     r3, [r0, #offThread_exception]  @ r3<- dvmGetException bypass
624     mov     r1, #0                      @ r1<- 0
625     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
626     SET_VREG(r3, r2)                    @ fp[AA]<- exception obj
627     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
628     str     r1, [r0, #offThread_exception]  @ dvmClearException bypass
629     GOTO_OPCODE(ip)                     @ jump to next instruction
630
631
632 /* ------------------------------ */
633     .balign 64
634 .L_OP_RETURN_VOID: /* 0x0e */
635 /* File: armv5te/OP_RETURN_VOID.S */
636     b       common_returnFromMethod
637
638
639 /* ------------------------------ */
640     .balign 64
641 .L_OP_RETURN: /* 0x0f */
642 /* File: armv5te/OP_RETURN.S */
643     /*
644      * Return a 32-bit value.  Copies the return value into the "glue"
645      * structure, then jumps to the return handler.
646      *
647      * for: return, return-object
648      */
649     /* op vAA */
650     mov     r2, rINST, lsr #8           @ r2<- AA
651     GET_VREG(r0, r2)                    @ r0<- vAA
652     str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
653     b       common_returnFromMethod
654
655
656 /* ------------------------------ */
657     .balign 64
658 .L_OP_RETURN_WIDE: /* 0x10 */
659 /* File: armv5te/OP_RETURN_WIDE.S */
660     /*
661      * Return a 64-bit value.  Copies the return value into the "glue"
662      * structure, then jumps to the return handler.
663      */
664     /* return-wide vAA */
665     mov     r2, rINST, lsr #8           @ r2<- AA
666     add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
667     add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
668     ldmia   r2, {r0-r1}                 @ r0/r1 <- vAA/vAA+1
669     stmia   r3, {r0-r1}                 @ retval<- r0/r1
670     b       common_returnFromMethod
671
672
673 /* ------------------------------ */
674     .balign 64
675 .L_OP_RETURN_OBJECT: /* 0x11 */
676 /* File: armv5te/OP_RETURN_OBJECT.S */
677 /* File: armv5te/OP_RETURN.S */
678     /*
679      * Return a 32-bit value.  Copies the return value into the "glue"
680      * structure, then jumps to the return handler.
681      *
682      * for: return, return-object
683      */
684     /* op vAA */
685     mov     r2, rINST, lsr #8           @ r2<- AA
686     GET_VREG(r0, r2)                    @ r0<- vAA
687     str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
688     b       common_returnFromMethod
689
690
691
692 /* ------------------------------ */
693     .balign 64
694 .L_OP_CONST_4: /* 0x12 */
695 /* File: armv5te/OP_CONST_4.S */
696     /* const/4 vA, #+B */
697     mov     r1, rINST, lsl #16          @ r1<- Bxxx0000
698     mov     r0, rINST, lsr #8           @ r0<- A+
699     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
700     mov     r1, r1, asr #28             @ r1<- sssssssB (sign-extended)
701     and     r0, r0, #15
702     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
703     SET_VREG(r1, r0)                    @ fp[A]<- r1
704     GOTO_OPCODE(ip)                     @ execute next instruction
705
706
707 /* ------------------------------ */
708     .balign 64
709 .L_OP_CONST_16: /* 0x13 */
710 /* File: armv5te/OP_CONST_16.S */
711     /* const/16 vAA, #+BBBB */
712     FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
713     mov     r3, rINST, lsr #8           @ r3<- AA
714     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
715     SET_VREG(r0, r3)                    @ vAA<- r0
716     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
717     GOTO_OPCODE(ip)                     @ jump to next instruction
718
719
720 /* ------------------------------ */
721     .balign 64
722 .L_OP_CONST: /* 0x14 */
723 /* File: armv5te/OP_CONST.S */
724     /* const vAA, #+BBBBbbbb */
725     mov     r3, rINST, lsr #8           @ r3<- AA
726     FETCH(r0, 1)                        @ r0<- bbbb (low)
727     FETCH(r1, 2)                        @ r1<- BBBB (high)
728     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
729     orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
730     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
731     SET_VREG(r0, r3)                    @ vAA<- r0
732     GOTO_OPCODE(ip)                     @ jump to next instruction
733
734
735 /* ------------------------------ */
736     .balign 64
737 .L_OP_CONST_HIGH16: /* 0x15 */
738 /* File: armv5te/OP_CONST_HIGH16.S */
739     /* const/high16 vAA, #+BBBB0000 */
740     FETCH(r0, 1)                        @ r0<- 0000BBBB (zero-extended)
741     mov     r3, rINST, lsr #8           @ r3<- AA
742     mov     r0, r0, lsl #16             @ r0<- BBBB0000
743     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
744     SET_VREG(r0, r3)                    @ vAA<- r0
745     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
746     GOTO_OPCODE(ip)                     @ jump to next instruction
747
748
749 /* ------------------------------ */
750     .balign 64
751 .L_OP_CONST_WIDE_16: /* 0x16 */
752 /* File: armv5te/OP_CONST_WIDE_16.S */
753     /* const-wide/16 vAA, #+BBBB */
754     FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
755     mov     r3, rINST, lsr #8           @ r3<- AA
756     mov     r1, r0, asr #31             @ r1<- ssssssss
757     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
758     add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
759     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
760     stmia   r3, {r0-r1}                 @ vAA<- r0/r1
761     GOTO_OPCODE(ip)                     @ jump to next instruction
762
763
764 /* ------------------------------ */
765     .balign 64
766 .L_OP_CONST_WIDE_32: /* 0x17 */
767 /* File: armv5te/OP_CONST_WIDE_32.S */
768     /* const-wide/32 vAA, #+BBBBbbbb */
769     FETCH(r0, 1)                        @ r0<- 0000bbbb (low)
770     mov     r3, rINST, lsr #8           @ r3<- AA
771     FETCH_S(r2, 2)                      @ r2<- ssssBBBB (high)
772     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
773     orr     r0, r0, r2, lsl #16         @ r0<- BBBBbbbb
774     add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
775     mov     r1, r0, asr #31             @ r1<- ssssssss
776     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
777     stmia   r3, {r0-r1}                 @ vAA<- r0/r1
778     GOTO_OPCODE(ip)                     @ jump to next instruction
779
780
781 /* ------------------------------ */
782     .balign 64
783 .L_OP_CONST_WIDE: /* 0x18 */
784 /* File: armv5te/OP_CONST_WIDE.S */
785     /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
786     FETCH(r0, 1)                        @ r0<- bbbb (low)
787     FETCH(r1, 2)                        @ r1<- BBBB (low middle)
788     FETCH(r2, 3)                        @ r2<- hhhh (high middle)
789     orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb (low word)
790     FETCH(r3, 4)                        @ r3<- HHHH (high)
791     mov     r9, rINST, lsr #8           @ r9<- AA
792     orr     r1, r2, r3, lsl #16         @ r1<- HHHHhhhh (high word)
793     FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
794     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
795     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
796     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
797     GOTO_OPCODE(ip)                     @ jump to next instruction
798
799
800 /* ------------------------------ */
801     .balign 64
802 .L_OP_CONST_WIDE_HIGH16: /* 0x19 */
803 /* File: armv5te/OP_CONST_WIDE_HIGH16.S */
804     /* const-wide/high16 vAA, #+BBBB000000000000 */
805     FETCH(r1, 1)                        @ r1<- 0000BBBB (zero-extended)
806     mov     r3, rINST, lsr #8           @ r3<- AA
807     mov     r0, #0                      @ r0<- 00000000
808     mov     r1, r1, lsl #16             @ r1<- BBBB0000
809     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
810     add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
811     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
812     stmia   r3, {r0-r1}                 @ vAA<- r0/r1
813     GOTO_OPCODE(ip)                     @ jump to next instruction
814
815
816 /* ------------------------------ */
817     .balign 64
818 .L_OP_CONST_STRING: /* 0x1a */
819 /* File: armv5te/OP_CONST_STRING.S */
820     /* const/string vAA, String@BBBB */
821     FETCH(r1, 1)                        @ r1<- BBBB
822     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
823     mov     r9, rINST, lsr #8           @ r9<- AA
824     ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
825     ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
826     cmp     r0, #0                      @ not yet resolved?
827     beq     .LOP_CONST_STRING_resolve
828     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
829     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
830     SET_VREG(r0, r9)                    @ vAA<- r0
831     GOTO_OPCODE(ip)                     @ jump to next instruction
832
833 /* ------------------------------ */
834     .balign 64
835 .L_OP_CONST_STRING_JUMBO: /* 0x1b */
836 /* File: armv5te/OP_CONST_STRING_JUMBO.S */
837     /* const/string vAA, String@BBBBBBBB */
838     FETCH(r0, 1)                        @ r0<- bbbb (low)
839     FETCH(r1, 2)                        @ r1<- BBBB (high)
840     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
841     mov     r9, rINST, lsr #8           @ r9<- AA
842     ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
843     orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
844     ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
845     cmp     r0, #0
846     beq     .LOP_CONST_STRING_JUMBO_resolve
847     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
848     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
849     SET_VREG(r0, r9)                    @ vAA<- r0
850     GOTO_OPCODE(ip)                     @ jump to next instruction
851
852 /* ------------------------------ */
853     .balign 64
854 .L_OP_CONST_CLASS: /* 0x1c */
855 /* File: armv5te/OP_CONST_CLASS.S */
856     /* const/class vAA, Class@BBBB */
857     FETCH(r1, 1)                        @ r1<- BBBB
858     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
859     mov     r9, rINST, lsr #8           @ r9<- AA
860     ldr     r2, [r2, #offDvmDex_pResClasses]   @ r2<- dvmDex->pResClasses
861     ldr     r0, [r2, r1, lsl #2]        @ r0<- pResClasses[BBBB]
862     cmp     r0, #0                      @ not yet resolved?
863     beq     .LOP_CONST_CLASS_resolve
864     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
865     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
866     SET_VREG(r0, r9)                    @ vAA<- r0
867     GOTO_OPCODE(ip)                     @ jump to next instruction
868
869 /* ------------------------------ */
870     .balign 64
871 .L_OP_MONITOR_ENTER: /* 0x1d */
872 /* File: armv5te/OP_MONITOR_ENTER.S */
873     /*
874      * Synchronize on an object.
875      */
876     /* monitor-enter vAA */
877     mov     r2, rINST, lsr #8           @ r2<- AA
878     GET_VREG(r1, r2)                    @ r1<- vAA (object)
879     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
880     cmp     r1, #0                      @ null object?
881     EXPORT_PC()                         @ need for precise GC, MONITOR_TRACKING
882     beq     common_errNullObject        @ null object, throw an exception
883     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
884     bl      dvmLockObject               @ call(self, obj)
885 #ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */
886     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
887     ldr     r1, [r0, #offThread_exception] @ check for exception
888     cmp     r1, #0
889     bne     common_exceptionThrown      @ exception raised, bail out
890 #endif
891     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
892     GOTO_OPCODE(ip)                     @ jump to next instruction
893
894
895 /* ------------------------------ */
896     .balign 64
897 .L_OP_MONITOR_EXIT: /* 0x1e */
898 /* File: armv5te/OP_MONITOR_EXIT.S */
899     /*
900      * Unlock an object.
901      *
902      * Exceptions that occur when unlocking a monitor need to appear as
903      * if they happened at the following instruction.  See the Dalvik
904      * instruction spec.
905      */
906     /* monitor-exit vAA */
907     mov     r2, rINST, lsr #8           @ r2<- AA
908     EXPORT_PC()                         @ before fetch: export the PC
909     GET_VREG(r1, r2)                    @ r1<- vAA (object)
910     cmp     r1, #0                      @ null object?
911     beq     1f                          @ yes
912     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
913     bl      dvmUnlockObject             @ r0<- success for unlock(self, obj)
914     cmp     r0, #0                      @ failed?
915     FETCH_ADVANCE_INST(1)               @ before throw: advance rPC, load rINST
916     beq     common_exceptionThrown      @ yes, exception is pending
917     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
918     GOTO_OPCODE(ip)                     @ jump to next instruction
919 1:
920     FETCH_ADVANCE_INST(1)               @ advance before throw
921     b      common_errNullObject
922
923
924 /* ------------------------------ */
925     .balign 64
926 .L_OP_CHECK_CAST: /* 0x1f */
927 /* File: armv5te/OP_CHECK_CAST.S */
928     /*
929      * Check to see if a cast from one class to another is allowed.
930      */
931     /* check-cast vAA, class@BBBB */
932     mov     r3, rINST, lsr #8           @ r3<- AA
933     FETCH(r2, 1)                        @ r2<- BBBB
934     GET_VREG(r9, r3)                    @ r9<- object
935     ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- pDvmDex
936     cmp     r9, #0                      @ is object null?
937     ldr     r0, [r0, #offDvmDex_pResClasses]    @ r0<- pDvmDex->pResClasses
938     beq     .LOP_CHECK_CAST_okay            @ null obj, cast always succeeds
939     ldr     r1, [r0, r2, lsl #2]        @ r1<- resolved class
940     ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
941     cmp     r1, #0                      @ have we resolved this before?
942     beq     .LOP_CHECK_CAST_resolve         @ not resolved, do it now
943 .LOP_CHECK_CAST_resolved:
944     cmp     r0, r1                      @ same class (trivial success)?
945     bne     .LOP_CHECK_CAST_fullcheck       @ no, do full check
946 .LOP_CHECK_CAST_okay:
947     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
948     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
949     GOTO_OPCODE(ip)                     @ jump to next instruction
950
951 /* ------------------------------ */
952     .balign 64
953 .L_OP_INSTANCE_OF: /* 0x20 */
954 /* File: armv5te/OP_INSTANCE_OF.S */
955     /*
956      * Check to see if an object reference is an instance of a class.
957      *
958      * Most common situation is a non-null object, being compared against
959      * an already-resolved class.
960      */
961     /* instance-of vA, vB, class@CCCC */
962     mov     r3, rINST, lsr #12          @ r3<- B
963     mov     r9, rINST, lsr #8           @ r9<- A+
964     GET_VREG(r0, r3)                    @ r0<- vB (object)
965     and     r9, r9, #15                 @ r9<- A
966     cmp     r0, #0                      @ is object null?
967     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- pDvmDex
968     beq     .LOP_INSTANCE_OF_store           @ null obj, not an instance, store r0
969     FETCH(r3, 1)                        @ r3<- CCCC
970     ldr     r2, [r2, #offDvmDex_pResClasses]    @ r2<- pDvmDex->pResClasses
971     ldr     r1, [r2, r3, lsl #2]        @ r1<- resolved class
972     ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
973     cmp     r1, #0                      @ have we resolved this before?
974     beq     .LOP_INSTANCE_OF_resolve         @ not resolved, do it now
975 .LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class
976     cmp     r0, r1                      @ same class (trivial success)?
977     beq     .LOP_INSTANCE_OF_trivial         @ yes, trivial finish
978     b       .LOP_INSTANCE_OF_fullcheck       @ no, do full check
979
980 /* ------------------------------ */
981     .balign 64
982 .L_OP_ARRAY_LENGTH: /* 0x21 */
983 /* File: armv5te/OP_ARRAY_LENGTH.S */
984     /*
985      * Return the length of an array.
986      */
987     mov     r1, rINST, lsr #12          @ r1<- B
988     mov     r2, rINST, lsr #8           @ r2<- A+
989     GET_VREG(r0, r1)                    @ r0<- vB (object ref)
990     and     r2, r2, #15                 @ r2<- A
991     cmp     r0, #0                      @ is object null?
992     beq     common_errNullObject        @ yup, fail
993     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
994     ldr     r3, [r0, #offArrayObject_length]    @ r3<- array length
995     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
996     SET_VREG(r3, r2)                    @ vB<- length
997     GOTO_OPCODE(ip)                     @ jump to next instruction
998
999
1000 /* ------------------------------ */
1001     .balign 64
1002 .L_OP_NEW_INSTANCE: /* 0x22 */
1003 /* File: armv5te/OP_NEW_INSTANCE.S */
1004     /*
1005      * Create a new instance of a class.
1006      */
1007     /* new-instance vAA, class@BBBB */
1008     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1009     FETCH(r1, 1)                        @ r1<- BBBB
1010     ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1011     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1012     EXPORT_PC()                         @ req'd for init, resolve, alloc
1013     cmp     r0, #0                      @ already resolved?
1014     beq     .LOP_NEW_INSTANCE_resolve         @ no, resolve it now
1015 .LOP_NEW_INSTANCE_resolved:   @ r0=class
1016     ldrb    r1, [r0, #offClassObject_status]    @ r1<- ClassStatus enum
1017     cmp     r1, #CLASS_INITIALIZED      @ has class been initialized?
1018     bne     .LOP_NEW_INSTANCE_needinit        @ no, init class now
1019 .LOP_NEW_INSTANCE_initialized: @ r0=class
1020     mov     r1, #ALLOC_DONT_TRACK       @ flags for alloc call
1021     bl      dvmAllocObject              @ r0<- new object
1022     b       .LOP_NEW_INSTANCE_finish          @ continue
1023
1024 /* ------------------------------ */
1025     .balign 64
1026 .L_OP_NEW_ARRAY: /* 0x23 */
1027 /* File: armv5te/OP_NEW_ARRAY.S */
1028     /*
1029      * Allocate an array of objects, specified with the array class
1030      * and a count.
1031      *
1032      * The verifier guarantees that this is an array class, so we don't
1033      * check for it here.
1034      */
1035     /* new-array vA, vB, class@CCCC */
1036     mov     r0, rINST, lsr #12          @ r0<- B
1037     FETCH(r2, 1)                        @ r2<- CCCC
1038     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1039     GET_VREG(r1, r0)                    @ r1<- vB (array length)
1040     ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1041     cmp     r1, #0                      @ check length
1042     ldr     r0, [r3, r2, lsl #2]        @ r0<- resolved class
1043     bmi     common_errNegativeArraySize @ negative length, bail
1044     cmp     r0, #0                      @ already resolved?
1045     EXPORT_PC()                         @ req'd for resolve, alloc
1046     bne     .LOP_NEW_ARRAY_finish          @ resolved, continue
1047     b       .LOP_NEW_ARRAY_resolve         @ do resolve now
1048
1049 /* ------------------------------ */
1050     .balign 64
1051 .L_OP_FILLED_NEW_ARRAY: /* 0x24 */
1052 /* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1053     /*
1054      * Create a new array with elements filled from registers.
1055      *
1056      * for: filled-new-array, filled-new-array/range
1057      */
1058     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1059     /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1060     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1061     FETCH(r1, 1)                        @ r1<- BBBB
1062     ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1063     EXPORT_PC()                         @ need for resolve and alloc
1064     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1065     mov     r10, rINST, lsr #8          @ r10<- AA or BA
1066     cmp     r0, #0                      @ already resolved?
1067     bne     .LOP_FILLED_NEW_ARRAY_continue        @ yes, continue on
1068 8:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1069     mov     r2, #0                      @ r2<- false
1070     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1071     bl      dvmResolveClass             @ r0<- call(clazz, ref)
1072     cmp     r0, #0                      @ got null?
1073     beq     common_exceptionThrown      @ yes, handle exception
1074     b       .LOP_FILLED_NEW_ARRAY_continue
1075
1076 /* ------------------------------ */
1077     .balign 64
1078 .L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
1079 /* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */
1080 /* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1081     /*
1082      * Create a new array with elements filled from registers.
1083      *
1084      * for: filled-new-array, filled-new-array/range
1085      */
1086     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1087     /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1088     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1089     FETCH(r1, 1)                        @ r1<- BBBB
1090     ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1091     EXPORT_PC()                         @ need for resolve and alloc
1092     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1093     mov     r10, rINST, lsr #8          @ r10<- AA or BA
1094     cmp     r0, #0                      @ already resolved?
1095     bne     .LOP_FILLED_NEW_ARRAY_RANGE_continue        @ yes, continue on
1096 8:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1097     mov     r2, #0                      @ r2<- false
1098     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1099     bl      dvmResolveClass             @ r0<- call(clazz, ref)
1100     cmp     r0, #0                      @ got null?
1101     beq     common_exceptionThrown      @ yes, handle exception
1102     b       .LOP_FILLED_NEW_ARRAY_RANGE_continue
1103
1104
1105 /* ------------------------------ */
1106     .balign 64
1107 .L_OP_FILL_ARRAY_DATA: /* 0x26 */
1108 /* File: armv5te/OP_FILL_ARRAY_DATA.S */
1109     /* fill-array-data vAA, +BBBBBBBB */
1110     FETCH(r0, 1)                        @ r0<- bbbb (lo)
1111     FETCH(r1, 2)                        @ r1<- BBBB (hi)
1112     mov     r3, rINST, lsr #8           @ r3<- AA
1113     orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
1114     GET_VREG(r0, r3)                    @ r0<- vAA (array object)
1115     add     r1, rPC, r1, lsl #1         @ r1<- PC + BBBBbbbb*2 (array data off.)
1116     EXPORT_PC();
1117     bl      dvmInterpHandleFillArrayData@ fill the array with predefined data
1118     cmp     r0, #0                      @ 0 means an exception is thrown
1119     beq     common_exceptionThrown      @ has exception
1120     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
1121     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1122     GOTO_OPCODE(ip)                     @ jump to next instruction
1123
1124 /* ------------------------------ */
1125     .balign 64
1126 .L_OP_THROW: /* 0x27 */
1127 /* File: armv5te/OP_THROW.S */
1128     /*
1129      * Throw an exception object in the current thread.
1130      */
1131     /* throw vAA */
1132     mov     r2, rINST, lsr #8           @ r2<- AA
1133     GET_VREG(r1, r2)                    @ r1<- vAA (exception object)
1134     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
1135     cmp     r1, #0                      @ null object?
1136     beq     common_errNullObject        @ yes, throw an NPE instead
1137     @ bypass dvmSetException, just store it
1138     str     r1, [r0, #offThread_exception]  @ thread->exception<- obj
1139     b       common_exceptionThrown
1140
1141
1142 /* ------------------------------ */
1143     .balign 64
1144 .L_OP_GOTO: /* 0x28 */
1145 /* File: armv5te/OP_GOTO.S */
1146     /*
1147      * Unconditional branch, 8-bit offset.
1148      *
1149      * The branch distance is a signed code-unit offset, which we need to
1150      * double to get a byte offset.
1151      */
1152     /* goto +AA */
1153     mov     r0, rINST, lsl #16          @ r0<- AAxx0000
1154     movs    r9, r0, asr #24             @ r9<- ssssssAA (sign-extended)
1155     mov     r9, r9, lsl #1              @ r9<- byte offset
1156     bmi     common_backwardBranch       @ backward branch, do periodic checks
1157 #if defined(WITH_JIT)
1158     GET_JIT_PROF_TABLE(r0)
1159     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1160     cmp     r0,#0
1161     bne     common_updateProfile
1162     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1163     GOTO_OPCODE(ip)                     @ jump to next instruction
1164 #else
1165     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1166     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1167     GOTO_OPCODE(ip)                     @ jump to next instruction
1168 #endif
1169
1170 /* ------------------------------ */
1171     .balign 64
1172 .L_OP_GOTO_16: /* 0x29 */
1173 /* File: armv5te/OP_GOTO_16.S */
1174     /*
1175      * Unconditional branch, 16-bit offset.
1176      *
1177      * The branch distance is a signed code-unit offset, which we need to
1178      * double to get a byte offset.
1179      */
1180     /* goto/16 +AAAA */
1181     FETCH_S(r0, 1)                      @ r0<- ssssAAAA (sign-extended)
1182     movs    r9, r0, asl #1              @ r9<- byte offset, check sign
1183     bmi     common_backwardBranch       @ backward branch, do periodic checks
1184 #if defined(WITH_JIT)
1185     GET_JIT_PROF_TABLE(r0)
1186     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1187     cmp     r0,#0
1188     bne     common_updateProfile
1189     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1190     GOTO_OPCODE(ip)                     @ jump to next instruction
1191 #else
1192     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1193     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1194     GOTO_OPCODE(ip)                     @ jump to next instruction
1195 #endif
1196
1197
1198 /* ------------------------------ */
1199     .balign 64
1200 .L_OP_GOTO_32: /* 0x2a */
1201 /* File: armv5te/OP_GOTO_32.S */
1202     /*
1203      * Unconditional branch, 32-bit offset.
1204      *
1205      * The branch distance is a signed code-unit offset, which we need to
1206      * double to get a byte offset.
1207      *
1208      * Unlike most opcodes, this one is allowed to branch to itself, so
1209      * our "backward branch" test must be "<=0" instead of "<0".  The ORRS
1210      * instruction doesn't affect the V flag, so we need to clear it
1211      * explicitly.
1212      */
1213     /* goto/32 +AAAAAAAA */
1214     FETCH(r0, 1)                        @ r0<- aaaa (lo)
1215     FETCH(r1, 2)                        @ r1<- AAAA (hi)
1216     cmp     ip, ip                      @ (clear V flag during stall)
1217     orrs    r0, r0, r1, lsl #16         @ r0<- AAAAaaaa, check sign
1218     mov     r9, r0, asl #1              @ r9<- byte offset
1219     ble     common_backwardBranch       @ backward branch, do periodic checks
1220 #if defined(WITH_JIT)
1221     GET_JIT_PROF_TABLE(r0)
1222     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1223     cmp     r0,#0
1224     bne     common_updateProfile
1225     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1226     GOTO_OPCODE(ip)                     @ jump to next instruction
1227 #else
1228     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1229     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1230     GOTO_OPCODE(ip)                     @ jump to next instruction
1231 #endif
1232
1233 /* ------------------------------ */
1234     .balign 64
1235 .L_OP_PACKED_SWITCH: /* 0x2b */
1236 /* File: armv5te/OP_PACKED_SWITCH.S */
1237     /*
1238      * Handle a packed-switch or sparse-switch instruction.  In both cases
1239      * we decode it and hand it off to a helper function.
1240      *
1241      * We don't really expect backward branches in a switch statement, but
1242      * they're perfectly legal, so we check for them here.
1243      *
1244      * for: packed-switch, sparse-switch
1245      */
1246     /* op vAA, +BBBB */
1247     FETCH(r0, 1)                        @ r0<- bbbb (lo)
1248     FETCH(r1, 2)                        @ r1<- BBBB (hi)
1249     mov     r3, rINST, lsr #8           @ r3<- AA
1250     orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1251     GET_VREG(r1, r3)                    @ r1<- vAA
1252     add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1253     bl      dvmInterpHandlePackedSwitch                       @ r0<- code-unit branch offset
1254     movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1255     bmi     common_backwardBranch       @ backward branch, do periodic checks
1256     beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1257 #if defined(WITH_JIT)
1258     GET_JIT_PROF_TABLE(r0)
1259     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1260     cmp     r0,#0
1261     bne     common_updateProfile
1262     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1263     GOTO_OPCODE(ip)                     @ jump to next instruction
1264 #else
1265     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1266     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1267     GOTO_OPCODE(ip)                     @ jump to next instruction
1268 #endif
1269
1270
1271 /* ------------------------------ */
1272     .balign 64
1273 .L_OP_SPARSE_SWITCH: /* 0x2c */
1274 /* File: armv5te/OP_SPARSE_SWITCH.S */
1275 /* File: armv5te/OP_PACKED_SWITCH.S */
1276     /*
1277      * Handle a packed-switch or sparse-switch instruction.  In both cases
1278      * we decode it and hand it off to a helper function.
1279      *
1280      * We don't really expect backward branches in a switch statement, but
1281      * they're perfectly legal, so we check for them here.
1282      *
1283      * for: packed-switch, sparse-switch
1284      */
1285     /* op vAA, +BBBB */
1286     FETCH(r0, 1)                        @ r0<- bbbb (lo)
1287     FETCH(r1, 2)                        @ r1<- BBBB (hi)
1288     mov     r3, rINST, lsr #8           @ r3<- AA
1289     orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1290     GET_VREG(r1, r3)                    @ r1<- vAA
1291     add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1292     bl      dvmInterpHandleSparseSwitch                       @ r0<- code-unit branch offset
1293     movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1294     bmi     common_backwardBranch       @ backward branch, do periodic checks
1295     beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1296 #if defined(WITH_JIT)
1297     GET_JIT_PROF_TABLE(r0)
1298     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1299     cmp     r0,#0
1300     bne     common_updateProfile
1301     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1302     GOTO_OPCODE(ip)                     @ jump to next instruction
1303 #else
1304     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1305     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1306     GOTO_OPCODE(ip)                     @ jump to next instruction
1307 #endif
1308
1309
1310
1311 /* ------------------------------ */
1312     .balign 64
1313 .L_OP_CMPL_FLOAT: /* 0x2d */
1314 /* File: armv5te/OP_CMPL_FLOAT.S */
1315     /*
1316      * Compare two floating-point values.  Puts 0, 1, or -1 into the
1317      * destination register based on the results of the comparison.
1318      *
1319      * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1320      * on what value we'd like to return when one of the operands is NaN.
1321      *
1322      * The operation we're implementing is:
1323      *   if (x == y)
1324      *     return 0;
1325      *   else if (x < y)
1326      *     return -1;
1327      *   else if (x > y)
1328      *     return 1;
1329      *   else
1330      *     return {-1,1};  // one or both operands was NaN
1331      *
1332      * The straightforward implementation requires 3 calls to functions
1333      * that return a result in r0.  We can do it with two calls if our
1334      * EABI library supports __aeabi_cfcmple (only one if we want to check
1335      * for NaN directly):
1336      *   check x <= y
1337      *     if <, return -1
1338      *     if ==, return 0
1339      *   check y <= x
1340      *     if <, return 1
1341      *   return {-1,1}
1342      *
1343      * for: cmpl-float, cmpg-float
1344      */
1345     /* op vAA, vBB, vCC */
1346     FETCH(r0, 1)                        @ r0<- CCBB
1347     and     r2, r0, #255                @ r2<- BB
1348     mov     r3, r0, lsr #8              @ r3<- CC
1349     GET_VREG(r9, r2)                    @ r9<- vBB
1350     GET_VREG(r10, r3)                   @ r10<- vCC
1351     mov     r0, r9                      @ copy to arg registers
1352     mov     r1, r10
1353     bl      __aeabi_cfcmple             @ cmp <=: C clear if <, Z set if eq
1354     bhi     .LOP_CMPL_FLOAT_gt_or_nan       @ C set and Z clear, disambiguate
1355     mvncc   r1, #0                      @ (less than) r1<- -1
1356     moveq   r1, #0                      @ (equal) r1<- 0, trumps less than
1357 .LOP_CMPL_FLOAT_finish:
1358     mov     r3, rINST, lsr #8           @ r3<- AA
1359     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1360     SET_VREG(r1, r3)                    @ vAA<- r1
1361     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1362     GOTO_OPCODE(ip)                     @ jump to next instruction
1363
1364 /* ------------------------------ */
1365     .balign 64
1366 .L_OP_CMPG_FLOAT: /* 0x2e */
1367 /* File: armv5te/OP_CMPG_FLOAT.S */
1368 /* File: armv5te/OP_CMPL_FLOAT.S */
1369     /*
1370      * Compare two floating-point values.  Puts 0, 1, or -1 into the
1371      * destination register based on the results of the comparison.
1372      *
1373      * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1374      * on what value we'd like to return when one of the operands is NaN.
1375      *
1376      * The operation we're implementing is:
1377      *   if (x == y)
1378      *     return 0;
1379      *   else if (x < y)
1380      *     return -1;
1381      *   else if (x > y)
1382      *     return 1;
1383      *   else
1384      *     return {-1,1};  // one or both operands was NaN
1385      *
1386      * The straightforward implementation requires 3 calls to functions
1387      * that return a result in r0.  We can do it with two calls if our
1388      * EABI library supports __aeabi_cfcmple (only one if we want to check
1389      * for NaN directly):
1390      *   check x <= y
1391      *     if <, return -1
1392      *     if ==, return 0
1393      *   check y <= x
1394      *     if <, return 1
1395      *   return {-1,1}
1396      *
1397      * for: cmpl-float, cmpg-float
1398      */
1399     /* op vAA, vBB, vCC */
1400     FETCH(r0, 1)                        @ r0<- CCBB
1401     and     r2, r0, #255                @ r2<- BB
1402     mov     r3, r0, lsr #8              @ r3<- CC
1403     GET_VREG(r9, r2)                    @ r9<- vBB
1404     GET_VREG(r10, r3)                   @ r10<- vCC
1405     mov     r0, r9                      @ copy to arg registers
1406     mov     r1, r10
1407     bl      __aeabi_cfcmple             @ cmp <=: C clear if <, Z set if eq
1408     bhi     .LOP_CMPG_FLOAT_gt_or_nan       @ C set and Z clear, disambiguate
1409     mvncc   r1, #0                      @ (less than) r1<- -1
1410     moveq   r1, #0                      @ (equal) r1<- 0, trumps less than
1411 .LOP_CMPG_FLOAT_finish:
1412     mov     r3, rINST, lsr #8           @ r3<- AA
1413     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1414     SET_VREG(r1, r3)                    @ vAA<- r1
1415     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1416     GOTO_OPCODE(ip)                     @ jump to next instruction
1417
1418
1419 /* ------------------------------ */
1420     .balign 64
1421 .L_OP_CMPL_DOUBLE: /* 0x2f */
1422 /* File: armv5te/OP_CMPL_DOUBLE.S */
1423     /*
1424      * Compare two floating-point values.  Puts 0, 1, or -1 into the
1425      * destination register based on the results of the comparison.
1426      *
1427      * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1428      * on what value we'd like to return when one of the operands is NaN.
1429      *
1430      * See OP_CMPL_FLOAT for an explanation.
1431      *
1432      * For: cmpl-double, cmpg-double
1433      */
1434     /* op vAA, vBB, vCC */
1435     FETCH(r0, 1)                        @ r0<- CCBB
1436     and     r9, r0, #255                @ r9<- BB
1437     mov     r10, r0, lsr #8             @ r10<- CC
1438     add     r9, rFP, r9, lsl #2         @ r9<- &fp[BB]
1439     add     r10, rFP, r10, lsl #2       @ r10<- &fp[CC]
1440     ldmia   r9, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1441     ldmia   r10, {r2-r3}                @ r2/r3<- vCC/vCC+1
1442     bl      __aeabi_cdcmple             @ cmp <=: C clear if <, Z set if eq
1443     bhi     .LOP_CMPL_DOUBLE_gt_or_nan       @ C set and Z clear, disambiguate
1444     mvncc   r1, #0                      @ (less than) r1<- -1
1445     moveq   r1, #0                      @ (equal) r1<- 0, trumps less than
1446 .LOP_CMPL_DOUBLE_finish:
1447     mov     r3, rINST, lsr #8           @ r3<- AA
1448     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1449     SET_VREG(r1, r3)                    @ vAA<- r1
1450     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1451     GOTO_OPCODE(ip)                     @ jump to next instruction
1452
1453 /* ------------------------------ */
1454     .balign 64
1455 .L_OP_CMPG_DOUBLE: /* 0x30 */
1456 /* File: armv5te/OP_CMPG_DOUBLE.S */
1457 /* File: armv5te/OP_CMPL_DOUBLE.S */
1458     /*
1459      * Compare two floating-point values.  Puts 0, 1, or -1 into the
1460      * destination register based on the results of the comparison.
1461      *
1462      * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1463      * on what value we'd like to return when one of the operands is NaN.
1464      *
1465      * See OP_CMPL_FLOAT for an explanation.
1466      *
1467      * For: cmpl-double, cmpg-double
1468      */
1469     /* op vAA, vBB, vCC */
1470     FETCH(r0, 1)                        @ r0<- CCBB
1471     and     r9, r0, #255                @ r9<- BB
1472     mov     r10, r0, lsr #8             @ r10<- CC
1473     add     r9, rFP, r9, lsl #2         @ r9<- &fp[BB]
1474     add     r10, rFP, r10, lsl #2       @ r10<- &fp[CC]
1475     ldmia   r9, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1476     ldmia   r10, {r2-r3}                @ r2/r3<- vCC/vCC+1
1477     bl      __aeabi_cdcmple             @ cmp <=: C clear if <, Z set if eq
1478     bhi     .LOP_CMPG_DOUBLE_gt_or_nan       @ C set and Z clear, disambiguate
1479     mvncc   r1, #0                      @ (less than) r1<- -1
1480     moveq   r1, #0                      @ (equal) r1<- 0, trumps less than
1481 .LOP_CMPG_DOUBLE_finish:
1482     mov     r3, rINST, lsr #8           @ r3<- AA
1483     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1484     SET_VREG(r1, r3)                    @ vAA<- r1
1485     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1486     GOTO_OPCODE(ip)                     @ jump to next instruction
1487
1488
1489 /* ------------------------------ */
1490     .balign 64
1491 .L_OP_CMP_LONG: /* 0x31 */
1492 /* File: armv5te/OP_CMP_LONG.S */
1493     /*
1494      * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
1495      * register based on the results of the comparison.
1496      *
1497      * We load the full values with LDM, but in practice many values could
1498      * be resolved by only looking at the high word.  This could be made
1499      * faster or slower by splitting the LDM into a pair of LDRs.
1500      *
1501      * If we just wanted to set condition flags, we could do this:
1502      *  subs    ip, r0, r2
1503      *  sbcs    ip, r1, r3
1504      *  subeqs  ip, r0, r2
1505      * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
1506      * integer value, which we can do with 2 conditional mov/mvn instructions
1507      * (set 1, set -1; if they're equal we already have 0 in ip), giving
1508      * us a constant 5-cycle path plus a branch at the end to the
1509      * instruction epilogue code.  The multi-compare approach below needs
1510      * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
1511      * in the worst case (the 64-bit values are equal).
1512      */
1513     /* cmp-long vAA, vBB, vCC */
1514     FETCH(r0, 1)                        @ r0<- CCBB
1515     mov     r9, rINST, lsr #8           @ r9<- AA
1516     and     r2, r0, #255                @ r2<- BB
1517     mov     r3, r0, lsr #8              @ r3<- CC
1518     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
1519     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
1520     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1521     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
1522     cmp     r1, r3                      @ compare (vBB+1, vCC+1)
1523     blt     .LOP_CMP_LONG_less            @ signed compare on high part
1524     bgt     .LOP_CMP_LONG_greater
1525     subs    r1, r0, r2                  @ r1<- r0 - r2
1526     bhi     .LOP_CMP_LONG_greater         @ unsigned compare on low part
1527     bne     .LOP_CMP_LONG_less
1528     b       .LOP_CMP_LONG_finish          @ equal; r1 already holds 0
1529
1530 /* ------------------------------ */
1531     .balign 64
1532 .L_OP_IF_EQ: /* 0x32 */
1533 /* File: armv5te/OP_IF_EQ.S */
1534 /* File: armv5te/bincmp.S */
1535     /*
1536      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1537      * fragment that specifies the *reverse* comparison to perform, e.g.
1538      * for "if-le" you would use "gt".
1539      *
1540      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1541      */
1542     /* if-cmp vA, vB, +CCCC */
1543     mov     r0, rINST, lsr #8           @ r0<- A+
1544     mov     r1, rINST, lsr #12          @ r1<- B
1545     and     r0, r0, #15
1546     GET_VREG(r3, r1)                    @ r3<- vB
1547     GET_VREG(r2, r0)                    @ r2<- vA
1548     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1549     cmp     r2, r3                      @ compare (vA, vB)
1550     bne  1f                      @ branch to 1 if comparison failed
1551     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1552     movs    r9, r9, asl #1              @ convert to bytes, check sign
1553     bmi     common_backwardBranch       @ yes, do periodic checks
1554 1:
1555 #if defined(WITH_JIT)
1556     GET_JIT_PROF_TABLE(r0)
1557     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1558     b        common_testUpdateProfile
1559 #else
1560     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1561     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1562     GOTO_OPCODE(ip)                     @ jump to next instruction
1563 #endif
1564
1565
1566
1567 /* ------------------------------ */
1568     .balign 64
1569 .L_OP_IF_NE: /* 0x33 */
1570 /* File: armv5te/OP_IF_NE.S */
1571 /* File: armv5te/bincmp.S */
1572     /*
1573      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1574      * fragment that specifies the *reverse* comparison to perform, e.g.
1575      * for "if-le" you would use "gt".
1576      *
1577      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1578      */
1579     /* if-cmp vA, vB, +CCCC */
1580     mov     r0, rINST, lsr #8           @ r0<- A+
1581     mov     r1, rINST, lsr #12          @ r1<- B
1582     and     r0, r0, #15
1583     GET_VREG(r3, r1)                    @ r3<- vB
1584     GET_VREG(r2, r0)                    @ r2<- vA
1585     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1586     cmp     r2, r3                      @ compare (vA, vB)
1587     beq  1f                      @ branch to 1 if comparison failed
1588     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1589     movs    r9, r9, asl #1              @ convert to bytes, check sign
1590     bmi     common_backwardBranch       @ yes, do periodic checks
1591 1:
1592 #if defined(WITH_JIT)
1593     GET_JIT_PROF_TABLE(r0)
1594     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1595     b        common_testUpdateProfile
1596 #else
1597     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1598     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1599     GOTO_OPCODE(ip)                     @ jump to next instruction
1600 #endif
1601
1602
1603
1604 /* ------------------------------ */
1605     .balign 64
1606 .L_OP_IF_LT: /* 0x34 */
1607 /* File: armv5te/OP_IF_LT.S */
1608 /* File: armv5te/bincmp.S */
1609     /*
1610      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1611      * fragment that specifies the *reverse* comparison to perform, e.g.
1612      * for "if-le" you would use "gt".
1613      *
1614      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1615      */
1616     /* if-cmp vA, vB, +CCCC */
1617     mov     r0, rINST, lsr #8           @ r0<- A+
1618     mov     r1, rINST, lsr #12          @ r1<- B
1619     and     r0, r0, #15
1620     GET_VREG(r3, r1)                    @ r3<- vB
1621     GET_VREG(r2, r0)                    @ r2<- vA
1622     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1623     cmp     r2, r3                      @ compare (vA, vB)
1624     bge  1f                      @ branch to 1 if comparison failed
1625     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1626     movs    r9, r9, asl #1              @ convert to bytes, check sign
1627     bmi     common_backwardBranch       @ yes, do periodic checks
1628 1:
1629 #if defined(WITH_JIT)
1630     GET_JIT_PROF_TABLE(r0)
1631     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1632     b        common_testUpdateProfile
1633 #else
1634     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1635     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1636     GOTO_OPCODE(ip)                     @ jump to next instruction
1637 #endif
1638
1639
1640
1641 /* ------------------------------ */
1642     .balign 64
1643 .L_OP_IF_GE: /* 0x35 */
1644 /* File: armv5te/OP_IF_GE.S */
1645 /* File: armv5te/bincmp.S */
1646     /*
1647      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1648      * fragment that specifies the *reverse* comparison to perform, e.g.
1649      * for "if-le" you would use "gt".
1650      *
1651      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1652      */
1653     /* if-cmp vA, vB, +CCCC */
1654     mov     r0, rINST, lsr #8           @ r0<- A+
1655     mov     r1, rINST, lsr #12          @ r1<- B
1656     and     r0, r0, #15
1657     GET_VREG(r3, r1)                    @ r3<- vB
1658     GET_VREG(r2, r0)                    @ r2<- vA
1659     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1660     cmp     r2, r3                      @ compare (vA, vB)
1661     blt  1f                      @ branch to 1 if comparison failed
1662     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1663     movs    r9, r9, asl #1              @ convert to bytes, check sign
1664     bmi     common_backwardBranch       @ yes, do periodic checks
1665 1:
1666 #if defined(WITH_JIT)
1667     GET_JIT_PROF_TABLE(r0)
1668     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1669     b        common_testUpdateProfile
1670 #else
1671     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1672     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1673     GOTO_OPCODE(ip)                     @ jump to next instruction
1674 #endif
1675
1676
1677
1678 /* ------------------------------ */
1679     .balign 64
1680 .L_OP_IF_GT: /* 0x36 */
1681 /* File: armv5te/OP_IF_GT.S */
1682 /* File: armv5te/bincmp.S */
1683     /*
1684      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1685      * fragment that specifies the *reverse* comparison to perform, e.g.
1686      * for "if-le" you would use "gt".
1687      *
1688      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1689      */
1690     /* if-cmp vA, vB, +CCCC */
1691     mov     r0, rINST, lsr #8           @ r0<- A+
1692     mov     r1, rINST, lsr #12          @ r1<- B
1693     and     r0, r0, #15
1694     GET_VREG(r3, r1)                    @ r3<- vB
1695     GET_VREG(r2, r0)                    @ r2<- vA
1696     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1697     cmp     r2, r3                      @ compare (vA, vB)
1698     ble  1f                      @ branch to 1 if comparison failed
1699     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1700     movs    r9, r9, asl #1              @ convert to bytes, check sign
1701     bmi     common_backwardBranch       @ yes, do periodic checks
1702 1:
1703 #if defined(WITH_JIT)
1704     GET_JIT_PROF_TABLE(r0)
1705     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1706     b        common_testUpdateProfile
1707 #else
1708     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1709     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1710     GOTO_OPCODE(ip)                     @ jump to next instruction
1711 #endif
1712
1713
1714
1715 /* ------------------------------ */
1716     .balign 64
1717 .L_OP_IF_LE: /* 0x37 */
1718 /* File: armv5te/OP_IF_LE.S */
1719 /* File: armv5te/bincmp.S */
1720     /*
1721      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1722      * fragment that specifies the *reverse* comparison to perform, e.g.
1723      * for "if-le" you would use "gt".
1724      *
1725      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1726      */
1727     /* if-cmp vA, vB, +CCCC */
1728     mov     r0, rINST, lsr #8           @ r0<- A+
1729     mov     r1, rINST, lsr #12          @ r1<- B
1730     and     r0, r0, #15
1731     GET_VREG(r3, r1)                    @ r3<- vB
1732     GET_VREG(r2, r0)                    @ r2<- vA
1733     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1734     cmp     r2, r3                      @ compare (vA, vB)
1735     bgt  1f                      @ branch to 1 if comparison failed
1736     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1737     movs    r9, r9, asl #1              @ convert to bytes, check sign
1738     bmi     common_backwardBranch       @ yes, do periodic checks
1739 1:
1740 #if defined(WITH_JIT)
1741     GET_JIT_PROF_TABLE(r0)
1742     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1743     b        common_testUpdateProfile
1744 #else
1745     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1746     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1747     GOTO_OPCODE(ip)                     @ jump to next instruction
1748 #endif
1749
1750
1751
1752 /* ------------------------------ */
1753     .balign 64
1754 .L_OP_IF_EQZ: /* 0x38 */
1755 /* File: armv5te/OP_IF_EQZ.S */
1756 /* File: armv5te/zcmp.S */
1757     /*
1758      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1759      * fragment that specifies the *reverse* comparison to perform, e.g.
1760      * for "if-le" you would use "gt".
1761      *
1762      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1763      */
1764     /* if-cmp vAA, +BBBB */
1765     mov     r0, rINST, lsr #8           @ r0<- AA
1766     GET_VREG(r2, r0)                    @ r2<- vAA
1767     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1768     cmp     r2, #0                      @ compare (vA, 0)
1769     bne  1f                      @ branch to 1 if comparison failed
1770     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1771     movs    r9, r9, asl #1              @ convert to bytes, check sign
1772     bmi     common_backwardBranch       @ backward branch, do periodic checks
1773 1:
1774 #if defined(WITH_JIT)
1775     GET_JIT_PROF_TABLE(r0)
1776     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1777     cmp     r0,#0
1778     bne     common_updateProfile
1779     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1780     GOTO_OPCODE(ip)                     @ jump to next instruction
1781 #else
1782     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1783     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1784     GOTO_OPCODE(ip)                     @ jump to next instruction
1785 #endif
1786
1787
1788
1789 /* ------------------------------ */
1790     .balign 64
1791 .L_OP_IF_NEZ: /* 0x39 */
1792 /* File: armv5te/OP_IF_NEZ.S */
1793 /* File: armv5te/zcmp.S */
1794     /*
1795      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1796      * fragment that specifies the *reverse* comparison to perform, e.g.
1797      * for "if-le" you would use "gt".
1798      *
1799      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1800      */
1801     /* if-cmp vAA, +BBBB */
1802     mov     r0, rINST, lsr #8           @ r0<- AA
1803     GET_VREG(r2, r0)                    @ r2<- vAA
1804     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1805     cmp     r2, #0                      @ compare (vA, 0)
1806     beq  1f                      @ branch to 1 if comparison failed
1807     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1808     movs    r9, r9, asl #1              @ convert to bytes, check sign
1809     bmi     common_backwardBranch       @ backward branch, do periodic checks
1810 1:
1811 #if defined(WITH_JIT)
1812     GET_JIT_PROF_TABLE(r0)
1813     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1814     cmp     r0,#0
1815     bne     common_updateProfile
1816     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1817     GOTO_OPCODE(ip)                     @ jump to next instruction
1818 #else
1819     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1820     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1821     GOTO_OPCODE(ip)                     @ jump to next instruction
1822 #endif
1823
1824
1825
1826 /* ------------------------------ */
1827     .balign 64
1828 .L_OP_IF_LTZ: /* 0x3a */
1829 /* File: armv5te/OP_IF_LTZ.S */
1830 /* File: armv5te/zcmp.S */
1831     /*
1832      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1833      * fragment that specifies the *reverse* comparison to perform, e.g.
1834      * for "if-le" you would use "gt".
1835      *
1836      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1837      */
1838     /* if-cmp vAA, +BBBB */
1839     mov     r0, rINST, lsr #8           @ r0<- AA
1840     GET_VREG(r2, r0)                    @ r2<- vAA
1841     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1842     cmp     r2, #0                      @ compare (vA, 0)
1843     bge  1f                      @ branch to 1 if comparison failed
1844     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1845     movs    r9, r9, asl #1              @ convert to bytes, check sign
1846     bmi     common_backwardBranch       @ backward branch, do periodic checks
1847 1:
1848 #if defined(WITH_JIT)
1849     GET_JIT_PROF_TABLE(r0)
1850     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1851     cmp     r0,#0
1852     bne     common_updateProfile
1853     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1854     GOTO_OPCODE(ip)                     @ jump to next instruction
1855 #else
1856     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1857     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1858     GOTO_OPCODE(ip)                     @ jump to next instruction
1859 #endif
1860
1861
1862
1863 /* ------------------------------ */
1864     .balign 64
1865 .L_OP_IF_GEZ: /* 0x3b */
1866 /* File: armv5te/OP_IF_GEZ.S */
1867 /* File: armv5te/zcmp.S */
1868     /*
1869      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1870      * fragment that specifies the *reverse* comparison to perform, e.g.
1871      * for "if-le" you would use "gt".
1872      *
1873      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1874      */
1875     /* if-cmp vAA, +BBBB */
1876     mov     r0, rINST, lsr #8           @ r0<- AA
1877     GET_VREG(r2, r0)                    @ r2<- vAA
1878     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1879     cmp     r2, #0                      @ compare (vA, 0)
1880     blt  1f                      @ branch to 1 if comparison failed
1881     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1882     movs    r9, r9, asl #1              @ convert to bytes, check sign
1883     bmi     common_backwardBranch       @ backward branch, do periodic checks
1884 1:
1885 #if defined(WITH_JIT)
1886     GET_JIT_PROF_TABLE(r0)
1887     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1888     cmp     r0,#0
1889     bne     common_updateProfile
1890     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1891     GOTO_OPCODE(ip)                     @ jump to next instruction
1892 #else
1893     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1894     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1895     GOTO_OPCODE(ip)                     @ jump to next instruction
1896 #endif
1897
1898
1899
1900 /* ------------------------------ */
1901     .balign 64
1902 .L_OP_IF_GTZ: /* 0x3c */
1903 /* File: armv5te/OP_IF_GTZ.S */
1904 /* File: armv5te/zcmp.S */
1905     /*
1906      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1907      * fragment that specifies the *reverse* comparison to perform, e.g.
1908      * for "if-le" you would use "gt".
1909      *
1910      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1911      */
1912     /* if-cmp vAA, +BBBB */
1913     mov     r0, rINST, lsr #8           @ r0<- AA
1914     GET_VREG(r2, r0)                    @ r2<- vAA
1915     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1916     cmp     r2, #0                      @ compare (vA, 0)
1917     ble  1f                      @ branch to 1 if comparison failed
1918     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1919     movs    r9, r9, asl #1              @ convert to bytes, check sign
1920     bmi     common_backwardBranch       @ backward branch, do periodic checks
1921 1:
1922 #if defined(WITH_JIT)
1923     GET_JIT_PROF_TABLE(r0)
1924     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1925     cmp     r0,#0
1926     bne     common_updateProfile
1927     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1928     GOTO_OPCODE(ip)                     @ jump to next instruction
1929 #else
1930     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1931     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1932     GOTO_OPCODE(ip)                     @ jump to next instruction
1933 #endif
1934
1935
1936
1937 /* ------------------------------ */
1938     .balign 64
1939 .L_OP_IF_LEZ: /* 0x3d */
1940 /* File: armv5te/OP_IF_LEZ.S */
1941 /* File: armv5te/zcmp.S */
1942     /*
1943      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1944      * fragment that specifies the *reverse* comparison to perform, e.g.
1945      * for "if-le" you would use "gt".
1946      *
1947      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1948      */
1949     /* if-cmp vAA, +BBBB */
1950     mov     r0, rINST, lsr #8           @ r0<- AA
1951     GET_VREG(r2, r0)                    @ r2<- vAA
1952     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1953     cmp     r2, #0                      @ compare (vA, 0)
1954     bgt  1f                      @ branch to 1 if comparison failed
1955     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1956     movs    r9, r9, asl #1              @ convert to bytes, check sign
1957     bmi     common_backwardBranch       @ backward branch, do periodic checks
1958 1:
1959 #if defined(WITH_JIT)
1960     GET_JIT_PROF_TABLE(r0)
1961     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1962     cmp     r0,#0
1963     bne     common_updateProfile
1964     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1965     GOTO_OPCODE(ip)                     @ jump to next instruction
1966 #else
1967     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1968     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1969     GOTO_OPCODE(ip)                     @ jump to next instruction
1970 #endif
1971
1972
1973
1974 /* ------------------------------ */
1975     .balign 64
1976 .L_OP_UNUSED_3E: /* 0x3e */
1977 /* File: armv5te/OP_UNUSED_3E.S */
1978 /* File: armv5te/unused.S */
1979     bl      common_abort
1980
1981
1982
1983 /* ------------------------------ */
1984     .balign 64
1985 .L_OP_UNUSED_3F: /* 0x3f */
1986 /* File: armv5te/OP_UNUSED_3F.S */
1987 /* File: armv5te/unused.S */
1988     bl      common_abort
1989
1990
1991
1992 /* ------------------------------ */
1993     .balign 64
1994 .L_OP_UNUSED_40: /* 0x40 */
1995 /* File: armv5te/OP_UNUSED_40.S */
1996 /* File: armv5te/unused.S */
1997     bl      common_abort
1998
1999
2000
2001 /* ------------------------------ */
2002     .balign 64
2003 .L_OP_UNUSED_41: /* 0x41 */
2004 /* File: armv5te/OP_UNUSED_41.S */
2005 /* File: armv5te/unused.S */
2006     bl      common_abort
2007
2008
2009
2010 /* ------------------------------ */
2011     .balign 64
2012 .L_OP_UNUSED_42: /* 0x42 */
2013 /* File: armv5te/OP_UNUSED_42.S */
2014 /* File: armv5te/unused.S */
2015     bl      common_abort
2016
2017
2018
2019 /* ------------------------------ */
2020     .balign 64
2021 .L_OP_UNUSED_43: /* 0x43 */
2022 /* File: armv5te/OP_UNUSED_43.S */
2023 /* File: armv5te/unused.S */
2024     bl      common_abort
2025
2026
2027
2028 /* ------------------------------ */
2029     .balign 64
2030 .L_OP_AGET: /* 0x44 */
2031 /* File: armv5te/OP_AGET.S */
2032     /*
2033      * Array get, 32 bits or less.  vAA <- vBB[vCC].
2034      *
2035      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2036      * instructions.  We use a pair of FETCH_Bs instead.
2037      *
2038      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2039      */
2040     /* op vAA, vBB, vCC */
2041     FETCH_B(r2, 1, 0)                   @ r2<- BB
2042     mov     r9, rINST, lsr #8           @ r9<- AA
2043     FETCH_B(r3, 1, 1)                   @ r3<- CC
2044     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2045     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2046     cmp     r0, #0                      @ null array object?
2047     beq     common_errNullObject        @ yes, bail
2048     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2049     add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2050     cmp     r1, r3                      @ compare unsigned index, length
2051     bcs     common_errArrayIndex        @ index >= length, bail
2052     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2053     ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2054     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2055     SET_VREG(r2, r9)                    @ vAA<- r2
2056     GOTO_OPCODE(ip)                     @ jump to next instruction
2057
2058
2059 /* ------------------------------ */
2060     .balign 64
2061 .L_OP_AGET_WIDE: /* 0x45 */
2062 /* File: armv4t/OP_AGET_WIDE.S */
2063     /*
2064      * Array get, 64 bits.  vAA <- vBB[vCC].
2065      *
2066      * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD.
2067      */
2068     /* aget-wide vAA, vBB, vCC */
2069     FETCH(r0, 1)                        @ r0<- CCBB
2070     mov     r9, rINST, lsr #8           @ r9<- AA
2071     and     r2, r0, #255                @ r2<- BB
2072     mov     r3, r0, lsr #8              @ r3<- CC
2073     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2074     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2075     cmp     r0, #0                      @ null array object?
2076     beq     common_errNullObject        @ yes, bail
2077     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2078     add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2079     cmp     r1, r3                      @ compare unsigned index, length
2080     bcc     .LOP_AGET_WIDE_finish          @ okay, continue below
2081     b       common_errArrayIndex        @ index >= length, bail
2082     @ May want to swap the order of these two branches depending on how the
2083     @ branch prediction (if any) handles conditional forward branches vs.
2084     @ unconditional forward branches.
2085
2086 /* ------------------------------ */
2087     .balign 64
2088 .L_OP_AGET_OBJECT: /* 0x46 */
2089 /* File: armv5te/OP_AGET_OBJECT.S */
2090 /* File: armv5te/OP_AGET.S */
2091     /*
2092      * Array get, 32 bits or less.  vAA <- vBB[vCC].
2093      *
2094      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2095      * instructions.  We use a pair of FETCH_Bs instead.
2096      *
2097      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2098      */
2099     /* op vAA, vBB, vCC */
2100     FETCH_B(r2, 1, 0)                   @ r2<- BB
2101     mov     r9, rINST, lsr #8           @ r9<- AA
2102     FETCH_B(r3, 1, 1)                   @ r3<- CC
2103     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2104     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2105     cmp     r0, #0                      @ null array object?
2106     beq     common_errNullObject        @ yes, bail
2107     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2108     add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2109     cmp     r1, r3                      @ compare unsigned index, length
2110     bcs     common_errArrayIndex        @ index >= length, bail
2111     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2112     ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2113     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2114     SET_VREG(r2, r9)                    @ vAA<- r2
2115     GOTO_OPCODE(ip)                     @ jump to next instruction
2116
2117
2118
2119 /* ------------------------------ */
2120     .balign 64
2121 .L_OP_AGET_BOOLEAN: /* 0x47 */
2122 /* File: armv5te/OP_AGET_BOOLEAN.S */
2123 /* File: armv5te/OP_AGET.S */
2124     /*
2125      * Array get, 32 bits or less.  vAA <- vBB[vCC].
2126      *
2127      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2128      * instructions.  We use a pair of FETCH_Bs instead.
2129      *
2130      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2131      */
2132     /* op vAA, vBB, vCC */
2133     FETCH_B(r2, 1, 0)                   @ r2<- BB
2134     mov     r9, rINST, lsr #8           @ r9<- AA
2135     FETCH_B(r3, 1, 1)                   @ r3<- CC
2136     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2137     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2138     cmp     r0, #0                      @ null array object?
2139     beq     common_errNullObject        @ yes, bail
2140     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2141     add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2142     cmp     r1, r3                      @ compare unsigned index, length
2143     bcs     common_errArrayIndex        @ index >= length, bail
2144     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2145     ldrb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2146     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2147     SET_VREG(r2, r9)                    @ vAA<- r2
2148     GOTO_OPCODE(ip)                     @ jump to next instruction
2149
2150
2151
2152 /* ------------------------------ */
2153     .balign 64
2154 .L_OP_AGET_BYTE: /* 0x48 */
2155 /* File: armv5te/OP_AGET_BYTE.S */
2156 /* File: armv5te/OP_AGET.S */
2157     /*
2158      * Array get, 32 bits or less.  vAA <- vBB[vCC].
2159      *
2160      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2161      * instructions.  We use a pair of FETCH_Bs instead.
2162      *
2163      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2164      */
2165     /* op vAA, vBB, vCC */
2166     FETCH_B(r2, 1, 0)                   @ r2<- BB
2167     mov     r9, rINST, lsr #8           @ r9<- AA
2168     FETCH_B(r3, 1, 1)                   @ r3<- CC
2169     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2170     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2171     cmp     r0, #0                      @ null array object?
2172     beq     common_errNullObject        @ yes, bail
2173     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2174     add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2175     cmp     r1, r3                      @ compare unsigned index, length
2176     bcs     common_errArrayIndex        @ index >= length, bail
2177     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2178     ldrsb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2179     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2180     SET_VREG(r2, r9)                    @ vAA<- r2
2181     GOTO_OPCODE(ip)                     @ jump to next instruction
2182
2183
2184
2185 /* ------------------------------ */
2186     .balign 64
2187 .L_OP_AGET_CHAR: /* 0x49 */
2188 /* File: armv5te/OP_AGET_CHAR.S */
2189 /* File: armv5te/OP_AGET.S */
2190     /*
2191      * Array get, 32 bits or less.  vAA <- vBB[vCC].
2192      *
2193      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2194      * instructions.  We use a pair of FETCH_Bs instead.
2195      *
2196      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2197      */
2198     /* op vAA, vBB, vCC */
2199     FETCH_B(r2, 1, 0)                   @ r2<- BB
2200     mov     r9, rINST, lsr #8           @ r9<- AA
2201     FETCH_B(r3, 1, 1)                   @ r3<- CC
2202     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2203     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2204     cmp     r0, #0                      @ null array object?
2205     beq     common_errNullObject        @ yes, bail
2206     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2207     add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2208     cmp     r1, r3                      @ compare unsigned index, length
2209     bcs     common_errArrayIndex        @ index >= length, bail
2210     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2211     ldrh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2212     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2213     SET_VREG(r2, r9)                    @ vAA<- r2
2214     GOTO_OPCODE(ip)                     @ jump to next instruction
2215
2216
2217
2218 /* ------------------------------ */
2219     .balign 64
2220 .L_OP_AGET_SHORT: /* 0x4a */
2221 /* File: armv5te/OP_AGET_SHORT.S */
2222 /* File: armv5te/OP_AGET.S */
2223     /*
2224      * Array get, 32 bits or less.  vAA <- vBB[vCC].
2225      *
2226      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2227      * instructions.  We use a pair of FETCH_Bs instead.
2228      *
2229      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2230      */
2231     /* op vAA, vBB, vCC */
2232     FETCH_B(r2, 1, 0)                   @ r2<- BB
2233     mov     r9, rINST, lsr #8           @ r9<- AA
2234     FETCH_B(r3, 1, 1)                   @ r3<- CC
2235     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2236     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2237     cmp     r0, #0                      @ null array object?
2238     beq     common_errNullObject        @ yes, bail
2239     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2240     add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2241     cmp     r1, r3                      @ compare unsigned index, length
2242     bcs     common_errArrayIndex        @ index >= length, bail
2243     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2244     ldrsh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2245     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2246     SET_VREG(r2, r9)                    @ vAA<- r2
2247     GOTO_OPCODE(ip)                     @ jump to next instruction
2248
2249
2250
2251 /* ------------------------------ */
2252     .balign 64
2253 .L_OP_APUT: /* 0x4b */
2254 /* File: armv5te/OP_APUT.S */
2255     /*
2256      * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2257      *
2258      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2259      * instructions.  We use a pair of FETCH_Bs instead.
2260      *
2261      * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2262      */
2263     /* op vAA, vBB, vCC */
2264     FETCH_B(r2, 1, 0)                   @ r2<- BB
2265     mov     r9, rINST, lsr #8           @ r9<- AA
2266     FETCH_B(r3, 1, 1)                   @ r3<- CC
2267     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2268     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2269     cmp     r0, #0                      @ null array object?
2270     beq     common_errNullObject        @ yes, bail
2271     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2272     add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2273     cmp     r1, r3                      @ compare unsigned index, length
2274     bcs     common_errArrayIndex        @ index >= length, bail
2275     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2276     GET_VREG(r2, r9)                    @ r2<- vAA
2277     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2278     str  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2279     GOTO_OPCODE(ip)                     @ jump to next instruction
2280
2281
2282 /* ------------------------------ */
2283     .balign 64
2284 .L_OP_APUT_WIDE: /* 0x4c */
2285 /* File: armv4t/OP_APUT_WIDE.S */
2286     /*
2287      * Array put, 64 bits.  vBB[vCC] <- vAA.
2288      */
2289     /* aput-wide vAA, vBB, vCC */
2290     FETCH(r0, 1)                        @ r0<- CCBB
2291     mov     r9, rINST, lsr #8           @ r9<- AA
2292     and     r2, r0, #255                @ r2<- BB
2293     mov     r3, r0, lsr #8              @ r3<- CC
2294     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2295     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2296     cmp     r0, #0                      @ null array object?
2297     beq     common_errNullObject        @ yes, bail
2298     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2299     add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2300     cmp     r1, r3                      @ compare unsigned index, length
2301     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2302     bcc     .LOP_APUT_WIDE_finish          @ okay, continue below
2303     b       common_errArrayIndex        @ index >= length, bail
2304     @ May want to swap the order of these two branches depending on how the
2305     @ branch prediction (if any) handles conditional forward branches vs.
2306     @ unconditional forward branches.
2307
2308 /* ------------------------------ */
2309     .balign 64
2310 .L_OP_APUT_OBJECT: /* 0x4d */
2311 /* File: armv5te/OP_APUT_OBJECT.S */
2312     /*
2313      * Store an object into an array.  vBB[vCC] <- vAA.
2314      *
2315      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2316      * instructions.  We use a pair of FETCH_Bs instead.
2317      */
2318     /* op vAA, vBB, vCC */
2319     FETCH(r0, 1)                        @ r0<- CCBB
2320     mov     r9, rINST, lsr #8           @ r9<- AA
2321     and     r2, r0, #255                @ r2<- BB
2322     mov     r3, r0, lsr #8              @ r3<- CC
2323     GET_VREG(r1, r2)                    @ r1<- vBB (array object)
2324     GET_VREG(r0, r3)                    @ r0<- vCC (requested index)
2325     cmp     r1, #0                      @ null array object?
2326     GET_VREG(r9, r9)                    @ r9<- vAA
2327     beq     common_errNullObject        @ yes, bail
2328     ldr     r3, [r1, #offArrayObject_length]    @ r3<- arrayObj->length
2329     add     r10, r1, r0, lsl #2         @ r10<- arrayObj + index*width
2330     cmp     r0, r3                      @ compare unsigned index, length
2331     bcc     .LOP_APUT_OBJECT_finish          @ we're okay, continue on
2332     b       common_errArrayIndex        @ index >= length, bail
2333
2334
2335 /* ------------------------------ */
2336     .balign 64
2337 .L_OP_APUT_BOOLEAN: /* 0x4e */
2338 /* File: armv5te/OP_APUT_BOOLEAN.S */
2339 /* File: armv5te/OP_APUT.S */
2340     /*
2341      * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2342      *
2343      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2344      * instructions.  We use a pair of FETCH_Bs instead.
2345      *
2346      * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2347      */
2348     /* op vAA, vBB, vCC */
2349     FETCH_B(r2, 1, 0)                   @ r2<- BB
2350     mov     r9, rINST, lsr #8           @ r9<- AA
2351     FETCH_B(r3, 1, 1)                   @ r3<- CC
2352     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2353     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2354     cmp     r0, #0                      @ null array object?
2355     beq     common_errNullObject        @ yes, bail
2356     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2357     add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2358     cmp     r1, r3                      @ compare unsigned index, length
2359     bcs     common_errArrayIndex        @ index >= length, bail
2360     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2361     GET_VREG(r2, r9)                    @ r2<- vAA
2362     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2363     strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2364     GOTO_OPCODE(ip)                     @ jump to next instruction
2365
2366
2367
2368 /* ------------------------------ */
2369     .balign 64
2370 .L_OP_APUT_BYTE: /* 0x4f */
2371 /* File: armv5te/OP_APUT_BYTE.S */
2372 /* File: armv5te/OP_APUT.S */
2373     /*
2374      * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2375      *
2376      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2377      * instructions.  We use a pair of FETCH_Bs instead.
2378      *
2379      * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2380      */
2381     /* op vAA, vBB, vCC */
2382     FETCH_B(r2, 1, 0)                   @ r2<- BB
2383     mov     r9, rINST, lsr #8           @ r9<- AA
2384     FETCH_B(r3, 1, 1)                   @ r3<- CC
2385     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2386     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2387     cmp     r0, #0                      @ null array object?
2388     beq     common_errNullObject        @ yes, bail
2389     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2390     add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2391     cmp     r1, r3                      @ compare unsigned index, length
2392     bcs     common_errArrayIndex        @ index >= length, bail
2393     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2394     GET_VREG(r2, r9)                    @ r2<- vAA
2395     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2396     strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2397     GOTO_OPCODE(ip)                     @ jump to next instruction
2398
2399
2400
2401 /* ------------------------------ */
2402     .balign 64
2403 .L_OP_APUT_CHAR: /* 0x50 */
2404 /* File: armv5te/OP_APUT_CHAR.S */
2405 /* File: armv5te/OP_APUT.S */
2406     /*
2407      * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2408      *
2409      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2410      * instructions.  We use a pair of FETCH_Bs instead.
2411      *
2412      * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2413      */
2414     /* op vAA, vBB, vCC */
2415     FETCH_B(r2, 1, 0)                   @ r2<- BB
2416     mov     r9, rINST, lsr #8           @ r9<- AA
2417     FETCH_B(r3, 1, 1)                   @ r3<- CC
2418     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2419     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2420     cmp     r0, #0                      @ null array object?
2421     beq     common_errNullObject        @ yes, bail
2422     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2423     add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2424     cmp     r1, r3                      @ compare unsigned index, length
2425     bcs     common_errArrayIndex        @ index >= length, bail
2426     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2427     GET_VREG(r2, r9)                    @ r2<- vAA
2428     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2429     strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2430     GOTO_OPCODE(ip)                     @ jump to next instruction
2431
2432
2433
2434 /* ------------------------------ */
2435     .balign 64
2436 .L_OP_APUT_SHORT: /* 0x51 */
2437 /* File: armv5te/OP_APUT_SHORT.S */
2438 /* File: armv5te/OP_APUT.S */
2439     /*
2440      * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2441      *
2442      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2443      * instructions.  We use a pair of FETCH_Bs instead.
2444      *
2445      * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2446      */
2447     /* op vAA, vBB, vCC */
2448     FETCH_B(r2, 1, 0)                   @ r2<- BB
2449     mov     r9, rINST, lsr #8           @ r9<- AA
2450     FETCH_B(r3, 1, 1)                   @ r3<- CC
2451     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2452     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2453     cmp     r0, #0                      @ null array object?
2454     beq     common_errNullObject        @ yes, bail
2455     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2456     add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2457     cmp     r1, r3                      @ compare unsigned index, length
2458     bcs     common_errArrayIndex        @ index >= length, bail
2459     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2460     GET_VREG(r2, r9)                    @ r2<- vAA
2461     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2462     strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2463     GOTO_OPCODE(ip)                     @ jump to next instruction
2464
2465
2466
2467 /* ------------------------------ */
2468     .balign 64
2469 .L_OP_IGET: /* 0x52 */
2470 /* File: armv5te/OP_IGET.S */
2471     /*
2472      * General 32-bit instance field get.
2473      *
2474      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2475      */
2476     /* op vA, vB, field@CCCC */
2477     mov     r0, rINST, lsr #12          @ r0<- B
2478     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2479     FETCH(r1, 1)                        @ r1<- field ref CCCC
2480     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2481     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2482     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2483     cmp     r0, #0                      @ is resolved entry null?
2484     bne     .LOP_IGET_finish          @ no, already resolved
2485 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2486     EXPORT_PC()                         @ resolve() could throw
2487     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2488     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2489     cmp     r0, #0
2490     bne     .LOP_IGET_finish
2491     b       common_exceptionThrown
2492
2493 /* ------------------------------ */
2494     .balign 64
2495 .L_OP_IGET_WIDE: /* 0x53 */
2496 /* File: armv4t/OP_IGET_WIDE.S */
2497     /*
2498      * Wide 32-bit instance field get.
2499      */
2500     /* iget-wide vA, vB, field@CCCC */
2501     mov     r0, rINST, lsr #12          @ r0<- B
2502     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2503     FETCH(r1, 1)                        @ r1<- field ref CCCC
2504     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2505     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2506     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2507     cmp     r0, #0                      @ is resolved entry null?
2508     bne     .LOP_IGET_WIDE_finish          @ no, already resolved
2509 8:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2510     EXPORT_PC()                         @ resolve() could throw
2511     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2512     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2513     cmp     r0, #0
2514     bne     .LOP_IGET_WIDE_finish
2515     b       common_exceptionThrown
2516
2517 /* ------------------------------ */
2518     .balign 64
2519 .L_OP_IGET_OBJECT: /* 0x54 */
2520 /* File: armv5te/OP_IGET_OBJECT.S */
2521 /* File: armv5te/OP_IGET.S */
2522     /*
2523      * General 32-bit instance field get.
2524      *
2525      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2526      */
2527     /* op vA, vB, field@CCCC */
2528     mov     r0, rINST, lsr #12          @ r0<- B
2529     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2530     FETCH(r1, 1)                        @ r1<- field ref CCCC
2531     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2532     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2533     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2534     cmp     r0, #0                      @ is resolved entry null?
2535     bne     .LOP_IGET_OBJECT_finish          @ no, already resolved
2536 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2537     EXPORT_PC()                         @ resolve() could throw
2538     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2539     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2540     cmp     r0, #0
2541     bne     .LOP_IGET_OBJECT_finish
2542     b       common_exceptionThrown
2543
2544
2545 /* ------------------------------ */
2546     .balign 64
2547 .L_OP_IGET_BOOLEAN: /* 0x55 */
2548 /* File: armv5te/OP_IGET_BOOLEAN.S */
2549 @include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" }
2550 /* File: armv5te/OP_IGET.S */
2551     /*
2552      * General 32-bit instance field get.
2553      *
2554      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2555      */
2556     /* op vA, vB, field@CCCC */
2557     mov     r0, rINST, lsr #12          @ r0<- B
2558     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2559     FETCH(r1, 1)                        @ r1<- field ref CCCC
2560     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2561     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2562     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2563     cmp     r0, #0                      @ is resolved entry null?
2564     bne     .LOP_IGET_BOOLEAN_finish          @ no, already resolved
2565 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2566     EXPORT_PC()                         @ resolve() could throw
2567     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2568     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2569     cmp     r0, #0
2570     bne     .LOP_IGET_BOOLEAN_finish
2571     b       common_exceptionThrown
2572
2573
2574 /* ------------------------------ */
2575     .balign 64
2576 .L_OP_IGET_BYTE: /* 0x56 */
2577 /* File: armv5te/OP_IGET_BYTE.S */
2578 @include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" }
2579 /* File: armv5te/OP_IGET.S */
2580     /*
2581      * General 32-bit instance field get.
2582      *
2583      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2584      */
2585     /* op vA, vB, field@CCCC */
2586     mov     r0, rINST, lsr #12          @ r0<- B
2587     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2588     FETCH(r1, 1)                        @ r1<- field ref CCCC
2589     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2590     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2591     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2592     cmp     r0, #0                      @ is resolved entry null?
2593     bne     .LOP_IGET_BYTE_finish          @ no, already resolved
2594 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2595     EXPORT_PC()                         @ resolve() could throw
2596     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2597     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2598     cmp     r0, #0
2599     bne     .LOP_IGET_BYTE_finish
2600     b       common_exceptionThrown
2601
2602
2603 /* ------------------------------ */
2604     .balign 64
2605 .L_OP_IGET_CHAR: /* 0x57 */
2606 /* File: armv5te/OP_IGET_CHAR.S */
2607 @include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" }
2608 /* File: armv5te/OP_IGET.S */
2609     /*
2610      * General 32-bit instance field get.
2611      *
2612      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2613      */
2614     /* op vA, vB, field@CCCC */
2615     mov     r0, rINST, lsr #12          @ r0<- B
2616     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2617     FETCH(r1, 1)                        @ r1<- field ref CCCC
2618     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2619     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2620     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2621     cmp     r0, #0                      @ is resolved entry null?
2622     bne     .LOP_IGET_CHAR_finish          @ no, already resolved
2623 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2624     EXPORT_PC()                         @ resolve() could throw
2625     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2626     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2627     cmp     r0, #0
2628     bne     .LOP_IGET_CHAR_finish
2629     b       common_exceptionThrown
2630
2631
2632 /* ------------------------------ */
2633     .balign 64
2634 .L_OP_IGET_SHORT: /* 0x58 */
2635 /* File: armv5te/OP_IGET_SHORT.S */
2636 @include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" }
2637 /* File: armv5te/OP_IGET.S */
2638     /*
2639      * General 32-bit instance field get.
2640      *
2641      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2642      */
2643     /* op vA, vB, field@CCCC */
2644     mov     r0, rINST, lsr #12          @ r0<- B
2645     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2646     FETCH(r1, 1)                        @ r1<- field ref CCCC
2647     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2648     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2649     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2650     cmp     r0, #0                      @ is resolved entry null?
2651     bne     .LOP_IGET_SHORT_finish          @ no, already resolved
2652 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2653     EXPORT_PC()                         @ resolve() could throw
2654     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2655     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2656     cmp     r0, #0
2657     bne     .LOP_IGET_SHORT_finish
2658     b       common_exceptionThrown
2659
2660
2661 /* ------------------------------ */
2662     .balign 64
2663 .L_OP_IPUT: /* 0x59 */
2664 /* File: armv5te/OP_IPUT.S */
2665     /*
2666      * General 32-bit instance field put.
2667      *
2668      * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2669      */
2670     /* op vA, vB, field@CCCC */
2671     mov     r0, rINST, lsr #12          @ r0<- B
2672     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2673     FETCH(r1, 1)                        @ r1<- field ref CCCC
2674     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2675     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2676     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2677     cmp     r0, #0                      @ is resolved entry null?
2678     bne     .LOP_IPUT_finish          @ no, already resolved
2679 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2680     EXPORT_PC()                         @ resolve() could throw
2681     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2682     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2683     cmp     r0, #0                      @ success?
2684     bne     .LOP_IPUT_finish          @ yes, finish up
2685     b       common_exceptionThrown
2686
2687 /* ------------------------------ */
2688     .balign 64
2689 .L_OP_IPUT_WIDE: /* 0x5a */
2690 /* File: armv4t/OP_IPUT_WIDE.S */
2691     /* iput-wide vA, vB, field@CCCC */
2692     mov     r0, rINST, lsr #12          @ r0<- B
2693     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2694     FETCH(r1, 1)                        @ r1<- field ref CCCC
2695     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2696     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2697     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2698     cmp     r0, #0                      @ is resolved entry null?
2699     bne     .LOP_IPUT_WIDE_finish          @ no, already resolved
2700 8:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2701     EXPORT_PC()                         @ resolve() could throw
2702     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2703     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2704     cmp     r0, #0                      @ success?
2705     bne     .LOP_IPUT_WIDE_finish          @ yes, finish up
2706     b       common_exceptionThrown
2707
2708 /* ------------------------------ */
2709     .balign 64
2710 .L_OP_IPUT_OBJECT: /* 0x5b */
2711 /* File: armv5te/OP_IPUT_OBJECT.S */
2712 /* File: armv5te/OP_IPUT.S */
2713     /*
2714      * General 32-bit instance field put.
2715      *
2716      * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2717      */
2718     /* op vA, vB, field@CCCC */
2719     mov     r0, rINST, lsr #12          @ r0<- B
2720     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2721     FETCH(r1, 1)                        @ r1<- field ref CCCC
2722     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2723     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2724     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2725     cmp     r0, #0                      @ is resolved entry null?
2726     bne     .LOP_IPUT_OBJECT_finish          @ no, already resolved
2727 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2728     EXPORT_PC()                         @ resolve() could throw
2729     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2730     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2731     cmp     r0, #0                      @ success?
2732     bne     .LOP_IPUT_OBJECT_finish          @ yes, finish up
2733     b       common_exceptionThrown
2734
2735
2736 /* ------------------------------ */
2737     .balign 64
2738 .L_OP_IPUT_BOOLEAN: /* 0x5c */
2739 /* File: armv5te/OP_IPUT_BOOLEAN.S */
2740 @include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" }
2741 /* File: armv5te/OP_IPUT.S */
2742     /*
2743      * General 32-bit instance field put.
2744      *
2745      * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2746      */
2747     /* op vA, vB, field@CCCC */
2748     mov     r0, rINST, lsr #12          @ r0<- B
2749     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2750     FETCH(r1, 1)                        @ r1<- field ref CCCC
2751     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2752     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2753     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2754     cmp     r0, #0                      @ is resolved entry null?
2755     bne     .LOP_IPUT_BOOLEAN_finish          @ no, already resolved
2756 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2757     EXPORT_PC()                         @ resolve() could throw
2758     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2759     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2760     cmp     r0, #0                      @ success?
2761     bne     .LOP_IPUT_BOOLEAN_finish          @ yes, finish up
2762     b       common_exceptionThrown
2763
2764
2765 /* ------------------------------ */
2766     .balign 64
2767 .L_OP_IPUT_BYTE: /* 0x5d */
2768 /* File: armv5te/OP_IPUT_BYTE.S */
2769 @include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" }
2770 /* File: armv5te/OP_IPUT.S */
2771     /*
2772      * General 32-bit instance field put.
2773      *
2774      * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2775      */
2776     /* op vA, vB, field@CCCC */
2777     mov     r0, rINST, lsr #12          @ r0<- B
2778     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2779     FETCH(r1, 1)                        @ r1<- field ref CCCC
2780     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2781     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2782     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2783     cmp     r0, #0                      @ is resolved entry null?
2784     bne     .LOP_IPUT_BYTE_finish          @ no, already resolved
2785 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2786     EXPORT_PC()                         @ resolve() could throw
2787     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2788     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2789     cmp     r0, #0                      @ success?
2790     bne     .LOP_IPUT_BYTE_finish          @ yes, finish up
2791     b       common_exceptionThrown
2792
2793
2794 /* ------------------------------ */
2795     .balign 64
2796 .L_OP_IPUT_CHAR: /* 0x5e */
2797 /* File: armv5te/OP_IPUT_CHAR.S */
2798 @include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" }
2799 /* File: armv5te/OP_IPUT.S */
2800     /*
2801      * General 32-bit instance field put.
2802      *
2803      * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2804      */
2805     /* op vA, vB, field@CCCC */
2806     mov     r0, rINST, lsr #12          @ r0<- B
2807     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2808     FETCH(r1, 1)                        @ r1<- field ref CCCC
2809     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2810     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2811     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2812     cmp     r0, #0                      @ is resolved entry null?
2813     bne     .LOP_IPUT_CHAR_finish          @ no, already resolved
2814 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2815     EXPORT_PC()                         @ resolve() could throw
2816     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2817     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2818     cmp     r0, #0                      @ success?
2819     bne     .LOP_IPUT_CHAR_finish          @ yes, finish up
2820     b       common_exceptionThrown
2821
2822
2823 /* ------------------------------ */
2824     .balign 64
2825 .L_OP_IPUT_SHORT: /* 0x5f */
2826 /* File: armv5te/OP_IPUT_SHORT.S */
2827 @include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" }
2828 /* File: armv5te/OP_IPUT.S */
2829     /*
2830      * General 32-bit instance field put.
2831      *
2832      * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2833      */
2834     /* op vA, vB, field@CCCC */
2835     mov     r0, rINST, lsr #12          @ r0<- B
2836     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2837     FETCH(r1, 1)                        @ r1<- field ref CCCC
2838     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2839     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2840     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2841     cmp     r0, #0                      @ is resolved entry null?
2842     bne     .LOP_IPUT_SHORT_finish          @ no, already resolved
2843 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2844     EXPORT_PC()                         @ resolve() could throw
2845     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2846     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2847     cmp     r0, #0                      @ success?
2848     bne     .LOP_IPUT_SHORT_finish          @ yes, finish up
2849     b       common_exceptionThrown
2850
2851
2852 /* ------------------------------ */
2853     .balign 64
2854 .L_OP_SGET: /* 0x60 */
2855 /* File: armv5te/OP_SGET.S */
2856     /*
2857      * General 32-bit SGET handler.
2858      *
2859      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2860      */
2861     /* op vAA, field@BBBB */
2862     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2863     FETCH(r1, 1)                        @ r1<- field ref BBBB
2864     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2865     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2866     cmp     r0, #0                      @ is resolved entry null?
2867     beq     .LOP_SGET_resolve         @ yes, do resolve
2868 .LOP_SGET_finish: @ field ptr in r0
2869     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2870     mov     r2, rINST, lsr #8           @ r2<- AA
2871     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2872     SET_VREG(r1, r2)                    @ fp[AA]<- r1
2873     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2874     GOTO_OPCODE(ip)                     @ jump to next instruction
2875
2876 /* ------------------------------ */
2877     .balign 64
2878 .L_OP_SGET_WIDE: /* 0x61 */
2879 /* File: armv4t/OP_SGET_WIDE.S */
2880     /*
2881      * 64-bit SGET handler.
2882      */
2883     /* sget-wide vAA, field@BBBB */
2884     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2885     FETCH(r1, 1)                        @ r1<- field ref BBBB
2886     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2887     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2888     cmp     r0, #0                      @ is resolved entry null?
2889     beq     .LOP_SGET_WIDE_resolve         @ yes, do resolve
2890 .LOP_SGET_WIDE_finish:
2891     mov     r1, rINST, lsr #8           @ r1<- AA
2892     add     r0, r0, #offStaticField_value
2893     ldmia   r0, {r2-r3}                 @ r2/r3<- field value (aligned)
2894     add     r1, rFP, r1, lsl #2         @ r1<- &fp[AA]
2895     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2896     stmia   r1, {r2-r3}                 @ vAA/vAA+1<- r2/r3
2897     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2898     GOTO_OPCODE(ip)                     @ jump to next instruction
2899
2900 /* ------------------------------ */
2901     .balign 64
2902 .L_OP_SGET_OBJECT: /* 0x62 */
2903 /* File: armv5te/OP_SGET_OBJECT.S */
2904 /* File: armv5te/OP_SGET.S */
2905     /*
2906      * General 32-bit SGET handler.
2907      *
2908      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2909      */
2910     /* op vAA, field@BBBB */
2911     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2912     FETCH(r1, 1)                        @ r1<- field ref BBBB
2913     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2914     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2915     cmp     r0, #0                      @ is resolved entry null?
2916     beq     .LOP_SGET_OBJECT_resolve         @ yes, do resolve
2917 .LOP_SGET_OBJECT_finish: @ field ptr in r0
2918     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2919     mov     r2, rINST, lsr #8           @ r2<- AA
2920     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2921     SET_VREG(r1, r2)                    @ fp[AA]<- r1
2922     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2923     GOTO_OPCODE(ip)                     @ jump to next instruction
2924
2925
2926 /* ------------------------------ */
2927     .balign 64
2928 .L_OP_SGET_BOOLEAN: /* 0x63 */
2929 /* File: armv5te/OP_SGET_BOOLEAN.S */
2930 /* File: armv5te/OP_SGET.S */
2931     /*
2932      * General 32-bit SGET handler.
2933      *
2934      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2935      */
2936     /* op vAA, field@BBBB */
2937     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2938     FETCH(r1, 1)                        @ r1<- field ref BBBB
2939     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2940     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2941     cmp     r0, #0                      @ is resolved entry null?
2942     beq     .LOP_SGET_BOOLEAN_resolve         @ yes, do resolve
2943 .LOP_SGET_BOOLEAN_finish: @ field ptr in r0
2944     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2945     mov     r2, rINST, lsr #8           @ r2<- AA
2946     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2947     SET_VREG(r1, r2)                    @ fp[AA]<- r1
2948     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2949     GOTO_OPCODE(ip)                     @ jump to next instruction
2950
2951
2952 /* ------------------------------ */
2953     .balign 64
2954 .L_OP_SGET_BYTE: /* 0x64 */
2955 /* File: armv5te/OP_SGET_BYTE.S */
2956 /* File: armv5te/OP_SGET.S */
2957     /*
2958      * General 32-bit SGET handler.
2959      *
2960      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2961      */
2962     /* op vAA, field@BBBB */
2963     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2964     FETCH(r1, 1)                        @ r1<- field ref BBBB
2965     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2966     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2967     cmp     r0, #0                      @ is resolved entry null?
2968     beq     .LOP_SGET_BYTE_resolve         @ yes, do resolve
2969 .LOP_SGET_BYTE_finish: @ field ptr in r0
2970     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2971     mov     r2, rINST, lsr #8           @ r2<- AA
2972     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2973     SET_VREG(r1, r2)                    @ fp[AA]<- r1
2974     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2975     GOTO_OPCODE(ip)                     @ jump to next instruction
2976
2977
2978 /* ------------------------------ */
2979     .balign 64
2980 .L_OP_SGET_CHAR: /* 0x65 */
2981 /* File: armv5te/OP_SGET_CHAR.S */
2982 /* File: armv5te/OP_SGET.S */
2983     /*
2984      * General 32-bit SGET handler.
2985      *
2986      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2987      */
2988     /* op vAA, field@BBBB */
2989     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2990     FETCH(r1, 1)                        @ r1<- field ref BBBB
2991     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2992     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2993     cmp     r0, #0                      @ is resolved entry null?
2994     beq     .LOP_SGET_CHAR_resolve         @ yes, do resolve
2995 .LOP_SGET_CHAR_finish: @ field ptr in r0
2996     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2997     mov     r2, rINST, lsr #8           @ r2<- AA
2998     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2999     SET_VREG(r1, r2)                    @ fp[AA]<- r1
3000     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3001     GOTO_OPCODE(ip)                     @ jump to next instruction
3002
3003
3004 /* ------------------------------ */
3005     .balign 64
3006 .L_OP_SGET_SHORT: /* 0x66 */
3007 /* File: armv5te/OP_SGET_SHORT.S */
3008 /* File: armv5te/OP_SGET.S */
3009     /*
3010      * General 32-bit SGET handler.
3011      *
3012      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
3013      */
3014     /* op vAA, field@BBBB */
3015     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3016     FETCH(r1, 1)                        @ r1<- field ref BBBB
3017     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3018     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3019     cmp     r0, #0                      @ is resolved entry null?
3020     beq     .LOP_SGET_SHORT_resolve         @ yes, do resolve
3021 .LOP_SGET_SHORT_finish: @ field ptr in r0
3022     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
3023     mov     r2, rINST, lsr #8           @ r2<- AA
3024     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3025     SET_VREG(r1, r2)                    @ fp[AA]<- r1
3026     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3027     GOTO_OPCODE(ip)                     @ jump to next instruction
3028
3029
3030 /* ------------------------------ */
3031     .balign 64
3032 .L_OP_SPUT: /* 0x67 */
3033 /* File: armv5te/OP_SPUT.S */
3034     /*
3035      * General 32-bit SPUT handler.
3036      *
3037      * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3038      */
3039     /* op vAA, field@BBBB */
3040     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3041     FETCH(r1, 1)                        @ r1<- field ref BBBB
3042     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3043     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3044     cmp     r0, #0                      @ is resolved entry null?
3045     beq     .LOP_SPUT_resolve         @ yes, do resolve
3046 .LOP_SPUT_finish:   @ field ptr in r0
3047     mov     r2, rINST, lsr #8           @ r2<- AA
3048     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3049     GET_VREG(r1, r2)                    @ r1<- fp[AA]
3050     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3051     str     r1, [r0, #offStaticField_value] @ field<- vAA
3052     GOTO_OPCODE(ip)                     @ jump to next instruction
3053
3054 /* ------------------------------ */
3055     .balign 64
3056 .L_OP_SPUT_WIDE: /* 0x68 */
3057 /* File: armv4t/OP_SPUT_WIDE.S */
3058     /*
3059      * 64-bit SPUT handler.
3060      */
3061     /* sput-wide vAA, field@BBBB */
3062     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3063     FETCH(r1, 1)                        @ r1<- field ref BBBB
3064     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3065     mov     r9, rINST, lsr #8           @ r9<- AA
3066     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3067     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
3068     cmp     r0, #0                      @ is resolved entry null?
3069     beq     .LOP_SPUT_WIDE_resolve         @ yes, do resolve
3070 .LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9
3071     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3072     ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
3073     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3074     add     r0, r0, #offStaticField_value
3075     stmia   r0, {r2-r3}                 @ field<- vAA/vAA+1
3076     GOTO_OPCODE(ip)                     @ jump to next instruction
3077
3078 /* ------------------------------ */
3079     .balign 64
3080 .L_OP_SPUT_OBJECT: /* 0x69 */
3081 /* File: armv5te/OP_SPUT_OBJECT.S */
3082 /* File: armv5te/OP_SPUT.S */
3083     /*
3084      * General 32-bit SPUT handler.
3085      *
3086      * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3087      */
3088     /* op vAA, field@BBBB */
3089     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3090     FETCH(r1, 1)                        @ r1<- field ref BBBB
3091     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3092     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3093     cmp     r0, #0                      @ is resolved entry null?
3094     beq     .LOP_SPUT_OBJECT_resolve         @ yes, do resolve
3095 .LOP_SPUT_OBJECT_finish:   @ field ptr in r0
3096     mov     r2, rINST, lsr #8           @ r2<- AA
3097     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3098     GET_VREG(r1, r2)                    @ r1<- fp[AA]
3099     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3100     str     r1, [r0, #offStaticField_value] @ field<- vAA
3101     GOTO_OPCODE(ip)                     @ jump to next instruction
3102
3103
3104 /* ------------------------------ */
3105     .balign 64
3106 .L_OP_SPUT_BOOLEAN: /* 0x6a */
3107 /* File: armv5te/OP_SPUT_BOOLEAN.S */
3108 /* File: armv5te/OP_SPUT.S */
3109     /*
3110      * General 32-bit SPUT handler.
3111      *
3112      * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3113      */
3114     /* op vAA, field@BBBB */
3115     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3116     FETCH(r1, 1)                        @ r1<- field ref BBBB
3117     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3118     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3119     cmp     r0, #0                      @ is resolved entry null?
3120     beq     .LOP_SPUT_BOOLEAN_resolve         @ yes, do resolve
3121 .LOP_SPUT_BOOLEAN_finish:   @ field ptr in r0
3122     mov     r2, rINST, lsr #8           @ r2<- AA
3123     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3124     GET_VREG(r1, r2)                    @ r1<- fp[AA]
3125     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3126     str     r1, [r0, #offStaticField_value] @ field<- vAA
3127     GOTO_OPCODE(ip)                     @ jump to next instruction
3128
3129
3130 /* ------------------------------ */
3131     .balign 64
3132 .L_OP_SPUT_BYTE: /* 0x6b */
3133 /* File: armv5te/OP_SPUT_BYTE.S */
3134 /* File: armv5te/OP_SPUT.S */
3135     /*
3136      * General 32-bit SPUT handler.
3137      *
3138      * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3139      */
3140     /* op vAA, field@BBBB */
3141     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3142     FETCH(r1, 1)                        @ r1<- field ref BBBB
3143     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3144     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3145     cmp     r0, #0                      @ is resolved entry null?
3146     beq     .LOP_SPUT_BYTE_resolve         @ yes, do resolve
3147 .LOP_SPUT_BYTE_finish:   @ field ptr in r0
3148     mov     r2, rINST, lsr #8           @ r2<- AA
3149     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3150     GET_VREG(r1, r2)                    @ r1<- fp[AA]
3151     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3152     str     r1, [r0, #offStaticField_value] @ field<- vAA
3153     GOTO_OPCODE(ip)                     @ jump to next instruction
3154
3155
3156 /* ------------------------------ */
3157     .balign 64
3158 .L_OP_SPUT_CHAR: /* 0x6c */
3159 /* File: armv5te/OP_SPUT_CHAR.S */
3160 /* File: armv5te/OP_SPUT.S */
3161     /*
3162      * General 32-bit SPUT handler.
3163      *
3164      * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3165      */
3166     /* op vAA, field@BBBB */
3167     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3168     FETCH(r1, 1)                        @ r1<- field ref BBBB
3169     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3170     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3171     cmp     r0, #0                      @ is resolved entry null?
3172     beq     .LOP_SPUT_CHAR_resolve         @ yes, do resolve
3173 .LOP_SPUT_CHAR_finish:   @ field ptr in r0
3174     mov     r2, rINST, lsr #8           @ r2<- AA
3175     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3176     GET_VREG(r1, r2)                    @ r1<- fp[AA]
3177     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3178     str     r1, [r0, #offStaticField_value] @ field<- vAA
3179     GOTO_OPCODE(ip)                     @ jump to next instruction
3180
3181
3182 /* ------------------------------ */
3183     .balign 64
3184 .L_OP_SPUT_SHORT: /* 0x6d */
3185 /* File: armv5te/OP_SPUT_SHORT.S */
3186 /* File: armv5te/OP_SPUT.S */
3187     /*
3188      * General 32-bit SPUT handler.
3189      *
3190      * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3191      */
3192     /* op vAA, field@BBBB */
3193     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3194     FETCH(r1, 1)                        @ r1<- field ref BBBB
3195     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3196     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3197     cmp     r0, #0                      @ is resolved entry null?
3198     beq     .LOP_SPUT_SHORT_resolve         @ yes, do resolve
3199 .LOP_SPUT_SHORT_finish:   @ field ptr in r0
3200     mov     r2, rINST, lsr #8           @ r2<- AA
3201     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3202     GET_VREG(r1, r2)                    @ r1<- fp[AA]
3203     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3204     str     r1, [r0, #offStaticField_value] @ field<- vAA
3205     GOTO_OPCODE(ip)                     @ jump to next instruction
3206
3207
3208 /* ------------------------------ */
3209     .balign 64
3210 .L_OP_INVOKE_VIRTUAL: /* 0x6e */
3211 /* File: armv5te/OP_INVOKE_VIRTUAL.S */
3212     /*
3213      * Handle a virtual method call.
3214      *
3215      * for: invoke-virtual, invoke-virtual/range
3216      */
3217     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3218     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3219     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3220     FETCH(r1, 1)                        @ r1<- BBBB
3221     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3222     FETCH(r10, 2)                       @ r10<- GFED or CCCC
3223     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3224     .if     (!0)
3225     and     r10, r10, #15               @ r10<- D (or stays CCCC)
3226     .endif
3227     cmp     r0, #0                      @ already resolved?
3228     EXPORT_PC()                         @ must export for invoke
3229     bne     .LOP_INVOKE_VIRTUAL_continue        @ yes, continue on
3230     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3231     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3232     mov     r2, #METHOD_VIRTUAL         @ resolver method type
3233     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3234     cmp     r0, #0                      @ got null?
3235     bne     .LOP_INVOKE_VIRTUAL_continue        @ no, continue
3236     b       common_exceptionThrown      @ yes, handle exception
3237
3238 /* ------------------------------ */
3239     .balign 64
3240 .L_OP_INVOKE_SUPER: /* 0x6f */
3241 /* File: armv5te/OP_INVOKE_SUPER.S */
3242     /*
3243      * Handle a "super" method call.
3244      *
3245      * for: invoke-super, invoke-super/range
3246      */
3247     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3248     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3249     FETCH(r10, 2)                       @ r10<- GFED or CCCC
3250     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3251     .if     (!0)
3252     and     r10, r10, #15               @ r10<- D (or stays CCCC)
3253     .endif
3254     FETCH(r1, 1)                        @ r1<- BBBB
3255     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3256     GET_VREG(r2, r10)                   @ r2<- "this" ptr
3257     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3258     cmp     r2, #0                      @ null "this"?
3259     ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3260     beq     common_errNullObject        @ null "this", throw exception
3261     cmp     r0, #0                      @ already resolved?
3262     ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3263     EXPORT_PC()                         @ must export for invoke
3264     bne     .LOP_INVOKE_SUPER_continue        @ resolved, continue on
3265     b       .LOP_INVOKE_SUPER_resolve         @ do resolve now
3266
3267 /* ------------------------------ */
3268     .balign 64
3269 .L_OP_INVOKE_DIRECT: /* 0x70 */
3270 /* File: armv5te/OP_INVOKE_DIRECT.S */
3271     /*
3272      * Handle a direct method call.
3273      *
3274      * (We could defer the "is 'this' pointer null" test to the common
3275      * method invocation code, and use a flag to indicate that static
3276      * calls don't count.  If we do this as part of copying the arguments
3277      * out we could avoiding loading the first arg twice.)
3278      *
3279      * for: invoke-direct, invoke-direct/range
3280      */
3281     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3282     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3283     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3284     FETCH(r1, 1)                        @ r1<- BBBB
3285     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3286     FETCH(r10, 2)                       @ r10<- GFED or CCCC
3287     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3288     .if     (!0)
3289     and     r10, r10, #15               @ r10<- D (or stays CCCC)
3290     .endif
3291     cmp     r0, #0                      @ already resolved?
3292     EXPORT_PC()                         @ must export for invoke
3293     GET_VREG(r2, r10)                   @ r2<- "this" ptr
3294     beq     .LOP_INVOKE_DIRECT_resolve         @ not resolved, do it now
3295 .LOP_INVOKE_DIRECT_finish:
3296     cmp     r2, #0                      @ null "this" ref?
3297     bne     common_invokeMethodNoRange   @ no, continue on
3298     b       common_errNullObject        @ yes, throw exception
3299
3300 /* ------------------------------ */
3301     .balign 64
3302 .L_OP_INVOKE_STATIC: /* 0x71 */
3303 /* File: armv5te/OP_INVOKE_STATIC.S */
3304     /*
3305      * Handle a static method call.
3306      *
3307      * for: invoke-static, invoke-static/range
3308      */
3309     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3310     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3311     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3312     FETCH(r1, 1)                        @ r1<- BBBB
3313     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3314     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3315     cmp     r0, #0                      @ already resolved?
3316     EXPORT_PC()                         @ must export for invoke
3317     bne     common_invokeMethodNoRange @ yes, continue on
3318 0:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3319     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3320     mov     r2, #METHOD_STATIC          @ resolver method type
3321     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3322     cmp     r0, #0                      @ got null?
3323     bne     common_invokeMethodNoRange @ no, continue
3324     b       common_exceptionThrown      @ yes, handle exception
3325
3326
3327 /* ------------------------------ */
3328     .balign 64
3329 .L_OP_INVOKE_INTERFACE: /* 0x72 */
3330 /* File: armv5te/OP_INVOKE_INTERFACE.S */
3331     /*
3332      * Handle an interface method call.
3333      *
3334      * for: invoke-interface, invoke-interface/range
3335      */
3336     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3337     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3338     FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3339     FETCH(r1, 1)                        @ r1<- BBBB
3340     .if     (!0)
3341     and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3342     .endif
3343     EXPORT_PC()                         @ must export for invoke
3344     GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3345     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3346     cmp     r0, #0                      @ null obj?
3347     ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3348     beq     common_errNullObject        @ yes, fail
3349     ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3350     bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3351     cmp     r0, #0                      @ failed?
3352     beq     common_exceptionThrown      @ yes, handle exception
3353     b       common_invokeMethodNoRange @ jump to common handler 
3354
3355
3356 /* ------------------------------ */
3357     .balign 64
3358 .L_OP_UNUSED_73: /* 0x73 */
3359 /* File: armv5te/OP_UNUSED_73.S */
3360 /* File: armv5te/unused.S */
3361     bl      common_abort
3362
3363
3364
3365 /* ------------------------------ */
3366     .balign 64
3367 .L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
3368 /* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */
3369 /* File: armv5te/OP_INVOKE_VIRTUAL.S */
3370     /*
3371      * Handle a virtual method call.
3372      *
3373      * for: invoke-virtual, invoke-virtual/range
3374      */
3375     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3376     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3377     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3378     FETCH(r1, 1)                        @ r1<- BBBB
3379     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3380     FETCH(r10, 2)                       @ r10<- GFED or CCCC
3381     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3382     .if     (!1)
3383     and     r10, r10, #15               @ r10<- D (or stays CCCC)
3384     .endif
3385     cmp     r0, #0                      @ already resolved?
3386     EXPORT_PC()                         @ must export for invoke
3387     bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ yes, continue on
3388     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3389     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3390     mov     r2, #METHOD_VIRTUAL         @ resolver method type
3391     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3392     cmp     r0, #0                      @ got null?
3393     bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ no, continue
3394     b       common_exceptionThrown      @ yes, handle exception
3395
3396
3397 /* ------------------------------ */
3398     .balign 64
3399 .L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
3400 /* File: armv5te/OP_INVOKE_SUPER_RANGE.S */
3401 /* File: armv5te/OP_INVOKE_SUPER.S */
3402     /*
3403      * Handle a "super" method call.
3404      *
3405      * for: invoke-super, invoke-super/range
3406      */
3407     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3408     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3409     FETCH(r10, 2)                       @ r10<- GFED or CCCC
3410     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3411     .if     (!1)
3412     and     r10, r10, #15               @ r10<- D (or stays CCCC)
3413     .endif
3414     FETCH(r1, 1)                        @ r1<- BBBB
3415     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3416     GET_VREG(r2, r10)                   @ r2<- "this" ptr
3417     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3418     cmp     r2, #0                      @ null "this"?
3419     ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3420     beq     common_errNullObject        @ null "this", throw exception
3421     cmp     r0, #0                      @ already resolved?
3422     ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3423     EXPORT_PC()                         @ must export for invoke
3424     bne     .LOP_INVOKE_SUPER_RANGE_continue        @ resolved, continue on
3425     b       .LOP_INVOKE_SUPER_RANGE_resolve         @ do resolve now
3426
3427
3428 /* ------------------------------ */
3429     .balign 64
3430 .L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
3431 /* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */
3432 /* File: armv5te/OP_INVOKE_DIRECT.S */
3433     /*
3434      * Handle a direct method call.
3435      *
3436      * (We could defer the "is 'this' pointer null" test to the common
3437      * method invocation code, and use a flag to indicate that static
3438      * calls don't count.  If we do this as part of copying the arguments
3439      * out we could avoiding loading the first arg twice.)
3440      *
3441      * for: invoke-direct, invoke-direct/range
3442      */
3443     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3444     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3445     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3446     FETCH(r1, 1)                        @ r1<- BBBB
3447     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3448     FETCH(r10, 2)                       @ r10<- GFED or CCCC
3449     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3450     .if     (!1)
3451     and     r10, r10, #15               @ r10<- D (or stays CCCC)
3452     .endif
3453     cmp     r0, #0                      @ already resolved?
3454     EXPORT_PC()                         @ must export for invoke
3455     GET_VREG(r2, r10)                   @ r2<- "this" ptr
3456     beq     .LOP_INVOKE_DIRECT_RANGE_resolve         @ not resolved, do it now
3457 .LOP_INVOKE_DIRECT_RANGE_finish:
3458     cmp     r2, #0                      @ null "this" ref?
3459     bne     common_invokeMethodRange   @ no, continue on
3460     b       common_errNullObject        @ yes, throw exception
3461
3462
3463 /* ------------------------------ */
3464     .balign 64
3465 .L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
3466 /* File: armv5te/OP_INVOKE_STATIC_RANGE.S */
3467 /* File: armv5te/OP_INVOKE_STATIC.S */
3468     /*
3469      * Handle a static method call.
3470      *
3471      * for: invoke-static, invoke-static/range
3472      */
3473     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3474     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3475     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3476     FETCH(r1, 1)                        @ r1<- BBBB
3477     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3478     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3479     cmp     r0, #0                      @ already resolved?
3480     EXPORT_PC()                         @ must export for invoke
3481     bne     common_invokeMethodRange @ yes, continue on
3482 0:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3483     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3484     mov     r2, #METHOD_STATIC          @ resolver method type
3485     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3486     cmp     r0, #0                      @ got null?
3487     bne     common_invokeMethodRange @ no, continue
3488     b       common_exceptionThrown      @ yes, handle exception
3489
3490
3491
3492 /* ------------------------------ */
3493     .balign 64
3494 .L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
3495 /* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */
3496 /* File: armv5te/OP_INVOKE_INTERFACE.S */
3497     /*
3498      * Handle an interface method call.
3499      *
3500      * for: invoke-interface, invoke-interface/range
3501      */
3502     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3503     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3504     FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3505     FETCH(r1, 1)                        @ r1<- BBBB
3506     .if     (!1)
3507     and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3508     .endif
3509     EXPORT_PC()                         @ must export for invoke
3510     GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3511     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3512     cmp     r0, #0                      @ null obj?
3513     ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3514     beq     common_errNullObject        @ yes, fail
3515     ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3516     bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3517     cmp     r0, #0                      @ failed?
3518     beq     common_exceptionThrown      @ yes, handle exception
3519     b       common_invokeMethodRange @ jump to common handler 
3520
3521
3522
3523 /* ------------------------------ */
3524     .balign 64
3525 .L_OP_UNUSED_79: /* 0x79 */
3526 /* File: armv5te/OP_UNUSED_79.S */
3527 /* File: armv5te/unused.S */
3528     bl      common_abort
3529
3530
3531
3532 /* ------------------------------ */
3533     .balign 64
3534 .L_OP_UNUSED_7A: /* 0x7a */
3535 /* File: armv5te/OP_UNUSED_7A.S */
3536 /* File: armv5te/unused.S */
3537     bl      common_abort
3538
3539
3540
3541 /* ------------------------------ */
3542     .balign 64
3543 .L_OP_NEG_INT: /* 0x7b */
3544 /* File: armv5te/OP_NEG_INT.S */
3545 /* File: armv5te/unop.S */
3546     /*
3547      * Generic 32-bit unary operation.  Provide an "instr" line that
3548      * specifies an instruction that performs "result = op r0".
3549      * This could be an ARM instruction or a function call.
3550      *
3551      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3552      *      int-to-byte, int-to-char, int-to-short
3553      */
3554     /* unop vA, vB */
3555     mov     r3, rINST, lsr #12          @ r3<- B
3556     mov     r9, rINST, lsr #8           @ r9<- A+
3557     GET_VREG(r0, r3)                    @ r0<- vB
3558     and     r9, r9, #15
3559                                @ optional op; may set condition codes
3560     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3561     rsb     r0, r0, #0                              @ r0<- op, r0-r3 changed
3562     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3563     SET_VREG(r0, r9)                    @ vAA<- r0
3564     GOTO_OPCODE(ip)                     @ jump to next instruction
3565     /* 9-10 instructions */
3566
3567
3568 /* ------------------------------ */
3569     .balign 64
3570 .L_OP_NOT_INT: /* 0x7c */
3571 /* File: armv5te/OP_NOT_INT.S */
3572 /* File: armv5te/unop.S */
3573     /*
3574      * Generic 32-bit unary operation.  Provide an "instr" line that
3575      * specifies an instruction that performs "result = op r0".
3576      * This could be an ARM instruction or a function call.
3577      *
3578      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3579      *      int-to-byte, int-to-char, int-to-short
3580      */
3581     /* unop vA, vB */
3582     mov     r3, rINST, lsr #12          @ r3<- B
3583     mov     r9, rINST, lsr #8           @ r9<- A+
3584     GET_VREG(r0, r3)                    @ r0<- vB
3585     and     r9, r9, #15
3586                                @ optional op; may set condition codes
3587     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3588     mvn     r0, r0                              @ r0<- op, r0-r3 changed
3589     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3590     SET_VREG(r0, r9)                    @ vAA<- r0
3591     GOTO_OPCODE(ip)                     @ jump to next instruction
3592     /* 9-10 instructions */
3593
3594
3595 /* ------------------------------ */
3596     .balign 64
3597 .L_OP_NEG_LONG: /* 0x7d */
3598 /* File: armv5te/OP_NEG_LONG.S */
3599 /* File: armv5te/unopWide.S */
3600     /*
3601      * Generic 64-bit unary operation.  Provide an "instr" line that
3602      * specifies an instruction that performs "result = op r0/r1".
3603      * This could be an ARM instruction or a function call.
3604      *
3605      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3606      */
3607     /* unop vA, vB */
3608     mov     r9, rINST, lsr #8           @ r9<- A+
3609     mov     r3, rINST, lsr #12          @ r3<- B
3610     and     r9, r9, #15
3611     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3612     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3613     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3614     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3615     rsbs    r0, r0, #0                           @ optional op; may set condition codes
3616     rsc     r1, r1, #0                              @ r0/r1<- op, r2-r3 changed
3617     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3618     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3619     GOTO_OPCODE(ip)                     @ jump to next instruction
3620     /* 12-13 instructions */
3621
3622
3623
3624 /* ------------------------------ */
3625     .balign 64
3626 .L_OP_NOT_LONG: /* 0x7e */
3627 /* File: armv5te/OP_NOT_LONG.S */
3628 /* File: armv5te/unopWide.S */
3629     /*
3630      * Generic 64-bit unary operation.  Provide an "instr" line that
3631      * specifies an instruction that performs "result = op r0/r1".
3632      * This could be an ARM instruction or a function call.
3633      *
3634      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3635      */
3636     /* unop vA, vB */
3637     mov     r9, rINST, lsr #8           @ r9<- A+
3638     mov     r3, rINST, lsr #12          @ r3<- B
3639     and     r9, r9, #15
3640     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3641     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3642     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3643     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3644     mvn     r0, r0                           @ optional op; may set condition codes
3645     mvn     r1, r1                              @ r0/r1<- op, r2-r3 changed
3646     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3647     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3648     GOTO_OPCODE(ip)                     @ jump to next instruction
3649     /* 12-13 instructions */
3650
3651
3652
3653 /* ------------------------------ */
3654     .balign 64
3655 .L_OP_NEG_FLOAT: /* 0x7f */
3656 /* File: armv5te/OP_NEG_FLOAT.S */
3657 /* File: armv5te/unop.S */
3658     /*
3659      * Generic 32-bit unary operation.  Provide an "instr" line that
3660      * specifies an instruction that performs "result = op r0".
3661      * This could be an ARM instruction or a function call.
3662      *
3663      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3664      *      int-to-byte, int-to-char, int-to-short
3665      */
3666     /* unop vA, vB */
3667     mov     r3, rINST, lsr #12          @ r3<- B
3668     mov     r9, rINST, lsr #8           @ r9<- A+
3669     GET_VREG(r0, r3)                    @ r0<- vB
3670     and     r9, r9, #15
3671                                @ optional op; may set condition codes
3672     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3673     add     r0, r0, #0x80000000                              @ r0<- op, r0-r3 changed
3674     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3675     SET_VREG(r0, r9)                    @ vAA<- r0
3676     GOTO_OPCODE(ip)                     @ jump to next instruction
3677     /* 9-10 instructions */
3678
3679
3680 /* ------------------------------ */
3681     .balign 64
3682 .L_OP_NEG_DOUBLE: /* 0x80 */
3683 /* File: armv5te/OP_NEG_DOUBLE.S */
3684 /* File: armv5te/unopWide.S */
3685     /*
3686      * Generic 64-bit unary operation.  Provide an "instr" line that
3687      * specifies an instruction that performs "result = op r0/r1".
3688      * This could be an ARM instruction or a function call.
3689      *
3690      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3691      */
3692     /* unop vA, vB */
3693     mov     r9, rINST, lsr #8           @ r9<- A+
3694     mov     r3, rINST, lsr #12          @ r3<- B
3695     and     r9, r9, #15
3696     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3697     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3698     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3699     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3700                                @ optional op; may set condition codes
3701     add     r1, r1, #0x80000000                              @ r0/r1<- op, r2-r3 changed
3702     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3703     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3704     GOTO_OPCODE(ip)                     @ jump to next instruction
3705     /* 12-13 instructions */
3706
3707
3708
3709 /* ------------------------------ */
3710     .balign 64
3711 .L_OP_INT_TO_LONG: /* 0x81 */
3712 /* File: armv5te/OP_INT_TO_LONG.S */
3713 /* File: armv5te/unopWider.S */
3714     /*
3715      * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3716      * that specifies an instruction that performs "result = op r0", where
3717      * "result" is a 64-bit quantity in r0/r1.
3718      *
3719      * For: int-to-long, int-to-double, float-to-long, float-to-double
3720      */
3721     /* unop vA, vB */
3722     mov     r9, rINST, lsr #8           @ r9<- A+
3723     mov     r3, rINST, lsr #12          @ r3<- B
3724     and     r9, r9, #15
3725     GET_VREG(r0, r3)                    @ r0<- vB
3726     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3727                                @ optional op; may set condition codes
3728     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3729     mov     r1, r0, asr #31                              @ r0<- op, r0-r3 changed
3730     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3731     stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3732     GOTO_OPCODE(ip)                     @ jump to next instruction
3733     /* 10-11 instructions */
3734
3735
3736 /* ------------------------------ */
3737     .balign 64
3738 .L_OP_INT_TO_FLOAT: /* 0x82 */
3739 /* File: armv5te/OP_INT_TO_FLOAT.S */
3740 /* File: armv5te/unop.S */
3741     /*
3742      * Generic 32-bit unary operation.  Provide an "instr" line that
3743      * specifies an instruction that performs "result = op r0".
3744      * This could be an ARM instruction or a function call.
3745      *
3746      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3747      *      int-to-byte, int-to-char, int-to-short
3748      */
3749     /* unop vA, vB */
3750     mov     r3, rINST, lsr #12          @ r3<- B
3751     mov     r9, rINST, lsr #8           @ r9<- A+
3752     GET_VREG(r0, r3)                    @ r0<- vB
3753     and     r9, r9, #15
3754                                @ optional op; may set condition codes
3755     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3756     bl      __aeabi_i2f                              @ r0<- op, r0-r3 changed
3757     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3758     SET_VREG(r0, r9)                    @ vAA<- r0
3759     GOTO_OPCODE(ip)                     @ jump to next instruction
3760     /* 9-10 instructions */
3761
3762
3763 /* ------------------------------ */
3764     .balign 64
3765 .L_OP_INT_TO_DOUBLE: /* 0x83 */
3766 /* File: armv5te/OP_INT_TO_DOUBLE.S */
3767 /* File: armv5te/unopWider.S */
3768     /*
3769      * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3770      * that specifies an instruction that performs "result = op r0", where
3771      * "result" is a 64-bit quantity in r0/r1.
3772      *
3773      * For: int-to-long, int-to-double, float-to-long, float-to-double
3774      */
3775     /* unop vA, vB */
3776     mov     r9, rINST, lsr #8           @ r9<- A+
3777     mov     r3, rINST, lsr #12          @ r3<- B
3778     and     r9, r9, #15
3779     GET_VREG(r0, r3)                    @ r0<- vB
3780     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3781                                @ optional op; may set condition codes
3782     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3783     bl      __aeabi_i2d                              @ r0<- op, r0-r3 changed
3784     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3785     stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3786     GOTO_OPCODE(ip)                     @ jump to next instruction
3787     /* 10-11 instructions */
3788
3789
3790 /* ------------------------------ */
3791     .balign 64
3792 .L_OP_LONG_TO_INT: /* 0x84 */
3793 /* File: armv5te/OP_LONG_TO_INT.S */
3794 /* we ignore the high word, making this equivalent to a 32-bit reg move */
3795 /* File: armv5te/OP_MOVE.S */
3796     /* for move, move-object, long-to-int */
3797     /* op vA, vB */
3798     mov     r1, rINST, lsr #12          @ r1<- B from 15:12
3799     mov     r0, rINST, lsr #8           @ r0<- A from 11:8
3800     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3801     GET_VREG(r2, r1)                    @ r2<- fp[B]
3802     and     r0, r0, #15
3803     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
3804     SET_VREG(r2, r0)                    @ fp[A]<- r2
3805     GOTO_OPCODE(ip)                     @ execute next instruction
3806
3807
3808
3809 /* ------------------------------ */
3810     .balign 64
3811 .L_OP_LONG_TO_FLOAT: /* 0x85 */
3812 /* File: armv5te/OP_LONG_TO_FLOAT.S */
3813 /* File: armv5te/unopNarrower.S */
3814     /*
3815      * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
3816      * that specifies an instruction that performs "result = op r0/r1", where
3817      * "result" is a 32-bit quantity in r0.
3818      *
3819      * For: long-to-float, double-to-int, double-to-float
3820      *
3821      * (This would work for long-to-int, but that instruction is actually
3822      * an exact match for OP_MOVE.)
3823      */
3824     /* unop vA, vB */
3825     mov     r3, rINST, lsr #12          @ r3<- B
3826     mov     r9, rINST, lsr #8           @ r9<- A+
3827     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3828     and     r9, r9, #15
3829     ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
3830     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3831                                @ optional op; may set condition codes
3832     bl      __aeabi_l2f                              @ r0<- op, r0-r3 changed
3833     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3834     SET_VREG(r0, r9)                    @ vA<- r0
3835     GOTO_OPCODE(ip)                     @ jump to next instruction
3836     /* 10-11 instructions */
3837
3838
3839 /* ------------------------------ */
3840     .balign 64
3841 .L_OP_LONG_TO_DOUBLE: /* 0x86 */
3842 /* File: armv5te/OP_LONG_TO_DOUBLE.S */
3843 /* File: armv5te/unopWide.S */
3844     /*
3845      * Generic 64-bit unary operation.  Provide an "instr" line that
3846      * specifies an instruction that performs "result = op r0/r1".
3847      * This could be an ARM instruction or a function call.
3848      *
3849      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3850      */
3851     /* unop vA, vB */
3852     mov     r9, rINST, lsr #8           @ r9<- A+
3853     mov     r3, rINST, lsr #12          @ r3<- B
3854     and     r9, r9, #15
3855     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3856     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3857     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3858     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3859                                @ optional op; may set condition codes
3860     bl      __aeabi_l2d                              @ r0/r1<- op, r2-r3 changed
3861     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3862     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3863     GOTO_OPCODE(ip)                     @ jump to next instruction
3864     /* 12-13 instructions */
3865
3866
3867
3868 /* ------------------------------ */
3869     .balign 64
3870 .L_OP_FLOAT_TO_INT: /* 0x87 */
3871 /* File: armv5te/OP_FLOAT_TO_INT.S */
3872 /* EABI appears to have Java-style conversions of +inf/-inf/NaN */
3873 /* File: armv5te/unop.S */
3874     /*
3875      * Generic 32-bit unary operation.  Provide an "instr" line that
3876      * specifies an instruction that performs "result = op r0".
3877      * This could be an ARM instruction or a function call.
3878      *
3879      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3880      *      int-to-byte, int-to-char, int-to-short
3881      */
3882     /* unop vA, vB */
3883     mov     r3, rINST, lsr #12          @ r3<- B
3884     mov     r9, rINST, lsr #8           @ r9<- A+
3885     GET_VREG(r0, r3)                    @ r0<- vB
3886     and     r9, r9, #15
3887                                @ optional op; may set condition codes
3888     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3889     bl      __aeabi_f2iz                              @ r0<- op, r0-r3 changed
3890     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3891     SET_VREG(r0, r9)                    @ vAA<- r0
3892     GOTO_OPCODE(ip)                     @ jump to next instruction
3893     /* 9-10 instructions */
3894
3895
3896 #if 0
3897 @include "armv5te/unop.S" {"instr":"bl      f2i_doconv"}
3898 @break
3899 /*
3900  * Convert the float in r0 to an int in r0.
3901  *
3902  * We have to clip values to int min/max per the specification.  The
3903  * expected common case is a "reasonable" value that converts directly
3904  * to modest integer.  The EABI convert function isn't doing this for us.
3905  */
3906 f2i_doconv:
3907     stmfd   sp!, {r4, lr}
3908     mov     r1, #0x4f000000             @ (float)maxint
3909     mov     r4, r0
3910     bl      __aeabi_fcmpge              @ is arg >= maxint?
3911     cmp     r0, #0                      @ nonzero == yes
3912     mvnne   r0, #0x80000000             @ return maxint (7fffffff)
3913     ldmnefd sp!, {r4, pc}
3914
3915     mov     r0, r4                      @ recover arg
3916     mov     r1, #0xcf000000             @ (float)minint
3917     bl      __aeabi_fcmple              @ is arg <= minint?
3918     cmp     r0, #0                      @ nonzero == yes
3919     movne   r0, #0x80000000             @ return minint (80000000)
3920     ldmnefd sp!, {r4, pc}
3921
3922     mov     r0, r4                      @ recover arg
3923     mov     r1, r4
3924     bl      __aeabi_fcmpeq              @ is arg == self?
3925     cmp     r0, #0                      @ zero == no
3926     ldmeqfd sp!, {r4, pc}               @ return zero for NaN
3927
3928     mov     r0, r4                      @ recover arg
3929     bl      __aeabi_f2iz                @ convert float to int
3930     ldmfd   sp!, {r4, pc}
3931 #endif
3932
3933
3934 /* ------------------------------ */
3935     .balign 64
3936 .L_OP_FLOAT_TO_LONG: /* 0x88 */
3937 /* File: armv5te/OP_FLOAT_TO_LONG.S */
3938 @include "armv5te/unopWider.S" {"instr":"bl      __aeabi_f2lz"}
3939 /* File: armv5te/unopWider.S */
3940     /*
3941      * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3942      * that specifies an instruction that performs "result = op r0", where
3943      * "result" is a 64-bit quantity in r0/r1.
3944      *
3945      * For: int-to-long, int-to-double, float-to-long, float-to-double
3946      */
3947     /* unop vA, vB */
3948     mov     r9, rINST, lsr #8           @ r9<- A+
3949     mov     r3, rINST, lsr #12          @ r3<- B
3950     and     r9, r9, #15
3951     GET_VREG(r0, r3)                    @ r0<- vB
3952     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3953                                @ optional op; may set condition codes
3954     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3955     bl      f2l_doconv                              @ r0<- op, r0-r3 changed
3956     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3957     stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3958     GOTO_OPCODE(ip)                     @ jump to next instruction
3959     /* 10-11 instructions */
3960
3961
3962
3963 /* ------------------------------ */
3964     .balign 64
3965 .L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
3966 /* File: armv5te/OP_FLOAT_TO_DOUBLE.S */
3967 /* File: armv5te/unopWider.S */
3968     /*
3969      * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3970      * that specifies an instruction that performs "result = op r0", where
3971      * "result" is a 64-bit quantity in r0/r1.
3972      *
3973      * For: int-to-long, int-to-double, float-to-long, float-to-double
3974      */
3975     /* unop vA, vB */
3976     mov     r9, rINST, lsr #8           @ r9<- A+
3977     mov     r3, rINST, lsr #12          @ r3<- B
3978     and     r9, r9, #15
3979     GET_VREG(r0, r3)                    @ r0<- vB
3980     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3981                                @ optional op; may set condition codes
3982     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3983     bl      __aeabi_f2d                              @ r0<- op, r0-r3 changed
3984     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3985     stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3986     GOTO_OPCODE(ip)                     @ jump to next instruction
3987     /* 10-11 instructions */
3988
3989
3990 /* ------------------------------ */
3991     .balign 64
3992 .L_OP_DOUBLE_TO_INT: /* 0x8a */
3993 /* File: armv5te/OP_DOUBLE_TO_INT.S */
3994 /* EABI appears to have Java-style conversions of +inf/-inf/NaN */
3995 /* File: armv5te/unopNarrower.S */
3996     /*
3997      * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
3998      * that specifies an instruction that performs "result = op r0/r1", where
3999      * "result" is a 32-bit quantity in r0.
4000      *
4001      * For: long-to-float, double-to-int, double-to-float
4002      *
4003      * (This would work for long-to-int, but that instruction is actually
4004      * an exact match for OP_MOVE.)
4005      */
4006     /* unop vA, vB */
4007     mov     r3, rINST, lsr #12          @ r3<- B
4008     mov     r9, rINST, lsr #8           @ r9<- A+
4009     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
4010     and     r9, r9, #15
4011     ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
4012     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4013                                @ optional op; may set condition codes
4014     bl      __aeabi_d2iz                              @ r0<- op, r0-r3 changed
4015     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4016     SET_VREG(r0, r9)                    @ vA<- r0
4017     GOTO_OPCODE(ip)                     @ jump to next instruction
4018     /* 10-11 instructions */
4019
4020
4021 #if 0
4022 @include "armv5te/unopNarrower.S" {"instr":"bl      d2i_doconv"}
4023 @break
4024 /*
4025  * Convert the double in r0/r1 to an int in r0.
4026  *
4027  * We have to clip values to int min/max per the specification.  The
4028  * expected common case is a "reasonable" value that converts directly
4029  * to modest integer.  The EABI convert function isn't doing this for us.
4030  */
4031 d2i_doconv:
4032     stmfd   sp!, {r4, r5, lr}           @ save regs
4033     mov     r2, #0x80000000             @ maxint, as a double (low word)
4034     mov     r2, r2, asr #9              @  0xffc00000
4035     sub     sp, sp, #4                  @ align for EABI
4036     mvn     r3, #0xbe000000             @ maxint, as a double (high word)
4037     sub     r3, r3, #0x00200000         @  0x41dfffff
4038     mov     r4, r0                      @ save a copy of r0
4039     mov     r5, r1                      @  and r1
4040     bl      __aeabi_dcmpge              @ is arg >= maxint?
4041     cmp     r0, #0                      @ nonzero == yes
4042     mvnne   r0, #0x80000000             @ return maxint (0x7fffffff)
4043     bne     1f
4044
4045     mov     r0, r4                      @ recover arg
4046     mov     r1, r5
4047     mov     r3, #0xc1000000             @ minint, as a double (high word)
4048     add     r3, r3, #0x00e00000         @  0xc1e00000
4049     mov     r2, #0                      @ minint, as a double (low word)
4050     bl      __aeabi_dcmple              @ is arg <= minint?
4051     cmp     r0, #0                      @ nonzero == yes
4052     movne   r0, #0x80000000             @ return minint (80000000)
4053     bne     1f
4054
4055     mov     r0, r4                      @ recover arg
4056     mov     r1, r5
4057     mov     r2, r4                      @ compare against self
4058     mov     r3, r5
4059     bl      __aeabi_dcmpeq              @ is arg == self?
4060     cmp     r0, #0                      @ zero == no
4061     beq     1f                          @ return zero for NaN
4062
4063     mov     r0, r4                      @ recover arg
4064     mov     r1, r5
4065     bl      __aeabi_d2iz                @ convert double to int
4066
4067 1:
4068     add     sp, sp, #4
4069     ldmfd   sp!, {r4, r5, pc}
4070 #endif
4071
4072
4073 /* ------------------------------ */
4074     .balign 64
4075 .L_OP_DOUBLE_TO_LONG: /* 0x8b */
4076 /* File: armv5te/OP_DOUBLE_TO_LONG.S */
4077 @include "armv5te/unopWide.S" {"instr":"bl      __aeabi_d2lz"}
4078 /* File: armv5te/unopWide.S */
4079     /*
4080      * Generic 64-bit unary operation.  Provide an "instr" line that
4081      * specifies an instruction that performs "result = op r0/r1".
4082      * This could be an ARM instruction or a function call.
4083      *
4084      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
4085      */
4086     /* unop vA, vB */
4087     mov     r9, rINST, lsr #8           @ r9<- A+
4088     mov     r3, rINST, lsr #12          @ r3<- B
4089     and     r9, r9, #15
4090     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
4091     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
4092     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
4093     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4094                                @ optional op; may set condition codes
4095     bl      d2l_doconv                              @ r0/r1<- op, r2-r3 changed
4096     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4097     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
4098     GOTO_OPCODE(ip)                     @ jump to next instruction
4099     /* 12-13 instructions */
4100
4101
4102
4103
4104 /* ------------------------------ */
4105     .balign 64
4106 .L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
4107 /* File: armv5te/OP_DOUBLE_TO_FLOAT.S */
4108 /* File: armv5te/unopNarrower.S */
4109     /*
4110      * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
4111      * that specifies an instruction that performs "result = op r0/r1", where
4112      * "result" is a 32-bit quantity in r0.
4113      *
4114      * For: long-to-float, double-to-int, double-to-float
4115      *
4116      * (This would work for long-to-int, but that instruction is actually
4117      * an exact match for OP_MOVE.)
4118      */
4119     /* unop vA, vB */
4120     mov     r3, rINST, lsr #12          @ r3<- B
4121     mov     r9, rINST, lsr #8           @ r9<- A+
4122     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
4123     and     r9, r9, #15
4124     ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
4125     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4126                                @ optional op; may set condition codes
4127     bl      __aeabi_d2f                              @ r0<- op, r0-r3 changed
4128     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4129     SET_VREG(r0, r9)                    @ vA<- r0
4130     GOTO_OPCODE(ip)                     @ jump to next instruction
4131     /* 10-11 instructions */
4132
4133
4134 /* ------------------------------ */
4135     .balign 64
4136 .L_OP_INT_TO_BYTE: /* 0x8d */
4137 /* File: armv5te/OP_INT_TO_BYTE.S */
4138 /* File: armv5te/unop.S */
4139     /*
4140      * Generic 32-bit unary operation.  Provide an "instr" line that
4141      * specifies an instruction that performs "result = op r0".
4142      * This could be an ARM instruction or a function call.
4143      *
4144      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4145      *      int-to-byte, int-to-char, int-to-short
4146      */
4147     /* unop vA, vB */
4148     mov     r3, rINST, lsr #12          @ r3<- B
4149     mov     r9, rINST, lsr #8           @ r9<- A+
4150     GET_VREG(r0, r3)                    @ r0<- vB
4151     and     r9, r9, #15
4152     mov     r0, r0, asl #24                           @ optional op; may set condition codes
4153     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4154     mov     r0, r0, asr #24                              @ r0<- op, r0-r3 changed
4155     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4156     SET_VREG(r0, r9)                    @ vAA<- r0
4157     GOTO_OPCODE(ip)                     @ jump to next instruction
4158     /* 9-10 instructions */
4159
4160
4161 /* ------------------------------ */
4162     .balign 64
4163 .L_OP_INT_TO_CHAR: /* 0x8e */
4164 /* File: armv5te/OP_INT_TO_CHAR.S */
4165 /* File: armv5te/unop.S */
4166     /*
4167      * Generic 32-bit unary operation.  Provide an "instr" line that
4168      * specifies an instruction that performs "result = op r0".
4169      * This could be an ARM instruction or a function call.
4170      *
4171      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4172      *      int-to-byte, int-to-char, int-to-short
4173      */
4174     /* unop vA, vB */
4175     mov     r3, rINST, lsr #12          @ r3<- B
4176     mov     r9, rINST, lsr #8           @ r9<- A+
4177     GET_VREG(r0, r3)                    @ r0<- vB
4178     and     r9, r9, #15
4179     mov     r0, r0, asl #16                           @ optional op; may set condition codes
4180     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4181     mov     r0, r0, lsr #16                              @ r0<- op, r0-r3 changed
4182     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4183     SET_VREG(r0, r9)                    @ vAA<- r0
4184     GOTO_OPCODE(ip)                     @ jump to next instruction
4185     /* 9-10 instructions */
4186
4187
4188 /* ------------------------------ */
4189     .balign 64
4190 .L_OP_INT_TO_SHORT: /* 0x8f */
4191 /* File: armv5te/OP_INT_TO_SHORT.S */
4192 /* File: armv5te/unop.S */
4193     /*
4194      * Generic 32-bit unary operation.  Provide an "instr" line that
4195      * specifies an instruction that performs "result = op r0".
4196      * This could be an ARM instruction or a function call.
4197      *
4198      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4199      *      int-to-byte, int-to-char, int-to-short
4200      */
4201     /* unop vA, vB */
4202     mov     r3, rINST, lsr #12          @ r3<- B
4203     mov     r9, rINST, lsr #8           @ r9<- A+
4204     GET_VREG(r0, r3)                    @ r0<- vB
4205     and     r9, r9, #15
4206     mov     r0, r0, asl #16                           @ optional op; may set condition codes
4207     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4208     mov     r0, r0, asr #16                              @ r0<- op, r0-r3 changed
4209     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4210     SET_VREG(r0, r9)                    @ vAA<- r0
4211     GOTO_OPCODE(ip)                     @ jump to next instruction
4212     /* 9-10 instructions */
4213
4214
4215 /* ------------------------------ */
4216     .balign 64
4217 .L_OP_ADD_INT: /* 0x90 */
4218 /* File: armv5te/OP_ADD_INT.S */
4219 /* File: armv5te/binop.S */
4220     /*
4221      * Generic 32-bit binary operation.  Provide an "instr" line that
4222      * specifies an instruction that performs "result = r0 op r1".
4223      * This could be an ARM instruction or a function call.  (If the result
4224      * comes back in a register other than r0, you can override "result".)
4225      *
4226      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4227      * vCC (r1).  Useful for integer division and modulus.  Note that we
4228      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4229      * handles it correctly.
4230      *
4231      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4232      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4233      *      mul-float, div-float, rem-float
4234      */
4235     /* binop vAA, vBB, vCC */
4236     FETCH(r0, 1)                        @ r0<- CCBB
4237     mov     r9, rINST, lsr #8           @ r9<- AA
4238     mov     r3, r0, lsr #8              @ r3<- CC
4239     and     r2, r0, #255                @ r2<- BB
4240     GET_VREG(r1, r3)                    @ r1<- vCC
4241     GET_VREG(r0, r2)                    @ r0<- vBB
4242     .if 0
4243     cmp     r1, #0                      @ is second operand zero?
4244     beq     common_errDivideByZero
4245     .endif
4246
4247     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4248                                @ optional op; may set condition codes
4249     add     r0, r0, r1                              @ r0<- op, r0-r3 changed
4250     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4251     SET_VREG(r0, r9)               @ vAA<- r0
4252     GOTO_OPCODE(ip)                     @ jump to next instruction
4253     /* 11-14 instructions */
4254
4255
4256
4257 /* ------------------------------ */
4258     .balign 64
4259 .L_OP_SUB_INT: /* 0x91 */
4260 /* File: armv5te/OP_SUB_INT.S */
4261 /* File: armv5te/binop.S */
4262     /*
4263      * Generic 32-bit binary operation.  Provide an "instr" line that
4264      * specifies an instruction that performs "result = r0 op r1".
4265      * This could be an ARM instruction or a function call.  (If the result
4266      * comes back in a register other than r0, you can override "result".)
4267      *
4268      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4269      * vCC (r1).  Useful for integer division and modulus.  Note that we
4270      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4271      * handles it correctly.
4272      *
4273      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4274      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4275      *      mul-float, div-float, rem-float
4276      */
4277     /* binop vAA, vBB, vCC */
4278     FETCH(r0, 1)                        @ r0<- CCBB
4279     mov     r9, rINST, lsr #8           @ r9<- AA
4280     mov     r3, r0, lsr #8              @ r3<- CC
4281     and     r2, r0, #255                @ r2<- BB
4282     GET_VREG(r1, r3)                    @ r1<- vCC
4283     GET_VREG(r0, r2)                    @ r0<- vBB
4284     .if 0
4285     cmp     r1, #0                      @ is second operand zero?
4286     beq     common_errDivideByZero
4287     .endif
4288
4289     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4290                                @ optional op; may set condition codes
4291     sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
4292     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4293     SET_VREG(r0, r9)               @ vAA<- r0
4294     GOTO_OPCODE(ip)                     @ jump to next instruction
4295     /* 11-14 instructions */
4296
4297
4298
4299 /* ------------------------------ */
4300     .balign 64
4301 .L_OP_MUL_INT: /* 0x92 */
4302 /* File: armv5te/OP_MUL_INT.S */
4303 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
4304 /* File: armv5te/binop.S */
4305     /*
4306      * Generic 32-bit binary operation.  Provide an "instr" line that
4307      * specifies an instruction that performs "result = r0 op r1".
4308      * This could be an ARM instruction or a function call.  (If the result
4309      * comes back in a register other than r0, you can override "result".)
4310      *
4311      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4312      * vCC (r1).  Useful for integer division and modulus.  Note that we
4313      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4314      * handles it correctly.
4315      *
4316      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4317      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4318      *      mul-float, div-float, rem-float
4319      */
4320     /* binop vAA, vBB, vCC */
4321     FETCH(r0, 1)                        @ r0<- CCBB
4322     mov     r9, rINST, lsr #8           @ r9<- AA
4323     mov     r3, r0, lsr #8              @ r3<- CC
4324     and     r2, r0, #255                @ r2<- BB
4325     GET_VREG(r1, r3)                    @ r1<- vCC
4326     GET_VREG(r0, r2)                    @ r0<- vBB
4327     .if 0
4328     cmp     r1, #0                      @ is second operand zero?
4329     beq     common_errDivideByZero
4330     .endif
4331
4332     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4333                                @ optional op; may set condition codes
4334     mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
4335     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4336     SET_VREG(r0, r9)               @ vAA<- r0
4337     GOTO_OPCODE(ip)                     @ jump to next instruction
4338     /* 11-14 instructions */
4339
4340
4341
4342 /* ------------------------------ */
4343     .balign 64
4344 .L_OP_DIV_INT: /* 0x93 */
4345 /* File: armv5te/OP_DIV_INT.S */
4346 /* File: armv5te/binop.S */
4347     /*
4348      * Generic 32-bit binary operation.  Provide an "instr" line that
4349      * specifies an instruction that performs "result = r0 op r1".
4350      * This could be an ARM instruction or a function call.  (If the result
4351      * comes back in a register other than r0, you can override "result".)
4352      *
4353      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4354      * vCC (r1).  Useful for integer division and modulus.  Note that we
4355      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4356      * handles it correctly.
4357      *
4358      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4359      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4360      *      mul-float, div-float, rem-float
4361      */
4362     /* binop vAA, vBB, vCC */
4363     FETCH(r0, 1)                        @ r0<- CCBB
4364     mov     r9, rINST, lsr #8           @ r9<- AA
4365     mov     r3, r0, lsr #8              @ r3<- CC
4366     and     r2, r0, #255                @ r2<- BB
4367     GET_VREG(r1, r3)                    @ r1<- vCC
4368     GET_VREG(r0, r2)                    @ r0<- vBB
4369     .if 1
4370     cmp     r1, #0                      @ is second operand zero?
4371     beq     common_errDivideByZero
4372     .endif
4373
4374     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4375                                @ optional op; may set condition codes
4376     bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
4377     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4378     SET_VREG(r0, r9)               @ vAA<- r0
4379     GOTO_OPCODE(ip)                     @ jump to next instruction
4380     /* 11-14 instructions */
4381
4382
4383
4384 /* ------------------------------ */
4385     .balign 64
4386 .L_OP_REM_INT: /* 0x94 */
4387 /* File: armv5te/OP_REM_INT.S */
4388 /* idivmod returns quotient in r0 and remainder in r1 */
4389 /* File: armv5te/binop.S */
4390     /*
4391      * Generic 32-bit binary operation.  Provide an "instr" line that
4392      * specifies an instruction that performs "result = r0 op r1".
4393      * This could be an ARM instruction or a function call.  (If the result
4394      * comes back in a register other than r0, you can override "result".)
4395      *
4396      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4397      * vCC (r1).  Useful for integer division and modulus.  Note that we
4398      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4399      * handles it correctly.
4400      *
4401      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4402      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4403      *      mul-float, div-float, rem-float
4404      */
4405     /* binop vAA, vBB, vCC */
4406     FETCH(r0, 1)                        @ r0<- CCBB
4407     mov     r9, rINST, lsr #8           @ r9<- AA
4408     mov     r3, r0, lsr #8              @ r3<- CC
4409     and     r2, r0, #255                @ r2<- BB
4410     GET_VREG(r1, r3)                    @ r1<- vCC
4411     GET_VREG(r0, r2)                    @ r0<- vBB
4412     .if 1
4413     cmp     r1, #0                      @ is second operand zero?
4414     beq     common_errDivideByZero
4415     .endif
4416
4417     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4418                                @ optional op; may set condition codes
4419     bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
4420     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4421     SET_VREG(r1, r9)               @ vAA<- r1
4422     GOTO_OPCODE(ip)                     @ jump to next instruction
4423     /* 11-14 instructions */
4424
4425
4426
4427 /* ------------------------------ */
4428     .balign 64
4429 .L_OP_AND_INT: /* 0x95 */
4430 /* File: armv5te/OP_AND_INT.S */
4431 /* File: armv5te/binop.S */
4432     /*
4433      * Generic 32-bit binary operation.  Provide an "instr" line that
4434      * specifies an instruction that performs "result = r0 op r1".
4435      * This could be an ARM instruction or a function call.  (If the result
4436      * comes back in a register other than r0, you can override "result".)
4437      *
4438      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4439      * vCC (r1).  Useful for integer division and modulus.  Note that we
4440      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4441      * handles it correctly.
4442      *
4443      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4444      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4445      *      mul-float, div-float, rem-float
4446      */
4447     /* binop vAA, vBB, vCC */
4448     FETCH(r0, 1)                        @ r0<- CCBB
4449     mov     r9, rINST, lsr #8           @ r9<- AA
4450     mov     r3, r0, lsr #8              @ r3<- CC
4451     and     r2, r0, #255                @ r2<- BB
4452     GET_VREG(r1, r3)                    @ r1<- vCC
4453     GET_VREG(r0, r2)                    @ r0<- vBB
4454     .if 0
4455     cmp     r1, #0                      @ is second operand zero?
4456     beq     common_errDivideByZero
4457     .endif
4458
4459     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4460                                @ optional op; may set condition codes
4461     and     r0, r0, r1                              @ r0<- op, r0-r3 changed
4462     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4463     SET_VREG(r0, r9)               @ vAA<- r0
4464     GOTO_OPCODE(ip)                     @ jump to next instruction
4465     /* 11-14 instructions */
4466
4467
4468
4469 /* ------------------------------ */
4470     .balign 64
4471 .L_OP_OR_INT: /* 0x96 */
4472 /* File: armv5te/OP_OR_INT.S */
4473 /* File: armv5te/binop.S */
4474     /*
4475      * Generic 32-bit binary operation.  Provide an "instr" line that
4476      * specifies an instruction that performs "result = r0 op r1".
4477      * This could be an ARM instruction or a function call.  (If the result
4478      * comes back in a register other than r0, you can override "result".)
4479      *
4480      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4481      * vCC (r1).  Useful for integer division and modulus.  Note that we
4482      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4483      * handles it correctly.
4484      *
4485      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4486      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4487      *      mul-float, div-float, rem-float
4488      */
4489     /* binop vAA, vBB, vCC */
4490     FETCH(r0, 1)                        @ r0<- CCBB
4491     mov     r9, rINST, lsr #8           @ r9<- AA
4492     mov     r3, r0, lsr #8              @ r3<- CC
4493     and     r2, r0, #255                @ r2<- BB
4494     GET_VREG(r1, r3)                    @ r1<- vCC
4495     GET_VREG(r0, r2)                    @ r0<- vBB
4496     .if 0
4497     cmp     r1, #0                      @ is second operand zero?
4498     beq     common_errDivideByZero
4499     .endif
4500
4501     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4502                                @ optional op; may set condition codes
4503     orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
4504     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4505     SET_VREG(r0, r9)               @ vAA<- r0
4506     GOTO_OPCODE(ip)                     @ jump to next instruction
4507     /* 11-14 instructions */
4508
4509
4510
4511 /* ------------------------------ */
4512     .balign 64
4513 .L_OP_XOR_INT: /* 0x97 */
4514 /* File: armv5te/OP_XOR_INT.S */
4515 /* File: armv5te/binop.S */
4516     /*
4517      * Generic 32-bit binary operation.  Provide an "instr" line that
4518      * specifies an instruction that performs "result = r0 op r1".
4519      * This could be an ARM instruction or a function call.  (If the result
4520      * comes back in a register other than r0, you can override "result".)
4521      *
4522      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4523      * vCC (r1).  Useful for integer division and modulus.  Note that we
4524      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4525      * handles it correctly.
4526      *
4527      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4528      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4529      *      mul-float, div-float, rem-float
4530      */
4531     /* binop vAA, vBB, vCC */
4532     FETCH(r0, 1)                        @ r0<- CCBB
4533     mov     r9, rINST, lsr #8           @ r9<- AA
4534     mov     r3, r0, lsr #8              @ r3<- CC
4535     and     r2, r0, #255                @ r2<- BB
4536     GET_VREG(r1, r3)                    @ r1<- vCC
4537     GET_VREG(r0, r2)                    @ r0<- vBB
4538     .if 0
4539     cmp     r1, #0                      @ is second operand zero?
4540     beq     common_errDivideByZero
4541     .endif
4542
4543     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4544                                @ optional op; may set condition codes
4545     eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
4546     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4547     SET_VREG(r0, r9)               @ vAA<- r0
4548     GOTO_OPCODE(ip)                     @ jump to next instruction
4549     /* 11-14 instructions */
4550
4551
4552
4553 /* ------------------------------ */
4554     .balign 64
4555 .L_OP_SHL_INT: /* 0x98 */
4556 /* File: armv5te/OP_SHL_INT.S */
4557 /* File: armv5te/binop.S */
4558     /*
4559      * Generic 32-bit binary operation.  Provide an "instr" line that
4560      * specifies an instruction that performs "result = r0 op r1".
4561      * This could be an ARM instruction or a function call.  (If the result
4562      * comes back in a register other than r0, you can override "result".)
4563      *
4564      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4565      * vCC (r1).  Useful for integer division and modulus.  Note that we
4566      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4567      * handles it correctly.
4568      *
4569      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4570      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4571      *      mul-float, div-float, rem-float
4572      */
4573     /* binop vAA, vBB, vCC */
4574     FETCH(r0, 1)                        @ r0<- CCBB
4575     mov     r9, rINST, lsr #8           @ r9<- AA
4576     mov     r3, r0, lsr #8              @ r3<- CC
4577     and     r2, r0, #255                @ r2<- BB
4578     GET_VREG(r1, r3)                    @ r1<- vCC
4579     GET_VREG(r0, r2)                    @ r0<- vBB
4580     .if 0
4581     cmp     r1, #0                      @ is second operand zero?
4582     beq     common_errDivideByZero
4583     .endif
4584
4585     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4586     and     r1, r1, #31                           @ optional op; may set condition codes
4587     mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
4588     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4589     SET_VREG(r0, r9)               @ vAA<- r0
4590     GOTO_OPCODE(ip)                     @ jump to next instruction
4591     /* 11-14 instructions */
4592
4593
4594
4595 /* ------------------------------ */
4596     .balign 64
4597 .L_OP_SHR_INT: /* 0x99 */
4598 /* File: armv5te/OP_SHR_INT.S */
4599 /* File: armv5te/binop.S */
4600     /*
4601      * Generic 32-bit binary operation.  Provide an "instr" line that
4602      * specifies an instruction that performs "result = r0 op r1".
4603      * This could be an ARM instruction or a function call.  (If the result
4604      * comes back in a register other than r0, you can override "result".)
4605      *
4606      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4607      * vCC (r1).  Useful for integer division and modulus.  Note that we
4608      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4609      * handles it correctly.
4610      *
4611      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4612      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4613      *      mul-float, div-float, rem-float
4614      */
4615     /* binop vAA, vBB, vCC */
4616     FETCH(r0, 1)                        @ r0<- CCBB
4617     mov     r9, rINST, lsr #8           @ r9<- AA
4618     mov     r3, r0, lsr #8              @ r3<- CC
4619     and     r2, r0, #255                @ r2<- BB
4620     GET_VREG(r1, r3)                    @ r1<- vCC
4621     GET_VREG(r0, r2)                    @ r0<- vBB
4622     .if 0
4623     cmp     r1, #0                      @ is second operand zero?
4624     beq     common_errDivideByZero
4625     .endif
4626
4627     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4628     and     r1, r1, #31                           @ optional op; may set condition codes
4629     mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
4630     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4631     SET_VREG(r0, r9)               @ vAA<- r0
4632     GOTO_OPCODE(ip)                     @ jump to next instruction
4633     /* 11-14 instructions */
4634
4635
4636
4637 /* ------------------------------ */
4638     .balign 64
4639 .L_OP_USHR_INT: /* 0x9a */
4640 /* File: armv5te/OP_USHR_INT.S */
4641 /* File: armv5te/binop.S */
4642     /*
4643      * Generic 32-bit binary operation.  Provide an "instr" line that
4644      * specifies an instruction that performs "result = r0 op r1".
4645      * This could be an ARM instruction or a function call.  (If the result
4646      * comes back in a register other than r0, you can override "result".)
4647      *
4648      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4649      * vCC (r1).  Useful for integer division and modulus.  Note that we
4650      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4651      * handles it correctly.
4652      *
4653      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4654      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4655      *      mul-float, div-float, rem-float
4656      */
4657     /* binop vAA, vBB, vCC */
4658     FETCH(r0, 1)                        @ r0<- CCBB
4659     mov     r9, rINST, lsr #8           @ r9<- AA
4660     mov     r3, r0, lsr #8              @ r3<- CC
4661     and     r2, r0, #255                @ r2<- BB
4662     GET_VREG(r1, r3)                    @ r1<- vCC
4663     GET_VREG(r0, r2)                    @ r0<- vBB
4664     .if 0
4665     cmp     r1, #0                      @ is second operand zero?
4666     beq     common_errDivideByZero
4667     .endif
4668
4669     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4670     and     r1, r1, #31                           @ optional op; may set condition codes
4671     mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
4672     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4673     SET_VREG(r0, r9)               @ vAA<- r0
4674     GOTO_OPCODE(ip)                     @ jump to next instruction
4675     /* 11-14 instructions */
4676
4677
4678
4679 /* ------------------------------ */
4680     .balign 64
4681 .L_OP_ADD_LONG: /* 0x9b */
4682 /* File: armv5te/OP_ADD_LONG.S */
4683 /* File: armv5te/binopWide.S */
4684     /*
4685      * Generic 64-bit binary operation.  Provide an "instr" line that
4686      * specifies an instruction that performs "result = r0-r1 op r2-r3".
4687      * This could be an ARM instruction or a function call.  (If the result
4688      * comes back in a register other than r0, you can override "result".)
4689      *
4690      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4691      * vCC (r1).  Useful for integer division and modulus.
4692      *
4693      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4694      *      xor-long, add-double, sub-double, mul-double, div-double,
4695      *      rem-double
4696      *
4697      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4698      */
4699     /* binop vAA, vBB, vCC */
4700     FETCH(r0, 1)                        @ r0<- CCBB
4701     mov     r9, rINST, lsr #8           @ r9<- AA
4702     and     r2, r0, #255                @ r2<- BB
4703     mov     r3, r0, lsr #8              @ r3<- CC
4704     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4705     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4706     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4707     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4708     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4709     .if 0
4710     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4711     beq     common_errDivideByZero
4712     .endif
4713     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4714
4715     adds    r0, r0, r2                           @ optional op; may set condition codes
4716     adc     r1, r1, r3                              @ result<- op, r0-r3 changed
4717     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4718     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4719     GOTO_OPCODE(ip)                     @ jump to next instruction
4720     /* 14-17 instructions */
4721
4722
4723
4724 /* ------------------------------ */
4725     .balign 64
4726 .L_OP_SUB_LONG: /* 0x9c */
4727 /* File: armv5te/OP_SUB_LONG.S */
4728 /* File: armv5te/binopWide.S */
4729     /*
4730      * Generic 64-bit binary operation.  Provide an "instr" line that
4731      * specifies an instruction that performs "result = r0-r1 op r2-r3".
4732      * This could be an ARM instruction or a function call.  (If the result
4733      * comes back in a register other than r0, you can override "result".)
4734      *
4735      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4736      * vCC (r1).  Useful for integer division and modulus.
4737      *
4738      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4739      *      xor-long, add-double, sub-double, mul-double, div-double,
4740      *      rem-double
4741      *
4742      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4743      */
4744     /* binop vAA, vBB, vCC */
4745     FETCH(r0, 1)                        @ r0<- CCBB
4746     mov     r9, rINST, lsr #8           @ r9<- AA
4747     and     r2, r0, #255                @ r2<- BB
4748     mov     r3, r0, lsr #8              @ r3<- CC
4749     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4750     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4751     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4752     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4753     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4754     .if 0
4755     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4756     beq     common_errDivideByZero
4757     .endif
4758     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4759
4760     subs    r0, r0, r2                           @ optional op; may set condition codes
4761     sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
4762     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4763     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4764     GOTO_OPCODE(ip)                     @ jump to next instruction
4765     /* 14-17 instructions */
4766
4767
4768
4769 /* ------------------------------ */
4770     .balign 64
4771 .L_OP_MUL_LONG: /* 0x9d */
4772 /* File: armv5te/OP_MUL_LONG.S */
4773     /*
4774      * Signed 64-bit integer multiply.
4775      *
4776      * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
4777      *        WX
4778      *      x YZ
4779      *  --------
4780      *     ZW ZX
4781      *  YW YX
4782      *
4783      * The low word of the result holds ZX, the high word holds
4784      * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
4785      * it doesn't fit in the low 64 bits.
4786      *
4787      * Unlike most ARM math operations, multiply instructions have
4788      * restrictions on using the same register more than once (Rd and Rm
4789      * cannot be the same).
4790      */
4791     /* mul-long vAA, vBB, vCC */
4792     FETCH(r0, 1)                        @ r0<- CCBB
4793     and     r2, r0, #255                @ r2<- BB
4794     mov     r3, r0, lsr #8              @ r3<- CC
4795     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4796     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4797     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4798     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4799     mul     ip, r2, r1                  @  ip<- ZxW
4800     umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
4801     mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
4802     mov     r0, rINST, lsr #8           @ r0<- AA
4803     add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
4804     add     r0, rFP, r0, lsl #2         @ r0<- &fp[AA]
4805     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4806     b       .LOP_MUL_LONG_finish
4807
4808 /* ------------------------------ */
4809     .balign 64
4810 .L_OP_DIV_LONG: /* 0x9e */
4811 /* File: armv5te/OP_DIV_LONG.S */
4812 /* File: armv5te/binopWide.S */
4813     /*
4814      * Generic 64-bit binary operation.  Provide an "instr" line that
4815      * specifies an instruction that performs "result = r0-r1 op r2-r3".
4816      * This could be an ARM instruction or a function call.  (If the result
4817      * comes back in a register other than r0, you can override "result".)
4818      *
4819      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4820      * vCC (r1).  Useful for integer division and modulus.
4821      *
4822      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4823      *      xor-long, add-double, sub-double, mul-double, div-double,
4824      *      rem-double
4825      *
4826      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4827      */
4828     /* binop vAA, vBB, vCC */
4829     FETCH(r0, 1)                        @ r0<- CCBB
4830     mov     r9, rINST, lsr #8           @ r9<- AA
4831     and     r2, r0, #255                @ r2<- BB
4832     mov     r3, r0, lsr #8              @ r3<- CC
4833     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4834     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4835     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4836     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4837     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4838     .if 1
4839     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4840     beq     common_errDivideByZero
4841     .endif
4842     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4843
4844                                @ optional op; may set condition codes
4845     bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4846     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4847     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4848     GOTO_OPCODE(ip)                     @ jump to next instruction
4849     /* 14-17 instructions */
4850
4851
4852
4853 /* ------------------------------ */
4854     .balign 64
4855 .L_OP_REM_LONG: /* 0x9f */
4856 /* File: armv5te/OP_REM_LONG.S */
4857 /* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
4858 /* File: armv5te/binopWide.S */
4859     /*
4860      * Generic 64-bit binary operation.  Provide an "instr" line that
4861      * specifies an instruction that performs "result = r0-r1 op r2-r3".
4862      * This could be an ARM instruction or a function call.  (If the result
4863      * comes back in a register other than r0, you can override "result".)
4864      *
4865      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4866      * vCC (r1).  Useful for integer division and modulus.
4867      *
4868      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4869      *      xor-long, add-double, sub-double, mul-double, div-double,
4870      *      rem-double
4871      *
4872      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4873      */
4874     /* binop vAA, vBB, vCC */
4875     FETCH(r0, 1)                        @ r0<- CCBB
4876     mov     r9, rINST, lsr #8           @ r9<- AA
4877     and     r2, r0, #255                @ r2<- BB
4878     mov     r3, r0, lsr #8              @ r3<- CC
4879     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4880     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4881     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4882     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4883     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4884     .if 1
4885     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4886     beq     common_errDivideByZero
4887     .endif
4888     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4889
4890                                @ optional op; may set condition codes
4891     bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4892     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4893     stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
4894     GOTO_OPCODE(ip)                     @ jump to next instruction
4895     /* 14-17 instructions */
4896
4897
4898
4899 /* ------------------------------ */
4900     .balign 64
4901 .L_OP_AND_LONG: /* 0xa0 */
4902 /* File: armv5te/OP_AND_LONG.S */
4903 /* File: armv5te/binopWide.S */
4904     /*
4905      * Generic 64-bit binary operation.  Provide an "instr" line that
4906      * specifies an instruction that performs "result = r0-r1 op r2-r3".
4907      * This could be an ARM instruction or a function call.  (If the result
4908      * comes back in a register other than r0, you can override "result".)
4909      *
4910      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4911      * vCC (r1).  Useful for integer division and modulus.
4912      *
4913      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4914      *      xor-long, add-double, sub-double, mul-double, div-double,
4915      *      rem-double
4916      *
4917      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4918      */
4919     /* binop vAA, vBB, vCC */
4920     FETCH(r0, 1)                        @ r0<- CCBB
4921     mov     r9, rINST, lsr #8           @ r9<- AA
4922     and     r2, r0, #255                @ r2<- BB
4923     mov     r3, r0, lsr #8              @ r3<- CC
4924     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4925     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4926     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4927     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4928     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4929     .if 0
4930     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4931     beq     common_errDivideByZero
4932     .endif
4933     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4934
4935     and     r0, r0, r2                           @ optional op; may set condition codes
4936     and     r1, r1, r3                              @ result<- op, r0-r3 changed
4937     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4938     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4939     GOTO_OPCODE(ip)                     @ jump to next instruction
4940     /* 14-17 instructions */
4941
4942
4943
4944 /* ------------------------------ */
4945     .balign 64
4946 .L_OP_OR_LONG: /* 0xa1 */
4947 /* File: armv5te/OP_OR_LONG.S */
4948 /* File: armv5te/binopWide.S */
4949     /*
4950      * Generic 64-bit binary operation.  Provide an "instr" line that
4951      * specifies an instruction that performs "result = r0-r1 op r2-r3".
4952      * This could be an ARM instruction or a function call.  (If the result
4953      * comes back in a register other than r0, you can override "result".)
4954      *
4955      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4956      * vCC (r1).  Useful for integer division and modulus.
4957      *
4958      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4959      *      xor-long, add-double, sub-double, mul-double, div-double,
4960      *      rem-double
4961      *
4962      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4963      */
4964     /* binop vAA, vBB, vCC */
4965     FETCH(r0, 1)                        @ r0<- CCBB
4966     mov     r9, rINST, lsr #8           @ r9<- AA
4967     and     r2, r0, #255                @ r2<- BB
4968     mov     r3, r0, lsr #8              @ r3<- CC
4969     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4970     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4971     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4972     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4973     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4974     .if 0
4975     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4976     beq     common_errDivideByZero
4977     .endif
4978     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4979
4980     orr     r0, r0, r2                           @ optional op; may set condition codes
4981     orr     r1, r1, r3                              @ result<- op, r0-r3 changed
4982     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4983     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4984     GOTO_OPCODE(ip)                     @ jump to next instruction
4985     /* 14-17 instructions */
4986
4987
4988
4989 /* ------------------------------ */
4990     .balign 64
4991 .L_OP_XOR_LONG: /* 0xa2 */
4992 /* File: armv5te/OP_XOR_LONG.S */
4993 /* File: armv5te/binopWide.S */
4994     /*
4995      * Generic 64-bit binary operation.  Provide an "instr" line that
4996      * specifies an instruction that performs "result = r0-r1 op r2-r3".
4997      * This could be an ARM instruction or a function call.  (If the result
4998      * comes back in a register other than r0, you can override "result".)
4999      *
5000      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5001      * vCC (r1).  Useful for integer division and modulus.
5002      *
5003      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5004      *      xor-long, add-double, sub-double, mul-double, div-double,
5005      *      rem-double
5006      *
5007      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5008      */
5009     /* binop vAA, vBB, vCC */
5010     FETCH(r0, 1)                        @ r0<- CCBB
5011     mov     r9, rINST, lsr #8           @ r9<- AA
5012     and     r2, r0, #255                @ r2<- BB
5013     mov     r3, r0, lsr #8              @ r3<- CC
5014     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5015     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5016     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5017     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5018     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5019     .if 0
5020     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5021     beq     common_errDivideByZero
5022     .endif
5023     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5024
5025     eor     r0, r0, r2                           @ optional op; may set condition codes
5026     eor     r1, r1, r3                              @ result<- op, r0-r3 changed
5027     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5028     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5029     GOTO_OPCODE(ip)                     @ jump to next instruction
5030     /* 14-17 instructions */
5031
5032
5033
5034 /* ------------------------------ */
5035     .balign 64
5036 .L_OP_SHL_LONG: /* 0xa3 */
5037 /* File: armv5te/OP_SHL_LONG.S */
5038     /*
5039      * Long integer shift.  This is different from the generic 32/64-bit
5040      * binary operations because vAA/vBB are 64-bit but vCC (the shift
5041      * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
5042      * 6 bits of the shift distance.
5043      */
5044     /* shl-long vAA, vBB, vCC */
5045     FETCH(r0, 1)                        @ r0<- CCBB
5046     mov     r9, rINST, lsr #8           @ r9<- AA
5047     and     r3, r0, #255                @ r3<- BB
5048     mov     r0, r0, lsr #8              @ r0<- CC
5049     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
5050     GET_VREG(r2, r0)                    @ r2<- vCC
5051     ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5052     and     r2, r2, #63                 @ r2<- r2 & 0x3f
5053     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5054
5055     mov     r1, r1, asl r2              @  r1<- r1 << r2
5056     rsb     r3, r2, #32                 @  r3<- 32 - r2
5057     orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
5058     subs    ip, r2, #32                 @  ip<- r2 - 32
5059     movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
5060     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5061     b       .LOP_SHL_LONG_finish
5062
5063 /* ------------------------------ */
5064     .balign 64
5065 .L_OP_SHR_LONG: /* 0xa4 */
5066 /* File: armv5te/OP_SHR_LONG.S */
5067     /*
5068      * Long integer shift.  This is different from the generic 32/64-bit
5069      * binary operations because vAA/vBB are 64-bit but vCC (the shift
5070      * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
5071      * 6 bits of the shift distance.
5072      */
5073     /* shr-long vAA, vBB, vCC */
5074     FETCH(r0, 1)                        @ r0<- CCBB
5075     mov     r9, rINST, lsr #8           @ r9<- AA
5076     and     r3, r0, #255                @ r3<- BB
5077     mov     r0, r0, lsr #8              @ r0<- CC
5078     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
5079     GET_VREG(r2, r0)                    @ r2<- vCC
5080     ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5081     and     r2, r2, #63                 @ r0<- r0 & 0x3f
5082     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5083
5084     mov     r0, r0, lsr r2              @  r0<- r2 >> r2
5085     rsb     r3, r2, #32                 @  r3<- 32 - r2
5086     orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
5087     subs    ip, r2, #32                 @  ip<- r2 - 32
5088     movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
5089     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5090     b       .LOP_SHR_LONG_finish
5091
5092 /* ------------------------------ */
5093     .balign 64
5094 .L_OP_USHR_LONG: /* 0xa5 */
5095 /* File: armv5te/OP_USHR_LONG.S */
5096     /*
5097      * Long integer shift.  This is different from the generic 32/64-bit
5098      * binary operations because vAA/vBB are 64-bit but vCC (the shift
5099      * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
5100      * 6 bits of the shift distance.
5101      */
5102     /* ushr-long vAA, vBB, vCC */
5103     FETCH(r0, 1)                        @ r0<- CCBB
5104     mov     r9, rINST, lsr #8           @ r9<- AA
5105     and     r3, r0, #255                @ r3<- BB
5106     mov     r0, r0, lsr #8              @ r0<- CC
5107     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
5108     GET_VREG(r2, r0)                    @ r2<- vCC
5109     ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5110     and     r2, r2, #63                 @ r0<- r0 & 0x3f
5111     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5112
5113     mov     r0, r0, lsr r2              @  r0<- r2 >> r2
5114     rsb     r3, r2, #32                 @  r3<- 32 - r2
5115     orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
5116     subs    ip, r2, #32                 @  ip<- r2 - 32
5117     movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
5118     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5119     b       .LOP_USHR_LONG_finish
5120
5121 /* ------------------------------ */
5122     .balign 64
5123 .L_OP_ADD_FLOAT: /* 0xa6 */
5124 /* File: armv5te/OP_ADD_FLOAT.S */
5125 /* File: armv5te/binop.S */
5126     /*
5127      * Generic 32-bit binary operation.  Provide an "instr" line that
5128      * specifies an instruction that performs "result = r0 op r1".
5129      * This could be an ARM instruction or a function call.  (If the result
5130      * comes back in a register other than r0, you can override "result".)
5131      *
5132      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5133      * vCC (r1).  Useful for integer division and modulus.  Note that we
5134      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5135      * handles it correctly.
5136      *
5137      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5138      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5139      *      mul-float, div-float, rem-float
5140      */
5141     /* binop vAA, vBB, vCC */
5142     FETCH(r0, 1)                        @ r0<- CCBB
5143     mov     r9, rINST, lsr #8           @ r9<- AA
5144     mov     r3, r0, lsr #8              @ r3<- CC
5145     and     r2, r0, #255                @ r2<- BB
5146     GET_VREG(r1, r3)                    @ r1<- vCC
5147     GET_VREG(r0, r2)                    @ r0<- vBB
5148     .if 0
5149     cmp     r1, #0                      @ is second operand zero?
5150     beq     common_errDivideByZero
5151     .endif
5152
5153     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5154                                @ optional op; may set condition codes
5155     bl      __aeabi_fadd                              @ r0<- op, r0-r3 changed
5156     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5157     SET_VREG(r0, r9)               @ vAA<- r0
5158     GOTO_OPCODE(ip)                     @ jump to next instruction
5159     /* 11-14 instructions */
5160
5161
5162
5163 /* ------------------------------ */
5164     .balign 64
5165 .L_OP_SUB_FLOAT: /* 0xa7 */
5166 /* File: armv5te/OP_SUB_FLOAT.S */
5167 /* File: armv5te/binop.S */
5168     /*
5169      * Generic 32-bit binary operation.  Provide an "instr" line that
5170      * specifies an instruction that performs "result = r0 op r1".
5171      * This could be an ARM instruction or a function call.  (If the result
5172      * comes back in a register other than r0, you can override "result".)
5173      *
5174      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5175      * vCC (r1).  Useful for integer division and modulus.  Note that we
5176      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5177      * handles it correctly.
5178      *
5179      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5180      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5181      *      mul-float, div-float, rem-float
5182      */
5183     /* binop vAA, vBB, vCC */
5184     FETCH(r0, 1)                        @ r0<- CCBB
5185     mov     r9, rINST, lsr #8           @ r9<- AA
5186     mov     r3, r0, lsr #8              @ r3<- CC
5187     and     r2, r0, #255                @ r2<- BB
5188     GET_VREG(r1, r3)                    @ r1<- vCC
5189     GET_VREG(r0, r2)                    @ r0<- vBB
5190     .if 0
5191     cmp     r1, #0                      @ is second operand zero?
5192     beq     common_errDivideByZero
5193     .endif
5194
5195     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5196                                @ optional op; may set condition codes
5197     bl      __aeabi_fsub                              @ r0<- op, r0-r3 changed
5198     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5199     SET_VREG(r0, r9)               @ vAA<- r0
5200     GOTO_OPCODE(ip)                     @ jump to next instruction
5201     /* 11-14 instructions */
5202
5203
5204
5205 /* ------------------------------ */
5206     .balign 64
5207 .L_OP_MUL_FLOAT: /* 0xa8 */
5208 /* File: armv5te/OP_MUL_FLOAT.S */
5209 /* File: armv5te/binop.S */
5210     /*
5211      * Generic 32-bit binary operation.  Provide an "instr" line that
5212      * specifies an instruction that performs "result = r0 op r1".
5213      * This could be an ARM instruction or a function call.  (If the result
5214      * comes back in a register other than r0, you can override "result".)
5215      *
5216      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5217      * vCC (r1).  Useful for integer division and modulus.  Note that we
5218      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5219      * handles it correctly.
5220      *
5221      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5222      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5223      *      mul-float, div-float, rem-float
5224      */
5225     /* binop vAA, vBB, vCC */
5226     FETCH(r0, 1)                        @ r0<- CCBB
5227     mov     r9, rINST, lsr #8           @ r9<- AA
5228     mov     r3, r0, lsr #8              @ r3<- CC
5229     and     r2, r0, #255                @ r2<- BB
5230     GET_VREG(r1, r3)                    @ r1<- vCC
5231     GET_VREG(r0, r2)                    @ r0<- vBB
5232     .if 0
5233     cmp     r1, #0                      @ is second operand zero?
5234     beq     common_errDivideByZero
5235     .endif
5236
5237     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5238                                @ optional op; may set condition codes
5239     bl      __aeabi_fmul                              @ r0<- op, r0-r3 changed
5240     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5241     SET_VREG(r0, r9)               @ vAA<- r0
5242     GOTO_OPCODE(ip)                     @ jump to next instruction
5243     /* 11-14 instructions */
5244
5245
5246
5247 /* ------------------------------ */
5248     .balign 64
5249 .L_OP_DIV_FLOAT: /* 0xa9 */
5250 /* File: armv5te/OP_DIV_FLOAT.S */
5251 /* File: armv5te/binop.S */
5252     /*
5253      * Generic 32-bit binary operation.  Provide an "instr" line that
5254      * specifies an instruction that performs "result = r0 op r1".
5255      * This could be an ARM instruction or a function call.  (If the result
5256      * comes back in a register other than r0, you can override "result".)
5257      *
5258      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5259      * vCC (r1).  Useful for integer division and modulus.  Note that we
5260      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5261      * handles it correctly.
5262      *
5263      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5264      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5265      *      mul-float, div-float, rem-float
5266      */
5267     /* binop vAA, vBB, vCC */
5268     FETCH(r0, 1)                        @ r0<- CCBB
5269     mov     r9, rINST, lsr #8           @ r9<- AA
5270     mov     r3, r0, lsr #8              @ r3<- CC
5271     and     r2, r0, #255                @ r2<- BB
5272     GET_VREG(r1, r3)                    @ r1<- vCC
5273     GET_VREG(r0, r2)                    @ r0<- vBB
5274     .if 0
5275     cmp     r1, #0                      @ is second operand zero?
5276     beq     common_errDivideByZero
5277     .endif
5278
5279     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5280                                @ optional op; may set condition codes
5281     bl      __aeabi_fdiv                              @ r0<- op, r0-r3 changed
5282     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5283     SET_VREG(r0, r9)               @ vAA<- r0
5284     GOTO_OPCODE(ip)                     @ jump to next instruction
5285     /* 11-14 instructions */
5286
5287
5288
5289 /* ------------------------------ */
5290     .balign 64
5291 .L_OP_REM_FLOAT: /* 0xaa */
5292 /* File: armv5te/OP_REM_FLOAT.S */
5293 /* EABI doesn't define a float remainder function, but libm does */
5294 /* File: armv5te/binop.S */
5295     /*
5296      * Generic 32-bit binary operation.  Provide an "instr" line that
5297      * specifies an instruction that performs "result = r0 op r1".
5298      * This could be an ARM instruction or a function call.  (If the result
5299      * comes back in a register other than r0, you can override "result".)
5300      *
5301      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5302      * vCC (r1).  Useful for integer division and modulus.  Note that we
5303      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5304      * handles it correctly.
5305      *
5306      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5307      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5308      *      mul-float, div-float, rem-float
5309      */
5310     /* binop vAA, vBB, vCC */
5311     FETCH(r0, 1)                        @ r0<- CCBB
5312     mov     r9, rINST, lsr #8           @ r9<- AA
5313     mov     r3, r0, lsr #8              @ r3<- CC
5314     and     r2, r0, #255                @ r2<- BB
5315     GET_VREG(r1, r3)                    @ r1<- vCC
5316     GET_VREG(r0, r2)                    @ r0<- vBB
5317     .if 0
5318     cmp     r1, #0                      @ is second operand zero?
5319     beq     common_errDivideByZero
5320     .endif
5321
5322     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5323                                @ optional op; may set condition codes
5324     bl      fmodf                              @ r0<- op, r0-r3 changed
5325     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5326     SET_VREG(r0, r9)               @ vAA<- r0
5327     GOTO_OPCODE(ip)                     @ jump to next instruction
5328     /* 11-14 instructions */
5329
5330
5331
5332 /* ------------------------------ */
5333     .balign 64
5334 .L_OP_ADD_DOUBLE: /* 0xab */
5335 /* File: armv5te/OP_ADD_DOUBLE.S */
5336 /* File: armv5te/binopWide.S */
5337     /*
5338      * Generic 64-bit binary operation.  Provide an "instr" line that
5339      * specifies an instruction that performs "result = r0-r1 op r2-r3".
5340      * This could be an ARM instruction or a function call.  (If the result
5341      * comes back in a register other than r0, you can override "result".)
5342      *
5343      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5344      * vCC (r1).  Useful for integer division and modulus.
5345      *
5346      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5347      *      xor-long, add-double, sub-double, mul-double, div-double,
5348      *      rem-double
5349      *
5350      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5351      */
5352     /* binop vAA, vBB, vCC */
5353     FETCH(r0, 1)                        @ r0<- CCBB
5354     mov     r9, rINST, lsr #8           @ r9<- AA
5355     and     r2, r0, #255                @ r2<- BB
5356     mov     r3, r0, lsr #8              @ r3<- CC
5357     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5358     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5359     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5360     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5361     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5362     .if 0
5363     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5364     beq     common_errDivideByZero
5365     .endif
5366     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5367
5368                                @ optional op; may set condition codes
5369     bl      __aeabi_dadd                              @ result<- op, r0-r3 changed
5370     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5371     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5372     GOTO_OPCODE(ip)                     @ jump to next instruction
5373     /* 14-17 instructions */
5374
5375
5376
5377 /* ------------------------------ */
5378     .balign 64
5379 .L_OP_SUB_DOUBLE: /* 0xac */
5380 /* File: armv5te/OP_SUB_DOUBLE.S */
5381 /* File: armv5te/binopWide.S */
5382     /*
5383      * Generic 64-bit binary operation.  Provide an "instr" line that
5384      * specifies an instruction that performs "result = r0-r1 op r2-r3".
5385      * This could be an ARM instruction or a function call.  (If the result
5386      * comes back in a register other than r0, you can override "result".)
5387      *
5388      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5389      * vCC (r1).  Useful for integer division and modulus.
5390      *
5391      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5392      *      xor-long, add-double, sub-double, mul-double, div-double,
5393      *      rem-double
5394      *
5395      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5396      */
5397     /* binop vAA, vBB, vCC */
5398     FETCH(r0, 1)                        @ r0<- CCBB
5399     mov     r9, rINST, lsr #8           @ r9<- AA
5400     and     r2, r0, #255                @ r2<- BB
5401     mov     r3, r0, lsr #8              @ r3<- CC
5402     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5403     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5404     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5405     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5406     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5407     .if 0
5408     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5409     beq     common_errDivideByZero
5410     .endif
5411     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5412
5413                                @ optional op; may set condition codes
5414     bl      __aeabi_dsub                              @ result<- op, r0-r3 changed
5415     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5416     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5417     GOTO_OPCODE(ip)                     @ jump to next instruction
5418     /* 14-17 instructions */
5419
5420
5421
5422 /* ------------------------------ */
5423     .balign 64
5424 .L_OP_MUL_DOUBLE: /* 0xad */
5425 /* File: armv5te/OP_MUL_DOUBLE.S */
5426 /* File: armv5te/binopWide.S */
5427     /*
5428      * Generic 64-bit binary operation.  Provide an "instr" line that
5429      * specifies an instruction that performs "result = r0-r1 op r2-r3".
5430      * This could be an ARM instruction or a function call.  (If the result
5431      * comes back in a register other than r0, you can override "result".)
5432      *
5433      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5434      * vCC (r1).  Useful for integer division and modulus.
5435      *
5436      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5437      *      xor-long, add-double, sub-double, mul-double, div-double,
5438      *      rem-double
5439      *
5440      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5441      */
5442     /* binop vAA, vBB, vCC */
5443     FETCH(r0, 1)                        @ r0<- CCBB
5444     mov     r9, rINST, lsr #8           @ r9<- AA
5445     and     r2, r0, #255                @ r2<- BB
5446     mov     r3, r0, lsr #8              @ r3<- CC
5447     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5448     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5449     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5450     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5451     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5452     .if 0
5453     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5454     beq     common_errDivideByZero
5455     .endif
5456     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5457
5458                                @ optional op; may set condition codes
5459     bl      __aeabi_dmul                              @ result<- op, r0-r3 changed
5460     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5461     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5462     GOTO_OPCODE(ip)                     @ jump to next instruction
5463     /* 14-17 instructions */
5464
5465
5466
5467 /* ------------------------------ */
5468     .balign 64
5469 .L_OP_DIV_DOUBLE: /* 0xae */
5470 /* File: armv5te/OP_DIV_DOUBLE.S */
5471 /* File: armv5te/binopWide.S */
5472     /*
5473      * Generic 64-bit binary operation.  Provide an "instr" line that
5474      * specifies an instruction that performs "result = r0-r1 op r2-r3".
5475      * This could be an ARM instruction or a function call.  (If the result
5476      * comes back in a register other than r0, you can override "result".)
5477      *
5478      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5479      * vCC (r1).  Useful for integer division and modulus.
5480      *
5481      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5482      *      xor-long, add-double, sub-double, mul-double, div-double,
5483      *      rem-double
5484      *
5485      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5486      */
5487     /* binop vAA, vBB, vCC */
5488     FETCH(r0, 1)                        @ r0<- CCBB
5489     mov     r9, rINST, lsr #8           @ r9<- AA
5490     and     r2, r0, #255                @ r2<- BB
5491     mov     r3, r0, lsr #8              @ r3<- CC
5492     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5493     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5494     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5495     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5496     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5497     .if 0
5498     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5499     beq     common_errDivideByZero
5500     .endif
5501     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5502
5503                                @ optional op; may set condition codes
5504     bl      __aeabi_ddiv                              @ result<- op, r0-r3 changed
5505     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5506     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5507     GOTO_OPCODE(ip)                     @ jump to next instruction
5508     /* 14-17 instructions */
5509
5510
5511
5512 /* ------------------------------ */
5513     .balign 64
5514 .L_OP_REM_DOUBLE: /* 0xaf */
5515 /* File: armv5te/OP_REM_DOUBLE.S */
5516 /* EABI doesn't define a double remainder function, but libm does */
5517 /* File: armv5te/binopWide.S */
5518     /*
5519      * Generic 64-bit binary operation.  Provide an "instr" line that
5520      * specifies an instruction that performs "result = r0-r1 op r2-r3".
5521      * This could be an ARM instruction or a function call.  (If the result
5522      * comes back in a register other than r0, you can override "result".)
5523      *
5524      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5525      * vCC (r1).  Useful for integer division and modulus.
5526      *
5527      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5528      *      xor-long, add-double, sub-double, mul-double, div-double,
5529      *      rem-double
5530      *
5531      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5532      */
5533     /* binop vAA, vBB, vCC */
5534     FETCH(r0, 1)                        @ r0<- CCBB
5535     mov     r9, rINST, lsr #8           @ r9<- AA
5536     and     r2, r0, #255                @ r2<- BB
5537     mov     r3, r0, lsr #8              @ r3<- CC
5538     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5539     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5540     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5541     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5542     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5543     .if 0
5544     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5545     beq     common_errDivideByZero
5546     .endif
5547     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5548
5549                                @ optional op; may set condition codes
5550     bl      fmod                              @ result<- op, r0-r3 changed
5551     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5552     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5553     GOTO_OPCODE(ip)                     @ jump to next instruction
5554     /* 14-17 instructions */
5555
5556
5557
5558 /* ------------------------------ */
5559     .balign 64
5560 .L_OP_ADD_INT_2ADDR: /* 0xb0 */
5561 /* File: armv5te/OP_ADD_INT_2ADDR.S */
5562 /* File: armv5te/binop2addr.S */
5563     /*
5564      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5565      * that specifies an instruction that performs "result = r0 op r1".
5566      * This could be an ARM instruction or a function call.  (If the result
5567      * comes back in a register other than r0, you can override "result".)
5568      *
5569      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5570      * vCC (r1).  Useful for integer division and modulus.
5571      *
5572      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5573      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5574      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5575      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5576      */
5577     /* binop/2addr vA, vB */
5578     mov     r9, rINST, lsr #8           @ r9<- A+
5579     mov     r3, rINST, lsr #12          @ r3<- B
5580     and     r9, r9, #15
5581     GET_VREG(r1, r3)                    @ r1<- vB
5582     GET_VREG(r0, r9)                    @ r0<- vA
5583     .if 0
5584     cmp     r1, #0                      @ is second operand zero?
5585     beq     common_errDivideByZero
5586     .endif
5587     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5588
5589                                @ optional op; may set condition codes
5590     add     r0, r0, r1                              @ r0<- op, r0-r3 changed
5591     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5592     SET_VREG(r0, r9)               @ vAA<- r0
5593     GOTO_OPCODE(ip)                     @ jump to next instruction
5594     /* 10-13 instructions */
5595
5596
5597
5598 /* ------------------------------ */
5599     .balign 64
5600 .L_OP_SUB_INT_2ADDR: /* 0xb1 */
5601 /* File: armv5te/OP_SUB_INT_2ADDR.S */
5602 /* File: armv5te/binop2addr.S */
5603     /*
5604      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5605      * that specifies an instruction that performs "result = r0 op r1".
5606      * This could be an ARM instruction or a function call.  (If the result
5607      * comes back in a register other than r0, you can override "result".)
5608      *
5609      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5610      * vCC (r1).  Useful for integer division and modulus.
5611      *
5612      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5613      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5614      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5615      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5616      */
5617     /* binop/2addr vA, vB */
5618     mov     r9, rINST, lsr #8           @ r9<- A+
5619     mov     r3, rINST, lsr #12          @ r3<- B
5620     and     r9, r9, #15
5621     GET_VREG(r1, r3)                    @ r1<- vB
5622     GET_VREG(r0, r9)                    @ r0<- vA
5623     .if 0
5624     cmp     r1, #0                      @ is second operand zero?
5625     beq     common_errDivideByZero
5626     .endif
5627     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5628
5629                                @ optional op; may set condition codes
5630     sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
5631     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5632     SET_VREG(r0, r9)               @ vAA<- r0
5633     GOTO_OPCODE(ip)                     @ jump to next instruction
5634     /* 10-13 instructions */
5635
5636
5637
5638 /* ------------------------------ */
5639     .balign 64
5640 .L_OP_MUL_INT_2ADDR: /* 0xb2 */
5641 /* File: armv5te/OP_MUL_INT_2ADDR.S */
5642 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
5643 /* File: armv5te/binop2addr.S */
5644     /*
5645      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5646      * that specifies an instruction that performs "result = r0 op r1".
5647      * This could be an ARM instruction or a function call.  (If the result
5648      * comes back in a register other than r0, you can override "result".)
5649      *
5650      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5651      * vCC (r1).  Useful for integer division and modulus.
5652      *
5653      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5654      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5655      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5656      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5657      */
5658     /* binop/2addr vA, vB */
5659     mov     r9, rINST, lsr #8           @ r9<- A+
5660     mov     r3, rINST, lsr #12          @ r3<- B
5661     and     r9, r9, #15
5662     GET_VREG(r1, r3)                    @ r1<- vB
5663     GET_VREG(r0, r9)                    @ r0<- vA
5664     .if 0
5665     cmp     r1, #0                      @ is second operand zero?
5666     beq     common_errDivideByZero
5667     .endif
5668     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5669
5670                                @ optional op; may set condition codes
5671     mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
5672     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5673     SET_VREG(r0, r9)               @ vAA<- r0
5674     GOTO_OPCODE(ip)                     @ jump to next instruction
5675     /* 10-13 instructions */
5676
5677
5678
5679 /* ------------------------------ */
5680     .balign 64
5681 .L_OP_DIV_INT_2ADDR: /* 0xb3 */
5682 /* File: armv5te/OP_DIV_INT_2ADDR.S */
5683 /* File: armv5te/binop2addr.S */
5684     /*
5685      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5686      * that specifies an instruction that performs "result = r0 op r1".
5687      * This could be an ARM instruction or a function call.  (If the result
5688      * comes back in a register other than r0, you can override "result".)
5689      *
5690      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5691      * vCC (r1).  Useful for integer division and modulus.
5692      *
5693      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5694      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5695      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5696      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5697      */
5698     /* binop/2addr vA, vB */
5699     mov     r9, rINST, lsr #8           @ r9<- A+
5700     mov     r3, rINST, lsr #12          @ r3<- B
5701     and     r9, r9, #15
5702     GET_VREG(r1, r3)                    @ r1<- vB
5703     GET_VREG(r0, r9)                    @ r0<- vA
5704     .if 1
5705     cmp     r1, #0                      @ is second operand zero?
5706     beq     common_errDivideByZero
5707     .endif
5708     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5709
5710                                @ optional op; may set condition codes
5711     bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
5712     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5713     SET_VREG(r0, r9)               @ vAA<- r0
5714     GOTO_OPCODE(ip)                     @ jump to next instruction
5715     /* 10-13 instructions */
5716
5717
5718
5719 /* ------------------------------ */
5720     .balign 64
5721 .L_OP_REM_INT_2ADDR: /* 0xb4 */
5722 /* File: armv5te/OP_REM_INT_2ADDR.S */
5723 /* idivmod returns quotient in r0 and remainder in r1 */
5724 /* File: armv5te/binop2addr.S */
5725     /*
5726      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5727      * that specifies an instruction that performs "result = r0 op r1".
5728      * This could be an ARM instruction or a function call.  (If the result
5729      * comes back in a register other than r0, you can override "result".)
5730      *
5731      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5732      * vCC (r1).  Useful for integer division and modulus.
5733      *
5734      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5735      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5736      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5737      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5738      */
5739     /* binop/2addr vA, vB */
5740     mov     r9, rINST, lsr #8           @ r9<- A+
5741     mov     r3, rINST, lsr #12          @ r3<- B
5742     and     r9, r9, #15
5743     GET_VREG(r1, r3)                    @ r1<- vB
5744     GET_VREG(r0, r9)                    @ r0<- vA
5745     .if 1
5746     cmp     r1, #0                      @ is second operand zero?
5747     beq     common_errDivideByZero
5748     .endif
5749     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5750
5751                                @ optional op; may set condition codes
5752     bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
5753     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5754     SET_VREG(r1, r9)               @ vAA<- r1
5755     GOTO_OPCODE(ip)                     @ jump to next instruction
5756     /* 10-13 instructions */
5757
5758
5759
5760 /* ------------------------------ */
5761     .balign 64
5762 .L_OP_AND_INT_2ADDR: /* 0xb5 */
5763 /* File: armv5te/OP_AND_INT_2ADDR.S */
5764 /* File: armv5te/binop2addr.S */
5765     /*
5766      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5767      * that specifies an instruction that performs "result = r0 op r1".
5768      * This could be an ARM instruction or a function call.  (If the result
5769      * comes back in a register other than r0, you can override "result".)
5770      *
5771      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5772      * vCC (r1).  Useful for integer division and modulus.
5773      *
5774      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5775      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5776      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5777      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5778      */
5779     /* binop/2addr vA, vB */
5780     mov     r9, rINST, lsr #8           @ r9<- A+
5781     mov     r3, rINST, lsr #12          @ r3<- B
5782     and     r9, r9, #15
5783     GET_VREG(r1, r3)                    @ r1<- vB
5784     GET_VREG(r0, r9)                    @ r0<- vA
5785     .if 0
5786     cmp     r1, #0                      @ is second operand zero?
5787     beq     common_errDivideByZero
5788     .endif
5789     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5790
5791                                @ optional op; may set condition codes
5792     and     r0, r0, r1                              @ r0<- op, r0-r3 changed
5793     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5794     SET_VREG(r0, r9)               @ vAA<- r0
5795     GOTO_OPCODE(ip)                     @ jump to next instruction
5796     /* 10-13 instructions */
5797
5798
5799
5800 /* ------------------------------ */
5801     .balign 64
5802 .L_OP_OR_INT_2ADDR: /* 0xb6 */
5803 /* File: armv5te/OP_OR_INT_2ADDR.S */
5804 /* File: armv5te/binop2addr.S */
5805     /*
5806      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5807      * that specifies an instruction that performs "result = r0 op r1".
5808      * This could be an ARM instruction or a function call.  (If the result
5809      * comes back in a register other than r0, you can override "result".)
5810      *
5811      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5812      * vCC (r1).  Useful for integer division and modulus.
5813      *
5814      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5815      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5816      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5817      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5818      */
5819     /* binop/2addr vA, vB */
5820     mov     r9, rINST, lsr #8           @ r9<- A+
5821     mov     r3, rINST, lsr #12          @ r3<- B
5822     and     r9, r9, #15
5823     GET_VREG(r1, r3)                    @ r1<- vB
5824     GET_VREG(r0, r9)                    @ r0<- vA
5825     .if 0
5826     cmp     r1, #0                      @ is second operand zero?
5827     beq     common_errDivideByZero
5828     .endif
5829     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5830
5831                                @ optional op; may set condition codes
5832     orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
5833     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5834     SET_VREG(r0, r9)               @ vAA<- r0
5835     GOTO_OPCODE(ip)                     @ jump to next instruction
5836     /* 10-13 instructions */
5837
5838
5839
5840 /* ------------------------------ */
5841     .balign 64
5842 .L_OP_XOR_INT_2ADDR: /* 0xb7 */
5843 /* File: armv5te/OP_XOR_INT_2ADDR.S */
5844 /* File: armv5te/binop2addr.S */
5845     /*
5846      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5847      * that specifies an instruction that performs "result = r0 op r1".
5848      * This could be an ARM instruction or a function call.  (If the result
5849      * comes back in a register other than r0, you can override "result".)
5850      *
5851      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5852      * vCC (r1).  Useful for integer division and modulus.
5853      *
5854      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5855      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5856      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5857      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5858      */
5859     /* binop/2addr vA, vB */
5860     mov     r9, rINST, lsr #8           @ r9<- A+
5861     mov     r3, rINST, lsr #12          @ r3<- B
5862     and     r9, r9, #15
5863     GET_VREG(r1, r3)                    @ r1<- vB
5864     GET_VREG(r0, r9)                    @ r0<- vA
5865     .if 0
5866     cmp     r1, #0                      @ is second operand zero?
5867     beq     common_errDivideByZero
5868     .endif
5869     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5870
5871                                @ optional op; may set condition codes
5872     eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
5873     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5874     SET_VREG(r0, r9)               @ vAA<- r0
5875     GOTO_OPCODE(ip)                     @ jump to next instruction
5876     /* 10-13 instructions */
5877
5878
5879
5880 /* ------------------------------ */
5881     .balign 64
5882 .L_OP_SHL_INT_2ADDR: /* 0xb8 */
5883 /* File: armv5te/OP_SHL_INT_2ADDR.S */
5884 /* File: armv5te/binop2addr.S */
5885     /*
5886      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5887      * that specifies an instruction that performs "result = r0 op r1".
5888      * This could be an ARM instruction or a function call.  (If the result
5889      * comes back in a register other than r0, you can override "result".)
5890      *
5891      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5892      * vCC (r1).  Useful for integer division and modulus.
5893      *
5894      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5895      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5896      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5897      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5898      */
5899     /* binop/2addr vA, vB */
5900     mov     r9, rINST, lsr #8           @ r9<- A+
5901     mov     r3, rINST, lsr #12          @ r3<- B
5902     and     r9, r9, #15
5903     GET_VREG(r1, r3)                    @ r1<- vB
5904     GET_VREG(r0, r9)                    @ r0<- vA
5905     .if 0
5906     cmp     r1, #0                      @ is second operand zero?
5907     beq     common_errDivideByZero
5908     .endif
5909     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5910
5911     and     r1, r1, #31                           @ optional op; may set condition codes
5912     mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
5913     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5914     SET_VREG(r0, r9)               @ vAA<- r0
5915     GOTO_OPCODE(ip)                     @ jump to next instruction
5916     /* 10-13 instructions */
5917
5918
5919
5920 /* ------------------------------ */
5921     .balign 64
5922 .L_OP_SHR_INT_2ADDR: /* 0xb9 */
5923 /* File: armv5te/OP_SHR_INT_2ADDR.S */
5924 /* File: armv5te/binop2addr.S */
5925     /*
5926      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5927      * that specifies an instruction that performs "result = r0 op r1".
5928      * This could be an ARM instruction or a function call.  (If the result
5929      * comes back in a register other than r0, you can override "result".)
5930      *
5931      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5932      * vCC (r1).  Useful for integer division and modulus.
5933      *
5934      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5935      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5936      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5937      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5938      */
5939     /* binop/2addr vA, vB */
5940     mov     r9, rINST, lsr #8           @ r9<- A+
5941     mov     r3, rINST, lsr #12          @ r3<- B
5942     and     r9, r9, #15
5943     GET_VREG(r1, r3)                    @ r1<- vB
5944     GET_VREG(r0, r9)                    @ r0<- vA
5945     .if 0
5946     cmp     r1, #0                      @ is second operand zero?
5947     beq     common_errDivideByZero
5948     .endif
5949     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5950
5951     and     r1, r1, #31                           @ optional op; may set condition codes
5952     mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
5953     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5954     SET_VREG(r0, r9)               @ vAA<- r0
5955     GOTO_OPCODE(ip)                     @ jump to next instruction
5956     /* 10-13 instructions */
5957
5958
5959
5960 /* ------------------------------ */
5961     .balign 64
5962 .L_OP_USHR_INT_2ADDR: /* 0xba */
5963 /* File: armv5te/OP_USHR_INT_2ADDR.S */
5964 /* File: armv5te/binop2addr.S */
5965     /*
5966      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5967      * that specifies an instruction that performs "result = r0 op r1".
5968      * This could be an ARM instruction or a function call.  (If the result
5969      * comes back in a register other than r0, you can override "result".)
5970      *
5971      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5972      * vCC (r1).  Useful for integer division and modulus.
5973      *
5974      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5975      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5976      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5977      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5978      */
5979     /* binop/2addr vA, vB */
5980     mov     r9, rINST, lsr #8           @ r9<- A+
5981     mov     r3, rINST, lsr #12          @ r3<- B
5982     and     r9, r9, #15
5983     GET_VREG(r1, r3)                    @ r1<- vB
5984     GET_VREG(r0, r9)                    @ r0<- vA
5985     .if 0
5986     cmp     r1, #0                      @ is second operand zero?
5987     beq     common_errDivideByZero
5988     .endif
5989     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5990
5991     and     r1, r1, #31                           @ optional op; may set condition codes
5992     mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
5993     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5994     SET_VREG(r0, r9)               @ vAA<- r0
5995     GOTO_OPCODE(ip)                     @ jump to next instruction
5996     /* 10-13 instructions */
5997
5998
5999
6000 /* ------------------------------ */
6001     .balign 64
6002 .L_OP_ADD_LONG_2ADDR: /* 0xbb */
6003 /* File: armv5te/OP_ADD_LONG_2ADDR.S */
6004 /* File: armv5te/binopWide2addr.S */
6005     /*
6006      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6007      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6008      * This could be an ARM instruction or a function call.  (If the result
6009      * comes back in a register other than r0, you can override "result".)
6010      *
6011      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6012      * vCC (r1).  Useful for integer division and modulus.
6013      *
6014      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6015      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6016      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6017      *      rem-double/2addr
6018      */
6019     /* binop/2addr vA, vB */
6020     mov     r9, rINST, lsr #8           @ r9<- A+
6021     mov     r1, rINST, lsr #12          @ r1<- B
6022     and     r9, r9, #15
6023     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6024     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6025     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6026     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6027     .if 0
6028     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6029     beq     common_errDivideByZero
6030     .endif
6031     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6032
6033     adds    r0, r0, r2                           @ optional op; may set condition codes
6034     adc     r1, r1, r3                              @ result<- op, r0-r3 changed
6035     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6036     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6037     GOTO_OPCODE(ip)                     @ jump to next instruction
6038     /* 12-15 instructions */
6039
6040
6041
6042 /* ------------------------------ */
6043     .balign 64
6044 .L_OP_SUB_LONG_2ADDR: /* 0xbc */
6045 /* File: armv5te/OP_SUB_LONG_2ADDR.S */
6046 /* File: armv5te/binopWide2addr.S */
6047     /*
6048      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6049      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6050      * This could be an ARM instruction or a function call.  (If the result
6051      * comes back in a register other than r0, you can override "result".)
6052      *
6053      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6054      * vCC (r1).  Useful for integer division and modulus.
6055      *
6056      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6057      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6058      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6059      *      rem-double/2addr
6060      */
6061     /* binop/2addr vA, vB */
6062     mov     r9, rINST, lsr #8           @ r9<- A+
6063     mov     r1, rINST, lsr #12          @ r1<- B
6064     and     r9, r9, #15
6065     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6066     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6067     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6068     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6069     .if 0
6070     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6071     beq     common_errDivideByZero
6072     .endif
6073     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6074
6075     subs    r0, r0, r2                           @ optional op; may set condition codes
6076     sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
6077     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6078     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6079     GOTO_OPCODE(ip)                     @ jump to next instruction
6080     /* 12-15 instructions */
6081
6082
6083
6084 /* ------------------------------ */
6085     .balign 64
6086 .L_OP_MUL_LONG_2ADDR: /* 0xbd */
6087 /* File: armv5te/OP_MUL_LONG_2ADDR.S */
6088     /*
6089      * Signed 64-bit integer multiply, "/2addr" version.
6090      *
6091      * See OP_MUL_LONG for an explanation.
6092      *
6093      * We get a little tight on registers, so to avoid looking up &fp[A]
6094      * again we stuff it into rINST.
6095      */
6096     /* mul-long/2addr vA, vB */
6097     mov     r9, rINST, lsr #8           @ r9<- A+
6098     mov     r1, rINST, lsr #12          @ r1<- B
6099     and     r9, r9, #15
6100     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6101     add     rINST, rFP, r9, lsl #2      @ rINST<- &fp[A]
6102     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6103     ldmia   rINST, {r0-r1}              @ r0/r1<- vAA/vAA+1
6104     mul     ip, r2, r1                  @  ip<- ZxW
6105     umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
6106     mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
6107     mov     r0, rINST                   @ r0<- &fp[A] (free up rINST)
6108     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6109     add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
6110     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6111     stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
6112     GOTO_OPCODE(ip)                     @ jump to next instruction
6113
6114
6115 /* ------------------------------ */
6116     .balign 64
6117 .L_OP_DIV_LONG_2ADDR: /* 0xbe */
6118 /* File: armv5te/OP_DIV_LONG_2ADDR.S */
6119 /* File: armv5te/binopWide2addr.S */
6120     /*
6121      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6122      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6123      * This could be an ARM instruction or a function call.  (If the result
6124      * comes back in a register other than r0, you can override "result".)
6125      *
6126      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6127      * vCC (r1).  Useful for integer division and modulus.
6128      *
6129      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6130      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6131      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6132      *      rem-double/2addr
6133      */
6134     /* binop/2addr vA, vB */
6135     mov     r9, rINST, lsr #8           @ r9<- A+
6136     mov     r1, rINST, lsr #12          @ r1<- B
6137     and     r9, r9, #15
6138     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6139     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6140     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6141     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6142     .if 1
6143     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6144     beq     common_errDivideByZero
6145     .endif
6146     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6147
6148                                @ optional op; may set condition codes
6149     bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
6150     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6151     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6152     GOTO_OPCODE(ip)                     @ jump to next instruction
6153     /* 12-15 instructions */
6154
6155
6156
6157 /* ------------------------------ */
6158     .balign 64
6159 .L_OP_REM_LONG_2ADDR: /* 0xbf */
6160 /* File: armv5te/OP_REM_LONG_2ADDR.S */
6161 /* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
6162 /* File: armv5te/binopWide2addr.S */
6163     /*
6164      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6165      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6166      * This could be an ARM instruction or a function call.  (If the result
6167      * comes back in a register other than r0, you can override "result".)
6168      *
6169      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6170      * vCC (r1).  Useful for integer division and modulus.
6171      *
6172      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6173      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6174      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6175      *      rem-double/2addr
6176      */
6177     /* binop/2addr vA, vB */
6178     mov     r9, rINST, lsr #8           @ r9<- A+
6179     mov     r1, rINST, lsr #12          @ r1<- B
6180     and     r9, r9, #15
6181     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6182     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6183     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6184     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6185     .if 1
6186     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6187     beq     common_errDivideByZero
6188     .endif
6189     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6190
6191                                @ optional op; may set condition codes
6192     bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
6193     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6194     stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
6195     GOTO_OPCODE(ip)                     @ jump to next instruction
6196     /* 12-15 instructions */
6197
6198
6199
6200 /* ------------------------------ */
6201     .balign 64
6202 .L_OP_AND_LONG_2ADDR: /* 0xc0 */
6203 /* File: armv5te/OP_AND_LONG_2ADDR.S */
6204 /* File: armv5te/binopWide2addr.S */
6205     /*
6206      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6207      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6208      * This could be an ARM instruction or a function call.  (If the result
6209      * comes back in a register other than r0, you can override "result".)
6210      *
6211      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6212      * vCC (r1).  Useful for integer division and modulus.
6213      *
6214      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6215      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6216      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6217      *      rem-double/2addr
6218      */
6219     /* binop/2addr vA, vB */
6220     mov     r9, rINST, lsr #8           @ r9<- A+
6221     mov     r1, rINST, lsr #12          @ r1<- B
6222     and     r9, r9, #15
6223     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6224     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6225     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6226     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6227     .if 0
6228     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6229     beq     common_errDivideByZero
6230     .endif
6231     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6232
6233     and     r0, r0, r2                           @ optional op; may set condition codes
6234     and     r1, r1, r3                              @ result<- op, r0-r3 changed
6235     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6236     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6237     GOTO_OPCODE(ip)                     @ jump to next instruction
6238     /* 12-15 instructions */
6239
6240
6241
6242 /* ------------------------------ */
6243     .balign 64
6244 .L_OP_OR_LONG_2ADDR: /* 0xc1 */
6245 /* File: armv5te/OP_OR_LONG_2ADDR.S */
6246 /* File: armv5te/binopWide2addr.S */
6247     /*
6248      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6249      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6250      * This could be an ARM instruction or a function call.  (If the result
6251      * comes back in a register other than r0, you can override "result".)
6252      *
6253      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6254      * vCC (r1).  Useful for integer division and modulus.
6255      *
6256      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6257      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6258      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6259      *      rem-double/2addr
6260      */
6261     /* binop/2addr vA, vB */
6262     mov     r9, rINST, lsr #8           @ r9<- A+
6263     mov     r1, rINST, lsr #12          @ r1<- B
6264     and     r9, r9, #15
6265     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6266     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6267     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6268     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6269     .if 0
6270     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6271     beq     common_errDivideByZero
6272     .endif
6273     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6274
6275     orr     r0, r0, r2                           @ optional op; may set condition codes
6276     orr     r1, r1, r3                              @ result<- op, r0-r3 changed
6277     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6278     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6279     GOTO_OPCODE(ip)                     @ jump to next instruction
6280     /* 12-15 instructions */
6281
6282
6283
6284 /* ------------------------------ */
6285     .balign 64
6286 .L_OP_XOR_LONG_2ADDR: /* 0xc2 */
6287 /* File: armv5te/OP_XOR_LONG_2ADDR.S */
6288 /* File: armv5te/binopWide2addr.S */
6289     /*
6290      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6291      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6292      * This could be an ARM instruction or a function call.  (If the result
6293      * comes back in a register other than r0, you can override "result".)
6294      *
6295      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6296      * vCC (r1).  Useful for integer division and modulus.
6297      *
6298      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6299      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6300      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6301      *      rem-double/2addr
6302      */
6303     /* binop/2addr vA, vB */
6304     mov     r9, rINST, lsr #8           @ r9<- A+
6305     mov     r1, rINST, lsr #12          @ r1<- B
6306     and     r9, r9, #15
6307     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6308     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6309     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6310     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6311     .if 0
6312     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6313     beq     common_errDivideByZero
6314     .endif
6315     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6316
6317     eor     r0, r0, r2                           @ optional op; may set condition codes
6318     eor     r1, r1, r3                              @ result<- op, r0-r3 changed
6319     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6320     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6321     GOTO_OPCODE(ip)                     @ jump to next instruction
6322     /* 12-15 instructions */
6323
6324
6325
6326 /* ------------------------------ */
6327     .balign 64
6328 .L_OP_SHL_LONG_2ADDR: /* 0xc3 */
6329 /* File: armv5te/OP_SHL_LONG_2ADDR.S */
6330     /*
6331      * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6332      * 32-bit shift distance.
6333      */
6334     /* shl-long/2addr vA, vB */
6335     mov     r9, rINST, lsr #8           @ r9<- A+
6336     mov     r3, rINST, lsr #12          @ r3<- B
6337     and     r9, r9, #15
6338     GET_VREG(r2, r3)                    @ r2<- vB
6339     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6340     and     r2, r2, #63                 @ r2<- r2 & 0x3f
6341     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6342
6343     mov     r1, r1, asl r2              @  r1<- r1 << r2
6344     rsb     r3, r2, #32                 @  r3<- 32 - r2
6345     orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
6346     subs    ip, r2, #32                 @  ip<- r2 - 32
6347     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6348     movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
6349     mov     r0, r0, asl r2              @  r0<- r0 << r2
6350     b       .LOP_SHL_LONG_2ADDR_finish
6351
6352 /* ------------------------------ */
6353     .balign 64
6354 .L_OP_SHR_LONG_2ADDR: /* 0xc4 */
6355 /* File: armv5te/OP_SHR_LONG_2ADDR.S */
6356     /*
6357      * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6358      * 32-bit shift distance.
6359      */
6360     /* shr-long/2addr vA, vB */
6361     mov     r9, rINST, lsr #8           @ r9<- A+
6362     mov     r3, rINST, lsr #12          @ r3<- B
6363     and     r9, r9, #15
6364     GET_VREG(r2, r3)                    @ r2<- vB
6365     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6366     and     r2, r2, #63                 @ r2<- r2 & 0x3f
6367     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6368
6369     mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6370     rsb     r3, r2, #32                 @  r3<- 32 - r2
6371     orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6372     subs    ip, r2, #32                 @  ip<- r2 - 32
6373     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6374     movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
6375     mov     r1, r1, asr r2              @  r1<- r1 >> r2
6376     b       .LOP_SHR_LONG_2ADDR_finish
6377
6378 /* ------------------------------ */
6379     .balign 64
6380 .L_OP_USHR_LONG_2ADDR: /* 0xc5 */
6381 /* File: armv5te/OP_USHR_LONG_2ADDR.S */
6382     /*
6383      * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6384      * 32-bit shift distance.
6385      */
6386     /* ushr-long/2addr vA, vB */
6387     mov     r9, rINST, lsr #8           @ r9<- A+
6388     mov     r3, rINST, lsr #12          @ r3<- B
6389     and     r9, r9, #15
6390     GET_VREG(r2, r3)                    @ r2<- vB
6391     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6392     and     r2, r2, #63                 @ r2<- r2 & 0x3f
6393     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6394
6395     mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6396     rsb     r3, r2, #32                 @  r3<- 32 - r2
6397     orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6398     subs    ip, r2, #32                 @  ip<- r2 - 32
6399     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6400     movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
6401     mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
6402     b       .LOP_USHR_LONG_2ADDR_finish
6403
6404 /* ------------------------------ */
6405     .balign 64
6406 .L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
6407 /* File: armv5te/OP_ADD_FLOAT_2ADDR.S */
6408 /* File: armv5te/binop2addr.S */
6409     /*
6410      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6411      * that specifies an instruction that performs "result = r0 op r1".
6412      * This could be an ARM instruction or a function call.  (If the result
6413      * comes back in a register other than r0, you can override "result".)
6414      *
6415      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6416      * vCC (r1).  Useful for integer division and modulus.
6417      *
6418      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6419      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6420      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6421      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6422      */
6423     /* binop/2addr vA, vB */
6424     mov     r9, rINST, lsr #8           @ r9<- A+
6425     mov     r3, rINST, lsr #12          @ r3<- B
6426     and     r9, r9, #15
6427     GET_VREG(r1, r3)                    @ r1<- vB
6428     GET_VREG(r0, r9)                    @ r0<- vA
6429     .if 0
6430     cmp     r1, #0                      @ is second operand zero?
6431     beq     common_errDivideByZero
6432     .endif
6433     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6434
6435                                @ optional op; may set condition codes
6436     bl      __aeabi_fadd                              @ r0<- op, r0-r3 changed
6437     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6438     SET_VREG(r0, r9)               @ vAA<- r0
6439     GOTO_OPCODE(ip)                     @ jump to next instruction
6440     /* 10-13 instructions */
6441
6442
6443
6444 /* ------------------------------ */
6445     .balign 64
6446 .L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
6447 /* File: armv5te/OP_SUB_FLOAT_2ADDR.S */
6448 /* File: armv5te/binop2addr.S */
6449     /*
6450      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6451      * that specifies an instruction that performs "result = r0 op r1".
6452      * This could be an ARM instruction or a function call.  (If the result
6453      * comes back in a register other than r0, you can override "result".)
6454      *
6455      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6456      * vCC (r1).  Useful for integer division and modulus.
6457      *
6458      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6459      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6460      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6461      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6462      */
6463     /* binop/2addr vA, vB */
6464     mov     r9, rINST, lsr #8           @ r9<- A+
6465     mov     r3, rINST, lsr #12          @ r3<- B
6466     and     r9, r9, #15
6467     GET_VREG(r1, r3)                    @ r1<- vB
6468     GET_VREG(r0, r9)                    @ r0<- vA
6469     .if 0
6470     cmp     r1, #0                      @ is second operand zero?
6471     beq     common_errDivideByZero
6472     .endif
6473     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6474
6475                                @ optional op; may set condition codes
6476     bl      __aeabi_fsub                              @ r0<- op, r0-r3 changed
6477     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6478     SET_VREG(r0, r9)               @ vAA<- r0
6479     GOTO_OPCODE(ip)                     @ jump to next instruction
6480     /* 10-13 instructions */
6481
6482
6483
6484 /* ------------------------------ */
6485     .balign 64
6486 .L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
6487 /* File: armv5te/OP_MUL_FLOAT_2ADDR.S */
6488 /* File: armv5te/binop2addr.S */
6489     /*
6490      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6491      * that specifies an instruction that performs "result = r0 op r1".
6492      * This could be an ARM instruction or a function call.  (If the result
6493      * comes back in a register other than r0, you can override "result".)
6494      *
6495      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6496      * vCC (r1).  Useful for integer division and modulus.
6497      *
6498      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6499      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6500      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6501      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6502      */
6503     /* binop/2addr vA, vB */
6504     mov     r9, rINST, lsr #8           @ r9<- A+
6505     mov     r3, rINST, lsr #12          @ r3<- B
6506     and     r9, r9, #15
6507     GET_VREG(r1, r3)                    @ r1<- vB
6508     GET_VREG(r0, r9)                    @ r0<- vA
6509     .if 0
6510     cmp     r1, #0                      @ is second operand zero?
6511     beq     common_errDivideByZero
6512     .endif
6513     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6514
6515                                @ optional op; may set condition codes
6516     bl      __aeabi_fmul                              @ r0<- op, r0-r3 changed
6517     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6518     SET_VREG(r0, r9)               @ vAA<- r0
6519     GOTO_OPCODE(ip)                     @ jump to next instruction
6520     /* 10-13 instructions */
6521
6522
6523
6524 /* ------------------------------ */
6525     .balign 64
6526 .L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
6527 /* File: armv5te/OP_DIV_FLOAT_2ADDR.S */
6528 /* File: armv5te/binop2addr.S */
6529     /*
6530      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6531      * that specifies an instruction that performs "result = r0 op r1".
6532      * This could be an ARM instruction or a function call.  (If the result
6533      * comes back in a register other than r0, you can override "result".)
6534      *
6535      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6536      * vCC (r1).  Useful for integer division and modulus.
6537      *
6538      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6539      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6540      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6541      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6542      */
6543     /* binop/2addr vA, vB */
6544     mov     r9, rINST, lsr #8           @ r9<- A+
6545     mov     r3, rINST, lsr #12          @ r3<- B
6546     and     r9, r9, #15
6547     GET_VREG(r1, r3)                    @ r1<- vB
6548     GET_VREG(r0, r9)                    @ r0<- vA
6549     .if 0
6550     cmp     r1, #0                      @ is second operand zero?
6551     beq     common_errDivideByZero
6552     .endif
6553     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6554
6555                                @ optional op; may set condition codes
6556     bl      __aeabi_fdiv                              @ r0<- op, r0-r3 changed
6557     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6558     SET_VREG(r0, r9)               @ vAA<- r0
6559     GOTO_OPCODE(ip)                     @ jump to next instruction
6560     /* 10-13 instructions */
6561
6562
6563
6564 /* ------------------------------ */
6565     .balign 64
6566 .L_OP_REM_FLOAT_2ADDR: /* 0xca */
6567 /* File: armv5te/OP_REM_FLOAT_2ADDR.S */
6568 /* EABI doesn't define a float remainder function, but libm does */
6569 /* File: armv5te/binop2addr.S */
6570     /*
6571      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6572      * that specifies an instruction that performs "result = r0 op r1".
6573      * This could be an ARM instruction or a function call.  (If the result
6574      * comes back in a register other than r0, you can override "result".)
6575      *
6576      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6577      * vCC (r1).  Useful for integer division and modulus.
6578      *
6579      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6580      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6581      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6582      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6583      */
6584     /* binop/2addr vA, vB */
6585     mov     r9, rINST, lsr #8           @ r9<- A+
6586     mov     r3, rINST, lsr #12          @ r3<- B
6587     and     r9, r9, #15
6588     GET_VREG(r1, r3)                    @ r1<- vB
6589     GET_VREG(r0, r9)                    @ r0<- vA
6590     .if 0
6591     cmp     r1, #0                      @ is second operand zero?
6592     beq     common_errDivideByZero
6593     .endif
6594     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6595
6596                                @ optional op; may set condition codes
6597     bl      fmodf                              @ r0<- op, r0-r3 changed
6598     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6599     SET_VREG(r0, r9)               @ vAA<- r0
6600     GOTO_OPCODE(ip)                     @ jump to next instruction
6601     /* 10-13 instructions */
6602
6603
6604
6605 /* ------------------------------ */
6606     .balign 64
6607 .L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
6608 /* File: armv5te/OP_ADD_DOUBLE_2ADDR.S */
6609 /* File: armv5te/binopWide2addr.S */
6610     /*
6611      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6612      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6613      * This could be an ARM instruction or a function call.  (If the result
6614      * comes back in a register other than r0, you can override "result".)
6615      *
6616      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6617      * vCC (r1).  Useful for integer division and modulus.
6618      *
6619      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6620      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6621      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6622      *      rem-double/2addr
6623      */
6624     /* binop/2addr vA, vB */
6625     mov     r9, rINST, lsr #8           @ r9<- A+
6626     mov     r1, rINST, lsr #12          @ r1<- B
6627     and     r9, r9, #15
6628     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6629     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6630     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6631     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6632     .if 0
6633     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6634     beq     common_errDivideByZero
6635     .endif
6636     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6637
6638                                @ optional op; may set condition codes
6639     bl      __aeabi_dadd                              @ result<- op, r0-r3 changed
6640     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6641     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6642     GOTO_OPCODE(ip)                     @ jump to next instruction
6643     /* 12-15 instructions */
6644
6645
6646
6647 /* ------------------------------ */
6648     .balign 64
6649 .L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
6650 /* File: armv5te/OP_SUB_DOUBLE_2ADDR.S */
6651 /* File: armv5te/binopWide2addr.S */
6652     /*
6653      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6654      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6655      * This could be an ARM instruction or a function call.  (If the result
6656      * comes back in a register other than r0, you can override "result".)
6657      *
6658      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6659      * vCC (r1).  Useful for integer division and modulus.
6660      *
6661      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6662      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6663      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6664      *      rem-double/2addr
6665      */
6666     /* binop/2addr vA, vB */
6667     mov     r9, rINST, lsr #8           @ r9<- A+
6668     mov     r1, rINST, lsr #12          @ r1<- B
6669     and     r9, r9, #15
6670     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6671     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6672     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6673     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6674     .if 0
6675     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6676     beq     common_errDivideByZero
6677     .endif
6678     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6679
6680                                @ optional op; may set condition codes
6681     bl      __aeabi_dsub                              @ result<- op, r0-r3 changed
6682     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6683     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6684     GOTO_OPCODE(ip)                     @ jump to next instruction
6685     /* 12-15 instructions */
6686
6687
6688
6689 /* ------------------------------ */
6690     .balign 64
6691 .L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
6692 /* File: armv5te/OP_MUL_DOUBLE_2ADDR.S */
6693 /* File: armv5te/binopWide2addr.S */
6694     /*
6695      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6696      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6697      * This could be an ARM instruction or a function call.  (If the result
6698      * comes back in a register other than r0, you can override "result".)
6699      *
6700      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6701      * vCC (r1).  Useful for integer division and modulus.
6702      *
6703      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6704      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6705      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6706      *      rem-double/2addr
6707      */
6708     /* binop/2addr vA, vB */
6709     mov     r9, rINST, lsr #8           @ r9<- A+
6710     mov     r1, rINST, lsr #12          @ r1<- B
6711     and     r9, r9, #15
6712     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6713     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6714     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6715     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6716     .if 0
6717     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6718     beq     common_errDivideByZero
6719     .endif
6720     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6721
6722                                @ optional op; may set condition codes
6723     bl      __aeabi_dmul                              @ result<- op, r0-r3 changed
6724     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6725     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6726     GOTO_OPCODE(ip)                     @ jump to next instruction
6727     /* 12-15 instructions */
6728
6729
6730
6731 /* ------------------------------ */
6732     .balign 64
6733 .L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
6734 /* File: armv5te/OP_DIV_DOUBLE_2ADDR.S */
6735 /* File: armv5te/binopWide2addr.S */
6736     /*
6737      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6738      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6739      * This could be an ARM instruction or a function call.  (If the result
6740      * comes back in a register other than r0, you can override "result".)
6741      *
6742      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6743      * vCC (r1).  Useful for integer division and modulus.
6744      *
6745      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6746      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6747      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6748      *      rem-double/2addr
6749      */
6750     /* binop/2addr vA, vB */
6751     mov     r9, rINST, lsr #8           @ r9<- A+
6752     mov     r1, rINST, lsr #12          @ r1<- B
6753     and     r9, r9, #15
6754     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6755     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6756     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6757     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6758     .if 0
6759     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6760     beq     common_errDivideByZero
6761     .endif
6762     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6763
6764                                @ optional op; may set condition codes
6765     bl      __aeabi_ddiv                              @ result<- op, r0-r3 changed
6766     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6767     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6768     GOTO_OPCODE(ip)                     @ jump to next instruction
6769     /* 12-15 instructions */
6770
6771
6772
6773 /* ------------------------------ */
6774     .balign 64
6775 .L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
6776 /* File: armv5te/OP_REM_DOUBLE_2ADDR.S */
6777 /* EABI doesn't define a double remainder function, but libm does */
6778 /* File: armv5te/binopWide2addr.S */
6779     /*
6780      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6781      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6782      * This could be an ARM instruction or a function call.  (If the result
6783      * comes back in a register other than r0, you can override "result".)
6784      *
6785      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6786      * vCC (r1).  Useful for integer division and modulus.
6787      *
6788      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6789      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6790      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6791      *      rem-double/2addr
6792      */
6793     /* binop/2addr vA, vB */
6794     mov     r9, rINST, lsr #8           @ r9<- A+
6795     mov     r1, rINST, lsr #12          @ r1<- B
6796     and     r9, r9, #15
6797     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6798     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6799     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6800     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6801     .if 0
6802     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6803     beq     common_errDivideByZero
6804     .endif
6805     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6806
6807                                @ optional op; may set condition codes
6808     bl      fmod                              @ result<- op, r0-r3 changed
6809     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6810     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6811     GOTO_OPCODE(ip)                     @ jump to next instruction
6812     /* 12-15 instructions */
6813
6814
6815
6816 /* ------------------------------ */
6817     .balign 64
6818 .L_OP_ADD_INT_LIT16: /* 0xd0 */
6819 /* File: armv5te/OP_ADD_INT_LIT16.S */
6820 /* File: armv5te/binopLit16.S */
6821     /*
6822      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6823      * that specifies an instruction that performs "result = r0 op r1".
6824      * This could be an ARM instruction or a function call.  (If the result
6825      * comes back in a register other than r0, you can override "result".)
6826      *
6827      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6828      * vCC (r1).  Useful for integer division and modulus.
6829      *
6830      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6831      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6832      */
6833     /* binop/lit16 vA, vB, #+CCCC */
6834     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6835     mov     r2, rINST, lsr #12          @ r2<- B
6836     mov     r9, rINST, lsr #8           @ r9<- A+
6837     GET_VREG(r0, r2)                    @ r0<- vB
6838     and     r9, r9, #15
6839     .if 0
6840     cmp     r1, #0                      @ is second operand zero?
6841     beq     common_errDivideByZero
6842     .endif
6843     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6844
6845     add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6846     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6847     SET_VREG(r0, r9)               @ vAA<- r0
6848     GOTO_OPCODE(ip)                     @ jump to next instruction
6849     /* 10-13 instructions */
6850
6851
6852
6853 /* ------------------------------ */
6854     .balign 64
6855 .L_OP_RSUB_INT: /* 0xd1 */
6856 /* File: armv5te/OP_RSUB_INT.S */
6857 /* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
6858 /* File: armv5te/binopLit16.S */
6859     /*
6860      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6861      * that specifies an instruction that performs "result = r0 op r1".
6862      * This could be an ARM instruction or a function call.  (If the result
6863      * comes back in a register other than r0, you can override "result".)
6864      *
6865      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6866      * vCC (r1).  Useful for integer division and modulus.
6867      *
6868      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6869      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6870      */
6871     /* binop/lit16 vA, vB, #+CCCC */
6872     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6873     mov     r2, rINST, lsr #12          @ r2<- B
6874     mov     r9, rINST, lsr #8           @ r9<- A+
6875     GET_VREG(r0, r2)                    @ r0<- vB
6876     and     r9, r9, #15
6877     .if 0
6878     cmp     r1, #0                      @ is second operand zero?
6879     beq     common_errDivideByZero
6880     .endif
6881     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6882
6883     rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6884     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6885     SET_VREG(r0, r9)               @ vAA<- r0
6886     GOTO_OPCODE(ip)                     @ jump to next instruction
6887     /* 10-13 instructions */
6888
6889
6890
6891 /* ------------------------------ */
6892     .balign 64
6893 .L_OP_MUL_INT_LIT16: /* 0xd2 */
6894 /* File: armv5te/OP_MUL_INT_LIT16.S */
6895 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6896 /* File: armv5te/binopLit16.S */
6897     /*
6898      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6899      * that specifies an instruction that performs "result = r0 op r1".
6900      * This could be an ARM instruction or a function call.  (If the result
6901      * comes back in a register other than r0, you can override "result".)
6902      *
6903      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6904      * vCC (r1).  Useful for integer division and modulus.
6905      *
6906      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6907      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6908      */
6909     /* binop/lit16 vA, vB, #+CCCC */
6910     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6911     mov     r2, rINST, lsr #12          @ r2<- B
6912     mov     r9, rINST, lsr #8           @ r9<- A+
6913     GET_VREG(r0, r2)                    @ r0<- vB
6914     and     r9, r9, #15
6915     .if 0
6916     cmp     r1, #0                      @ is second operand zero?
6917     beq     common_errDivideByZero
6918     .endif
6919     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6920
6921     mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6922     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6923     SET_VREG(r0, r9)               @ vAA<- r0
6924     GOTO_OPCODE(ip)                     @ jump to next instruction
6925     /* 10-13 instructions */
6926
6927
6928
6929 /* ------------------------------ */
6930     .balign 64
6931 .L_OP_DIV_INT_LIT16: /* 0xd3 */
6932 /* File: armv5te/OP_DIV_INT_LIT16.S */
6933 /* File: armv5te/binopLit16.S */
6934     /*
6935      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6936      * that specifies an instruction that performs "result = r0 op r1".
6937      * This could be an ARM instruction or a function call.  (If the result
6938      * comes back in a register other than r0, you can override "result".)
6939      *
6940      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6941      * vCC (r1).  Useful for integer division and modulus.
6942      *
6943      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6944      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6945      */
6946     /* binop/lit16 vA, vB, #+CCCC */
6947     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6948     mov     r2, rINST, lsr #12          @ r2<- B
6949     mov     r9, rINST, lsr #8           @ r9<- A+
6950     GET_VREG(r0, r2)                    @ r0<- vB
6951     and     r9, r9, #15
6952     .if 1
6953     cmp     r1, #0                      @ is second operand zero?
6954     beq     common_errDivideByZero
6955     .endif
6956     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6957
6958     bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6959     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6960     SET_VREG(r0, r9)               @ vAA<- r0
6961     GOTO_OPCODE(ip)                     @ jump to next instruction
6962     /* 10-13 instructions */
6963
6964
6965
6966 /* ------------------------------ */
6967     .balign 64
6968 .L_OP_REM_INT_LIT16: /* 0xd4 */
6969 /* File: armv5te/OP_REM_INT_LIT16.S */
6970 /* idivmod returns quotient in r0 and remainder in r1 */
6971 /* File: armv5te/binopLit16.S */
6972     /*
6973      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6974      * that specifies an instruction that performs "result = r0 op r1".
6975      * This could be an ARM instruction or a function call.  (If the result
6976      * comes back in a register other than r0, you can override "result".)
6977      *
6978      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6979      * vCC (r1).  Useful for integer division and modulus.
6980      *
6981      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6982      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6983      */
6984     /* binop/lit16 vA, vB, #+CCCC */
6985     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6986     mov     r2, rINST, lsr #12          @ r2<- B
6987     mov     r9, rINST, lsr #8           @ r9<- A+
6988     GET_VREG(r0, r2)                    @ r0<- vB
6989     and     r9, r9, #15
6990     .if 1
6991     cmp     r1, #0                      @ is second operand zero?
6992     beq     common_errDivideByZero
6993     .endif
6994     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6995
6996     bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6997     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6998     SET_VREG(r1, r9)               @ vAA<- r1
6999     GOTO_OPCODE(ip)                     @ jump to next instruction
7000     /* 10-13 instructions */
7001
7002
7003
7004 /* ------------------------------ */
7005     .balign 64
7006 .L_OP_AND_INT_LIT16: /* 0xd5 */
7007 /* File: armv5te/OP_AND_INT_LIT16.S */
7008 /* File: armv5te/binopLit16.S */
7009     /*
7010      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
7011      * that specifies an instruction that performs "result = r0 op r1".
7012      * This could be an ARM instruction or a function call.  (If the result
7013      * comes back in a register other than r0, you can override "result".)
7014      *
7015      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7016      * vCC (r1).  Useful for integer division and modulus.
7017      *
7018      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
7019      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
7020      */
7021     /* binop/lit16 vA, vB, #+CCCC */
7022     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
7023     mov     r2, rINST, lsr #12          @ r2<- B
7024     mov     r9, rINST, lsr #8           @ r9<- A+
7025     GET_VREG(r0, r2)                    @ r0<- vB
7026     and     r9, r9, #15
7027     .if 0
7028     cmp     r1, #0                      @ is second operand zero?
7029     beq     common_errDivideByZero
7030     .endif
7031     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7032
7033     and     r0, r0, r1                              @ r0<- op, r0-r3 changed
7034     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7035     SET_VREG(r0, r9)               @ vAA<- r0
7036     GOTO_OPCODE(ip)                     @ jump to next instruction
7037     /* 10-13 instructions */
7038
7039
7040
7041 /* ------------------------------ */
7042     .balign 64
7043 .L_OP_OR_INT_LIT16: /* 0xd6 */
7044 /* File: armv5te/OP_OR_INT_LIT16.S */
7045 /* File: armv5te/binopLit16.S */
7046     /*
7047      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
7048      * that specifies an instruction that performs "result = r0 op r1".
7049      * This could be an ARM instruction or a function call.  (If the result
7050      * comes back in a register other than r0, you can override "result".)
7051      *
7052      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7053      * vCC (r1).  Useful for integer division and modulus.
7054      *
7055      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
7056      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
7057      */
7058     /* binop/lit16 vA, vB, #+CCCC */
7059     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
7060     mov     r2, rINST, lsr #12          @ r2<- B
7061     mov     r9, rINST, lsr #8           @ r9<- A+
7062     GET_VREG(r0, r2)                    @ r0<- vB
7063     and     r9, r9, #15
7064     .if 0
7065     cmp     r1, #0                      @ is second operand zero?
7066     beq     common_errDivideByZero
7067     .endif
7068     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7069
7070     orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
7071     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7072     SET_VREG(r0, r9)               @ vAA<- r0
7073     GOTO_OPCODE(ip)                     @ jump to next instruction
7074     /* 10-13 instructions */
7075
7076
7077
7078 /* ------------------------------ */
7079     .balign 64
7080 .L_OP_XOR_INT_LIT16: /* 0xd7 */
7081 /* File: armv5te/OP_XOR_INT_LIT16.S */
7082 /* File: armv5te/binopLit16.S */
7083     /*
7084      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
7085      * that specifies an instruction that performs "result = r0 op r1".
7086      * This could be an ARM instruction or a function call.  (If the result
7087      * comes back in a register other than r0, you can override "result".)
7088      *
7089      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7090      * vCC (r1).  Useful for integer division and modulus.
7091      *
7092      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
7093      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
7094      */
7095     /* binop/lit16 vA, vB, #+CCCC */
7096     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
7097     mov     r2, rINST, lsr #12          @ r2<- B
7098     mov     r9, rINST, lsr #8           @ r9<- A+
7099     GET_VREG(r0, r2)                    @ r0<- vB
7100     and     r9, r9, #15
7101     .if 0
7102     cmp     r1, #0                      @ is second operand zero?
7103     beq     common_errDivideByZero
7104     .endif
7105     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7106
7107     eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
7108     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7109     SET_VREG(r0, r9)               @ vAA<- r0
7110     GOTO_OPCODE(ip)                     @ jump to next instruction
7111     /* 10-13 instructions */
7112
7113
7114
7115 /* ------------------------------ */
7116     .balign 64
7117 .L_OP_ADD_INT_LIT8: /* 0xd8 */
7118 /* File: armv5te/OP_ADD_INT_LIT8.S */
7119 /* File: armv5te/binopLit8.S */
7120     /*
7121      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7122      * that specifies an instruction that performs "result = r0 op r1".
7123      * This could be an ARM instruction or a function call.  (If the result
7124      * comes back in a register other than r0, you can override "result".)
7125      *
7126      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7127      * vCC (r1).  Useful for integer division and modulus.
7128      *
7129      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7130      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7131      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7132      */
7133     /* binop/lit8 vAA, vBB, #+CC */
7134     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7135     mov     r9, rINST, lsr #8           @ r9<- AA
7136     and     r2, r3, #255                @ r2<- BB
7137     GET_VREG(r0, r2)                    @ r0<- vBB
7138     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7139     .if 0
7140     @cmp     r1, #0                      @ is second operand zero?
7141     beq     common_errDivideByZero
7142     .endif
7143     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7144
7145                                @ optional op; may set condition codes
7146     add     r0, r0, r1                              @ r0<- op, r0-r3 changed
7147     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7148     SET_VREG(r0, r9)               @ vAA<- r0
7149     GOTO_OPCODE(ip)                     @ jump to next instruction
7150     /* 10-12 instructions */
7151
7152
7153
7154 /* ------------------------------ */
7155     .balign 64
7156 .L_OP_RSUB_INT_LIT8: /* 0xd9 */
7157 /* File: armv5te/OP_RSUB_INT_LIT8.S */
7158 /* File: armv5te/binopLit8.S */
7159     /*
7160      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7161      * that specifies an instruction that performs "result = r0 op r1".
7162      * This could be an ARM instruction or a function call.  (If the result
7163      * comes back in a register other than r0, you can override "result".)
7164      *
7165      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7166      * vCC (r1).  Useful for integer division and modulus.
7167      *
7168      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7169      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7170      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7171      */
7172     /* binop/lit8 vAA, vBB, #+CC */
7173     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7174     mov     r9, rINST, lsr #8           @ r9<- AA
7175     and     r2, r3, #255                @ r2<- BB
7176     GET_VREG(r0, r2)                    @ r0<- vBB
7177     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7178     .if 0
7179     @cmp     r1, #0                      @ is second operand zero?
7180     beq     common_errDivideByZero
7181     .endif
7182     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7183
7184                                @ optional op; may set condition codes
7185     rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
7186     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7187     SET_VREG(r0, r9)               @ vAA<- r0
7188     GOTO_OPCODE(ip)                     @ jump to next instruction
7189     /* 10-12 instructions */
7190
7191
7192
7193 /* ------------------------------ */
7194     .balign 64
7195 .L_OP_MUL_INT_LIT8: /* 0xda */
7196 /* File: armv5te/OP_MUL_INT_LIT8.S */
7197 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
7198 /* File: armv5te/binopLit8.S */
7199     /*
7200      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7201      * that specifies an instruction that performs "result = r0 op r1".
7202      * This could be an ARM instruction or a function call.  (If the result
7203      * comes back in a register other than r0, you can override "result".)
7204      *
7205      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7206      * vCC (r1).  Useful for integer division and modulus.
7207      *
7208      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7209      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7210      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7211      */
7212     /* binop/lit8 vAA, vBB, #+CC */
7213     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7214     mov     r9, rINST, lsr #8           @ r9<- AA
7215     and     r2, r3, #255                @ r2<- BB
7216     GET_VREG(r0, r2)                    @ r0<- vBB
7217     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7218     .if 0
7219     @cmp     r1, #0                      @ is second operand zero?
7220     beq     common_errDivideByZero
7221     .endif
7222     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7223
7224                                @ optional op; may set condition codes
7225     mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
7226     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7227     SET_VREG(r0, r9)               @ vAA<- r0
7228     GOTO_OPCODE(ip)                     @ jump to next instruction
7229     /* 10-12 instructions */
7230
7231
7232
7233 /* ------------------------------ */
7234     .balign 64
7235 .L_OP_DIV_INT_LIT8: /* 0xdb */
7236 /* File: armv5te/OP_DIV_INT_LIT8.S */
7237 /* File: armv5te/binopLit8.S */
7238     /*
7239      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7240      * that specifies an instruction that performs "result = r0 op r1".
7241      * This could be an ARM instruction or a function call.  (If the result
7242      * comes back in a register other than r0, you can override "result".)
7243      *
7244      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7245      * vCC (r1).  Useful for integer division and modulus.
7246      *
7247      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7248      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7249      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7250      */
7251     /* binop/lit8 vAA, vBB, #+CC */
7252     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7253     mov     r9, rINST, lsr #8           @ r9<- AA
7254     and     r2, r3, #255                @ r2<- BB
7255     GET_VREG(r0, r2)                    @ r0<- vBB
7256     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7257     .if 1
7258     @cmp     r1, #0                      @ is second operand zero?
7259     beq     common_errDivideByZero
7260     .endif
7261     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7262
7263                                @ optional op; may set condition codes
7264     bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
7265     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7266     SET_VREG(r0, r9)               @ vAA<- r0
7267     GOTO_OPCODE(ip)                     @ jump to next instruction
7268     /* 10-12 instructions */
7269
7270
7271
7272 /* ------------------------------ */
7273     .balign 64
7274 .L_OP_REM_INT_LIT8: /* 0xdc */
7275 /* File: armv5te/OP_REM_INT_LIT8.S */
7276 /* idivmod returns quotient in r0 and remainder in r1 */
7277 /* File: armv5te/binopLit8.S */
7278     /*
7279      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7280      * that specifies an instruction that performs "result = r0 op r1".
7281      * This could be an ARM instruction or a function call.  (If the result
7282      * comes back in a register other than r0, you can override "result".)
7283      *
7284      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7285      * vCC (r1).  Useful for integer division and modulus.
7286      *
7287      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7288      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7289      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7290      */
7291     /* binop/lit8 vAA, vBB, #+CC */
7292     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7293     mov     r9, rINST, lsr #8           @ r9<- AA
7294     and     r2, r3, #255                @ r2<- BB
7295     GET_VREG(r0, r2)                    @ r0<- vBB
7296     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7297     .if 1
7298     @cmp     r1, #0                      @ is second operand zero?
7299     beq     common_errDivideByZero
7300     .endif
7301     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7302
7303                                @ optional op; may set condition codes
7304     bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
7305     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7306     SET_VREG(r1, r9)               @ vAA<- r1
7307     GOTO_OPCODE(ip)                     @ jump to next instruction
7308     /* 10-12 instructions */
7309
7310
7311
7312 /* ------------------------------ */
7313     .balign 64
7314 .L_OP_AND_INT_LIT8: /* 0xdd */
7315 /* File: armv5te/OP_AND_INT_LIT8.S */
7316 /* File: armv5te/binopLit8.S */
7317     /*
7318      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7319      * that specifies an instruction that performs "result = r0 op r1".
7320      * This could be an ARM instruction or a function call.  (If the result
7321      * comes back in a register other than r0, you can override "result".)
7322      *
7323      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7324      * vCC (r1).  Useful for integer division and modulus.
7325      *
7326      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7327      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7328      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7329      */
7330     /* binop/lit8 vAA, vBB, #+CC */
7331     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7332     mov     r9, rINST, lsr #8           @ r9<- AA
7333     and     r2, r3, #255                @ r2<- BB
7334     GET_VREG(r0, r2)                    @ r0<- vBB
7335     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7336     .if 0
7337     @cmp     r1, #0                      @ is second operand zero?
7338     beq     common_errDivideByZero
7339     .endif
7340     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7341
7342                                @ optional op; may set condition codes
7343     and     r0, r0, r1                              @ r0<- op, r0-r3 changed
7344     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7345     SET_VREG(r0, r9)               @ vAA<- r0
7346     GOTO_OPCODE(ip)                     @ jump to next instruction
7347     /* 10-12 instructions */
7348
7349
7350
7351 /* ------------------------------ */
7352     .balign 64
7353 .L_OP_OR_INT_LIT8: /* 0xde */
7354 /* File: armv5te/OP_OR_INT_LIT8.S */
7355 /* File: armv5te/binopLit8.S */
7356     /*
7357      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7358      * that specifies an instruction that performs "result = r0 op r1".
7359      * This could be an ARM instruction or a function call.  (If the result
7360      * comes back in a register other than r0, you can override "result".)
7361      *
7362      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7363      * vCC (r1).  Useful for integer division and modulus.
7364      *
7365      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7366      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7367      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7368      */
7369     /* binop/lit8 vAA, vBB, #+CC */
7370     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7371     mov     r9, rINST, lsr #8           @ r9<- AA
7372     and     r2, r3, #255                @ r2<- BB
7373     GET_VREG(r0, r2)                    @ r0<- vBB
7374     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7375     .if 0
7376     @cmp     r1, #0                      @ is second operand zero?
7377     beq     common_errDivideByZero
7378     .endif
7379     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7380
7381                                @ optional op; may set condition codes
7382     orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
7383     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7384     SET_VREG(r0, r9)               @ vAA<- r0
7385     GOTO_OPCODE(ip)                     @ jump to next instruction
7386     /* 10-12 instructions */
7387
7388
7389
7390 /* ------------------------------ */
7391     .balign 64
7392 .L_OP_XOR_INT_LIT8: /* 0xdf */
7393 /* File: armv5te/OP_XOR_INT_LIT8.S */
7394 /* File: armv5te/binopLit8.S */
7395     /*
7396      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7397      * that specifies an instruction that performs "result = r0 op r1".
7398      * This could be an ARM instruction or a function call.  (If the result
7399      * comes back in a register other than r0, you can override "result".)
7400      *
7401      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7402      * vCC (r1).  Useful for integer division and modulus.
7403      *
7404      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7405      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7406      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7407      */
7408     /* binop/lit8 vAA, vBB, #+CC */
7409     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7410     mov     r9, rINST, lsr #8           @ r9<- AA
7411     and     r2, r3, #255                @ r2<- BB
7412     GET_VREG(r0, r2)                    @ r0<- vBB
7413     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7414     .if 0
7415     @cmp     r1, #0                      @ is second operand zero?
7416     beq     common_errDivideByZero
7417     .endif
7418     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7419
7420                                @ optional op; may set condition codes
7421     eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
7422     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7423     SET_VREG(r0, r9)               @ vAA<- r0
7424     GOTO_OPCODE(ip)                     @ jump to next instruction
7425     /* 10-12 instructions */
7426
7427
7428
7429 /* ------------------------------ */
7430     .balign 64
7431 .L_OP_SHL_INT_LIT8: /* 0xe0 */
7432 /* File: armv5te/OP_SHL_INT_LIT8.S */
7433 /* File: armv5te/binopLit8.S */
7434     /*
7435      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7436      * that specifies an instruction that performs "result = r0 op r1".
7437      * This could be an ARM instruction or a function call.  (If the result
7438      * comes back in a register other than r0, you can override "result".)
7439      *
7440      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7441      * vCC (r1).  Useful for integer division and modulus.
7442      *
7443      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7444      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7445      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7446      */
7447     /* binop/lit8 vAA, vBB, #+CC */
7448     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7449     mov     r9, rINST, lsr #8           @ r9<- AA
7450     and     r2, r3, #255                @ r2<- BB
7451     GET_VREG(r0, r2)                    @ r0<- vBB
7452     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7453     .if 0
7454     @cmp     r1, #0                      @ is second operand zero?
7455     beq     common_errDivideByZero
7456     .endif
7457     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7458
7459     and     r1, r1, #31                           @ optional op; may set condition codes
7460     mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
7461     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7462     SET_VREG(r0, r9)               @ vAA<- r0
7463     GOTO_OPCODE(ip)                     @ jump to next instruction
7464     /* 10-12 instructions */
7465
7466
7467
7468 /* ------------------------------ */
7469     .balign 64
7470 .L_OP_SHR_INT_LIT8: /* 0xe1 */
7471 /* File: armv5te/OP_SHR_INT_LIT8.S */
7472 /* File: armv5te/binopLit8.S */
7473     /*
7474      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7475      * that specifies an instruction that performs "result = r0 op r1".
7476      * This could be an ARM instruction or a function call.  (If the result
7477      * comes back in a register other than r0, you can override "result".)
7478      *
7479      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7480      * vCC (r1).  Useful for integer division and modulus.
7481      *
7482      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7483      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7484      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7485      */
7486     /* binop/lit8 vAA, vBB, #+CC */
7487     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7488     mov     r9, rINST, lsr #8           @ r9<- AA
7489     and     r2, r3, #255                @ r2<- BB
7490     GET_VREG(r0, r2)                    @ r0<- vBB
7491     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7492     .if 0
7493     @cmp     r1, #0                      @ is second operand zero?
7494     beq     common_errDivideByZero
7495     .endif
7496     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7497
7498     and     r1, r1, #31                           @ optional op; may set condition codes
7499     mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
7500     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7501     SET_VREG(r0, r9)               @ vAA<- r0
7502     GOTO_OPCODE(ip)                     @ jump to next instruction
7503     /* 10-12 instructions */
7504
7505
7506
7507 /* ------------------------------ */
7508     .balign 64
7509 .L_OP_USHR_INT_LIT8: /* 0xe2 */
7510 /* File: armv5te/OP_USHR_INT_LIT8.S */
7511 /* File: armv5te/binopLit8.S */
7512     /*
7513      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7514      * that specifies an instruction that performs "result = r0 op r1".
7515      * This could be an ARM instruction or a function call.  (If the result
7516      * comes back in a register other than r0, you can override "result".)
7517      *
7518      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7519      * vCC (r1).  Useful for integer division and modulus.
7520      *
7521      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7522      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7523      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7524      */
7525     /* binop/lit8 vAA, vBB, #+CC */
7526     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7527     mov     r9, rINST, lsr #8           @ r9<- AA
7528     and     r2, r3, #255                @ r2<- BB
7529     GET_VREG(r0, r2)                    @ r0<- vBB
7530     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7531     .if 0
7532     @cmp     r1, #0                      @ is second operand zero?
7533     beq     common_errDivideByZero
7534     .endif
7535     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7536
7537     and     r1, r1, #31                           @ optional op; may set condition codes
7538     mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
7539     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7540     SET_VREG(r0, r9)               @ vAA<- r0
7541     GOTO_OPCODE(ip)                     @ jump to next instruction
7542     /* 10-12 instructions */
7543
7544
7545
7546 /* ------------------------------ */
7547     .balign 64
7548 .L_OP_UNUSED_E3: /* 0xe3 */
7549 /* File: armv5te/OP_UNUSED_E3.S */
7550 /* File: armv5te/unused.S */
7551     bl      common_abort
7552
7553
7554
7555 /* ------------------------------ */
7556     .balign 64
7557 .L_OP_UNUSED_E4: /* 0xe4 */
7558 /* File: armv5te/OP_UNUSED_E4.S */
7559 /* File: armv5te/unused.S */
7560     bl      common_abort
7561
7562
7563
7564 /* ------------------------------ */
7565     .balign 64
7566 .L_OP_UNUSED_E5: /* 0xe5 */
7567 /* File: armv5te/OP_UNUSED_E5.S */
7568 /* File: armv5te/unused.S */
7569     bl      common_abort
7570
7571
7572
7573 /* ------------------------------ */
7574     .balign 64
7575 .L_OP_UNUSED_E6: /* 0xe6 */
7576 /* File: armv5te/OP_UNUSED_E6.S */
7577 /* File: armv5te/unused.S */
7578     bl      common_abort
7579
7580
7581
7582 /* ------------------------------ */
7583     .balign 64
7584 .L_OP_UNUSED_E7: /* 0xe7 */
7585 /* File: armv5te/OP_UNUSED_E7.S */
7586 /* File: armv5te/unused.S */
7587     bl      common_abort
7588
7589
7590
7591 /* ------------------------------ */
7592     .balign 64
7593 .L_OP_UNUSED_E8: /* 0xe8 */
7594 /* File: armv5te/OP_UNUSED_E8.S */
7595 /* File: armv5te/unused.S */
7596     bl      common_abort
7597
7598
7599
7600 /* ------------------------------ */
7601     .balign 64
7602 .L_OP_UNUSED_E9: /* 0xe9 */
7603 /* File: armv5te/OP_UNUSED_E9.S */
7604 /* File: armv5te/unused.S */
7605     bl      common_abort
7606
7607
7608
7609 /* ------------------------------ */
7610     .balign 64
7611 .L_OP_UNUSED_EA: /* 0xea */
7612 /* File: armv5te/OP_UNUSED_EA.S */
7613 /* File: armv5te/unused.S */
7614     bl      common_abort
7615
7616
7617
7618 /* ------------------------------ */
7619     .balign 64
7620 .L_OP_UNUSED_EB: /* 0xeb */
7621 /* File: armv5te/OP_UNUSED_EB.S */
7622 /* File: armv5te/unused.S */
7623     bl      common_abort
7624
7625
7626
7627 /* ------------------------------ */
7628     .balign 64
7629 .L_OP_BREAKPOINT: /* 0xec */
7630 /* File: armv5te/OP_BREAKPOINT.S */
7631 /* File: armv5te/unused.S */
7632     bl      common_abort
7633
7634
7635
7636 /* ------------------------------ */
7637     .balign 64
7638 .L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
7639 /* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
7640     /*
7641      * Handle a throw-verification-error instruction.  This throws an
7642      * exception for an error discovered during verification.  The
7643      * exception is indicated by AA, with some detail provided by BBBB.
7644      */
7645     /* op AA, ref@BBBB */
7646     ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7647     FETCH(r2, 1)                        @ r2<- BBBB
7648     EXPORT_PC()                         @ export the PC
7649     mov     r1, rINST, lsr #8           @ r1<- AA
7650     bl      dvmThrowVerificationError   @ always throws
7651     b       common_exceptionThrown      @ handle exception
7652
7653
7654 /* ------------------------------ */
7655     .balign 64
7656 .L_OP_EXECUTE_INLINE: /* 0xee */
7657 /* File: armv5te/OP_EXECUTE_INLINE.S */
7658     /*
7659      * Execute a "native inline" instruction.
7660      *
7661      * We need to call an InlineOp4Func:
7662      *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7663      *
7664      * The first four args are in r0-r3, pointer to return value storage
7665      * is on the stack.  The function's return value is a flag that tells
7666      * us if an exception was thrown.
7667      */
7668     /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
7669     FETCH(r10, 1)                       @ r10<- BBBB
7670     add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7671     EXPORT_PC()                         @ can throw
7672     sub     sp, sp, #8                  @ make room for arg, +64 bit align
7673     mov     r0, rINST, lsr #12          @ r0<- B
7674     str     r1, [sp]                    @ push &glue->retval
7675     bl      .LOP_EXECUTE_INLINE_continue        @ make call; will return after
7676     add     sp, sp, #8                  @ pop stack
7677     cmp     r0, #0                      @ test boolean result of inline
7678     beq     common_exceptionThrown      @ returned false, handle exception
7679     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7680     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7681     GOTO_OPCODE(ip)                     @ jump to next instruction
7682
7683 /* ------------------------------ */
7684     .balign 64
7685 .L_OP_EXECUTE_INLINE_RANGE: /* 0xef */
7686 /* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */
7687     /*
7688      * Execute a "native inline" instruction, using "/range" semantics.
7689      * Same idea as execute-inline, but we get the args differently.
7690      *
7691      * We need to call an InlineOp4Func:
7692      *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7693      *
7694      * The first four args are in r0-r3, pointer to return value storage
7695      * is on the stack.  The function's return value is a flag that tells
7696      * us if an exception was thrown.
7697      */
7698     /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */
7699     FETCH(r10, 1)                       @ r10<- BBBB
7700     add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7701     EXPORT_PC()                         @ can throw
7702     sub     sp, sp, #8                  @ make room for arg, +64 bit align
7703     mov     r0, rINST, lsr #8           @ r0<- AA
7704     str     r1, [sp]                    @ push &glue->retval
7705     bl      .LOP_EXECUTE_INLINE_RANGE_continue        @ make call; will return after
7706     add     sp, sp, #8                  @ pop stack
7707     cmp     r0, #0                      @ test boolean result of inline
7708     beq     common_exceptionThrown      @ returned false, handle exception
7709     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7710     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7711     GOTO_OPCODE(ip)                     @ jump to next instruction
7712
7713 /* ------------------------------ */
7714     .balign 64
7715 .L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
7716 /* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
7717     /*
7718      * invoke-direct-empty is a no-op in a "standard" interpreter.
7719      */
7720     FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7721     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7722     GOTO_OPCODE(ip)                     @ execute it
7723
7724 /* ------------------------------ */
7725     .balign 64
7726 .L_OP_UNUSED_F1: /* 0xf1 */
7727 /* File: armv5te/OP_UNUSED_F1.S */
7728 /* File: armv5te/unused.S */
7729     bl      common_abort
7730
7731
7732
7733 /* ------------------------------ */
7734     .balign 64
7735 .L_OP_IGET_QUICK: /* 0xf2 */
7736 /* File: armv5te/OP_IGET_QUICK.S */
7737     /* For: iget-quick, iget-object-quick */
7738     /* op vA, vB, offset@CCCC */
7739     mov     r2, rINST, lsr #12          @ r2<- B
7740     GET_VREG(r3, r2)                    @ r3<- object we're operating on
7741     FETCH(r1, 1)                        @ r1<- field byte offset
7742     cmp     r3, #0                      @ check object for null
7743     mov     r2, rINST, lsr #8           @ r2<- A(+)
7744     beq     common_errNullObject        @ object was null
7745     ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7746     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7747     and     r2, r2, #15
7748     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7749     SET_VREG(r0, r2)                    @ fp[A]<- r0
7750     GOTO_OPCODE(ip)                     @ jump to next instruction
7751
7752
7753 /* ------------------------------ */
7754     .balign 64
7755 .L_OP_IGET_WIDE_QUICK: /* 0xf3 */
7756 /* File: armv4t/OP_IGET_WIDE_QUICK.S */
7757     /* iget-wide-quick vA, vB, offset@CCCC */
7758     mov     r2, rINST, lsr #12          @ r2<- B
7759     GET_VREG(r3, r2)                    @ r3<- object we're operating on
7760     FETCH(r1, 1)                        @ r1<- field byte offset
7761     cmp     r3, #0                      @ check object for null
7762     mov     r2, rINST, lsr #8           @ r2<- A(+)
7763     beq     common_errNullObject        @ object was null
7764     add     r9, r3, r1                  @ r9<- object + offset
7765     ldmia   r9, {r0-r1}                 @ r0/r1<- obj.field (64 bits, aligned)
7766     and     r2, r2, #15                 @ r2<- A
7767     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7768     add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
7769     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7770     stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
7771     GOTO_OPCODE(ip)                     @ jump to next instruction
7772
7773
7774 /* ------------------------------ */
7775     .balign 64
7776 .L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
7777 /* File: armv5te/OP_IGET_OBJECT_QUICK.S */
7778 /* File: armv5te/OP_IGET_QUICK.S */
7779     /* For: iget-quick, iget-object-quick */
7780     /* op vA, vB, offset@CCCC */
7781     mov     r2, rINST, lsr #12          @ r2<- B
7782     GET_VREG(r3, r2)                    @ r3<- object we're operating on
7783     FETCH(r1, 1)                        @ r1<- field byte offset
7784     cmp     r3, #0                      @ check object for null
7785     mov     r2, rINST, lsr #8           @ r2<- A(+)
7786     beq     common_errNullObject        @ object was null
7787     ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7788     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7789     and     r2, r2, #15
7790     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7791     SET_VREG(r0, r2)                    @ fp[A]<- r0
7792     GOTO_OPCODE(ip)                     @ jump to next instruction
7793
7794
7795
7796 /* ------------------------------ */
7797     .balign 64
7798 .L_OP_IPUT_QUICK: /* 0xf5 */
7799 /* File: armv5te/OP_IPUT_QUICK.S */
7800     /* For: iput-quick, iput-object-quick */
7801     /* op vA, vB, offset@CCCC */
7802     mov     r2, rINST, lsr #12          @ r2<- B
7803     GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7804     FETCH(r1, 1)                        @ r1<- field byte offset
7805     cmp     r3, #0                      @ check object for null
7806     mov     r2, rINST, lsr #8           @ r2<- A(+)
7807     beq     common_errNullObject        @ object was null
7808     and     r2, r2, #15
7809     GET_VREG(r0, r2)                    @ r0<- fp[A]
7810     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7811     str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7812     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7813     GOTO_OPCODE(ip)                     @ jump to next instruction
7814
7815
7816 /* ------------------------------ */
7817     .balign 64
7818 .L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
7819 /* File: armv4t/OP_IPUT_WIDE_QUICK.S */
7820     /* iput-wide-quick vA, vB, offset@CCCC */
7821     mov     r0, rINST, lsr #8           @ r0<- A(+)
7822     mov     r1, rINST, lsr #12          @ r1<- B
7823     and     r0, r0, #15
7824     GET_VREG(r2, r1)                    @ r2<- fp[B], the object pointer
7825     add     r3, rFP, r0, lsl #2         @ r3<- &fp[A]
7826     cmp     r2, #0                      @ check object for null
7827     ldmia   r3, {r0-r1}                 @ r0/r1<- fp[A]
7828     beq     common_errNullObject        @ object was null
7829     FETCH(r3, 1)                        @ r3<- field byte offset
7830     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7831     add     r2, r2, r3                  @ r2<- object + byte offset
7832     stmia   r2, {r0-r1}                 @ obj.field (64 bits, aligned)<- r0/r1
7833     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7834     GOTO_OPCODE(ip)                     @ jump to next instruction
7835
7836
7837 /* ------------------------------ */
7838     .balign 64
7839 .L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
7840 /* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
7841 /* File: armv5te/OP_IPUT_QUICK.S */
7842     /* For: iput-quick, iput-object-quick */
7843     /* op vA, vB, offset@CCCC */
7844     mov     r2, rINST, lsr #12          @ r2<- B
7845     GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7846     FETCH(r1, 1)                        @ r1<- field byte offset
7847     cmp     r3, #0                      @ check object for null
7848     mov     r2, rINST, lsr #8           @ r2<- A(+)
7849     beq     common_errNullObject        @ object was null
7850     and     r2, r2, #15
7851     GET_VREG(r0, r2)                    @ r0<- fp[A]
7852     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7853     str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7854     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7855     GOTO_OPCODE(ip)                     @ jump to next instruction
7856
7857
7858
7859 /* ------------------------------ */
7860     .balign 64
7861 .L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
7862 /* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7863     /*
7864      * Handle an optimized virtual method call.
7865      *
7866      * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7867      */
7868     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7869     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7870     FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7871     FETCH(r1, 1)                        @ r1<- BBBB
7872     .if     (!0)
7873     and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7874     .endif
7875     GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7876     cmp     r2, #0                      @ is "this" null?
7877     beq     common_errNullObject        @ null "this", throw exception
7878     ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7879     ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7880     EXPORT_PC()                         @ invoke must export
7881     ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7882     bl      common_invokeMethodNoRange @ continue on
7883
7884 /* ------------------------------ */
7885     .balign 64
7886 .L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
7887 /* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
7888 /* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7889     /*
7890      * Handle an optimized virtual method call.
7891      *
7892      * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7893      */
7894     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7895     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7896     FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7897     FETCH(r1, 1)                        @ r1<- BBBB
7898     .if     (!1)
7899     and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7900     .endif
7901     GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7902     cmp     r2, #0                      @ is "this" null?
7903     beq     common_errNullObject        @ null "this", throw exception
7904     ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7905     ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7906     EXPORT_PC()                         @ invoke must export
7907     ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7908     bl      common_invokeMethodRange @ continue on
7909
7910
7911 /* ------------------------------ */
7912     .balign 64
7913 .L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
7914 /* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7915     /*
7916      * Handle an optimized "super" method call.
7917      *
7918      * for: [opt] invoke-super-quick, invoke-super-quick/range
7919      */
7920     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7921     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7922     FETCH(r10, 2)                       @ r10<- GFED or CCCC
7923     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7924     .if     (!0)
7925     and     r10, r10, #15               @ r10<- D (or stays CCCC)
7926     .endif
7927     FETCH(r1, 1)                        @ r1<- BBBB
7928     ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7929     EXPORT_PC()                         @ must export for invoke
7930     ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7931     GET_VREG(r3, r10)                   @ r3<- "this"
7932     ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7933     cmp     r3, #0                      @ null "this" ref?
7934     ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7935     beq     common_errNullObject        @ "this" is null, throw exception
7936     bl      common_invokeMethodNoRange @ continue on
7937
7938
7939 /* ------------------------------ */
7940     .balign 64
7941 .L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
7942 /* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
7943 /* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7944     /*
7945      * Handle an optimized "super" method call.
7946      *
7947      * for: [opt] invoke-super-quick, invoke-super-quick/range
7948      */
7949     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7950     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7951     FETCH(r10, 2)                       @ r10<- GFED or CCCC
7952     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7953     .if     (!1)
7954     and     r10, r10, #15               @ r10<- D (or stays CCCC)
7955     .endif
7956     FETCH(r1, 1)                        @ r1<- BBBB
7957     ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7958     EXPORT_PC()                         @ must export for invoke
7959     ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7960     GET_VREG(r3, r10)                   @ r3<- "this"
7961     ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7962     cmp     r3, #0                      @ null "this" ref?
7963     ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7964     beq     common_errNullObject        @ "this" is null, throw exception
7965     bl      common_invokeMethodRange @ continue on
7966
7967
7968
7969 /* ------------------------------ */
7970     .balign 64
7971 .L_OP_UNUSED_FC: /* 0xfc */
7972 /* File: armv5te/OP_UNUSED_FC.S */
7973 /* File: armv5te/unused.S */
7974     bl      common_abort
7975
7976
7977
7978 /* ------------------------------ */
7979     .balign 64
7980 .L_OP_UNUSED_FD: /* 0xfd */
7981 /* File: armv5te/OP_UNUSED_FD.S */
7982 /* File: armv5te/unused.S */
7983     bl      common_abort
7984
7985
7986
7987 /* ------------------------------ */
7988     .balign 64
7989 .L_OP_UNUSED_FE: /* 0xfe */
7990 /* File: armv5te/OP_UNUSED_FE.S */
7991 /* File: armv5te/unused.S */
7992     bl      common_abort
7993
7994
7995
7996 /* ------------------------------ */
7997     .balign 64
7998 .L_OP_UNUSED_FF: /* 0xff */
7999 /* File: armv5te/OP_UNUSED_FF.S */
8000 /* File: armv5te/unused.S */
8001     bl      common_abort
8002
8003
8004
8005
8006     .balign 64
8007     .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
8008     .global dvmAsmInstructionEnd
8009 dvmAsmInstructionEnd:
8010
8011 /*
8012  * ===========================================================================
8013  *  Sister implementations
8014  * ===========================================================================
8015  */
8016     .global dvmAsmSisterStart
8017     .type   dvmAsmSisterStart, %function
8018     .text
8019     .balign 4
8020 dvmAsmSisterStart:
8021
8022 /* continuation for OP_CONST_STRING */
8023
8024     /*
8025      * Continuation if the String has not yet been resolved.
8026      *  r1: BBBB (String ref)
8027      *  r9: target register
8028      */
8029 .LOP_CONST_STRING_resolve:
8030     EXPORT_PC()
8031     ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
8032     ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
8033     bl      dvmResolveString            @ r0<- String reference
8034     cmp     r0, #0                      @ failed?
8035     beq     common_exceptionThrown      @ yup, handle the exception
8036     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8037     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8038     SET_VREG(r0, r9)                    @ vAA<- r0
8039     GOTO_OPCODE(ip)                     @ jump to next instruction
8040
8041
8042 /* continuation for OP_CONST_STRING_JUMBO */
8043
8044     /*
8045      * Continuation if the String has not yet been resolved.
8046      *  r1: BBBBBBBB (String ref)
8047      *  r9: target register
8048      */
8049 .LOP_CONST_STRING_JUMBO_resolve:
8050     EXPORT_PC()
8051     ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
8052     ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
8053     bl      dvmResolveString            @ r0<- String reference
8054     cmp     r0, #0                      @ failed?
8055     beq     common_exceptionThrown      @ yup, handle the exception
8056     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
8057     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8058     SET_VREG(r0, r9)                    @ vAA<- r0
8059     GOTO_OPCODE(ip)                     @ jump to next instruction
8060
8061
8062 /* continuation for OP_CONST_CLASS */
8063
8064     /*
8065      * Continuation if the Class has not yet been resolved.
8066      *  r1: BBBB (Class ref)
8067      *  r9: target register
8068      */
8069 .LOP_CONST_CLASS_resolve:
8070     EXPORT_PC()
8071     ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
8072     mov     r2, #1                      @ r2<- true
8073     ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
8074     bl      dvmResolveClass             @ r0<- Class reference
8075     cmp     r0, #0                      @ failed?
8076     beq     common_exceptionThrown      @ yup, handle the exception
8077     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8078     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8079     SET_VREG(r0, r9)                    @ vAA<- r0
8080     GOTO_OPCODE(ip)                     @ jump to next instruction
8081
8082
8083 /* continuation for OP_CHECK_CAST */
8084
8085     /*
8086      * Trivial test failed, need to perform full check.  This is common.
8087      *  r0 holds obj->clazz
8088      *  r1 holds class resolved from BBBB
8089      *  r9 holds object
8090      */
8091 .LOP_CHECK_CAST_fullcheck:
8092     bl      dvmInstanceofNonTrivial     @ r0<- boolean result
8093     cmp     r0, #0                      @ failed?
8094     bne     .LOP_CHECK_CAST_okay            @ no, success
8095
8096     @ A cast has failed.  We need to throw a ClassCastException with the
8097     @ class of the object that failed to be cast.
8098     EXPORT_PC()                         @ about to throw
8099     ldr     r3, [r9, #offObject_clazz]  @ r3<- obj->clazz
8100     ldr     r0, .LstrClassCastExceptionPtr
8101     ldr     r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor
8102     bl      dvmThrowExceptionWithClassMessage
8103     b       common_exceptionThrown
8104
8105     /*
8106      * Resolution required.  This is the least-likely path.
8107      *
8108      *  r2 holds BBBB
8109      *  r9 holds object
8110      */
8111 .LOP_CHECK_CAST_resolve:
8112     EXPORT_PC()                         @ resolve() could throw
8113     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8114     mov     r1, r2                      @ r1<- BBBB
8115     mov     r2, #0                      @ r2<- false
8116     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8117     bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
8118     cmp     r0, #0                      @ got null?
8119     beq     common_exceptionThrown      @ yes, handle exception
8120     mov     r1, r0                      @ r1<- class resolved from BBB
8121     ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
8122     b       .LOP_CHECK_CAST_resolved        @ pick up where we left off
8123
8124 .LstrClassCastExceptionPtr:
8125     .word   .LstrClassCastException
8126
8127
8128 /* continuation for OP_INSTANCE_OF */
8129
8130     /*
8131      * Trivial test failed, need to perform full check.  This is common.
8132      *  r0 holds obj->clazz
8133      *  r1 holds class resolved from BBBB
8134      *  r9 holds A
8135      */
8136 .LOP_INSTANCE_OF_fullcheck:
8137     bl      dvmInstanceofNonTrivial     @ r0<- boolean result
8138     @ fall through to OP_INSTANCE_OF_store
8139
8140     /*
8141      * r0 holds boolean result
8142      * r9 holds A
8143      */
8144 .LOP_INSTANCE_OF_store:
8145     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8146     SET_VREG(r0, r9)                    @ vA<- r0
8147     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8148     GOTO_OPCODE(ip)                     @ jump to next instruction
8149
8150     /*
8151      * Trivial test succeeded, save and bail.
8152      *  r9 holds A
8153      */
8154 .LOP_INSTANCE_OF_trivial:
8155     mov     r0, #1                      @ indicate success
8156     @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
8157     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8158     SET_VREG(r0, r9)                    @ vA<- r0
8159     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8160     GOTO_OPCODE(ip)                     @ jump to next instruction
8161
8162     /*
8163      * Resolution required.  This is the least-likely path.
8164      *
8165      *  r3 holds BBBB
8166      *  r9 holds A
8167      */
8168 .LOP_INSTANCE_OF_resolve:
8169     EXPORT_PC()                         @ resolve() could throw
8170     ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
8171     mov     r1, r3                      @ r1<- BBBB
8172     mov     r2, #1                      @ r2<- true
8173     ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
8174     bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
8175     cmp     r0, #0                      @ got null?
8176     beq     common_exceptionThrown      @ yes, handle exception
8177     mov     r1, r0                      @ r1<- class resolved from BBB
8178     mov     r3, rINST, lsr #12          @ r3<- B
8179     GET_VREG(r0, r3)                    @ r0<- vB (object)
8180     ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
8181     b       .LOP_INSTANCE_OF_resolved        @ pick up where we left off
8182
8183
8184 /* continuation for OP_NEW_INSTANCE */
8185
8186     .balign 32                          @ minimize cache lines
8187 .LOP_NEW_INSTANCE_finish: @ r0=new object
8188     mov     r3, rINST, lsr #8           @ r3<- AA
8189     cmp     r0, #0                      @ failed?
8190     beq     common_exceptionThrown      @ yes, handle the exception
8191     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8192     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8193     SET_VREG(r0, r3)                    @ vAA<- r0
8194     GOTO_OPCODE(ip)                     @ jump to next instruction
8195
8196     /*
8197      * Class initialization required.
8198      *
8199      *  r0 holds class object
8200      */
8201 .LOP_NEW_INSTANCE_needinit:
8202     mov     r9, r0                      @ save r0
8203     bl      dvmInitClass                @ initialize class
8204     cmp     r0, #0                      @ check boolean result
8205     mov     r0, r9                      @ restore r0
8206     bne     .LOP_NEW_INSTANCE_initialized     @ success, continue
8207     b       common_exceptionThrown      @ failed, deal with init exception
8208
8209     /*
8210      * Resolution required.  This is the least-likely path.
8211      *
8212      *  r1 holds BBBB
8213      */
8214 .LOP_NEW_INSTANCE_resolve:
8215     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8216     mov     r2, #0                      @ r2<- false
8217     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8218     bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
8219     cmp     r0, #0                      @ got null?
8220     bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
8221     b       common_exceptionThrown      @ yes, handle exception
8222
8223 .LstrInstantiationErrorPtr:
8224     .word   .LstrInstantiationError
8225
8226
8227 /* continuation for OP_NEW_ARRAY */
8228
8229
8230     /*
8231      * Resolve class.  (This is an uncommon case.)
8232      *
8233      *  r1 holds array length
8234      *  r2 holds class ref CCCC
8235      */
8236 .LOP_NEW_ARRAY_resolve:
8237     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8238     mov     r9, r1                      @ r9<- length (save)
8239     mov     r1, r2                      @ r1<- CCCC
8240     mov     r2, #0                      @ r2<- false
8241     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8242     bl      dvmResolveClass             @ r0<- call(clazz, ref)
8243     cmp     r0, #0                      @ got null?
8244     mov     r1, r9                      @ r1<- length (restore)
8245     beq     common_exceptionThrown      @ yes, handle exception
8246     @ fall through to OP_NEW_ARRAY_finish
8247
8248     /*
8249      * Finish allocation.
8250      *
8251      *  r0 holds class
8252      *  r1 holds array length
8253      */
8254 .LOP_NEW_ARRAY_finish:
8255     mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
8256     bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
8257     cmp     r0, #0                      @ failed?
8258     mov     r2, rINST, lsr #8           @ r2<- A+
8259     beq     common_exceptionThrown      @ yes, handle the exception
8260     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8261     and     r2, r2, #15                 @ r2<- A
8262     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8263     SET_VREG(r0, r2)                    @ vA<- r0
8264     GOTO_OPCODE(ip)                     @ jump to next instruction
8265
8266
8267 /* continuation for OP_FILLED_NEW_ARRAY */
8268
8269     /*
8270      * On entry:
8271      *  r0 holds array class
8272      *  r10 holds AA or BA
8273      */
8274 .LOP_FILLED_NEW_ARRAY_continue:
8275     ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8276     mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8277     ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
8278     .if     0
8279     mov     r1, r10                     @ r1<- AA (length)
8280     .else
8281     mov     r1, r10, lsr #4             @ r1<- B (length)
8282     .endif
8283     cmp     r3, #'I'                    @ array of ints?
8284     cmpne   r3, #'L'                    @ array of objects?
8285     cmpne   r3, #'['                    @ array of arrays?
8286     mov     r9, r1                      @ save length in r9
8287     bne     .LOP_FILLED_NEW_ARRAY_notimpl         @ no, not handled yet
8288     bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8289     cmp     r0, #0                      @ null return?
8290     beq     common_exceptionThrown      @ alloc failed, handle exception
8291
8292     FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8293     str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
8294     add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8295     subs    r9, r9, #1                  @ length--, check for neg
8296     FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8297     bmi     2f                          @ was zero, bail
8298
8299     @ copy values from registers into the array
8300     @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8301     .if     0
8302     add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
8303 1:  ldr     r3, [r2], #4                @ r3<- *r2++
8304     subs    r9, r9, #1                  @ count--
8305     str     r3, [r0], #4                @ *contents++ = vX
8306     bpl     1b
8307     @ continue at 2
8308     .else
8309     cmp     r9, #4                      @ length was initially 5?
8310     and     r2, r10, #15                @ r2<- A
8311     bne     1f                          @ <= 4 args, branch
8312     GET_VREG(r3, r2)                    @ r3<- vA
8313     sub     r9, r9, #1                  @ count--
8314     str     r3, [r0, #16]               @ contents[4] = vA
8315 1:  and     r2, r1, #15                 @ r2<- F/E/D/C
8316     GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8317     mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8318     subs    r9, r9, #1                  @ count--
8319     str     r3, [r0], #4                @ *contents++ = vX
8320     bpl     1b
8321     @ continue at 2
8322     .endif
8323
8324 2:
8325     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
8326     GOTO_OPCODE(ip)                     @ execute it
8327
8328     /*
8329      * Throw an exception indicating that we have not implemented this
8330      * mode of filled-new-array.
8331      */
8332 .LOP_FILLED_NEW_ARRAY_notimpl:
8333     ldr     r0, .L_strInternalError
8334     ldr     r1, .L_strFilledNewArrayNotImpl
8335     bl      dvmThrowException
8336     b       common_exceptionThrown
8337
8338     .if     (!0)                 @ define in one or the other, not both
8339 .L_strFilledNewArrayNotImpl:
8340     .word   .LstrFilledNewArrayNotImpl
8341 .L_strInternalError:
8342     .word   .LstrInternalError
8343     .endif
8344
8345
8346 /* continuation for OP_FILLED_NEW_ARRAY_RANGE */
8347
8348     /*
8349      * On entry:
8350      *  r0 holds array class
8351      *  r10 holds AA or BA
8352      */
8353 .LOP_FILLED_NEW_ARRAY_RANGE_continue:
8354     ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8355     mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8356     ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
8357     .if     1
8358     mov     r1, r10                     @ r1<- AA (length)
8359     .else
8360     mov     r1, r10, lsr #4             @ r1<- B (length)
8361     .endif
8362     cmp     r3, #'I'                    @ array of ints?
8363     cmpne   r3, #'L'                    @ array of objects?
8364     cmpne   r3, #'['                    @ array of arrays?
8365     mov     r9, r1                      @ save length in r9
8366     bne     .LOP_FILLED_NEW_ARRAY_RANGE_notimpl         @ no, not handled yet
8367     bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8368     cmp     r0, #0                      @ null return?
8369     beq     common_exceptionThrown      @ alloc failed, handle exception
8370
8371     FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8372     str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
8373     add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8374     subs    r9, r9, #1                  @ length--, check for neg
8375     FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8376     bmi     2f                          @ was zero, bail
8377
8378     @ copy values from registers into the array
8379     @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8380     .if     1
8381     add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
8382 1:  ldr     r3, [r2], #4                @ r3<- *r2++
8383     subs    r9, r9, #1                  @ count--
8384     str     r3, [r0], #4                @ *contents++ = vX
8385     bpl     1b
8386     @ continue at 2
8387     .else
8388     cmp     r9, #4                      @ length was initially 5?
8389     and     r2, r10, #15                @ r2<- A
8390     bne     1f                          @ <= 4 args, branch
8391     GET_VREG(r3, r2)                    @ r3<- vA
8392     sub     r9, r9, #1                  @ count--
8393     str     r3, [r0, #16]               @ contents[4] = vA
8394 1:  and     r2, r1, #15                 @ r2<- F/E/D/C
8395     GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8396     mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8397     subs    r9, r9, #1                  @ count--
8398     str     r3, [r0], #4                @ *contents++ = vX
8399     bpl     1b
8400     @ continue at 2
8401     .endif
8402
8403 2:
8404     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
8405     GOTO_OPCODE(ip)                     @ execute it
8406
8407     /*
8408      * Throw an exception indicating that we have not implemented this
8409      * mode of filled-new-array.
8410      */
8411 .LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
8412     ldr     r0, .L_strInternalError
8413     ldr     r1, .L_strFilledNewArrayNotImpl
8414     bl      dvmThrowException
8415     b       common_exceptionThrown
8416
8417     .if     (!1)                 @ define in one or the other, not both
8418 .L_strFilledNewArrayNotImpl:
8419     .word   .LstrFilledNewArrayNotImpl
8420 .L_strInternalError:
8421     .word   .LstrInternalError
8422     .endif
8423
8424
8425 /* continuation for OP_CMPL_FLOAT */
8426
8427     @ Test for NaN with a second comparison.  EABI forbids testing bit
8428     @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8429     @ make the library call.
8430 .LOP_CMPL_FLOAT_gt_or_nan:
8431     mov     r1, r9                      @ reverse order
8432     mov     r0, r10
8433     bl      __aeabi_cfcmple             @ r0<- Z set if eq, C clear if <
8434     @bleq    common_abort
8435     movcc   r1, #1                      @ (greater than) r1<- 1
8436     bcc     .LOP_CMPL_FLOAT_finish
8437     mvn     r1, #0                            @ r1<- 1 or -1 for NaN
8438     b       .LOP_CMPL_FLOAT_finish
8439
8440
8441 #if 0       /* "clasic" form */
8442     FETCH(r0, 1)                        @ r0<- CCBB
8443     and     r2, r0, #255                @ r2<- BB
8444     mov     r3, r0, lsr #8              @ r3<- CC
8445     GET_VREG(r9, r2)                    @ r9<- vBB
8446     GET_VREG(r10, r3)                   @ r10<- vCC
8447     mov     r0, r9                      @ r0<- vBB
8448     mov     r1, r10                     @ r1<- vCC
8449     bl      __aeabi_fcmpeq              @ r0<- (vBB == vCC)
8450     cmp     r0, #0                      @ equal?
8451     movne   r1, #0                      @ yes, result is 0
8452     bne     OP_CMPL_FLOAT_finish
8453     mov     r0, r9                      @ r0<- vBB
8454     mov     r1, r10                     @ r1<- vCC
8455     bl      __aeabi_fcmplt              @ r0<- (vBB < vCC)
8456     cmp     r0, #0                      @ less than?
8457     b       OP_CMPL_FLOAT_continue
8458 @%break
8459
8460 OP_CMPL_FLOAT_continue:
8461     mvnne   r1, #0                      @ yes, result is -1
8462     bne     OP_CMPL_FLOAT_finish
8463     mov     r0, r9                      @ r0<- vBB
8464     mov     r1, r10                     @ r1<- vCC
8465     bl      __aeabi_fcmpgt              @ r0<- (vBB > vCC)
8466     cmp     r0, #0                      @ greater than?
8467     beq     OP_CMPL_FLOAT_nan               @ no, must be NaN
8468     mov     r1, #1                      @ yes, result is 1
8469     @ fall through to _finish
8470
8471 OP_CMPL_FLOAT_finish:
8472     mov     r3, rINST, lsr #8           @ r3<- AA
8473     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8474     SET_VREG(r1, r3)                    @ vAA<- r1
8475     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8476     GOTO_OPCODE(ip)                     @ jump to next instruction
8477
8478     /*
8479      * This is expected to be uncommon, so we double-branch (once to here,
8480      * again back to _finish).
8481      */
8482 OP_CMPL_FLOAT_nan:
8483     mvn     r1, #0                            @ r1<- 1 or -1 for NaN
8484     b       OP_CMPL_FLOAT_finish
8485
8486 #endif
8487
8488
8489 /* continuation for OP_CMPG_FLOAT */
8490
8491     @ Test for NaN with a second comparison.  EABI forbids testing bit
8492     @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8493     @ make the library call.
8494 .LOP_CMPG_FLOAT_gt_or_nan:
8495     mov     r1, r9                      @ reverse order
8496     mov     r0, r10
8497     bl      __aeabi_cfcmple             @ r0<- Z set if eq, C clear if <
8498     @bleq    common_abort
8499     movcc   r1, #1                      @ (greater than) r1<- 1
8500     bcc     .LOP_CMPG_FLOAT_finish
8501     mov     r1, #1                            @ r1<- 1 or -1 for NaN
8502     b       .LOP_CMPG_FLOAT_finish
8503
8504
8505 #if 0       /* "clasic" form */
8506     FETCH(r0, 1)                        @ r0<- CCBB
8507     and     r2, r0, #255                @ r2<- BB
8508     mov     r3, r0, lsr #8              @ r3<- CC
8509     GET_VREG(r9, r2)                    @ r9<- vBB
8510     GET_VREG(r10, r3)                   @ r10<- vCC
8511     mov     r0, r9                      @ r0<- vBB
8512     mov     r1, r10                     @ r1<- vCC
8513     bl      __aeabi_fcmpeq              @ r0<- (vBB == vCC)
8514     cmp     r0, #0                      @ equal?
8515     movne   r1, #0                      @ yes, result is 0
8516     bne     OP_CMPG_FLOAT_finish
8517     mov     r0, r9                      @ r0<- vBB
8518     mov     r1, r10                     @ r1<- vCC
8519     bl      __aeabi_fcmplt              @ r0<- (vBB < vCC)
8520     cmp     r0, #0                      @ less than?
8521     b       OP_CMPG_FLOAT_continue
8522 @%break
8523
8524 OP_CMPG_FLOAT_continue:
8525     mvnne   r1, #0                      @ yes, result is -1
8526     bne     OP_CMPG_FLOAT_finish
8527     mov     r0, r9                      @ r0<- vBB
8528     mov     r1, r10                     @ r1<- vCC
8529     bl      __aeabi_fcmpgt              @ r0<- (vBB > vCC)
8530     cmp     r0, #0                      @ greater than?
8531     beq     OP_CMPG_FLOAT_nan               @ no, must be NaN
8532     mov     r1, #1                      @ yes, result is 1
8533     @ fall through to _finish
8534
8535 OP_CMPG_FLOAT_finish:
8536     mov     r3, rINST, lsr #8           @ r3<- AA
8537     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8538     SET_VREG(r1, r3)                    @ vAA<- r1
8539     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8540     GOTO_OPCODE(ip)                     @ jump to next instruction
8541
8542     /*
8543      * This is expected to be uncommon, so we double-branch (once to here,
8544      * again back to _finish).
8545      */
8546 OP_CMPG_FLOAT_nan:
8547     mov     r1, #1                            @ r1<- 1 or -1 for NaN
8548     b       OP_CMPG_FLOAT_finish
8549
8550 #endif
8551
8552
8553 /* continuation for OP_CMPL_DOUBLE */
8554
8555     @ Test for NaN with a second comparison.  EABI forbids testing bit
8556     @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8557     @ make the library call.
8558 .LOP_CMPL_DOUBLE_gt_or_nan:
8559     ldmia   r10, {r0-r1}                @ reverse order
8560     ldmia   r9, {r2-r3}
8561     bl      __aeabi_cdcmple             @ r0<- Z set if eq, C clear if <
8562     @bleq    common_abort
8563     movcc   r1, #1                      @ (greater than) r1<- 1
8564     bcc     .LOP_CMPL_DOUBLE_finish
8565     mvn     r1, #0                            @ r1<- 1 or -1 for NaN
8566     b       .LOP_CMPL_DOUBLE_finish
8567
8568
8569 /* continuation for OP_CMPG_DOUBLE */
8570
8571     @ Test for NaN with a second comparison.  EABI forbids testing bit
8572     @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8573     @ make the library call.
8574 .LOP_CMPG_DOUBLE_gt_or_nan:
8575     ldmia   r10, {r0-r1}                @ reverse order
8576     ldmia   r9, {r2-r3}
8577     bl      __aeabi_cdcmple             @ r0<- Z set if eq, C clear if <
8578     @bleq    common_abort
8579     movcc   r1, #1                      @ (greater than) r1<- 1
8580     bcc     .LOP_CMPG_DOUBLE_finish
8581     mov     r1, #1                            @ r1<- 1 or -1 for NaN
8582     b       .LOP_CMPG_DOUBLE_finish
8583
8584
8585 /* continuation for OP_CMP_LONG */
8586
8587 .LOP_CMP_LONG_less:
8588     mvn     r1, #0                      @ r1<- -1
8589     @ Want to cond code the next mov so we can avoid branch, but don't see it;
8590     @ instead, we just replicate the tail end.
8591     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8592     SET_VREG(r1, r9)                    @ vAA<- r1
8593     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8594     GOTO_OPCODE(ip)                     @ jump to next instruction
8595
8596 .LOP_CMP_LONG_greater:
8597     mov     r1, #1                      @ r1<- 1
8598     @ fall through to _finish
8599
8600 .LOP_CMP_LONG_finish:
8601     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8602     SET_VREG(r1, r9)                    @ vAA<- r1
8603     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8604     GOTO_OPCODE(ip)                     @ jump to next instruction
8605
8606
8607 /* continuation for OP_AGET_WIDE */
8608
8609 .LOP_AGET_WIDE_finish:
8610     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8611     add     r0, r0, #offArrayObject_contents
8612     ldmia   r0, {r2-r3}                 @ r2/r3 <- vBB[vCC]
8613     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
8614     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8615     stmia   r9, {r2-r3}                 @ vAA/vAA+1<- r2/r3
8616     GOTO_OPCODE(ip)                     @ jump to next instruction
8617
8618
8619 /* continuation for OP_APUT_WIDE */
8620
8621 .LOP_APUT_WIDE_finish:
8622     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8623     ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
8624     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8625     add     r0, #offArrayObject_contents
8626     stmia   r0, {r2-r3}                 @ vBB[vCC] <- r2/r3
8627     GOTO_OPCODE(ip)                     @ jump to next instruction
8628
8629
8630 /* continuation for OP_APUT_OBJECT */
8631     /*
8632      * On entry:
8633      *  r1 = vBB (arrayObj)
8634      *  r9 = vAA (obj)
8635      *  r10 = offset into array (vBB + vCC * width)
8636      */
8637 .LOP_APUT_OBJECT_finish:
8638     cmp     r9, #0                      @ storing null reference?
8639     beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
8640     ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
8641     ldr     r1, [r1, #offObject_clazz]  @ r1<- arrayObj->clazz
8642     bl      dvmCanPutArrayElement       @ test object type vs. array type
8643     cmp     r0, #0                      @ okay?
8644     beq     common_errArrayStore        @ no
8645 .LOP_APUT_OBJECT_skip_check:
8646     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8647     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8648     str     r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
8649     GOTO_OPCODE(ip)                     @ jump to next instruction
8650
8651
8652 /* continuation for OP_IGET */
8653
8654     /*
8655      * Currently:
8656      *  r0 holds resolved field
8657      *  r9 holds object
8658      */
8659 .LOP_IGET_finish:
8660     @bl      common_squeak0
8661     cmp     r9, #0                      @ check object for null
8662     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8663     beq     common_errNullObject        @ object was null
8664     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8665     mov     r2, rINST, lsr #8           @ r2<- A+
8666     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8667     and     r2, r2, #15                 @ r2<- A
8668     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8669     SET_VREG(r0, r2)                    @ fp[A]<- r0
8670     GOTO_OPCODE(ip)                     @ jump to next instruction
8671
8672
8673 /* continuation for OP_IGET_WIDE */
8674
8675     /*
8676      * Currently:
8677      *  r0 holds resolved field
8678      *  r9 holds object
8679      */
8680 .LOP_IGET_WIDE_finish:
8681     cmp     r9, #0                      @ check object for null
8682     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8683     beq     common_errNullObject        @ object was null
8684     mov     r2, rINST, lsr #8           @ r2<- A+
8685     add     r9, r9, r3                  @ r9<- obj + field offset
8686     ldmia   r9, {r0-r1}                 @ r0/r1<- obj.field (64-bit align ok)
8687     and     r2, r2, #15                 @ r2<- A
8688     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8689     add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
8690     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8691     stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
8692     GOTO_OPCODE(ip)                     @ jump to next instruction
8693
8694
8695 /* continuation for OP_IGET_OBJECT */
8696
8697     /*
8698      * Currently:
8699      *  r0 holds resolved field
8700      *  r9 holds object
8701      */
8702 .LOP_IGET_OBJECT_finish:
8703     @bl      common_squeak0
8704     cmp     r9, #0                      @ check object for null
8705     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8706     beq     common_errNullObject        @ object was null
8707     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8708     mov     r2, rINST, lsr #8           @ r2<- A+
8709     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8710     and     r2, r2, #15                 @ r2<- A
8711     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8712     SET_VREG(r0, r2)                    @ fp[A]<- r0
8713     GOTO_OPCODE(ip)                     @ jump to next instruction
8714
8715
8716 /* continuation for OP_IGET_BOOLEAN */
8717
8718     /*
8719      * Currently:
8720      *  r0 holds resolved field
8721      *  r9 holds object
8722      */
8723 .LOP_IGET_BOOLEAN_finish:
8724     @bl      common_squeak1
8725     cmp     r9, #0                      @ check object for null
8726     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8727     beq     common_errNullObject        @ object was null
8728     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8729     mov     r2, rINST, lsr #8           @ r2<- A+
8730     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8731     and     r2, r2, #15                 @ r2<- A
8732     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8733     SET_VREG(r0, r2)                    @ fp[A]<- r0
8734     GOTO_OPCODE(ip)                     @ jump to next instruction
8735
8736
8737 /* continuation for OP_IGET_BYTE */
8738
8739     /*
8740      * Currently:
8741      *  r0 holds resolved field
8742      *  r9 holds object
8743      */
8744 .LOP_IGET_BYTE_finish:
8745     @bl      common_squeak2
8746     cmp     r9, #0                      @ check object for null
8747     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8748     beq     common_errNullObject        @ object was null
8749     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8750     mov     r2, rINST, lsr #8           @ r2<- A+
8751     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8752     and     r2, r2, #15                 @ r2<- A
8753     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8754     SET_VREG(r0, r2)                    @ fp[A]<- r0
8755     GOTO_OPCODE(ip)                     @ jump to next instruction
8756
8757
8758 /* continuation for OP_IGET_CHAR */
8759
8760     /*
8761      * Currently:
8762      *  r0 holds resolved field
8763      *  r9 holds object
8764      */
8765 .LOP_IGET_CHAR_finish:
8766     @bl      common_squeak3
8767     cmp     r9, #0                      @ check object for null
8768     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8769     beq     common_errNullObject        @ object was null
8770     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8771     mov     r2, rINST, lsr #8           @ r2<- A+
8772     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8773     and     r2, r2, #15                 @ r2<- A
8774     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8775     SET_VREG(r0, r2)                    @ fp[A]<- r0
8776     GOTO_OPCODE(ip)                     @ jump to next instruction
8777
8778
8779 /* continuation for OP_IGET_SHORT */
8780
8781     /*
8782      * Currently:
8783      *  r0 holds resolved field
8784      *  r9 holds object
8785      */
8786 .LOP_IGET_SHORT_finish:
8787     @bl      common_squeak4
8788     cmp     r9, #0                      @ check object for null
8789     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8790     beq     common_errNullObject        @ object was null
8791     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8792     mov     r2, rINST, lsr #8           @ r2<- A+
8793     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8794     and     r2, r2, #15                 @ r2<- A
8795     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8796     SET_VREG(r0, r2)                    @ fp[A]<- r0
8797     GOTO_OPCODE(ip)                     @ jump to next instruction
8798
8799
8800 /* continuation for OP_IPUT */
8801
8802     /*
8803      * Currently:
8804      *  r0 holds resolved field
8805      *  r9 holds object
8806      */
8807 .LOP_IPUT_finish:
8808     @bl      common_squeak0
8809     mov     r1, rINST, lsr #8           @ r1<- A+
8810     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8811     and     r1, r1, #15                 @ r1<- A
8812     cmp     r9, #0                      @ check object for null
8813     GET_VREG(r0, r1)                    @ r0<- fp[A]
8814     beq     common_errNullObject        @ object was null
8815     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8816     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8817     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8818     GOTO_OPCODE(ip)                     @ jump to next instruction
8819
8820
8821 /* continuation for OP_IPUT_WIDE */
8822
8823     /*
8824      * Currently:
8825      *  r0 holds resolved field
8826      *  r9 holds object
8827      */
8828 .LOP_IPUT_WIDE_finish:
8829     mov     r2, rINST, lsr #8           @ r2<- A+
8830     cmp     r9, #0                      @ check object for null
8831     and     r2, r2, #15                 @ r2<- A
8832     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8833     add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
8834     beq     common_errNullObject        @ object was null
8835     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8836     ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
8837     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8838     add     r9, r9, r3                  @ r9<- object + byte offset
8839     stmia   r9, {r0-r1}                 @ obj.field (64 bits, aligned)<- r0/r1
8840     GOTO_OPCODE(ip)                     @ jump to next instruction
8841
8842
8843 /* continuation for OP_IPUT_OBJECT */
8844
8845     /*
8846      * Currently:
8847      *  r0 holds resolved field
8848      *  r9 holds object
8849      */
8850 .LOP_IPUT_OBJECT_finish:
8851     @bl      common_squeak0
8852     mov     r1, rINST, lsr #8           @ r1<- A+
8853     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8854     and     r1, r1, #15                 @ r1<- A
8855     cmp     r9, #0                      @ check object for null
8856     GET_VREG(r0, r1)                    @ r0<- fp[A]
8857     beq     common_errNullObject        @ object was null
8858     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8859     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8860     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8861     GOTO_OPCODE(ip)                     @ jump to next instruction
8862
8863
8864 /* continuation for OP_IPUT_BOOLEAN */
8865
8866     /*
8867      * Currently:
8868      *  r0 holds resolved field
8869      *  r9 holds object
8870      */
8871 .LOP_IPUT_BOOLEAN_finish:
8872     @bl      common_squeak1
8873     mov     r1, rINST, lsr #8           @ r1<- A+
8874     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8875     and     r1, r1, #15                 @ r1<- A
8876     cmp     r9, #0                      @ check object for null
8877     GET_VREG(r0, r1)                    @ r0<- fp[A]
8878     beq     common_errNullObject        @ object was null
8879     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8880     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8881     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8882     GOTO_OPCODE(ip)                     @ jump to next instruction
8883
8884
8885 /* continuation for OP_IPUT_BYTE */
8886
8887     /*
8888      * Currently:
8889      *  r0 holds resolved field
8890      *  r9 holds object
8891      */
8892 .LOP_IPUT_BYTE_finish:
8893     @bl      common_squeak2
8894     mov     r1, rINST, lsr #8           @ r1<- A+
8895     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8896     and     r1, r1, #15                 @ r1<- A
8897     cmp     r9, #0                      @ check object for null
8898     GET_VREG(r0, r1)                    @ r0<- fp[A]
8899     beq     common_errNullObject        @ object was null
8900     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8901     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8902     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8903     GOTO_OPCODE(ip)                     @ jump to next instruction
8904
8905
8906 /* continuation for OP_IPUT_CHAR */
8907
8908     /*
8909      * Currently:
8910      *  r0 holds resolved field
8911      *  r9 holds object
8912      */
8913 .LOP_IPUT_CHAR_finish:
8914     @bl      common_squeak3
8915     mov     r1, rINST, lsr #8           @ r1<- A+
8916     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8917     and     r1, r1, #15                 @ r1<- A
8918     cmp     r9, #0                      @ check object for null
8919     GET_VREG(r0, r1)                    @ r0<- fp[A]
8920     beq     common_errNullObject        @ object was null
8921     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8922     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8923     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8924     GOTO_OPCODE(ip)                     @ jump to next instruction
8925
8926
8927 /* continuation for OP_IPUT_SHORT */
8928
8929     /*
8930      * Currently:
8931      *  r0 holds resolved field
8932      *  r9 holds object
8933      */
8934 .LOP_IPUT_SHORT_finish:
8935     @bl      common_squeak4
8936     mov     r1, rINST, lsr #8           @ r1<- A+
8937     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8938     and     r1, r1, #15                 @ r1<- A
8939     cmp     r9, #0                      @ check object for null
8940     GET_VREG(r0, r1)                    @ r0<- fp[A]
8941     beq     common_errNullObject        @ object was null
8942     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8943     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8944     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8945     GOTO_OPCODE(ip)                     @ jump to next instruction
8946
8947
8948 /* continuation for OP_SGET */
8949
8950     /*
8951      * Continuation if the field has not yet been resolved.
8952      *  r1: BBBB field ref
8953      */
8954 .LOP_SGET_resolve:
8955     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8956     EXPORT_PC()                         @ resolve() could throw, so export now
8957     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8958     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8959     cmp     r0, #0                      @ success?
8960     bne     .LOP_SGET_finish          @ yes, finish
8961     b       common_exceptionThrown      @ no, handle exception
8962
8963
8964 /* continuation for OP_SGET_WIDE */
8965
8966     /*
8967      * Continuation if the field has not yet been resolved.
8968      *  r1: BBBB field ref
8969      */
8970 .LOP_SGET_WIDE_resolve:
8971     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8972     EXPORT_PC()                         @ resolve() could throw, so export now
8973     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8974     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8975     cmp     r0, #0                      @ success?
8976     bne     .LOP_SGET_WIDE_finish          @ yes, finish
8977     b       common_exceptionThrown      @ no, handle exception
8978
8979
8980 /* continuation for OP_SGET_OBJECT */
8981
8982     /*
8983      * Continuation if the field has not yet been resolved.
8984      *  r1: BBBB field ref
8985      */
8986 .LOP_SGET_OBJECT_resolve:
8987     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8988     EXPORT_PC()                         @ resolve() could throw, so export now
8989     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8990     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8991     cmp     r0, #0                      @ success?
8992     bne     .LOP_SGET_OBJECT_finish          @ yes, finish
8993     b       common_exceptionThrown      @ no, handle exception
8994
8995
8996 /* continuation for OP_SGET_BOOLEAN */
8997
8998     /*
8999      * Continuation if the field has not yet been resolved.
9000      *  r1: BBBB field ref
9001      */
9002 .LOP_SGET_BOOLEAN_resolve:
9003     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9004     EXPORT_PC()                         @ resolve() could throw, so export now
9005     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9006     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9007     cmp     r0, #0                      @ success?
9008     bne     .LOP_SGET_BOOLEAN_finish          @ yes, finish
9009     b       common_exceptionThrown      @ no, handle exception
9010
9011
9012 /* continuation for OP_SGET_BYTE */
9013
9014     /*
9015      * Continuation if the field has not yet been resolved.
9016      *  r1: BBBB field ref
9017      */
9018 .LOP_SGET_BYTE_resolve:
9019     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9020     EXPORT_PC()                         @ resolve() could throw, so export now
9021     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9022     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9023     cmp     r0, #0                      @ success?
9024     bne     .LOP_SGET_BYTE_finish          @ yes, finish
9025     b       common_exceptionThrown      @ no, handle exception
9026
9027
9028 /* continuation for OP_SGET_CHAR */
9029
9030     /*
9031      * Continuation if the field has not yet been resolved.
9032      *  r1: BBBB field ref
9033      */
9034 .LOP_SGET_CHAR_resolve:
9035     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9036     EXPORT_PC()                         @ resolve() could throw, so export now
9037     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9038     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9039     cmp     r0, #0                      @ success?
9040     bne     .LOP_SGET_CHAR_finish          @ yes, finish
9041     b       common_exceptionThrown      @ no, handle exception
9042
9043
9044 /* continuation for OP_SGET_SHORT */
9045
9046     /*
9047      * Continuation if the field has not yet been resolved.
9048      *  r1: BBBB field ref
9049      */
9050 .LOP_SGET_SHORT_resolve:
9051     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9052     EXPORT_PC()                         @ resolve() could throw, so export now
9053     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9054     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9055     cmp     r0, #0                      @ success?
9056     bne     .LOP_SGET_SHORT_finish          @ yes, finish
9057     b       common_exceptionThrown      @ no, handle exception
9058
9059
9060 /* continuation for OP_SPUT */
9061
9062     /*
9063      * Continuation if the field has not yet been resolved.
9064      *  r1: BBBB field ref
9065      */
9066 .LOP_SPUT_resolve:
9067     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9068     EXPORT_PC()                         @ resolve() could throw, so export now
9069     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9070     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9071     cmp     r0, #0                      @ success?
9072     bne     .LOP_SPUT_finish          @ yes, finish
9073     b       common_exceptionThrown      @ no, handle exception
9074
9075
9076 /* continuation for OP_SPUT_WIDE */
9077
9078     /*
9079      * Continuation if the field has not yet been resolved.
9080      *  r1: BBBB field ref
9081      *  r9: &fp[AA]
9082      */
9083 .LOP_SPUT_WIDE_resolve:
9084     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9085     EXPORT_PC()                         @ resolve() could throw, so export now
9086     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9087     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9088     cmp     r0, #0                      @ success?
9089     bne     .LOP_SPUT_WIDE_finish          @ yes, finish
9090     b       common_exceptionThrown      @ no, handle exception
9091
9092
9093 /* continuation for OP_SPUT_OBJECT */
9094
9095     /*
9096      * Continuation if the field has not yet been resolved.
9097      *  r1: BBBB field ref
9098      */
9099 .LOP_SPUT_OBJECT_resolve:
9100     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9101     EXPORT_PC()                         @ resolve() could throw, so export now
9102     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9103     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9104     cmp     r0, #0                      @ success?
9105     bne     .LOP_SPUT_OBJECT_finish          @ yes, finish
9106     b       common_exceptionThrown      @ no, handle exception
9107
9108
9109 /* continuation for OP_SPUT_BOOLEAN */
9110
9111     /*
9112      * Continuation if the field has not yet been resolved.
9113      *  r1: BBBB field ref
9114      */
9115 .LOP_SPUT_BOOLEAN_resolve:
9116     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9117     EXPORT_PC()                         @ resolve() could throw, so export now
9118     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9119     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9120     cmp     r0, #0                      @ success?
9121     bne     .LOP_SPUT_BOOLEAN_finish          @ yes, finish
9122     b       common_exceptionThrown      @ no, handle exception
9123
9124
9125 /* continuation for OP_SPUT_BYTE */
9126
9127     /*
9128      * Continuation if the field has not yet been resolved.
9129      *  r1: BBBB field ref
9130      */
9131 .LOP_SPUT_BYTE_resolve:
9132     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9133     EXPORT_PC()                         @ resolve() could throw, so export now
9134     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9135     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9136     cmp     r0, #0                      @ success?
9137     bne     .LOP_SPUT_BYTE_finish          @ yes, finish
9138     b       common_exceptionThrown      @ no, handle exception
9139
9140
9141 /* continuation for OP_SPUT_CHAR */
9142
9143     /*
9144      * Continuation if the field has not yet been resolved.
9145      *  r1: BBBB field ref
9146      */
9147 .LOP_SPUT_CHAR_resolve:
9148     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9149     EXPORT_PC()                         @ resolve() could throw, so export now
9150     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9151     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9152     cmp     r0, #0                      @ success?
9153     bne     .LOP_SPUT_CHAR_finish          @ yes, finish
9154     b       common_exceptionThrown      @ no, handle exception
9155
9156
9157 /* continuation for OP_SPUT_SHORT */
9158
9159     /*
9160      * Continuation if the field has not yet been resolved.
9161      *  r1: BBBB field ref
9162      */
9163 .LOP_SPUT_SHORT_resolve:
9164     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9165     EXPORT_PC()                         @ resolve() could throw, so export now
9166     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9167     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9168     cmp     r0, #0                      @ success?
9169     bne     .LOP_SPUT_SHORT_finish          @ yes, finish
9170     b       common_exceptionThrown      @ no, handle exception
9171
9172
9173 /* continuation for OP_INVOKE_VIRTUAL */
9174
9175     /*
9176      * At this point:
9177      *  r0 = resolved base method
9178      *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
9179      */
9180 .LOP_INVOKE_VIRTUAL_continue:
9181     GET_VREG(r1, r10)                   @ r1<- "this" ptr
9182     ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
9183     cmp     r1, #0                      @ is "this" null?
9184     beq     common_errNullObject        @ null "this", throw exception
9185     ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
9186     ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
9187     ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
9188     bl      common_invokeMethodNoRange @ continue on
9189
9190
9191 /* continuation for OP_INVOKE_SUPER */
9192
9193     /*
9194      * At this point:
9195      *  r0 = resolved base method
9196      *  r9 = method->clazz
9197      */
9198 .LOP_INVOKE_SUPER_continue:
9199     ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
9200     ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
9201     ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
9202     EXPORT_PC()                         @ must export for invoke
9203     cmp     r2, r3                      @ compare (methodIndex, vtableCount)
9204     bcs     .LOP_INVOKE_SUPER_nsm             @ method not present in superclass
9205     ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
9206     ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
9207     bl      common_invokeMethodNoRange @ continue on
9208
9209 .LOP_INVOKE_SUPER_resolve:
9210     mov     r0, r9                      @ r0<- method->clazz
9211     mov     r2, #METHOD_VIRTUAL         @ resolver method type
9212     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
9213     cmp     r0, #0                      @ got null?
9214     bne     .LOP_INVOKE_SUPER_continue        @ no, continue
9215     b       common_exceptionThrown      @ yes, handle exception
9216
9217     /*
9218      * Throw a NoSuchMethodError with the method name as the message.
9219      *  r0 = resolved base method
9220      */
9221 .LOP_INVOKE_SUPER_nsm:
9222     ldr     r1, [r0, #offMethod_name]   @ r1<- method name
9223     b       common_errNoSuchMethod
9224
9225
9226 /* continuation for OP_INVOKE_DIRECT */
9227
9228     /*
9229      * On entry:
9230      *  r1 = reference (BBBB or CCCC)
9231      *  r10 = "this" register
9232      */
9233 .LOP_INVOKE_DIRECT_resolve:
9234     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
9235     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
9236     mov     r2, #METHOD_DIRECT          @ resolver method type
9237     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
9238     cmp     r0, #0                      @ got null?
9239     GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
9240     bne     .LOP_INVOKE_DIRECT_finish          @ no, continue
9241     b       common_exceptionThrown      @ yes, handle exception
9242
9243
9244 /* continuation for OP_INVOKE_VIRTUAL_RANGE */
9245
9246     /*
9247      * At this point:
9248      *  r0 = resolved base method
9249      *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
9250      */
9251 .LOP_INVOKE_VIRTUAL_RANGE_continue:
9252     GET_VREG(r1, r10)                   @ r1<- "this" ptr
9253     ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
9254     cmp     r1, #0                      @ is "this" null?
9255     beq     common_errNullObject        @ null "this", throw exception
9256     ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
9257     ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
9258     ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
9259     bl      common_invokeMethodRange @ continue on
9260
9261
9262 /* continuation for OP_INVOKE_SUPER_RANGE */
9263
9264     /*
9265      * At this point:
9266      *  r0 = resolved base method
9267      *  r9 = method->clazz
9268      */
9269 .LOP_INVOKE_SUPER_RANGE_continue:
9270     ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
9271     ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
9272     ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
9273     EXPORT_PC()                         @ must export for invoke
9274     cmp     r2, r3                      @ compare (methodIndex, vtableCount)
9275     bcs     .LOP_INVOKE_SUPER_RANGE_nsm             @ method not present in superclass
9276     ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
9277     ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
9278     bl      common_invokeMethodRange @ continue on
9279
9280 .LOP_INVOKE_SUPER_RANGE_resolve:
9281     mov     r0, r9                      @ r0<- method->clazz
9282     mov     r2, #METHOD_VIRTUAL         @ resolver method type
9283     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
9284     cmp     r0, #0                      @ got null?
9285     bne     .LOP_INVOKE_SUPER_RANGE_continue        @ no, continue
9286     b       common_exceptionThrown      @ yes, handle exception
9287
9288     /*
9289      * Throw a NoSuchMethodError with the method name as the message.
9290      *  r0 = resolved base method
9291      */
9292 .LOP_INVOKE_SUPER_RANGE_nsm:
9293     ldr     r1, [r0, #offMethod_name]   @ r1<- method name
9294     b       common_errNoSuchMethod
9295
9296
9297 /* continuation for OP_INVOKE_DIRECT_RANGE */
9298
9299     /*
9300      * On entry:
9301      *  r1 = reference (BBBB or CCCC)
9302      *  r10 = "this" register
9303      */
9304 .LOP_INVOKE_DIRECT_RANGE_resolve:
9305     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
9306     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
9307     mov     r2, #METHOD_DIRECT          @ resolver method type
9308     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
9309     cmp     r0, #0                      @ got null?
9310     GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
9311     bne     .LOP_INVOKE_DIRECT_RANGE_finish          @ no, continue
9312     b       common_exceptionThrown      @ yes, handle exception
9313
9314
9315 /* continuation for OP_FLOAT_TO_LONG */
9316 /*
9317  * Convert the float in r0 to a long in r0/r1.
9318  *
9319  * We have to clip values to long min/max per the specification.  The
9320  * expected common case is a "reasonable" value that converts directly
9321  * to modest integer.  The EABI convert function isn't doing this for us.
9322  */
9323 f2l_doconv:
9324     stmfd   sp!, {r4, lr}
9325     mov     r1, #0x5f000000             @ (float)maxlong
9326     mov     r4, r0
9327     bl      __aeabi_fcmpge              @ is arg >= maxlong?
9328     cmp     r0, #0                      @ nonzero == yes
9329     mvnne   r0, #0                      @ return maxlong (7fffffff)
9330     mvnne   r1, #0x80000000
9331     ldmnefd sp!, {r4, pc}
9332
9333     mov     r0, r4                      @ recover arg
9334     mov     r1, #0xdf000000             @ (float)minlong
9335     bl      __aeabi_fcmple              @ is arg <= minlong?
9336     cmp     r0, #0                      @ nonzero == yes
9337     movne   r0, #0                      @ return minlong (80000000)
9338     movne   r1, #0x80000000
9339     ldmnefd sp!, {r4, pc}
9340
9341     mov     r0, r4                      @ recover arg
9342     mov     r1, r4
9343     bl      __aeabi_fcmpeq              @ is arg == self?
9344     cmp     r0, #0                      @ zero == no
9345     moveq   r1, #0                      @ return zero for NaN
9346     ldmeqfd sp!, {r4, pc}
9347
9348     mov     r0, r4                      @ recover arg
9349     bl      __aeabi_f2lz                @ convert float to long
9350     ldmfd   sp!, {r4, pc}
9351
9352
9353 /* continuation for OP_DOUBLE_TO_LONG */
9354 /*
9355  * Convert the double in r0/r1 to a long in r0/r1.
9356  *
9357  * We have to clip values to long min/max per the specification.  The
9358  * expected common case is a "reasonable" value that converts directly
9359  * to modest integer.  The EABI convert function isn't doing this for us.
9360  */
9361 d2l_doconv:
9362     stmfd   sp!, {r4, r5, lr}           @ save regs
9363     mov     r3, #0x43000000             @ maxlong, as a double (high word)
9364     add     r3, #0x00e00000             @  0x43e00000
9365     mov     r2, #0                      @ maxlong, as a double (low word)
9366     sub     sp, sp, #4                  @ align for EABI
9367     mov     r4, r0                      @ save a copy of r0
9368     mov     r5, r1                      @  and r1
9369     bl      __aeabi_dcmpge              @ is arg >= maxlong?
9370     cmp     r0, #0                      @ nonzero == yes
9371     mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
9372     mvnne   r1, #0x80000000
9373     bne     1f
9374
9375     mov     r0, r4                      @ recover arg
9376     mov     r1, r5
9377     mov     r3, #0xc3000000             @ minlong, as a double (high word)
9378     add     r3, #0x00e00000             @  0xc3e00000
9379     mov     r2, #0                      @ minlong, as a double (low word)
9380     bl      __aeabi_dcmple              @ is arg <= minlong?
9381     cmp     r0, #0                      @ nonzero == yes
9382     movne   r0, #0                      @ return minlong (8000000000000000)
9383     movne   r1, #0x80000000
9384     bne     1f
9385
9386     mov     r0, r4                      @ recover arg
9387     mov     r1, r5
9388     mov     r2, r4                      @ compare against self
9389     mov     r3, r5
9390     bl      __aeabi_dcmpeq              @ is arg == self?
9391     cmp     r0, #0                      @ zero == no
9392     moveq   r1, #0                      @ return zero for NaN
9393     beq     1f
9394
9395     mov     r0, r4                      @ recover arg
9396     mov     r1, r5
9397     bl      __aeabi_d2lz                @ convert double to long
9398
9399 1:
9400     add     sp, sp, #4
9401     ldmfd   sp!, {r4, r5, pc}
9402
9403
9404 /* continuation for OP_MUL_LONG */
9405
9406 .LOP_MUL_LONG_finish:
9407     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9408     stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
9409     GOTO_OPCODE(ip)                     @ jump to next instruction
9410
9411
9412 /* continuation for OP_SHL_LONG */
9413
9414 .LOP_SHL_LONG_finish:
9415     mov     r0, r0, asl r2              @  r0<- r0 << r2
9416     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9417     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9418     GOTO_OPCODE(ip)                     @ jump to next instruction
9419
9420
9421 /* continuation for OP_SHR_LONG */
9422
9423 .LOP_SHR_LONG_finish:
9424     mov     r1, r1, asr r2              @  r1<- r1 >> r2
9425     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9426     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9427     GOTO_OPCODE(ip)                     @ jump to next instruction
9428
9429
9430 /* continuation for OP_USHR_LONG */
9431
9432 .LOP_USHR_LONG_finish:
9433     mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
9434     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9435     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9436     GOTO_OPCODE(ip)                     @ jump to next instruction
9437
9438
9439 /* continuation for OP_SHL_LONG_2ADDR */
9440
9441 .LOP_SHL_LONG_2ADDR_finish:
9442     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9443     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9444     GOTO_OPCODE(ip)                     @ jump to next instruction
9445
9446
9447 /* continuation for OP_SHR_LONG_2ADDR */
9448
9449 .LOP_SHR_LONG_2ADDR_finish:
9450     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9451     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9452     GOTO_OPCODE(ip)                     @ jump to next instruction
9453
9454
9455 /* continuation for OP_USHR_LONG_2ADDR */
9456
9457 .LOP_USHR_LONG_2ADDR_finish:
9458     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9459     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9460     GOTO_OPCODE(ip)                     @ jump to next instruction
9461
9462
9463 /* continuation for OP_EXECUTE_INLINE */
9464
9465     /*
9466      * Extract args, call function.
9467      *  r0 = #of args (0-4)
9468      *  r10 = call index
9469      *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
9470      *
9471      * Other ideas:
9472      * - Use a jump table from the main piece to jump directly into the
9473      *   AND/LDR pairs.  Costs a data load, saves a branch.
9474      * - Have five separate pieces that do the loading, so we can work the
9475      *   interleave a little better.  Increases code size.
9476      */
9477 .LOP_EXECUTE_INLINE_continue:
9478     rsb     r0, r0, #4                  @ r0<- 4-r0
9479     FETCH(r9, 2)                        @ r9<- FEDC
9480     add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
9481     bl      common_abort                @ (skipped due to ARM prefetch)
9482 4:  and     ip, r9, #0xf000             @ isolate F
9483     ldr     r3, [rFP, ip, lsr #10]      @ r3<- vF (shift right 12, left 2)
9484 3:  and     ip, r9, #0x0f00             @ isolate E
9485     ldr     r2, [rFP, ip, lsr #6]       @ r2<- vE
9486 2:  and     ip, r9, #0x00f0             @ isolate D
9487     ldr     r1, [rFP, ip, lsr #2]       @ r1<- vD
9488 1:  and     ip, r9, #0x000f             @ isolate C
9489     ldr     r0, [rFP, ip, lsl #2]       @ r0<- vC
9490 0:
9491     ldr     r9, .LOP_EXECUTE_INLINE_table       @ table of InlineOperation
9492     LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
9493     @ (not reached)
9494
9495 .LOP_EXECUTE_INLINE_table:
9496     .word   gDvmInlineOpsTable
9497
9498
9499 /* continuation for OP_EXECUTE_INLINE_RANGE */
9500
9501     /*
9502      * Extract args, call function.
9503      *  r0 = #of args (0-4)
9504      *  r10 = call index
9505      *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
9506      */
9507 .LOP_EXECUTE_INLINE_RANGE_continue:
9508     rsb     r0, r0, #4                  @ r0<- 4-r0
9509     FETCH(r9, 2)                        @ r9<- CCCC
9510     add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
9511     bl      common_abort                @ (skipped due to ARM prefetch)
9512 4:  add     ip, r9, #3                  @ base+3
9513     GET_VREG(r3, ip)                    @ r3<- vBase[3]
9514 3:  add     ip, r9, #2                  @ base+2
9515     GET_VREG(r2, ip)                    @ r2<- vBase[2]
9516 2:  add     ip, r9, #1                  @ base+1
9517     GET_VREG(r1, ip)                    @ r1<- vBase[1]
9518 1:  add     ip, r9, #0                  @ (nop)
9519     GET_VREG(r0, ip)                    @ r0<- vBase[0]
9520 0:
9521     ldr     r9, .LOP_EXECUTE_INLINE_RANGE_table       @ table of InlineOperation
9522     LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
9523     @ (not reached)
9524
9525 .LOP_EXECUTE_INLINE_RANGE_table:
9526     .word   gDvmInlineOpsTable
9527
9528
9529     .size   dvmAsmSisterStart, .-dvmAsmSisterStart
9530     .global dvmAsmSisterEnd
9531 dvmAsmSisterEnd:
9532
9533 /* File: armv5te/footer.S */
9534
9535 /*
9536  * ===========================================================================
9537  *  Common subroutines and data
9538  * ===========================================================================
9539  */
9540
9541
9542
9543     .text
9544     .align  2
9545
9546 #if defined(WITH_JIT)
9547 #if defined(WITH_SELF_VERIFICATION)
9548     .global dvmJitToInterpPunt
9549 dvmJitToInterpPunt:
9550     mov    r2,#kSVSPunt                 @ r2<- interpreter entry point
9551     b      dvmJitSelfVerificationEnd    @ doesn't return
9552
9553     .global dvmJitToInterpSingleStep
9554 dvmJitToInterpSingleStep:
9555     mov    r2,#kSVSSingleStep           @ r2<- interpreter entry point
9556     b      dvmJitSelfVerificationEnd    @ doesn't return
9557
9558     .global dvmJitToTraceSelect
9559 dvmJitToTraceSelect:
9560     ldr    r0,[lr, #-1]                 @ pass our target PC
9561     mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
9562     b      dvmJitSelfVerificationEnd    @ doesn't return
9563
9564     .global dvmJitToBackwardBranch
9565 dvmJitToBackwardBranch:
9566     ldr    r0,[lr, #-1]                 @ pass our target PC
9567     mov    r2,#kSVSBackwardBranch       @ r2<- interpreter entry point
9568     b      dvmJitSelfVerificationEnd    @ doesn't return
9569
9570     .global dvmJitToInterpNormal
9571 dvmJitToInterpNormal:
9572     ldr    r0,[lr, #-1]                 @ pass our target PC
9573     mov    r2,#kSVSNormal               @ r2<- interpreter entry point
9574     b      dvmJitSelfVerificationEnd    @ doesn't return
9575
9576     .global dvmJitToInterpNoChain
9577 dvmJitToInterpNoChain:
9578     mov    r0,rPC                       @ pass our target PC
9579     mov    r2,#kSVSNoChain              @ r2<- interpreter entry point
9580     b      dvmJitSelfVerificationEnd    @ doesn't return
9581 #else
9582 /*
9583  * Return from the translation cache to the interpreter when the compiler is
9584  * having issues translating/executing a Dalvik instruction. We have to skip
9585  * the code cache lookup otherwise it is possible to indefinitely bouce
9586  * between the interpreter and the code cache if the instruction that fails
9587  * to be compiled happens to be at a trace start.
9588  */
9589     .global dvmJitToInterpPunt
9590 dvmJitToInterpPunt:
9591     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9592     mov    rPC, r0
9593 #ifdef EXIT_STATS
9594     mov    r0,lr
9595     bl     dvmBumpPunt;
9596 #endif
9597     EXPORT_PC()
9598     mov    r0, #0
9599     str    r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9600     adrl   rIBASE, dvmAsmInstructionStart
9601     FETCH_INST()
9602     GET_INST_OPCODE(ip)
9603     GOTO_OPCODE(ip)
9604
9605 /*
9606  * Return to the interpreter to handle a single instruction.
9607  * On entry:
9608  *    r0 <= PC
9609  *    r1 <= PC of resume instruction
9610  *    lr <= resume point in translation
9611  */
9612     .global dvmJitToInterpSingleStep
9613 dvmJitToInterpSingleStep:
9614     str    lr,[rGLUE,#offGlue_jitResume]
9615     str    r1,[rGLUE,#offGlue_jitResumePC]
9616     mov    r1,#kInterpEntryInstr
9617     @ enum is 4 byte in aapcs-EABI
9618     str    r1, [rGLUE, #offGlue_entryPoint]
9619     mov    rPC,r0
9620     EXPORT_PC()
9621
9622     adrl   rIBASE, dvmAsmInstructionStart
9623     mov    r2,#kJitSingleStep     @ Ask for single step and then revert
9624     str    r2,[rGLUE,#offGlue_jitState]
9625     mov    r1,#1                  @ set changeInterp to bail to debug interp
9626     b      common_gotoBail
9627
9628
9629 /*
9630  * Return from the translation cache and immediately request
9631  * a translation for the exit target.  Commonly used following
9632  * invokes.
9633  */
9634     .global dvmJitToTraceSelect
9635 dvmJitToTraceSelect:
9636     ldr    rPC,[lr, #-1]           @ get our target PC
9637     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9638     add    rINST,lr,#-5            @ save start of chain branch
9639     mov    r0,rPC
9640     bl     dvmJitGetCodeAddr       @ Is there a translation?
9641     str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9642     cmp    r0,#0
9643     beq    2f
9644     mov    r1,rINST
9645     bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9646     mov    r1, rPC                  @ arg1 of translation may need this
9647     mov    lr, #0                   @ in case target is HANDLER_INTERPRET
9648     cmp    r0,#0                    @ successful chain?
9649     bxne   r0                       @ continue native execution
9650     b      toInterpreter            @ didn't chain - resume with interpreter
9651
9652 /* No translation, so request one if profiling isn't disabled*/
9653 2:
9654     adrl   rIBASE, dvmAsmInstructionStart
9655     GET_JIT_PROF_TABLE(r0)
9656     FETCH_INST()
9657     cmp    r0, #0
9658     bne    common_selectTrace
9659     GET_INST_OPCODE(ip)
9660     GOTO_OPCODE(ip)
9661
9662 /*
9663  * Return from the translation cache to the interpreter.
9664  * The return was done with a BLX from thumb mode, and
9665  * the following 32-bit word contains the target rPC value.
9666  * Note that lr (r14) will have its low-order bit set to denote
9667  * its thumb-mode origin.
9668  *
9669  * We'll need to stash our lr origin away, recover the new
9670  * target and then check to see if there is a translation available
9671  * for our new target.  If so, we do a translation chain and
9672  * go back to native execution.  Otherwise, it's back to the
9673  * interpreter (after treating this entry as a potential
9674  * trace start).
9675  */
9676     .global dvmJitToInterpNormal
9677 dvmJitToInterpNormal:
9678     ldr    rPC,[lr, #-1]           @ get our target PC
9679     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9680     add    rINST,lr,#-5            @ save start of chain branch
9681 #ifdef EXIT_STATS
9682     bl     dvmBumpNormal
9683 #endif
9684     mov    r0,rPC
9685     bl     dvmJitGetCodeAddr        @ Is there a translation?
9686     str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9687     cmp    r0,#0
9688     beq    toInterpreter            @ go if not, otherwise do chain
9689     mov    r1,rINST
9690     bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9691     mov    r1, rPC                  @ arg1 of translation may need this
9692     mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9693     cmp    r0,#0                    @ successful chain?
9694     bxne   r0                       @ continue native execution
9695     b      toInterpreter            @ didn't chain - resume with interpreter
9696
9697 /*
9698  * Return from the translation cache to the interpreter to do method invocation.
9699  * Check if translation exists for the callee, but don't chain to it.
9700  */
9701     .global dvmJitToInterpNoChain
9702 dvmJitToInterpNoChain:
9703 #ifdef EXIT_STATS
9704     bl     dvmBumpNoChain
9705 #endif
9706     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9707     mov    r0,rPC
9708     bl     dvmJitGetCodeAddr        @ Is there a translation?
9709     str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9710     mov    r1, rPC                  @ arg1 of translation may need this
9711     mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9712     cmp    r0,#0
9713     bxne   r0                       @ continue native execution if so
9714 #endif
9715
9716 /*
9717  * No translation, restore interpreter regs and start interpreting.
9718  * rGLUE & rFP were preserved in the translated code, and rPC has
9719  * already been restored by the time we get here.  We'll need to set
9720  * up rIBASE & rINST, and load the address of the JitTable into r0.
9721  */
9722 toInterpreter:
9723     EXPORT_PC()
9724     adrl   rIBASE, dvmAsmInstructionStart
9725     FETCH_INST()
9726     GET_JIT_PROF_TABLE(r0)
9727     @ NOTE: intended fallthrough
9728 /*
9729  * Common code to update potential trace start counter, and initiate
9730  * a trace-build if appropriate.  On entry, rPC should point to the
9731  * next instruction to execute, and rINST should be already loaded with
9732  * the next opcode word, and r0 holds a pointer to the jit profile
9733  * table (pJitProfTable).
9734  */
9735 common_testUpdateProfile:
9736     cmp     r0,#0
9737     GET_INST_OPCODE(ip)
9738     GOTO_OPCODE_IFEQ(ip)       @ if not profiling, fallthrough otherwise */
9739
9740 common_updateProfile:
9741     eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
9742     lsl     r3,r3,#(32 - JIT_PROF_SIZE_LOG_2)          @ shift out excess bits
9743     ldrb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter
9744     GET_INST_OPCODE(ip)
9745     subs    r1,r1,#1           @ decrement counter
9746     strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it
9747     GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
9748
9749 /*
9750  * Here, we switch to the debug interpreter to request
9751  * trace selection.  First, though, check to see if there
9752  * is already a native translation in place (and, if so,
9753  * jump to it now).
9754  */
9755     GET_JIT_THRESHOLD(r1)
9756     ldr     r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
9757     strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter
9758     EXPORT_PC()
9759     mov     r0,rPC
9760     bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
9761     str     r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9762     mov     r1, rPC                     @ arg1 of translation may need this
9763     mov     lr, #0                      @  in case target is HANDLER_INTERPRET
9764     cmp     r0,#0
9765 #if !defined(WITH_SELF_VERIFICATION)
9766     bxne    r0                          @ jump to the translation
9767 #else
9768     beq     common_selectTrace
9769     /*
9770      * At this point, we have a target translation.  However, if
9771      * that translation is actually the interpret-only pseudo-translation
9772      * we want to treat it the same as no translation.
9773      */
9774     mov     r10, r0                      @ save target
9775     bl      dvmCompilerGetInterpretTemplate
9776     cmp     r0, r10                      @ special case?
9777     bne     dvmJitSelfVerificationStart  @ set up self verification
9778     GET_INST_OPCODE(ip)
9779     GOTO_OPCODE(ip)
9780     /* no return */
9781 #endif
9782
9783 common_selectTrace:
9784     mov     r2,#kJitTSelectRequest      @ ask for trace selection
9785     str     r2,[rGLUE,#offGlue_jitState]
9786     mov     r2,#kInterpEntryInstr       @ normal entry reason
9787     str     r2,[rGLUE,#offGlue_entryPoint]
9788     mov     r1,#1                       @ set changeInterp
9789     b       common_gotoBail
9790
9791 #if defined(WITH_SELF_VERIFICATION)
9792 /*
9793  * Save PC and registers to shadow memory for self verification mode
9794  * before jumping to native translation.
9795  * On entry, r10 contains the address of the target translation.
9796  */
9797 dvmJitSelfVerificationStart:
9798     mov     r0,rPC                      @ r0<- program counter
9799     mov     r1,rFP                      @ r1<- frame pointer
9800     mov     r2,rGLUE                    @ r2<- InterpState pointer
9801     mov     r3,r10                      @ r3<- target translation
9802     bl      dvmSelfVerificationSaveState @ save registers to shadow space
9803     ldr     rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
9804     add     rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
9805     bx      r10                         @ jump to the translation
9806
9807 /*
9808  * Restore PC, registers, and interpState to original values
9809  * before jumping back to the interpreter.
9810  */
9811 dvmJitSelfVerificationEnd:
9812     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9813     mov    r1, #0
9814     str    r1, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9815     mov    r1,rFP                        @ pass ending fp
9816     bl     dvmSelfVerificationRestoreState @ restore pc and fp values
9817     ldr    rPC,[r0,#offShadowSpace_startPC] @ restore PC
9818     ldr    rFP,[r0,#offShadowSpace_fp]   @ restore FP
9819     ldr    rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
9820     ldr    r1,[r0,#offShadowSpace_svState] @ get self verification state
9821     cmp    r1,#0                         @ check for punt condition
9822     beq    1f
9823     mov    r2,#kJitSelfVerification      @ ask for self verification
9824     str    r2,[rGLUE,#offGlue_jitState]
9825     mov    r2,#kInterpEntryInstr         @ normal entry reason
9826     str    r2,[rGLUE,#offGlue_entryPoint]
9827     mov    r1,#1                         @ set changeInterp
9828     b      common_gotoBail
9829
9830 1:                                       @ exit to interpreter without check
9831     EXPORT_PC()
9832     adrl   rIBASE, dvmAsmInstructionStart
9833     FETCH_INST()
9834     GET_INST_OPCODE(ip)
9835     GOTO_OPCODE(ip)
9836 #endif
9837
9838 #endif
9839
9840 /*
9841  * Common code when a backward branch is taken.
9842  *
9843  * On entry:
9844  *  r9 is PC adjustment *in bytes*
9845  */
9846 common_backwardBranch:
9847     mov     r0, #kInterpEntryInstr
9848     bl      common_periodicChecks
9849 #if defined(WITH_JIT)
9850     GET_JIT_PROF_TABLE(r0)
9851     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9852     cmp     r0,#0
9853     bne     common_updateProfile
9854     GET_INST_OPCODE(ip)
9855     GOTO_OPCODE(ip)
9856 #else
9857     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9858     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9859     GOTO_OPCODE(ip)                     @ jump to next instruction
9860 #endif
9861
9862
9863 /*
9864  * Need to see if the thread needs to be suspended or debugger/profiler
9865  * activity has begun.
9866  *
9867  * TODO: if JDWP isn't running, zero out pDebuggerActive pointer so we don't
9868  * have to do the second ldr.
9869  *
9870  * TODO: reduce this so we're just checking a single location.
9871  *
9872  * On entry:
9873  *  r0 is reentry type, e.g. kInterpEntryInstr
9874  *  r9 is trampoline PC adjustment *in bytes*
9875  */
9876 common_periodicChecks:
9877     ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
9878
9879     @ speculatively store r0 before it is clobbered by dvmCheckSuspendPending
9880     str     r0, [rGLUE, #offGlue_entryPoint]
9881
9882 #if defined(WITH_DEBUGGER)
9883     ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9884 #endif
9885 #if defined(WITH_PROFILER)
9886     ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9887 #endif
9888
9889     ldr     r3, [r3]                    @ r3<- suspendCount (int)
9890
9891 #if defined(WITH_DEBUGGER)
9892     ldrb    r1, [r1]                    @ r1<- debuggerActive (boolean)
9893 #endif
9894 #if defined (WITH_PROFILER)
9895     ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9896 #endif
9897
9898     cmp     r3, #0                      @ suspend pending?
9899     bne     2f                          @ yes, do full suspension check
9900
9901 #if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
9902 # if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
9903     orrs    r1, r1, r2                  @ r1<- r1 | r2
9904     cmp     r1, #0                      @ debugger attached or profiler started?
9905 # elif defined(WITH_DEBUGGER)
9906     cmp     r1, #0                      @ debugger attached?
9907 # elif defined(WITH_PROFILER)
9908     cmp     r2, #0                      @ profiler started?
9909 # endif
9910     bne     3f                          @ debugger/profiler, switch interp
9911 #endif
9912
9913     bx      lr                          @ nothing to do, return
9914
9915 2:  @ check suspend
9916 #if defined(WITH_JIT)
9917     /*
9918      * Refresh the Jit's cached copy of profile table pointer.  This pointer
9919      * doubles as the Jit's on/off switch.
9920      */
9921     ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ r10<-&gDvmJit.pJitProfTable
9922     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9923     ldr     r3, [r3] @ r10 <- pJitProfTable
9924     EXPORT_PC()                         @ need for precise GC
9925     str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch
9926 #else
9927     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9928     EXPORT_PC()                         @ need for precise GC
9929 #endif
9930     b       dvmCheckSuspendPending      @ suspend if necessary, then return
9931
9932 3:  @ debugger/profiler enabled, bail out
9933     add     rPC, rPC, r9                @ update rPC
9934     mov     r1, #1                      @ "want switch" = true
9935     b       common_gotoBail
9936
9937
9938 /*
9939  * The equivalent of "goto bail", this calls through the "bail handler".
9940  *
9941  * State registers will be saved to the "glue" area before bailing.
9942  *
9943  * On entry:
9944  *  r1 is "bool changeInterp", indicating if we want to switch to the
9945  *     other interpreter or just bail all the way out
9946  */
9947 common_gotoBail:
9948     SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9949     mov     r0, rGLUE                   @ r0<- glue ptr
9950     b       dvmMterpStdBail             @ call(glue, changeInterp)
9951
9952     @add     r1, r1, #1                  @ using (boolean+1)
9953     @add     r0, rGLUE, #offGlue_jmpBuf  @ r0<- &glue->jmpBuf
9954     @bl      _longjmp                    @ does not return
9955     @bl      common_abort
9956
9957
9958 /*
9959  * Common code for method invocation with range.
9960  *
9961  * On entry:
9962  *  r0 is "Method* methodToCall", the method we're trying to call
9963  */
9964 common_invokeMethodRange:
9965 .LinvokeNewRange:
9966     @ prepare to copy args to "outs" area of current frame
9967     movs    r2, rINST, lsr #8           @ r2<- AA (arg count) -- test for zero
9968     SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9969     beq     .LinvokeArgsDone            @ if no args, skip the rest
9970     FETCH(r1, 2)                        @ r1<- CCCC
9971
9972     @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
9973     @ (very few methods have > 10 args; could unroll for common cases)
9974     add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
9975     sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
9976     ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
9977 1:  ldr     r1, [r3], #4                @ val = *fp++
9978     subs    r2, r2, #1                  @ count--
9979     str     r1, [r10], #4               @ *outs++ = val
9980     bne     1b                          @ ...while count != 0
9981     ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
9982     b       .LinvokeArgsDone
9983
9984 /*
9985  * Common code for method invocation without range.
9986  *
9987  * On entry:
9988  *  r0 is "Method* methodToCall", the method we're trying to call
9989  */
9990 common_invokeMethodNoRange:
9991 .LinvokeNewNoRange:
9992     @ prepare to copy args to "outs" area of current frame
9993     movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
9994     SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9995     FETCH(r1, 2)                        @ r1<- GFED (load here to hide latency)
9996     ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
9997     ldrh    r3, [r0, #offMethod_outsSize]  @ r3<- methodToCall->outsSize
9998     beq     .LinvokeArgsDone
9999
10000     @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
10001 .LinvokeNonRange:
10002     rsb     r2, r2, #5                  @ r2<- 5-r2
10003     add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
10004     bl      common_abort                @ (skipped due to ARM prefetch)
10005 5:  and     ip, rINST, #0x0f00          @ isolate A
10006     ldr     r2, [rFP, ip, lsr #6]       @ r2<- vA (shift right 8, left 2)
10007     mov     r0, r0                      @ nop
10008     str     r2, [r10, #-4]!             @ *--outs = vA
10009 4:  and     ip, r1, #0xf000             @ isolate G
10010     ldr     r2, [rFP, ip, lsr #10]      @ r2<- vG (shift right 12, left 2)
10011     mov     r0, r0                      @ nop
10012     str     r2, [r10, #-4]!             @ *--outs = vG
10013 3:  and     ip, r1, #0x0f00             @ isolate F
10014     ldr     r2, [rFP, ip, lsr #6]       @ r2<- vF
10015     mov     r0, r0                      @ nop
10016     str     r2, [r10, #-4]!             @ *--outs = vF
10017 2:  and     ip, r1, #0x00f0             @ isolate E
10018     ldr     r2, [rFP, ip, lsr #2]       @ r2<- vE
10019     mov     r0, r0                      @ nop
10020     str     r2, [r10, #-4]!             @ *--outs = vE
10021 1:  and     ip, r1, #0x000f             @ isolate D
10022     ldr     r2, [rFP, ip, lsl #2]       @ r2<- vD
10023     mov     r0, r0                      @ nop
10024     str     r2, [r10, #-4]!             @ *--outs = vD
10025 0:  @ fall through to .LinvokeArgsDone
10026
10027 .LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
10028     ldr     r2, [r0, #offMethod_insns]  @ r2<- method->insns
10029     ldr     rINST, [r0, #offMethod_clazz]  @ rINST<- method->clazz
10030     @ find space for the new stack frame, check for overflow
10031     SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
10032     sub     r1, r1, r9, lsl #2          @ r1<- newFp (old savearea - regsSize)
10033     SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
10034 @    bl      common_dumpRegs
10035     ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
10036     sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
10037     cmp     r3, r9                      @ bottom < interpStackEnd?
10038     ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
10039     blt     .LstackOverflow             @ yes, this frame will overflow stack
10040
10041     @ set up newSaveArea
10042 #ifdef EASY_GDB
10043     SAVEAREA_FROM_FP(ip, rFP)           @ ip<- stack save area
10044     str     ip, [r10, #offStackSaveArea_prevSave]
10045 #endif
10046     str     rFP, [r10, #offStackSaveArea_prevFrame]
10047     str     rPC, [r10, #offStackSaveArea_savedPc]
10048 #if defined(WITH_JIT)
10049     mov     r9, #0
10050     str     r9, [r10, #offStackSaveArea_returnAddr]
10051 #endif
10052     str     r0, [r10, #offStackSaveArea_method]
10053     tst     r3, #ACC_NATIVE
10054     bne     .LinvokeNative
10055
10056     /*
10057     stmfd   sp!, {r0-r3}
10058     bl      common_printNewline
10059     mov     r0, rFP
10060     mov     r1, #0
10061     bl      dvmDumpFp
10062     ldmfd   sp!, {r0-r3}
10063     stmfd   sp!, {r0-r3}
10064     mov     r0, r1
10065     mov     r1, r10
10066     bl      dvmDumpFp
10067     bl      common_printNewline
10068     ldmfd   sp!, {r0-r3}
10069     */
10070
10071     ldrh    r9, [r2]                        @ r9 <- load INST from new PC
10072     ldr     r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
10073     mov     rPC, r2                         @ publish new rPC
10074     ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
10075
10076     @ Update "glue" values for the new method
10077     @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
10078     str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
10079     str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
10080 #if defined(WITH_JIT)
10081     GET_JIT_PROF_TABLE(r0)
10082     mov     rFP, r1                         @ fp = newFp
10083     GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
10084     mov     rINST, r9                       @ publish new rINST
10085     str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
10086     cmp     r0,#0
10087     bne     common_updateProfile
10088     GOTO_OPCODE(ip)                         @ jump to next instruction
10089 #else
10090     mov     rFP, r1                         @ fp = newFp
10091     GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
10092     mov     rINST, r9                       @ publish new rINST
10093     str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
10094     GOTO_OPCODE(ip)                         @ jump to next instruction
10095 #endif
10096
10097 .LinvokeNative:
10098     @ Prep for the native call
10099     @ r0=methodToCall, r1=newFp, r10=newSaveArea
10100     ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
10101     ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
10102     str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
10103     str     r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
10104     mov     r9, r3                      @ r9<- glue->self (preserve)
10105
10106     mov     r2, r0                      @ r2<- methodToCall
10107     mov     r0, r1                      @ r0<- newFp (points to args)
10108     add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
10109
10110 #ifdef ASSIST_DEBUGGER
10111     /* insert fake function header to help gdb find the stack frame */
10112     b       .Lskip
10113     .type   dalvik_mterp, %function
10114 dalvik_mterp:
10115     .fnstart
10116     MTERP_ENTRY1
10117     MTERP_ENTRY2
10118 .Lskip:
10119 #endif
10120
10121     @mov     lr, pc                      @ set return addr
10122     @ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
10123     LDR_PC_LR "[r2, #offMethod_nativeFunc]"
10124
10125 #if defined(WITH_JIT)
10126     ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status
10127 #endif
10128
10129     @ native return; r9=self, r10=newSaveArea
10130     @ equivalent to dvmPopJniLocals
10131     ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
10132     ldr     r1, [r9, #offThread_exception] @ check for exception
10133 #if defined(WITH_JIT)
10134     ldr     r3, [r3]                    @ r3 <- gDvmJit.pProfTable
10135 #endif
10136     str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
10137     cmp     r1, #0                      @ null?
10138     str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
10139 #if defined(WITH_JIT)
10140     str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch
10141 #endif
10142     bne     common_exceptionThrown      @ no, handle exception
10143
10144     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
10145     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10146     GOTO_OPCODE(ip)                     @ jump to next instruction
10147
10148 .LstackOverflow:    @ r0=methodToCall
10149     mov     r1, r0                      @ r1<- methodToCall
10150     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
10151     bl      dvmHandleStackOverflow
10152     b       common_exceptionThrown
10153 #ifdef ASSIST_DEBUGGER
10154     .fnend
10155 #endif
10156
10157
10158     /*
10159      * Common code for method invocation, calling through "glue code".
10160      *
10161      * TODO: now that we have range and non-range invoke handlers, this
10162      *       needs to be split into two.  Maybe just create entry points
10163      *       that set r9 and jump here?
10164      *
10165      * On entry:
10166      *  r0 is "Method* methodToCall", the method we're trying to call
10167      *  r9 is "bool methodCallRange", indicating if this is a /range variant
10168      */
10169      .if    0
10170 .LinvokeOld:
10171     sub     sp, sp, #8                  @ space for args + pad
10172     FETCH(ip, 2)                        @ ip<- FEDC or CCCC
10173     mov     r2, r0                      @ A2<- methodToCall
10174     mov     r0, rGLUE                   @ A0<- glue
10175     SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
10176     mov     r1, r9                      @ A1<- methodCallRange
10177     mov     r3, rINST, lsr #8           @ A3<- AA
10178     str     ip, [sp, #0]                @ A4<- ip
10179     bl      dvmMterp_invokeMethod       @ call the C invokeMethod
10180     add     sp, sp, #8                  @ remove arg area
10181     b       common_resumeAfterGlueCall  @ continue to next instruction
10182     .endif
10183
10184
10185
10186 /*
10187  * Common code for handling a return instruction.
10188  *
10189  * This does not return.
10190  */
10191 common_returnFromMethod:
10192 .LreturnNew:
10193     mov     r0, #kInterpEntryReturn
10194     mov     r9, #0
10195     bl      common_periodicChecks
10196
10197     SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
10198     ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
10199     ldr     r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
10200     ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
10201                                         @ r2<- method we're returning to
10202     ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
10203     cmp     r2, #0                      @ is this a break frame?
10204     ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
10205     mov     r1, #0                      @ "want switch" = false
10206     beq     common_gotoBail             @ break frame, bail out completely
10207
10208     PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
10209     str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
10210     ldr     r1, [r10, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
10211     str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
10212 #if defined(WITH_JIT)
10213     ldr     r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr
10214     GET_JIT_PROF_TABLE(r0)
10215     mov     rPC, r9                     @ publish new rPC
10216     str     r1, [rGLUE, #offGlue_methodClassDex]
10217     str     r10, [r3, #offThread_inJitCodeCache]  @ may return to JIT'ed land
10218     cmp     r10, #0                      @ caller is compiled code
10219     blxne   r10
10220     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10221     cmp     r0,#0
10222     bne     common_updateProfile
10223     GOTO_OPCODE(ip)                     @ jump to next instruction
10224 #else
10225     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10226     mov     rPC, r9                     @ publish new rPC
10227     str     r1, [rGLUE, #offGlue_methodClassDex]
10228     GOTO_OPCODE(ip)                     @ jump to next instruction
10229 #endif
10230
10231     /*
10232      * Return handling, calls through "glue code".
10233      */
10234      .if    0
10235 .LreturnOld:
10236     SAVE_PC_FP_TO_GLUE()                @ export state
10237     mov     r0, rGLUE                   @ arg to function
10238     bl      dvmMterp_returnFromMethod
10239     b       common_resumeAfterGlueCall
10240     .endif
10241
10242
10243 /*
10244  * Somebody has thrown an exception.  Handle it.
10245  *
10246  * If the exception processing code returns to us (instead of falling
10247  * out of the interpreter), continue with whatever the next instruction
10248  * now happens to be.
10249  *
10250  * This does not return.
10251  */
10252      .global dvmMterpCommonExceptionThrown
10253 dvmMterpCommonExceptionThrown:
10254 common_exceptionThrown:
10255 .LexceptionNew:
10256     mov     r0, #kInterpEntryThrow
10257     mov     r9, #0
10258     bl      common_periodicChecks
10259
10260 #if defined(WITH_JIT)
10261     mov     r2,#kJitTSelectAbort        @ abandon trace selection in progress
10262     str     r2,[rGLUE,#offGlue_jitState]
10263 #endif
10264
10265     ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
10266     ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
10267     mov     r1, r10                     @ r1<- self
10268     mov     r0, r9                      @ r0<- exception
10269     bl      dvmAddTrackedAlloc          @ don't let the exception be GCed
10270     mov     r3, #0                      @ r3<- NULL
10271     str     r3, [r10, #offThread_exception] @ self->exception = NULL
10272
10273     /* set up args and a local for "&fp" */
10274     /* (str sp, [sp, #-4]!  would be perfect here, but is discouraged) */
10275     str     rFP, [sp, #-4]!             @ *--sp = fp
10276     mov     ip, sp                      @ ip<- &fp
10277     mov     r3, #0                      @ r3<- false
10278     str     ip, [sp, #-4]!              @ *--sp = &fp
10279     ldr     r1, [rGLUE, #offGlue_method] @ r1<- glue->method
10280     mov     r0, r10                     @ r0<- self
10281     ldr     r1, [r1, #offMethod_insns]  @ r1<- method->insns
10282     mov     r2, r9                      @ r2<- exception
10283     sub     r1, rPC, r1                 @ r1<- pc - method->insns
10284     mov     r1, r1, asr #1              @ r1<- offset in code units
10285
10286     /* call, r0 gets catchRelPc (a code-unit offset) */
10287     bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
10288
10289     /* fix earlier stack overflow if necessary; may trash rFP */
10290     ldrb    r1, [r10, #offThread_stackOverflowed]
10291     cmp     r1, #0                      @ did we overflow earlier?
10292     beq     1f                          @ no, skip ahead
10293     mov     rFP, r0                     @ save relPc result in rFP
10294     mov     r0, r10                     @ r0<- self
10295     mov     r1, r9                      @ r1<- exception
10296     bl      dvmCleanupStackOverflow     @ call(self)
10297     mov     r0, rFP                     @ restore result
10298 1:
10299
10300     /* update frame pointer and check result from dvmFindCatchBlock */
10301     ldr     rFP, [sp, #4]               @ retrieve the updated rFP
10302     cmp     r0, #0                      @ is catchRelPc < 0?
10303     add     sp, sp, #8                  @ restore stack
10304     bmi     .LnotCaughtLocally
10305
10306     /* adjust locals to match self->curFrame and updated PC */
10307     SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
10308     ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
10309     str     r1, [rGLUE, #offGlue_method]    @ glue->method = new method
10310     ldr     r2, [r1, #offMethod_clazz]      @ r2<- method->clazz
10311     ldr     r3, [r1, #offMethod_insns]      @ r3<- method->insns
10312     ldr     r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
10313     add     rPC, r3, r0, asl #1             @ rPC<- method->insns + catchRelPc
10314     str     r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
10315
10316     /* release the tracked alloc on the exception */
10317     mov     r0, r9                      @ r0<- exception
10318     mov     r1, r10                     @ r1<- self
10319     bl      dvmReleaseTrackedAlloc      @ release the exception
10320
10321     /* restore the exception if the handler wants it */
10322     FETCH_INST()                        @ load rINST from rPC
10323     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10324     cmp     ip, #OP_MOVE_EXCEPTION      @ is it "move-exception"?
10325     streq   r9, [r10, #offThread_exception] @ yes, restore the exception
10326     GOTO_OPCODE(ip)                     @ jump to next instruction
10327
10328 .LnotCaughtLocally: @ r9=exception, r10=self
10329     /* fix stack overflow if necessary */
10330     ldrb    r1, [r10, #offThread_stackOverflowed]
10331     cmp     r1, #0                      @ did we overflow earlier?
10332     movne   r0, r10                     @ if yes: r0<- self
10333     movne   r1, r9                      @ if yes: r1<- exception
10334     blne    dvmCleanupStackOverflow     @ if yes: call(self)
10335
10336     @ may want to show "not caught locally" debug messages here
10337 #if DVM_SHOW_EXCEPTION >= 2
10338     /* call __android_log_print(prio, tag, format, ...) */
10339     /* "Exception %s from %s:%d not caught locally" */
10340     @ dvmLineNumFromPC(method, pc - method->insns)
10341     ldr     r0, [rGLUE, #offGlue_method]
10342     ldr     r1, [r0, #offMethod_insns]
10343     sub     r1, rPC, r1
10344     asr     r1, r1, #1
10345     bl      dvmLineNumFromPC
10346     str     r0, [sp, #-4]!
10347     @ dvmGetMethodSourceFile(method)
10348     ldr     r0, [rGLUE, #offGlue_method]
10349     bl      dvmGetMethodSourceFile
10350     str     r0, [sp, #-4]!
10351     @ exception->clazz->descriptor
10352     ldr     r3, [r9, #offObject_clazz]
10353     ldr     r3, [r3, #offClassObject_descriptor]
10354     @
10355     ldr     r2, strExceptionNotCaughtLocally
10356     ldr     r1, strLogTag
10357     mov     r0, #3                      @ LOG_DEBUG
10358     bl      __android_log_print
10359 #endif
10360     str     r9, [r10, #offThread_exception] @ restore exception
10361     mov     r0, r9                      @ r0<- exception
10362     mov     r1, r10                     @ r1<- self
10363     bl      dvmReleaseTrackedAlloc      @ release the exception
10364     mov     r1, #0                      @ "want switch" = false
10365     b       common_gotoBail             @ bail out
10366
10367
10368     /*
10369      * Exception handling, calls through "glue code".
10370      */
10371     .if     0
10372 .LexceptionOld:
10373     SAVE_PC_FP_TO_GLUE()                @ export state
10374     mov     r0, rGLUE                   @ arg to function
10375     bl      dvmMterp_exceptionThrown
10376     b       common_resumeAfterGlueCall
10377     .endif
10378
10379
10380 /*
10381  * After returning from a "glued" function, pull out the updated
10382  * values and start executing at the next instruction.
10383  */
10384 common_resumeAfterGlueCall:
10385     LOAD_PC_FP_FROM_GLUE()              @ pull rPC and rFP out of glue
10386     FETCH_INST()                        @ load rINST from rPC
10387     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10388     GOTO_OPCODE(ip)                     @ jump to next instruction
10389
10390 /*
10391  * Invalid array index.
10392  */
10393 common_errArrayIndex:
10394     EXPORT_PC()
10395     ldr     r0, strArrayIndexException
10396     mov     r1, #0
10397     bl      dvmThrowException
10398     b       common_exceptionThrown
10399
10400 /*
10401  * Invalid array value.
10402  */
10403 common_errArrayStore:
10404     EXPORT_PC()
10405     ldr     r0, strArrayStoreException
10406     mov     r1, #0
10407     bl      dvmThrowException
10408     b       common_exceptionThrown
10409
10410 /*
10411  * Integer divide or mod by zero.
10412  */
10413 common_errDivideByZero:
10414     EXPORT_PC()
10415     ldr     r0, strArithmeticException
10416     ldr     r1, strDivideByZero
10417     bl      dvmThrowException
10418     b       common_exceptionThrown
10419
10420 /*
10421  * Attempt to allocate an array with a negative size.
10422  */
10423 common_errNegativeArraySize:
10424     EXPORT_PC()
10425     ldr     r0, strNegativeArraySizeException
10426     mov     r1, #0
10427     bl      dvmThrowException
10428     b       common_exceptionThrown
10429
10430 /*
10431  * Invocation of a non-existent method.
10432  */
10433 common_errNoSuchMethod:
10434     EXPORT_PC()
10435     ldr     r0, strNoSuchMethodError
10436     mov     r1, #0
10437     bl      dvmThrowException
10438     b       common_exceptionThrown
10439
10440 /*
10441  * We encountered a null object when we weren't expecting one.  We
10442  * export the PC, throw a NullPointerException, and goto the exception
10443  * processing code.
10444  */
10445 common_errNullObject:
10446     EXPORT_PC()
10447     ldr     r0, strNullPointerException
10448     mov     r1, #0
10449     bl      dvmThrowException
10450     b       common_exceptionThrown
10451
10452 /*
10453  * For debugging, cause an immediate fault.  The source address will
10454  * be in lr (use a bl instruction to jump here).
10455  */
10456 common_abort:
10457     ldr     pc, .LdeadFood
10458 .LdeadFood:
10459     .word   0xdeadf00d
10460
10461 /*
10462  * Spit out a "we were here", preserving all registers.  (The attempt
10463  * to save ip won't work, but we need to save an even number of
10464  * registers for EABI 64-bit stack alignment.)
10465  */
10466     .macro  SQUEAK num
10467 common_squeak\num:
10468     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10469     ldr     r0, strSqueak
10470     mov     r1, #\num
10471     bl      printf
10472     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10473     bx      lr
10474     .endm
10475
10476     SQUEAK  0
10477     SQUEAK  1
10478     SQUEAK  2
10479     SQUEAK  3
10480     SQUEAK  4
10481     SQUEAK  5
10482
10483 /*
10484  * Spit out the number in r0, preserving registers.
10485  */
10486 common_printNum:
10487     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10488     mov     r1, r0
10489     ldr     r0, strSqueak
10490     bl      printf
10491     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10492     bx      lr
10493
10494 /*
10495  * Print a newline, preserving registers.
10496  */
10497 common_printNewline:
10498     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10499     ldr     r0, strNewline
10500     bl      printf
10501     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10502     bx      lr
10503
10504     /*
10505      * Print the 32-bit quantity in r0 as a hex value, preserving registers.
10506      */
10507 common_printHex:
10508     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10509     mov     r1, r0
10510     ldr     r0, strPrintHex
10511     bl      printf
10512     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10513     bx      lr
10514
10515 /*
10516  * Print the 64-bit quantity in r0-r1, preserving registers.
10517  */
10518 common_printLong:
10519     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10520     mov     r3, r1
10521     mov     r2, r0
10522     ldr     r0, strPrintLong
10523     bl      printf
10524     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10525     bx      lr
10526
10527 /*
10528  * Print full method info.  Pass the Method* in r0.  Preserves regs.
10529  */
10530 common_printMethod:
10531     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10532     bl      dvmMterpPrintMethod
10533     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10534     bx      lr
10535
10536 /*
10537  * Call a C helper function that dumps regs and possibly some
10538  * additional info.  Requires the C function to be compiled in.
10539  */
10540     .if     0
10541 common_dumpRegs:
10542     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10543     bl      dvmMterpDumpArmRegs
10544     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10545     bx      lr
10546     .endif
10547
10548 #if 0
10549 /*
10550  * Experiment on VFP mode.
10551  *
10552  * uint32_t setFPSCR(uint32_t val, uint32_t mask)
10553  *
10554  * Updates the bits specified by "mask", setting them to the values in "val".
10555  */
10556 setFPSCR:
10557     and     r0, r0, r1                  @ make sure no stray bits are set
10558     fmrx    r2, fpscr                   @ get VFP reg
10559     mvn     r1, r1                      @ bit-invert mask
10560     and     r2, r2, r1                  @ clear masked bits
10561     orr     r2, r2, r0                  @ set specified bits
10562     fmxr    fpscr, r2                   @ set VFP reg
10563     mov     r0, r2                      @ return new value
10564     bx      lr
10565
10566     .align  2
10567     .global dvmConfigureFP
10568     .type   dvmConfigureFP, %function
10569 dvmConfigureFP:
10570     stmfd   sp!, {ip, lr}
10571     /* 0x03000000 sets DN/FZ */
10572     /* 0x00009f00 clears the six exception enable flags */
10573     bl      common_squeak0
10574     mov     r0, #0x03000000             @ r0<- 0x03000000
10575     add     r1, r0, #0x9f00             @ r1<- 0x03009f00
10576     bl      setFPSCR
10577     ldmfd   sp!, {ip, pc}
10578 #endif
10579
10580
10581 /*
10582  * String references, must be close to the code that uses them.
10583  */
10584     .align  2
10585 strArithmeticException:
10586     .word   .LstrArithmeticException
10587 strArrayIndexException:
10588     .word   .LstrArrayIndexException
10589 strArrayStoreException:
10590     .word   .LstrArrayStoreException
10591 strDivideByZero:
10592     .word   .LstrDivideByZero
10593 strNegativeArraySizeException:
10594     .word   .LstrNegativeArraySizeException
10595 strNoSuchMethodError:
10596     .word   .LstrNoSuchMethodError
10597 strNullPointerException:
10598     .word   .LstrNullPointerException
10599
10600 strLogTag:
10601     .word   .LstrLogTag
10602 strExceptionNotCaughtLocally:
10603     .word   .LstrExceptionNotCaughtLocally
10604
10605 strNewline:
10606     .word   .LstrNewline
10607 strSqueak:
10608     .word   .LstrSqueak
10609 strPrintHex:
10610     .word   .LstrPrintHex
10611 strPrintLong:
10612     .word   .LstrPrintLong
10613
10614 /*
10615  * Zero-terminated ASCII string data.
10616  *
10617  * On ARM we have two choices: do like gcc does, and LDR from a .word
10618  * with the address, or use an ADR pseudo-op to get the address
10619  * directly.  ADR saves 4 bytes and an indirection, but it's using a
10620  * PC-relative addressing mode and hence has a limited range, which
10621  * makes it not work well with mergeable string sections.
10622  */
10623     .section .rodata.str1.4,"aMS",%progbits,1
10624
10625 .LstrBadEntryPoint:
10626     .asciz  "Bad entry point %d\n"
10627 .LstrArithmeticException:
10628     .asciz  "Ljava/lang/ArithmeticException;"
10629 .LstrArrayIndexException:
10630     .asciz  "Ljava/lang/ArrayIndexOutOfBoundsException;"
10631 .LstrArrayStoreException:
10632     .asciz  "Ljava/lang/ArrayStoreException;"
10633 .LstrClassCastException:
10634     .asciz  "Ljava/lang/ClassCastException;"
10635 .LstrDivideByZero:
10636     .asciz  "divide by zero"
10637 .LstrFilledNewArrayNotImpl:
10638     .asciz  "filled-new-array only implemented for objects and 'int'"
10639 .LstrInternalError:
10640     .asciz  "Ljava/lang/InternalError;"
10641 .LstrInstantiationError:
10642     .asciz  "Ljava/lang/InstantiationError;"
10643 .LstrNegativeArraySizeException:
10644     .asciz  "Ljava/lang/NegativeArraySizeException;"
10645 .LstrNoSuchMethodError:
10646     .asciz  "Ljava/lang/NoSuchMethodError;"
10647 .LstrNullPointerException:
10648     .asciz  "Ljava/lang/NullPointerException;"
10649
10650 .LstrLogTag:
10651     .asciz  "mterp"
10652 .LstrExceptionNotCaughtLocally:
10653     .asciz  "Exception %s from %s:%d not caught locally\n"
10654
10655 .LstrNewline:
10656     .asciz  "\n"
10657 .LstrSqueak:
10658     .asciz  "<%d>"
10659 .LstrPrintHex:
10660     .asciz  "<0x%x>"
10661 .LstrPrintLong:
10662     .asciz  "<%lld>"
10663
10664