OSDN Git Service

AI 144925: Rename armv4 to armv4t, which is what it really is.
[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.
44
45 Stack is "full descending".  Only the arguments that don't fit in the first 4
46 registers are placed on the stack.  "sp" points at the first stacked argument
47 (i.e. the 5th arg).
48
49 VFP: single-precision results in s0, double-precision results in d0.
50
51 In the EABI, "sp" must be 64-bit aligned on entry to a function, and any
52 64-bit quantities (long long, double) must be 64-bit aligned.
53 */
54
55 /*
56 Mterp and ARM notes:
57
58 The following registers have fixed assignments:
59
60   reg nick      purpose
61   r4  rPC       interpreted program counter, used for fetching instructions
62   r5  rFP       interpreted frame pointer, used for accessing locals and args
63   r6  rGLUE     MterpGlue pointer
64   r7  rIBASE    interpreted instruction base pointer, used for computed goto
65   r8  rINST     first 16-bit code unit of current instruction
66
67 Macros are provided for common operations.  Each macro MUST emit only
68 one instruction to make instruction-counting easier.  They MUST NOT alter
69 unspecified registers or condition codes.
70 */
71
72 /* single-purpose registers, given names for clarity */
73 #define rPC     r4
74 #define rFP     r5
75 #define rGLUE   r6
76 #define rIBASE  r7
77 #define rINST   r8
78
79 /* save/restore the PC and/or FP from the glue struct */
80 #define LOAD_PC_FROM_GLUE()     ldr     rPC, [rGLUE, #offGlue_pc]
81 #define SAVE_PC_TO_GLUE()       str     rPC, [rGLUE, #offGlue_pc]
82 #define LOAD_FP_FROM_GLUE()     ldr     rFP, [rGLUE, #offGlue_fp]
83 #define SAVE_FP_TO_GLUE()       str     rFP, [rGLUE, #offGlue_fp]
84 #define LOAD_PC_FP_FROM_GLUE()  ldmia   rGLUE, {rPC, rFP}
85 #define SAVE_PC_FP_TO_GLUE()    stmia   rGLUE, {rPC, rFP}
86
87 /*
88  * "export" the PC to the stack frame, f/b/o future exception objects.  Must
89  * be done *before* something calls dvmThrowException.
90  *
91  * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e.
92  * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc)
93  *
94  * It's okay to do this more than once.
95  */
96 #define EXPORT_PC() \
97     str     rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)]
98
99 /*
100  * Given a frame pointer, find the stack save area.
101  *
102  * In C this is "((StackSaveArea*)(_fp) -1)".
103  */
104 #define SAVEAREA_FROM_FP(_reg, _fpreg) \
105     sub     _reg, _fpreg, #sizeofStackSaveArea
106
107 /*
108  * Fetch the next instruction from rPC into rINST.  Does not advance rPC.
109  */
110 #define FETCH_INST()            ldrh    rINST, [rPC]
111
112 /*
113  * Fetch the next instruction from the specified offset.  Advances rPC
114  * to point to the next instruction.  "_count" is in 16-bit code units.
115  *
116  * Because of the limited size of immediate constants on ARM, this is only
117  * suitable for small forward movements (i.e. don't try to implement "goto"
118  * with this).
119  *
120  * This must come AFTER anything that can throw an exception, or the
121  * exception catch may miss.  (This also implies that it must come after
122  * EXPORT_PC().)
123  */
124 #define FETCH_ADVANCE_INST(_count) ldrh    rINST, [rPC, #(_count*2)]!
125
126 /*
127  * Fetch the next instruction from an offset specified by _reg.  Updates
128  * rPC to point to the next instruction.  "_reg" must specify the distance
129  * in bytes, *not* 16-bit code units, and may be a signed value.
130  *
131  * We want to write "ldrh rINST, [rPC, _reg, lsl #2]!", but some of the
132  * bits that hold the shift distance are used for the half/byte/sign flags.
133  * In some cases we can pre-double _reg for free, so we require a byte offset
134  * here.
135  */
136 #define FETCH_ADVANCE_INST_RB(_reg) ldrh    rINST, [rPC, _reg]!
137
138 /*
139  * Fetch a half-word code unit from an offset past the current PC.  The
140  * "_count" value is in 16-bit code units.  Does not advance rPC.
141  *
142  * The "_S" variant works the same but treats the value as signed.
143  */
144 #define FETCH(_reg, _count)     ldrh    _reg, [rPC, #(_count*2)]
145 #define FETCH_S(_reg, _count)   ldrsh   _reg, [rPC, #(_count*2)]
146
147 /*
148  * Fetch one byte from an offset past the current PC.  Pass in the same
149  * "_count" as you would for FETCH, and an additional 0/1 indicating which
150  * byte of the halfword you want (lo/hi).
151  */
152 #define FETCH_B(_reg, _count, _byte) ldrb     _reg, [rPC, #(_count*2+_byte)]
153
154 /*
155  * Put the instruction's opcode field into the specified register.
156  */
157 #define GET_INST_OPCODE(_reg)   and     _reg, rINST, #255
158
159 /*
160  * Begin executing the opcode in _reg.  Because this only jumps within the
161  * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork.
162  */
163 #define GOTO_OPCODE(_reg)       add     pc, rIBASE, _reg, lsl #6
164
165 /*
166  * Get/set the 32-bit value from a Dalvik register.
167  */
168 #define GET_VREG(_reg, _vreg)   ldr     _reg, [rFP, _vreg, lsl #2]
169 #define SET_VREG(_reg, _vreg)   str     _reg, [rFP, _vreg, lsl #2]
170
171 /*
172  * This is a #include, not a %include, because we want the C pre-processor
173  * to expand the macros into assembler assignment statements.
174  */
175 #include "../common/asm-constants.h"
176
177
178 /* File: armv5te/platform.S */
179 /*
180  * ===========================================================================
181  *  CPU-version-specific defines
182  * ===========================================================================
183  */
184
185 /*
186  * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5.  Essentially a
187  * one-way branch.
188  *
189  * May modify IP.  Does not modify LR.
190  */
191 .macro  LDR_PC source
192     ldr     pc, \source
193 .endm
194
195 /*
196  * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5.
197  * Jump to subroutine.
198  *
199  * May modify IP and LR.
200  */
201 .macro  LDR_PC_LR source
202     mov     lr, pc
203     ldr     pc, \source
204 .endm
205
206 /*
207  * Macro for "LDMFD SP!, {...regs...,PC}".
208  *
209  * May modify IP and LR.
210  */
211 .macro  LDMFD_PC regs
212     ldmfd   sp!, {\regs,pc}
213 .endm
214
215
216 /* File: armv5te/entry.S */
217 /*
218  * Copyright (C) 2008 The Android Open Source Project
219  *
220  * Licensed under the Apache License, Version 2.0 (the "License");
221  * you may not use this file except in compliance with the License.
222  * You may obtain a copy of the License at
223  *
224  *      http://www.apache.org/licenses/LICENSE-2.0
225  *
226  * Unless required by applicable law or agreed to in writing, software
227  * distributed under the License is distributed on an "AS IS" BASIS,
228  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
229  * See the License for the specific language governing permissions and
230  * limitations under the License.
231  */
232 /*
233  * Interpreter entry point.
234  */
235
236 /*
237  * We don't have formal stack frames, so gdb scans upward in the code
238  * to find the start of the function (a label with the %function type),
239  * and then looks at the next few instructions to figure out what
240  * got pushed onto the stack.  From this it figures out how to restore
241  * the registers, including PC, for the previous stack frame.  If gdb
242  * sees a non-function label, it stops scanning, so either we need to
243  * have nothing but assembler-local labels between the entry point and
244  * the break, or we need to fake it out.
245  *
246  * When this is defined, we add some stuff to make gdb less confused.
247  */
248 #define ASSIST_DEBUGGER 1
249
250     .text
251     .align  2
252     .global dvmMterpStdRun
253     .type   dvmMterpStdRun, %function
254
255 /*
256  * On entry:
257  *  r0  MterpGlue* glue
258  *
259  * This function returns a boolean "changeInterp" value.  The return comes
260  * via a call to dvmMterpStdBail().
261  */
262 dvmMterpStdRun:
263 #define MTERP_ENTRY1 \
264     .save {r4-r10,fp,lr}; \
265     stmfd   sp!, {r4-r10,fp,lr}         @ save 9 regs
266 #define MTERP_ENTRY2 \
267     .pad    #4; \
268     sub     sp, sp, #4                  @ align 64
269
270     .fnstart
271     MTERP_ENTRY1
272     MTERP_ENTRY2
273
274     /* save stack pointer, add magic word for debuggerd */
275     str     sp, [r0, #offGlue_bailPtr]  @ save SP for eventual return
276
277     /* set up "named" registers, figure out entry point */
278     mov     rGLUE, r0                   @ set rGLUE
279     ldrb    r1, [r0, #offGlue_entryPoint]   @ InterpEntry enum is char
280     LOAD_PC_FP_FROM_GLUE()              @ load rPC and rFP from "glue"
281     adr     rIBASE, dvmAsmInstructionStart  @ set rIBASE
282     cmp     r1, #kInterpEntryInstr      @ usual case?
283     bne     .Lnot_instr                 @ no, handle it
284
285     /* start executing the instruction at rPC */
286     FETCH_INST()                        @ load rINST from rPC
287     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
288     GOTO_OPCODE(ip)                     @ jump to next instruction
289
290 .Lnot_instr:
291     cmp     r1, #kInterpEntryReturn     @ were we returning from a method?
292     beq     common_returnFromMethod
293
294 .Lnot_return:
295     cmp     r1, #kInterpEntryThrow      @ were we throwing an exception?
296     beq     common_exceptionThrown
297
298 .Lbad_arg:
299     ldr     r0, strBadEntryPoint
300     @ r1 holds value of entryPoint
301     bl      printf
302     bl      dvmAbort
303     .fnend
304
305
306     .global dvmMterpStdBail
307     .type   dvmMterpStdBail, %function
308
309 /*
310  * Restore the stack pointer and PC from the save point established on entry.
311  * This is essentially the same as a longjmp, but should be cheaper.  The
312  * last instruction causes us to return to whoever called dvmMterpStdRun.
313  *
314  * We pushed some registers on the stack in dvmMterpStdRun, then saved
315  * SP and LR.  Here we restore SP, restore the registers, and then restore
316  * LR to PC.
317  *
318  * On entry:
319  *  r0  MterpGlue* glue
320  *  r1  bool changeInterp
321  */
322 dvmMterpStdBail:
323     ldr     sp, [r0, #offGlue_bailPtr]      @ sp<- saved SP
324     mov     r0, r1                          @ return the changeInterp value
325     add     sp, sp, #4                      @ un-align 64
326     LDMFD_PC "r4-r10,fp"                    @ restore 9 regs and return
327
328
329 /*
330  * String references.
331  */
332 strBadEntryPoint:
333     .word   .LstrBadEntryPoint
334
335
336
337     .global dvmAsmInstructionStart
338     .type   dvmAsmInstructionStart, %function
339 dvmAsmInstructionStart = .L_OP_NOP
340     .text
341
342 /* ------------------------------ */
343     .balign 64
344 .L_OP_NOP: /* 0x00 */
345 /* File: armv5te/OP_NOP.S */
346     FETCH_ADVANCE_INST(1)               @ advance to next instr, load rINST
347     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
348     GOTO_OPCODE(ip)                     @ execute it
349
350 #ifdef ASSIST_DEBUGGER
351     /* insert fake function header to help gdb find the stack frame */
352     .type   dalvik_inst, %function
353 dalvik_inst:
354     .fnstart
355     MTERP_ENTRY1
356     MTERP_ENTRY2
357     .fnend
358 #endif
359
360
361 /* ------------------------------ */
362     .balign 64
363 .L_OP_MOVE: /* 0x01 */
364 /* File: armv5te/OP_MOVE.S */
365     /* for move, move-object, long-to-int */
366     /* op vA, vB */
367     mov     r1, rINST, lsr #12          @ r1<- B from 15:12
368     mov     r0, rINST, lsr #8           @ r0<- A from 11:8
369     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
370     GET_VREG(r2, r1)                    @ r2<- fp[B]
371     and     r0, r0, #15
372     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
373     SET_VREG(r2, r0)                    @ fp[A]<- r2
374     GOTO_OPCODE(ip)                     @ execute next instruction
375
376
377 /* ------------------------------ */
378     .balign 64
379 .L_OP_MOVE_FROM16: /* 0x02 */
380 /* File: armv5te/OP_MOVE_FROM16.S */
381     /* for: move/from16, move-object/from16 */
382     /* op vAA, vBBBB */
383     FETCH(r1, 1)                        @ r1<- BBBB
384     mov     r0, rINST, lsr #8           @ r0<- AA
385     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
386     GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
387     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
388     SET_VREG(r2, r0)                    @ fp[AA]<- r2
389     GOTO_OPCODE(ip)                     @ jump to next instruction
390
391
392 /* ------------------------------ */
393     .balign 64
394 .L_OP_MOVE_16: /* 0x03 */
395 /* File: armv5te/OP_MOVE_16.S */
396     /* for: move/16, move-object/16 */
397     /* op vAAAA, vBBBB */
398     FETCH(r1, 2)                        @ r1<- BBBB
399     FETCH(r0, 1)                        @ r0<- AAAA
400     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
401     GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
402     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
403     SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
404     GOTO_OPCODE(ip)                     @ jump to next instruction
405
406
407 /* ------------------------------ */
408     .balign 64
409 .L_OP_MOVE_WIDE: /* 0x04 */
410 /* File: armv5te/OP_MOVE_WIDE.S */
411     /* move-wide vA, vB */
412     /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
413     mov     r2, rINST, lsr #8           @ r2<- A(+)
414     mov     r3, rINST, lsr #12          @ r3<- B
415     and     r2, r2, #15
416     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
417     add     r2, rFP, r2, lsl #2         @ r2<- &fp[A]
418     ldmia   r3, {r0-r1}                 @ r0/r1<- fp[B]
419     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
420     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
421     stmia   r2, {r0-r1}                 @ fp[A]<- r0/r1
422     GOTO_OPCODE(ip)                     @ jump to next instruction
423
424
425 /* ------------------------------ */
426     .balign 64
427 .L_OP_MOVE_WIDE_FROM16: /* 0x05 */
428 /* File: armv5te/OP_MOVE_WIDE_FROM16.S */
429     /* move-wide/from16 vAA, vBBBB */
430     /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
431     FETCH(r3, 1)                        @ r3<- BBBB
432     mov     r2, rINST, lsr #8           @ r2<- AA
433     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
434     add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
435     ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
436     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
437     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
438     stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
439     GOTO_OPCODE(ip)                     @ jump to next instruction
440
441
442 /* ------------------------------ */
443     .balign 64
444 .L_OP_MOVE_WIDE_16: /* 0x06 */
445 /* File: armv5te/OP_MOVE_WIDE_16.S */
446     /* move-wide/16 vAAAA, vBBBB */
447     /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
448     FETCH(r3, 2)                        @ r3<- BBBB
449     FETCH(r2, 1)                        @ r2<- AAAA
450     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
451     add     r2, rFP, r2, lsl #2         @ r2<- &fp[AAAA]
452     ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
453     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
454     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
455     stmia   r2, {r0-r1}                 @ fp[AAAA]<- r0/r1
456     GOTO_OPCODE(ip)                     @ jump to next instruction
457
458
459 /* ------------------------------ */
460     .balign 64
461 .L_OP_MOVE_OBJECT: /* 0x07 */
462 /* File: armv5te/OP_MOVE_OBJECT.S */
463 /* File: armv5te/OP_MOVE.S */
464     /* for move, move-object, long-to-int */
465     /* op vA, vB */
466     mov     r1, rINST, lsr #12          @ r1<- B from 15:12
467     mov     r0, rINST, lsr #8           @ r0<- A from 11:8
468     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
469     GET_VREG(r2, r1)                    @ r2<- fp[B]
470     and     r0, r0, #15
471     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
472     SET_VREG(r2, r0)                    @ fp[A]<- r2
473     GOTO_OPCODE(ip)                     @ execute next instruction
474
475
476
477 /* ------------------------------ */
478     .balign 64
479 .L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
480 /* File: armv5te/OP_MOVE_OBJECT_FROM16.S */
481 /* File: armv5te/OP_MOVE_FROM16.S */
482     /* for: move/from16, move-object/from16 */
483     /* op vAA, vBBBB */
484     FETCH(r1, 1)                        @ r1<- BBBB
485     mov     r0, rINST, lsr #8           @ r0<- AA
486     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
487     GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
488     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
489     SET_VREG(r2, r0)                    @ fp[AA]<- r2
490     GOTO_OPCODE(ip)                     @ jump to next instruction
491
492
493
494 /* ------------------------------ */
495     .balign 64
496 .L_OP_MOVE_OBJECT_16: /* 0x09 */
497 /* File: armv5te/OP_MOVE_OBJECT_16.S */
498 /* File: armv5te/OP_MOVE_16.S */
499     /* for: move/16, move-object/16 */
500     /* op vAAAA, vBBBB */
501     FETCH(r1, 2)                        @ r1<- BBBB
502     FETCH(r0, 1)                        @ r0<- AAAA
503     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
504     GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
505     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
506     SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
507     GOTO_OPCODE(ip)                     @ jump to next instruction
508
509
510
511 /* ------------------------------ */
512     .balign 64
513 .L_OP_MOVE_RESULT: /* 0x0a */
514 /* File: armv5te/OP_MOVE_RESULT.S */
515     /* for: move-result, move-result-object */
516     /* op vAA */
517     mov     r2, rINST, lsr #8           @ r2<- AA
518     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
519     ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
520     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
521     SET_VREG(r0, r2)                    @ fp[AA]<- r0
522     GOTO_OPCODE(ip)                     @ jump to next instruction
523
524
525 /* ------------------------------ */
526     .balign 64
527 .L_OP_MOVE_RESULT_WIDE: /* 0x0b */
528 /* File: armv5te/OP_MOVE_RESULT_WIDE.S */
529     /* move-result-wide vAA */
530     mov     r2, rINST, lsr #8           @ r2<- AA
531     add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
532     add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
533     ldmia   r3, {r0-r1}                 @ r0/r1<- retval.j
534     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
535     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
536     stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
537     GOTO_OPCODE(ip)                     @ jump to next instruction
538
539
540 /* ------------------------------ */
541     .balign 64
542 .L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
543 /* File: armv5te/OP_MOVE_RESULT_OBJECT.S */
544 /* File: armv5te/OP_MOVE_RESULT.S */
545     /* for: move-result, move-result-object */
546     /* op vAA */
547     mov     r2, rINST, lsr #8           @ r2<- AA
548     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
549     ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
550     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
551     SET_VREG(r0, r2)                    @ fp[AA]<- r0
552     GOTO_OPCODE(ip)                     @ jump to next instruction
553
554
555
556 /* ------------------------------ */
557     .balign 64
558 .L_OP_MOVE_EXCEPTION: /* 0x0d */
559 /* File: armv5te/OP_MOVE_EXCEPTION.S */
560     /* move-exception vAA */
561     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
562     mov     r2, rINST, lsr #8           @ r2<- AA
563     ldr     r3, [r0, #offThread_exception]  @ r3<- dvmGetException bypass
564     mov     r1, #0                      @ r1<- 0
565     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
566     SET_VREG(r3, r2)                    @ fp[AA]<- exception obj
567     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
568     str     r1, [r0, #offThread_exception]  @ dvmClearException bypass
569     GOTO_OPCODE(ip)                     @ jump to next instruction
570
571
572 /* ------------------------------ */
573     .balign 64
574 .L_OP_RETURN_VOID: /* 0x0e */
575 /* File: armv5te/OP_RETURN_VOID.S */
576     b       common_returnFromMethod
577
578
579 /* ------------------------------ */
580     .balign 64
581 .L_OP_RETURN: /* 0x0f */
582 /* File: armv5te/OP_RETURN.S */
583     /*
584      * Return a 32-bit value.  Copies the return value into the "glue"
585      * structure, then jumps to the return handler.
586      *
587      * for: return, return-object
588      */
589     /* op vAA */
590     mov     r2, rINST, lsr #8           @ r2<- AA
591     GET_VREG(r0, r2)                    @ r0<- vAA
592     str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
593     b       common_returnFromMethod
594
595
596 /* ------------------------------ */
597     .balign 64
598 .L_OP_RETURN_WIDE: /* 0x10 */
599 /* File: armv5te/OP_RETURN_WIDE.S */
600     /*
601      * Return a 64-bit value.  Copies the return value into the "glue"
602      * structure, then jumps to the return handler.
603      */
604     /* return-wide vAA */
605     mov     r2, rINST, lsr #8           @ r2<- AA
606     add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
607     add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
608     ldmia   r2, {r0-r1}                 @ r0/r1 <- vAA/vAA+1
609     stmia   r3, {r0-r1}                 @ retval<- r0/r1
610     b       common_returnFromMethod
611
612
613 /* ------------------------------ */
614     .balign 64
615 .L_OP_RETURN_OBJECT: /* 0x11 */
616 /* File: armv5te/OP_RETURN_OBJECT.S */
617 /* File: armv5te/OP_RETURN.S */
618     /*
619      * Return a 32-bit value.  Copies the return value into the "glue"
620      * structure, then jumps to the return handler.
621      *
622      * for: return, return-object
623      */
624     /* op vAA */
625     mov     r2, rINST, lsr #8           @ r2<- AA
626     GET_VREG(r0, r2)                    @ r0<- vAA
627     str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
628     b       common_returnFromMethod
629
630
631
632 /* ------------------------------ */
633     .balign 64
634 .L_OP_CONST_4: /* 0x12 */
635 /* File: armv5te/OP_CONST_4.S */
636     /* const/4 vA, #+B */
637     mov     r1, rINST, lsl #16          @ r1<- Bxxx0000
638     mov     r0, rINST, lsr #8           @ r0<- A+
639     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
640     mov     r1, r1, asr #28             @ r1<- sssssssB (sign-extended)
641     and     r0, r0, #15
642     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
643     SET_VREG(r1, r0)                    @ fp[A]<- r1
644     GOTO_OPCODE(ip)                     @ execute next instruction
645
646
647 /* ------------------------------ */
648     .balign 64
649 .L_OP_CONST_16: /* 0x13 */
650 /* File: armv5te/OP_CONST_16.S */
651     /* const/16 vAA, #+BBBB */
652     FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
653     mov     r3, rINST, lsr #8           @ r3<- AA
654     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
655     SET_VREG(r0, r3)                    @ vAA<- r0
656     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
657     GOTO_OPCODE(ip)                     @ jump to next instruction
658
659
660 /* ------------------------------ */
661     .balign 64
662 .L_OP_CONST: /* 0x14 */
663 /* File: armv5te/OP_CONST.S */
664     /* const vAA, #+BBBBbbbb */
665     mov     r3, rINST, lsr #8           @ r3<- AA
666     FETCH(r0, 1)                        @ r0<- bbbb (low)
667     FETCH(r1, 2)                        @ r1<- BBBB (high)
668     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
669     orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
670     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
671     SET_VREG(r0, r3)                    @ vAA<- r0
672     GOTO_OPCODE(ip)                     @ jump to next instruction
673
674
675 /* ------------------------------ */
676     .balign 64
677 .L_OP_CONST_HIGH16: /* 0x15 */
678 /* File: armv5te/OP_CONST_HIGH16.S */
679     /* const/high16 vAA, #+BBBB0000 */
680     FETCH(r0, 1)                        @ r0<- 0000BBBB (zero-extended)
681     mov     r3, rINST, lsr #8           @ r3<- AA
682     mov     r0, r0, lsl #16             @ r0<- BBBB0000
683     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
684     SET_VREG(r0, r3)                    @ vAA<- r0
685     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
686     GOTO_OPCODE(ip)                     @ jump to next instruction
687
688
689 /* ------------------------------ */
690     .balign 64
691 .L_OP_CONST_WIDE_16: /* 0x16 */
692 /* File: armv5te/OP_CONST_WIDE_16.S */
693     /* const-wide/16 vAA, #+BBBB */
694     FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
695     mov     r3, rINST, lsr #8           @ r3<- AA
696     mov     r1, r0, asr #31             @ r1<- ssssssss
697     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
698     add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
699     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
700     stmia   r3, {r0-r1}                 @ vAA<- r0/r1
701     GOTO_OPCODE(ip)                     @ jump to next instruction
702
703
704 /* ------------------------------ */
705     .balign 64
706 .L_OP_CONST_WIDE_32: /* 0x17 */
707 /* File: armv5te/OP_CONST_WIDE_32.S */
708     /* const-wide/32 vAA, #+BBBBbbbb */
709     FETCH(r0, 1)                        @ r0<- 0000bbbb (low)
710     mov     r3, rINST, lsr #8           @ r3<- AA
711     FETCH_S(r2, 2)                      @ r2<- ssssBBBB (high)
712     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
713     orr     r0, r0, r2, lsl #16         @ r0<- BBBBbbbb
714     add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
715     mov     r1, r0, asr #31             @ r1<- ssssssss
716     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
717     stmia   r3, {r0-r1}                 @ vAA<- r0/r1
718     GOTO_OPCODE(ip)                     @ jump to next instruction
719
720
721 /* ------------------------------ */
722     .balign 64
723 .L_OP_CONST_WIDE: /* 0x18 */
724 /* File: armv5te/OP_CONST_WIDE.S */
725     /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
726     FETCH(r0, 1)                        @ r0<- bbbb (low)
727     FETCH(r1, 2)                        @ r1<- BBBB (low middle)
728     FETCH(r2, 3)                        @ r2<- hhhh (high middle)
729     orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb (low word)
730     FETCH(r3, 4)                        @ r3<- HHHH (high)
731     mov     r9, rINST, lsr #8           @ r9<- AA
732     orr     r1, r2, r3, lsl #16         @ r1<- HHHHhhhh (high word)
733     FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
734     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
735     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
736     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
737     GOTO_OPCODE(ip)                     @ jump to next instruction
738
739
740 /* ------------------------------ */
741     .balign 64
742 .L_OP_CONST_WIDE_HIGH16: /* 0x19 */
743 /* File: armv5te/OP_CONST_WIDE_HIGH16.S */
744     /* const-wide/high16 vAA, #+BBBB000000000000 */
745     FETCH(r1, 1)                        @ r1<- 0000BBBB (zero-extended)
746     mov     r3, rINST, lsr #8           @ r3<- AA
747     mov     r0, #0                      @ r0<- 00000000
748     mov     r1, r1, lsl #16             @ r1<- BBBB0000
749     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
750     add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
751     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
752     stmia   r3, {r0-r1}                 @ vAA<- r0/r1
753     GOTO_OPCODE(ip)                     @ jump to next instruction
754
755
756 /* ------------------------------ */
757     .balign 64
758 .L_OP_CONST_STRING: /* 0x1a */
759 /* File: armv5te/OP_CONST_STRING.S */
760     /* const/string vAA, String@BBBB */
761     FETCH(r1, 1)                        @ r1<- BBBB
762     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
763     mov     r9, rINST, lsr #8           @ r9<- AA
764     ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
765     ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
766     cmp     r0, #0                      @ not yet resolved?
767     beq     .LOP_CONST_STRING_resolve
768     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
769     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
770     SET_VREG(r0, r9)                    @ vAA<- r0
771     GOTO_OPCODE(ip)                     @ jump to next instruction
772
773 /* ------------------------------ */
774     .balign 64
775 .L_OP_CONST_STRING_JUMBO: /* 0x1b */
776 /* File: armv5te/OP_CONST_STRING_JUMBO.S */
777     /* const/string vAA, String@BBBBBBBB */
778     FETCH(r0, 1)                        @ r0<- bbbb (low)
779     FETCH(r1, 2)                        @ r1<- BBBB (high)
780     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
781     mov     r9, rINST, lsr #8           @ r9<- AA
782     ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
783     orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
784     ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
785     cmp     r0, #0
786     beq     .LOP_CONST_STRING_JUMBO_resolve
787     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
788     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
789     SET_VREG(r0, r9)                    @ vAA<- r0
790     GOTO_OPCODE(ip)                     @ jump to next instruction
791
792 /* ------------------------------ */
793     .balign 64
794 .L_OP_CONST_CLASS: /* 0x1c */
795 /* File: armv5te/OP_CONST_CLASS.S */
796     /* const/class vAA, Class@BBBB */
797     FETCH(r1, 1)                        @ r1<- BBBB
798     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
799     mov     r9, rINST, lsr #8           @ r9<- AA
800     ldr     r2, [r2, #offDvmDex_pResClasses]   @ r2<- dvmDex->pResClasses
801     ldr     r0, [r2, r1, lsl #2]        @ r0<- pResClasses[BBBB]
802     cmp     r0, #0                      @ not yet resolved?
803     beq     .LOP_CONST_CLASS_resolve
804     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
805     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
806     SET_VREG(r0, r9)                    @ vAA<- r0
807     GOTO_OPCODE(ip)                     @ jump to next instruction
808
809 /* ------------------------------ */
810     .balign 64
811 .L_OP_MONITOR_ENTER: /* 0x1d */
812 /* File: armv5te/OP_MONITOR_ENTER.S */
813     /*
814      * Synchronize on an object.
815      */
816     /* monitor-enter vAA */
817     mov     r2, rINST, lsr #8           @ r2<- AA
818     GET_VREG(r1, r2)                    @ r1<- vAA (object)
819     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
820     cmp     r1, #0                      @ null object?
821 #ifdef WITH_MONITOR_TRACKING
822     EXPORT_PC()                         @ export PC so we can grab stack trace
823 #endif
824     beq     common_errNullObject        @ null object, throw an exception
825     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
826     bl      dvmLockObject               @ call(self, obj)
827 #ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */
828     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
829     ldr     r1, [r0, #offThread_exception] @ check for exception
830     cmp     r1, #0
831     bne     common_exceptionThrown      @ exception raised, bail out
832 #endif
833     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
834     GOTO_OPCODE(ip)                     @ jump to next instruction
835
836
837 /* ------------------------------ */
838     .balign 64
839 .L_OP_MONITOR_EXIT: /* 0x1e */
840 /* File: armv5te/OP_MONITOR_EXIT.S */
841     /*
842      * Unlock an object.
843      *
844      * Exceptions that occur when unlocking a monitor need to appear as
845      * if they happened at the following instruction.  See the Dalvik
846      * instruction spec.
847      */
848     /* monitor-exit vAA */
849     mov     r2, rINST, lsr #8           @ r2<- AA
850     EXPORT_PC()                         @ before fetch: export the PC
851     GET_VREG(r1, r2)                    @ r1<- vAA (object)
852     cmp     r1, #0                      @ null object?
853     beq     common_errNullObject        @ yes
854     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
855     bl      dvmUnlockObject             @ r0<- success for unlock(self, obj)
856     cmp     r0, #0                      @ failed?
857     beq     common_exceptionThrown      @ yes, exception is pending
858     FETCH_ADVANCE_INST(1)               @ before throw: advance rPC, load rINST
859     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
860     GOTO_OPCODE(ip)                     @ jump to next instruction
861
862
863 /* ------------------------------ */
864     .balign 64
865 .L_OP_CHECK_CAST: /* 0x1f */
866 /* File: armv5te/OP_CHECK_CAST.S */
867     /*
868      * Check to see if a cast from one class to another is allowed.
869      */
870     /* check-cast vAA, class@BBBB */
871     mov     r3, rINST, lsr #8           @ r3<- AA
872     FETCH(r2, 1)                        @ r2<- BBBB
873     GET_VREG(r9, r3)                    @ r9<- object
874     ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- pDvmDex
875     cmp     r9, #0                      @ is object null?
876     ldr     r0, [r0, #offDvmDex_pResClasses]    @ r0<- pDvmDex->pResClasses
877     beq     .LOP_CHECK_CAST_okay            @ null obj, cast always succeeds
878     ldr     r1, [r0, r2, lsl #2]        @ r1<- resolved class
879     ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
880     cmp     r1, #0                      @ have we resolved this before?
881     beq     .LOP_CHECK_CAST_resolve         @ not resolved, do it now
882 .LOP_CHECK_CAST_resolved:
883     cmp     r0, r1                      @ same class (trivial success)?
884     bne     .LOP_CHECK_CAST_fullcheck       @ no, do full check
885 .LOP_CHECK_CAST_okay:
886     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
887     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
888     GOTO_OPCODE(ip)                     @ jump to next instruction
889
890 /* ------------------------------ */
891     .balign 64
892 .L_OP_INSTANCE_OF: /* 0x20 */
893 /* File: armv5te/OP_INSTANCE_OF.S */
894     /*
895      * Check to see if an object reference is an instance of a class.
896      *
897      * Most common situation is a non-null object, being compared against
898      * an already-resolved class.
899      */
900     /* instance-of vA, vB, class@CCCC */
901     mov     r3, rINST, lsr #12          @ r3<- B
902     mov     r9, rINST, lsr #8           @ r9<- A+
903     GET_VREG(r0, r3)                    @ r0<- vB (object)
904     and     r9, r9, #15                 @ r9<- A
905     cmp     r0, #0                      @ is object null?
906     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- pDvmDex
907     beq     .LOP_INSTANCE_OF_store           @ null obj, not an instance, store r0
908     FETCH(r3, 1)                        @ r3<- CCCC
909     ldr     r2, [r2, #offDvmDex_pResClasses]    @ r2<- pDvmDex->pResClasses
910     ldr     r1, [r2, r3, lsl #2]        @ r1<- resolved class
911     ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
912     cmp     r1, #0                      @ have we resolved this before?
913     beq     .LOP_INSTANCE_OF_resolve         @ not resolved, do it now
914 .LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class
915     cmp     r0, r1                      @ same class (trivial success)?
916     beq     .LOP_INSTANCE_OF_trivial         @ yes, trivial finish
917     b       .LOP_INSTANCE_OF_fullcheck       @ no, do full check
918
919 /* ------------------------------ */
920     .balign 64
921 .L_OP_ARRAY_LENGTH: /* 0x21 */
922 /* File: armv5te/OP_ARRAY_LENGTH.S */
923     /*
924      * Return the length of an array.
925      */
926     mov     r1, rINST, lsr #12          @ r1<- B
927     mov     r2, rINST, lsr #8           @ r2<- A+
928     GET_VREG(r0, r1)                    @ r0<- vB (object ref)
929     and     r2, r2, #15                 @ r2<- A
930     cmp     r0, #0                      @ is object null?
931     beq     common_errNullObject        @ yup, fail
932     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
933     ldr     r3, [r0, #offArrayObject_length]    @ r3<- array length
934     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
935     SET_VREG(r3, r2)                    @ vB<- length
936     GOTO_OPCODE(ip)                     @ jump to next instruction
937
938
939 /* ------------------------------ */
940     .balign 64
941 .L_OP_NEW_INSTANCE: /* 0x22 */
942 /* File: armv5te/OP_NEW_INSTANCE.S */
943     /*
944      * Create a new instance of a class.
945      */
946     /* new-instance vAA, class@BBBB */
947     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
948     FETCH(r1, 1)                        @ r1<- BBBB
949     ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
950     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
951     EXPORT_PC()                         @ req'd for init, resolve, alloc
952     cmp     r0, #0                      @ already resolved?
953     beq     .LOP_NEW_INSTANCE_resolve         @ no, resolve it now
954 .LOP_NEW_INSTANCE_resolved:   @ r0=class
955     ldrb    r1, [r0, #offClassObject_status]    @ r1<- ClassStatus enum
956     cmp     r1, #CLASS_INITIALIZED      @ has class been initialized?
957     bne     .LOP_NEW_INSTANCE_needinit        @ no, init class now
958 .LOP_NEW_INSTANCE_initialized: @ r0=class
959     ldr     r3, [r0, #offClassObject_accessFlags]   @ r3<- clazz->accessFlags
960     tst     r3, #(ACC_INTERFACE|ACC_ABSTRACT)   @ abstract or interface?
961     mov     r1, #ALLOC_DONT_TRACK       @ flags for alloc call
962     beq     .LOP_NEW_INSTANCE_finish          @ concrete class, continue
963     b       .LOP_NEW_INSTANCE_abstract        @ fail
964
965 /* ------------------------------ */
966     .balign 64
967 .L_OP_NEW_ARRAY: /* 0x23 */
968 /* File: armv5te/OP_NEW_ARRAY.S */
969     /*
970      * Allocate an array of objects, specified with the array class
971      * and a count.
972      *
973      * The verifier guarantees that this is an array class, so we don't
974      * check for it here.
975      */
976     /* new-array vA, vB, class@CCCC */
977     mov     r0, rINST, lsr #12          @ r0<- B
978     FETCH(r2, 1)                        @ r2<- CCCC
979     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
980     GET_VREG(r1, r0)                    @ r1<- vB (array length)
981     ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
982     cmp     r1, #0                      @ check length
983     ldr     r0, [r3, r2, lsl #2]        @ r0<- resolved class
984     bmi     common_errNegativeArraySize @ negative length, bail
985     cmp     r0, #0                      @ already resolved?
986     EXPORT_PC()                         @ req'd for resolve, alloc
987     bne     .LOP_NEW_ARRAY_finish          @ resolved, continue
988     b       .LOP_NEW_ARRAY_resolve         @ do resolve now
989
990 /* ------------------------------ */
991     .balign 64
992 .L_OP_FILLED_NEW_ARRAY: /* 0x24 */
993 /* File: armv5te/OP_FILLED_NEW_ARRAY.S */
994     /*
995      * Create a new array with elements filled from registers.
996      *
997      * for: filled-new-array, filled-new-array/range
998      */
999     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1000     /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1001     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1002     FETCH(r1, 1)                        @ r1<- BBBB
1003     ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1004     EXPORT_PC()                         @ need for resolve and alloc
1005     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1006     mov     r10, rINST, lsr #8          @ r10<- AA or BA
1007     cmp     r0, #0                      @ already resolved?
1008     bne     .LOP_FILLED_NEW_ARRAY_continue        @ yes, continue on
1009 8:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1010     mov     r2, #0                      @ r2<- false
1011     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1012     bl      dvmResolveClass             @ r0<- call(clazz, ref)
1013     cmp     r0, #0                      @ got null?
1014     beq     common_exceptionThrown      @ yes, handle exception
1015     b       .LOP_FILLED_NEW_ARRAY_continue
1016
1017 /* ------------------------------ */
1018     .balign 64
1019 .L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
1020 /* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */
1021 /* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1022     /*
1023      * Create a new array with elements filled from registers.
1024      *
1025      * for: filled-new-array, filled-new-array/range
1026      */
1027     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1028     /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1029     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1030     FETCH(r1, 1)                        @ r1<- BBBB
1031     ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1032     EXPORT_PC()                         @ need for resolve and alloc
1033     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1034     mov     r10, rINST, lsr #8          @ r10<- AA or BA
1035     cmp     r0, #0                      @ already resolved?
1036     bne     .LOP_FILLED_NEW_ARRAY_RANGE_continue        @ yes, continue on
1037 8:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1038     mov     r2, #0                      @ r2<- false
1039     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1040     bl      dvmResolveClass             @ r0<- call(clazz, ref)
1041     cmp     r0, #0                      @ got null?
1042     beq     common_exceptionThrown      @ yes, handle exception
1043     b       .LOP_FILLED_NEW_ARRAY_RANGE_continue
1044
1045
1046 /* ------------------------------ */
1047     .balign 64
1048 .L_OP_FILL_ARRAY_DATA: /* 0x26 */
1049 /* File: armv5te/OP_FILL_ARRAY_DATA.S */
1050     /* fill-array-data vAA, +BBBBBBBB */
1051     FETCH(r0, 1)                        @ r0<- bbbb (lo)
1052     FETCH(r1, 2)                        @ r1<- BBBB (hi)
1053     mov     r3, rINST, lsr #8           @ r3<- AA
1054     orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
1055     GET_VREG(r0, r3)                    @ r0<- vAA (array object)
1056     add     r1, rPC, r1, lsl #1         @ r1<- PC + BBBBbbbb*2 (array data off.)
1057     EXPORT_PC();
1058     bl      dvmInterpHandleFillArrayData@ fill the array with predefined data
1059     cmp     r0, #0                      @ 0 means an exception is thrown
1060     beq     common_exceptionThrown      @ has exception
1061     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
1062     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1063     GOTO_OPCODE(ip)                     @ jump to next instruction
1064
1065 /* ------------------------------ */
1066     .balign 64
1067 .L_OP_THROW: /* 0x27 */
1068 /* File: armv5te/OP_THROW.S */
1069     /*
1070      * Throw an exception object in the current thread.
1071      */
1072     /* throw vAA */
1073     mov     r2, rINST, lsr #8           @ r2<- AA
1074     GET_VREG(r1, r2)                    @ r1<- vAA (exception object)
1075     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
1076     cmp     r1, #0                      @ null object?
1077     beq     common_errNullObject        @ yes, throw an NPE instead
1078     @ bypass dvmSetException, just store it
1079     str     r1, [r0, #offThread_exception]  @ thread->exception<- obj
1080     b       common_exceptionThrown
1081
1082
1083 /* ------------------------------ */
1084     .balign 64
1085 .L_OP_GOTO: /* 0x28 */
1086 /* File: armv5te/OP_GOTO.S */
1087     /*
1088      * Unconditional branch, 8-bit offset.
1089      *
1090      * The branch distance is a signed code-unit offset, which we need to
1091      * double to get a byte offset.
1092      */
1093     /* goto +AA */
1094     mov     r0, rINST, lsl #16          @ r0<- AAxx0000
1095     movs    r9, r0, asr #24             @ r9<- ssssssAA (sign-extended)
1096     mov     r9, r9, lsl #1              @ r9<- byte offset
1097     bmi     common_backwardBranch       @ backward branch, do periodic checks
1098     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1099     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1100     GOTO_OPCODE(ip)                     @ jump to next instruction
1101
1102
1103 /* ------------------------------ */
1104     .balign 64
1105 .L_OP_GOTO_16: /* 0x29 */
1106 /* File: armv5te/OP_GOTO_16.S */
1107     /*
1108      * Unconditional branch, 16-bit offset.
1109      *
1110      * The branch distance is a signed code-unit offset, which we need to
1111      * double to get a byte offset.
1112      */
1113     /* goto/16 +AAAA */
1114     FETCH_S(r0, 1)                      @ r0<- ssssAAAA (sign-extended)
1115     movs    r9, r0, asl #1              @ r9<- byte offset, check sign
1116     bmi     common_backwardBranch       @ backward branch, do periodic checks
1117     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1118     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1119     GOTO_OPCODE(ip)                     @ jump to next instruction
1120
1121
1122 /* ------------------------------ */
1123     .balign 64
1124 .L_OP_GOTO_32: /* 0x2a */
1125 /* File: armv5te/OP_GOTO_32.S */
1126     /*
1127      * Unconditional branch, 32-bit offset.
1128      *
1129      * The branch distance is a signed code-unit offset, which we need to
1130      * double to get a byte offset.
1131      *
1132      * Unlike most opcodes, this one is allowed to branch to itself, so
1133      * our "backward branch" test must be "<=0" instead of "<0".  The ORRS
1134      * instruction doesn't affect the V flag, so we need to clear it
1135      * explicitly.
1136      */
1137     /* goto/32 +AAAAAAAA */
1138     FETCH(r0, 1)                        @ r0<- aaaa (lo)
1139     FETCH(r1, 2)                        @ r1<- AAAA (hi)
1140     cmp     ip, ip                      @ (clear V flag during stall)
1141     orrs    r0, r0, r1, lsl #16         @ r0<- AAAAaaaa, check sign
1142     mov     r9, r0, asl #1              @ r9<- byte offset
1143     ble     common_backwardBranch       @ backward branch, do periodic checks
1144     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1145     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1146     GOTO_OPCODE(ip)                     @ jump to next instruction
1147
1148
1149 /* ------------------------------ */
1150     .balign 64
1151 .L_OP_PACKED_SWITCH: /* 0x2b */
1152 /* File: armv5te/OP_PACKED_SWITCH.S */
1153     /*
1154      * Handle a packed-switch or sparse-switch instruction.  In both cases
1155      * we decode it and hand it off to a helper function.
1156      *
1157      * We don't really expect backward branches in a switch statement, but
1158      * they're perfectly legal, so we check for them here.
1159      *
1160      * for: packed-switch, sparse-switch
1161      */
1162     /* op vAA, +BBBB */
1163     FETCH(r0, 1)                        @ r0<- bbbb (lo)
1164     FETCH(r1, 2)                        @ r1<- BBBB (hi)
1165     mov     r3, rINST, lsr #8           @ r3<- AA
1166     orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1167     GET_VREG(r1, r3)                    @ r1<- vAA
1168     add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1169     bl      dvmInterpHandlePackedSwitch                       @ r0<- code-unit branch offset
1170     movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1171     bmi     common_backwardBranch       @ backward branch, do periodic checks
1172     beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1173     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1174     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1175     GOTO_OPCODE(ip)                     @ jump to next instruction
1176
1177
1178 /* ------------------------------ */
1179     .balign 64
1180 .L_OP_SPARSE_SWITCH: /* 0x2c */
1181 /* File: armv5te/OP_SPARSE_SWITCH.S */
1182 /* File: armv5te/OP_PACKED_SWITCH.S */
1183     /*
1184      * Handle a packed-switch or sparse-switch instruction.  In both cases
1185      * we decode it and hand it off to a helper function.
1186      *
1187      * We don't really expect backward branches in a switch statement, but
1188      * they're perfectly legal, so we check for them here.
1189      *
1190      * for: packed-switch, sparse-switch
1191      */
1192     /* op vAA, +BBBB */
1193     FETCH(r0, 1)                        @ r0<- bbbb (lo)
1194     FETCH(r1, 2)                        @ r1<- BBBB (hi)
1195     mov     r3, rINST, lsr #8           @ r3<- AA
1196     orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1197     GET_VREG(r1, r3)                    @ r1<- vAA
1198     add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1199     bl      dvmInterpHandleSparseSwitch                       @ r0<- code-unit branch offset
1200     movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1201     bmi     common_backwardBranch       @ backward branch, do periodic checks
1202     beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1203     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1204     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1205     GOTO_OPCODE(ip)                     @ jump to next instruction
1206
1207
1208
1209 /* ------------------------------ */
1210     .balign 64
1211 .L_OP_CMPL_FLOAT: /* 0x2d */
1212 /* File: armv5te/OP_CMPL_FLOAT.S */
1213     /*
1214      * Compare two floating-point values.  Puts 0, 1, or -1 into the
1215      * destination register based on the results of the comparison.
1216      *
1217      * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1218      * on what value we'd like to return when one of the operands is NaN.
1219      *
1220      * The operation we're implementing is:
1221      *   if (x == y)
1222      *     return 0;
1223      *   else if (x < y)
1224      *     return -1;
1225      *   else if (x > y)
1226      *     return 1;
1227      *   else
1228      *     return {-1,1};  // one or both operands was NaN
1229      *
1230      * The straightforward implementation requires 3 calls to functions
1231      * that return a result in r0.  We can do it with two calls if our
1232      * EABI library supports __aeabi_cfcmple (only one if we want to check
1233      * for NaN directly):
1234      *   check x <= y
1235      *     if <, return -1
1236      *     if ==, return 0
1237      *   check y <= x
1238      *     if <, return 1
1239      *   return {-1,1}
1240      *
1241      * for: cmpl-float, cmpg-float
1242      */
1243     /* op vAA, vBB, vCC */
1244     FETCH(r0, 1)                        @ r0<- CCBB
1245     and     r2, r0, #255                @ r2<- BB
1246     mov     r3, r0, lsr #8              @ r3<- CC
1247     GET_VREG(r9, r2)                    @ r9<- vBB
1248     GET_VREG(r10, r3)                   @ r10<- vCC
1249     mov     r0, r9                      @ copy to arg registers
1250     mov     r1, r10
1251     bl      __aeabi_cfcmple             @ cmp <=: C clear if <, Z set if eq
1252     bhi     .LOP_CMPL_FLOAT_gt_or_nan       @ C set and Z clear, disambiguate
1253     mvncc   r1, #0                      @ (less than) r1<- -1
1254     moveq   r1, #0                      @ (equal) r1<- 0, trumps less than
1255 .LOP_CMPL_FLOAT_finish:
1256     mov     r3, rINST, lsr #8           @ r3<- AA
1257     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1258     SET_VREG(r1, r3)                    @ vAA<- r1
1259     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1260     GOTO_OPCODE(ip)                     @ jump to next instruction
1261
1262 /* ------------------------------ */
1263     .balign 64
1264 .L_OP_CMPG_FLOAT: /* 0x2e */
1265 /* File: armv5te/OP_CMPG_FLOAT.S */
1266 /* File: armv5te/OP_CMPL_FLOAT.S */
1267     /*
1268      * Compare two floating-point values.  Puts 0, 1, or -1 into the
1269      * destination register based on the results of the comparison.
1270      *
1271      * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1272      * on what value we'd like to return when one of the operands is NaN.
1273      *
1274      * The operation we're implementing is:
1275      *   if (x == y)
1276      *     return 0;
1277      *   else if (x < y)
1278      *     return -1;
1279      *   else if (x > y)
1280      *     return 1;
1281      *   else
1282      *     return {-1,1};  // one or both operands was NaN
1283      *
1284      * The straightforward implementation requires 3 calls to functions
1285      * that return a result in r0.  We can do it with two calls if our
1286      * EABI library supports __aeabi_cfcmple (only one if we want to check
1287      * for NaN directly):
1288      *   check x <= y
1289      *     if <, return -1
1290      *     if ==, return 0
1291      *   check y <= x
1292      *     if <, return 1
1293      *   return {-1,1}
1294      *
1295      * for: cmpl-float, cmpg-float
1296      */
1297     /* op vAA, vBB, vCC */
1298     FETCH(r0, 1)                        @ r0<- CCBB
1299     and     r2, r0, #255                @ r2<- BB
1300     mov     r3, r0, lsr #8              @ r3<- CC
1301     GET_VREG(r9, r2)                    @ r9<- vBB
1302     GET_VREG(r10, r3)                   @ r10<- vCC
1303     mov     r0, r9                      @ copy to arg registers
1304     mov     r1, r10
1305     bl      __aeabi_cfcmple             @ cmp <=: C clear if <, Z set if eq
1306     bhi     .LOP_CMPG_FLOAT_gt_or_nan       @ C set and Z clear, disambiguate
1307     mvncc   r1, #0                      @ (less than) r1<- -1
1308     moveq   r1, #0                      @ (equal) r1<- 0, trumps less than
1309 .LOP_CMPG_FLOAT_finish:
1310     mov     r3, rINST, lsr #8           @ r3<- AA
1311     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1312     SET_VREG(r1, r3)                    @ vAA<- r1
1313     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1314     GOTO_OPCODE(ip)                     @ jump to next instruction
1315
1316
1317 /* ------------------------------ */
1318     .balign 64
1319 .L_OP_CMPL_DOUBLE: /* 0x2f */
1320 /* File: armv5te/OP_CMPL_DOUBLE.S */
1321     /*
1322      * Compare two floating-point values.  Puts 0, 1, or -1 into the
1323      * destination register based on the results of the comparison.
1324      *
1325      * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1326      * on what value we'd like to return when one of the operands is NaN.
1327      *
1328      * See OP_CMPL_FLOAT for an explanation.
1329      *
1330      * For: cmpl-double, cmpg-double
1331      */
1332     /* op vAA, vBB, vCC */
1333     FETCH(r0, 1)                        @ r0<- CCBB
1334     and     r9, r0, #255                @ r9<- BB
1335     mov     r10, r0, lsr #8             @ r10<- CC
1336     add     r9, rFP, r9, lsl #2         @ r9<- &fp[BB]
1337     add     r10, rFP, r10, lsl #2       @ r10<- &fp[CC]
1338     ldmia   r9, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1339     ldmia   r10, {r2-r3}                @ r2/r3<- vCC/vCC+1
1340     bl      __aeabi_cdcmple             @ cmp <=: C clear if <, Z set if eq
1341     bhi     .LOP_CMPL_DOUBLE_gt_or_nan       @ C set and Z clear, disambiguate
1342     mvncc   r1, #0                      @ (less than) r1<- -1
1343     moveq   r1, #0                      @ (equal) r1<- 0, trumps less than
1344 .LOP_CMPL_DOUBLE_finish:
1345     mov     r3, rINST, lsr #8           @ r3<- AA
1346     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1347     SET_VREG(r1, r3)                    @ vAA<- r1
1348     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1349     GOTO_OPCODE(ip)                     @ jump to next instruction
1350
1351 /* ------------------------------ */
1352     .balign 64
1353 .L_OP_CMPG_DOUBLE: /* 0x30 */
1354 /* File: armv5te/OP_CMPG_DOUBLE.S */
1355 /* File: armv5te/OP_CMPL_DOUBLE.S */
1356     /*
1357      * Compare two floating-point values.  Puts 0, 1, or -1 into the
1358      * destination register based on the results of the comparison.
1359      *
1360      * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1361      * on what value we'd like to return when one of the operands is NaN.
1362      *
1363      * See OP_CMPL_FLOAT for an explanation.
1364      *
1365      * For: cmpl-double, cmpg-double
1366      */
1367     /* op vAA, vBB, vCC */
1368     FETCH(r0, 1)                        @ r0<- CCBB
1369     and     r9, r0, #255                @ r9<- BB
1370     mov     r10, r0, lsr #8             @ r10<- CC
1371     add     r9, rFP, r9, lsl #2         @ r9<- &fp[BB]
1372     add     r10, rFP, r10, lsl #2       @ r10<- &fp[CC]
1373     ldmia   r9, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1374     ldmia   r10, {r2-r3}                @ r2/r3<- vCC/vCC+1
1375     bl      __aeabi_cdcmple             @ cmp <=: C clear if <, Z set if eq
1376     bhi     .LOP_CMPG_DOUBLE_gt_or_nan       @ C set and Z clear, disambiguate
1377     mvncc   r1, #0                      @ (less than) r1<- -1
1378     moveq   r1, #0                      @ (equal) r1<- 0, trumps less than
1379 .LOP_CMPG_DOUBLE_finish:
1380     mov     r3, rINST, lsr #8           @ r3<- AA
1381     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1382     SET_VREG(r1, r3)                    @ vAA<- r1
1383     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1384     GOTO_OPCODE(ip)                     @ jump to next instruction
1385
1386
1387 /* ------------------------------ */
1388     .balign 64
1389 .L_OP_CMP_LONG: /* 0x31 */
1390 /* File: armv5te/OP_CMP_LONG.S */
1391     /*
1392      * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
1393      * register based on the results of the comparison.
1394      *
1395      * We load the full values with LDM, but in practice many values could
1396      * be resolved by only looking at the high word.  This could be made
1397      * faster or slower by splitting the LDM into a pair of LDRs.
1398      *
1399      * If we just wanted to set condition flags, we could do this:
1400      *  subs    ip, r0, r2
1401      *  sbcs    ip, r1, r3
1402      *  subeqs  ip, r0, r2
1403      * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
1404      * integer value, which we can do with 2 conditional mov/mvn instructions
1405      * (set 1, set -1; if they're equal we already have 0 in ip), giving
1406      * us a constant 5-cycle path plus a branch at the end to the
1407      * instruction epilogue code.  The multi-compare approach below needs
1408      * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
1409      * in the worst case (the 64-bit values are equal).
1410      */
1411     /* cmp-long vAA, vBB, vCC */
1412     FETCH(r0, 1)                        @ r0<- CCBB
1413     mov     r9, rINST, lsr #8           @ r9<- AA
1414     and     r2, r0, #255                @ r2<- BB
1415     mov     r3, r0, lsr #8              @ r3<- CC
1416     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
1417     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
1418     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1419     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
1420     cmp     r1, r3                      @ compare (vBB+1, vCC+1)
1421     blt     .LOP_CMP_LONG_less            @ signed compare on high part
1422     bgt     .LOP_CMP_LONG_greater
1423     subs    r1, r0, r2                  @ r1<- r0 - r2
1424     bhi     .LOP_CMP_LONG_greater         @ unsigned compare on low part
1425     bne     .LOP_CMP_LONG_less
1426     b       .LOP_CMP_LONG_finish          @ equal; r1 already holds 0
1427
1428 /* ------------------------------ */
1429     .balign 64
1430 .L_OP_IF_EQ: /* 0x32 */
1431 /* File: armv5te/OP_IF_EQ.S */
1432 /* File: armv5te/bincmp.S */
1433     /*
1434      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1435      * fragment that specifies the *reverse* comparison to perform, e.g.
1436      * for "if-le" you would use "gt".
1437      *
1438      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1439      */
1440     /* if-cmp vA, vB, +CCCC */
1441     mov     r0, rINST, lsr #8           @ r0<- A+
1442     mov     r1, rINST, lsr #12          @ r1<- B
1443     and     r0, r0, #15
1444     GET_VREG(r3, r1)                    @ r3<- vB
1445     GET_VREG(r2, r0)                    @ r2<- vA
1446     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1447     cmp     r2, r3                      @ compare (vA, vB)
1448     bne  1f                      @ branch to 1 if comparison failed
1449     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1450     movs    r9, r9, asl #1              @ convert to bytes, check sign
1451     bmi     common_backwardBranch       @ yes, do periodic checks
1452 1:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1453     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1454     GOTO_OPCODE(ip)                     @ jump to next instruction
1455
1456
1457
1458 /* ------------------------------ */
1459     .balign 64
1460 .L_OP_IF_NE: /* 0x33 */
1461 /* File: armv5te/OP_IF_NE.S */
1462 /* File: armv5te/bincmp.S */
1463     /*
1464      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1465      * fragment that specifies the *reverse* comparison to perform, e.g.
1466      * for "if-le" you would use "gt".
1467      *
1468      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1469      */
1470     /* if-cmp vA, vB, +CCCC */
1471     mov     r0, rINST, lsr #8           @ r0<- A+
1472     mov     r1, rINST, lsr #12          @ r1<- B
1473     and     r0, r0, #15
1474     GET_VREG(r3, r1)                    @ r3<- vB
1475     GET_VREG(r2, r0)                    @ r2<- vA
1476     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1477     cmp     r2, r3                      @ compare (vA, vB)
1478     beq  1f                      @ branch to 1 if comparison failed
1479     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1480     movs    r9, r9, asl #1              @ convert to bytes, check sign
1481     bmi     common_backwardBranch       @ yes, do periodic checks
1482 1:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1483     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1484     GOTO_OPCODE(ip)                     @ jump to next instruction
1485
1486
1487
1488 /* ------------------------------ */
1489     .balign 64
1490 .L_OP_IF_LT: /* 0x34 */
1491 /* File: armv5te/OP_IF_LT.S */
1492 /* File: armv5te/bincmp.S */
1493     /*
1494      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1495      * fragment that specifies the *reverse* comparison to perform, e.g.
1496      * for "if-le" you would use "gt".
1497      *
1498      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1499      */
1500     /* if-cmp vA, vB, +CCCC */
1501     mov     r0, rINST, lsr #8           @ r0<- A+
1502     mov     r1, rINST, lsr #12          @ r1<- B
1503     and     r0, r0, #15
1504     GET_VREG(r3, r1)                    @ r3<- vB
1505     GET_VREG(r2, r0)                    @ r2<- vA
1506     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1507     cmp     r2, r3                      @ compare (vA, vB)
1508     bge  1f                      @ branch to 1 if comparison failed
1509     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1510     movs    r9, r9, asl #1              @ convert to bytes, check sign
1511     bmi     common_backwardBranch       @ yes, do periodic checks
1512 1:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1513     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1514     GOTO_OPCODE(ip)                     @ jump to next instruction
1515
1516
1517
1518 /* ------------------------------ */
1519     .balign 64
1520 .L_OP_IF_GE: /* 0x35 */
1521 /* File: armv5te/OP_IF_GE.S */
1522 /* File: armv5te/bincmp.S */
1523     /*
1524      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1525      * fragment that specifies the *reverse* comparison to perform, e.g.
1526      * for "if-le" you would use "gt".
1527      *
1528      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1529      */
1530     /* if-cmp vA, vB, +CCCC */
1531     mov     r0, rINST, lsr #8           @ r0<- A+
1532     mov     r1, rINST, lsr #12          @ r1<- B
1533     and     r0, r0, #15
1534     GET_VREG(r3, r1)                    @ r3<- vB
1535     GET_VREG(r2, r0)                    @ r2<- vA
1536     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1537     cmp     r2, r3                      @ compare (vA, vB)
1538     blt  1f                      @ branch to 1 if comparison failed
1539     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1540     movs    r9, r9, asl #1              @ convert to bytes, check sign
1541     bmi     common_backwardBranch       @ yes, do periodic checks
1542 1:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1543     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1544     GOTO_OPCODE(ip)                     @ jump to next instruction
1545
1546
1547
1548 /* ------------------------------ */
1549     .balign 64
1550 .L_OP_IF_GT: /* 0x36 */
1551 /* File: armv5te/OP_IF_GT.S */
1552 /* File: armv5te/bincmp.S */
1553     /*
1554      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1555      * fragment that specifies the *reverse* comparison to perform, e.g.
1556      * for "if-le" you would use "gt".
1557      *
1558      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1559      */
1560     /* if-cmp vA, vB, +CCCC */
1561     mov     r0, rINST, lsr #8           @ r0<- A+
1562     mov     r1, rINST, lsr #12          @ r1<- B
1563     and     r0, r0, #15
1564     GET_VREG(r3, r1)                    @ r3<- vB
1565     GET_VREG(r2, r0)                    @ r2<- vA
1566     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1567     cmp     r2, r3                      @ compare (vA, vB)
1568     ble  1f                      @ branch to 1 if comparison failed
1569     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1570     movs    r9, r9, asl #1              @ convert to bytes, check sign
1571     bmi     common_backwardBranch       @ yes, do periodic checks
1572 1:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1573     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1574     GOTO_OPCODE(ip)                     @ jump to next instruction
1575
1576
1577
1578 /* ------------------------------ */
1579     .balign 64
1580 .L_OP_IF_LE: /* 0x37 */
1581 /* File: armv5te/OP_IF_LE.S */
1582 /* File: armv5te/bincmp.S */
1583     /*
1584      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1585      * fragment that specifies the *reverse* comparison to perform, e.g.
1586      * for "if-le" you would use "gt".
1587      *
1588      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1589      */
1590     /* if-cmp vA, vB, +CCCC */
1591     mov     r0, rINST, lsr #8           @ r0<- A+
1592     mov     r1, rINST, lsr #12          @ r1<- B
1593     and     r0, r0, #15
1594     GET_VREG(r3, r1)                    @ r3<- vB
1595     GET_VREG(r2, r0)                    @ r2<- vA
1596     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1597     cmp     r2, r3                      @ compare (vA, vB)
1598     bgt  1f                      @ branch to 1 if comparison failed
1599     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1600     movs    r9, r9, asl #1              @ convert to bytes, check sign
1601     bmi     common_backwardBranch       @ yes, do periodic checks
1602 1:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1603     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1604     GOTO_OPCODE(ip)                     @ jump to next instruction
1605
1606
1607
1608 /* ------------------------------ */
1609     .balign 64
1610 .L_OP_IF_EQZ: /* 0x38 */
1611 /* File: armv5te/OP_IF_EQZ.S */
1612 /* File: armv5te/zcmp.S */
1613     /*
1614      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1615      * fragment that specifies the *reverse* comparison to perform, e.g.
1616      * for "if-le" you would use "gt".
1617      *
1618      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1619      */
1620     /* if-cmp vAA, +BBBB */
1621     mov     r0, rINST, lsr #8           @ r0<- AA
1622     GET_VREG(r2, r0)                    @ r2<- vAA
1623     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1624     cmp     r2, #0                      @ compare (vA, 0)
1625     bne  1f                      @ branch to 1 if comparison failed
1626     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1627     movs    r9, r9, asl #1              @ convert to bytes, check sign
1628     bmi     common_backwardBranch       @ backward branch, do periodic checks
1629 1:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1630     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1631     GOTO_OPCODE(ip)                     @ jump to next instruction
1632
1633
1634
1635 /* ------------------------------ */
1636     .balign 64
1637 .L_OP_IF_NEZ: /* 0x39 */
1638 /* File: armv5te/OP_IF_NEZ.S */
1639 /* File: armv5te/zcmp.S */
1640     /*
1641      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1642      * fragment that specifies the *reverse* comparison to perform, e.g.
1643      * for "if-le" you would use "gt".
1644      *
1645      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1646      */
1647     /* if-cmp vAA, +BBBB */
1648     mov     r0, rINST, lsr #8           @ r0<- AA
1649     GET_VREG(r2, r0)                    @ r2<- vAA
1650     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1651     cmp     r2, #0                      @ compare (vA, 0)
1652     beq  1f                      @ branch to 1 if comparison failed
1653     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1654     movs    r9, r9, asl #1              @ convert to bytes, check sign
1655     bmi     common_backwardBranch       @ backward branch, do periodic checks
1656 1:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1657     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1658     GOTO_OPCODE(ip)                     @ jump to next instruction
1659
1660
1661
1662 /* ------------------------------ */
1663     .balign 64
1664 .L_OP_IF_LTZ: /* 0x3a */
1665 /* File: armv5te/OP_IF_LTZ.S */
1666 /* File: armv5te/zcmp.S */
1667     /*
1668      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1669      * fragment that specifies the *reverse* comparison to perform, e.g.
1670      * for "if-le" you would use "gt".
1671      *
1672      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1673      */
1674     /* if-cmp vAA, +BBBB */
1675     mov     r0, rINST, lsr #8           @ r0<- AA
1676     GET_VREG(r2, r0)                    @ r2<- vAA
1677     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1678     cmp     r2, #0                      @ compare (vA, 0)
1679     bge  1f                      @ branch to 1 if comparison failed
1680     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1681     movs    r9, r9, asl #1              @ convert to bytes, check sign
1682     bmi     common_backwardBranch       @ backward branch, do periodic checks
1683 1:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1684     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1685     GOTO_OPCODE(ip)                     @ jump to next instruction
1686
1687
1688
1689 /* ------------------------------ */
1690     .balign 64
1691 .L_OP_IF_GEZ: /* 0x3b */
1692 /* File: armv5te/OP_IF_GEZ.S */
1693 /* File: armv5te/zcmp.S */
1694     /*
1695      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1696      * fragment that specifies the *reverse* comparison to perform, e.g.
1697      * for "if-le" you would use "gt".
1698      *
1699      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1700      */
1701     /* if-cmp vAA, +BBBB */
1702     mov     r0, rINST, lsr #8           @ r0<- AA
1703     GET_VREG(r2, r0)                    @ r2<- vAA
1704     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1705     cmp     r2, #0                      @ compare (vA, 0)
1706     blt  1f                      @ branch to 1 if comparison failed
1707     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1708     movs    r9, r9, asl #1              @ convert to bytes, check sign
1709     bmi     common_backwardBranch       @ backward branch, do periodic checks
1710 1:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1711     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1712     GOTO_OPCODE(ip)                     @ jump to next instruction
1713
1714
1715
1716 /* ------------------------------ */
1717     .balign 64
1718 .L_OP_IF_GTZ: /* 0x3c */
1719 /* File: armv5te/OP_IF_GTZ.S */
1720 /* File: armv5te/zcmp.S */
1721     /*
1722      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1723      * fragment that specifies the *reverse* comparison to perform, e.g.
1724      * for "if-le" you would use "gt".
1725      *
1726      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1727      */
1728     /* if-cmp vAA, +BBBB */
1729     mov     r0, rINST, lsr #8           @ r0<- AA
1730     GET_VREG(r2, r0)                    @ r2<- vAA
1731     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1732     cmp     r2, #0                      @ compare (vA, 0)
1733     ble  1f                      @ branch to 1 if comparison failed
1734     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1735     movs    r9, r9, asl #1              @ convert to bytes, check sign
1736     bmi     common_backwardBranch       @ backward branch, do periodic checks
1737 1:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1738     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1739     GOTO_OPCODE(ip)                     @ jump to next instruction
1740
1741
1742
1743 /* ------------------------------ */
1744     .balign 64
1745 .L_OP_IF_LEZ: /* 0x3d */
1746 /* File: armv5te/OP_IF_LEZ.S */
1747 /* File: armv5te/zcmp.S */
1748     /*
1749      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1750      * fragment that specifies the *reverse* comparison to perform, e.g.
1751      * for "if-le" you would use "gt".
1752      *
1753      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1754      */
1755     /* if-cmp vAA, +BBBB */
1756     mov     r0, rINST, lsr #8           @ r0<- AA
1757     GET_VREG(r2, r0)                    @ r2<- vAA
1758     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1759     cmp     r2, #0                      @ compare (vA, 0)
1760     bgt  1f                      @ branch to 1 if comparison failed
1761     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1762     movs    r9, r9, asl #1              @ convert to bytes, check sign
1763     bmi     common_backwardBranch       @ backward branch, do periodic checks
1764 1:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1765     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1766     GOTO_OPCODE(ip)                     @ jump to next instruction
1767
1768
1769
1770 /* ------------------------------ */
1771     .balign 64
1772 .L_OP_UNUSED_3E: /* 0x3e */
1773 /* File: armv5te/OP_UNUSED_3E.S */
1774 /* File: armv5te/unused.S */
1775     bl      common_abort
1776
1777
1778
1779 /* ------------------------------ */
1780     .balign 64
1781 .L_OP_UNUSED_3F: /* 0x3f */
1782 /* File: armv5te/OP_UNUSED_3F.S */
1783 /* File: armv5te/unused.S */
1784     bl      common_abort
1785
1786
1787
1788 /* ------------------------------ */
1789     .balign 64
1790 .L_OP_UNUSED_40: /* 0x40 */
1791 /* File: armv5te/OP_UNUSED_40.S */
1792 /* File: armv5te/unused.S */
1793     bl      common_abort
1794
1795
1796
1797 /* ------------------------------ */
1798     .balign 64
1799 .L_OP_UNUSED_41: /* 0x41 */
1800 /* File: armv5te/OP_UNUSED_41.S */
1801 /* File: armv5te/unused.S */
1802     bl      common_abort
1803
1804
1805
1806 /* ------------------------------ */
1807     .balign 64
1808 .L_OP_UNUSED_42: /* 0x42 */
1809 /* File: armv5te/OP_UNUSED_42.S */
1810 /* File: armv5te/unused.S */
1811     bl      common_abort
1812
1813
1814
1815 /* ------------------------------ */
1816     .balign 64
1817 .L_OP_UNUSED_43: /* 0x43 */
1818 /* File: armv5te/OP_UNUSED_43.S */
1819 /* File: armv5te/unused.S */
1820     bl      common_abort
1821
1822
1823
1824 /* ------------------------------ */
1825     .balign 64
1826 .L_OP_AGET: /* 0x44 */
1827 /* File: armv5te/OP_AGET.S */
1828     /*
1829      * Array get, 32 bits or less.  vAA <- vBB[vCC].
1830      *
1831      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
1832      * instructions.  We use a pair of FETCH_Bs instead.
1833      *
1834      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1835      */
1836     /* op vAA, vBB, vCC */
1837     FETCH_B(r2, 1, 0)                   @ r2<- BB
1838     mov     r9, rINST, lsr #8           @ r9<- AA
1839     FETCH_B(r3, 1, 1)                   @ r3<- CC
1840     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
1841     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
1842     cmp     r0, #0                      @ null array object?
1843     beq     common_errNullObject        @ yes, bail
1844     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
1845     add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
1846     cmp     r1, r3                      @ compare unsigned index, length
1847     bcs     common_errArrayIndex        @ index >= length, bail
1848     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1849     ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
1850     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1851     SET_VREG(r2, r9)                    @ vAA<- r2
1852     GOTO_OPCODE(ip)                     @ jump to next instruction
1853
1854
1855 /* ------------------------------ */
1856     .balign 64
1857 .L_OP_AGET_WIDE: /* 0x45 */
1858 /* File: armv4t/OP_AGET_WIDE.S */
1859     /*
1860      * Array get, 64 bits.  vAA <- vBB[vCC].
1861      *
1862      * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD.
1863      */
1864     /* aget-wide vAA, vBB, vCC */
1865     FETCH(r0, 1)                        @ r0<- CCBB
1866     mov     r9, rINST, lsr #8           @ r9<- AA
1867     and     r2, r0, #255                @ r2<- BB
1868     mov     r3, r0, lsr #8              @ r3<- CC
1869     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
1870     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
1871     cmp     r0, #0                      @ null array object?
1872     beq     common_errNullObject        @ yes, bail
1873     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
1874     add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
1875     cmp     r1, r3                      @ compare unsigned index, length
1876     bcc     .LOP_AGET_WIDE_finish          @ okay, continue below
1877     b       common_errArrayIndex        @ index >= length, bail
1878     @ May want to swap the order of these two branches depending on how the
1879     @ branch prediction (if any) handles conditional forward branches vs.
1880     @ unconditional forward branches.
1881
1882 /* ------------------------------ */
1883     .balign 64
1884 .L_OP_AGET_OBJECT: /* 0x46 */
1885 /* File: armv5te/OP_AGET_OBJECT.S */
1886 /* File: armv5te/OP_AGET.S */
1887     /*
1888      * Array get, 32 bits or less.  vAA <- vBB[vCC].
1889      *
1890      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
1891      * instructions.  We use a pair of FETCH_Bs instead.
1892      *
1893      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1894      */
1895     /* op vAA, vBB, vCC */
1896     FETCH_B(r2, 1, 0)                   @ r2<- BB
1897     mov     r9, rINST, lsr #8           @ r9<- AA
1898     FETCH_B(r3, 1, 1)                   @ r3<- CC
1899     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
1900     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
1901     cmp     r0, #0                      @ null array object?
1902     beq     common_errNullObject        @ yes, bail
1903     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
1904     add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
1905     cmp     r1, r3                      @ compare unsigned index, length
1906     bcs     common_errArrayIndex        @ index >= length, bail
1907     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1908     ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
1909     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1910     SET_VREG(r2, r9)                    @ vAA<- r2
1911     GOTO_OPCODE(ip)                     @ jump to next instruction
1912
1913
1914
1915 /* ------------------------------ */
1916     .balign 64
1917 .L_OP_AGET_BOOLEAN: /* 0x47 */
1918 /* File: armv5te/OP_AGET_BOOLEAN.S */
1919 /* File: armv5te/OP_AGET.S */
1920     /*
1921      * Array get, 32 bits or less.  vAA <- vBB[vCC].
1922      *
1923      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
1924      * instructions.  We use a pair of FETCH_Bs instead.
1925      *
1926      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1927      */
1928     /* op vAA, vBB, vCC */
1929     FETCH_B(r2, 1, 0)                   @ r2<- BB
1930     mov     r9, rINST, lsr #8           @ r9<- AA
1931     FETCH_B(r3, 1, 1)                   @ r3<- CC
1932     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
1933     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
1934     cmp     r0, #0                      @ null array object?
1935     beq     common_errNullObject        @ yes, bail
1936     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
1937     add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
1938     cmp     r1, r3                      @ compare unsigned index, length
1939     bcs     common_errArrayIndex        @ index >= length, bail
1940     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1941     ldrb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
1942     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1943     SET_VREG(r2, r9)                    @ vAA<- r2
1944     GOTO_OPCODE(ip)                     @ jump to next instruction
1945
1946
1947
1948 /* ------------------------------ */
1949     .balign 64
1950 .L_OP_AGET_BYTE: /* 0x48 */
1951 /* File: armv5te/OP_AGET_BYTE.S */
1952 /* File: armv5te/OP_AGET.S */
1953     /*
1954      * Array get, 32 bits or less.  vAA <- vBB[vCC].
1955      *
1956      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
1957      * instructions.  We use a pair of FETCH_Bs instead.
1958      *
1959      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1960      */
1961     /* op vAA, vBB, vCC */
1962     FETCH_B(r2, 1, 0)                   @ r2<- BB
1963     mov     r9, rINST, lsr #8           @ r9<- AA
1964     FETCH_B(r3, 1, 1)                   @ r3<- CC
1965     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
1966     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
1967     cmp     r0, #0                      @ null array object?
1968     beq     common_errNullObject        @ yes, bail
1969     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
1970     add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
1971     cmp     r1, r3                      @ compare unsigned index, length
1972     bcs     common_errArrayIndex        @ index >= length, bail
1973     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1974     ldrsb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
1975     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1976     SET_VREG(r2, r9)                    @ vAA<- r2
1977     GOTO_OPCODE(ip)                     @ jump to next instruction
1978
1979
1980
1981 /* ------------------------------ */
1982     .balign 64
1983 .L_OP_AGET_CHAR: /* 0x49 */
1984 /* File: armv5te/OP_AGET_CHAR.S */
1985 /* File: armv5te/OP_AGET.S */
1986     /*
1987      * Array get, 32 bits or less.  vAA <- vBB[vCC].
1988      *
1989      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
1990      * instructions.  We use a pair of FETCH_Bs instead.
1991      *
1992      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1993      */
1994     /* op vAA, vBB, vCC */
1995     FETCH_B(r2, 1, 0)                   @ r2<- BB
1996     mov     r9, rINST, lsr #8           @ r9<- AA
1997     FETCH_B(r3, 1, 1)                   @ r3<- CC
1998     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
1999     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2000     cmp     r0, #0                      @ null array object?
2001     beq     common_errNullObject        @ yes, bail
2002     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2003     add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2004     cmp     r1, r3                      @ compare unsigned index, length
2005     bcs     common_errArrayIndex        @ index >= length, bail
2006     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2007     ldrh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2008     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2009     SET_VREG(r2, r9)                    @ vAA<- r2
2010     GOTO_OPCODE(ip)                     @ jump to next instruction
2011
2012
2013
2014 /* ------------------------------ */
2015     .balign 64
2016 .L_OP_AGET_SHORT: /* 0x4a */
2017 /* File: armv5te/OP_AGET_SHORT.S */
2018 /* File: armv5te/OP_AGET.S */
2019     /*
2020      * Array get, 32 bits or less.  vAA <- vBB[vCC].
2021      *
2022      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2023      * instructions.  We use a pair of FETCH_Bs instead.
2024      *
2025      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2026      */
2027     /* op vAA, vBB, vCC */
2028     FETCH_B(r2, 1, 0)                   @ r2<- BB
2029     mov     r9, rINST, lsr #8           @ r9<- AA
2030     FETCH_B(r3, 1, 1)                   @ r3<- CC
2031     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2032     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2033     cmp     r0, #0                      @ null array object?
2034     beq     common_errNullObject        @ yes, bail
2035     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2036     add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2037     cmp     r1, r3                      @ compare unsigned index, length
2038     bcs     common_errArrayIndex        @ index >= length, bail
2039     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2040     ldrsh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2041     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2042     SET_VREG(r2, r9)                    @ vAA<- r2
2043     GOTO_OPCODE(ip)                     @ jump to next instruction
2044
2045
2046
2047 /* ------------------------------ */
2048     .balign 64
2049 .L_OP_APUT: /* 0x4b */
2050 /* File: armv5te/OP_APUT.S */
2051     /*
2052      * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2053      *
2054      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2055      * instructions.  We use a pair of FETCH_Bs instead.
2056      *
2057      * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2058      */
2059     /* op vAA, vBB, vCC */
2060     FETCH_B(r2, 1, 0)                   @ r2<- BB
2061     mov     r9, rINST, lsr #8           @ r9<- AA
2062     FETCH_B(r3, 1, 1)                   @ r3<- CC
2063     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2064     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2065     cmp     r0, #0                      @ null array object?
2066     beq     common_errNullObject        @ yes, bail
2067     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2068     add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2069     cmp     r1, r3                      @ compare unsigned index, length
2070     bcs     common_errArrayIndex        @ index >= length, bail
2071     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2072     GET_VREG(r2, r9)                    @ r2<- vAA
2073     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2074     str  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2075     GOTO_OPCODE(ip)                     @ jump to next instruction
2076
2077
2078 /* ------------------------------ */
2079     .balign 64
2080 .L_OP_APUT_WIDE: /* 0x4c */
2081 /* File: armv4t/OP_APUT_WIDE.S */
2082     /*
2083      * Array put, 64 bits.  vBB[vCC] <- vAA.
2084      */
2085     /* aput-wide vAA, vBB, vCC */
2086     FETCH(r0, 1)                        @ r0<- CCBB
2087     mov     r9, rINST, lsr #8           @ r9<- AA
2088     and     r2, r0, #255                @ r2<- BB
2089     mov     r3, r0, lsr #8              @ r3<- CC
2090     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2091     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2092     cmp     r0, #0                      @ null array object?
2093     beq     common_errNullObject        @ yes, bail
2094     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2095     add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2096     cmp     r1, r3                      @ compare unsigned index, length
2097     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2098     bcc     .LOP_APUT_WIDE_finish          @ okay, continue below
2099     b       common_errArrayIndex        @ index >= length, bail
2100     @ May want to swap the order of these two branches depending on how the
2101     @ branch prediction (if any) handles conditional forward branches vs.
2102     @ unconditional forward branches.
2103
2104 /* ------------------------------ */
2105     .balign 64
2106 .L_OP_APUT_OBJECT: /* 0x4d */
2107 /* File: armv5te/OP_APUT_OBJECT.S */
2108     /*
2109      * Store an object into an array.  vBB[vCC] <- vAA.
2110      *
2111      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2112      * instructions.  We use a pair of FETCH_Bs instead.
2113      */
2114     /* op vAA, vBB, vCC */
2115     FETCH(r0, 1)                        @ r0<- CCBB
2116     mov     r9, rINST, lsr #8           @ r9<- AA
2117     and     r2, r0, #255                @ r2<- BB
2118     mov     r3, r0, lsr #8              @ r3<- CC
2119     GET_VREG(r1, r2)                    @ r1<- vBB (array object)
2120     GET_VREG(r0, r3)                    @ r0<- vCC (requested index)
2121     cmp     r1, #0                      @ null array object?
2122     GET_VREG(r9, r9)                    @ r9<- vAA
2123     beq     common_errNullObject        @ yes, bail
2124     ldr     r3, [r1, #offArrayObject_length]    @ r3<- arrayObj->length
2125     add     r10, r1, r0, lsl #2         @ r10<- arrayObj + index*width
2126     cmp     r0, r3                      @ compare unsigned index, length
2127     bcc     .LOP_APUT_OBJECT_finish          @ we're okay, continue on
2128     b       common_errArrayIndex        @ index >= length, bail
2129
2130
2131 /* ------------------------------ */
2132     .balign 64
2133 .L_OP_APUT_BOOLEAN: /* 0x4e */
2134 /* File: armv5te/OP_APUT_BOOLEAN.S */
2135 /* File: armv5te/OP_APUT.S */
2136     /*
2137      * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2138      *
2139      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2140      * instructions.  We use a pair of FETCH_Bs instead.
2141      *
2142      * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2143      */
2144     /* op vAA, vBB, vCC */
2145     FETCH_B(r2, 1, 0)                   @ r2<- BB
2146     mov     r9, rINST, lsr #8           @ r9<- AA
2147     FETCH_B(r3, 1, 1)                   @ r3<- CC
2148     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2149     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2150     cmp     r0, #0                      @ null array object?
2151     beq     common_errNullObject        @ yes, bail
2152     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2153     add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2154     cmp     r1, r3                      @ compare unsigned index, length
2155     bcs     common_errArrayIndex        @ index >= length, bail
2156     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2157     GET_VREG(r2, r9)                    @ r2<- vAA
2158     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2159     strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2160     GOTO_OPCODE(ip)                     @ jump to next instruction
2161
2162
2163
2164 /* ------------------------------ */
2165     .balign 64
2166 .L_OP_APUT_BYTE: /* 0x4f */
2167 /* File: armv5te/OP_APUT_BYTE.S */
2168 /* File: armv5te/OP_APUT.S */
2169     /*
2170      * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2171      *
2172      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2173      * instructions.  We use a pair of FETCH_Bs instead.
2174      *
2175      * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2176      */
2177     /* op vAA, vBB, vCC */
2178     FETCH_B(r2, 1, 0)                   @ r2<- BB
2179     mov     r9, rINST, lsr #8           @ r9<- AA
2180     FETCH_B(r3, 1, 1)                   @ r3<- CC
2181     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2182     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2183     cmp     r0, #0                      @ null array object?
2184     beq     common_errNullObject        @ yes, bail
2185     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2186     add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2187     cmp     r1, r3                      @ compare unsigned index, length
2188     bcs     common_errArrayIndex        @ index >= length, bail
2189     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2190     GET_VREG(r2, r9)                    @ r2<- vAA
2191     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2192     strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2193     GOTO_OPCODE(ip)                     @ jump to next instruction
2194
2195
2196
2197 /* ------------------------------ */
2198     .balign 64
2199 .L_OP_APUT_CHAR: /* 0x50 */
2200 /* File: armv5te/OP_APUT_CHAR.S */
2201 /* File: armv5te/OP_APUT.S */
2202     /*
2203      * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2204      *
2205      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2206      * instructions.  We use a pair of FETCH_Bs instead.
2207      *
2208      * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2209      */
2210     /* op vAA, vBB, vCC */
2211     FETCH_B(r2, 1, 0)                   @ r2<- BB
2212     mov     r9, rINST, lsr #8           @ r9<- AA
2213     FETCH_B(r3, 1, 1)                   @ r3<- CC
2214     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2215     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2216     cmp     r0, #0                      @ null array object?
2217     beq     common_errNullObject        @ yes, bail
2218     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2219     add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2220     cmp     r1, r3                      @ compare unsigned index, length
2221     bcs     common_errArrayIndex        @ index >= length, bail
2222     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2223     GET_VREG(r2, r9)                    @ r2<- vAA
2224     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2225     strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2226     GOTO_OPCODE(ip)                     @ jump to next instruction
2227
2228
2229
2230 /* ------------------------------ */
2231     .balign 64
2232 .L_OP_APUT_SHORT: /* 0x51 */
2233 /* File: armv5te/OP_APUT_SHORT.S */
2234 /* File: armv5te/OP_APUT.S */
2235     /*
2236      * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2237      *
2238      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2239      * instructions.  We use a pair of FETCH_Bs instead.
2240      *
2241      * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2242      */
2243     /* op vAA, vBB, vCC */
2244     FETCH_B(r2, 1, 0)                   @ r2<- BB
2245     mov     r9, rINST, lsr #8           @ r9<- AA
2246     FETCH_B(r3, 1, 1)                   @ r3<- CC
2247     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2248     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2249     cmp     r0, #0                      @ null array object?
2250     beq     common_errNullObject        @ yes, bail
2251     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2252     add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2253     cmp     r1, r3                      @ compare unsigned index, length
2254     bcs     common_errArrayIndex        @ index >= length, bail
2255     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2256     GET_VREG(r2, r9)                    @ r2<- vAA
2257     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2258     strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2259     GOTO_OPCODE(ip)                     @ jump to next instruction
2260
2261
2262
2263 /* ------------------------------ */
2264     .balign 64
2265 .L_OP_IGET: /* 0x52 */
2266 /* File: armv5te/OP_IGET.S */
2267     /*
2268      * General 32-bit instance field get.
2269      *
2270      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2271      */
2272     /* op vA, vB, field@CCCC */
2273     mov     r0, rINST, lsr #12          @ r0<- B
2274     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2275     FETCH(r1, 1)                        @ r1<- field ref CCCC
2276     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2277     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2278     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2279     cmp     r0, #0                      @ is resolved entry null?
2280     bne     .LOP_IGET_finish          @ no, already resolved
2281 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2282     EXPORT_PC()                         @ resolve() could throw
2283     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2284     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2285     cmp     r0, #0
2286     bne     .LOP_IGET_finish
2287     b       common_exceptionThrown
2288
2289 /* ------------------------------ */
2290     .balign 64
2291 .L_OP_IGET_WIDE: /* 0x53 */
2292 /* File: armv4t/OP_IGET_WIDE.S */
2293     /*
2294      * Wide 32-bit instance field get.
2295      */
2296     /* iget-wide vA, vB, field@CCCC */
2297     mov     r0, rINST, lsr #12          @ r0<- B
2298     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2299     FETCH(r1, 1)                        @ r1<- field ref CCCC
2300     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2301     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2302     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2303     cmp     r0, #0                      @ is resolved entry null?
2304     bne     .LOP_IGET_WIDE_finish          @ no, already resolved
2305 8:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2306     EXPORT_PC()                         @ resolve() could throw
2307     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2308     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2309     cmp     r0, #0
2310     bne     .LOP_IGET_WIDE_finish
2311     b       common_exceptionThrown
2312
2313 /* ------------------------------ */
2314     .balign 64
2315 .L_OP_IGET_OBJECT: /* 0x54 */
2316 /* File: armv5te/OP_IGET_OBJECT.S */
2317 /* File: armv5te/OP_IGET.S */
2318     /*
2319      * General 32-bit instance field get.
2320      *
2321      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2322      */
2323     /* op vA, vB, field@CCCC */
2324     mov     r0, rINST, lsr #12          @ r0<- B
2325     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2326     FETCH(r1, 1)                        @ r1<- field ref CCCC
2327     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2328     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2329     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2330     cmp     r0, #0                      @ is resolved entry null?
2331     bne     .LOP_IGET_OBJECT_finish          @ no, already resolved
2332 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2333     EXPORT_PC()                         @ resolve() could throw
2334     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2335     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2336     cmp     r0, #0
2337     bne     .LOP_IGET_OBJECT_finish
2338     b       common_exceptionThrown
2339
2340
2341 /* ------------------------------ */
2342     .balign 64
2343 .L_OP_IGET_BOOLEAN: /* 0x55 */
2344 /* File: armv5te/OP_IGET_BOOLEAN.S */
2345 @include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" }
2346 /* File: armv5te/OP_IGET.S */
2347     /*
2348      * General 32-bit instance field get.
2349      *
2350      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2351      */
2352     /* op vA, vB, field@CCCC */
2353     mov     r0, rINST, lsr #12          @ r0<- B
2354     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2355     FETCH(r1, 1)                        @ r1<- field ref CCCC
2356     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2357     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2358     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2359     cmp     r0, #0                      @ is resolved entry null?
2360     bne     .LOP_IGET_BOOLEAN_finish          @ no, already resolved
2361 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2362     EXPORT_PC()                         @ resolve() could throw
2363     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2364     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2365     cmp     r0, #0
2366     bne     .LOP_IGET_BOOLEAN_finish
2367     b       common_exceptionThrown
2368
2369
2370 /* ------------------------------ */
2371     .balign 64
2372 .L_OP_IGET_BYTE: /* 0x56 */
2373 /* File: armv5te/OP_IGET_BYTE.S */
2374 @include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" }
2375 /* File: armv5te/OP_IGET.S */
2376     /*
2377      * General 32-bit instance field get.
2378      *
2379      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2380      */
2381     /* op vA, vB, field@CCCC */
2382     mov     r0, rINST, lsr #12          @ r0<- B
2383     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2384     FETCH(r1, 1)                        @ r1<- field ref CCCC
2385     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2386     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2387     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2388     cmp     r0, #0                      @ is resolved entry null?
2389     bne     .LOP_IGET_BYTE_finish          @ no, already resolved
2390 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2391     EXPORT_PC()                         @ resolve() could throw
2392     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2393     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2394     cmp     r0, #0
2395     bne     .LOP_IGET_BYTE_finish
2396     b       common_exceptionThrown
2397
2398
2399 /* ------------------------------ */
2400     .balign 64
2401 .L_OP_IGET_CHAR: /* 0x57 */
2402 /* File: armv5te/OP_IGET_CHAR.S */
2403 @include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" }
2404 /* File: armv5te/OP_IGET.S */
2405     /*
2406      * General 32-bit instance field get.
2407      *
2408      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2409      */
2410     /* op vA, vB, field@CCCC */
2411     mov     r0, rINST, lsr #12          @ r0<- B
2412     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2413     FETCH(r1, 1)                        @ r1<- field ref CCCC
2414     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2415     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2416     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2417     cmp     r0, #0                      @ is resolved entry null?
2418     bne     .LOP_IGET_CHAR_finish          @ no, already resolved
2419 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2420     EXPORT_PC()                         @ resolve() could throw
2421     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2422     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2423     cmp     r0, #0
2424     bne     .LOP_IGET_CHAR_finish
2425     b       common_exceptionThrown
2426
2427
2428 /* ------------------------------ */
2429     .balign 64
2430 .L_OP_IGET_SHORT: /* 0x58 */
2431 /* File: armv5te/OP_IGET_SHORT.S */
2432 @include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" }
2433 /* File: armv5te/OP_IGET.S */
2434     /*
2435      * General 32-bit instance field get.
2436      *
2437      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2438      */
2439     /* op vA, vB, field@CCCC */
2440     mov     r0, rINST, lsr #12          @ r0<- B
2441     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2442     FETCH(r1, 1)                        @ r1<- field ref CCCC
2443     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2444     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2445     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2446     cmp     r0, #0                      @ is resolved entry null?
2447     bne     .LOP_IGET_SHORT_finish          @ no, already resolved
2448 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2449     EXPORT_PC()                         @ resolve() could throw
2450     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2451     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2452     cmp     r0, #0
2453     bne     .LOP_IGET_SHORT_finish
2454     b       common_exceptionThrown
2455
2456
2457 /* ------------------------------ */
2458     .balign 64
2459 .L_OP_IPUT: /* 0x59 */
2460 /* File: armv5te/OP_IPUT.S */
2461     /*
2462      * General 32-bit instance field put.
2463      *
2464      * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2465      */
2466     /* op vA, vB, field@CCCC */
2467     mov     r0, rINST, lsr #12          @ r0<- B
2468     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2469     FETCH(r1, 1)                        @ r1<- field ref CCCC
2470     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2471     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2472     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2473     cmp     r0, #0                      @ is resolved entry null?
2474     bne     .LOP_IPUT_finish          @ no, already resolved
2475 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2476     EXPORT_PC()                         @ resolve() could throw
2477     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2478     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2479     cmp     r0, #0                      @ success?
2480     bne     .LOP_IPUT_finish          @ yes, finish up
2481     b       common_exceptionThrown
2482
2483 /* ------------------------------ */
2484     .balign 64
2485 .L_OP_IPUT_WIDE: /* 0x5a */
2486 /* File: armv4t/OP_IPUT_WIDE.S */
2487     /* iput-wide vA, vB, field@CCCC */
2488     mov     r0, rINST, lsr #12          @ r0<- B
2489     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2490     FETCH(r1, 1)                        @ r1<- field ref CCCC
2491     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2492     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2493     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2494     cmp     r0, #0                      @ is resolved entry null?
2495     bne     .LOP_IPUT_WIDE_finish          @ no, already resolved
2496 8:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2497     EXPORT_PC()                         @ resolve() could throw
2498     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2499     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2500     cmp     r0, #0                      @ success?
2501     bne     .LOP_IPUT_WIDE_finish          @ yes, finish up
2502     b       common_exceptionThrown
2503
2504 /* ------------------------------ */
2505     .balign 64
2506 .L_OP_IPUT_OBJECT: /* 0x5b */
2507 /* File: armv5te/OP_IPUT_OBJECT.S */
2508 /* File: armv5te/OP_IPUT.S */
2509     /*
2510      * General 32-bit instance field put.
2511      *
2512      * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2513      */
2514     /* op vA, vB, field@CCCC */
2515     mov     r0, rINST, lsr #12          @ r0<- B
2516     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2517     FETCH(r1, 1)                        @ r1<- field ref CCCC
2518     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2519     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2520     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2521     cmp     r0, #0                      @ is resolved entry null?
2522     bne     .LOP_IPUT_OBJECT_finish          @ no, already resolved
2523 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2524     EXPORT_PC()                         @ resolve() could throw
2525     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2526     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2527     cmp     r0, #0                      @ success?
2528     bne     .LOP_IPUT_OBJECT_finish          @ yes, finish up
2529     b       common_exceptionThrown
2530
2531
2532 /* ------------------------------ */
2533     .balign 64
2534 .L_OP_IPUT_BOOLEAN: /* 0x5c */
2535 /* File: armv5te/OP_IPUT_BOOLEAN.S */
2536 @include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" }
2537 /* File: armv5te/OP_IPUT.S */
2538     /*
2539      * General 32-bit instance field put.
2540      *
2541      * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2542      */
2543     /* op vA, vB, field@CCCC */
2544     mov     r0, rINST, lsr #12          @ r0<- B
2545     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2546     FETCH(r1, 1)                        @ r1<- field ref CCCC
2547     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2548     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2549     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2550     cmp     r0, #0                      @ is resolved entry null?
2551     bne     .LOP_IPUT_BOOLEAN_finish          @ no, already resolved
2552 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2553     EXPORT_PC()                         @ resolve() could throw
2554     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2555     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2556     cmp     r0, #0                      @ success?
2557     bne     .LOP_IPUT_BOOLEAN_finish          @ yes, finish up
2558     b       common_exceptionThrown
2559
2560
2561 /* ------------------------------ */
2562     .balign 64
2563 .L_OP_IPUT_BYTE: /* 0x5d */
2564 /* File: armv5te/OP_IPUT_BYTE.S */
2565 @include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" }
2566 /* File: armv5te/OP_IPUT.S */
2567     /*
2568      * General 32-bit instance field put.
2569      *
2570      * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2571      */
2572     /* op vA, vB, field@CCCC */
2573     mov     r0, rINST, lsr #12          @ r0<- B
2574     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2575     FETCH(r1, 1)                        @ r1<- field ref CCCC
2576     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2577     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2578     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2579     cmp     r0, #0                      @ is resolved entry null?
2580     bne     .LOP_IPUT_BYTE_finish          @ no, already resolved
2581 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2582     EXPORT_PC()                         @ resolve() could throw
2583     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2584     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2585     cmp     r0, #0                      @ success?
2586     bne     .LOP_IPUT_BYTE_finish          @ yes, finish up
2587     b       common_exceptionThrown
2588
2589
2590 /* ------------------------------ */
2591     .balign 64
2592 .L_OP_IPUT_CHAR: /* 0x5e */
2593 /* File: armv5te/OP_IPUT_CHAR.S */
2594 @include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" }
2595 /* File: armv5te/OP_IPUT.S */
2596     /*
2597      * General 32-bit instance field put.
2598      *
2599      * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2600      */
2601     /* op vA, vB, field@CCCC */
2602     mov     r0, rINST, lsr #12          @ r0<- B
2603     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2604     FETCH(r1, 1)                        @ r1<- field ref CCCC
2605     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2606     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2607     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2608     cmp     r0, #0                      @ is resolved entry null?
2609     bne     .LOP_IPUT_CHAR_finish          @ no, already resolved
2610 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2611     EXPORT_PC()                         @ resolve() could throw
2612     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2613     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2614     cmp     r0, #0                      @ success?
2615     bne     .LOP_IPUT_CHAR_finish          @ yes, finish up
2616     b       common_exceptionThrown
2617
2618
2619 /* ------------------------------ */
2620     .balign 64
2621 .L_OP_IPUT_SHORT: /* 0x5f */
2622 /* File: armv5te/OP_IPUT_SHORT.S */
2623 @include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" }
2624 /* File: armv5te/OP_IPUT.S */
2625     /*
2626      * General 32-bit instance field put.
2627      *
2628      * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2629      */
2630     /* op vA, vB, field@CCCC */
2631     mov     r0, rINST, lsr #12          @ r0<- B
2632     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2633     FETCH(r1, 1)                        @ r1<- field ref CCCC
2634     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2635     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2636     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2637     cmp     r0, #0                      @ is resolved entry null?
2638     bne     .LOP_IPUT_SHORT_finish          @ no, already resolved
2639 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2640     EXPORT_PC()                         @ resolve() could throw
2641     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2642     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2643     cmp     r0, #0                      @ success?
2644     bne     .LOP_IPUT_SHORT_finish          @ yes, finish up
2645     b       common_exceptionThrown
2646
2647
2648 /* ------------------------------ */
2649     .balign 64
2650 .L_OP_SGET: /* 0x60 */
2651 /* File: armv5te/OP_SGET.S */
2652     /*
2653      * General 32-bit SGET handler.
2654      *
2655      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2656      */
2657     /* op vAA, field@BBBB */
2658     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2659     FETCH(r1, 1)                        @ r1<- field ref BBBB
2660     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2661     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2662     cmp     r0, #0                      @ is resolved entry null?
2663     beq     .LOP_SGET_resolve         @ yes, do resolve
2664 .LOP_SGET_finish: @ field ptr in r0
2665     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2666     mov     r2, rINST, lsr #8           @ r2<- AA
2667     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2668     SET_VREG(r1, r2)                    @ fp[AA]<- r1
2669     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2670     GOTO_OPCODE(ip)                     @ jump to next instruction
2671
2672 /* ------------------------------ */
2673     .balign 64
2674 .L_OP_SGET_WIDE: /* 0x61 */
2675 /* File: armv4t/OP_SGET_WIDE.S */
2676     /*
2677      * 64-bit SGET handler.
2678      */
2679     /* sget-wide vAA, field@BBBB */
2680     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2681     FETCH(r1, 1)                        @ r1<- field ref BBBB
2682     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2683     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2684     cmp     r0, #0                      @ is resolved entry null?
2685     beq     .LOP_SGET_WIDE_resolve         @ yes, do resolve
2686 .LOP_SGET_WIDE_finish:
2687     mov     r1, rINST, lsr #8           @ r1<- AA
2688     add     r0, r0, #offStaticField_value
2689     ldmia   r0, {r2-r3}                 @ r2/r3<- field value (aligned)
2690     add     r1, rFP, r1, lsl #2         @ r1<- &fp[AA]
2691     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2692     stmia   r1, {r2-r3}                 @ vAA/vAA+1<- r2/r3
2693     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2694     GOTO_OPCODE(ip)                     @ jump to next instruction
2695
2696 /* ------------------------------ */
2697     .balign 64
2698 .L_OP_SGET_OBJECT: /* 0x62 */
2699 /* File: armv5te/OP_SGET_OBJECT.S */
2700 /* File: armv5te/OP_SGET.S */
2701     /*
2702      * General 32-bit SGET handler.
2703      *
2704      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2705      */
2706     /* op vAA, field@BBBB */
2707     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2708     FETCH(r1, 1)                        @ r1<- field ref BBBB
2709     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2710     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2711     cmp     r0, #0                      @ is resolved entry null?
2712     beq     .LOP_SGET_OBJECT_resolve         @ yes, do resolve
2713 .LOP_SGET_OBJECT_finish: @ field ptr in r0
2714     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2715     mov     r2, rINST, lsr #8           @ r2<- AA
2716     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2717     SET_VREG(r1, r2)                    @ fp[AA]<- r1
2718     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2719     GOTO_OPCODE(ip)                     @ jump to next instruction
2720
2721
2722 /* ------------------------------ */
2723     .balign 64
2724 .L_OP_SGET_BOOLEAN: /* 0x63 */
2725 /* File: armv5te/OP_SGET_BOOLEAN.S */
2726 /* File: armv5te/OP_SGET.S */
2727     /*
2728      * General 32-bit SGET handler.
2729      *
2730      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2731      */
2732     /* op vAA, field@BBBB */
2733     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2734     FETCH(r1, 1)                        @ r1<- field ref BBBB
2735     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2736     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2737     cmp     r0, #0                      @ is resolved entry null?
2738     beq     .LOP_SGET_BOOLEAN_resolve         @ yes, do resolve
2739 .LOP_SGET_BOOLEAN_finish: @ field ptr in r0
2740     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2741     mov     r2, rINST, lsr #8           @ r2<- AA
2742     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2743     SET_VREG(r1, r2)                    @ fp[AA]<- r1
2744     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2745     GOTO_OPCODE(ip)                     @ jump to next instruction
2746
2747
2748 /* ------------------------------ */
2749     .balign 64
2750 .L_OP_SGET_BYTE: /* 0x64 */
2751 /* File: armv5te/OP_SGET_BYTE.S */
2752 /* File: armv5te/OP_SGET.S */
2753     /*
2754      * General 32-bit SGET handler.
2755      *
2756      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2757      */
2758     /* op vAA, field@BBBB */
2759     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2760     FETCH(r1, 1)                        @ r1<- field ref BBBB
2761     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2762     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2763     cmp     r0, #0                      @ is resolved entry null?
2764     beq     .LOP_SGET_BYTE_resolve         @ yes, do resolve
2765 .LOP_SGET_BYTE_finish: @ field ptr in r0
2766     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2767     mov     r2, rINST, lsr #8           @ r2<- AA
2768     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2769     SET_VREG(r1, r2)                    @ fp[AA]<- r1
2770     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2771     GOTO_OPCODE(ip)                     @ jump to next instruction
2772
2773
2774 /* ------------------------------ */
2775     .balign 64
2776 .L_OP_SGET_CHAR: /* 0x65 */
2777 /* File: armv5te/OP_SGET_CHAR.S */
2778 /* File: armv5te/OP_SGET.S */
2779     /*
2780      * General 32-bit SGET handler.
2781      *
2782      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2783      */
2784     /* op vAA, field@BBBB */
2785     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2786     FETCH(r1, 1)                        @ r1<- field ref BBBB
2787     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2788     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2789     cmp     r0, #0                      @ is resolved entry null?
2790     beq     .LOP_SGET_CHAR_resolve         @ yes, do resolve
2791 .LOP_SGET_CHAR_finish: @ field ptr in r0
2792     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2793     mov     r2, rINST, lsr #8           @ r2<- AA
2794     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2795     SET_VREG(r1, r2)                    @ fp[AA]<- r1
2796     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2797     GOTO_OPCODE(ip)                     @ jump to next instruction
2798
2799
2800 /* ------------------------------ */
2801     .balign 64
2802 .L_OP_SGET_SHORT: /* 0x66 */
2803 /* File: armv5te/OP_SGET_SHORT.S */
2804 /* File: armv5te/OP_SGET.S */
2805     /*
2806      * General 32-bit SGET handler.
2807      *
2808      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2809      */
2810     /* op vAA, field@BBBB */
2811     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2812     FETCH(r1, 1)                        @ r1<- field ref BBBB
2813     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2814     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2815     cmp     r0, #0                      @ is resolved entry null?
2816     beq     .LOP_SGET_SHORT_resolve         @ yes, do resolve
2817 .LOP_SGET_SHORT_finish: @ field ptr in r0
2818     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2819     mov     r2, rINST, lsr #8           @ r2<- AA
2820     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2821     SET_VREG(r1, r2)                    @ fp[AA]<- r1
2822     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2823     GOTO_OPCODE(ip)                     @ jump to next instruction
2824
2825
2826 /* ------------------------------ */
2827     .balign 64
2828 .L_OP_SPUT: /* 0x67 */
2829 /* File: armv5te/OP_SPUT.S */
2830     /*
2831      * General 32-bit SPUT handler.
2832      *
2833      * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2834      */
2835     /* op vAA, field@BBBB */
2836     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2837     FETCH(r1, 1)                        @ r1<- field ref BBBB
2838     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2839     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2840     cmp     r0, #0                      @ is resolved entry null?
2841     beq     .LOP_SPUT_resolve         @ yes, do resolve
2842 .LOP_SPUT_finish:   @ field ptr in r0
2843     mov     r2, rINST, lsr #8           @ r2<- AA
2844     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2845     GET_VREG(r1, r2)                    @ r1<- fp[AA]
2846     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2847     str     r1, [r0, #offStaticField_value] @ field<- vAA
2848     GOTO_OPCODE(ip)                     @ jump to next instruction
2849
2850 /* ------------------------------ */
2851     .balign 64
2852 .L_OP_SPUT_WIDE: /* 0x68 */
2853 /* File: armv4t/OP_SPUT_WIDE.S */
2854     /*
2855      * 64-bit SPUT handler.
2856      */
2857     /* sput-wide vAA, field@BBBB */
2858     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2859     FETCH(r1, 1)                        @ r1<- field ref BBBB
2860     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2861     mov     r9, rINST, lsr #8           @ r9<- AA
2862     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2863     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2864     cmp     r0, #0                      @ is resolved entry null?
2865     beq     .LOP_SPUT_WIDE_resolve         @ yes, do resolve
2866 .LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9
2867     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2868     ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
2869     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2870     add     r0, r0, #offStaticField_value
2871     stmia   r0, {r2-r3}                 @ field<- vAA/vAA+1
2872     GOTO_OPCODE(ip)                     @ jump to next instruction
2873
2874 /* ------------------------------ */
2875     .balign 64
2876 .L_OP_SPUT_OBJECT: /* 0x69 */
2877 /* File: armv5te/OP_SPUT_OBJECT.S */
2878 /* File: armv5te/OP_SPUT.S */
2879     /*
2880      * General 32-bit SPUT handler.
2881      *
2882      * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2883      */
2884     /* op vAA, field@BBBB */
2885     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2886     FETCH(r1, 1)                        @ r1<- field ref BBBB
2887     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2888     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2889     cmp     r0, #0                      @ is resolved entry null?
2890     beq     .LOP_SPUT_OBJECT_resolve         @ yes, do resolve
2891 .LOP_SPUT_OBJECT_finish:   @ field ptr in r0
2892     mov     r2, rINST, lsr #8           @ r2<- AA
2893     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2894     GET_VREG(r1, r2)                    @ r1<- fp[AA]
2895     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2896     str     r1, [r0, #offStaticField_value] @ field<- vAA
2897     GOTO_OPCODE(ip)                     @ jump to next instruction
2898
2899
2900 /* ------------------------------ */
2901     .balign 64
2902 .L_OP_SPUT_BOOLEAN: /* 0x6a */
2903 /* File: armv5te/OP_SPUT_BOOLEAN.S */
2904 /* File: armv5te/OP_SPUT.S */
2905     /*
2906      * General 32-bit SPUT handler.
2907      *
2908      * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-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_SPUT_BOOLEAN_resolve         @ yes, do resolve
2917 .LOP_SPUT_BOOLEAN_finish:   @ field ptr in r0
2918     mov     r2, rINST, lsr #8           @ r2<- AA
2919     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2920     GET_VREG(r1, r2)                    @ r1<- fp[AA]
2921     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2922     str     r1, [r0, #offStaticField_value] @ field<- vAA
2923     GOTO_OPCODE(ip)                     @ jump to next instruction
2924
2925
2926 /* ------------------------------ */
2927     .balign 64
2928 .L_OP_SPUT_BYTE: /* 0x6b */
2929 /* File: armv5te/OP_SPUT_BYTE.S */
2930 /* File: armv5te/OP_SPUT.S */
2931     /*
2932      * General 32-bit SPUT handler.
2933      *
2934      * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-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_SPUT_BYTE_resolve         @ yes, do resolve
2943 .LOP_SPUT_BYTE_finish:   @ field ptr in r0
2944     mov     r2, rINST, lsr #8           @ r2<- AA
2945     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2946     GET_VREG(r1, r2)                    @ r1<- fp[AA]
2947     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2948     str     r1, [r0, #offStaticField_value] @ field<- vAA
2949     GOTO_OPCODE(ip)                     @ jump to next instruction
2950
2951
2952 /* ------------------------------ */
2953     .balign 64
2954 .L_OP_SPUT_CHAR: /* 0x6c */
2955 /* File: armv5te/OP_SPUT_CHAR.S */
2956 /* File: armv5te/OP_SPUT.S */
2957     /*
2958      * General 32-bit SPUT handler.
2959      *
2960      * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-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_SPUT_CHAR_resolve         @ yes, do resolve
2969 .LOP_SPUT_CHAR_finish:   @ field ptr in r0
2970     mov     r2, rINST, lsr #8           @ r2<- AA
2971     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2972     GET_VREG(r1, r2)                    @ r1<- fp[AA]
2973     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2974     str     r1, [r0, #offStaticField_value] @ field<- vAA
2975     GOTO_OPCODE(ip)                     @ jump to next instruction
2976
2977
2978 /* ------------------------------ */
2979     .balign 64
2980 .L_OP_SPUT_SHORT: /* 0x6d */
2981 /* File: armv5te/OP_SPUT_SHORT.S */
2982 /* File: armv5te/OP_SPUT.S */
2983     /*
2984      * General 32-bit SPUT handler.
2985      *
2986      * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-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_SPUT_SHORT_resolve         @ yes, do resolve
2995 .LOP_SPUT_SHORT_finish:   @ field ptr in r0
2996     mov     r2, rINST, lsr #8           @ r2<- AA
2997     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2998     GET_VREG(r1, r2)                    @ r1<- fp[AA]
2999     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3000     str     r1, [r0, #offStaticField_value] @ field<- vAA
3001     GOTO_OPCODE(ip)                     @ jump to next instruction
3002
3003
3004 /* ------------------------------ */
3005     .balign 64
3006 .L_OP_INVOKE_VIRTUAL: /* 0x6e */
3007 /* File: armv5te/OP_INVOKE_VIRTUAL.S */
3008     /*
3009      * Handle a virtual method call.
3010      *
3011      * for: invoke-virtual, invoke-virtual/range
3012      */
3013     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3014     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3015     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3016     FETCH(r1, 1)                        @ r1<- BBBB
3017     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3018     FETCH(r10, 2)                       @ r10<- GFED or CCCC
3019     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3020     .if     (!0)
3021     and     r10, r10, #15               @ r10<- D (or stays CCCC)
3022     .endif
3023     cmp     r0, #0                      @ already resolved?
3024     EXPORT_PC()                         @ must export for invoke
3025     bne     .LOP_INVOKE_VIRTUAL_continue        @ yes, continue on
3026     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3027     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3028     mov     r2, #METHOD_VIRTUAL         @ resolver method type
3029     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3030     cmp     r0, #0                      @ got null?
3031     bne     .LOP_INVOKE_VIRTUAL_continue        @ no, continue
3032     b       common_exceptionThrown      @ yes, handle exception
3033
3034 /* ------------------------------ */
3035     .balign 64
3036 .L_OP_INVOKE_SUPER: /* 0x6f */
3037 /* File: armv5te/OP_INVOKE_SUPER.S */
3038     /*
3039      * Handle a "super" method call.
3040      *
3041      * for: invoke-super, invoke-super/range
3042      */
3043     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3044     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3045     FETCH(r10, 2)                       @ r10<- GFED or CCCC
3046     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3047     .if     (!0)
3048     and     r10, r10, #15               @ r10<- D (or stays CCCC)
3049     .endif
3050     FETCH(r1, 1)                        @ r1<- BBBB
3051     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3052     GET_VREG(r2, r10)                   @ r2<- "this" ptr
3053     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3054     cmp     r2, #0                      @ null "this"?
3055     ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3056     beq     common_errNullObject        @ null "this", throw exception
3057     cmp     r0, #0                      @ already resolved?
3058     ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3059     EXPORT_PC()                         @ must export for invoke
3060     bne     .LOP_INVOKE_SUPER_continue        @ resolved, continue on
3061     b       .LOP_INVOKE_SUPER_resolve         @ do resolve now
3062
3063 /* ------------------------------ */
3064     .balign 64
3065 .L_OP_INVOKE_DIRECT: /* 0x70 */
3066 /* File: armv5te/OP_INVOKE_DIRECT.S */
3067     /*
3068      * Handle a direct method call.
3069      *
3070      * (We could defer the "is 'this' pointer null" test to the common
3071      * method invocation code, and use a flag to indicate that static
3072      * calls don't count.  If we do this as part of copying the arguments
3073      * out we could avoiding loading the first arg twice.)
3074      *
3075      * for: invoke-direct, invoke-direct/range
3076      */
3077     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3078     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3079     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3080     FETCH(r1, 1)                        @ r1<- BBBB
3081     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3082     FETCH(r10, 2)                       @ r10<- GFED or CCCC
3083     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3084     .if     (!0)
3085     and     r10, r10, #15               @ r10<- D (or stays CCCC)
3086     .endif
3087     cmp     r0, #0                      @ already resolved?
3088     EXPORT_PC()                         @ must export for invoke
3089     GET_VREG(r2, r10)                   @ r2<- "this" ptr
3090     beq     .LOP_INVOKE_DIRECT_resolve         @ not resolved, do it now
3091 .LOP_INVOKE_DIRECT_finish:
3092     cmp     r2, #0                      @ null "this" ref?
3093     bne     common_invokeMethodNoRange   @ no, continue on
3094     b       common_errNullObject        @ yes, throw exception
3095
3096 /* ------------------------------ */
3097     .balign 64
3098 .L_OP_INVOKE_STATIC: /* 0x71 */
3099 /* File: armv5te/OP_INVOKE_STATIC.S */
3100     /*
3101      * Handle a static method call.
3102      *
3103      * for: invoke-static, invoke-static/range
3104      */
3105     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3106     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3107     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3108     FETCH(r1, 1)                        @ r1<- BBBB
3109     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3110     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3111     cmp     r0, #0                      @ already resolved?
3112     EXPORT_PC()                         @ must export for invoke
3113     bne     common_invokeMethodNoRange @ yes, continue on
3114 0:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3115     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3116     mov     r2, #METHOD_STATIC          @ resolver method type
3117     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3118     cmp     r0, #0                      @ got null?
3119     bne     common_invokeMethodNoRange @ no, continue
3120     b       common_exceptionThrown      @ yes, handle exception
3121
3122
3123 /* ------------------------------ */
3124     .balign 64
3125 .L_OP_INVOKE_INTERFACE: /* 0x72 */
3126 /* File: armv5te/OP_INVOKE_INTERFACE.S */
3127     /*
3128      * Handle an interface method call.
3129      *
3130      * for: invoke-interface, invoke-interface/range
3131      */
3132     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3133     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3134     FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3135     FETCH(r1, 1)                        @ r1<- BBBB
3136     .if     (!0)
3137     and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3138     .endif
3139     EXPORT_PC()                         @ must export for invoke
3140     GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3141     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3142     cmp     r0, #0                      @ null obj?
3143     ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3144     beq     common_errNullObject        @ yes, fail
3145     ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3146     bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3147     cmp     r0, #0                      @ failed?
3148     beq     common_exceptionThrown      @ yes, handle exception
3149     b       common_invokeMethodNoRange @ jump to common handler 
3150
3151
3152 /* ------------------------------ */
3153     .balign 64
3154 .L_OP_UNUSED_73: /* 0x73 */
3155 /* File: armv5te/OP_UNUSED_73.S */
3156 /* File: armv5te/unused.S */
3157     bl      common_abort
3158
3159
3160
3161 /* ------------------------------ */
3162     .balign 64
3163 .L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
3164 /* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */
3165 /* File: armv5te/OP_INVOKE_VIRTUAL.S */
3166     /*
3167      * Handle a virtual method call.
3168      *
3169      * for: invoke-virtual, invoke-virtual/range
3170      */
3171     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3172     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3173     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3174     FETCH(r1, 1)                        @ r1<- BBBB
3175     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3176     FETCH(r10, 2)                       @ r10<- GFED or CCCC
3177     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3178     .if     (!1)
3179     and     r10, r10, #15               @ r10<- D (or stays CCCC)
3180     .endif
3181     cmp     r0, #0                      @ already resolved?
3182     EXPORT_PC()                         @ must export for invoke
3183     bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ yes, continue on
3184     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3185     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3186     mov     r2, #METHOD_VIRTUAL         @ resolver method type
3187     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3188     cmp     r0, #0                      @ got null?
3189     bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ no, continue
3190     b       common_exceptionThrown      @ yes, handle exception
3191
3192
3193 /* ------------------------------ */
3194     .balign 64
3195 .L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
3196 /* File: armv5te/OP_INVOKE_SUPER_RANGE.S */
3197 /* File: armv5te/OP_INVOKE_SUPER.S */
3198     /*
3199      * Handle a "super" method call.
3200      *
3201      * for: invoke-super, invoke-super/range
3202      */
3203     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3204     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3205     FETCH(r10, 2)                       @ r10<- GFED or CCCC
3206     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3207     .if     (!1)
3208     and     r10, r10, #15               @ r10<- D (or stays CCCC)
3209     .endif
3210     FETCH(r1, 1)                        @ r1<- BBBB
3211     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3212     GET_VREG(r2, r10)                   @ r2<- "this" ptr
3213     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3214     cmp     r2, #0                      @ null "this"?
3215     ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3216     beq     common_errNullObject        @ null "this", throw exception
3217     cmp     r0, #0                      @ already resolved?
3218     ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3219     EXPORT_PC()                         @ must export for invoke
3220     bne     .LOP_INVOKE_SUPER_RANGE_continue        @ resolved, continue on
3221     b       .LOP_INVOKE_SUPER_RANGE_resolve         @ do resolve now
3222
3223
3224 /* ------------------------------ */
3225     .balign 64
3226 .L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
3227 /* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */
3228 /* File: armv5te/OP_INVOKE_DIRECT.S */
3229     /*
3230      * Handle a direct method call.
3231      *
3232      * (We could defer the "is 'this' pointer null" test to the common
3233      * method invocation code, and use a flag to indicate that static
3234      * calls don't count.  If we do this as part of copying the arguments
3235      * out we could avoiding loading the first arg twice.)
3236      *
3237      * for: invoke-direct, invoke-direct/range
3238      */
3239     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3240     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3241     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3242     FETCH(r1, 1)                        @ r1<- BBBB
3243     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3244     FETCH(r10, 2)                       @ r10<- GFED or CCCC
3245     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3246     .if     (!1)
3247     and     r10, r10, #15               @ r10<- D (or stays CCCC)
3248     .endif
3249     cmp     r0, #0                      @ already resolved?
3250     EXPORT_PC()                         @ must export for invoke
3251     GET_VREG(r2, r10)                   @ r2<- "this" ptr
3252     beq     .LOP_INVOKE_DIRECT_RANGE_resolve         @ not resolved, do it now
3253 .LOP_INVOKE_DIRECT_RANGE_finish:
3254     cmp     r2, #0                      @ null "this" ref?
3255     bne     common_invokeMethodRange   @ no, continue on
3256     b       common_errNullObject        @ yes, throw exception
3257
3258
3259 /* ------------------------------ */
3260     .balign 64
3261 .L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
3262 /* File: armv5te/OP_INVOKE_STATIC_RANGE.S */
3263 /* File: armv5te/OP_INVOKE_STATIC.S */
3264     /*
3265      * Handle a static method call.
3266      *
3267      * for: invoke-static, invoke-static/range
3268      */
3269     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3270     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3271     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3272     FETCH(r1, 1)                        @ r1<- BBBB
3273     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3274     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3275     cmp     r0, #0                      @ already resolved?
3276     EXPORT_PC()                         @ must export for invoke
3277     bne     common_invokeMethodRange @ yes, continue on
3278 0:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3279     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3280     mov     r2, #METHOD_STATIC          @ resolver method type
3281     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3282     cmp     r0, #0                      @ got null?
3283     bne     common_invokeMethodRange @ no, continue
3284     b       common_exceptionThrown      @ yes, handle exception
3285
3286
3287
3288 /* ------------------------------ */
3289     .balign 64
3290 .L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
3291 /* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */
3292 /* File: armv5te/OP_INVOKE_INTERFACE.S */
3293     /*
3294      * Handle an interface method call.
3295      *
3296      * for: invoke-interface, invoke-interface/range
3297      */
3298     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3299     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3300     FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3301     FETCH(r1, 1)                        @ r1<- BBBB
3302     .if     (!1)
3303     and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3304     .endif
3305     EXPORT_PC()                         @ must export for invoke
3306     GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3307     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3308     cmp     r0, #0                      @ null obj?
3309     ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3310     beq     common_errNullObject        @ yes, fail
3311     ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3312     bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3313     cmp     r0, #0                      @ failed?
3314     beq     common_exceptionThrown      @ yes, handle exception
3315     b       common_invokeMethodRange @ jump to common handler 
3316
3317
3318
3319 /* ------------------------------ */
3320     .balign 64
3321 .L_OP_UNUSED_79: /* 0x79 */
3322 /* File: armv5te/OP_UNUSED_79.S */
3323 /* File: armv5te/unused.S */
3324     bl      common_abort
3325
3326
3327
3328 /* ------------------------------ */
3329     .balign 64
3330 .L_OP_UNUSED_7A: /* 0x7a */
3331 /* File: armv5te/OP_UNUSED_7A.S */
3332 /* File: armv5te/unused.S */
3333     bl      common_abort
3334
3335
3336
3337 /* ------------------------------ */
3338     .balign 64
3339 .L_OP_NEG_INT: /* 0x7b */
3340 /* File: armv5te/OP_NEG_INT.S */
3341 /* File: armv5te/unop.S */
3342     /*
3343      * Generic 32-bit unary operation.  Provide an "instr" line that
3344      * specifies an instruction that performs "result = op r0".
3345      * This could be an ARM instruction or a function call.
3346      *
3347      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3348      *      int-to-byte, int-to-char, int-to-short
3349      */
3350     /* unop vA, vB */
3351     mov     r3, rINST, lsr #12          @ r3<- B
3352     mov     r9, rINST, lsr #8           @ r9<- A+
3353     GET_VREG(r0, r3)                    @ r0<- vB
3354     and     r9, r9, #15
3355                                @ optional op; may set condition codes
3356     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3357     rsb     r0, r0, #0                              @ r0<- op, r0-r3 changed
3358     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3359     SET_VREG(r0, r9)                    @ vAA<- r0
3360     GOTO_OPCODE(ip)                     @ jump to next instruction
3361     /* 9-10 instructions */
3362
3363
3364 /* ------------------------------ */
3365     .balign 64
3366 .L_OP_NOT_INT: /* 0x7c */
3367 /* File: armv5te/OP_NOT_INT.S */
3368 /* File: armv5te/unop.S */
3369     /*
3370      * Generic 32-bit unary operation.  Provide an "instr" line that
3371      * specifies an instruction that performs "result = op r0".
3372      * This could be an ARM instruction or a function call.
3373      *
3374      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3375      *      int-to-byte, int-to-char, int-to-short
3376      */
3377     /* unop vA, vB */
3378     mov     r3, rINST, lsr #12          @ r3<- B
3379     mov     r9, rINST, lsr #8           @ r9<- A+
3380     GET_VREG(r0, r3)                    @ r0<- vB
3381     and     r9, r9, #15
3382                                @ optional op; may set condition codes
3383     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3384     mvn     r0, r0                              @ r0<- op, r0-r3 changed
3385     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3386     SET_VREG(r0, r9)                    @ vAA<- r0
3387     GOTO_OPCODE(ip)                     @ jump to next instruction
3388     /* 9-10 instructions */
3389
3390
3391 /* ------------------------------ */
3392     .balign 64
3393 .L_OP_NEG_LONG: /* 0x7d */
3394 /* File: armv5te/OP_NEG_LONG.S */
3395 /* File: armv5te/unopWide.S */
3396     /*
3397      * Generic 64-bit unary operation.  Provide an "instr" line that
3398      * specifies an instruction that performs "result = op r0/r1".
3399      * This could be an ARM instruction or a function call.
3400      *
3401      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3402      */
3403     /* unop vA, vB */
3404     mov     r9, rINST, lsr #8           @ r9<- A+
3405     mov     r3, rINST, lsr #12          @ r3<- B
3406     and     r9, r9, #15
3407     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3408     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3409     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3410     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3411     rsbs    r0, r0, #0                           @ optional op; may set condition codes
3412     rsc     r1, r1, #0                              @ r0/r1<- op, r2-r3 changed
3413     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3414     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3415     GOTO_OPCODE(ip)                     @ jump to next instruction
3416     /* 12-13 instructions */
3417
3418
3419
3420 /* ------------------------------ */
3421     .balign 64
3422 .L_OP_NOT_LONG: /* 0x7e */
3423 /* File: armv5te/OP_NOT_LONG.S */
3424 /* File: armv5te/unopWide.S */
3425     /*
3426      * Generic 64-bit unary operation.  Provide an "instr" line that
3427      * specifies an instruction that performs "result = op r0/r1".
3428      * This could be an ARM instruction or a function call.
3429      *
3430      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3431      */
3432     /* unop vA, vB */
3433     mov     r9, rINST, lsr #8           @ r9<- A+
3434     mov     r3, rINST, lsr #12          @ r3<- B
3435     and     r9, r9, #15
3436     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3437     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3438     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3439     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3440     mvn     r0, r0                           @ optional op; may set condition codes
3441     mvn     r1, r1                              @ r0/r1<- op, r2-r3 changed
3442     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3443     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3444     GOTO_OPCODE(ip)                     @ jump to next instruction
3445     /* 12-13 instructions */
3446
3447
3448
3449 /* ------------------------------ */
3450     .balign 64
3451 .L_OP_NEG_FLOAT: /* 0x7f */
3452 /* File: armv5te/OP_NEG_FLOAT.S */
3453 /* File: armv5te/unop.S */
3454     /*
3455      * Generic 32-bit unary operation.  Provide an "instr" line that
3456      * specifies an instruction that performs "result = op r0".
3457      * This could be an ARM instruction or a function call.
3458      *
3459      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3460      *      int-to-byte, int-to-char, int-to-short
3461      */
3462     /* unop vA, vB */
3463     mov     r3, rINST, lsr #12          @ r3<- B
3464     mov     r9, rINST, lsr #8           @ r9<- A+
3465     GET_VREG(r0, r3)                    @ r0<- vB
3466     and     r9, r9, #15
3467                                @ optional op; may set condition codes
3468     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3469     add     r0, r0, #0x80000000                              @ r0<- op, r0-r3 changed
3470     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3471     SET_VREG(r0, r9)                    @ vAA<- r0
3472     GOTO_OPCODE(ip)                     @ jump to next instruction
3473     /* 9-10 instructions */
3474
3475
3476 /* ------------------------------ */
3477     .balign 64
3478 .L_OP_NEG_DOUBLE: /* 0x80 */
3479 /* File: armv5te/OP_NEG_DOUBLE.S */
3480 /* File: armv5te/unopWide.S */
3481     /*
3482      * Generic 64-bit unary operation.  Provide an "instr" line that
3483      * specifies an instruction that performs "result = op r0/r1".
3484      * This could be an ARM instruction or a function call.
3485      *
3486      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3487      */
3488     /* unop vA, vB */
3489     mov     r9, rINST, lsr #8           @ r9<- A+
3490     mov     r3, rINST, lsr #12          @ r3<- B
3491     and     r9, r9, #15
3492     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3493     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3494     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3495     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3496                                @ optional op; may set condition codes
3497     add     r1, r1, #0x80000000                              @ r0/r1<- op, r2-r3 changed
3498     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3499     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3500     GOTO_OPCODE(ip)                     @ jump to next instruction
3501     /* 12-13 instructions */
3502
3503
3504
3505 /* ------------------------------ */
3506     .balign 64
3507 .L_OP_INT_TO_LONG: /* 0x81 */
3508 /* File: armv5te/OP_INT_TO_LONG.S */
3509 /* File: armv5te/unopWider.S */
3510     /*
3511      * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3512      * that specifies an instruction that performs "result = op r0", where
3513      * "result" is a 64-bit quantity in r0/r1.
3514      *
3515      * For: int-to-long, int-to-double, float-to-long, float-to-double
3516      */
3517     /* unop vA, vB */
3518     mov     r9, rINST, lsr #8           @ r9<- A+
3519     mov     r3, rINST, lsr #12          @ r3<- B
3520     and     r9, r9, #15
3521     GET_VREG(r0, r3)                    @ r0<- vB
3522     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3523                                @ optional op; may set condition codes
3524     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3525     mov     r1, r0, asr #31                              @ r0<- op, r0-r3 changed
3526     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3527     stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3528     GOTO_OPCODE(ip)                     @ jump to next instruction
3529     /* 10-11 instructions */
3530
3531
3532 /* ------------------------------ */
3533     .balign 64
3534 .L_OP_INT_TO_FLOAT: /* 0x82 */
3535 /* File: armv5te/OP_INT_TO_FLOAT.S */
3536 /* File: armv5te/unop.S */
3537     /*
3538      * Generic 32-bit unary operation.  Provide an "instr" line that
3539      * specifies an instruction that performs "result = op r0".
3540      * This could be an ARM instruction or a function call.
3541      *
3542      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3543      *      int-to-byte, int-to-char, int-to-short
3544      */
3545     /* unop vA, vB */
3546     mov     r3, rINST, lsr #12          @ r3<- B
3547     mov     r9, rINST, lsr #8           @ r9<- A+
3548     GET_VREG(r0, r3)                    @ r0<- vB
3549     and     r9, r9, #15
3550                                @ optional op; may set condition codes
3551     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3552     bl      __aeabi_i2f                              @ r0<- op, r0-r3 changed
3553     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3554     SET_VREG(r0, r9)                    @ vAA<- r0
3555     GOTO_OPCODE(ip)                     @ jump to next instruction
3556     /* 9-10 instructions */
3557
3558
3559 /* ------------------------------ */
3560     .balign 64
3561 .L_OP_INT_TO_DOUBLE: /* 0x83 */
3562 /* File: armv5te/OP_INT_TO_DOUBLE.S */
3563 /* File: armv5te/unopWider.S */
3564     /*
3565      * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3566      * that specifies an instruction that performs "result = op r0", where
3567      * "result" is a 64-bit quantity in r0/r1.
3568      *
3569      * For: int-to-long, int-to-double, float-to-long, float-to-double
3570      */
3571     /* unop vA, vB */
3572     mov     r9, rINST, lsr #8           @ r9<- A+
3573     mov     r3, rINST, lsr #12          @ r3<- B
3574     and     r9, r9, #15
3575     GET_VREG(r0, r3)                    @ r0<- vB
3576     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3577                                @ optional op; may set condition codes
3578     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3579     bl      __aeabi_i2d                              @ r0<- op, r0-r3 changed
3580     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3581     stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3582     GOTO_OPCODE(ip)                     @ jump to next instruction
3583     /* 10-11 instructions */
3584
3585
3586 /* ------------------------------ */
3587     .balign 64
3588 .L_OP_LONG_TO_INT: /* 0x84 */
3589 /* File: armv5te/OP_LONG_TO_INT.S */
3590 /* we ignore the high word, making this equivalent to a 32-bit reg move */
3591 /* File: armv5te/OP_MOVE.S */
3592     /* for move, move-object, long-to-int */
3593     /* op vA, vB */
3594     mov     r1, rINST, lsr #12          @ r1<- B from 15:12
3595     mov     r0, rINST, lsr #8           @ r0<- A from 11:8
3596     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3597     GET_VREG(r2, r1)                    @ r2<- fp[B]
3598     and     r0, r0, #15
3599     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
3600     SET_VREG(r2, r0)                    @ fp[A]<- r2
3601     GOTO_OPCODE(ip)                     @ execute next instruction
3602
3603
3604
3605 /* ------------------------------ */
3606     .balign 64
3607 .L_OP_LONG_TO_FLOAT: /* 0x85 */
3608 /* File: armv5te/OP_LONG_TO_FLOAT.S */
3609 /* File: armv5te/unopNarrower.S */
3610     /*
3611      * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
3612      * that specifies an instruction that performs "result = op r0/r1", where
3613      * "result" is a 32-bit quantity in r0.
3614      *
3615      * For: long-to-float, double-to-int, double-to-float
3616      *
3617      * (This would work for long-to-int, but that instruction is actually
3618      * an exact match for OP_MOVE.)
3619      */
3620     /* unop vA, vB */
3621     mov     r3, rINST, lsr #12          @ r3<- B
3622     mov     r9, rINST, lsr #8           @ r9<- A+
3623     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3624     and     r9, r9, #15
3625     ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
3626     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3627                                @ optional op; may set condition codes
3628     bl      __aeabi_l2f                              @ r0<- op, r0-r3 changed
3629     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3630     SET_VREG(r0, r9)                    @ vA<- r0
3631     GOTO_OPCODE(ip)                     @ jump to next instruction
3632     /* 10-11 instructions */
3633
3634
3635 /* ------------------------------ */
3636     .balign 64
3637 .L_OP_LONG_TO_DOUBLE: /* 0x86 */
3638 /* File: armv5te/OP_LONG_TO_DOUBLE.S */
3639 /* File: armv5te/unopWide.S */
3640     /*
3641      * Generic 64-bit unary operation.  Provide an "instr" line that
3642      * specifies an instruction that performs "result = op r0/r1".
3643      * This could be an ARM instruction or a function call.
3644      *
3645      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3646      */
3647     /* unop vA, vB */
3648     mov     r9, rINST, lsr #8           @ r9<- A+
3649     mov     r3, rINST, lsr #12          @ r3<- B
3650     and     r9, r9, #15
3651     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3652     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3653     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3654     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3655                                @ optional op; may set condition codes
3656     bl      __aeabi_l2d                              @ r0/r1<- op, r2-r3 changed
3657     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3658     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3659     GOTO_OPCODE(ip)                     @ jump to next instruction
3660     /* 12-13 instructions */
3661
3662
3663
3664 /* ------------------------------ */
3665     .balign 64
3666 .L_OP_FLOAT_TO_INT: /* 0x87 */
3667 /* File: armv5te/OP_FLOAT_TO_INT.S */
3668 /* EABI appears to have Java-style conversions of +inf/-inf/NaN */
3669 /* File: armv5te/unop.S */
3670     /*
3671      * Generic 32-bit unary operation.  Provide an "instr" line that
3672      * specifies an instruction that performs "result = op r0".
3673      * This could be an ARM instruction or a function call.
3674      *
3675      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3676      *      int-to-byte, int-to-char, int-to-short
3677      */
3678     /* unop vA, vB */
3679     mov     r3, rINST, lsr #12          @ r3<- B
3680     mov     r9, rINST, lsr #8           @ r9<- A+
3681     GET_VREG(r0, r3)                    @ r0<- vB
3682     and     r9, r9, #15
3683                                @ optional op; may set condition codes
3684     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3685     bl      __aeabi_f2iz                              @ r0<- op, r0-r3 changed
3686     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3687     SET_VREG(r0, r9)                    @ vAA<- r0
3688     GOTO_OPCODE(ip)                     @ jump to next instruction
3689     /* 9-10 instructions */
3690
3691
3692 #if 0
3693 @include "armv5te/unop.S" {"instr":"bl      f2i_doconv"}
3694 @break
3695 /*
3696  * Convert the float in r0 to an int in r0.
3697  *
3698  * We have to clip values to int min/max per the specification.  The
3699  * expected common case is a "reasonable" value that converts directly
3700  * to modest integer.  The EABI convert function isn't doing this for us.
3701  */
3702 f2i_doconv:
3703     stmfd   sp!, {r4, lr}
3704     mov     r1, #0x4f000000             @ (float)maxint
3705     mov     r4, r0
3706     bl      __aeabi_fcmpge              @ is arg >= maxint?
3707     cmp     r0, #0                      @ nonzero == yes
3708     mvnne   r0, #0x80000000             @ return maxint (7fffffff)
3709     ldmnefd sp!, {r4, pc}
3710
3711     mov     r0, r4                      @ recover arg
3712     mov     r1, #0xcf000000             @ (float)minint
3713     bl      __aeabi_fcmple              @ is arg <= minint?
3714     cmp     r0, #0                      @ nonzero == yes
3715     movne   r0, #0x80000000             @ return minint (80000000)
3716     ldmnefd sp!, {r4, pc}
3717
3718     mov     r0, r4                      @ recover arg
3719     mov     r1, r4
3720     bl      __aeabi_fcmpeq              @ is arg == self?
3721     cmp     r0, #0                      @ zero == no
3722     ldmeqfd sp!, {r4, pc}               @ return zero for NaN
3723
3724     mov     r0, r4                      @ recover arg
3725     bl      __aeabi_f2iz                @ convert float to int
3726     ldmfd   sp!, {r4, pc}
3727 #endif
3728
3729
3730 /* ------------------------------ */
3731     .balign 64
3732 .L_OP_FLOAT_TO_LONG: /* 0x88 */
3733 /* File: armv5te/OP_FLOAT_TO_LONG.S */
3734 @include "armv5te/unopWider.S" {"instr":"bl      __aeabi_f2lz"}
3735 /* File: armv5te/unopWider.S */
3736     /*
3737      * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3738      * that specifies an instruction that performs "result = op r0", where
3739      * "result" is a 64-bit quantity in r0/r1.
3740      *
3741      * For: int-to-long, int-to-double, float-to-long, float-to-double
3742      */
3743     /* unop vA, vB */
3744     mov     r9, rINST, lsr #8           @ r9<- A+
3745     mov     r3, rINST, lsr #12          @ r3<- B
3746     and     r9, r9, #15
3747     GET_VREG(r0, r3)                    @ r0<- vB
3748     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3749                                @ optional op; may set condition codes
3750     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3751     bl      f2l_doconv                              @ r0<- op, r0-r3 changed
3752     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3753     stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3754     GOTO_OPCODE(ip)                     @ jump to next instruction
3755     /* 10-11 instructions */
3756
3757
3758
3759 /* ------------------------------ */
3760     .balign 64
3761 .L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
3762 /* File: armv5te/OP_FLOAT_TO_DOUBLE.S */
3763 /* File: armv5te/unopWider.S */
3764     /*
3765      * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3766      * that specifies an instruction that performs "result = op r0", where
3767      * "result" is a 64-bit quantity in r0/r1.
3768      *
3769      * For: int-to-long, int-to-double, float-to-long, float-to-double
3770      */
3771     /* unop vA, vB */
3772     mov     r9, rINST, lsr #8           @ r9<- A+
3773     mov     r3, rINST, lsr #12          @ r3<- B
3774     and     r9, r9, #15
3775     GET_VREG(r0, r3)                    @ r0<- vB
3776     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3777                                @ optional op; may set condition codes
3778     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3779     bl      __aeabi_f2d                              @ r0<- op, r0-r3 changed
3780     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3781     stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3782     GOTO_OPCODE(ip)                     @ jump to next instruction
3783     /* 10-11 instructions */
3784
3785
3786 /* ------------------------------ */
3787     .balign 64
3788 .L_OP_DOUBLE_TO_INT: /* 0x8a */
3789 /* File: armv5te/OP_DOUBLE_TO_INT.S */
3790 /* EABI appears to have Java-style conversions of +inf/-inf/NaN */
3791 /* File: armv5te/unopNarrower.S */
3792     /*
3793      * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
3794      * that specifies an instruction that performs "result = op r0/r1", where
3795      * "result" is a 32-bit quantity in r0.
3796      *
3797      * For: long-to-float, double-to-int, double-to-float
3798      *
3799      * (This would work for long-to-int, but that instruction is actually
3800      * an exact match for OP_MOVE.)
3801      */
3802     /* unop vA, vB */
3803     mov     r3, rINST, lsr #12          @ r3<- B
3804     mov     r9, rINST, lsr #8           @ r9<- A+
3805     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3806     and     r9, r9, #15
3807     ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
3808     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3809                                @ optional op; may set condition codes
3810     bl      __aeabi_d2iz                              @ r0<- op, r0-r3 changed
3811     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3812     SET_VREG(r0, r9)                    @ vA<- r0
3813     GOTO_OPCODE(ip)                     @ jump to next instruction
3814     /* 10-11 instructions */
3815
3816
3817 #if 0
3818 @include "armv5te/unopNarrower.S" {"instr":"bl      d2i_doconv"}
3819 @break
3820 /*
3821  * Convert the double in r0/r1 to an int in r0.
3822  *
3823  * We have to clip values to int min/max per the specification.  The
3824  * expected common case is a "reasonable" value that converts directly
3825  * to modest integer.  The EABI convert function isn't doing this for us.
3826  */
3827 d2i_doconv:
3828     stmfd   sp!, {r4, r5, lr}           @ save regs
3829     ldr     r2, .LOP_DOUBLE_TO_INT_maxlo       @ (double)maxint, lo
3830     ldr     r3, .LOP_DOUBLE_TO_INT_maxhi       @ (double)maxint, hi
3831     sub     sp, sp, #4                  @ align for EABI
3832     mov     r4, r0                      @ save r0
3833     mov     r5, r1                      @  and r1
3834     bl      __aeabi_dcmpge              @ is arg >= maxint?
3835     cmp     r0, #0                      @ nonzero == yes
3836     mvnne   r0, #0x80000000             @ return maxint (7fffffff)
3837     bne     1f
3838
3839     mov     r0, r4                      @ recover arg
3840     mov     r1, r5
3841     ldr     r3, .LOP_DOUBLE_TO_INT_min         @ (double)minint, hi
3842     mov     r2, #0                      @ (double)minint, lo
3843     bl      __aeabi_dcmple              @ is arg <= minint?
3844     cmp     r0, #0                      @ nonzero == yes
3845     movne   r0, #0x80000000             @ return minint (80000000)
3846     bne     1f
3847
3848     mov     r0, r4                      @ recover arg
3849     mov     r1, r5
3850     mov     r2, r4                      @ compare against self
3851     mov     r3, r5
3852     bl      __aeabi_dcmpeq              @ is arg == self?
3853     cmp     r0, #0                      @ zero == no
3854     beq     1f                          @ return zero for NaN
3855
3856     mov     r0, r4                      @ recover arg
3857     mov     r1, r5
3858     bl      __aeabi_d2iz                @ convert double to int
3859
3860 1:
3861     add     sp, sp, #4
3862     ldmfd   sp!, {r4, r5, pc}
3863
3864 .LOP_DOUBLE_TO_INT_maxlo:
3865     .word   0xffc00000                  @ maxint, as a double (low word)
3866 .LOP_DOUBLE_TO_INT_maxhi:
3867     .word   0x41dfffff                  @ maxint, as a double (high word)
3868 .LOP_DOUBLE_TO_INT_min:
3869     .word   0xc1e00000                  @ minint, as a double (high word)
3870 #endif
3871
3872
3873 /* ------------------------------ */
3874     .balign 64
3875 .L_OP_DOUBLE_TO_LONG: /* 0x8b */
3876 /* File: armv5te/OP_DOUBLE_TO_LONG.S */
3877 @include "armv5te/unopWide.S" {"instr":"bl      __aeabi_d2lz"}
3878 /* File: armv5te/unopWide.S */
3879     /*
3880      * Generic 64-bit unary operation.  Provide an "instr" line that
3881      * specifies an instruction that performs "result = op r0/r1".
3882      * This could be an ARM instruction or a function call.
3883      *
3884      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3885      */
3886     /* unop vA, vB */
3887     mov     r9, rINST, lsr #8           @ r9<- A+
3888     mov     r3, rINST, lsr #12          @ r3<- B
3889     and     r9, r9, #15
3890     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3891     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3892     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3893     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3894                                @ optional op; may set condition codes
3895     bl      d2l_doconv                              @ r0/r1<- op, r2-r3 changed
3896     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3897     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3898     GOTO_OPCODE(ip)                     @ jump to next instruction
3899     /* 12-13 instructions */
3900
3901
3902
3903
3904 /* ------------------------------ */
3905     .balign 64
3906 .L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
3907 /* File: armv5te/OP_DOUBLE_TO_FLOAT.S */
3908 /* File: armv5te/unopNarrower.S */
3909     /*
3910      * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
3911      * that specifies an instruction that performs "result = op r0/r1", where
3912      * "result" is a 32-bit quantity in r0.
3913      *
3914      * For: long-to-float, double-to-int, double-to-float
3915      *
3916      * (This would work for long-to-int, but that instruction is actually
3917      * an exact match for OP_MOVE.)
3918      */
3919     /* unop vA, vB */
3920     mov     r3, rINST, lsr #12          @ r3<- B
3921     mov     r9, rINST, lsr #8           @ r9<- A+
3922     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3923     and     r9, r9, #15
3924     ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
3925     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3926                                @ optional op; may set condition codes
3927     bl      __aeabi_d2f                              @ r0<- op, r0-r3 changed
3928     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3929     SET_VREG(r0, r9)                    @ vA<- r0
3930     GOTO_OPCODE(ip)                     @ jump to next instruction
3931     /* 10-11 instructions */
3932
3933
3934 /* ------------------------------ */
3935     .balign 64
3936 .L_OP_INT_TO_BYTE: /* 0x8d */
3937 /* File: armv5te/OP_INT_TO_BYTE.S */
3938 /* File: armv5te/unop.S */
3939     /*
3940      * Generic 32-bit unary operation.  Provide an "instr" line that
3941      * specifies an instruction that performs "result = op r0".
3942      * This could be an ARM instruction or a function call.
3943      *
3944      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3945      *      int-to-byte, int-to-char, int-to-short
3946      */
3947     /* unop vA, vB */
3948     mov     r3, rINST, lsr #12          @ r3<- B
3949     mov     r9, rINST, lsr #8           @ r9<- A+
3950     GET_VREG(r0, r3)                    @ r0<- vB
3951     and     r9, r9, #15
3952     mov     r0, r0, asl #24                           @ optional op; may set condition codes
3953     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3954     mov     r0, r0, asr #24                              @ r0<- op, r0-r3 changed
3955     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3956     SET_VREG(r0, r9)                    @ vAA<- r0
3957     GOTO_OPCODE(ip)                     @ jump to next instruction
3958     /* 9-10 instructions */
3959
3960
3961 /* ------------------------------ */
3962     .balign 64
3963 .L_OP_INT_TO_CHAR: /* 0x8e */
3964 /* File: armv5te/OP_INT_TO_CHAR.S */
3965 /* File: armv5te/unop.S */
3966     /*
3967      * Generic 32-bit unary operation.  Provide an "instr" line that
3968      * specifies an instruction that performs "result = op r0".
3969      * This could be an ARM instruction or a function call.
3970      *
3971      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3972      *      int-to-byte, int-to-char, int-to-short
3973      */
3974     /* unop vA, vB */
3975     mov     r3, rINST, lsr #12          @ r3<- B
3976     mov     r9, rINST, lsr #8           @ r9<- A+
3977     GET_VREG(r0, r3)                    @ r0<- vB
3978     and     r9, r9, #15
3979     mov     r0, r0, asl #16                           @ optional op; may set condition codes
3980     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3981     mov     r0, r0, lsr #16                              @ r0<- op, r0-r3 changed
3982     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3983     SET_VREG(r0, r9)                    @ vAA<- r0
3984     GOTO_OPCODE(ip)                     @ jump to next instruction
3985     /* 9-10 instructions */
3986
3987
3988 /* ------------------------------ */
3989     .balign 64
3990 .L_OP_INT_TO_SHORT: /* 0x8f */
3991 /* File: armv5te/OP_INT_TO_SHORT.S */
3992 /* File: armv5te/unop.S */
3993     /*
3994      * Generic 32-bit unary operation.  Provide an "instr" line that
3995      * specifies an instruction that performs "result = op r0".
3996      * This could be an ARM instruction or a function call.
3997      *
3998      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3999      *      int-to-byte, int-to-char, int-to-short
4000      */
4001     /* unop vA, vB */
4002     mov     r3, rINST, lsr #12          @ r3<- B
4003     mov     r9, rINST, lsr #8           @ r9<- A+
4004     GET_VREG(r0, r3)                    @ r0<- vB
4005     and     r9, r9, #15
4006     mov     r0, r0, asl #16                           @ optional op; may set condition codes
4007     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4008     mov     r0, r0, asr #16                              @ r0<- op, r0-r3 changed
4009     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4010     SET_VREG(r0, r9)                    @ vAA<- r0
4011     GOTO_OPCODE(ip)                     @ jump to next instruction
4012     /* 9-10 instructions */
4013
4014
4015 /* ------------------------------ */
4016     .balign 64
4017 .L_OP_ADD_INT: /* 0x90 */
4018 /* File: armv5te/OP_ADD_INT.S */
4019 /* File: armv5te/binop.S */
4020     /*
4021      * Generic 32-bit binary operation.  Provide an "instr" line that
4022      * specifies an instruction that performs "result = r0 op r1".
4023      * This could be an ARM instruction or a function call.  (If the result
4024      * comes back in a register other than r0, you can override "result".)
4025      *
4026      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4027      * vCC (r1).  Useful for integer division and modulus.  Note that we
4028      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4029      * handles it correctly.
4030      *
4031      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4032      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4033      *      mul-float, div-float, rem-float
4034      */
4035     /* binop vAA, vBB, vCC */
4036     FETCH(r0, 1)                        @ r0<- CCBB
4037     mov     r9, rINST, lsr #8           @ r9<- AA
4038     mov     r3, r0, lsr #8              @ r3<- CC
4039     and     r2, r0, #255                @ r2<- BB
4040     GET_VREG(r1, r3)                    @ r1<- vCC
4041     GET_VREG(r0, r2)                    @ r0<- vBB
4042     .if 0
4043     cmp     r1, #0                      @ is second operand zero?
4044     beq     common_errDivideByZero
4045     .endif
4046
4047     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4048                                @ optional op; may set condition codes
4049     add     r0, r0, r1                              @ r0<- op, r0-r3 changed
4050     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4051     SET_VREG(r0, r9)               @ vAA<- r0
4052     GOTO_OPCODE(ip)                     @ jump to next instruction
4053     /* 11-14 instructions */
4054
4055
4056
4057 /* ------------------------------ */
4058     .balign 64
4059 .L_OP_SUB_INT: /* 0x91 */
4060 /* File: armv5te/OP_SUB_INT.S */
4061 /* File: armv5te/binop.S */
4062     /*
4063      * Generic 32-bit binary operation.  Provide an "instr" line that
4064      * specifies an instruction that performs "result = r0 op r1".
4065      * This could be an ARM instruction or a function call.  (If the result
4066      * comes back in a register other than r0, you can override "result".)
4067      *
4068      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4069      * vCC (r1).  Useful for integer division and modulus.  Note that we
4070      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4071      * handles it correctly.
4072      *
4073      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4074      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4075      *      mul-float, div-float, rem-float
4076      */
4077     /* binop vAA, vBB, vCC */
4078     FETCH(r0, 1)                        @ r0<- CCBB
4079     mov     r9, rINST, lsr #8           @ r9<- AA
4080     mov     r3, r0, lsr #8              @ r3<- CC
4081     and     r2, r0, #255                @ r2<- BB
4082     GET_VREG(r1, r3)                    @ r1<- vCC
4083     GET_VREG(r0, r2)                    @ r0<- vBB
4084     .if 0
4085     cmp     r1, #0                      @ is second operand zero?
4086     beq     common_errDivideByZero
4087     .endif
4088
4089     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4090                                @ optional op; may set condition codes
4091     sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
4092     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4093     SET_VREG(r0, r9)               @ vAA<- r0
4094     GOTO_OPCODE(ip)                     @ jump to next instruction
4095     /* 11-14 instructions */
4096
4097
4098
4099 /* ------------------------------ */
4100     .balign 64
4101 .L_OP_MUL_INT: /* 0x92 */
4102 /* File: armv5te/OP_MUL_INT.S */
4103 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
4104 /* File: armv5te/binop.S */
4105     /*
4106      * Generic 32-bit binary operation.  Provide an "instr" line that
4107      * specifies an instruction that performs "result = r0 op r1".
4108      * This could be an ARM instruction or a function call.  (If the result
4109      * comes back in a register other than r0, you can override "result".)
4110      *
4111      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4112      * vCC (r1).  Useful for integer division and modulus.  Note that we
4113      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4114      * handles it correctly.
4115      *
4116      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4117      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4118      *      mul-float, div-float, rem-float
4119      */
4120     /* binop vAA, vBB, vCC */
4121     FETCH(r0, 1)                        @ r0<- CCBB
4122     mov     r9, rINST, lsr #8           @ r9<- AA
4123     mov     r3, r0, lsr #8              @ r3<- CC
4124     and     r2, r0, #255                @ r2<- BB
4125     GET_VREG(r1, r3)                    @ r1<- vCC
4126     GET_VREG(r0, r2)                    @ r0<- vBB
4127     .if 0
4128     cmp     r1, #0                      @ is second operand zero?
4129     beq     common_errDivideByZero
4130     .endif
4131
4132     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4133                                @ optional op; may set condition codes
4134     mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
4135     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4136     SET_VREG(r0, r9)               @ vAA<- r0
4137     GOTO_OPCODE(ip)                     @ jump to next instruction
4138     /* 11-14 instructions */
4139
4140
4141
4142 /* ------------------------------ */
4143     .balign 64
4144 .L_OP_DIV_INT: /* 0x93 */
4145 /* File: armv5te/OP_DIV_INT.S */
4146 /* File: armv5te/binop.S */
4147     /*
4148      * Generic 32-bit binary operation.  Provide an "instr" line that
4149      * specifies an instruction that performs "result = r0 op r1".
4150      * This could be an ARM instruction or a function call.  (If the result
4151      * comes back in a register other than r0, you can override "result".)
4152      *
4153      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4154      * vCC (r1).  Useful for integer division and modulus.  Note that we
4155      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4156      * handles it correctly.
4157      *
4158      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4159      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4160      *      mul-float, div-float, rem-float
4161      */
4162     /* binop vAA, vBB, vCC */
4163     FETCH(r0, 1)                        @ r0<- CCBB
4164     mov     r9, rINST, lsr #8           @ r9<- AA
4165     mov     r3, r0, lsr #8              @ r3<- CC
4166     and     r2, r0, #255                @ r2<- BB
4167     GET_VREG(r1, r3)                    @ r1<- vCC
4168     GET_VREG(r0, r2)                    @ r0<- vBB
4169     .if 1
4170     cmp     r1, #0                      @ is second operand zero?
4171     beq     common_errDivideByZero
4172     .endif
4173
4174     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4175                                @ optional op; may set condition codes
4176     bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
4177     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4178     SET_VREG(r0, r9)               @ vAA<- r0
4179     GOTO_OPCODE(ip)                     @ jump to next instruction
4180     /* 11-14 instructions */
4181
4182
4183
4184 /* ------------------------------ */
4185     .balign 64
4186 .L_OP_REM_INT: /* 0x94 */
4187 /* File: armv5te/OP_REM_INT.S */
4188 /* idivmod returns quotient in r0 and remainder in r1 */
4189 /* File: armv5te/binop.S */
4190     /*
4191      * Generic 32-bit binary operation.  Provide an "instr" line that
4192      * specifies an instruction that performs "result = r0 op r1".
4193      * This could be an ARM instruction or a function call.  (If the result
4194      * comes back in a register other than r0, you can override "result".)
4195      *
4196      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4197      * vCC (r1).  Useful for integer division and modulus.  Note that we
4198      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4199      * handles it correctly.
4200      *
4201      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4202      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4203      *      mul-float, div-float, rem-float
4204      */
4205     /* binop vAA, vBB, vCC */
4206     FETCH(r0, 1)                        @ r0<- CCBB
4207     mov     r9, rINST, lsr #8           @ r9<- AA
4208     mov     r3, r0, lsr #8              @ r3<- CC
4209     and     r2, r0, #255                @ r2<- BB
4210     GET_VREG(r1, r3)                    @ r1<- vCC
4211     GET_VREG(r0, r2)                    @ r0<- vBB
4212     .if 1
4213     cmp     r1, #0                      @ is second operand zero?
4214     beq     common_errDivideByZero
4215     .endif
4216
4217     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4218                                @ optional op; may set condition codes
4219     bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
4220     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4221     SET_VREG(r1, r9)               @ vAA<- r1
4222     GOTO_OPCODE(ip)                     @ jump to next instruction
4223     /* 11-14 instructions */
4224
4225
4226
4227 /* ------------------------------ */
4228     .balign 64
4229 .L_OP_AND_INT: /* 0x95 */
4230 /* File: armv5te/OP_AND_INT.S */
4231 /* File: armv5te/binop.S */
4232     /*
4233      * Generic 32-bit binary operation.  Provide an "instr" line that
4234      * specifies an instruction that performs "result = r0 op r1".
4235      * This could be an ARM instruction or a function call.  (If the result
4236      * comes back in a register other than r0, you can override "result".)
4237      *
4238      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4239      * vCC (r1).  Useful for integer division and modulus.  Note that we
4240      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4241      * handles it correctly.
4242      *
4243      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4244      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4245      *      mul-float, div-float, rem-float
4246      */
4247     /* binop vAA, vBB, vCC */
4248     FETCH(r0, 1)                        @ r0<- CCBB
4249     mov     r9, rINST, lsr #8           @ r9<- AA
4250     mov     r3, r0, lsr #8              @ r3<- CC
4251     and     r2, r0, #255                @ r2<- BB
4252     GET_VREG(r1, r3)                    @ r1<- vCC
4253     GET_VREG(r0, r2)                    @ r0<- vBB
4254     .if 0
4255     cmp     r1, #0                      @ is second operand zero?
4256     beq     common_errDivideByZero
4257     .endif
4258
4259     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4260                                @ optional op; may set condition codes
4261     and     r0, r0, r1                              @ r0<- op, r0-r3 changed
4262     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4263     SET_VREG(r0, r9)               @ vAA<- r0
4264     GOTO_OPCODE(ip)                     @ jump to next instruction
4265     /* 11-14 instructions */
4266
4267
4268
4269 /* ------------------------------ */
4270     .balign 64
4271 .L_OP_OR_INT: /* 0x96 */
4272 /* File: armv5te/OP_OR_INT.S */
4273 /* File: armv5te/binop.S */
4274     /*
4275      * Generic 32-bit binary operation.  Provide an "instr" line that
4276      * specifies an instruction that performs "result = r0 op r1".
4277      * This could be an ARM instruction or a function call.  (If the result
4278      * comes back in a register other than r0, you can override "result".)
4279      *
4280      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4281      * vCC (r1).  Useful for integer division and modulus.  Note that we
4282      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4283      * handles it correctly.
4284      *
4285      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4286      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4287      *      mul-float, div-float, rem-float
4288      */
4289     /* binop vAA, vBB, vCC */
4290     FETCH(r0, 1)                        @ r0<- CCBB
4291     mov     r9, rINST, lsr #8           @ r9<- AA
4292     mov     r3, r0, lsr #8              @ r3<- CC
4293     and     r2, r0, #255                @ r2<- BB
4294     GET_VREG(r1, r3)                    @ r1<- vCC
4295     GET_VREG(r0, r2)                    @ r0<- vBB
4296     .if 0
4297     cmp     r1, #0                      @ is second operand zero?
4298     beq     common_errDivideByZero
4299     .endif
4300
4301     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4302                                @ optional op; may set condition codes
4303     orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
4304     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4305     SET_VREG(r0, r9)               @ vAA<- r0
4306     GOTO_OPCODE(ip)                     @ jump to next instruction
4307     /* 11-14 instructions */
4308
4309
4310
4311 /* ------------------------------ */
4312     .balign 64
4313 .L_OP_XOR_INT: /* 0x97 */
4314 /* File: armv5te/OP_XOR_INT.S */
4315 /* File: armv5te/binop.S */
4316     /*
4317      * Generic 32-bit binary operation.  Provide an "instr" line that
4318      * specifies an instruction that performs "result = r0 op r1".
4319      * This could be an ARM instruction or a function call.  (If the result
4320      * comes back in a register other than r0, you can override "result".)
4321      *
4322      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4323      * vCC (r1).  Useful for integer division and modulus.  Note that we
4324      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4325      * handles it correctly.
4326      *
4327      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4328      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4329      *      mul-float, div-float, rem-float
4330      */
4331     /* binop vAA, vBB, vCC */
4332     FETCH(r0, 1)                        @ r0<- CCBB
4333     mov     r9, rINST, lsr #8           @ r9<- AA
4334     mov     r3, r0, lsr #8              @ r3<- CC
4335     and     r2, r0, #255                @ r2<- BB
4336     GET_VREG(r1, r3)                    @ r1<- vCC
4337     GET_VREG(r0, r2)                    @ r0<- vBB
4338     .if 0
4339     cmp     r1, #0                      @ is second operand zero?
4340     beq     common_errDivideByZero
4341     .endif
4342
4343     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4344                                @ optional op; may set condition codes
4345     eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
4346     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4347     SET_VREG(r0, r9)               @ vAA<- r0
4348     GOTO_OPCODE(ip)                     @ jump to next instruction
4349     /* 11-14 instructions */
4350
4351
4352
4353 /* ------------------------------ */
4354     .balign 64
4355 .L_OP_SHL_INT: /* 0x98 */
4356 /* File: armv5te/OP_SHL_INT.S */
4357 /* File: armv5te/binop.S */
4358     /*
4359      * Generic 32-bit binary operation.  Provide an "instr" line that
4360      * specifies an instruction that performs "result = r0 op r1".
4361      * This could be an ARM instruction or a function call.  (If the result
4362      * comes back in a register other than r0, you can override "result".)
4363      *
4364      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4365      * vCC (r1).  Useful for integer division and modulus.  Note that we
4366      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4367      * handles it correctly.
4368      *
4369      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4370      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4371      *      mul-float, div-float, rem-float
4372      */
4373     /* binop vAA, vBB, vCC */
4374     FETCH(r0, 1)                        @ r0<- CCBB
4375     mov     r9, rINST, lsr #8           @ r9<- AA
4376     mov     r3, r0, lsr #8              @ r3<- CC
4377     and     r2, r0, #255                @ r2<- BB
4378     GET_VREG(r1, r3)                    @ r1<- vCC
4379     GET_VREG(r0, r2)                    @ r0<- vBB
4380     .if 0
4381     cmp     r1, #0                      @ is second operand zero?
4382     beq     common_errDivideByZero
4383     .endif
4384
4385     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4386     and     r1, r1, #31                           @ optional op; may set condition codes
4387     mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
4388     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4389     SET_VREG(r0, r9)               @ vAA<- r0
4390     GOTO_OPCODE(ip)                     @ jump to next instruction
4391     /* 11-14 instructions */
4392
4393
4394
4395 /* ------------------------------ */
4396     .balign 64
4397 .L_OP_SHR_INT: /* 0x99 */
4398 /* File: armv5te/OP_SHR_INT.S */
4399 /* File: armv5te/binop.S */
4400     /*
4401      * Generic 32-bit binary operation.  Provide an "instr" line that
4402      * specifies an instruction that performs "result = r0 op r1".
4403      * This could be an ARM instruction or a function call.  (If the result
4404      * comes back in a register other than r0, you can override "result".)
4405      *
4406      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4407      * vCC (r1).  Useful for integer division and modulus.  Note that we
4408      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4409      * handles it correctly.
4410      *
4411      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4412      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4413      *      mul-float, div-float, rem-float
4414      */
4415     /* binop vAA, vBB, vCC */
4416     FETCH(r0, 1)                        @ r0<- CCBB
4417     mov     r9, rINST, lsr #8           @ r9<- AA
4418     mov     r3, r0, lsr #8              @ r3<- CC
4419     and     r2, r0, #255                @ r2<- BB
4420     GET_VREG(r1, r3)                    @ r1<- vCC
4421     GET_VREG(r0, r2)                    @ r0<- vBB
4422     .if 0
4423     cmp     r1, #0                      @ is second operand zero?
4424     beq     common_errDivideByZero
4425     .endif
4426
4427     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4428     and     r1, r1, #31                           @ optional op; may set condition codes
4429     mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
4430     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4431     SET_VREG(r0, r9)               @ vAA<- r0
4432     GOTO_OPCODE(ip)                     @ jump to next instruction
4433     /* 11-14 instructions */
4434
4435
4436
4437 /* ------------------------------ */
4438     .balign 64
4439 .L_OP_USHR_INT: /* 0x9a */
4440 /* File: armv5te/OP_USHR_INT.S */
4441 /* File: armv5te/binop.S */
4442     /*
4443      * Generic 32-bit binary operation.  Provide an "instr" line that
4444      * specifies an instruction that performs "result = r0 op r1".
4445      * This could be an ARM instruction or a function call.  (If the result
4446      * comes back in a register other than r0, you can override "result".)
4447      *
4448      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4449      * vCC (r1).  Useful for integer division and modulus.  Note that we
4450      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4451      * handles it correctly.
4452      *
4453      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4454      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4455      *      mul-float, div-float, rem-float
4456      */
4457     /* binop vAA, vBB, vCC */
4458     FETCH(r0, 1)                        @ r0<- CCBB
4459     mov     r9, rINST, lsr #8           @ r9<- AA
4460     mov     r3, r0, lsr #8              @ r3<- CC
4461     and     r2, r0, #255                @ r2<- BB
4462     GET_VREG(r1, r3)                    @ r1<- vCC
4463     GET_VREG(r0, r2)                    @ r0<- vBB
4464     .if 0
4465     cmp     r1, #0                      @ is second operand zero?
4466     beq     common_errDivideByZero
4467     .endif
4468
4469     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4470     and     r1, r1, #31                           @ optional op; may set condition codes
4471     mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
4472     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4473     SET_VREG(r0, r9)               @ vAA<- r0
4474     GOTO_OPCODE(ip)                     @ jump to next instruction
4475     /* 11-14 instructions */
4476
4477
4478
4479 /* ------------------------------ */
4480     .balign 64
4481 .L_OP_ADD_LONG: /* 0x9b */
4482 /* File: armv5te/OP_ADD_LONG.S */
4483 /* File: armv5te/binopWide.S */
4484     /*
4485      * Generic 64-bit binary operation.  Provide an "instr" line that
4486      * specifies an instruction that performs "result = r0-r1 op r2-r3".
4487      * This could be an ARM instruction or a function call.  (If the result
4488      * comes back in a register other than r0, you can override "result".)
4489      *
4490      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4491      * vCC (r1).  Useful for integer division and modulus.
4492      *
4493      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4494      *      xor-long, add-double, sub-double, mul-double, div-double,
4495      *      rem-double
4496      *
4497      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4498      */
4499     /* binop vAA, vBB, vCC */
4500     FETCH(r0, 1)                        @ r0<- CCBB
4501     mov     r9, rINST, lsr #8           @ r9<- AA
4502     and     r2, r0, #255                @ r2<- BB
4503     mov     r3, r0, lsr #8              @ r3<- CC
4504     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4505     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4506     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4507     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4508     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4509     .if 0
4510     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4511     beq     common_errDivideByZero
4512     .endif
4513     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4514
4515     adds    r0, r0, r2                           @ optional op; may set condition codes
4516     adc     r1, r1, r3                              @ result<- op, r0-r3 changed
4517     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4518     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4519     GOTO_OPCODE(ip)                     @ jump to next instruction
4520     /* 14-17 instructions */
4521
4522
4523
4524 /* ------------------------------ */
4525     .balign 64
4526 .L_OP_SUB_LONG: /* 0x9c */
4527 /* File: armv5te/OP_SUB_LONG.S */
4528 /* File: armv5te/binopWide.S */
4529     /*
4530      * Generic 64-bit binary operation.  Provide an "instr" line that
4531      * specifies an instruction that performs "result = r0-r1 op r2-r3".
4532      * This could be an ARM instruction or a function call.  (If the result
4533      * comes back in a register other than r0, you can override "result".)
4534      *
4535      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4536      * vCC (r1).  Useful for integer division and modulus.
4537      *
4538      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4539      *      xor-long, add-double, sub-double, mul-double, div-double,
4540      *      rem-double
4541      *
4542      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4543      */
4544     /* binop vAA, vBB, vCC */
4545     FETCH(r0, 1)                        @ r0<- CCBB
4546     mov     r9, rINST, lsr #8           @ r9<- AA
4547     and     r2, r0, #255                @ r2<- BB
4548     mov     r3, r0, lsr #8              @ r3<- CC
4549     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4550     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4551     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4552     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4553     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4554     .if 0
4555     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4556     beq     common_errDivideByZero
4557     .endif
4558     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4559
4560     subs    r0, r0, r2                           @ optional op; may set condition codes
4561     sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
4562     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4563     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4564     GOTO_OPCODE(ip)                     @ jump to next instruction
4565     /* 14-17 instructions */
4566
4567
4568
4569 /* ------------------------------ */
4570     .balign 64
4571 .L_OP_MUL_LONG: /* 0x9d */
4572 /* File: armv5te/OP_MUL_LONG.S */
4573     /*
4574      * Signed 64-bit integer multiply.
4575      *
4576      * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
4577      *        WX
4578      *      x YZ
4579      *  --------
4580      *     ZW ZX
4581      *  YW YX
4582      *
4583      * The low word of the result holds ZX, the high word holds
4584      * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
4585      * it doesn't fit in the low 64 bits.
4586      *
4587      * Unlike most ARM math operations, multiply instructions have
4588      * restrictions on using the same register more than once (Rd and Rm
4589      * cannot be the same).
4590      */
4591     /* mul-long vAA, vBB, vCC */
4592     FETCH(r0, 1)                        @ r0<- CCBB
4593     and     r2, r0, #255                @ r2<- BB
4594     mov     r3, r0, lsr #8              @ r3<- CC
4595     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4596     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4597     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4598     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4599     mul     ip, r2, r1                  @  ip<- ZxW
4600     umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
4601     mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
4602     mov     r0, rINST, lsr #8           @ r0<- AA
4603     add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
4604     add     r0, rFP, r0, lsl #2         @ r0<- &fp[AA]
4605     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4606     b       .LOP_MUL_LONG_finish
4607
4608 /* ------------------------------ */
4609     .balign 64
4610 .L_OP_DIV_LONG: /* 0x9e */
4611 /* File: armv5te/OP_DIV_LONG.S */
4612 /* File: armv5te/binopWide.S */
4613     /*
4614      * Generic 64-bit binary operation.  Provide an "instr" line that
4615      * specifies an instruction that performs "result = r0-r1 op r2-r3".
4616      * This could be an ARM instruction or a function call.  (If the result
4617      * comes back in a register other than r0, you can override "result".)
4618      *
4619      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4620      * vCC (r1).  Useful for integer division and modulus.
4621      *
4622      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4623      *      xor-long, add-double, sub-double, mul-double, div-double,
4624      *      rem-double
4625      *
4626      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4627      */
4628     /* binop vAA, vBB, vCC */
4629     FETCH(r0, 1)                        @ r0<- CCBB
4630     mov     r9, rINST, lsr #8           @ r9<- AA
4631     and     r2, r0, #255                @ r2<- BB
4632     mov     r3, r0, lsr #8              @ r3<- CC
4633     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4634     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4635     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4636     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4637     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4638     .if 1
4639     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4640     beq     common_errDivideByZero
4641     .endif
4642     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4643
4644                                @ optional op; may set condition codes
4645     bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4646     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4647     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4648     GOTO_OPCODE(ip)                     @ jump to next instruction
4649     /* 14-17 instructions */
4650
4651
4652
4653 /* ------------------------------ */
4654     .balign 64
4655 .L_OP_REM_LONG: /* 0x9f */
4656 /* File: armv5te/OP_REM_LONG.S */
4657 /* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
4658 /* File: armv5te/binopWide.S */
4659     /*
4660      * Generic 64-bit binary operation.  Provide an "instr" line that
4661      * specifies an instruction that performs "result = r0-r1 op r2-r3".
4662      * This could be an ARM instruction or a function call.  (If the result
4663      * comes back in a register other than r0, you can override "result".)
4664      *
4665      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4666      * vCC (r1).  Useful for integer division and modulus.
4667      *
4668      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4669      *      xor-long, add-double, sub-double, mul-double, div-double,
4670      *      rem-double
4671      *
4672      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4673      */
4674     /* binop vAA, vBB, vCC */
4675     FETCH(r0, 1)                        @ r0<- CCBB
4676     mov     r9, rINST, lsr #8           @ r9<- AA
4677     and     r2, r0, #255                @ r2<- BB
4678     mov     r3, r0, lsr #8              @ r3<- CC
4679     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4680     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4681     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4682     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4683     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4684     .if 1
4685     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4686     beq     common_errDivideByZero
4687     .endif
4688     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4689
4690                                @ optional op; may set condition codes
4691     bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4692     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4693     stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
4694     GOTO_OPCODE(ip)                     @ jump to next instruction
4695     /* 14-17 instructions */
4696
4697
4698
4699 /* ------------------------------ */
4700     .balign 64
4701 .L_OP_AND_LONG: /* 0xa0 */
4702 /* File: armv5te/OP_AND_LONG.S */
4703 /* File: armv5te/binopWide.S */
4704     /*
4705      * Generic 64-bit binary operation.  Provide an "instr" line that
4706      * specifies an instruction that performs "result = r0-r1 op r2-r3".
4707      * This could be an ARM instruction or a function call.  (If the result
4708      * comes back in a register other than r0, you can override "result".)
4709      *
4710      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4711      * vCC (r1).  Useful for integer division and modulus.
4712      *
4713      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4714      *      xor-long, add-double, sub-double, mul-double, div-double,
4715      *      rem-double
4716      *
4717      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4718      */
4719     /* binop vAA, vBB, vCC */
4720     FETCH(r0, 1)                        @ r0<- CCBB
4721     mov     r9, rINST, lsr #8           @ r9<- AA
4722     and     r2, r0, #255                @ r2<- BB
4723     mov     r3, r0, lsr #8              @ r3<- CC
4724     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4725     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4726     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4727     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4728     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4729     .if 0
4730     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4731     beq     common_errDivideByZero
4732     .endif
4733     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4734
4735     and     r0, r0, r2                           @ optional op; may set condition codes
4736     and     r1, r1, r3                              @ result<- op, r0-r3 changed
4737     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4738     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4739     GOTO_OPCODE(ip)                     @ jump to next instruction
4740     /* 14-17 instructions */
4741
4742
4743
4744 /* ------------------------------ */
4745     .balign 64
4746 .L_OP_OR_LONG: /* 0xa1 */
4747 /* File: armv5te/OP_OR_LONG.S */
4748 /* File: armv5te/binopWide.S */
4749     /*
4750      * Generic 64-bit binary operation.  Provide an "instr" line that
4751      * specifies an instruction that performs "result = r0-r1 op r2-r3".
4752      * This could be an ARM instruction or a function call.  (If the result
4753      * comes back in a register other than r0, you can override "result".)
4754      *
4755      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4756      * vCC (r1).  Useful for integer division and modulus.
4757      *
4758      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4759      *      xor-long, add-double, sub-double, mul-double, div-double,
4760      *      rem-double
4761      *
4762      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4763      */
4764     /* binop vAA, vBB, vCC */
4765     FETCH(r0, 1)                        @ r0<- CCBB
4766     mov     r9, rINST, lsr #8           @ r9<- AA
4767     and     r2, r0, #255                @ r2<- BB
4768     mov     r3, r0, lsr #8              @ r3<- CC
4769     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4770     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4771     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4772     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4773     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4774     .if 0
4775     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4776     beq     common_errDivideByZero
4777     .endif
4778     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4779
4780     orr     r0, r0, r2                           @ optional op; may set condition codes
4781     orr     r1, r1, r3                              @ result<- op, r0-r3 changed
4782     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4783     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4784     GOTO_OPCODE(ip)                     @ jump to next instruction
4785     /* 14-17 instructions */
4786
4787
4788
4789 /* ------------------------------ */
4790     .balign 64
4791 .L_OP_XOR_LONG: /* 0xa2 */
4792 /* File: armv5te/OP_XOR_LONG.S */
4793 /* File: armv5te/binopWide.S */
4794     /*
4795      * Generic 64-bit binary operation.  Provide an "instr" line that
4796      * specifies an instruction that performs "result = r0-r1 op r2-r3".
4797      * This could be an ARM instruction or a function call.  (If the result
4798      * comes back in a register other than r0, you can override "result".)
4799      *
4800      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4801      * vCC (r1).  Useful for integer division and modulus.
4802      *
4803      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4804      *      xor-long, add-double, sub-double, mul-double, div-double,
4805      *      rem-double
4806      *
4807      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4808      */
4809     /* binop vAA, vBB, vCC */
4810     FETCH(r0, 1)                        @ r0<- CCBB
4811     mov     r9, rINST, lsr #8           @ r9<- AA
4812     and     r2, r0, #255                @ r2<- BB
4813     mov     r3, r0, lsr #8              @ r3<- CC
4814     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4815     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4816     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4817     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4818     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4819     .if 0
4820     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4821     beq     common_errDivideByZero
4822     .endif
4823     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4824
4825     eor     r0, r0, r2                           @ optional op; may set condition codes
4826     eor     r1, r1, r3                              @ result<- op, r0-r3 changed
4827     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4828     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4829     GOTO_OPCODE(ip)                     @ jump to next instruction
4830     /* 14-17 instructions */
4831
4832
4833
4834 /* ------------------------------ */
4835     .balign 64
4836 .L_OP_SHL_LONG: /* 0xa3 */
4837 /* File: armv5te/OP_SHL_LONG.S */
4838     /*
4839      * Long integer shift.  This is different from the generic 32/64-bit
4840      * binary operations because vAA/vBB are 64-bit but vCC (the shift
4841      * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4842      * 6 bits of the shift distance.
4843      */
4844     /* shl-long vAA, vBB, vCC */
4845     FETCH(r0, 1)                        @ r0<- CCBB
4846     mov     r9, rINST, lsr #8           @ r9<- AA
4847     and     r3, r0, #255                @ r3<- BB
4848     mov     r0, r0, lsr #8              @ r0<- CC
4849     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4850     GET_VREG(r2, r0)                    @ r2<- vCC
4851     ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4852     and     r2, r2, #63                 @ r2<- r2 & 0x3f
4853     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4854
4855     mov     r1, r1, asl r2              @  r1<- r1 << r2
4856     rsb     r3, r2, #32                 @  r3<- 32 - r2
4857     orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
4858     subs    ip, r2, #32                 @  ip<- r2 - 32
4859     movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
4860     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4861     b       .LOP_SHL_LONG_finish
4862
4863 /* ------------------------------ */
4864     .balign 64
4865 .L_OP_SHR_LONG: /* 0xa4 */
4866 /* File: armv5te/OP_SHR_LONG.S */
4867     /*
4868      * Long integer shift.  This is different from the generic 32/64-bit
4869      * binary operations because vAA/vBB are 64-bit but vCC (the shift
4870      * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4871      * 6 bits of the shift distance.
4872      */
4873     /* shr-long vAA, vBB, vCC */
4874     FETCH(r0, 1)                        @ r0<- CCBB
4875     mov     r9, rINST, lsr #8           @ r9<- AA
4876     and     r3, r0, #255                @ r3<- BB
4877     mov     r0, r0, lsr #8              @ r0<- CC
4878     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4879     GET_VREG(r2, r0)                    @ r2<- vCC
4880     ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4881     and     r2, r2, #63                 @ r0<- r0 & 0x3f
4882     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4883
4884     mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4885     rsb     r3, r2, #32                 @  r3<- 32 - r2
4886     orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4887     subs    ip, r2, #32                 @  ip<- r2 - 32
4888     movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
4889     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4890     b       .LOP_SHR_LONG_finish
4891
4892 /* ------------------------------ */
4893     .balign 64
4894 .L_OP_USHR_LONG: /* 0xa5 */
4895 /* File: armv5te/OP_USHR_LONG.S */
4896     /*
4897      * Long integer shift.  This is different from the generic 32/64-bit
4898      * binary operations because vAA/vBB are 64-bit but vCC (the shift
4899      * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4900      * 6 bits of the shift distance.
4901      */
4902     /* ushr-long vAA, vBB, vCC */
4903     FETCH(r0, 1)                        @ r0<- CCBB
4904     mov     r9, rINST, lsr #8           @ r9<- AA
4905     and     r3, r0, #255                @ r3<- BB
4906     mov     r0, r0, lsr #8              @ r0<- CC
4907     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4908     GET_VREG(r2, r0)                    @ r2<- vCC
4909     ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4910     and     r2, r2, #63                 @ r0<- r0 & 0x3f
4911     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4912
4913     mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4914     rsb     r3, r2, #32                 @  r3<- 32 - r2
4915     orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4916     subs    ip, r2, #32                 @  ip<- r2 - 32
4917     movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
4918     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4919     b       .LOP_USHR_LONG_finish
4920
4921 /* ------------------------------ */
4922     .balign 64
4923 .L_OP_ADD_FLOAT: /* 0xa6 */
4924 /* File: armv5te/OP_ADD_FLOAT.S */
4925 /* File: armv5te/binop.S */
4926     /*
4927      * Generic 32-bit binary operation.  Provide an "instr" line that
4928      * specifies an instruction that performs "result = r0 op r1".
4929      * This could be an ARM instruction or a function call.  (If the result
4930      * comes back in a register other than r0, you can override "result".)
4931      *
4932      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4933      * vCC (r1).  Useful for integer division and modulus.  Note that we
4934      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4935      * handles it correctly.
4936      *
4937      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4938      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4939      *      mul-float, div-float, rem-float
4940      */
4941     /* binop vAA, vBB, vCC */
4942     FETCH(r0, 1)                        @ r0<- CCBB
4943     mov     r9, rINST, lsr #8           @ r9<- AA
4944     mov     r3, r0, lsr #8              @ r3<- CC
4945     and     r2, r0, #255                @ r2<- BB
4946     GET_VREG(r1, r3)                    @ r1<- vCC
4947     GET_VREG(r0, r2)                    @ r0<- vBB
4948     .if 0
4949     cmp     r1, #0                      @ is second operand zero?
4950     beq     common_errDivideByZero
4951     .endif
4952
4953     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4954                                @ optional op; may set condition codes
4955     bl      __aeabi_fadd                              @ r0<- op, r0-r3 changed
4956     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4957     SET_VREG(r0, r9)               @ vAA<- r0
4958     GOTO_OPCODE(ip)                     @ jump to next instruction
4959     /* 11-14 instructions */
4960
4961
4962
4963 /* ------------------------------ */
4964     .balign 64
4965 .L_OP_SUB_FLOAT: /* 0xa7 */
4966 /* File: armv5te/OP_SUB_FLOAT.S */
4967 /* File: armv5te/binop.S */
4968     /*
4969      * Generic 32-bit binary operation.  Provide an "instr" line that
4970      * specifies an instruction that performs "result = r0 op r1".
4971      * This could be an ARM instruction or a function call.  (If the result
4972      * comes back in a register other than r0, you can override "result".)
4973      *
4974      * If "chkzero" is set to 1, we perform a divide-by-zero check on
4975      * vCC (r1).  Useful for integer division and modulus.  Note that we
4976      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4977      * handles it correctly.
4978      *
4979      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4980      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4981      *      mul-float, div-float, rem-float
4982      */
4983     /* binop vAA, vBB, vCC */
4984     FETCH(r0, 1)                        @ r0<- CCBB
4985     mov     r9, rINST, lsr #8           @ r9<- AA
4986     mov     r3, r0, lsr #8              @ r3<- CC
4987     and     r2, r0, #255                @ r2<- BB
4988     GET_VREG(r1, r3)                    @ r1<- vCC
4989     GET_VREG(r0, r2)                    @ r0<- vBB
4990     .if 0
4991     cmp     r1, #0                      @ is second operand zero?
4992     beq     common_errDivideByZero
4993     .endif
4994
4995     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4996                                @ optional op; may set condition codes
4997     bl      __aeabi_fsub                              @ r0<- op, r0-r3 changed
4998     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4999     SET_VREG(r0, r9)               @ vAA<- r0
5000     GOTO_OPCODE(ip)                     @ jump to next instruction
5001     /* 11-14 instructions */
5002
5003
5004
5005 /* ------------------------------ */
5006     .balign 64
5007 .L_OP_MUL_FLOAT: /* 0xa8 */
5008 /* File: armv5te/OP_MUL_FLOAT.S */
5009 /* File: armv5te/binop.S */
5010     /*
5011      * Generic 32-bit binary operation.  Provide an "instr" line that
5012      * specifies an instruction that performs "result = r0 op r1".
5013      * This could be an ARM instruction or a function call.  (If the result
5014      * comes back in a register other than r0, you can override "result".)
5015      *
5016      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5017      * vCC (r1).  Useful for integer division and modulus.  Note that we
5018      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5019      * handles it correctly.
5020      *
5021      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5022      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5023      *      mul-float, div-float, rem-float
5024      */
5025     /* binop vAA, vBB, vCC */
5026     FETCH(r0, 1)                        @ r0<- CCBB
5027     mov     r9, rINST, lsr #8           @ r9<- AA
5028     mov     r3, r0, lsr #8              @ r3<- CC
5029     and     r2, r0, #255                @ r2<- BB
5030     GET_VREG(r1, r3)                    @ r1<- vCC
5031     GET_VREG(r0, r2)                    @ r0<- vBB
5032     .if 0
5033     cmp     r1, #0                      @ is second operand zero?
5034     beq     common_errDivideByZero
5035     .endif
5036
5037     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5038                                @ optional op; may set condition codes
5039     bl      __aeabi_fmul                              @ r0<- op, r0-r3 changed
5040     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5041     SET_VREG(r0, r9)               @ vAA<- r0
5042     GOTO_OPCODE(ip)                     @ jump to next instruction
5043     /* 11-14 instructions */
5044
5045
5046
5047 /* ------------------------------ */
5048     .balign 64
5049 .L_OP_DIV_FLOAT: /* 0xa9 */
5050 /* File: armv5te/OP_DIV_FLOAT.S */
5051 /* File: armv5te/binop.S */
5052     /*
5053      * Generic 32-bit binary operation.  Provide an "instr" line that
5054      * specifies an instruction that performs "result = r0 op r1".
5055      * This could be an ARM instruction or a function call.  (If the result
5056      * comes back in a register other than r0, you can override "result".)
5057      *
5058      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5059      * vCC (r1).  Useful for integer division and modulus.  Note that we
5060      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5061      * handles it correctly.
5062      *
5063      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5064      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5065      *      mul-float, div-float, rem-float
5066      */
5067     /* binop vAA, vBB, vCC */
5068     FETCH(r0, 1)                        @ r0<- CCBB
5069     mov     r9, rINST, lsr #8           @ r9<- AA
5070     mov     r3, r0, lsr #8              @ r3<- CC
5071     and     r2, r0, #255                @ r2<- BB
5072     GET_VREG(r1, r3)                    @ r1<- vCC
5073     GET_VREG(r0, r2)                    @ r0<- vBB
5074     .if 0
5075     cmp     r1, #0                      @ is second operand zero?
5076     beq     common_errDivideByZero
5077     .endif
5078
5079     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5080                                @ optional op; may set condition codes
5081     bl      __aeabi_fdiv                              @ r0<- op, r0-r3 changed
5082     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5083     SET_VREG(r0, r9)               @ vAA<- r0
5084     GOTO_OPCODE(ip)                     @ jump to next instruction
5085     /* 11-14 instructions */
5086
5087
5088
5089 /* ------------------------------ */
5090     .balign 64
5091 .L_OP_REM_FLOAT: /* 0xaa */
5092 /* File: armv5te/OP_REM_FLOAT.S */
5093 /* EABI doesn't define a float remainder function, but libm does */
5094 /* File: armv5te/binop.S */
5095     /*
5096      * Generic 32-bit binary operation.  Provide an "instr" line that
5097      * specifies an instruction that performs "result = r0 op r1".
5098      * This could be an ARM instruction or a function call.  (If the result
5099      * comes back in a register other than r0, you can override "result".)
5100      *
5101      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5102      * vCC (r1).  Useful for integer division and modulus.  Note that we
5103      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5104      * handles it correctly.
5105      *
5106      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5107      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5108      *      mul-float, div-float, rem-float
5109      */
5110     /* binop vAA, vBB, vCC */
5111     FETCH(r0, 1)                        @ r0<- CCBB
5112     mov     r9, rINST, lsr #8           @ r9<- AA
5113     mov     r3, r0, lsr #8              @ r3<- CC
5114     and     r2, r0, #255                @ r2<- BB
5115     GET_VREG(r1, r3)                    @ r1<- vCC
5116     GET_VREG(r0, r2)                    @ r0<- vBB
5117     .if 0
5118     cmp     r1, #0                      @ is second operand zero?
5119     beq     common_errDivideByZero
5120     .endif
5121
5122     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5123                                @ optional op; may set condition codes
5124     bl      fmodf                              @ r0<- op, r0-r3 changed
5125     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5126     SET_VREG(r0, r9)               @ vAA<- r0
5127     GOTO_OPCODE(ip)                     @ jump to next instruction
5128     /* 11-14 instructions */
5129
5130
5131
5132 /* ------------------------------ */
5133     .balign 64
5134 .L_OP_ADD_DOUBLE: /* 0xab */
5135 /* File: armv5te/OP_ADD_DOUBLE.S */
5136 /* File: armv5te/binopWide.S */
5137     /*
5138      * Generic 64-bit binary operation.  Provide an "instr" line that
5139      * specifies an instruction that performs "result = r0-r1 op r2-r3".
5140      * This could be an ARM instruction or a function call.  (If the result
5141      * comes back in a register other than r0, you can override "result".)
5142      *
5143      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5144      * vCC (r1).  Useful for integer division and modulus.
5145      *
5146      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5147      *      xor-long, add-double, sub-double, mul-double, div-double,
5148      *      rem-double
5149      *
5150      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5151      */
5152     /* binop vAA, vBB, vCC */
5153     FETCH(r0, 1)                        @ r0<- CCBB
5154     mov     r9, rINST, lsr #8           @ r9<- AA
5155     and     r2, r0, #255                @ r2<- BB
5156     mov     r3, r0, lsr #8              @ r3<- CC
5157     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5158     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5159     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5160     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5161     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5162     .if 0
5163     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5164     beq     common_errDivideByZero
5165     .endif
5166     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5167
5168                                @ optional op; may set condition codes
5169     bl      __aeabi_dadd                              @ result<- op, r0-r3 changed
5170     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5171     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5172     GOTO_OPCODE(ip)                     @ jump to next instruction
5173     /* 14-17 instructions */
5174
5175
5176
5177 /* ------------------------------ */
5178     .balign 64
5179 .L_OP_SUB_DOUBLE: /* 0xac */
5180 /* File: armv5te/OP_SUB_DOUBLE.S */
5181 /* File: armv5te/binopWide.S */
5182     /*
5183      * Generic 64-bit binary operation.  Provide an "instr" line that
5184      * specifies an instruction that performs "result = r0-r1 op r2-r3".
5185      * This could be an ARM instruction or a function call.  (If the result
5186      * comes back in a register other than r0, you can override "result".)
5187      *
5188      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5189      * vCC (r1).  Useful for integer division and modulus.
5190      *
5191      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5192      *      xor-long, add-double, sub-double, mul-double, div-double,
5193      *      rem-double
5194      *
5195      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5196      */
5197     /* binop vAA, vBB, vCC */
5198     FETCH(r0, 1)                        @ r0<- CCBB
5199     mov     r9, rINST, lsr #8           @ r9<- AA
5200     and     r2, r0, #255                @ r2<- BB
5201     mov     r3, r0, lsr #8              @ r3<- CC
5202     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5203     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5204     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5205     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5206     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5207     .if 0
5208     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5209     beq     common_errDivideByZero
5210     .endif
5211     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5212
5213                                @ optional op; may set condition codes
5214     bl      __aeabi_dsub                              @ result<- op, r0-r3 changed
5215     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5216     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5217     GOTO_OPCODE(ip)                     @ jump to next instruction
5218     /* 14-17 instructions */
5219
5220
5221
5222 /* ------------------------------ */
5223     .balign 64
5224 .L_OP_MUL_DOUBLE: /* 0xad */
5225 /* File: armv5te/OP_MUL_DOUBLE.S */
5226 /* File: armv5te/binopWide.S */
5227     /*
5228      * Generic 64-bit binary operation.  Provide an "instr" line that
5229      * specifies an instruction that performs "result = r0-r1 op r2-r3".
5230      * This could be an ARM instruction or a function call.  (If the result
5231      * comes back in a register other than r0, you can override "result".)
5232      *
5233      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5234      * vCC (r1).  Useful for integer division and modulus.
5235      *
5236      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5237      *      xor-long, add-double, sub-double, mul-double, div-double,
5238      *      rem-double
5239      *
5240      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5241      */
5242     /* binop vAA, vBB, vCC */
5243     FETCH(r0, 1)                        @ r0<- CCBB
5244     mov     r9, rINST, lsr #8           @ r9<- AA
5245     and     r2, r0, #255                @ r2<- BB
5246     mov     r3, r0, lsr #8              @ r3<- CC
5247     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5248     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5249     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5250     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5251     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5252     .if 0
5253     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5254     beq     common_errDivideByZero
5255     .endif
5256     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5257
5258                                @ optional op; may set condition codes
5259     bl      __aeabi_dmul                              @ result<- op, r0-r3 changed
5260     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5261     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5262     GOTO_OPCODE(ip)                     @ jump to next instruction
5263     /* 14-17 instructions */
5264
5265
5266
5267 /* ------------------------------ */
5268     .balign 64
5269 .L_OP_DIV_DOUBLE: /* 0xae */
5270 /* File: armv5te/OP_DIV_DOUBLE.S */
5271 /* File: armv5te/binopWide.S */
5272     /*
5273      * Generic 64-bit binary operation.  Provide an "instr" line that
5274      * specifies an instruction that performs "result = r0-r1 op r2-r3".
5275      * This could be an ARM instruction or a function call.  (If the result
5276      * comes back in a register other than r0, you can override "result".)
5277      *
5278      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5279      * vCC (r1).  Useful for integer division and modulus.
5280      *
5281      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5282      *      xor-long, add-double, sub-double, mul-double, div-double,
5283      *      rem-double
5284      *
5285      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5286      */
5287     /* binop vAA, vBB, vCC */
5288     FETCH(r0, 1)                        @ r0<- CCBB
5289     mov     r9, rINST, lsr #8           @ r9<- AA
5290     and     r2, r0, #255                @ r2<- BB
5291     mov     r3, r0, lsr #8              @ r3<- CC
5292     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5293     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5294     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5295     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5296     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5297     .if 0
5298     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5299     beq     common_errDivideByZero
5300     .endif
5301     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5302
5303                                @ optional op; may set condition codes
5304     bl      __aeabi_ddiv                              @ result<- op, r0-r3 changed
5305     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5306     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5307     GOTO_OPCODE(ip)                     @ jump to next instruction
5308     /* 14-17 instructions */
5309
5310
5311
5312 /* ------------------------------ */
5313     .balign 64
5314 .L_OP_REM_DOUBLE: /* 0xaf */
5315 /* File: armv5te/OP_REM_DOUBLE.S */
5316 /* EABI doesn't define a double remainder function, but libm does */
5317 /* File: armv5te/binopWide.S */
5318     /*
5319      * Generic 64-bit binary operation.  Provide an "instr" line that
5320      * specifies an instruction that performs "result = r0-r1 op r2-r3".
5321      * This could be an ARM instruction or a function call.  (If the result
5322      * comes back in a register other than r0, you can override "result".)
5323      *
5324      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5325      * vCC (r1).  Useful for integer division and modulus.
5326      *
5327      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5328      *      xor-long, add-double, sub-double, mul-double, div-double,
5329      *      rem-double
5330      *
5331      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5332      */
5333     /* binop vAA, vBB, vCC */
5334     FETCH(r0, 1)                        @ r0<- CCBB
5335     mov     r9, rINST, lsr #8           @ r9<- AA
5336     and     r2, r0, #255                @ r2<- BB
5337     mov     r3, r0, lsr #8              @ r3<- CC
5338     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5339     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5340     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5341     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5342     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5343     .if 0
5344     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5345     beq     common_errDivideByZero
5346     .endif
5347     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5348
5349                                @ optional op; may set condition codes
5350     bl      fmod                              @ result<- op, r0-r3 changed
5351     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5352     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5353     GOTO_OPCODE(ip)                     @ jump to next instruction
5354     /* 14-17 instructions */
5355
5356
5357
5358 /* ------------------------------ */
5359     .balign 64
5360 .L_OP_ADD_INT_2ADDR: /* 0xb0 */
5361 /* File: armv5te/OP_ADD_INT_2ADDR.S */
5362 /* File: armv5te/binop2addr.S */
5363     /*
5364      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5365      * that specifies an instruction that performs "result = r0 op r1".
5366      * This could be an ARM instruction or a function call.  (If the result
5367      * comes back in a register other than r0, you can override "result".)
5368      *
5369      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5370      * vCC (r1).  Useful for integer division and modulus.
5371      *
5372      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5373      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5374      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5375      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5376      */
5377     /* binop/2addr vA, vB */
5378     mov     r9, rINST, lsr #8           @ r9<- A+
5379     mov     r3, rINST, lsr #12          @ r3<- B
5380     and     r9, r9, #15
5381     GET_VREG(r0, r9)                    @ r0<- vA
5382     GET_VREG(r1, r3)                    @ r1<- vB
5383     .if 0
5384     cmp     r1, #0                      @ is second operand zero?
5385     beq     common_errDivideByZero
5386     .endif
5387     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5388
5389                                @ optional op; may set condition codes
5390     add     r0, r0, r1                              @ r0<- op, r0-r3 changed
5391     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5392     SET_VREG(r0, r9)               @ vAA<- r0
5393     GOTO_OPCODE(ip)                     @ jump to next instruction
5394     /* 10-13 instructions */
5395
5396
5397
5398 /* ------------------------------ */
5399     .balign 64
5400 .L_OP_SUB_INT_2ADDR: /* 0xb1 */
5401 /* File: armv5te/OP_SUB_INT_2ADDR.S */
5402 /* File: armv5te/binop2addr.S */
5403     /*
5404      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5405      * that specifies an instruction that performs "result = r0 op r1".
5406      * This could be an ARM instruction or a function call.  (If the result
5407      * comes back in a register other than r0, you can override "result".)
5408      *
5409      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5410      * vCC (r1).  Useful for integer division and modulus.
5411      *
5412      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5413      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5414      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5415      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5416      */
5417     /* binop/2addr vA, vB */
5418     mov     r9, rINST, lsr #8           @ r9<- A+
5419     mov     r3, rINST, lsr #12          @ r3<- B
5420     and     r9, r9, #15
5421     GET_VREG(r0, r9)                    @ r0<- vA
5422     GET_VREG(r1, r3)                    @ r1<- vB
5423     .if 0
5424     cmp     r1, #0                      @ is second operand zero?
5425     beq     common_errDivideByZero
5426     .endif
5427     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5428
5429                                @ optional op; may set condition codes
5430     sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
5431     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5432     SET_VREG(r0, r9)               @ vAA<- r0
5433     GOTO_OPCODE(ip)                     @ jump to next instruction
5434     /* 10-13 instructions */
5435
5436
5437
5438 /* ------------------------------ */
5439     .balign 64
5440 .L_OP_MUL_INT_2ADDR: /* 0xb2 */
5441 /* File: armv5te/OP_MUL_INT_2ADDR.S */
5442 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
5443 /* File: armv5te/binop2addr.S */
5444     /*
5445      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5446      * that specifies an instruction that performs "result = r0 op r1".
5447      * This could be an ARM instruction or a function call.  (If the result
5448      * comes back in a register other than r0, you can override "result".)
5449      *
5450      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5451      * vCC (r1).  Useful for integer division and modulus.
5452      *
5453      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5454      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5455      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5456      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5457      */
5458     /* binop/2addr vA, vB */
5459     mov     r9, rINST, lsr #8           @ r9<- A+
5460     mov     r3, rINST, lsr #12          @ r3<- B
5461     and     r9, r9, #15
5462     GET_VREG(r0, r9)                    @ r0<- vA
5463     GET_VREG(r1, r3)                    @ r1<- vB
5464     .if 0
5465     cmp     r1, #0                      @ is second operand zero?
5466     beq     common_errDivideByZero
5467     .endif
5468     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5469
5470                                @ optional op; may set condition codes
5471     mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
5472     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5473     SET_VREG(r0, r9)               @ vAA<- r0
5474     GOTO_OPCODE(ip)                     @ jump to next instruction
5475     /* 10-13 instructions */
5476
5477
5478
5479 /* ------------------------------ */
5480     .balign 64
5481 .L_OP_DIV_INT_2ADDR: /* 0xb3 */
5482 /* File: armv5te/OP_DIV_INT_2ADDR.S */
5483 /* File: armv5te/binop2addr.S */
5484     /*
5485      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5486      * that specifies an instruction that performs "result = r0 op r1".
5487      * This could be an ARM instruction or a function call.  (If the result
5488      * comes back in a register other than r0, you can override "result".)
5489      *
5490      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5491      * vCC (r1).  Useful for integer division and modulus.
5492      *
5493      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5494      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5495      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5496      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5497      */
5498     /* binop/2addr vA, vB */
5499     mov     r9, rINST, lsr #8           @ r9<- A+
5500     mov     r3, rINST, lsr #12          @ r3<- B
5501     and     r9, r9, #15
5502     GET_VREG(r0, r9)                    @ r0<- vA
5503     GET_VREG(r1, r3)                    @ r1<- vB
5504     .if 1
5505     cmp     r1, #0                      @ is second operand zero?
5506     beq     common_errDivideByZero
5507     .endif
5508     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5509
5510                                @ optional op; may set condition codes
5511     bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
5512     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5513     SET_VREG(r0, r9)               @ vAA<- r0
5514     GOTO_OPCODE(ip)                     @ jump to next instruction
5515     /* 10-13 instructions */
5516
5517
5518
5519 /* ------------------------------ */
5520     .balign 64
5521 .L_OP_REM_INT_2ADDR: /* 0xb4 */
5522 /* File: armv5te/OP_REM_INT_2ADDR.S */
5523 /* idivmod returns quotient in r0 and remainder in r1 */
5524 /* File: armv5te/binop2addr.S */
5525     /*
5526      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5527      * that specifies an instruction that performs "result = r0 op r1".
5528      * This could be an ARM instruction or a function call.  (If the result
5529      * comes back in a register other than r0, you can override "result".)
5530      *
5531      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5532      * vCC (r1).  Useful for integer division and modulus.
5533      *
5534      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5535      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5536      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5537      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5538      */
5539     /* binop/2addr vA, vB */
5540     mov     r9, rINST, lsr #8           @ r9<- A+
5541     mov     r3, rINST, lsr #12          @ r3<- B
5542     and     r9, r9, #15
5543     GET_VREG(r0, r9)                    @ r0<- vA
5544     GET_VREG(r1, r3)                    @ r1<- vB
5545     .if 1
5546     cmp     r1, #0                      @ is second operand zero?
5547     beq     common_errDivideByZero
5548     .endif
5549     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5550
5551                                @ optional op; may set condition codes
5552     bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
5553     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5554     SET_VREG(r1, r9)               @ vAA<- r1
5555     GOTO_OPCODE(ip)                     @ jump to next instruction
5556     /* 10-13 instructions */
5557
5558
5559
5560 /* ------------------------------ */
5561     .balign 64
5562 .L_OP_AND_INT_2ADDR: /* 0xb5 */
5563 /* File: armv5te/OP_AND_INT_2ADDR.S */
5564 /* File: armv5te/binop2addr.S */
5565     /*
5566      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5567      * that specifies an instruction that performs "result = r0 op r1".
5568      * This could be an ARM instruction or a function call.  (If the result
5569      * comes back in a register other than r0, you can override "result".)
5570      *
5571      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5572      * vCC (r1).  Useful for integer division and modulus.
5573      *
5574      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5575      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5576      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5577      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5578      */
5579     /* binop/2addr vA, vB */
5580     mov     r9, rINST, lsr #8           @ r9<- A+
5581     mov     r3, rINST, lsr #12          @ r3<- B
5582     and     r9, r9, #15
5583     GET_VREG(r0, r9)                    @ r0<- vA
5584     GET_VREG(r1, r3)                    @ r1<- vB
5585     .if 0
5586     cmp     r1, #0                      @ is second operand zero?
5587     beq     common_errDivideByZero
5588     .endif
5589     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5590
5591                                @ optional op; may set condition codes
5592     and     r0, r0, r1                              @ r0<- op, r0-r3 changed
5593     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5594     SET_VREG(r0, r9)               @ vAA<- r0
5595     GOTO_OPCODE(ip)                     @ jump to next instruction
5596     /* 10-13 instructions */
5597
5598
5599
5600 /* ------------------------------ */
5601     .balign 64
5602 .L_OP_OR_INT_2ADDR: /* 0xb6 */
5603 /* File: armv5te/OP_OR_INT_2ADDR.S */
5604 /* File: armv5te/binop2addr.S */
5605     /*
5606      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5607      * that specifies an instruction that performs "result = r0 op r1".
5608      * This could be an ARM instruction or a function call.  (If the result
5609      * comes back in a register other than r0, you can override "result".)
5610      *
5611      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5612      * vCC (r1).  Useful for integer division and modulus.
5613      *
5614      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5615      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5616      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5617      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5618      */
5619     /* binop/2addr vA, vB */
5620     mov     r9, rINST, lsr #8           @ r9<- A+
5621     mov     r3, rINST, lsr #12          @ r3<- B
5622     and     r9, r9, #15
5623     GET_VREG(r0, r9)                    @ r0<- vA
5624     GET_VREG(r1, r3)                    @ r1<- vB
5625     .if 0
5626     cmp     r1, #0                      @ is second operand zero?
5627     beq     common_errDivideByZero
5628     .endif
5629     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5630
5631                                @ optional op; may set condition codes
5632     orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
5633     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5634     SET_VREG(r0, r9)               @ vAA<- r0
5635     GOTO_OPCODE(ip)                     @ jump to next instruction
5636     /* 10-13 instructions */
5637
5638
5639
5640 /* ------------------------------ */
5641     .balign 64
5642 .L_OP_XOR_INT_2ADDR: /* 0xb7 */
5643 /* File: armv5te/OP_XOR_INT_2ADDR.S */
5644 /* File: armv5te/binop2addr.S */
5645     /*
5646      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5647      * that specifies an instruction that performs "result = r0 op r1".
5648      * This could be an ARM instruction or a function call.  (If the result
5649      * comes back in a register other than r0, you can override "result".)
5650      *
5651      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5652      * vCC (r1).  Useful for integer division and modulus.
5653      *
5654      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5655      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5656      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5657      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5658      */
5659     /* binop/2addr vA, vB */
5660     mov     r9, rINST, lsr #8           @ r9<- A+
5661     mov     r3, rINST, lsr #12          @ r3<- B
5662     and     r9, r9, #15
5663     GET_VREG(r0, r9)                    @ r0<- vA
5664     GET_VREG(r1, r3)                    @ r1<- vB
5665     .if 0
5666     cmp     r1, #0                      @ is second operand zero?
5667     beq     common_errDivideByZero
5668     .endif
5669     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5670
5671                                @ optional op; may set condition codes
5672     eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
5673     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5674     SET_VREG(r0, r9)               @ vAA<- r0
5675     GOTO_OPCODE(ip)                     @ jump to next instruction
5676     /* 10-13 instructions */
5677
5678
5679
5680 /* ------------------------------ */
5681     .balign 64
5682 .L_OP_SHL_INT_2ADDR: /* 0xb8 */
5683 /* File: armv5te/OP_SHL_INT_2ADDR.S */
5684 /* File: armv5te/binop2addr.S */
5685     /*
5686      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5687      * that specifies an instruction that performs "result = r0 op r1".
5688      * This could be an ARM instruction or a function call.  (If the result
5689      * comes back in a register other than r0, you can override "result".)
5690      *
5691      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5692      * vCC (r1).  Useful for integer division and modulus.
5693      *
5694      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5695      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5696      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5697      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5698      */
5699     /* binop/2addr vA, vB */
5700     mov     r9, rINST, lsr #8           @ r9<- A+
5701     mov     r3, rINST, lsr #12          @ r3<- B
5702     and     r9, r9, #15
5703     GET_VREG(r0, r9)                    @ r0<- vA
5704     GET_VREG(r1, r3)                    @ r1<- vB
5705     .if 0
5706     cmp     r1, #0                      @ is second operand zero?
5707     beq     common_errDivideByZero
5708     .endif
5709     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5710
5711     and     r1, r1, #31                           @ optional op; may set condition codes
5712     mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
5713     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5714     SET_VREG(r0, r9)               @ vAA<- r0
5715     GOTO_OPCODE(ip)                     @ jump to next instruction
5716     /* 10-13 instructions */
5717
5718
5719
5720 /* ------------------------------ */
5721     .balign 64
5722 .L_OP_SHR_INT_2ADDR: /* 0xb9 */
5723 /* File: armv5te/OP_SHR_INT_2ADDR.S */
5724 /* File: armv5te/binop2addr.S */
5725     /*
5726      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5727      * that specifies an instruction that performs "result = r0 op r1".
5728      * This could be an ARM instruction or a function call.  (If the result
5729      * comes back in a register other than r0, you can override "result".)
5730      *
5731      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5732      * vCC (r1).  Useful for integer division and modulus.
5733      *
5734      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5735      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5736      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5737      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5738      */
5739     /* binop/2addr vA, vB */
5740     mov     r9, rINST, lsr #8           @ r9<- A+
5741     mov     r3, rINST, lsr #12          @ r3<- B
5742     and     r9, r9, #15
5743     GET_VREG(r0, r9)                    @ r0<- vA
5744     GET_VREG(r1, r3)                    @ r1<- vB
5745     .if 0
5746     cmp     r1, #0                      @ is second operand zero?
5747     beq     common_errDivideByZero
5748     .endif
5749     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5750
5751     and     r1, r1, #31                           @ optional op; may set condition codes
5752     mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
5753     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5754     SET_VREG(r0, r9)               @ vAA<- r0
5755     GOTO_OPCODE(ip)                     @ jump to next instruction
5756     /* 10-13 instructions */
5757
5758
5759
5760 /* ------------------------------ */
5761     .balign 64
5762 .L_OP_USHR_INT_2ADDR: /* 0xba */
5763 /* File: armv5te/OP_USHR_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(r0, r9)                    @ r0<- vA
5784     GET_VREG(r1, r3)                    @ r1<- vB
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     and     r1, r1, #31                           @ optional op; may set condition codes
5792     mov     r0, r0, lsr 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_ADD_LONG_2ADDR: /* 0xbb */
5803 /* File: armv5te/OP_ADD_LONG_2ADDR.S */
5804 /* File: armv5te/binopWide2addr.S */
5805     /*
5806      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5807      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
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-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5815      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5816      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5817      *      rem-double/2addr
5818      */
5819     /* binop/2addr vA, vB */
5820     mov     r9, rINST, lsr #8           @ r9<- A+
5821     mov     r1, rINST, lsr #12          @ r1<- B
5822     and     r9, r9, #15
5823     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5824     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5825     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5826     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5827     .if 0
5828     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5829     beq     common_errDivideByZero
5830     .endif
5831     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5832
5833     adds    r0, r0, r2                           @ optional op; may set condition codes
5834     adc     r1, r1, r3                              @ result<- op, r0-r3 changed
5835     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5836     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5837     GOTO_OPCODE(ip)                     @ jump to next instruction
5838     /* 12-15 instructions */
5839
5840
5841
5842 /* ------------------------------ */
5843     .balign 64
5844 .L_OP_SUB_LONG_2ADDR: /* 0xbc */
5845 /* File: armv5te/OP_SUB_LONG_2ADDR.S */
5846 /* File: armv5te/binopWide2addr.S */
5847     /*
5848      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5849      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5850      * This could be an ARM instruction or a function call.  (If the result
5851      * comes back in a register other than r0, you can override "result".)
5852      *
5853      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5854      * vCC (r1).  Useful for integer division and modulus.
5855      *
5856      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5857      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5858      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5859      *      rem-double/2addr
5860      */
5861     /* binop/2addr vA, vB */
5862     mov     r9, rINST, lsr #8           @ r9<- A+
5863     mov     r1, rINST, lsr #12          @ r1<- B
5864     and     r9, r9, #15
5865     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5866     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5867     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5868     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5869     .if 0
5870     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5871     beq     common_errDivideByZero
5872     .endif
5873     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5874
5875     subs    r0, r0, r2                           @ optional op; may set condition codes
5876     sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
5877     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5878     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5879     GOTO_OPCODE(ip)                     @ jump to next instruction
5880     /* 12-15 instructions */
5881
5882
5883
5884 /* ------------------------------ */
5885     .balign 64
5886 .L_OP_MUL_LONG_2ADDR: /* 0xbd */
5887 /* File: armv5te/OP_MUL_LONG_2ADDR.S */
5888     /*
5889      * Signed 64-bit integer multiply, "/2addr" version.
5890      *
5891      * See OP_MUL_LONG for an explanation.
5892      *
5893      * We get a little tight on registers, so to avoid looking up &fp[A]
5894      * again we stuff it into rINST.
5895      */
5896     /* mul-long/2addr vA, vB */
5897     mov     r9, rINST, lsr #8           @ r9<- A+
5898     mov     r1, rINST, lsr #12          @ r1<- B
5899     and     r9, r9, #15
5900     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5901     add     rINST, rFP, r9, lsl #2      @ rINST<- &fp[A]
5902     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5903     ldmia   rINST, {r0-r1}              @ r0/r1<- vAA/vAA+1
5904     mul     ip, r2, r1                  @  ip<- ZxW
5905     umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
5906     mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
5907     mov     r0, rINST                   @ r0<- &fp[A] (free up rINST)
5908     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5909     add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
5910     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5911     stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
5912     GOTO_OPCODE(ip)                     @ jump to next instruction
5913
5914
5915 /* ------------------------------ */
5916     .balign 64
5917 .L_OP_DIV_LONG_2ADDR: /* 0xbe */
5918 /* File: armv5te/OP_DIV_LONG_2ADDR.S */
5919 /* File: armv5te/binopWide2addr.S */
5920     /*
5921      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5922      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5923      * This could be an ARM instruction or a function call.  (If the result
5924      * comes back in a register other than r0, you can override "result".)
5925      *
5926      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5927      * vCC (r1).  Useful for integer division and modulus.
5928      *
5929      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5930      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5931      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5932      *      rem-double/2addr
5933      */
5934     /* binop/2addr vA, vB */
5935     mov     r9, rINST, lsr #8           @ r9<- A+
5936     mov     r1, rINST, lsr #12          @ r1<- B
5937     and     r9, r9, #15
5938     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5939     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5940     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5941     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5942     .if 1
5943     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5944     beq     common_errDivideByZero
5945     .endif
5946     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5947
5948                                @ optional op; may set condition codes
5949     bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5950     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5951     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5952     GOTO_OPCODE(ip)                     @ jump to next instruction
5953     /* 12-15 instructions */
5954
5955
5956
5957 /* ------------------------------ */
5958     .balign 64
5959 .L_OP_REM_LONG_2ADDR: /* 0xbf */
5960 /* File: armv5te/OP_REM_LONG_2ADDR.S */
5961 /* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
5962 /* File: armv5te/binopWide2addr.S */
5963     /*
5964      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5965      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5966      * This could be an ARM instruction or a function call.  (If the result
5967      * comes back in a register other than r0, you can override "result".)
5968      *
5969      * If "chkzero" is set to 1, we perform a divide-by-zero check on
5970      * vCC (r1).  Useful for integer division and modulus.
5971      *
5972      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5973      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5974      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5975      *      rem-double/2addr
5976      */
5977     /* binop/2addr vA, vB */
5978     mov     r9, rINST, lsr #8           @ r9<- A+
5979     mov     r1, rINST, lsr #12          @ r1<- B
5980     and     r9, r9, #15
5981     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5982     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5983     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5984     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5985     .if 1
5986     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5987     beq     common_errDivideByZero
5988     .endif
5989     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5990
5991                                @ optional op; may set condition codes
5992     bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5993     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5994     stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
5995     GOTO_OPCODE(ip)                     @ jump to next instruction
5996     /* 12-15 instructions */
5997
5998
5999
6000 /* ------------------------------ */
6001     .balign 64
6002 .L_OP_AND_LONG_2ADDR: /* 0xc0 */
6003 /* File: armv5te/OP_AND_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     and     r0, r0, r2                           @ optional op; may set condition codes
6034     and     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_OR_LONG_2ADDR: /* 0xc1 */
6045 /* File: armv5te/OP_OR_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     orr     r0, r0, r2                           @ optional op; may set condition codes
6076     orr     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_XOR_LONG_2ADDR: /* 0xc2 */
6087 /* File: armv5te/OP_XOR_LONG_2ADDR.S */
6088 /* File: armv5te/binopWide2addr.S */
6089     /*
6090      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6091      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6092      * This could be an ARM instruction or a function call.  (If the result
6093      * comes back in a register other than r0, you can override "result".)
6094      *
6095      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6096      * vCC (r1).  Useful for integer division and modulus.
6097      *
6098      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6099      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6100      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6101      *      rem-double/2addr
6102      */
6103     /* binop/2addr vA, vB */
6104     mov     r9, rINST, lsr #8           @ r9<- A+
6105     mov     r1, rINST, lsr #12          @ r1<- B
6106     and     r9, r9, #15
6107     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6108     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6109     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6110     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6111     .if 0
6112     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6113     beq     common_errDivideByZero
6114     .endif
6115     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6116
6117     eor     r0, r0, r2                           @ optional op; may set condition codes
6118     eor     r1, r1, r3                              @ result<- op, r0-r3 changed
6119     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6120     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6121     GOTO_OPCODE(ip)                     @ jump to next instruction
6122     /* 12-15 instructions */
6123
6124
6125
6126 /* ------------------------------ */
6127     .balign 64
6128 .L_OP_SHL_LONG_2ADDR: /* 0xc3 */
6129 /* File: armv5te/OP_SHL_LONG_2ADDR.S */
6130     /*
6131      * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6132      * 32-bit shift distance.
6133      */
6134     /* shl-long/2addr vA, vB */
6135     mov     r9, rINST, lsr #8           @ r9<- A+
6136     mov     r3, rINST, lsr #12          @ r3<- B
6137     and     r9, r9, #15
6138     GET_VREG(r2, r3)                    @ r2<- vB
6139     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6140     and     r2, r2, #63                 @ r2<- r2 & 0x3f
6141     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6142
6143     mov     r1, r1, asl r2              @  r1<- r1 << r2
6144     rsb     r3, r2, #32                 @  r3<- 32 - r2
6145     orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
6146     subs    ip, r2, #32                 @  ip<- r2 - 32
6147     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6148     movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
6149     mov     r0, r0, asl r2              @  r0<- r0 << r2
6150     b       .LOP_SHL_LONG_2ADDR_finish
6151
6152 /* ------------------------------ */
6153     .balign 64
6154 .L_OP_SHR_LONG_2ADDR: /* 0xc4 */
6155 /* File: armv5te/OP_SHR_LONG_2ADDR.S */
6156     /*
6157      * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6158      * 32-bit shift distance.
6159      */
6160     /* shr-long/2addr vA, vB */
6161     mov     r9, rINST, lsr #8           @ r9<- A+
6162     mov     r3, rINST, lsr #12          @ r3<- B
6163     and     r9, r9, #15
6164     GET_VREG(r2, r3)                    @ r2<- vB
6165     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6166     and     r2, r2, #63                 @ r2<- r2 & 0x3f
6167     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6168
6169     mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6170     rsb     r3, r2, #32                 @  r3<- 32 - r2
6171     orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6172     subs    ip, r2, #32                 @  ip<- r2 - 32
6173     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6174     movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
6175     mov     r1, r1, asr r2              @  r1<- r1 >> r2
6176     b       .LOP_SHR_LONG_2ADDR_finish
6177
6178 /* ------------------------------ */
6179     .balign 64
6180 .L_OP_USHR_LONG_2ADDR: /* 0xc5 */
6181 /* File: armv5te/OP_USHR_LONG_2ADDR.S */
6182     /*
6183      * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6184      * 32-bit shift distance.
6185      */
6186     /* ushr-long/2addr vA, vB */
6187     mov     r9, rINST, lsr #8           @ r9<- A+
6188     mov     r3, rINST, lsr #12          @ r3<- B
6189     and     r9, r9, #15
6190     GET_VREG(r2, r3)                    @ r2<- vB
6191     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6192     and     r2, r2, #63                 @ r2<- r2 & 0x3f
6193     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6194
6195     mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6196     rsb     r3, r2, #32                 @  r3<- 32 - r2
6197     orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6198     subs    ip, r2, #32                 @  ip<- r2 - 32
6199     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6200     movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
6201     mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
6202     b       .LOP_USHR_LONG_2ADDR_finish
6203
6204 /* ------------------------------ */
6205     .balign 64
6206 .L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
6207 /* File: armv5te/OP_ADD_FLOAT_2ADDR.S */
6208 /* File: armv5te/binop2addr.S */
6209     /*
6210      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6211      * that specifies an instruction that performs "result = r0 op r1".
6212      * This could be an ARM instruction or a function call.  (If the result
6213      * comes back in a register other than r0, you can override "result".)
6214      *
6215      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6216      * vCC (r1).  Useful for integer division and modulus.
6217      *
6218      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6219      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6220      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6221      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6222      */
6223     /* binop/2addr vA, vB */
6224     mov     r9, rINST, lsr #8           @ r9<- A+
6225     mov     r3, rINST, lsr #12          @ r3<- B
6226     and     r9, r9, #15
6227     GET_VREG(r0, r9)                    @ r0<- vA
6228     GET_VREG(r1, r3)                    @ r1<- vB
6229     .if 0
6230     cmp     r1, #0                      @ is second operand zero?
6231     beq     common_errDivideByZero
6232     .endif
6233     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6234
6235                                @ optional op; may set condition codes
6236     bl      __aeabi_fadd                              @ r0<- op, r0-r3 changed
6237     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6238     SET_VREG(r0, r9)               @ vAA<- r0
6239     GOTO_OPCODE(ip)                     @ jump to next instruction
6240     /* 10-13 instructions */
6241
6242
6243
6244 /* ------------------------------ */
6245     .balign 64
6246 .L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
6247 /* File: armv5te/OP_SUB_FLOAT_2ADDR.S */
6248 /* File: armv5te/binop2addr.S */
6249     /*
6250      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6251      * that specifies an instruction that performs "result = r0 op r1".
6252      * This could be an ARM instruction or a function call.  (If the result
6253      * comes back in a register other than r0, you can override "result".)
6254      *
6255      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6256      * vCC (r1).  Useful for integer division and modulus.
6257      *
6258      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6259      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6260      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6261      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6262      */
6263     /* binop/2addr vA, vB */
6264     mov     r9, rINST, lsr #8           @ r9<- A+
6265     mov     r3, rINST, lsr #12          @ r3<- B
6266     and     r9, r9, #15
6267     GET_VREG(r0, r9)                    @ r0<- vA
6268     GET_VREG(r1, r3)                    @ r1<- vB
6269     .if 0
6270     cmp     r1, #0                      @ is second operand zero?
6271     beq     common_errDivideByZero
6272     .endif
6273     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6274
6275                                @ optional op; may set condition codes
6276     bl      __aeabi_fsub                              @ r0<- op, r0-r3 changed
6277     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6278     SET_VREG(r0, r9)               @ vAA<- r0
6279     GOTO_OPCODE(ip)                     @ jump to next instruction
6280     /* 10-13 instructions */
6281
6282
6283
6284 /* ------------------------------ */
6285     .balign 64
6286 .L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
6287 /* File: armv5te/OP_MUL_FLOAT_2ADDR.S */
6288 /* File: armv5te/binop2addr.S */
6289     /*
6290      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6291      * that specifies an instruction that performs "result = r0 op r1".
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-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6299      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6300      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6301      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6302      */
6303     /* binop/2addr vA, vB */
6304     mov     r9, rINST, lsr #8           @ r9<- A+
6305     mov     r3, rINST, lsr #12          @ r3<- B
6306     and     r9, r9, #15
6307     GET_VREG(r0, r9)                    @ r0<- vA
6308     GET_VREG(r1, r3)                    @ r1<- vB
6309     .if 0
6310     cmp     r1, #0                      @ is second operand zero?
6311     beq     common_errDivideByZero
6312     .endif
6313     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6314
6315                                @ optional op; may set condition codes
6316     bl      __aeabi_fmul                              @ r0<- op, r0-r3 changed
6317     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6318     SET_VREG(r0, r9)               @ vAA<- r0
6319     GOTO_OPCODE(ip)                     @ jump to next instruction
6320     /* 10-13 instructions */
6321
6322
6323
6324 /* ------------------------------ */
6325     .balign 64
6326 .L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
6327 /* File: armv5te/OP_DIV_FLOAT_2ADDR.S */
6328 /* File: armv5te/binop2addr.S */
6329     /*
6330      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6331      * that specifies an instruction that performs "result = r0 op r1".
6332      * This could be an ARM instruction or a function call.  (If the result
6333      * comes back in a register other than r0, you can override "result".)
6334      *
6335      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6336      * vCC (r1).  Useful for integer division and modulus.
6337      *
6338      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6339      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6340      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6341      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6342      */
6343     /* binop/2addr vA, vB */
6344     mov     r9, rINST, lsr #8           @ r9<- A+
6345     mov     r3, rINST, lsr #12          @ r3<- B
6346     and     r9, r9, #15
6347     GET_VREG(r0, r9)                    @ r0<- vA
6348     GET_VREG(r1, r3)                    @ r1<- vB
6349     .if 0
6350     cmp     r1, #0                      @ is second operand zero?
6351     beq     common_errDivideByZero
6352     .endif
6353     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6354
6355                                @ optional op; may set condition codes
6356     bl      __aeabi_fdiv                              @ r0<- op, r0-r3 changed
6357     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6358     SET_VREG(r0, r9)               @ vAA<- r0
6359     GOTO_OPCODE(ip)                     @ jump to next instruction
6360     /* 10-13 instructions */
6361
6362
6363
6364 /* ------------------------------ */
6365     .balign 64
6366 .L_OP_REM_FLOAT_2ADDR: /* 0xca */
6367 /* File: armv5te/OP_REM_FLOAT_2ADDR.S */
6368 /* EABI doesn't define a float remainder function, but libm does */
6369 /* File: armv5te/binop2addr.S */
6370     /*
6371      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6372      * that specifies an instruction that performs "result = r0 op r1".
6373      * This could be an ARM instruction or a function call.  (If the result
6374      * comes back in a register other than r0, you can override "result".)
6375      *
6376      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6377      * vCC (r1).  Useful for integer division and modulus.
6378      *
6379      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6380      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6381      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6382      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6383      */
6384     /* binop/2addr vA, vB */
6385     mov     r9, rINST, lsr #8           @ r9<- A+
6386     mov     r3, rINST, lsr #12          @ r3<- B
6387     and     r9, r9, #15
6388     GET_VREG(r0, r9)                    @ r0<- vA
6389     GET_VREG(r1, r3)                    @ r1<- vB
6390     .if 0
6391     cmp     r1, #0                      @ is second operand zero?
6392     beq     common_errDivideByZero
6393     .endif
6394     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6395
6396                                @ optional op; may set condition codes
6397     bl      fmodf                              @ r0<- op, r0-r3 changed
6398     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6399     SET_VREG(r0, r9)               @ vAA<- r0
6400     GOTO_OPCODE(ip)                     @ jump to next instruction
6401     /* 10-13 instructions */
6402
6403
6404
6405 /* ------------------------------ */
6406     .balign 64
6407 .L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
6408 /* File: armv5te/OP_ADD_DOUBLE_2ADDR.S */
6409 /* File: armv5te/binopWide2addr.S */
6410     /*
6411      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6412      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6413      * This could be an ARM instruction or a function call.  (If the result
6414      * comes back in a register other than r0, you can override "result".)
6415      *
6416      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6417      * vCC (r1).  Useful for integer division and modulus.
6418      *
6419      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6420      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6421      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6422      *      rem-double/2addr
6423      */
6424     /* binop/2addr vA, vB */
6425     mov     r9, rINST, lsr #8           @ r9<- A+
6426     mov     r1, rINST, lsr #12          @ r1<- B
6427     and     r9, r9, #15
6428     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6429     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6430     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6431     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6432     .if 0
6433     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6434     beq     common_errDivideByZero
6435     .endif
6436     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6437
6438                                @ optional op; may set condition codes
6439     bl      __aeabi_dadd                              @ result<- op, r0-r3 changed
6440     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6441     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6442     GOTO_OPCODE(ip)                     @ jump to next instruction
6443     /* 12-15 instructions */
6444
6445
6446
6447 /* ------------------------------ */
6448     .balign 64
6449 .L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
6450 /* File: armv5te/OP_SUB_DOUBLE_2ADDR.S */
6451 /* File: armv5te/binopWide2addr.S */
6452     /*
6453      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6454      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6455      * This could be an ARM instruction or a function call.  (If the result
6456      * comes back in a register other than r0, you can override "result".)
6457      *
6458      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6459      * vCC (r1).  Useful for integer division and modulus.
6460      *
6461      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6462      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6463      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6464      *      rem-double/2addr
6465      */
6466     /* binop/2addr vA, vB */
6467     mov     r9, rINST, lsr #8           @ r9<- A+
6468     mov     r1, rINST, lsr #12          @ r1<- B
6469     and     r9, r9, #15
6470     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6471     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6472     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6473     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6474     .if 0
6475     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6476     beq     common_errDivideByZero
6477     .endif
6478     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6479
6480                                @ optional op; may set condition codes
6481     bl      __aeabi_dsub                              @ result<- op, r0-r3 changed
6482     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6483     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6484     GOTO_OPCODE(ip)                     @ jump to next instruction
6485     /* 12-15 instructions */
6486
6487
6488
6489 /* ------------------------------ */
6490     .balign 64
6491 .L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
6492 /* File: armv5te/OP_MUL_DOUBLE_2ADDR.S */
6493 /* File: armv5te/binopWide2addr.S */
6494     /*
6495      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6496      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6497      * This could be an ARM instruction or a function call.  (If the result
6498      * comes back in a register other than r0, you can override "result".)
6499      *
6500      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6501      * vCC (r1).  Useful for integer division and modulus.
6502      *
6503      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6504      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6505      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6506      *      rem-double/2addr
6507      */
6508     /* binop/2addr vA, vB */
6509     mov     r9, rINST, lsr #8           @ r9<- A+
6510     mov     r1, rINST, lsr #12          @ r1<- B
6511     and     r9, r9, #15
6512     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6513     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6514     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6515     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6516     .if 0
6517     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6518     beq     common_errDivideByZero
6519     .endif
6520     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6521
6522                                @ optional op; may set condition codes
6523     bl      __aeabi_dmul                              @ result<- op, r0-r3 changed
6524     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6525     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6526     GOTO_OPCODE(ip)                     @ jump to next instruction
6527     /* 12-15 instructions */
6528
6529
6530
6531 /* ------------------------------ */
6532     .balign 64
6533 .L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
6534 /* File: armv5te/OP_DIV_DOUBLE_2ADDR.S */
6535 /* File: armv5te/binopWide2addr.S */
6536     /*
6537      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6538      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6539      * This could be an ARM instruction or a function call.  (If the result
6540      * comes back in a register other than r0, you can override "result".)
6541      *
6542      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6543      * vCC (r1).  Useful for integer division and modulus.
6544      *
6545      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6546      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6547      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6548      *      rem-double/2addr
6549      */
6550     /* binop/2addr vA, vB */
6551     mov     r9, rINST, lsr #8           @ r9<- A+
6552     mov     r1, rINST, lsr #12          @ r1<- B
6553     and     r9, r9, #15
6554     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6555     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6556     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6557     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6558     .if 0
6559     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6560     beq     common_errDivideByZero
6561     .endif
6562     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6563
6564                                @ optional op; may set condition codes
6565     bl      __aeabi_ddiv                              @ result<- op, r0-r3 changed
6566     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6567     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6568     GOTO_OPCODE(ip)                     @ jump to next instruction
6569     /* 12-15 instructions */
6570
6571
6572
6573 /* ------------------------------ */
6574     .balign 64
6575 .L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
6576 /* File: armv5te/OP_REM_DOUBLE_2ADDR.S */
6577 /* EABI doesn't define a double remainder function, but libm does */
6578 /* File: armv5te/binopWide2addr.S */
6579     /*
6580      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6581      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6582      * This could be an ARM instruction or a function call.  (If the result
6583      * comes back in a register other than r0, you can override "result".)
6584      *
6585      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6586      * vCC (r1).  Useful for integer division and modulus.
6587      *
6588      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6589      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6590      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6591      *      rem-double/2addr
6592      */
6593     /* binop/2addr vA, vB */
6594     mov     r9, rINST, lsr #8           @ r9<- A+
6595     mov     r1, rINST, lsr #12          @ r1<- B
6596     and     r9, r9, #15
6597     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6598     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6599     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6600     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6601     .if 0
6602     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6603     beq     common_errDivideByZero
6604     .endif
6605     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6606
6607                                @ optional op; may set condition codes
6608     bl      fmod                              @ result<- op, r0-r3 changed
6609     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6610     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6611     GOTO_OPCODE(ip)                     @ jump to next instruction
6612     /* 12-15 instructions */
6613
6614
6615
6616 /* ------------------------------ */
6617     .balign 64
6618 .L_OP_ADD_INT_LIT16: /* 0xd0 */
6619 /* File: armv5te/OP_ADD_INT_LIT16.S */
6620 /* File: armv5te/binopLit16.S */
6621     /*
6622      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6623      * that specifies an instruction that performs "result = r0 op r1".
6624      * This could be an ARM instruction or a function call.  (If the result
6625      * comes back in a register other than r0, you can override "result".)
6626      *
6627      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6628      * vCC (r1).  Useful for integer division and modulus.
6629      *
6630      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6631      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6632      */
6633     /* binop/lit16 vA, vB, #+CCCC */
6634     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6635     mov     r2, rINST, lsr #12          @ r2<- B
6636     mov     r9, rINST, lsr #8           @ r9<- A+
6637     GET_VREG(r0, r2)                    @ r0<- vB
6638     and     r9, r9, #15
6639     .if 0
6640     cmp     r1, #0                      @ is second operand zero?
6641     beq     common_errDivideByZero
6642     .endif
6643     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6644
6645     add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6646     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6647     SET_VREG(r0, r9)               @ vAA<- r0
6648     GOTO_OPCODE(ip)                     @ jump to next instruction
6649     /* 10-13 instructions */
6650
6651
6652
6653 /* ------------------------------ */
6654     .balign 64
6655 .L_OP_RSUB_INT: /* 0xd1 */
6656 /* File: armv5te/OP_RSUB_INT.S */
6657 /* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
6658 /* File: armv5te/binopLit16.S */
6659     /*
6660      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6661      * that specifies an instruction that performs "result = r0 op r1".
6662      * This could be an ARM instruction or a function call.  (If the result
6663      * comes back in a register other than r0, you can override "result".)
6664      *
6665      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6666      * vCC (r1).  Useful for integer division and modulus.
6667      *
6668      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6669      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6670      */
6671     /* binop/lit16 vA, vB, #+CCCC */
6672     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6673     mov     r2, rINST, lsr #12          @ r2<- B
6674     mov     r9, rINST, lsr #8           @ r9<- A+
6675     GET_VREG(r0, r2)                    @ r0<- vB
6676     and     r9, r9, #15
6677     .if 0
6678     cmp     r1, #0                      @ is second operand zero?
6679     beq     common_errDivideByZero
6680     .endif
6681     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6682
6683     rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6684     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6685     SET_VREG(r0, r9)               @ vAA<- r0
6686     GOTO_OPCODE(ip)                     @ jump to next instruction
6687     /* 10-13 instructions */
6688
6689
6690
6691 /* ------------------------------ */
6692     .balign 64
6693 .L_OP_MUL_INT_LIT16: /* 0xd2 */
6694 /* File: armv5te/OP_MUL_INT_LIT16.S */
6695 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6696 /* File: armv5te/binopLit16.S */
6697     /*
6698      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6699      * that specifies an instruction that performs "result = r0 op r1".
6700      * This could be an ARM instruction or a function call.  (If the result
6701      * comes back in a register other than r0, you can override "result".)
6702      *
6703      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6704      * vCC (r1).  Useful for integer division and modulus.
6705      *
6706      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6707      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6708      */
6709     /* binop/lit16 vA, vB, #+CCCC */
6710     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6711     mov     r2, rINST, lsr #12          @ r2<- B
6712     mov     r9, rINST, lsr #8           @ r9<- A+
6713     GET_VREG(r0, r2)                    @ r0<- vB
6714     and     r9, r9, #15
6715     .if 0
6716     cmp     r1, #0                      @ is second operand zero?
6717     beq     common_errDivideByZero
6718     .endif
6719     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6720
6721     mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6722     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6723     SET_VREG(r0, r9)               @ vAA<- r0
6724     GOTO_OPCODE(ip)                     @ jump to next instruction
6725     /* 10-13 instructions */
6726
6727
6728
6729 /* ------------------------------ */
6730     .balign 64
6731 .L_OP_DIV_INT_LIT16: /* 0xd3 */
6732 /* File: armv5te/OP_DIV_INT_LIT16.S */
6733 /* File: armv5te/binopLit16.S */
6734     /*
6735      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6736      * that specifies an instruction that performs "result = r0 op r1".
6737      * This could be an ARM instruction or a function call.  (If the result
6738      * comes back in a register other than r0, you can override "result".)
6739      *
6740      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6741      * vCC (r1).  Useful for integer division and modulus.
6742      *
6743      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6744      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6745      */
6746     /* binop/lit16 vA, vB, #+CCCC */
6747     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6748     mov     r2, rINST, lsr #12          @ r2<- B
6749     mov     r9, rINST, lsr #8           @ r9<- A+
6750     GET_VREG(r0, r2)                    @ r0<- vB
6751     and     r9, r9, #15
6752     .if 1
6753     cmp     r1, #0                      @ is second operand zero?
6754     beq     common_errDivideByZero
6755     .endif
6756     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6757
6758     bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6759     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6760     SET_VREG(r0, r9)               @ vAA<- r0
6761     GOTO_OPCODE(ip)                     @ jump to next instruction
6762     /* 10-13 instructions */
6763
6764
6765
6766 /* ------------------------------ */
6767     .balign 64
6768 .L_OP_REM_INT_LIT16: /* 0xd4 */
6769 /* File: armv5te/OP_REM_INT_LIT16.S */
6770 /* idivmod returns quotient in r0 and remainder in r1 */
6771 /* File: armv5te/binopLit16.S */
6772     /*
6773      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6774      * that specifies an instruction that performs "result = r0 op r1".
6775      * This could be an ARM instruction or a function call.  (If the result
6776      * comes back in a register other than r0, you can override "result".)
6777      *
6778      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6779      * vCC (r1).  Useful for integer division and modulus.
6780      *
6781      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6782      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6783      */
6784     /* binop/lit16 vA, vB, #+CCCC */
6785     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6786     mov     r2, rINST, lsr #12          @ r2<- B
6787     mov     r9, rINST, lsr #8           @ r9<- A+
6788     GET_VREG(r0, r2)                    @ r0<- vB
6789     and     r9, r9, #15
6790     .if 1
6791     cmp     r1, #0                      @ is second operand zero?
6792     beq     common_errDivideByZero
6793     .endif
6794     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6795
6796     bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6797     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6798     SET_VREG(r1, r9)               @ vAA<- r1
6799     GOTO_OPCODE(ip)                     @ jump to next instruction
6800     /* 10-13 instructions */
6801
6802
6803
6804 /* ------------------------------ */
6805     .balign 64
6806 .L_OP_AND_INT_LIT16: /* 0xd5 */
6807 /* File: armv5te/OP_AND_INT_LIT16.S */
6808 /* File: armv5te/binopLit16.S */
6809     /*
6810      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6811      * that specifies an instruction that performs "result = r0 op r1".
6812      * This could be an ARM instruction or a function call.  (If the result
6813      * comes back in a register other than r0, you can override "result".)
6814      *
6815      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6816      * vCC (r1).  Useful for integer division and modulus.
6817      *
6818      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6819      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6820      */
6821     /* binop/lit16 vA, vB, #+CCCC */
6822     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6823     mov     r2, rINST, lsr #12          @ r2<- B
6824     mov     r9, rINST, lsr #8           @ r9<- A+
6825     GET_VREG(r0, r2)                    @ r0<- vB
6826     and     r9, r9, #15
6827     .if 0
6828     cmp     r1, #0                      @ is second operand zero?
6829     beq     common_errDivideByZero
6830     .endif
6831     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6832
6833     and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6834     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6835     SET_VREG(r0, r9)               @ vAA<- r0
6836     GOTO_OPCODE(ip)                     @ jump to next instruction
6837     /* 10-13 instructions */
6838
6839
6840
6841 /* ------------------------------ */
6842     .balign 64
6843 .L_OP_OR_INT_LIT16: /* 0xd6 */
6844 /* File: armv5te/OP_OR_INT_LIT16.S */
6845 /* File: armv5te/binopLit16.S */
6846     /*
6847      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6848      * that specifies an instruction that performs "result = r0 op r1".
6849      * This could be an ARM instruction or a function call.  (If the result
6850      * comes back in a register other than r0, you can override "result".)
6851      *
6852      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6853      * vCC (r1).  Useful for integer division and modulus.
6854      *
6855      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6856      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6857      */
6858     /* binop/lit16 vA, vB, #+CCCC */
6859     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6860     mov     r2, rINST, lsr #12          @ r2<- B
6861     mov     r9, rINST, lsr #8           @ r9<- A+
6862     GET_VREG(r0, r2)                    @ r0<- vB
6863     and     r9, r9, #15
6864     .if 0
6865     cmp     r1, #0                      @ is second operand zero?
6866     beq     common_errDivideByZero
6867     .endif
6868     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6869
6870     orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6871     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6872     SET_VREG(r0, r9)               @ vAA<- r0
6873     GOTO_OPCODE(ip)                     @ jump to next instruction
6874     /* 10-13 instructions */
6875
6876
6877
6878 /* ------------------------------ */
6879     .balign 64
6880 .L_OP_XOR_INT_LIT16: /* 0xd7 */
6881 /* File: armv5te/OP_XOR_INT_LIT16.S */
6882 /* File: armv5te/binopLit16.S */
6883     /*
6884      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6885      * that specifies an instruction that performs "result = r0 op r1".
6886      * This could be an ARM instruction or a function call.  (If the result
6887      * comes back in a register other than r0, you can override "result".)
6888      *
6889      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6890      * vCC (r1).  Useful for integer division and modulus.
6891      *
6892      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6893      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6894      */
6895     /* binop/lit16 vA, vB, #+CCCC */
6896     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6897     mov     r2, rINST, lsr #12          @ r2<- B
6898     mov     r9, rINST, lsr #8           @ r9<- A+
6899     GET_VREG(r0, r2)                    @ r0<- vB
6900     and     r9, r9, #15
6901     .if 0
6902     cmp     r1, #0                      @ is second operand zero?
6903     beq     common_errDivideByZero
6904     .endif
6905     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6906
6907     eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
6908     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6909     SET_VREG(r0, r9)               @ vAA<- r0
6910     GOTO_OPCODE(ip)                     @ jump to next instruction
6911     /* 10-13 instructions */
6912
6913
6914
6915 /* ------------------------------ */
6916     .balign 64
6917 .L_OP_ADD_INT_LIT8: /* 0xd8 */
6918 /* File: armv5te/OP_ADD_INT_LIT8.S */
6919 /* File: armv5te/binopLit8.S */
6920     /*
6921      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6922      * that specifies an instruction that performs "result = r0 op r1".
6923      * This could be an ARM instruction or a function call.  (If the result
6924      * comes back in a register other than r0, you can override "result".)
6925      *
6926      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6927      * vCC (r1).  Useful for integer division and modulus.
6928      *
6929      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6930      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6931      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6932      */
6933     /* binop/lit8 vAA, vBB, #+CC */
6934     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6935     mov     r9, rINST, lsr #8           @ r9<- AA
6936     and     r2, r3, #255                @ r2<- BB
6937     GET_VREG(r0, r2)                    @ r0<- vBB
6938     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6939     .if 0
6940     @cmp     r1, #0                      @ is second operand zero?
6941     beq     common_errDivideByZero
6942     .endif
6943     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6944
6945                                @ optional op; may set condition codes
6946     add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6947     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6948     SET_VREG(r0, r9)               @ vAA<- r0
6949     GOTO_OPCODE(ip)                     @ jump to next instruction
6950     /* 10-12 instructions */
6951
6952
6953
6954 /* ------------------------------ */
6955     .balign 64
6956 .L_OP_RSUB_INT_LIT8: /* 0xd9 */
6957 /* File: armv5te/OP_RSUB_INT_LIT8.S */
6958 /* File: armv5te/binopLit8.S */
6959     /*
6960      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6961      * that specifies an instruction that performs "result = r0 op r1".
6962      * This could be an ARM instruction or a function call.  (If the result
6963      * comes back in a register other than r0, you can override "result".)
6964      *
6965      * If "chkzero" is set to 1, we perform a divide-by-zero check on
6966      * vCC (r1).  Useful for integer division and modulus.
6967      *
6968      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6969      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6970      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6971      */
6972     /* binop/lit8 vAA, vBB, #+CC */
6973     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6974     mov     r9, rINST, lsr #8           @ r9<- AA
6975     and     r2, r3, #255                @ r2<- BB
6976     GET_VREG(r0, r2)                    @ r0<- vBB
6977     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6978     .if 0
6979     @cmp     r1, #0                      @ is second operand zero?
6980     beq     common_errDivideByZero
6981     .endif
6982     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6983
6984                                @ optional op; may set condition codes
6985     rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6986     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6987     SET_VREG(r0, r9)               @ vAA<- r0
6988     GOTO_OPCODE(ip)                     @ jump to next instruction
6989     /* 10-12 instructions */
6990
6991
6992
6993 /* ------------------------------ */
6994     .balign 64
6995 .L_OP_MUL_INT_LIT8: /* 0xda */
6996 /* File: armv5te/OP_MUL_INT_LIT8.S */
6997 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6998 /* File: armv5te/binopLit8.S */
6999     /*
7000      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7001      * that specifies an instruction that performs "result = r0 op r1".
7002      * This could be an ARM instruction or a function call.  (If the result
7003      * comes back in a register other than r0, you can override "result".)
7004      *
7005      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7006      * vCC (r1).  Useful for integer division and modulus.
7007      *
7008      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7009      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7010      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7011      */
7012     /* binop/lit8 vAA, vBB, #+CC */
7013     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7014     mov     r9, rINST, lsr #8           @ r9<- AA
7015     and     r2, r3, #255                @ r2<- BB
7016     GET_VREG(r0, r2)                    @ r0<- vBB
7017     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7018     .if 0
7019     @cmp     r1, #0                      @ is second operand zero?
7020     beq     common_errDivideByZero
7021     .endif
7022     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7023
7024                                @ optional op; may set condition codes
7025     mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
7026     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7027     SET_VREG(r0, r9)               @ vAA<- r0
7028     GOTO_OPCODE(ip)                     @ jump to next instruction
7029     /* 10-12 instructions */
7030
7031
7032
7033 /* ------------------------------ */
7034     .balign 64
7035 .L_OP_DIV_INT_LIT8: /* 0xdb */
7036 /* File: armv5te/OP_DIV_INT_LIT8.S */
7037 /* File: armv5te/binopLit8.S */
7038     /*
7039      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7040      * that specifies an instruction that performs "result = r0 op r1".
7041      * This could be an ARM instruction or a function call.  (If the result
7042      * comes back in a register other than r0, you can override "result".)
7043      *
7044      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7045      * vCC (r1).  Useful for integer division and modulus.
7046      *
7047      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7048      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7049      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7050      */
7051     /* binop/lit8 vAA, vBB, #+CC */
7052     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7053     mov     r9, rINST, lsr #8           @ r9<- AA
7054     and     r2, r3, #255                @ r2<- BB
7055     GET_VREG(r0, r2)                    @ r0<- vBB
7056     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7057     .if 1
7058     @cmp     r1, #0                      @ is second operand zero?
7059     beq     common_errDivideByZero
7060     .endif
7061     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7062
7063                                @ optional op; may set condition codes
7064     bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
7065     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7066     SET_VREG(r0, r9)               @ vAA<- r0
7067     GOTO_OPCODE(ip)                     @ jump to next instruction
7068     /* 10-12 instructions */
7069
7070
7071
7072 /* ------------------------------ */
7073     .balign 64
7074 .L_OP_REM_INT_LIT8: /* 0xdc */
7075 /* File: armv5te/OP_REM_INT_LIT8.S */
7076 /* idivmod returns quotient in r0 and remainder in r1 */
7077 /* File: armv5te/binopLit8.S */
7078     /*
7079      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7080      * that specifies an instruction that performs "result = r0 op r1".
7081      * This could be an ARM instruction or a function call.  (If the result
7082      * comes back in a register other than r0, you can override "result".)
7083      *
7084      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7085      * vCC (r1).  Useful for integer division and modulus.
7086      *
7087      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7088      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7089      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7090      */
7091     /* binop/lit8 vAA, vBB, #+CC */
7092     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7093     mov     r9, rINST, lsr #8           @ r9<- AA
7094     and     r2, r3, #255                @ r2<- BB
7095     GET_VREG(r0, r2)                    @ r0<- vBB
7096     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7097     .if 1
7098     @cmp     r1, #0                      @ is second operand zero?
7099     beq     common_errDivideByZero
7100     .endif
7101     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7102
7103                                @ optional op; may set condition codes
7104     bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
7105     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7106     SET_VREG(r1, r9)               @ vAA<- r1
7107     GOTO_OPCODE(ip)                     @ jump to next instruction
7108     /* 10-12 instructions */
7109
7110
7111
7112 /* ------------------------------ */
7113     .balign 64
7114 .L_OP_AND_INT_LIT8: /* 0xdd */
7115 /* File: armv5te/OP_AND_INT_LIT8.S */
7116 /* File: armv5te/binopLit8.S */
7117     /*
7118      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7119      * that specifies an instruction that performs "result = r0 op r1".
7120      * This could be an ARM instruction or a function call.  (If the result
7121      * comes back in a register other than r0, you can override "result".)
7122      *
7123      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7124      * vCC (r1).  Useful for integer division and modulus.
7125      *
7126      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7127      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7128      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7129      */
7130     /* binop/lit8 vAA, vBB, #+CC */
7131     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7132     mov     r9, rINST, lsr #8           @ r9<- AA
7133     and     r2, r3, #255                @ r2<- BB
7134     GET_VREG(r0, r2)                    @ r0<- vBB
7135     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7136     .if 0
7137     @cmp     r1, #0                      @ is second operand zero?
7138     beq     common_errDivideByZero
7139     .endif
7140     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7141
7142                                @ optional op; may set condition codes
7143     and     r0, r0, r1                              @ r0<- op, r0-r3 changed
7144     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7145     SET_VREG(r0, r9)               @ vAA<- r0
7146     GOTO_OPCODE(ip)                     @ jump to next instruction
7147     /* 10-12 instructions */
7148
7149
7150
7151 /* ------------------------------ */
7152     .balign 64
7153 .L_OP_OR_INT_LIT8: /* 0xde */
7154 /* File: armv5te/OP_OR_INT_LIT8.S */
7155 /* File: armv5te/binopLit8.S */
7156     /*
7157      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7158      * that specifies an instruction that performs "result = r0 op r1".
7159      * This could be an ARM instruction or a function call.  (If the result
7160      * comes back in a register other than r0, you can override "result".)
7161      *
7162      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7163      * vCC (r1).  Useful for integer division and modulus.
7164      *
7165      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7166      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7167      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7168      */
7169     /* binop/lit8 vAA, vBB, #+CC */
7170     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7171     mov     r9, rINST, lsr #8           @ r9<- AA
7172     and     r2, r3, #255                @ r2<- BB
7173     GET_VREG(r0, r2)                    @ r0<- vBB
7174     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7175     .if 0
7176     @cmp     r1, #0                      @ is second operand zero?
7177     beq     common_errDivideByZero
7178     .endif
7179     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7180
7181                                @ optional op; may set condition codes
7182     orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
7183     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7184     SET_VREG(r0, r9)               @ vAA<- r0
7185     GOTO_OPCODE(ip)                     @ jump to next instruction
7186     /* 10-12 instructions */
7187
7188
7189
7190 /* ------------------------------ */
7191     .balign 64
7192 .L_OP_XOR_INT_LIT8: /* 0xdf */
7193 /* File: armv5te/OP_XOR_INT_LIT8.S */
7194 /* File: armv5te/binopLit8.S */
7195     /*
7196      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7197      * that specifies an instruction that performs "result = r0 op r1".
7198      * This could be an ARM instruction or a function call.  (If the result
7199      * comes back in a register other than r0, you can override "result".)
7200      *
7201      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7202      * vCC (r1).  Useful for integer division and modulus.
7203      *
7204      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7205      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7206      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7207      */
7208     /* binop/lit8 vAA, vBB, #+CC */
7209     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7210     mov     r9, rINST, lsr #8           @ r9<- AA
7211     and     r2, r3, #255                @ r2<- BB
7212     GET_VREG(r0, r2)                    @ r0<- vBB
7213     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7214     .if 0
7215     @cmp     r1, #0                      @ is second operand zero?
7216     beq     common_errDivideByZero
7217     .endif
7218     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7219
7220                                @ optional op; may set condition codes
7221     eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
7222     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7223     SET_VREG(r0, r9)               @ vAA<- r0
7224     GOTO_OPCODE(ip)                     @ jump to next instruction
7225     /* 10-12 instructions */
7226
7227
7228
7229 /* ------------------------------ */
7230     .balign 64
7231 .L_OP_SHL_INT_LIT8: /* 0xe0 */
7232 /* File: armv5te/OP_SHL_INT_LIT8.S */
7233 /* File: armv5te/binopLit8.S */
7234     /*
7235      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7236      * that specifies an instruction that performs "result = r0 op r1".
7237      * This could be an ARM instruction or a function call.  (If the result
7238      * comes back in a register other than r0, you can override "result".)
7239      *
7240      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7241      * vCC (r1).  Useful for integer division and modulus.
7242      *
7243      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7244      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7245      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7246      */
7247     /* binop/lit8 vAA, vBB, #+CC */
7248     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7249     mov     r9, rINST, lsr #8           @ r9<- AA
7250     and     r2, r3, #255                @ r2<- BB
7251     GET_VREG(r0, r2)                    @ r0<- vBB
7252     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7253     .if 0
7254     @cmp     r1, #0                      @ is second operand zero?
7255     beq     common_errDivideByZero
7256     .endif
7257     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7258
7259     and     r1, r1, #31                           @ optional op; may set condition codes
7260     mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
7261     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7262     SET_VREG(r0, r9)               @ vAA<- r0
7263     GOTO_OPCODE(ip)                     @ jump to next instruction
7264     /* 10-12 instructions */
7265
7266
7267
7268 /* ------------------------------ */
7269     .balign 64
7270 .L_OP_SHR_INT_LIT8: /* 0xe1 */
7271 /* File: armv5te/OP_SHR_INT_LIT8.S */
7272 /* File: armv5te/binopLit8.S */
7273     /*
7274      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7275      * that specifies an instruction that performs "result = r0 op r1".
7276      * This could be an ARM instruction or a function call.  (If the result
7277      * comes back in a register other than r0, you can override "result".)
7278      *
7279      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7280      * vCC (r1).  Useful for integer division and modulus.
7281      *
7282      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7283      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7284      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7285      */
7286     /* binop/lit8 vAA, vBB, #+CC */
7287     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7288     mov     r9, rINST, lsr #8           @ r9<- AA
7289     and     r2, r3, #255                @ r2<- BB
7290     GET_VREG(r0, r2)                    @ r0<- vBB
7291     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7292     .if 0
7293     @cmp     r1, #0                      @ is second operand zero?
7294     beq     common_errDivideByZero
7295     .endif
7296     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7297
7298     and     r1, r1, #31                           @ optional op; may set condition codes
7299     mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
7300     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7301     SET_VREG(r0, r9)               @ vAA<- r0
7302     GOTO_OPCODE(ip)                     @ jump to next instruction
7303     /* 10-12 instructions */
7304
7305
7306
7307 /* ------------------------------ */
7308     .balign 64
7309 .L_OP_USHR_INT_LIT8: /* 0xe2 */
7310 /* File: armv5te/OP_USHR_INT_LIT8.S */
7311 /* File: armv5te/binopLit8.S */
7312     /*
7313      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7314      * that specifies an instruction that performs "result = r0 op r1".
7315      * This could be an ARM instruction or a function call.  (If the result
7316      * comes back in a register other than r0, you can override "result".)
7317      *
7318      * If "chkzero" is set to 1, we perform a divide-by-zero check on
7319      * vCC (r1).  Useful for integer division and modulus.
7320      *
7321      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7322      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7323      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7324      */
7325     /* binop/lit8 vAA, vBB, #+CC */
7326     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7327     mov     r9, rINST, lsr #8           @ r9<- AA
7328     and     r2, r3, #255                @ r2<- BB
7329     GET_VREG(r0, r2)                    @ r0<- vBB
7330     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7331     .if 0
7332     @cmp     r1, #0                      @ is second operand zero?
7333     beq     common_errDivideByZero
7334     .endif
7335     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7336
7337     and     r1, r1, #31                           @ optional op; may set condition codes
7338     mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
7339     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7340     SET_VREG(r0, r9)               @ vAA<- r0
7341     GOTO_OPCODE(ip)                     @ jump to next instruction
7342     /* 10-12 instructions */
7343
7344
7345
7346 /* ------------------------------ */
7347     .balign 64
7348 .L_OP_UNUSED_E3: /* 0xe3 */
7349 /* File: armv5te/OP_UNUSED_E3.S */
7350 /* File: armv5te/unused.S */
7351     bl      common_abort
7352
7353
7354
7355 /* ------------------------------ */
7356     .balign 64
7357 .L_OP_UNUSED_E4: /* 0xe4 */
7358 /* File: armv5te/OP_UNUSED_E4.S */
7359 /* File: armv5te/unused.S */
7360     bl      common_abort
7361
7362
7363
7364 /* ------------------------------ */
7365     .balign 64
7366 .L_OP_UNUSED_E5: /* 0xe5 */
7367 /* File: armv5te/OP_UNUSED_E5.S */
7368 /* File: armv5te/unused.S */
7369     bl      common_abort
7370
7371
7372
7373 /* ------------------------------ */
7374     .balign 64
7375 .L_OP_UNUSED_E6: /* 0xe6 */
7376 /* File: armv5te/OP_UNUSED_E6.S */
7377 /* File: armv5te/unused.S */
7378     bl      common_abort
7379
7380
7381
7382 /* ------------------------------ */
7383     .balign 64
7384 .L_OP_UNUSED_E7: /* 0xe7 */
7385 /* File: armv5te/OP_UNUSED_E7.S */
7386 /* File: armv5te/unused.S */
7387     bl      common_abort
7388
7389
7390
7391 /* ------------------------------ */
7392     .balign 64
7393 .L_OP_UNUSED_E8: /* 0xe8 */
7394 /* File: armv5te/OP_UNUSED_E8.S */
7395 /* File: armv5te/unused.S */
7396     bl      common_abort
7397
7398
7399
7400 /* ------------------------------ */
7401     .balign 64
7402 .L_OP_UNUSED_E9: /* 0xe9 */
7403 /* File: armv5te/OP_UNUSED_E9.S */
7404 /* File: armv5te/unused.S */
7405     bl      common_abort
7406
7407
7408
7409 /* ------------------------------ */
7410     .balign 64
7411 .L_OP_UNUSED_EA: /* 0xea */
7412 /* File: armv5te/OP_UNUSED_EA.S */
7413 /* File: armv5te/unused.S */
7414     bl      common_abort
7415
7416
7417
7418 /* ------------------------------ */
7419     .balign 64
7420 .L_OP_UNUSED_EB: /* 0xeb */
7421 /* File: armv5te/OP_UNUSED_EB.S */
7422 /* File: armv5te/unused.S */
7423     bl      common_abort
7424
7425
7426
7427 /* ------------------------------ */
7428     .balign 64
7429 .L_OP_UNUSED_EC: /* 0xec */
7430 /* File: armv5te/OP_UNUSED_EC.S */
7431 /* File: armv5te/unused.S */
7432     bl      common_abort
7433
7434
7435
7436 /* ------------------------------ */
7437     .balign 64
7438 .L_OP_UNUSED_ED: /* 0xed */
7439 /* File: armv5te/OP_UNUSED_ED.S */
7440 /* File: armv5te/unused.S */
7441     bl      common_abort
7442
7443
7444
7445 /* ------------------------------ */
7446     .balign 64
7447 .L_OP_EXECUTE_INLINE: /* 0xee */
7448 /* File: armv5te/OP_EXECUTE_INLINE.S */
7449     /*
7450      * Execute a "native inline" instruction.
7451      *
7452      * We need to call:
7453      *  dvmPerformInlineOp4Std(arg0, arg1, arg2, arg3, &retval, ref)
7454      *
7455      * The first four args are in r0-r3, but the last two must be pushed
7456      * onto the stack.
7457      */
7458     /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
7459     FETCH(r10, 1)                       @ r10<- BBBB
7460     add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7461     EXPORT_PC()                         @ can throw
7462     sub     sp, sp, #8                  @ make room for arg(s)
7463     mov     r0, rINST, lsr #12          @ r0<- B
7464     str     r1, [sp]                    @ push &glue->retval
7465     bl      .LOP_EXECUTE_INLINE_continue        @ make call; will return after
7466     add     sp, sp, #8                  @ pop stack
7467     cmp     r0, #0                      @ test boolean result of inline
7468     beq     common_exceptionThrown      @ returned false, handle exception
7469     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7470     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7471     GOTO_OPCODE(ip)                     @ jump to next instruction
7472
7473 /* ------------------------------ */
7474     .balign 64
7475 .L_OP_UNUSED_EF: /* 0xef */
7476 /* File: armv5te/OP_UNUSED_EF.S */
7477 /* File: armv5te/unused.S */
7478     bl      common_abort
7479
7480
7481
7482 /* ------------------------------ */
7483     .balign 64
7484 .L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
7485 /* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
7486     /*
7487      * invoke-direct-empty is a no-op in a "standard" interpreter.
7488      */
7489     FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7490     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7491     GOTO_OPCODE(ip)                     @ execute it
7492
7493 /* ------------------------------ */
7494     .balign 64
7495 .L_OP_UNUSED_F1: /* 0xf1 */
7496 /* File: armv5te/OP_UNUSED_F1.S */
7497 /* File: armv5te/unused.S */
7498     bl      common_abort
7499
7500
7501
7502 /* ------------------------------ */
7503     .balign 64
7504 .L_OP_IGET_QUICK: /* 0xf2 */
7505 /* File: armv5te/OP_IGET_QUICK.S */
7506     /* For: iget-quick, iget-object-quick */
7507     /* op vA, vB, offset@CCCC */
7508     mov     r2, rINST, lsr #12          @ r2<- B
7509     GET_VREG(r3, r2)                    @ r3<- object we're operating on
7510     FETCH(r1, 1)                        @ r1<- field byte offset
7511     cmp     r3, #0                      @ check object for null
7512     mov     r2, rINST, lsr #8           @ r2<- A(+)
7513     beq     common_errNullObject        @ object was null
7514     ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7515     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7516     and     r2, r2, #15
7517     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7518     SET_VREG(r0, r2)                    @ fp[A]<- r0
7519     GOTO_OPCODE(ip)                     @ jump to next instruction
7520
7521
7522 /* ------------------------------ */
7523     .balign 64
7524 .L_OP_IGET_WIDE_QUICK: /* 0xf3 */
7525 /* File: armv4t/OP_IGET_WIDE_QUICK.S */
7526     /* iget-wide-quick vA, vB, offset@CCCC */
7527     mov     r2, rINST, lsr #12          @ r2<- B
7528     GET_VREG(r3, r2)                    @ r3<- object we're operating on
7529     FETCH(r1, 1)                        @ r1<- field byte offset
7530     cmp     r3, #0                      @ check object for null
7531     mov     r2, rINST, lsr #8           @ r2<- A(+)
7532     beq     common_errNullObject        @ object was null
7533     add     r9, r3, r1                  @ r9<- object + offset
7534     ldmia   r9, {r0-r1}                 @ r0/r1<- obj.field (64 bits, aligned)
7535     and     r2, r2, #15                 @ r2<- A
7536     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7537     add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
7538     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7539     stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
7540     GOTO_OPCODE(ip)                     @ jump to next instruction
7541
7542
7543 /* ------------------------------ */
7544     .balign 64
7545 .L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
7546 /* File: armv5te/OP_IGET_OBJECT_QUICK.S */
7547 /* File: armv5te/OP_IGET_QUICK.S */
7548     /* For: iget-quick, iget-object-quick */
7549     /* op vA, vB, offset@CCCC */
7550     mov     r2, rINST, lsr #12          @ r2<- B
7551     GET_VREG(r3, r2)                    @ r3<- object we're operating on
7552     FETCH(r1, 1)                        @ r1<- field byte offset
7553     cmp     r3, #0                      @ check object for null
7554     mov     r2, rINST, lsr #8           @ r2<- A(+)
7555     beq     common_errNullObject        @ object was null
7556     ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7557     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7558     and     r2, r2, #15
7559     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7560     SET_VREG(r0, r2)                    @ fp[A]<- r0
7561     GOTO_OPCODE(ip)                     @ jump to next instruction
7562
7563
7564
7565 /* ------------------------------ */
7566     .balign 64
7567 .L_OP_IPUT_QUICK: /* 0xf5 */
7568 /* File: armv5te/OP_IPUT_QUICK.S */
7569     /* For: iput-quick, iput-object-quick */
7570     /* op vA, vB, offset@CCCC */
7571     mov     r2, rINST, lsr #12          @ r2<- B
7572     GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7573     FETCH(r1, 1)                        @ r1<- field byte offset
7574     cmp     r3, #0                      @ check object for null
7575     mov     r2, rINST, lsr #8           @ r2<- A(+)
7576     beq     common_errNullObject        @ object was null
7577     and     r2, r2, #15
7578     GET_VREG(r0, r2)                    @ r0<- fp[A]
7579     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7580     str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7581     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7582     GOTO_OPCODE(ip)                     @ jump to next instruction
7583
7584
7585 /* ------------------------------ */
7586     .balign 64
7587 .L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
7588 /* File: armv4t/OP_IPUT_WIDE_QUICK.S */
7589     /* iput-wide-quick vA, vB, offset@CCCC */
7590     mov     r0, rINST, lsr #8           @ r0<- A(+)
7591     mov     r1, rINST, lsr #12          @ r1<- B
7592     and     r0, r0, #15
7593     GET_VREG(r2, r1)                    @ r2<- fp[B], the object pointer
7594     add     r3, rFP, r0, lsl #2         @ r3<- &fp[A]
7595     cmp     r2, #0                      @ check object for null
7596     ldmia   r3, {r0-r1}                 @ r0/r1<- fp[A]
7597     beq     common_errNullObject        @ object was null
7598     FETCH(r3, 1)                        @ r3<- field byte offset
7599     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7600     add     r2, r2, r3                  @ r2<- object + byte offset
7601     stmia   r2, {r0-r1}                 @ obj.field (64 bits, aligned)<- r0/r1
7602     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7603     GOTO_OPCODE(ip)                     @ jump to next instruction
7604
7605
7606 /* ------------------------------ */
7607     .balign 64
7608 .L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
7609 /* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
7610 /* File: armv5te/OP_IPUT_QUICK.S */
7611     /* For: iput-quick, iput-object-quick */
7612     /* op vA, vB, offset@CCCC */
7613     mov     r2, rINST, lsr #12          @ r2<- B
7614     GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7615     FETCH(r1, 1)                        @ r1<- field byte offset
7616     cmp     r3, #0                      @ check object for null
7617     mov     r2, rINST, lsr #8           @ r2<- A(+)
7618     beq     common_errNullObject        @ object was null
7619     and     r2, r2, #15
7620     GET_VREG(r0, r2)                    @ r0<- fp[A]
7621     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7622     str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7623     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7624     GOTO_OPCODE(ip)                     @ jump to next instruction
7625
7626
7627
7628 /* ------------------------------ */
7629     .balign 64
7630 .L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
7631 /* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7632     /*
7633      * Handle an optimized virtual method call.
7634      *
7635      * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7636      */
7637     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7638     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7639     FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7640     FETCH(r1, 1)                        @ r1<- BBBB
7641     .if     (!0)
7642     and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7643     .endif
7644     GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7645     cmp     r2, #0                      @ is "this" null?
7646     beq     common_errNullObject        @ null "this", throw exception
7647     ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7648     ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7649     EXPORT_PC()                         @ invoke must export
7650     ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7651     bl      common_invokeMethodNoRange @ continue on
7652
7653 /* ------------------------------ */
7654     .balign 64
7655 .L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
7656 /* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
7657 /* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7658     /*
7659      * Handle an optimized virtual method call.
7660      *
7661      * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7662      */
7663     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7664     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7665     FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7666     FETCH(r1, 1)                        @ r1<- BBBB
7667     .if     (!1)
7668     and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7669     .endif
7670     GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7671     cmp     r2, #0                      @ is "this" null?
7672     beq     common_errNullObject        @ null "this", throw exception
7673     ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7674     ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7675     EXPORT_PC()                         @ invoke must export
7676     ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7677     bl      common_invokeMethodRange @ continue on
7678
7679
7680 /* ------------------------------ */
7681     .balign 64
7682 .L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
7683 /* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7684     /*
7685      * Handle an optimized "super" method call.
7686      *
7687      * for: [opt] invoke-super-quick, invoke-super-quick/range
7688      */
7689     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7690     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7691     FETCH(r10, 2)                       @ r10<- GFED or CCCC
7692     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7693     .if     (!0)
7694     and     r10, r10, #15               @ r10<- D (or stays CCCC)
7695     .endif
7696     FETCH(r1, 1)                        @ r1<- BBBB
7697     ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7698     EXPORT_PC()                         @ must export for invoke
7699     ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7700     GET_VREG(r3, r10)                   @ r3<- "this"
7701     ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7702     cmp     r3, #0                      @ null "this" ref?
7703     ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7704     beq     common_errNullObject        @ "this" is null, throw exception
7705     bl      common_invokeMethodNoRange @ continue on
7706
7707
7708 /* ------------------------------ */
7709     .balign 64
7710 .L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
7711 /* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
7712 /* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7713     /*
7714      * Handle an optimized "super" method call.
7715      *
7716      * for: [opt] invoke-super-quick, invoke-super-quick/range
7717      */
7718     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7719     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7720     FETCH(r10, 2)                       @ r10<- GFED or CCCC
7721     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7722     .if     (!1)
7723     and     r10, r10, #15               @ r10<- D (or stays CCCC)
7724     .endif
7725     FETCH(r1, 1)                        @ r1<- BBBB
7726     ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7727     EXPORT_PC()                         @ must export for invoke
7728     ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7729     GET_VREG(r3, r10)                   @ r3<- "this"
7730     ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7731     cmp     r3, #0                      @ null "this" ref?
7732     ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7733     beq     common_errNullObject        @ "this" is null, throw exception
7734     bl      common_invokeMethodRange @ continue on
7735
7736
7737
7738 /* ------------------------------ */
7739     .balign 64
7740 .L_OP_UNUSED_FC: /* 0xfc */
7741 /* File: armv5te/OP_UNUSED_FC.S */
7742 /* File: armv5te/unused.S */
7743     bl      common_abort
7744
7745
7746
7747 /* ------------------------------ */
7748     .balign 64
7749 .L_OP_UNUSED_FD: /* 0xfd */
7750 /* File: armv5te/OP_UNUSED_FD.S */
7751 /* File: armv5te/unused.S */
7752     bl      common_abort
7753
7754
7755
7756 /* ------------------------------ */
7757     .balign 64
7758 .L_OP_UNUSED_FE: /* 0xfe */
7759 /* File: armv5te/OP_UNUSED_FE.S */
7760 /* File: armv5te/unused.S */
7761     bl      common_abort
7762
7763
7764
7765 /* ------------------------------ */
7766     .balign 64
7767 .L_OP_UNUSED_FF: /* 0xff */
7768 /* File: armv5te/OP_UNUSED_FF.S */
7769 /* File: armv5te/unused.S */
7770     bl      common_abort
7771
7772
7773
7774
7775     .balign 64
7776     .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
7777     .global dvmAsmInstructionEnd
7778 dvmAsmInstructionEnd:
7779
7780 /*
7781  * ===========================================================================
7782  *  Sister implementations
7783  * ===========================================================================
7784  */
7785     .global dvmAsmSisterStart
7786     .type   dvmAsmSisterStart, %function
7787     .text
7788     .balign 4
7789 dvmAsmSisterStart:
7790
7791 /* continuation for OP_CONST_STRING */
7792
7793     /*
7794      * Continuation if the String has not yet been resolved.
7795      *  r1: BBBB (String ref)
7796      *  r9: target register
7797      */
7798 .LOP_CONST_STRING_resolve:
7799     EXPORT_PC()
7800     ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7801     ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7802     bl      dvmResolveString            @ r0<- String reference
7803     cmp     r0, #0                      @ failed?
7804     beq     common_exceptionThrown      @ yup, handle the exception
7805     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7806     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7807     SET_VREG(r0, r9)                    @ vAA<- r0
7808     GOTO_OPCODE(ip)                     @ jump to next instruction
7809
7810
7811 /* continuation for OP_CONST_STRING_JUMBO */
7812
7813     /*
7814      * Continuation if the String has not yet been resolved.
7815      *  r1: BBBBBBBB (String ref)
7816      *  r9: target register
7817      */
7818 .LOP_CONST_STRING_JUMBO_resolve:
7819     EXPORT_PC()
7820     ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7821     ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7822     bl      dvmResolveString            @ r0<- String reference
7823     cmp     r0, #0                      @ failed?
7824     beq     common_exceptionThrown      @ yup, handle the exception
7825     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7826     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7827     SET_VREG(r0, r9)                    @ vAA<- r0
7828     GOTO_OPCODE(ip)                     @ jump to next instruction
7829
7830
7831 /* continuation for OP_CONST_CLASS */
7832
7833     /*
7834      * Continuation if the Class has not yet been resolved.
7835      *  r1: BBBB (Class ref)
7836      *  r9: target register
7837      */
7838 .LOP_CONST_CLASS_resolve:
7839     EXPORT_PC()
7840     ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7841     mov     r2, #1                      @ r2<- true
7842     ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7843     bl      dvmResolveClass             @ r0<- Class reference
7844     cmp     r0, #0                      @ failed?
7845     beq     common_exceptionThrown      @ yup, handle the exception
7846     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7847     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7848     SET_VREG(r0, r9)                    @ vAA<- r0
7849     GOTO_OPCODE(ip)                     @ jump to next instruction
7850
7851
7852 /* continuation for OP_CHECK_CAST */
7853
7854     /*
7855      * Trivial test failed, need to perform full check.  This is common.
7856      *  r0 holds obj->clazz
7857      *  r1 holds class resolved from BBBB
7858      *  r9 holds object
7859      */
7860 .LOP_CHECK_CAST_fullcheck:
7861     bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7862     cmp     r0, #0                      @ failed?
7863     bne     .LOP_CHECK_CAST_okay            @ no, success
7864
7865     @ A cast has failed.  We need to throw a ClassCastException with the
7866     @ class of the object that failed to be cast.
7867     EXPORT_PC()                         @ about to throw
7868     ldr     r3, [r9, #offObject_clazz]  @ r3<- obj->clazz
7869     ldr     r0, .LstrClassCastExceptionPtr
7870     ldr     r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor
7871     bl      dvmThrowExceptionWithClassMessage
7872     b       common_exceptionThrown
7873
7874     /*
7875      * Resolution required.  This is the least-likely path.
7876      *
7877      *  r2 holds BBBB
7878      *  r9 holds object
7879      */
7880 .LOP_CHECK_CAST_resolve:
7881     EXPORT_PC()                         @ resolve() could throw
7882     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7883     mov     r1, r2                      @ r1<- BBBB
7884     mov     r2, #0                      @ r2<- false
7885     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7886     bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7887     cmp     r0, #0                      @ got null?
7888     beq     common_exceptionThrown      @ yes, handle exception
7889     mov     r1, r0                      @ r1<- class resolved from BBB
7890     ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
7891     b       .LOP_CHECK_CAST_resolved        @ pick up where we left off
7892
7893 .LstrClassCastExceptionPtr:
7894     .word   .LstrClassCastException
7895
7896
7897 /* continuation for OP_INSTANCE_OF */
7898
7899     /*
7900      * Trivial test failed, need to perform full check.  This is common.
7901      *  r0 holds obj->clazz
7902      *  r1 holds class resolved from BBBB
7903      *  r9 holds A
7904      */
7905 .LOP_INSTANCE_OF_fullcheck:
7906     bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7907     @ fall through to OP_INSTANCE_OF_store
7908
7909     /*
7910      * r0 holds boolean result
7911      * r9 holds A
7912      */
7913 .LOP_INSTANCE_OF_store:
7914     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7915     SET_VREG(r0, r9)                    @ vA<- r0
7916     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7917     GOTO_OPCODE(ip)                     @ jump to next instruction
7918
7919     /*
7920      * Trivial test succeeded, save and bail.
7921      *  r9 holds A
7922      */
7923 .LOP_INSTANCE_OF_trivial:
7924     mov     r0, #1                      @ indicate success
7925     @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
7926     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7927     SET_VREG(r0, r9)                    @ vA<- r0
7928     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7929     GOTO_OPCODE(ip)                     @ jump to next instruction
7930
7931     /*
7932      * Resolution required.  This is the least-likely path.
7933      *
7934      *  r3 holds BBBB
7935      *  r9 holds A
7936      */
7937 .LOP_INSTANCE_OF_resolve:
7938     EXPORT_PC()                         @ resolve() could throw
7939     ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7940     mov     r1, r3                      @ r1<- BBBB
7941     mov     r2, #1                      @ r2<- true
7942     ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7943     bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7944     cmp     r0, #0                      @ got null?
7945     beq     common_exceptionThrown      @ yes, handle exception
7946     mov     r1, r0                      @ r1<- class resolved from BBB
7947     mov     r3, rINST, lsr #12          @ r3<- B
7948     GET_VREG(r0, r3)                    @ r0<- vB (object)
7949     ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
7950     b       .LOP_INSTANCE_OF_resolved        @ pick up where we left off
7951
7952
7953 /* continuation for OP_NEW_INSTANCE */
7954
7955     .balign 32                          @ minimize cache lines
7956 .LOP_NEW_INSTANCE_finish: @ r0=class
7957     bl      dvmAllocObject              @ r0<- new object
7958     mov     r3, rINST, lsr #8           @ r3<- AA
7959     cmp     r0, #0                      @ failed?
7960     beq     common_exceptionThrown      @ yes, handle the exception
7961     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7962     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7963     SET_VREG(r0, r3)                    @ vAA<- r0
7964     GOTO_OPCODE(ip)                     @ jump to next instruction
7965
7966     /*
7967      * Class initialization required.
7968      *
7969      *  r0 holds class object
7970      */
7971 .LOP_NEW_INSTANCE_needinit:
7972     mov     r9, r0                      @ save r0
7973     bl      dvmInitClass                @ initialize class
7974     cmp     r0, #0                      @ check boolean result
7975     mov     r0, r9                      @ restore r0
7976     bne     .LOP_NEW_INSTANCE_initialized     @ success, continue
7977     b       common_exceptionThrown      @ failed, deal with init exception
7978
7979     /*
7980      * Resolution required.  This is the least-likely path.
7981      *
7982      *  r1 holds BBBB
7983      */
7984 .LOP_NEW_INSTANCE_resolve:
7985     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7986     mov     r2, #0                      @ r2<- false
7987     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7988     bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7989     cmp     r0, #0                      @ got null?
7990     bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
7991     b       common_exceptionThrown      @ yes, handle exception
7992
7993     /*
7994      * We can't instantiate an abstract class or interface, so throw an
7995      * InstantiationError with the class descriptor as the message.
7996      *
7997      *  r0 holds class object
7998      */
7999 .LOP_NEW_INSTANCE_abstract:
8000     ldr     r1, [r0, #offClassObject_descriptor]
8001     ldr     r0, .LstrInstantiationErrorPtr
8002     bl      dvmThrowExceptionWithClassMessage
8003     b       common_exceptionThrown
8004
8005 .LstrInstantiationErrorPtr:
8006     .word   .LstrInstantiationError
8007
8008
8009 /* continuation for OP_NEW_ARRAY */
8010
8011
8012     /*
8013      * Resolve class.  (This is an uncommon case.)
8014      *
8015      *  r1 holds array length
8016      *  r2 holds class ref CCCC
8017      */
8018 .LOP_NEW_ARRAY_resolve:
8019     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8020     mov     r9, r1                      @ r9<- length (save)
8021     mov     r1, r2                      @ r1<- CCCC
8022     mov     r2, #0                      @ r2<- false
8023     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8024     bl      dvmResolveClass             @ r0<- call(clazz, ref)
8025     cmp     r0, #0                      @ got null?
8026     mov     r1, r9                      @ r1<- length (restore)
8027     beq     common_exceptionThrown      @ yes, handle exception
8028     @ fall through to OP_NEW_ARRAY_finish
8029
8030     /*
8031      * Finish allocation.
8032      *
8033      *  r0 holds class
8034      *  r1 holds array length
8035      */
8036 .LOP_NEW_ARRAY_finish:
8037     mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
8038     bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
8039     cmp     r0, #0                      @ failed?
8040     mov     r2, rINST, lsr #8           @ r2<- A+
8041     beq     common_exceptionThrown      @ yes, handle the exception
8042     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8043     and     r2, r2, #15                 @ r2<- A
8044     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8045     SET_VREG(r0, r2)                    @ vA<- r0
8046     GOTO_OPCODE(ip)                     @ jump to next instruction
8047
8048
8049 /* continuation for OP_FILLED_NEW_ARRAY */
8050
8051     /*
8052      * On entry:
8053      *  r0 holds array class
8054      *  r10 holds AA or BA
8055      */
8056 .LOP_FILLED_NEW_ARRAY_continue:
8057     ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8058     mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8059     ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
8060     .if     0
8061     mov     r1, r10                     @ r1<- AA (length)
8062     .else
8063     mov     r1, r10, lsr #4             @ r1<- B (length)
8064     .endif
8065     cmp     r3, #'I'                    @ array of ints?
8066     cmpne   r3, #'L'                    @ array of objects?
8067     cmpne   r3, #'['                    @ array of arrays?
8068     mov     r9, r1                      @ save length in r9
8069     bne     .LOP_FILLED_NEW_ARRAY_notimpl         @ no, not handled yet
8070     bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8071     cmp     r0, #0                      @ null return?
8072     beq     common_exceptionThrown      @ alloc failed, handle exception
8073
8074     FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8075     str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
8076     add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8077     subs    r9, r9, #1                  @ length--, check for neg
8078     FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8079     bmi     2f                          @ was zero, bail
8080
8081     @ copy values from registers into the array
8082     @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8083     .if     0
8084     add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
8085 1:  ldr     r3, [r2], #4                @ r3<- *r2++
8086     subs    r9, r9, #1                  @ count--
8087     str     r3, [r0], #4                @ *contents++ = vX
8088     bpl     1b
8089     @ continue at 2
8090     .else
8091     cmp     r9, #4                      @ length was initially 5?
8092     and     r2, r10, #15                @ r2<- A
8093     bne     1f                          @ <= 4 args, branch
8094     GET_VREG(r3, r2)                    @ r3<- vA
8095     sub     r9, r9, #1                  @ count--
8096     str     r3, [r0, #16]               @ contents[4] = vA
8097 1:  and     r2, r1, #15                 @ r2<- F/E/D/C
8098     GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8099     mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8100     subs    r9, r9, #1                  @ count--
8101     str     r3, [r0], #4                @ *contents++ = vX
8102     bpl     1b
8103     @ continue at 2
8104     .endif
8105
8106 2:
8107     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
8108     GOTO_OPCODE(ip)                     @ execute it
8109
8110     /*
8111      * Throw an exception indicating that we have not implemented this
8112      * mode of filled-new-array.
8113      */
8114 .LOP_FILLED_NEW_ARRAY_notimpl:
8115     ldr     r0, .L_strInternalError
8116     ldr     r1, .L_strFilledNewArrayNotImpl
8117     bl      dvmThrowException
8118     b       common_exceptionThrown
8119
8120     .if     (!0)                 @ define in one or the other, not both
8121 .L_strFilledNewArrayNotImpl:
8122     .word   .LstrFilledNewArrayNotImpl
8123 .L_strInternalError:
8124     .word   .LstrInternalError
8125     .endif
8126
8127
8128 /* continuation for OP_FILLED_NEW_ARRAY_RANGE */
8129
8130     /*
8131      * On entry:
8132      *  r0 holds array class
8133      *  r10 holds AA or BA
8134      */
8135 .LOP_FILLED_NEW_ARRAY_RANGE_continue:
8136     ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8137     mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8138     ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
8139     .if     1
8140     mov     r1, r10                     @ r1<- AA (length)
8141     .else
8142     mov     r1, r10, lsr #4             @ r1<- B (length)
8143     .endif
8144     cmp     r3, #'I'                    @ array of ints?
8145     cmpne   r3, #'L'                    @ array of objects?
8146     cmpne   r3, #'['                    @ array of arrays?
8147     mov     r9, r1                      @ save length in r9
8148     bne     .LOP_FILLED_NEW_ARRAY_RANGE_notimpl         @ no, not handled yet
8149     bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8150     cmp     r0, #0                      @ null return?
8151     beq     common_exceptionThrown      @ alloc failed, handle exception
8152
8153     FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8154     str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
8155     add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8156     subs    r9, r9, #1                  @ length--, check for neg
8157     FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8158     bmi     2f                          @ was zero, bail
8159
8160     @ copy values from registers into the array
8161     @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8162     .if     1
8163     add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
8164 1:  ldr     r3, [r2], #4                @ r3<- *r2++
8165     subs    r9, r9, #1                  @ count--
8166     str     r3, [r0], #4                @ *contents++ = vX
8167     bpl     1b
8168     @ continue at 2
8169     .else
8170     cmp     r9, #4                      @ length was initially 5?
8171     and     r2, r10, #15                @ r2<- A
8172     bne     1f                          @ <= 4 args, branch
8173     GET_VREG(r3, r2)                    @ r3<- vA
8174     sub     r9, r9, #1                  @ count--
8175     str     r3, [r0, #16]               @ contents[4] = vA
8176 1:  and     r2, r1, #15                 @ r2<- F/E/D/C
8177     GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8178     mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8179     subs    r9, r9, #1                  @ count--
8180     str     r3, [r0], #4                @ *contents++ = vX
8181     bpl     1b
8182     @ continue at 2
8183     .endif
8184
8185 2:
8186     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
8187     GOTO_OPCODE(ip)                     @ execute it
8188
8189     /*
8190      * Throw an exception indicating that we have not implemented this
8191      * mode of filled-new-array.
8192      */
8193 .LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
8194     ldr     r0, .L_strInternalError
8195     ldr     r1, .L_strFilledNewArrayNotImpl
8196     bl      dvmThrowException
8197     b       common_exceptionThrown
8198
8199     .if     (!1)                 @ define in one or the other, not both
8200 .L_strFilledNewArrayNotImpl:
8201     .word   .LstrFilledNewArrayNotImpl
8202 .L_strInternalError:
8203     .word   .LstrInternalError
8204     .endif
8205
8206
8207 /* continuation for OP_CMPL_FLOAT */
8208
8209     @ Test for NaN with a second comparison.  EABI forbids testing bit
8210     @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8211     @ make the library call.
8212 .LOP_CMPL_FLOAT_gt_or_nan:
8213     mov     r1, r9                      @ reverse order
8214     mov     r0, r10
8215     bl      __aeabi_cfcmple             @ r0<- Z set if eq, C clear if <
8216     @bleq    common_abort
8217     movcc   r1, #1                      @ (greater than) r1<- 1
8218     bcc     .LOP_CMPL_FLOAT_finish
8219     mvn     r1, #0                            @ r1<- 1 or -1 for NaN
8220     b       .LOP_CMPL_FLOAT_finish
8221
8222
8223 #if 0       /* "clasic" form */
8224     FETCH(r0, 1)                        @ r0<- CCBB
8225     and     r2, r0, #255                @ r2<- BB
8226     mov     r3, r0, lsr #8              @ r3<- CC
8227     GET_VREG(r9, r2)                    @ r9<- vBB
8228     GET_VREG(r10, r3)                   @ r10<- vCC
8229     mov     r0, r9                      @ r0<- vBB
8230     mov     r1, r10                     @ r1<- vCC
8231     bl      __aeabi_fcmpeq              @ r0<- (vBB == vCC)
8232     cmp     r0, #0                      @ equal?
8233     movne   r1, #0                      @ yes, result is 0
8234     bne     OP_CMPL_FLOAT_finish
8235     mov     r0, r9                      @ r0<- vBB
8236     mov     r1, r10                     @ r1<- vCC
8237     bl      __aeabi_fcmplt              @ r0<- (vBB < vCC)
8238     cmp     r0, #0                      @ less than?
8239     b       OP_CMPL_FLOAT_continue
8240 @%break
8241
8242 OP_CMPL_FLOAT_continue:
8243     mvnne   r1, #0                      @ yes, result is -1
8244     bne     OP_CMPL_FLOAT_finish
8245     mov     r0, r9                      @ r0<- vBB
8246     mov     r1, r10                     @ r1<- vCC
8247     bl      __aeabi_fcmpgt              @ r0<- (vBB > vCC)
8248     cmp     r0, #0                      @ greater than?
8249     beq     OP_CMPL_FLOAT_nan               @ no, must be NaN
8250     mov     r1, #1                      @ yes, result is 1
8251     @ fall through to _finish
8252
8253 OP_CMPL_FLOAT_finish:
8254     mov     r3, rINST, lsr #8           @ r3<- AA
8255     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8256     SET_VREG(r1, r3)                    @ vAA<- r1
8257     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8258     GOTO_OPCODE(ip)                     @ jump to next instruction
8259
8260     /*
8261      * This is expected to be uncommon, so we double-branch (once to here,
8262      * again back to _finish).
8263      */
8264 OP_CMPL_FLOAT_nan:
8265     mvn     r1, #0                            @ r1<- 1 or -1 for NaN
8266     b       OP_CMPL_FLOAT_finish
8267
8268 #endif
8269
8270
8271 /* continuation for OP_CMPG_FLOAT */
8272
8273     @ Test for NaN with a second comparison.  EABI forbids testing bit
8274     @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8275     @ make the library call.
8276 .LOP_CMPG_FLOAT_gt_or_nan:
8277     mov     r1, r9                      @ reverse order
8278     mov     r0, r10
8279     bl      __aeabi_cfcmple             @ r0<- Z set if eq, C clear if <
8280     @bleq    common_abort
8281     movcc   r1, #1                      @ (greater than) r1<- 1
8282     bcc     .LOP_CMPG_FLOAT_finish
8283     mov     r1, #1                            @ r1<- 1 or -1 for NaN
8284     b       .LOP_CMPG_FLOAT_finish
8285
8286
8287 #if 0       /* "clasic" form */
8288     FETCH(r0, 1)                        @ r0<- CCBB
8289     and     r2, r0, #255                @ r2<- BB
8290     mov     r3, r0, lsr #8              @ r3<- CC
8291     GET_VREG(r9, r2)                    @ r9<- vBB
8292     GET_VREG(r10, r3)                   @ r10<- vCC
8293     mov     r0, r9                      @ r0<- vBB
8294     mov     r1, r10                     @ r1<- vCC
8295     bl      __aeabi_fcmpeq              @ r0<- (vBB == vCC)
8296     cmp     r0, #0                      @ equal?
8297     movne   r1, #0                      @ yes, result is 0
8298     bne     OP_CMPG_FLOAT_finish
8299     mov     r0, r9                      @ r0<- vBB
8300     mov     r1, r10                     @ r1<- vCC
8301     bl      __aeabi_fcmplt              @ r0<- (vBB < vCC)
8302     cmp     r0, #0                      @ less than?
8303     b       OP_CMPG_FLOAT_continue
8304 @%break
8305
8306 OP_CMPG_FLOAT_continue:
8307     mvnne   r1, #0                      @ yes, result is -1
8308     bne     OP_CMPG_FLOAT_finish
8309     mov     r0, r9                      @ r0<- vBB
8310     mov     r1, r10                     @ r1<- vCC
8311     bl      __aeabi_fcmpgt              @ r0<- (vBB > vCC)
8312     cmp     r0, #0                      @ greater than?
8313     beq     OP_CMPG_FLOAT_nan               @ no, must be NaN
8314     mov     r1, #1                      @ yes, result is 1
8315     @ fall through to _finish
8316
8317 OP_CMPG_FLOAT_finish:
8318     mov     r3, rINST, lsr #8           @ r3<- AA
8319     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8320     SET_VREG(r1, r3)                    @ vAA<- r1
8321     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8322     GOTO_OPCODE(ip)                     @ jump to next instruction
8323
8324     /*
8325      * This is expected to be uncommon, so we double-branch (once to here,
8326      * again back to _finish).
8327      */
8328 OP_CMPG_FLOAT_nan:
8329     mov     r1, #1                            @ r1<- 1 or -1 for NaN
8330     b       OP_CMPG_FLOAT_finish
8331
8332 #endif
8333
8334
8335 /* continuation for OP_CMPL_DOUBLE */
8336
8337     @ Test for NaN with a second comparison.  EABI forbids testing bit
8338     @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8339     @ make the library call.
8340 .LOP_CMPL_DOUBLE_gt_or_nan:
8341     ldmia   r10, {r0-r1}                @ reverse order
8342     ldmia   r9, {r2-r3}
8343     bl      __aeabi_cdcmple             @ r0<- Z set if eq, C clear if <
8344     @bleq    common_abort
8345     movcc   r1, #1                      @ (greater than) r1<- 1
8346     bcc     .LOP_CMPL_DOUBLE_finish
8347     mvn     r1, #0                            @ r1<- 1 or -1 for NaN
8348     b       .LOP_CMPL_DOUBLE_finish
8349
8350
8351 /* continuation for OP_CMPG_DOUBLE */
8352
8353     @ Test for NaN with a second comparison.  EABI forbids testing bit
8354     @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8355     @ make the library call.
8356 .LOP_CMPG_DOUBLE_gt_or_nan:
8357     ldmia   r10, {r0-r1}                @ reverse order
8358     ldmia   r9, {r2-r3}
8359     bl      __aeabi_cdcmple             @ r0<- Z set if eq, C clear if <
8360     @bleq    common_abort
8361     movcc   r1, #1                      @ (greater than) r1<- 1
8362     bcc     .LOP_CMPG_DOUBLE_finish
8363     mov     r1, #1                            @ r1<- 1 or -1 for NaN
8364     b       .LOP_CMPG_DOUBLE_finish
8365
8366
8367 /* continuation for OP_CMP_LONG */
8368
8369 .LOP_CMP_LONG_less:
8370     mvn     r1, #0                      @ r1<- -1
8371     @ Want to cond code the next mov so we can avoid branch, but don't see it;
8372     @ instead, we just replicate the tail end.
8373     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8374     SET_VREG(r1, r9)                    @ vAA<- r1
8375     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8376     GOTO_OPCODE(ip)                     @ jump to next instruction
8377
8378 .LOP_CMP_LONG_greater:
8379     mov     r1, #1                      @ r1<- 1
8380     @ fall through to _finish
8381
8382 .LOP_CMP_LONG_finish:
8383     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8384     SET_VREG(r1, r9)                    @ vAA<- r1
8385     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8386     GOTO_OPCODE(ip)                     @ jump to next instruction
8387
8388
8389 /* continuation for OP_AGET_WIDE */
8390
8391 .LOP_AGET_WIDE_finish:
8392     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8393     add     r0, r0, #offArrayObject_contents
8394     ldmia   r0, {r2-r3}                 @ r2/r3 <- vBB[vCC]
8395     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
8396     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8397     stmia   r9, {r2-r3}                 @ vAA/vAA+1<- r2/r3
8398     GOTO_OPCODE(ip)                     @ jump to next instruction
8399
8400
8401 /* continuation for OP_APUT_WIDE */
8402
8403 .LOP_APUT_WIDE_finish:
8404     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8405     ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
8406     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8407     add     r0, #offArrayObject_contents
8408     stmia   r0, {r2-r3}                 @ vBB[vCC] <- r2/r3
8409     GOTO_OPCODE(ip)                     @ jump to next instruction
8410
8411
8412 /* continuation for OP_APUT_OBJECT */
8413     /*
8414      * On entry:
8415      *  r1 = vBB (arrayObj)
8416      *  r9 = vAA (obj)
8417      *  r10 = offset into array (vBB + vCC * width)
8418      */
8419 .LOP_APUT_OBJECT_finish:
8420     cmp     r9, #0                      @ storing null reference?
8421     beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
8422     ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
8423     ldr     r1, [r1, #offObject_clazz]  @ r1<- arrayObj->clazz
8424     bl      dvmCanPutArrayElement       @ test object type vs. array type
8425     cmp     r0, #0                      @ okay?
8426     beq     common_errArrayStore        @ no
8427 .LOP_APUT_OBJECT_skip_check:
8428     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8429     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8430     str     r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
8431     GOTO_OPCODE(ip)                     @ jump to next instruction
8432
8433
8434 /* continuation for OP_IGET */
8435
8436     /*
8437      * Currently:
8438      *  r0 holds resolved field
8439      *  r9 holds object
8440      */
8441 .LOP_IGET_finish:
8442     @bl      common_squeak0
8443     cmp     r9, #0                      @ check object for null
8444     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8445     beq     common_errNullObject        @ object was null
8446     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8447     mov     r2, rINST, lsr #8           @ r2<- A+
8448     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8449     and     r2, r2, #15                 @ r2<- A
8450     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8451     SET_VREG(r0, r2)                    @ fp[A]<- r0
8452     GOTO_OPCODE(ip)                     @ jump to next instruction
8453
8454
8455 /* continuation for OP_IGET_WIDE */
8456
8457     /*
8458      * Currently:
8459      *  r0 holds resolved field
8460      *  r9 holds object
8461      */
8462 .LOP_IGET_WIDE_finish:
8463     cmp     r9, #0                      @ check object for null
8464     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8465     beq     common_errNullObject        @ object was null
8466     mov     r2, rINST, lsr #8           @ r2<- A+
8467     add     r9, r9, r3                  @ r9<- obj + field offset
8468     ldmia   r9, {r0-r1}                 @ r0/r1<- obj.field (64-bit align ok)
8469     and     r2, r2, #15                 @ r2<- A
8470     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8471     add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
8472     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8473     stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
8474     GOTO_OPCODE(ip)                     @ jump to next instruction
8475
8476
8477 /* continuation for OP_IGET_OBJECT */
8478
8479     /*
8480      * Currently:
8481      *  r0 holds resolved field
8482      *  r9 holds object
8483      */
8484 .LOP_IGET_OBJECT_finish:
8485     @bl      common_squeak0
8486     cmp     r9, #0                      @ check object for null
8487     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8488     beq     common_errNullObject        @ object was null
8489     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8490     mov     r2, rINST, lsr #8           @ r2<- A+
8491     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8492     and     r2, r2, #15                 @ r2<- A
8493     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8494     SET_VREG(r0, r2)                    @ fp[A]<- r0
8495     GOTO_OPCODE(ip)                     @ jump to next instruction
8496
8497
8498 /* continuation for OP_IGET_BOOLEAN */
8499
8500     /*
8501      * Currently:
8502      *  r0 holds resolved field
8503      *  r9 holds object
8504      */
8505 .LOP_IGET_BOOLEAN_finish:
8506     @bl      common_squeak1
8507     cmp     r9, #0                      @ check object for null
8508     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8509     beq     common_errNullObject        @ object was null
8510     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8511     mov     r2, rINST, lsr #8           @ r2<- A+
8512     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8513     and     r2, r2, #15                 @ r2<- A
8514     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8515     SET_VREG(r0, r2)                    @ fp[A]<- r0
8516     GOTO_OPCODE(ip)                     @ jump to next instruction
8517
8518
8519 /* continuation for OP_IGET_BYTE */
8520
8521     /*
8522      * Currently:
8523      *  r0 holds resolved field
8524      *  r9 holds object
8525      */
8526 .LOP_IGET_BYTE_finish:
8527     @bl      common_squeak2
8528     cmp     r9, #0                      @ check object for null
8529     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8530     beq     common_errNullObject        @ object was null
8531     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8532     mov     r2, rINST, lsr #8           @ r2<- A+
8533     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8534     and     r2, r2, #15                 @ r2<- A
8535     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8536     SET_VREG(r0, r2)                    @ fp[A]<- r0
8537     GOTO_OPCODE(ip)                     @ jump to next instruction
8538
8539
8540 /* continuation for OP_IGET_CHAR */
8541
8542     /*
8543      * Currently:
8544      *  r0 holds resolved field
8545      *  r9 holds object
8546      */
8547 .LOP_IGET_CHAR_finish:
8548     @bl      common_squeak3
8549     cmp     r9, #0                      @ check object for null
8550     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8551     beq     common_errNullObject        @ object was null
8552     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8553     mov     r2, rINST, lsr #8           @ r2<- A+
8554     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8555     and     r2, r2, #15                 @ r2<- A
8556     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8557     SET_VREG(r0, r2)                    @ fp[A]<- r0
8558     GOTO_OPCODE(ip)                     @ jump to next instruction
8559
8560
8561 /* continuation for OP_IGET_SHORT */
8562
8563     /*
8564      * Currently:
8565      *  r0 holds resolved field
8566      *  r9 holds object
8567      */
8568 .LOP_IGET_SHORT_finish:
8569     @bl      common_squeak4
8570     cmp     r9, #0                      @ check object for null
8571     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8572     beq     common_errNullObject        @ object was null
8573     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8574     mov     r2, rINST, lsr #8           @ r2<- A+
8575     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8576     and     r2, r2, #15                 @ r2<- A
8577     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8578     SET_VREG(r0, r2)                    @ fp[A]<- r0
8579     GOTO_OPCODE(ip)                     @ jump to next instruction
8580
8581
8582 /* continuation for OP_IPUT */
8583
8584     /*
8585      * Currently:
8586      *  r0 holds resolved field
8587      *  r9 holds object
8588      */
8589 .LOP_IPUT_finish:
8590     @bl      common_squeak0
8591     mov     r1, rINST, lsr #8           @ r1<- A+
8592     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8593     and     r1, r1, #15                 @ r1<- A
8594     cmp     r9, #0                      @ check object for null
8595     GET_VREG(r0, r1)                    @ r0<- fp[A]
8596     beq     common_errNullObject        @ object was null
8597     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8598     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8599     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8600     GOTO_OPCODE(ip)                     @ jump to next instruction
8601
8602
8603 /* continuation for OP_IPUT_WIDE */
8604
8605     /*
8606      * Currently:
8607      *  r0 holds resolved field
8608      *  r9 holds object
8609      */
8610 .LOP_IPUT_WIDE_finish:
8611     mov     r2, rINST, lsr #8           @ r2<- A+
8612     cmp     r9, #0                      @ check object for null
8613     and     r2, r2, #15                 @ r2<- A
8614     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8615     add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
8616     beq     common_errNullObject        @ object was null
8617     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8618     ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
8619     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8620     add     r9, r9, r3                  @ r9<- object + byte offset
8621     stmia   r9, {r0-r1}                 @ obj.field (64 bits, aligned)<- r0/r1
8622     GOTO_OPCODE(ip)                     @ jump to next instruction
8623
8624
8625 /* continuation for OP_IPUT_OBJECT */
8626
8627     /*
8628      * Currently:
8629      *  r0 holds resolved field
8630      *  r9 holds object
8631      */
8632 .LOP_IPUT_OBJECT_finish:
8633     @bl      common_squeak0
8634     mov     r1, rINST, lsr #8           @ r1<- A+
8635     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8636     and     r1, r1, #15                 @ r1<- A
8637     cmp     r9, #0                      @ check object for null
8638     GET_VREG(r0, r1)                    @ r0<- fp[A]
8639     beq     common_errNullObject        @ object was null
8640     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8641     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8642     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8643     GOTO_OPCODE(ip)                     @ jump to next instruction
8644
8645
8646 /* continuation for OP_IPUT_BOOLEAN */
8647
8648     /*
8649      * Currently:
8650      *  r0 holds resolved field
8651      *  r9 holds object
8652      */
8653 .LOP_IPUT_BOOLEAN_finish:
8654     @bl      common_squeak1
8655     mov     r1, rINST, lsr #8           @ r1<- A+
8656     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8657     and     r1, r1, #15                 @ r1<- A
8658     cmp     r9, #0                      @ check object for null
8659     GET_VREG(r0, r1)                    @ r0<- fp[A]
8660     beq     common_errNullObject        @ object was null
8661     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8662     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8663     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8664     GOTO_OPCODE(ip)                     @ jump to next instruction
8665
8666
8667 /* continuation for OP_IPUT_BYTE */
8668
8669     /*
8670      * Currently:
8671      *  r0 holds resolved field
8672      *  r9 holds object
8673      */
8674 .LOP_IPUT_BYTE_finish:
8675     @bl      common_squeak2
8676     mov     r1, rINST, lsr #8           @ r1<- A+
8677     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8678     and     r1, r1, #15                 @ r1<- A
8679     cmp     r9, #0                      @ check object for null
8680     GET_VREG(r0, r1)                    @ r0<- fp[A]
8681     beq     common_errNullObject        @ object was null
8682     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8683     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8684     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8685     GOTO_OPCODE(ip)                     @ jump to next instruction
8686
8687
8688 /* continuation for OP_IPUT_CHAR */
8689
8690     /*
8691      * Currently:
8692      *  r0 holds resolved field
8693      *  r9 holds object
8694      */
8695 .LOP_IPUT_CHAR_finish:
8696     @bl      common_squeak3
8697     mov     r1, rINST, lsr #8           @ r1<- A+
8698     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8699     and     r1, r1, #15                 @ r1<- A
8700     cmp     r9, #0                      @ check object for null
8701     GET_VREG(r0, r1)                    @ r0<- fp[A]
8702     beq     common_errNullObject        @ object was null
8703     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8704     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8705     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8706     GOTO_OPCODE(ip)                     @ jump to next instruction
8707
8708
8709 /* continuation for OP_IPUT_SHORT */
8710
8711     /*
8712      * Currently:
8713      *  r0 holds resolved field
8714      *  r9 holds object
8715      */
8716 .LOP_IPUT_SHORT_finish:
8717     @bl      common_squeak4
8718     mov     r1, rINST, lsr #8           @ r1<- A+
8719     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8720     and     r1, r1, #15                 @ r1<- A
8721     cmp     r9, #0                      @ check object for null
8722     GET_VREG(r0, r1)                    @ r0<- fp[A]
8723     beq     common_errNullObject        @ object was null
8724     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8725     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8726     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8727     GOTO_OPCODE(ip)                     @ jump to next instruction
8728
8729
8730 /* continuation for OP_SGET */
8731
8732     /*
8733      * Continuation if the field has not yet been resolved.
8734      *  r1: BBBB field ref
8735      */
8736 .LOP_SGET_resolve:
8737     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8738     EXPORT_PC()                         @ resolve() could throw, so export now
8739     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8740     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8741     cmp     r0, #0                      @ success?
8742     bne     .LOP_SGET_finish          @ yes, finish
8743     b       common_exceptionThrown      @ no, handle exception
8744
8745
8746 /* continuation for OP_SGET_WIDE */
8747
8748     /*
8749      * Continuation if the field has not yet been resolved.
8750      *  r1: BBBB field ref
8751      */
8752 .LOP_SGET_WIDE_resolve:
8753     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8754     EXPORT_PC()                         @ resolve() could throw, so export now
8755     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8756     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8757     cmp     r0, #0                      @ success?
8758     bne     .LOP_SGET_WIDE_finish          @ yes, finish
8759     b       common_exceptionThrown      @ no, handle exception
8760
8761
8762 /* continuation for OP_SGET_OBJECT */
8763
8764     /*
8765      * Continuation if the field has not yet been resolved.
8766      *  r1: BBBB field ref
8767      */
8768 .LOP_SGET_OBJECT_resolve:
8769     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8770     EXPORT_PC()                         @ resolve() could throw, so export now
8771     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8772     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8773     cmp     r0, #0                      @ success?
8774     bne     .LOP_SGET_OBJECT_finish          @ yes, finish
8775     b       common_exceptionThrown      @ no, handle exception
8776
8777
8778 /* continuation for OP_SGET_BOOLEAN */
8779
8780     /*
8781      * Continuation if the field has not yet been resolved.
8782      *  r1: BBBB field ref
8783      */
8784 .LOP_SGET_BOOLEAN_resolve:
8785     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8786     EXPORT_PC()                         @ resolve() could throw, so export now
8787     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8788     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8789     cmp     r0, #0                      @ success?
8790     bne     .LOP_SGET_BOOLEAN_finish          @ yes, finish
8791     b       common_exceptionThrown      @ no, handle exception
8792
8793
8794 /* continuation for OP_SGET_BYTE */
8795
8796     /*
8797      * Continuation if the field has not yet been resolved.
8798      *  r1: BBBB field ref
8799      */
8800 .LOP_SGET_BYTE_resolve:
8801     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8802     EXPORT_PC()                         @ resolve() could throw, so export now
8803     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8804     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8805     cmp     r0, #0                      @ success?
8806     bne     .LOP_SGET_BYTE_finish          @ yes, finish
8807     b       common_exceptionThrown      @ no, handle exception
8808
8809
8810 /* continuation for OP_SGET_CHAR */
8811
8812     /*
8813      * Continuation if the field has not yet been resolved.
8814      *  r1: BBBB field ref
8815      */
8816 .LOP_SGET_CHAR_resolve:
8817     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8818     EXPORT_PC()                         @ resolve() could throw, so export now
8819     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8820     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8821     cmp     r0, #0                      @ success?
8822     bne     .LOP_SGET_CHAR_finish          @ yes, finish
8823     b       common_exceptionThrown      @ no, handle exception
8824
8825
8826 /* continuation for OP_SGET_SHORT */
8827
8828     /*
8829      * Continuation if the field has not yet been resolved.
8830      *  r1: BBBB field ref
8831      */
8832 .LOP_SGET_SHORT_resolve:
8833     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8834     EXPORT_PC()                         @ resolve() could throw, so export now
8835     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8836     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8837     cmp     r0, #0                      @ success?
8838     bne     .LOP_SGET_SHORT_finish          @ yes, finish
8839     b       common_exceptionThrown      @ no, handle exception
8840
8841
8842 /* continuation for OP_SPUT */
8843
8844     /*
8845      * Continuation if the field has not yet been resolved.
8846      *  r1: BBBB field ref
8847      */
8848 .LOP_SPUT_resolve:
8849     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8850     EXPORT_PC()                         @ resolve() could throw, so export now
8851     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8852     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8853     cmp     r0, #0                      @ success?
8854     bne     .LOP_SPUT_finish          @ yes, finish
8855     b       common_exceptionThrown      @ no, handle exception
8856
8857
8858 /* continuation for OP_SPUT_WIDE */
8859
8860     /*
8861      * Continuation if the field has not yet been resolved.
8862      *  r1: BBBB field ref
8863      *  r9: &fp[AA]
8864      */
8865 .LOP_SPUT_WIDE_resolve:
8866     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8867     EXPORT_PC()                         @ resolve() could throw, so export now
8868     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8869     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8870     cmp     r0, #0                      @ success?
8871     bne     .LOP_SPUT_WIDE_finish          @ yes, finish
8872     b       common_exceptionThrown      @ no, handle exception
8873
8874
8875 /* continuation for OP_SPUT_OBJECT */
8876
8877     /*
8878      * Continuation if the field has not yet been resolved.
8879      *  r1: BBBB field ref
8880      */
8881 .LOP_SPUT_OBJECT_resolve:
8882     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8883     EXPORT_PC()                         @ resolve() could throw, so export now
8884     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8885     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8886     cmp     r0, #0                      @ success?
8887     bne     .LOP_SPUT_OBJECT_finish          @ yes, finish
8888     b       common_exceptionThrown      @ no, handle exception
8889
8890
8891 /* continuation for OP_SPUT_BOOLEAN */
8892
8893     /*
8894      * Continuation if the field has not yet been resolved.
8895      *  r1: BBBB field ref
8896      */
8897 .LOP_SPUT_BOOLEAN_resolve:
8898     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8899     EXPORT_PC()                         @ resolve() could throw, so export now
8900     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8901     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8902     cmp     r0, #0                      @ success?
8903     bne     .LOP_SPUT_BOOLEAN_finish          @ yes, finish
8904     b       common_exceptionThrown      @ no, handle exception
8905
8906
8907 /* continuation for OP_SPUT_BYTE */
8908
8909     /*
8910      * Continuation if the field has not yet been resolved.
8911      *  r1: BBBB field ref
8912      */
8913 .LOP_SPUT_BYTE_resolve:
8914     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8915     EXPORT_PC()                         @ resolve() could throw, so export now
8916     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8917     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8918     cmp     r0, #0                      @ success?
8919     bne     .LOP_SPUT_BYTE_finish          @ yes, finish
8920     b       common_exceptionThrown      @ no, handle exception
8921
8922
8923 /* continuation for OP_SPUT_CHAR */
8924
8925     /*
8926      * Continuation if the field has not yet been resolved.
8927      *  r1: BBBB field ref
8928      */
8929 .LOP_SPUT_CHAR_resolve:
8930     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8931     EXPORT_PC()                         @ resolve() could throw, so export now
8932     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8933     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8934     cmp     r0, #0                      @ success?
8935     bne     .LOP_SPUT_CHAR_finish          @ yes, finish
8936     b       common_exceptionThrown      @ no, handle exception
8937
8938
8939 /* continuation for OP_SPUT_SHORT */
8940
8941     /*
8942      * Continuation if the field has not yet been resolved.
8943      *  r1: BBBB field ref
8944      */
8945 .LOP_SPUT_SHORT_resolve:
8946     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8947     EXPORT_PC()                         @ resolve() could throw, so export now
8948     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8949     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8950     cmp     r0, #0                      @ success?
8951     bne     .LOP_SPUT_SHORT_finish          @ yes, finish
8952     b       common_exceptionThrown      @ no, handle exception
8953
8954
8955 /* continuation for OP_INVOKE_VIRTUAL */
8956
8957     /*
8958      * At this point:
8959      *  r0 = resolved base method
8960      *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8961      */
8962 .LOP_INVOKE_VIRTUAL_continue:
8963     GET_VREG(r1, r10)                   @ r1<- "this" ptr
8964     ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8965     cmp     r1, #0                      @ is "this" null?
8966     beq     common_errNullObject        @ null "this", throw exception
8967     ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8968     ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8969     ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8970     bl      common_invokeMethodNoRange @ continue on
8971
8972
8973 /* continuation for OP_INVOKE_SUPER */
8974
8975     /*
8976      * At this point:
8977      *  r0 = resolved base method
8978      *  r9 = method->clazz
8979      */
8980 .LOP_INVOKE_SUPER_continue:
8981     ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8982     ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8983     ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8984     EXPORT_PC()                         @ must export for invoke
8985     cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8986     bcs     .LOP_INVOKE_SUPER_nsm             @ method not present in superclass
8987     ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8988     ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8989     bl      common_invokeMethodNoRange @ continue on
8990
8991 .LOP_INVOKE_SUPER_resolve:
8992     mov     r0, r9                      @ r0<- method->clazz
8993     mov     r2, #METHOD_VIRTUAL         @ resolver method type
8994     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8995     cmp     r0, #0                      @ got null?
8996     bne     .LOP_INVOKE_SUPER_continue        @ no, continue
8997     b       common_exceptionThrown      @ yes, handle exception
8998
8999     /*
9000      * Throw a NoSuchMethodError with the method name as the message.
9001      *  r0 = resolved base method
9002      */
9003 .LOP_INVOKE_SUPER_nsm:
9004     ldr     r1, [r0, #offMethod_name]   @ r1<- method name
9005     b       common_errNoSuchMethod
9006
9007
9008 /* continuation for OP_INVOKE_DIRECT */
9009
9010     /*
9011      * On entry:
9012      *  r1 = reference (BBBB or CCCC)
9013      *  r10 = "this" register
9014      */
9015 .LOP_INVOKE_DIRECT_resolve:
9016     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
9017     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
9018     mov     r2, #METHOD_DIRECT          @ resolver method type
9019     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
9020     cmp     r0, #0                      @ got null?
9021     GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
9022     bne     .LOP_INVOKE_DIRECT_finish          @ no, continue
9023     b       common_exceptionThrown      @ yes, handle exception
9024
9025
9026 /* continuation for OP_INVOKE_VIRTUAL_RANGE */
9027
9028     /*
9029      * At this point:
9030      *  r0 = resolved base method
9031      *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
9032      */
9033 .LOP_INVOKE_VIRTUAL_RANGE_continue:
9034     GET_VREG(r1, r10)                   @ r1<- "this" ptr
9035     ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
9036     cmp     r1, #0                      @ is "this" null?
9037     beq     common_errNullObject        @ null "this", throw exception
9038     ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
9039     ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
9040     ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
9041     bl      common_invokeMethodRange @ continue on
9042
9043
9044 /* continuation for OP_INVOKE_SUPER_RANGE */
9045
9046     /*
9047      * At this point:
9048      *  r0 = resolved base method
9049      *  r9 = method->clazz
9050      */
9051 .LOP_INVOKE_SUPER_RANGE_continue:
9052     ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
9053     ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
9054     ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
9055     EXPORT_PC()                         @ must export for invoke
9056     cmp     r2, r3                      @ compare (methodIndex, vtableCount)
9057     bcs     .LOP_INVOKE_SUPER_RANGE_nsm             @ method not present in superclass
9058     ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
9059     ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
9060     bl      common_invokeMethodRange @ continue on
9061
9062 .LOP_INVOKE_SUPER_RANGE_resolve:
9063     mov     r0, r9                      @ r0<- method->clazz
9064     mov     r2, #METHOD_VIRTUAL         @ resolver method type
9065     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
9066     cmp     r0, #0                      @ got null?
9067     bne     .LOP_INVOKE_SUPER_RANGE_continue        @ no, continue
9068     b       common_exceptionThrown      @ yes, handle exception
9069
9070     /*
9071      * Throw a NoSuchMethodError with the method name as the message.
9072      *  r0 = resolved base method
9073      */
9074 .LOP_INVOKE_SUPER_RANGE_nsm:
9075     ldr     r1, [r0, #offMethod_name]   @ r1<- method name
9076     b       common_errNoSuchMethod
9077
9078
9079 /* continuation for OP_INVOKE_DIRECT_RANGE */
9080
9081     /*
9082      * On entry:
9083      *  r1 = reference (BBBB or CCCC)
9084      *  r10 = "this" register
9085      */
9086 .LOP_INVOKE_DIRECT_RANGE_resolve:
9087     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
9088     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
9089     mov     r2, #METHOD_DIRECT          @ resolver method type
9090     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
9091     cmp     r0, #0                      @ got null?
9092     GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
9093     bne     .LOP_INVOKE_DIRECT_RANGE_finish          @ no, continue
9094     b       common_exceptionThrown      @ yes, handle exception
9095
9096
9097 /* continuation for OP_FLOAT_TO_LONG */
9098 /*
9099  * Convert the float in r0 to a long in r0/r1.
9100  *
9101  * We have to clip values to long min/max per the specification.  The
9102  * expected common case is a "reasonable" value that converts directly
9103  * to modest integer.  The EABI convert function isn't doing this for us.
9104  */
9105 f2l_doconv:
9106     stmfd   sp!, {r4, lr}
9107     mov     r1, #0x5f000000             @ (float)maxlong
9108     mov     r4, r0
9109     bl      __aeabi_fcmpge              @ is arg >= maxlong?
9110     cmp     r0, #0                      @ nonzero == yes
9111     mvnne   r0, #0                      @ return maxlong (7fffffff)
9112     mvnne   r1, #0x80000000
9113     ldmnefd sp!, {r4, pc}
9114
9115     mov     r0, r4                      @ recover arg
9116     mov     r1, #0xdf000000             @ (float)minlong
9117     bl      __aeabi_fcmple              @ is arg <= minlong?
9118     cmp     r0, #0                      @ nonzero == yes
9119     movne   r0, #0                      @ return minlong (80000000)
9120     movne   r1, #0x80000000
9121     ldmnefd sp!, {r4, pc}
9122
9123     mov     r0, r4                      @ recover arg
9124     mov     r1, r4
9125     bl      __aeabi_fcmpeq              @ is arg == self?
9126     cmp     r0, #0                      @ zero == no
9127     moveq   r1, #0                      @ return zero for NaN
9128     ldmeqfd sp!, {r4, pc}
9129
9130     mov     r0, r4                      @ recover arg
9131     bl      __aeabi_f2lz                @ convert float to long
9132     ldmfd   sp!, {r4, pc}
9133
9134
9135 /* continuation for OP_DOUBLE_TO_LONG */
9136 /*
9137  * Convert the double in r0/r1 to a long in r0/r1.
9138  *
9139  * We have to clip values to long min/max per the specification.  The
9140  * expected common case is a "reasonable" value that converts directly
9141  * to modest integer.  The EABI convert function isn't doing this for us.
9142  */
9143 d2l_doconv:
9144     stmfd   sp!, {r4, r5, lr}           @ save regs
9145     ldr     r3, .LOP_DOUBLE_TO_LONG_max         @ (double)maxlong, hi
9146     sub     sp, sp, #4                  @ align for EABI
9147     mov     r2, #0                      @ (double)maxlong, lo
9148     mov     r4, r0                      @ save r0
9149     mov     r5, r1                      @  and r1
9150     bl      __aeabi_dcmpge              @ is arg >= maxlong?
9151     cmp     r0, #0                      @ nonzero == yes
9152     mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
9153     mvnne   r1, #0x80000000
9154     bne     1f
9155
9156     mov     r0, r4                      @ recover arg
9157     mov     r1, r5
9158     ldr     r3, .LOP_DOUBLE_TO_LONG_min         @ (double)minlong, hi
9159     mov     r2, #0                      @ (double)minlong, lo
9160     bl      __aeabi_dcmple              @ is arg <= minlong?
9161     cmp     r0, #0                      @ nonzero == yes
9162     movne   r0, #0                      @ return minlong (8000000000000000)
9163     movne   r1, #0x80000000
9164     bne     1f
9165
9166     mov     r0, r4                      @ recover arg
9167     mov     r1, r5
9168     mov     r2, r4                      @ compare against self
9169     mov     r3, r5
9170     bl      __aeabi_dcmpeq              @ is arg == self?
9171     cmp     r0, #0                      @ zero == no
9172     moveq   r1, #0                      @ return zero for NaN
9173     beq     1f
9174
9175     mov     r0, r4                      @ recover arg
9176     mov     r1, r5
9177     bl      __aeabi_d2lz                @ convert double to long
9178
9179 1:
9180     add     sp, sp, #4
9181     ldmfd   sp!, {r4, r5, pc}
9182
9183 .LOP_DOUBLE_TO_LONG_max:
9184     .word   0x43e00000                  @ maxlong, as a double (high word)
9185 .LOP_DOUBLE_TO_LONG_min:
9186     .word   0xc3e00000                  @ minlong, as a double (high word)
9187
9188
9189 /* continuation for OP_MUL_LONG */
9190
9191 .LOP_MUL_LONG_finish:
9192     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9193     stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
9194     GOTO_OPCODE(ip)                     @ jump to next instruction
9195
9196
9197 /* continuation for OP_SHL_LONG */
9198
9199 .LOP_SHL_LONG_finish:
9200     mov     r0, r0, asl r2              @  r0<- r0 << r2
9201     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9202     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9203     GOTO_OPCODE(ip)                     @ jump to next instruction
9204
9205
9206 /* continuation for OP_SHR_LONG */
9207
9208 .LOP_SHR_LONG_finish:
9209     mov     r1, r1, asr r2              @  r1<- r1 >> r2
9210     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9211     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9212     GOTO_OPCODE(ip)                     @ jump to next instruction
9213
9214
9215 /* continuation for OP_USHR_LONG */
9216
9217 .LOP_USHR_LONG_finish:
9218     mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
9219     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9220     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9221     GOTO_OPCODE(ip)                     @ jump to next instruction
9222
9223
9224 /* continuation for OP_SHL_LONG_2ADDR */
9225
9226 .LOP_SHL_LONG_2ADDR_finish:
9227     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9228     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9229     GOTO_OPCODE(ip)                     @ jump to next instruction
9230
9231
9232 /* continuation for OP_SHR_LONG_2ADDR */
9233
9234 .LOP_SHR_LONG_2ADDR_finish:
9235     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9236     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9237     GOTO_OPCODE(ip)                     @ jump to next instruction
9238
9239
9240 /* continuation for OP_USHR_LONG_2ADDR */
9241
9242 .LOP_USHR_LONG_2ADDR_finish:
9243     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9244     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9245     GOTO_OPCODE(ip)                     @ jump to next instruction
9246
9247
9248 /* continuation for OP_EXECUTE_INLINE */
9249
9250     /*
9251      * Extract args, call function.
9252      *  r0 = #of args (0-4)
9253      *  r10 = call index
9254      *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
9255      *
9256      * Other ideas:
9257      * - Use a jump table from the main piece to jump directly into the
9258      *   AND/LDR pairs.  Costs a data load, saves a branch.
9259      * - Have five separate pieces that do the loading, so we can work the
9260      *   interleave a little better.  Increases code size.
9261      */
9262 .LOP_EXECUTE_INLINE_continue:
9263     rsb     r0, r0, #4                  @ r0<- 4-r0
9264     FETCH(r9, 2)                        @ r9<- FEDC
9265     add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
9266     bl      common_abort                @ (skipped due to ARM prefetch)
9267 4:  and     ip, r9, #0xf000             @ isolate F
9268     ldr     r3, [rFP, ip, lsr #10]      @ r3<- vF (shift right 12, left 2)
9269 3:  and     ip, r9, #0x0f00             @ isolate E
9270     ldr     r2, [rFP, ip, lsr #6]       @ r2<- vE
9271 2:  and     ip, r9, #0x00f0             @ isolate D
9272     ldr     r1, [rFP, ip, lsr #2]       @ r1<- vD
9273 1:  and     ip, r9, #0x000f             @ isolate C
9274     ldr     r0, [rFP, ip, lsl #2]       @ r0<- vC
9275 0:
9276     ldr     r9, .LOP_EXECUTE_INLINE_table       @ table of InlineOperation
9277     LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
9278     @ (not reached)
9279
9280 .LOP_EXECUTE_INLINE_table:
9281     .word   gDvmInlineOpsTable
9282
9283
9284     .size   dvmAsmSisterStart, .-dvmAsmSisterStart
9285     .global dvmAsmSisterEnd
9286 dvmAsmSisterEnd:
9287
9288 /* File: armv5te/footer.S */
9289 /*
9290  * ===========================================================================
9291  *  Common subroutines and data
9292  * ===========================================================================
9293  */
9294
9295     .text
9296     .align  2
9297
9298 /*
9299  * Common code when a backward branch is taken.
9300  *
9301  * On entry:
9302  *  r9 is PC adjustment *in bytes*
9303  */
9304 common_backwardBranch:
9305     mov     r0, #kInterpEntryInstr
9306     bl      common_periodicChecks
9307     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9308     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9309     GOTO_OPCODE(ip)                     @ jump to next instruction
9310
9311
9312 /*
9313  * Need to see if the thread needs to be suspended or debugger/profiler
9314  * activity has begun.
9315  *
9316  * TODO: if JDWP isn't running, zero out pDebuggerActive pointer so we don't
9317  * have to do the second ldr.
9318  *
9319  * TODO: reduce this so we're just checking a single location.
9320  *
9321  * On entry:
9322  *  r0 is reentry type, e.g. kInterpEntryInstr
9323  *  r9 is trampoline PC adjustment *in bytes*
9324  */
9325 common_periodicChecks:
9326     ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
9327
9328 #if defined(WITH_DEBUGGER)
9329     ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9330 #endif
9331 #if defined(WITH_PROFILER)
9332     ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9333 #endif
9334
9335     ldr     r3, [r3]                    @ r3<- suspendCount (int)
9336
9337 #if defined(WITH_DEBUGGER)
9338     ldrb    r1, [r1]                    @ r1<- debuggerActive (boolean)
9339 #endif
9340 #if defined (WITH_PROFILER)
9341     ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9342 #endif
9343
9344     cmp     r3, #0                      @ suspend pending?
9345     bne     2f                          @ yes, check suspend
9346
9347 #if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
9348 # if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
9349     orrs    r1, r1, r2                  @ r1<- r1 | r2
9350     cmp     r1, #0                      @ debugger attached or profiler started?
9351 # elif defined(WITH_DEBUGGER)
9352     cmp     r1, #0                      @ debugger attached?
9353 # elif defined(WITH_PROFILER)
9354     cmp     r2, #0                      @ profiler started?
9355 # endif
9356     bne     3f                          @ debugger/profiler, switch interp
9357 #endif
9358
9359     bx      lr                          @ nothing to do, return
9360
9361 2:  @ check suspend
9362     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9363     b       dvmCheckSuspendPending      @ suspend if necessary, then return
9364
9365 3:  @ debugger/profiler enabled, bail out
9366     add     rPC, rPC, r9                @ update rPC
9367     str     r0, [rGLUE, #offGlue_entryPoint]
9368     mov     r1, #1                      @ "want switch" = true
9369     b       common_gotoBail
9370
9371
9372 /*
9373  * The equivalent of "goto bail", this calls through the "bail handler".
9374  *
9375  * State registers will be saved to the "glue" area before bailing.
9376  *
9377  * On entry:
9378  *  r1 is "bool changeInterp", indicating if we want to switch to the
9379  *     other interpreter or just bail all the way out
9380  */
9381 common_gotoBail:
9382     SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9383     mov     r0, rGLUE                   @ r0<- glue ptr
9384     b       dvmMterpStdBail             @ call(glue, changeInterp)
9385
9386     @add     r1, r1, #1                  @ using (boolean+1)
9387     @add     r0, rGLUE, #offGlue_jmpBuf  @ r0<- &glue->jmpBuf
9388     @bl      _longjmp                    @ does not return
9389     @bl      common_abort
9390
9391
9392 /*
9393  * Common code for method invocation with range.
9394  *
9395  * On entry:
9396  *  r0 is "Method* methodToCall", the method we're trying to call
9397  */
9398 common_invokeMethodRange:
9399 .LinvokeNewRange:
9400     @ prepare to copy args to "outs" area of current frame
9401     movs    r2, rINST, lsr #8           @ r2<- AA (arg count) -- test for zero
9402     SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9403     beq     .LinvokeArgsDone            @ if no args, skip the rest
9404     FETCH(r1, 2)                        @ r1<- CCCC
9405
9406     @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
9407     @ (very few methods have > 10 args; could unroll for common cases)
9408     add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
9409     sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
9410 1:  ldr     r1, [r3], #4                @ val = *fp++
9411     subs    r2, r2, #1                  @ count--
9412     str     r1, [r10], #4               @ *outs++ = val
9413     bne     1b                          @ ...while count != 0
9414     b       .LinvokeArgsDone
9415
9416 /*
9417  * Common code for method invocation without range.
9418  *
9419  * On entry:
9420  *  r0 is "Method* methodToCall", the method we're trying to call
9421  */
9422 common_invokeMethodNoRange:
9423 .LinvokeNewNoRange:
9424     @ prepare to copy args to "outs" area of current frame
9425     movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
9426     SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9427     beq     .LinvokeArgsDone            @ if no args, skip the rest
9428     FETCH(r1, 2)                        @ r1<- GFED
9429
9430     @ r0=methodToCall, r1=GFED, r2=count, r10=outs
9431 .LinvokeNonRange:
9432     rsb     r2, r2, #5                  @ r2<- 5-r2
9433     add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
9434     bl      common_abort                @ (skipped due to ARM prefetch)
9435 5:  and     ip, rINST, #0x0f00          @ isolate A
9436     ldr     r3, [rFP, ip, lsr #6]       @ r3<- vA (shift right 8, left 2)
9437     mov     r0, r0                      @ nop
9438     str     r3, [r10, #-4]!             @ *--outs = vA
9439 4:  and     ip, r1, #0xf000             @ isolate G
9440     ldr     r3, [rFP, ip, lsr #10]      @ r3<- vG (shift right 12, left 2)
9441     mov     r0, r0                      @ nop
9442     str     r3, [r10, #-4]!             @ *--outs = vG
9443 3:  and     ip, r1, #0x0f00             @ isolate F
9444     ldr     r3, [rFP, ip, lsr #6]       @ r3<- vF
9445     mov     r0, r0                      @ nop
9446     str     r3, [r10, #-4]!             @ *--outs = vF
9447 2:  and     ip, r1, #0x00f0             @ isolate E
9448     ldr     r3, [rFP, ip, lsr #2]       @ r3<- vE
9449     mov     r0, r0                      @ nop
9450     str     r3, [r10, #-4]!             @ *--outs = vE
9451 1:  and     ip, r1, #0x000f             @ isolate D
9452     ldr     r3, [rFP, ip, lsl #2]       @ r3<- vD
9453     mov     r0, r0                      @ nop
9454     str     r3, [r10, #-4]!             @ *--outs = vD
9455 0:  @ fall through to .LinvokeArgsDone
9456
9457 .LinvokeArgsDone: @ r0=methodToCall
9458     @ find space for the new stack frame, check for overflow
9459     SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
9460     ldrh    r2, [r0, #offMethod_registersSize]  @ r2<- methodToCall->regsSize
9461     ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
9462     sub     r1, r1, r2, lsl #2          @ r1<- newFp (old savearea - regsSize)
9463     SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
9464 @    bl      common_dumpRegs
9465     ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
9466     sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
9467     cmp     r3, r9                      @ bottom < interpStackEnd?
9468     blt     .LstackOverflow             @ yes, this frame will overflow stack
9469
9470     @ set up newSaveArea
9471 #ifdef EASY_GDB
9472     SAVEAREA_FROM_FP(ip, rFP)           @ ip<- stack save area
9473     str     ip, [r10, #offStackSaveArea_prevSave]
9474 #endif
9475     str     rFP, [r10, #offStackSaveArea_prevFrame]
9476     str     rPC, [r10, #offStackSaveArea_savedPc]
9477     str     r0, [r10, #offStackSaveArea_method]
9478
9479     ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
9480     tst     r3, #ACC_NATIVE
9481     bne     .LinvokeNative
9482
9483     /*
9484     stmfd   sp!, {r0-r3}
9485     bl      common_printNewline
9486     mov     r0, rFP
9487     mov     r1, #0
9488     bl      dvmDumpFp
9489     ldmfd   sp!, {r0-r3}
9490     stmfd   sp!, {r0-r3}
9491     mov     r0, r1
9492     mov     r1, r10
9493     bl      dvmDumpFp
9494     bl      common_printNewline
9495     ldmfd   sp!, {r0-r3}
9496     */
9497
9498     @ Update "glue" values for the new method
9499     @ r0=methodToCall, r1=newFp
9500     ldr     r3, [r0, #offMethod_clazz]      @ r3<- method->clazz
9501     str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
9502     ldr     r3, [r3, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
9503     ldr     rPC, [r0, #offMethod_insns]     @ rPC<- method->insns
9504     str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
9505     ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
9506     FETCH_INST()                            @ load rINST from rPC
9507     mov     rFP, r1                         @ fp = newFp
9508     GET_INST_OPCODE(ip)                     @ extract opcode from rINST
9509     str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
9510     GOTO_OPCODE(ip)                         @ jump to next instruction
9511
9512 .LinvokeNative:
9513     @ Prep for the native call
9514     @ r0=methodToCall, r1=newFp, r10=newSaveArea
9515     ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
9516     ldr     r9, [r3, #offThread_jniLocal_nextEntry] @ r9<- thread->refNext
9517     str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
9518     str     r9, [r10, #offStackSaveArea_localRefTop] @newFp->localRefTop=refNext
9519     mov     r9, r3                      @ r9<- glue->self (preserve)
9520
9521     mov     r2, r0                      @ r2<- methodToCall
9522     mov     r0, r1                      @ r0<- newFp (points to args)
9523     add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
9524
9525 #ifdef ASSIST_DEBUGGER
9526     /* insert fake function header to help gdb find the stack frame */
9527     b       .Lskip
9528     .type   dalvik_mterp, %function
9529 dalvik_mterp:
9530     .fnstart
9531     MTERP_ENTRY1
9532     MTERP_ENTRY2
9533 .Lskip:
9534 #endif
9535
9536     @mov     lr, pc                      @ set return addr
9537     @ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
9538     LDR_PC_LR "[r2, #offMethod_nativeFunc]"
9539
9540     @ native return; r9=self, r10=newSaveArea
9541     @ equivalent to dvmPopJniLocals
9542     ldr     r0, [r10, #offStackSaveArea_localRefTop] @ r0<- newSave->localRefTop
9543     ldr     r1, [r9, #offThread_exception] @ check for exception
9544     str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
9545     cmp     r1, #0                      @ null?
9546     str     r0, [r9, #offThread_jniLocal_nextEntry] @ self->refNext<- r0
9547     bne     common_exceptionThrown      @ no, handle exception
9548
9549     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
9550     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9551     GOTO_OPCODE(ip)                     @ jump to next instruction
9552
9553 .LstackOverflow:
9554     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
9555     bl      dvmHandleStackOverflow
9556     b       common_exceptionThrown
9557 #ifdef ASSIST_DEBUGGER
9558     .fnend
9559 #endif
9560
9561
9562     /*
9563      * Common code for method invocation, calling through "glue code".
9564      *
9565      * TODO: now that we have range and non-range invoke handlers, this
9566      *       needs to be split into two.  Maybe just create entry points
9567      *       that set r9 and jump here?
9568      *
9569      * On entry:
9570      *  r0 is "Method* methodToCall", the method we're trying to call
9571      *  r9 is "bool methodCallRange", indicating if this is a /range variant
9572      */
9573      .if    0
9574 .LinvokeOld:
9575     sub     sp, sp, #8                  @ space for args + pad
9576     FETCH(ip, 2)                        @ ip<- FEDC or CCCC
9577     mov     r2, r0                      @ A2<- methodToCall
9578     mov     r0, rGLUE                   @ A0<- glue
9579     SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9580     mov     r1, r9                      @ A1<- methodCallRange
9581     mov     r3, rINST, lsr #8           @ A3<- AA
9582     str     ip, [sp, #0]                @ A4<- ip
9583     bl      dvmMterp_invokeMethod       @ call the C invokeMethod
9584     add     sp, sp, #8                  @ remove arg area
9585     b       common_resumeAfterGlueCall  @ continue to next instruction
9586     .endif
9587
9588
9589
9590 /*
9591  * Common code for handling a return instruction.
9592  *
9593  * This does not return.
9594  */
9595 common_returnFromMethod:
9596 .LreturnNew:
9597     mov     r0, #kInterpEntryReturn
9598     mov     r9, #0
9599     bl      common_periodicChecks
9600
9601     SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
9602     ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
9603     ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
9604                                         @ r2<- method we're returning to
9605     cmp     r2, #0                      @ is this a break frame?
9606     mov     r1, #0                      @ "want switch" = false
9607     beq     common_gotoBail             @ break frame, bail out completely
9608
9609     ldr     rPC, [r0, #offStackSaveArea_savedPc] @ pc = saveArea->savedPc
9610     ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
9611     str     r2, [rGLUE, #offGlue_method]    @ glue->method = newSave->method
9612     str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
9613     ldr     r1, [r2, #offMethod_clazz]      @ r1<- method->clazz
9614     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
9615     ldr     r1, [r1, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
9616     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9617     str     r1, [rGLUE, #offGlue_methodClassDex]
9618     GOTO_OPCODE(ip)                     @ jump to next instruction
9619
9620     /*
9621      * Return handling, calls through "glue code".
9622      */
9623      .if    0
9624 .LreturnOld:
9625     SAVE_PC_FP_TO_GLUE()                @ export state
9626     mov     r0, rGLUE                   @ arg to function
9627     bl      dvmMterp_returnFromMethod
9628     b       common_resumeAfterGlueCall
9629     .endif
9630
9631
9632 /*
9633  * Somebody has thrown an exception.  Handle it.
9634  *
9635  * If the exception processing code returns to us (instead of falling
9636  * out of the interpreter), continue with whatever the next instruction
9637  * now happens to be.
9638  *
9639  * This does not return.
9640  */
9641 common_exceptionThrown:
9642 .LexceptionNew:
9643     mov     r0, #kInterpEntryThrow
9644     mov     r9, #0
9645     bl      common_periodicChecks
9646
9647     ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
9648     ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
9649     mov     r1, r10                     @ r1<- self
9650     mov     r0, r9                      @ r0<- exception
9651     bl      dvmAddTrackedAlloc          @ don't let the exception be GCed
9652     mov     r3, #0                      @ r3<- NULL
9653     str     r3, [r10, #offThread_exception] @ self->exception = NULL
9654
9655     /* set up args and a local for "&fp" */
9656     /* (str sp, [sp, #-4]!  would be perfect here, but is discouraged) */
9657     str     rFP, [sp, #-4]!             @ *--sp = fp
9658     mov     ip, sp                      @ ip<- &fp
9659     mov     r3, #0                      @ r3<- false
9660     str     ip, [sp, #-4]!              @ *--sp = &fp
9661     ldr     r1, [rGLUE, #offGlue_method] @ r1<- glue->method
9662     mov     r0, r10                     @ r0<- self
9663     ldr     r1, [r1, #offMethod_insns]  @ r1<- method->insns
9664     mov     r2, r9                      @ r2<- exception
9665     sub     r1, rPC, r1                 @ r1<- pc - method->insns
9666     mov     r1, r1, asr #1              @ r1<- offset in code units
9667
9668     /* call, r0 gets catchRelPc (a code-unit offset) */
9669     bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
9670
9671     /* fix earlier stack overflow if necessary; may trash rFP */
9672     ldrb    r1, [r10, #offThread_stackOverflowed]
9673     cmp     r1, #0                      @ did we overflow earlier?
9674     beq     1f                          @ no, skip ahead
9675     mov     rFP, r0                     @ save relPc result in rFP
9676     mov     r0, r10                     @ r0<- self
9677     bl      dvmCleanupStackOverflow     @ call(self)
9678     mov     r0, rFP                     @ restore result
9679 1:
9680
9681     /* update frame pointer and check result from dvmFindCatchBlock */
9682     ldr     rFP, [sp, #4]               @ retrieve the updated rFP
9683     cmp     r0, #0                      @ is catchRelPc < 0?
9684     add     sp, sp, #8                  @ restore stack
9685     bmi     .LnotCaughtLocally
9686
9687     /* adjust locals to match self->curFrame and updated PC */
9688     SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
9689     ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
9690     str     r1, [rGLUE, #offGlue_method]    @ glue->method = new method
9691     ldr     r2, [r1, #offMethod_clazz]      @ r2<- method->clazz
9692     ldr     r3, [r1, #offMethod_insns]      @ r3<- method->insns
9693     ldr     r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
9694     add     rPC, r3, r0, asl #1             @ rPC<- method->insns + catchRelPc
9695     str     r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
9696
9697     /* release the tracked alloc on the exception */
9698     mov     r0, r9                      @ r0<- exception
9699     mov     r1, r10                     @ r1<- self
9700     bl      dvmReleaseTrackedAlloc      @ release the exception
9701
9702     /* restore the exception if the handler wants it */
9703     FETCH_INST()                        @ load rINST from rPC
9704     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9705     cmp     ip, #OP_MOVE_EXCEPTION      @ is it "move-exception"?
9706     streq   r9, [r10, #offThread_exception] @ yes, restore the exception
9707     GOTO_OPCODE(ip)                     @ jump to next instruction
9708
9709 .LnotCaughtLocally: @ r9=exception, r10=self
9710     /* fix stack overflow if necessary */
9711     ldrb    r1, [r10, #offThread_stackOverflowed]
9712     cmp     r1, #0                      @ did we overflow earlier?
9713     movne   r0, r10                     @ if yes: r0<- self
9714     blne    dvmCleanupStackOverflow     @ if yes: call(self)
9715
9716     @ may want to show "not caught locally" debug messages here
9717 #if DVM_SHOW_EXCEPTION >= 2
9718     /* call __android_log_print(prio, tag, format, ...) */
9719     /* "Exception %s from %s:%d not caught locally" */
9720     @ dvmLineNumFromPC(method, pc - method->insns)
9721     ldr     r0, [rGLUE, #offGlue_method]
9722     ldr     r1, [r0, #offMethod_insns]
9723     sub     r1, rPC, r1
9724     asr     r1, r1, #1
9725     bl      dvmLineNumFromPC
9726     str     r0, [sp, #-4]!
9727     @ dvmGetMethodSourceFile(method)
9728     ldr     r0, [rGLUE, #offGlue_method]
9729     bl      dvmGetMethodSourceFile
9730     str     r0, [sp, #-4]!
9731     @ exception->clazz->descriptor
9732     ldr     r3, [r9, #offObject_clazz]
9733     ldr     r3, [r3, #offClassObject_descriptor]
9734     @
9735     ldr     r2, strExceptionNotCaughtLocally
9736     ldr     r1, strLogTag
9737     mov     r0, #3                      @ LOG_DEBUG
9738     bl      __android_log_print
9739 #endif
9740     str     r9, [r10, #offThread_exception] @ restore exception
9741     mov     r0, r9                      @ r0<- exception
9742     mov     r1, r10                     @ r1<- self
9743     bl      dvmReleaseTrackedAlloc      @ release the exception
9744     mov     r1, #0                      @ "want switch" = false
9745     b       common_gotoBail             @ bail out
9746
9747
9748     /*
9749      * Exception handling, calls through "glue code".
9750      */
9751     .if     0
9752 .LexceptionOld:
9753     SAVE_PC_FP_TO_GLUE()                @ export state
9754     mov     r0, rGLUE                   @ arg to function
9755     bl      dvmMterp_exceptionThrown
9756     b       common_resumeAfterGlueCall
9757     .endif
9758
9759
9760 /*
9761  * After returning from a "glued" function, pull out the updated
9762  * values and start executing at the next instruction.
9763  */
9764 common_resumeAfterGlueCall:
9765     LOAD_PC_FP_FROM_GLUE()              @ pull rPC and rFP out of glue
9766     FETCH_INST()                        @ load rINST from rPC
9767     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9768     GOTO_OPCODE(ip)                     @ jump to next instruction
9769
9770 /*
9771  * Invalid array index.
9772  */
9773 common_errArrayIndex:
9774     EXPORT_PC()
9775     ldr     r0, strArrayIndexException
9776     mov     r1, #0
9777     bl      dvmThrowException
9778     b       common_exceptionThrown
9779
9780 /*
9781  * Invalid array value.
9782  */
9783 common_errArrayStore:
9784     EXPORT_PC()
9785     ldr     r0, strArrayStoreException
9786     mov     r1, #0
9787     bl      dvmThrowException
9788     b       common_exceptionThrown
9789
9790 /*
9791  * Integer divide or mod by zero.
9792  */
9793 common_errDivideByZero:
9794     EXPORT_PC()
9795     ldr     r0, strArithmeticException
9796     ldr     r1, strDivideByZero
9797     bl      dvmThrowException
9798     b       common_exceptionThrown
9799
9800 /*
9801  * Attempt to allocate an array with a negative size.
9802  */
9803 common_errNegativeArraySize:
9804     EXPORT_PC()
9805     ldr     r0, strNegativeArraySizeException
9806     mov     r1, #0
9807     bl      dvmThrowException
9808     b       common_exceptionThrown
9809
9810 /*
9811  * Invocation of a non-existent method.
9812  */
9813 common_errNoSuchMethod:
9814     EXPORT_PC()
9815     ldr     r0, strNoSuchMethodError
9816     mov     r1, #0
9817     bl      dvmThrowException
9818     b       common_exceptionThrown
9819
9820 /*
9821  * We encountered a null object when we weren't expecting one.  We
9822  * export the PC, throw a NullPointerException, and goto the exception
9823  * processing code.
9824  */
9825 common_errNullObject:
9826     EXPORT_PC()
9827     ldr     r0, strNullPointerException
9828     mov     r1, #0
9829     bl      dvmThrowException
9830     b       common_exceptionThrown
9831
9832 /*
9833  * For debugging, cause an immediate fault.  The source address will
9834  * be in lr (use a bl instruction to jump here).
9835  */
9836 common_abort:
9837     ldr     pc, .LdeadFood
9838 .LdeadFood:
9839     .word   0xdeadf00d
9840
9841 /*
9842  * Spit out a "we were here", preserving all registers.  (The attempt
9843  * to save ip won't work, but we need to save an even number of
9844  * registers for EABI 64-bit stack alignment.)
9845  */
9846     .macro  SQUEAK num
9847 common_squeak\num:
9848     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9849     ldr     r0, strSqueak
9850     mov     r1, #\num
9851     bl      printf
9852     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9853     bx      lr
9854     .endm
9855
9856     SQUEAK  0
9857     SQUEAK  1
9858     SQUEAK  2
9859     SQUEAK  3
9860     SQUEAK  4
9861     SQUEAK  5
9862
9863 /*
9864  * Spit out the number in r0, preserving registers.
9865  */
9866 common_printNum:
9867     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9868     mov     r1, r0
9869     ldr     r0, strSqueak
9870     bl      printf
9871     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9872     bx      lr
9873
9874 /*
9875  * Print a newline, preserving registers.
9876  */
9877 common_printNewline:
9878     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9879     ldr     r0, strNewline
9880     bl      printf
9881     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9882     bx      lr
9883
9884     /*
9885      * Print the 32-bit quantity in r0 as a hex value, preserving registers.
9886      */
9887 common_printHex:
9888     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9889     mov     r1, r0
9890     ldr     r0, strPrintHex
9891     bl      printf
9892     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9893     bx      lr
9894
9895 /*
9896  * Print the 64-bit quantity in r0-r1, preserving registers.
9897  */
9898 common_printLong:
9899     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9900     mov     r3, r1
9901     mov     r2, r0
9902     ldr     r0, strPrintLong
9903     bl      printf
9904     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9905     bx      lr
9906
9907 /*
9908  * Print full method info.  Pass the Method* in r0.  Preserves regs.
9909  */
9910 common_printMethod:
9911     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9912     bl      dvmMterpPrintMethod
9913     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9914     bx      lr
9915
9916 /*
9917  * Call a C helper function that dumps regs and possibly some
9918  * additional info.  Requires the C function to be compiled in.
9919  */
9920     .if     0
9921 common_dumpRegs:
9922     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9923     bl      dvmMterpDumpArmRegs
9924     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9925     bx      lr
9926     .endif
9927
9928
9929 /*
9930  * String references, must be close to the code that uses them.
9931  */
9932     .align  2
9933 strArithmeticException:
9934     .word   .LstrArithmeticException
9935 strArrayIndexException:
9936     .word   .LstrArrayIndexException
9937 strArrayStoreException:
9938     .word   .LstrArrayStoreException
9939 strDivideByZero:
9940     .word   .LstrDivideByZero
9941 strNegativeArraySizeException:
9942     .word   .LstrNegativeArraySizeException
9943 strNoSuchMethodError:
9944     .word   .LstrNoSuchMethodError
9945 strNullPointerException:
9946     .word   .LstrNullPointerException
9947
9948 strLogTag:
9949     .word   .LstrLogTag
9950 strExceptionNotCaughtLocally:
9951     .word   .LstrExceptionNotCaughtLocally
9952
9953 strNewline:
9954     .word   .LstrNewline
9955 strSqueak:
9956     .word   .LstrSqueak
9957 strPrintHex:
9958     .word   .LstrPrintHex
9959 strPrintLong:
9960     .word   .LstrPrintLong
9961
9962 /*
9963  * Zero-terminated ASCII string data.
9964  *
9965  * On ARM we have two choices: do like gcc does, and LDR from a .word
9966  * with the address, or use an ADR pseudo-op to get the address
9967  * directly.  ADR saves 4 bytes and an indirection, but it's using a
9968  * PC-relative addressing mode and hence has a limited range, which
9969  * makes it not work well with mergeable string sections.
9970  */
9971     .section .rodata.str1.4,"aMS",%progbits,1
9972
9973 .LstrBadEntryPoint:
9974     .asciz  "Bad entry point %d\n"
9975 .LstrArithmeticException:
9976     .asciz  "Ljava/lang/ArithmeticException;"
9977 .LstrArrayIndexException:
9978     .asciz  "Ljava/lang/ArrayIndexOutOfBoundsException;"
9979 .LstrArrayStoreException:
9980     .asciz  "Ljava/lang/ArrayStoreException;"
9981 .LstrClassCastException:
9982     .asciz  "Ljava/lang/ClassCastException;"
9983 .LstrDivideByZero:
9984     .asciz  "divide by zero"
9985 .LstrFilledNewArrayNotImpl:
9986     .asciz  "filled-new-array only implemented for objects and 'int'"
9987 .LstrInternalError:
9988     .asciz  "Ljava/lang/InternalError;"
9989 .LstrInstantiationError:
9990     .asciz  "Ljava/lang/InstantiationError;"
9991 .LstrNegativeArraySizeException:
9992     .asciz  "Ljava/lang/NegativeArraySizeException;"
9993 .LstrNoSuchMethodError:
9994     .asciz  "Ljava/lang/NoSuchMethodError;"
9995 .LstrNullPointerException:
9996     .asciz  "Ljava/lang/NullPointerException;"
9997
9998 .LstrLogTag:
9999     .asciz  "mterp"
10000 .LstrExceptionNotCaughtLocally:
10001     .asciz  "Exception %s from %s:%d not caught locally\n"
10002
10003 .LstrNewline:
10004     .asciz  "\n"
10005 .LstrSqueak:
10006     .asciz  "<%d>"
10007 .LstrPrintHex:
10008     .asciz  "<0x%x>"
10009 .LstrPrintLong:
10010     .asciz  "<%lld>"
10011
10012