InterpAsm-armv5te.S revision 2717622484eb0f7ad537275f7260b2f93324eda2
1/*
2 * This file was generated automatically by gen-mterp.py for 'armv5te'.
3 *
4 * --> DO NOT EDIT <--
5 */
6
7/* File: armv5te/header.S */
8/*
9 * Copyright (C) 2008 The Android Open Source Project
10 *
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 *      http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
22 */
23/*
24 * ARMv5 definitions and declarations.
25 */
26
27/*
28ARM EABI general notes:
29
30r0-r3 hold first 4 args to a method; they are not preserved across method calls
31r4-r8 are available for general use
32r9 is given special treatment in some situations, but not for us
33r10 (sl) seems to be generally available
34r11 (fp) is used by gcc (unless -fomit-frame-pointer is set)
35r12 (ip) is scratch -- not preserved across method calls
36r13 (sp) should be managed carefully in case a signal arrives
37r14 (lr) must be preserved
38r15 (pc) can be tinkered with directly
39
40r0 holds returns of <= 4 bytes
41r0-r1 hold returns of 8 bytes, low word in r0
42
43Callee must save/restore r4+ (except r12) if it modifies them.  If VFP
44is present, registers s16-s31 (a/k/a d8-d15, a/k/a q4-q7) must be preserved,
45s0-s15 (d0-d7, q0-a3) do not need to be.
46
47Stack is "full descending".  Only the arguments that don't fit in the first 4
48registers are placed on the stack.  "sp" points at the first stacked argument
49(i.e. the 5th arg).
50
51VFP: single-precision results in s0, double-precision results in d0.
52
53In the EABI, "sp" must be 64-bit aligned on entry to a function, and any
5464-bit quantities (long long, double) must be 64-bit aligned.
55*/
56
57/*
58Mterp and ARM notes:
59
60The following registers have fixed assignments:
61
62  reg nick      purpose
63  r4  rPC       interpreted program counter, used for fetching instructions
64  r5  rFP       interpreted frame pointer, used for accessing locals and args
65  r6  rGLUE     MterpGlue pointer
66  r7  rINST     first 16-bit code unit of current instruction
67  r8  rIBASE    interpreted instruction base pointer, used for computed goto
68
69Macros are provided for common operations.  Each macro MUST emit only
70one instruction to make instruction-counting easier.  They MUST NOT alter
71unspecified registers or condition codes.
72*/
73
74/* single-purpose registers, given names for clarity */
75#define rPC     r4
76#define rFP     r5
77#define rGLUE   r6
78#define rINST   r7
79#define rIBASE  r8
80
81/* save/restore the PC and/or FP from the glue struct */
82#define LOAD_PC_FROM_GLUE()     ldr     rPC, [rGLUE, #offGlue_pc]
83#define SAVE_PC_TO_GLUE()       str     rPC, [rGLUE, #offGlue_pc]
84#define LOAD_FP_FROM_GLUE()     ldr     rFP, [rGLUE, #offGlue_fp]
85#define SAVE_FP_TO_GLUE()       str     rFP, [rGLUE, #offGlue_fp]
86#define LOAD_PC_FP_FROM_GLUE()  ldmia   rGLUE, {rPC, rFP}
87#define SAVE_PC_FP_TO_GLUE()    stmia   rGLUE, {rPC, rFP}
88
89/*
90 * "export" the PC to the stack frame, f/b/o future exception objects.  Must
91 * be done *before* something calls dvmThrowException.
92 *
93 * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e.
94 * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc)
95 *
96 * It's okay to do this more than once.
97 */
98#define EXPORT_PC() \
99    str     rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)]
100
101/*
102 * Given a frame pointer, find the stack save area.
103 *
104 * In C this is "((StackSaveArea*)(_fp) -1)".
105 */
106#define SAVEAREA_FROM_FP(_reg, _fpreg) \
107    sub     _reg, _fpreg, #sizeofStackSaveArea
108
109/*
110 * Fetch the next instruction from rPC into rINST.  Does not advance rPC.
111 */
112#define FETCH_INST()            ldrh    rINST, [rPC]
113
114/*
115 * Fetch the next instruction from the specified offset.  Advances rPC
116 * to point to the next instruction.  "_count" is in 16-bit code units.
117 *
118 * Because of the limited size of immediate constants on ARM, this is only
119 * suitable for small forward movements (i.e. don't try to implement "goto"
120 * with this).
121 *
122 * This must come AFTER anything that can throw an exception, or the
123 * exception catch may miss.  (This also implies that it must come after
124 * EXPORT_PC().)
125 */
126#define FETCH_ADVANCE_INST(_count) ldrh    rINST, [rPC, #(_count*2)]!
127
128/*
129 * The operation performed here is similar to FETCH_ADVANCE_INST, except the
130 * src and dest registers are parameterized (not hard-wired to rPC and rINST).
131 */
132#define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \
133        ldrh    _dreg, [_sreg, #(_count*2)]!
134
135/*
136 * Fetch the next instruction from an offset specified by _reg.  Updates
137 * rPC to point to the next instruction.  "_reg" must specify the distance
138 * in bytes, *not* 16-bit code units, and may be a signed value.
139 *
140 * We want to write "ldrh rINST, [rPC, _reg, lsl #2]!", but some of the
141 * bits that hold the shift distance are used for the half/byte/sign flags.
142 * In some cases we can pre-double _reg for free, so we require a byte offset
143 * here.
144 */
145#define FETCH_ADVANCE_INST_RB(_reg) ldrh    rINST, [rPC, _reg]!
146
147/*
148 * Fetch a half-word code unit from an offset past the current PC.  The
149 * "_count" value is in 16-bit code units.  Does not advance rPC.
150 *
151 * The "_S" variant works the same but treats the value as signed.
152 */
153#define FETCH(_reg, _count)     ldrh    _reg, [rPC, #(_count*2)]
154#define FETCH_S(_reg, _count)   ldrsh   _reg, [rPC, #(_count*2)]
155
156/*
157 * Fetch one byte from an offset past the current PC.  Pass in the same
158 * "_count" as you would for FETCH, and an additional 0/1 indicating which
159 * byte of the halfword you want (lo/hi).
160 */
161#define FETCH_B(_reg, _count, _byte) ldrb     _reg, [rPC, #(_count*2+_byte)]
162
163/*
164 * Put the instruction's opcode field into the specified register.
165 */
166#define GET_INST_OPCODE(_reg)   and     _reg, rINST, #255
167
168/*
169 * Put the prefetched instruction's opcode field into the specified register.
170 */
171#define GET_PREFETCHED_OPCODE(_oreg, _ireg)   and     _oreg, _ireg, #255
172
173/*
174 * Begin executing the opcode in _reg.  Because this only jumps within the
175 * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork.
176 */
177#define GOTO_OPCODE(_reg)       add     pc, rIBASE, _reg, lsl #6
178#define GOTO_OPCODE_IFEQ(_reg)  addeq   pc, rIBASE, _reg, lsl #6
179#define GOTO_OPCODE_IFNE(_reg)  addne   pc, rIBASE, _reg, lsl #6
180
181/*
182 * Get/set the 32-bit value from a Dalvik register.
183 */
184#define GET_VREG(_reg, _vreg)   ldr     _reg, [rFP, _vreg, lsl #2]
185#define SET_VREG(_reg, _vreg)   str     _reg, [rFP, _vreg, lsl #2]
186
187#if defined(WITH_JIT)
188#define GET_JIT_ENABLED(_reg)       ldr     _reg,[rGLUE,#offGlue_jitEnabled]
189#define GET_JIT_PROF_TABLE(_reg)    ldr     _reg,[rGLUE,#offGlue_pJitProfTable]
190#endif
191
192/*
193 * Convert a virtual register index into an address.
194 */
195#define VREG_INDEX_TO_ADDR(_reg, _vreg) \
196        add     _reg, rFP, _vreg, lsl #2
197
198/*
199 * This is a #include, not a %include, because we want the C pre-processor
200 * to expand the macros into assembler assignment statements.
201 */
202#include "../common/asm-constants.h"
203
204
205/* File: armv5te/platform.S */
206/*
207 * ===========================================================================
208 *  CPU-version-specific defines
209 * ===========================================================================
210 */
211
212/*
213 * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5.  Essentially a
214 * one-way branch.
215 *
216 * May modify IP.  Does not modify LR.
217 */
218.macro  LDR_PC source
219    ldr     pc, \source
220.endm
221
222/*
223 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5.
224 * Jump to subroutine.
225 *
226 * May modify IP and LR.
227 */
228.macro  LDR_PC_LR source
229    mov     lr, pc
230    ldr     pc, \source
231.endm
232
233/*
234 * Macro for "LDMFD SP!, {...regs...,PC}".
235 *
236 * May modify IP and LR.
237 */
238.macro  LDMFD_PC regs
239    ldmfd   sp!, {\regs,pc}
240.endm
241
242
243/* File: armv5te/entry.S */
244/*
245 * Copyright (C) 2008 The Android Open Source Project
246 *
247 * Licensed under the Apache License, Version 2.0 (the "License");
248 * you may not use this file except in compliance with the License.
249 * You may obtain a copy of the License at
250 *
251 *      http://www.apache.org/licenses/LICENSE-2.0
252 *
253 * Unless required by applicable law or agreed to in writing, software
254 * distributed under the License is distributed on an "AS IS" BASIS,
255 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
256 * See the License for the specific language governing permissions and
257 * limitations under the License.
258 */
259/*
260 * Interpreter entry point.
261 */
262
263/*
264 * We don't have formal stack frames, so gdb scans upward in the code
265 * to find the start of the function (a label with the %function type),
266 * and then looks at the next few instructions to figure out what
267 * got pushed onto the stack.  From this it figures out how to restore
268 * the registers, including PC, for the previous stack frame.  If gdb
269 * sees a non-function label, it stops scanning, so either we need to
270 * have nothing but assembler-local labels between the entry point and
271 * the break, or we need to fake it out.
272 *
273 * When this is defined, we add some stuff to make gdb less confused.
274 */
275#define ASSIST_DEBUGGER 1
276
277    .text
278    .align  2
279    .global dvmMterpStdRun
280    .type   dvmMterpStdRun, %function
281
282/*
283 * On entry:
284 *  r0  MterpGlue* glue
285 *
286 * This function returns a boolean "changeInterp" value.  The return comes
287 * via a call to dvmMterpStdBail().
288 */
289dvmMterpStdRun:
290#define MTERP_ENTRY1 \
291    .save {r4-r10,fp,lr}; \
292    stmfd   sp!, {r4-r10,fp,lr}         @ save 9 regs
293#define MTERP_ENTRY2 \
294    .pad    #4; \
295    sub     sp, sp, #4                  @ align 64
296
297    .fnstart
298    MTERP_ENTRY1
299    MTERP_ENTRY2
300
301    /* save stack pointer, add magic word for debuggerd */
302    str     sp, [r0, #offGlue_bailPtr]  @ save SP for eventual return
303
304    /* set up "named" registers, figure out entry point */
305    mov     rGLUE, r0                   @ set rGLUE
306    ldrb    r1, [r0, #offGlue_entryPoint]   @ InterpEntry enum is char
307    LOAD_PC_FP_FROM_GLUE()              @ load rPC and rFP from "glue"
308    adr     rIBASE, dvmAsmInstructionStart  @ set rIBASE
309    cmp     r1, #kInterpEntryInstr      @ usual case?
310    bne     .Lnot_instr                 @ no, handle it
311
312#if defined(WITH_JIT)
313.Lno_singleStep:
314    /* Entry is always a possible trace start */
315    GET_JIT_PROF_TABLE(r0)
316    FETCH_INST()
317    cmp    r0,#0
318    bne    common_updateProfile
319    GET_INST_OPCODE(ip)
320    GOTO_OPCODE(ip)
321#else
322    /* start executing the instruction at rPC */
323    FETCH_INST()                        @ load rINST from rPC
324    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
325    GOTO_OPCODE(ip)                     @ jump to next instruction
326#endif
327
328.Lnot_instr:
329    cmp     r1, #kInterpEntryReturn     @ were we returning from a method?
330    beq     common_returnFromMethod
331
332.Lnot_return:
333    cmp     r1, #kInterpEntryThrow      @ were we throwing an exception?
334    beq     common_exceptionThrown
335
336#if defined(WITH_JIT)
337.Lnot_throw:
338    ldr     r0,[rGLUE, #offGlue_jitResume]
339    ldr     r2,[rGLUE, #offGlue_jitResumePC]
340    cmp     r1, #kInterpEntryResume     @ resuming after Jit single-step?
341    bne     .Lbad_arg
342    cmp     rPC,r2
343    bne     .Lno_singleStep             @ must have branched, don't resume
344    mov     r1, #kInterpEntryInstr
345    strb    r1, [rGLUE, #offGlue_entryPoint]
346    ldr     rINST, .LdvmCompilerTemplate
347    bx      r0                          @ re-enter the translation
348.LdvmCompilerTemplate:
349    .word   dvmCompilerTemplateStart
350#endif
351
352.Lbad_arg:
353    ldr     r0, strBadEntryPoint
354    @ r1 holds value of entryPoint
355    bl      printf
356    bl      dvmAbort
357    .fnend
358
359
360    .global dvmMterpStdBail
361    .type   dvmMterpStdBail, %function
362
363/*
364 * Restore the stack pointer and PC from the save point established on entry.
365 * This is essentially the same as a longjmp, but should be cheaper.  The
366 * last instruction causes us to return to whoever called dvmMterpStdRun.
367 *
368 * We pushed some registers on the stack in dvmMterpStdRun, then saved
369 * SP and LR.  Here we restore SP, restore the registers, and then restore
370 * LR to PC.
371 *
372 * On entry:
373 *  r0  MterpGlue* glue
374 *  r1  bool changeInterp
375 */
376dvmMterpStdBail:
377    ldr     sp, [r0, #offGlue_bailPtr]      @ sp<- saved SP
378    mov     r0, r1                          @ return the changeInterp value
379    add     sp, sp, #4                      @ un-align 64
380    LDMFD_PC "r4-r10,fp"                    @ restore 9 regs and return
381
382
383/*
384 * String references.
385 */
386strBadEntryPoint:
387    .word   .LstrBadEntryPoint
388
389
390
391    .global dvmAsmInstructionStart
392    .type   dvmAsmInstructionStart, %function
393dvmAsmInstructionStart = .L_OP_NOP
394    .text
395
396/* ------------------------------ */
397    .balign 64
398.L_OP_NOP: /* 0x00 */
399/* File: armv5te/OP_NOP.S */
400    FETCH_ADVANCE_INST(1)               @ advance to next instr, load rINST
401    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
402    GOTO_OPCODE(ip)                     @ execute it
403
404#ifdef ASSIST_DEBUGGER
405    /* insert fake function header to help gdb find the stack frame */
406    .type   dalvik_inst, %function
407dalvik_inst:
408    .fnstart
409    MTERP_ENTRY1
410    MTERP_ENTRY2
411    .fnend
412#endif
413
414
415/* ------------------------------ */
416    .balign 64
417.L_OP_MOVE: /* 0x01 */
418/* File: armv5te/OP_MOVE.S */
419    /* for move, move-object, long-to-int */
420    /* op vA, vB */
421    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
422    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
423    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
424    GET_VREG(r2, r1)                    @ r2<- fp[B]
425    and     r0, r0, #15
426    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
427    SET_VREG(r2, r0)                    @ fp[A]<- r2
428    GOTO_OPCODE(ip)                     @ execute next instruction
429
430
431/* ------------------------------ */
432    .balign 64
433.L_OP_MOVE_FROM16: /* 0x02 */
434/* File: armv5te/OP_MOVE_FROM16.S */
435    /* for: move/from16, move-object/from16 */
436    /* op vAA, vBBBB */
437    FETCH(r1, 1)                        @ r1<- BBBB
438    mov     r0, rINST, lsr #8           @ r0<- AA
439    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
440    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
441    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
442    SET_VREG(r2, r0)                    @ fp[AA]<- r2
443    GOTO_OPCODE(ip)                     @ jump to next instruction
444
445
446/* ------------------------------ */
447    .balign 64
448.L_OP_MOVE_16: /* 0x03 */
449/* File: armv5te/OP_MOVE_16.S */
450    /* for: move/16, move-object/16 */
451    /* op vAAAA, vBBBB */
452    FETCH(r1, 2)                        @ r1<- BBBB
453    FETCH(r0, 1)                        @ r0<- AAAA
454    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
455    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
456    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
457    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
458    GOTO_OPCODE(ip)                     @ jump to next instruction
459
460
461/* ------------------------------ */
462    .balign 64
463.L_OP_MOVE_WIDE: /* 0x04 */
464/* File: armv5te/OP_MOVE_WIDE.S */
465    /* move-wide vA, vB */
466    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
467    mov     r2, rINST, lsr #8           @ r2<- A(+)
468    mov     r3, rINST, lsr #12          @ r3<- B
469    and     r2, r2, #15
470    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
471    add     r2, rFP, r2, lsl #2         @ r2<- &fp[A]
472    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[B]
473    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
474    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
475    stmia   r2, {r0-r1}                 @ fp[A]<- r0/r1
476    GOTO_OPCODE(ip)                     @ jump to next instruction
477
478
479/* ------------------------------ */
480    .balign 64
481.L_OP_MOVE_WIDE_FROM16: /* 0x05 */
482/* File: armv5te/OP_MOVE_WIDE_FROM16.S */
483    /* move-wide/from16 vAA, vBBBB */
484    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
485    FETCH(r3, 1)                        @ r3<- BBBB
486    mov     r2, rINST, lsr #8           @ r2<- AA
487    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
488    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
489    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
490    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
491    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
492    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
493    GOTO_OPCODE(ip)                     @ jump to next instruction
494
495
496/* ------------------------------ */
497    .balign 64
498.L_OP_MOVE_WIDE_16: /* 0x06 */
499/* File: armv5te/OP_MOVE_WIDE_16.S */
500    /* move-wide/16 vAAAA, vBBBB */
501    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
502    FETCH(r3, 2)                        @ r3<- BBBB
503    FETCH(r2, 1)                        @ r2<- AAAA
504    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
505    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AAAA]
506    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
507    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
508    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
509    stmia   r2, {r0-r1}                 @ fp[AAAA]<- r0/r1
510    GOTO_OPCODE(ip)                     @ jump to next instruction
511
512
513/* ------------------------------ */
514    .balign 64
515.L_OP_MOVE_OBJECT: /* 0x07 */
516/* File: armv5te/OP_MOVE_OBJECT.S */
517/* File: armv5te/OP_MOVE.S */
518    /* for move, move-object, long-to-int */
519    /* op vA, vB */
520    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
521    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
522    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
523    GET_VREG(r2, r1)                    @ r2<- fp[B]
524    and     r0, r0, #15
525    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
526    SET_VREG(r2, r0)                    @ fp[A]<- r2
527    GOTO_OPCODE(ip)                     @ execute next instruction
528
529
530
531/* ------------------------------ */
532    .balign 64
533.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
534/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */
535/* File: armv5te/OP_MOVE_FROM16.S */
536    /* for: move/from16, move-object/from16 */
537    /* op vAA, vBBBB */
538    FETCH(r1, 1)                        @ r1<- BBBB
539    mov     r0, rINST, lsr #8           @ r0<- AA
540    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
541    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
542    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
543    SET_VREG(r2, r0)                    @ fp[AA]<- r2
544    GOTO_OPCODE(ip)                     @ jump to next instruction
545
546
547
548/* ------------------------------ */
549    .balign 64
550.L_OP_MOVE_OBJECT_16: /* 0x09 */
551/* File: armv5te/OP_MOVE_OBJECT_16.S */
552/* File: armv5te/OP_MOVE_16.S */
553    /* for: move/16, move-object/16 */
554    /* op vAAAA, vBBBB */
555    FETCH(r1, 2)                        @ r1<- BBBB
556    FETCH(r0, 1)                        @ r0<- AAAA
557    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
558    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
559    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
560    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
561    GOTO_OPCODE(ip)                     @ jump to next instruction
562
563
564
565/* ------------------------------ */
566    .balign 64
567.L_OP_MOVE_RESULT: /* 0x0a */
568/* File: armv5te/OP_MOVE_RESULT.S */
569    /* for: move-result, move-result-object */
570    /* op vAA */
571    mov     r2, rINST, lsr #8           @ r2<- AA
572    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
573    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
574    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
575    SET_VREG(r0, r2)                    @ fp[AA]<- r0
576    GOTO_OPCODE(ip)                     @ jump to next instruction
577
578
579/* ------------------------------ */
580    .balign 64
581.L_OP_MOVE_RESULT_WIDE: /* 0x0b */
582/* File: armv5te/OP_MOVE_RESULT_WIDE.S */
583    /* move-result-wide vAA */
584    mov     r2, rINST, lsr #8           @ r2<- AA
585    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
586    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
587    ldmia   r3, {r0-r1}                 @ r0/r1<- retval.j
588    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
589    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
590    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
591    GOTO_OPCODE(ip)                     @ jump to next instruction
592
593
594/* ------------------------------ */
595    .balign 64
596.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
597/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */
598/* File: armv5te/OP_MOVE_RESULT.S */
599    /* for: move-result, move-result-object */
600    /* op vAA */
601    mov     r2, rINST, lsr #8           @ r2<- AA
602    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
603    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
604    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
605    SET_VREG(r0, r2)                    @ fp[AA]<- r0
606    GOTO_OPCODE(ip)                     @ jump to next instruction
607
608
609
610/* ------------------------------ */
611    .balign 64
612.L_OP_MOVE_EXCEPTION: /* 0x0d */
613/* File: armv5te/OP_MOVE_EXCEPTION.S */
614    /* move-exception vAA */
615    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
616    mov     r2, rINST, lsr #8           @ r2<- AA
617    ldr     r3, [r0, #offThread_exception]  @ r3<- dvmGetException bypass
618    mov     r1, #0                      @ r1<- 0
619    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
620    SET_VREG(r3, r2)                    @ fp[AA]<- exception obj
621    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
622    str     r1, [r0, #offThread_exception]  @ dvmClearException bypass
623    GOTO_OPCODE(ip)                     @ jump to next instruction
624
625
626/* ------------------------------ */
627    .balign 64
628.L_OP_RETURN_VOID: /* 0x0e */
629/* File: armv5te/OP_RETURN_VOID.S */
630    b       common_returnFromMethod
631
632
633/* ------------------------------ */
634    .balign 64
635.L_OP_RETURN: /* 0x0f */
636/* File: armv5te/OP_RETURN.S */
637    /*
638     * Return a 32-bit value.  Copies the return value into the "glue"
639     * structure, then jumps to the return handler.
640     *
641     * for: return, return-object
642     */
643    /* op vAA */
644    mov     r2, rINST, lsr #8           @ r2<- AA
645    GET_VREG(r0, r2)                    @ r0<- vAA
646    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
647    b       common_returnFromMethod
648
649
650/* ------------------------------ */
651    .balign 64
652.L_OP_RETURN_WIDE: /* 0x10 */
653/* File: armv5te/OP_RETURN_WIDE.S */
654    /*
655     * Return a 64-bit value.  Copies the return value into the "glue"
656     * structure, then jumps to the return handler.
657     */
658    /* return-wide vAA */
659    mov     r2, rINST, lsr #8           @ r2<- AA
660    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
661    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
662    ldmia   r2, {r0-r1}                 @ r0/r1 <- vAA/vAA+1
663    stmia   r3, {r0-r1}                 @ retval<- r0/r1
664    b       common_returnFromMethod
665
666
667/* ------------------------------ */
668    .balign 64
669.L_OP_RETURN_OBJECT: /* 0x11 */
670/* File: armv5te/OP_RETURN_OBJECT.S */
671/* File: armv5te/OP_RETURN.S */
672    /*
673     * Return a 32-bit value.  Copies the return value into the "glue"
674     * structure, then jumps to the return handler.
675     *
676     * for: return, return-object
677     */
678    /* op vAA */
679    mov     r2, rINST, lsr #8           @ r2<- AA
680    GET_VREG(r0, r2)                    @ r0<- vAA
681    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
682    b       common_returnFromMethod
683
684
685
686/* ------------------------------ */
687    .balign 64
688.L_OP_CONST_4: /* 0x12 */
689/* File: armv5te/OP_CONST_4.S */
690    /* const/4 vA, #+B */
691    mov     r1, rINST, lsl #16          @ r1<- Bxxx0000
692    mov     r0, rINST, lsr #8           @ r0<- A+
693    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
694    mov     r1, r1, asr #28             @ r1<- sssssssB (sign-extended)
695    and     r0, r0, #15
696    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
697    SET_VREG(r1, r0)                    @ fp[A]<- r1
698    GOTO_OPCODE(ip)                     @ execute next instruction
699
700
701/* ------------------------------ */
702    .balign 64
703.L_OP_CONST_16: /* 0x13 */
704/* File: armv5te/OP_CONST_16.S */
705    /* const/16 vAA, #+BBBB */
706    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
707    mov     r3, rINST, lsr #8           @ r3<- AA
708    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
709    SET_VREG(r0, r3)                    @ vAA<- r0
710    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
711    GOTO_OPCODE(ip)                     @ jump to next instruction
712
713
714/* ------------------------------ */
715    .balign 64
716.L_OP_CONST: /* 0x14 */
717/* File: armv5te/OP_CONST.S */
718    /* const vAA, #+BBBBbbbb */
719    mov     r3, rINST, lsr #8           @ r3<- AA
720    FETCH(r0, 1)                        @ r0<- bbbb (low)
721    FETCH(r1, 2)                        @ r1<- BBBB (high)
722    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
723    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
724    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
725    SET_VREG(r0, r3)                    @ vAA<- r0
726    GOTO_OPCODE(ip)                     @ jump to next instruction
727
728
729/* ------------------------------ */
730    .balign 64
731.L_OP_CONST_HIGH16: /* 0x15 */
732/* File: armv5te/OP_CONST_HIGH16.S */
733    /* const/high16 vAA, #+BBBB0000 */
734    FETCH(r0, 1)                        @ r0<- 0000BBBB (zero-extended)
735    mov     r3, rINST, lsr #8           @ r3<- AA
736    mov     r0, r0, lsl #16             @ r0<- BBBB0000
737    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
738    SET_VREG(r0, r3)                    @ vAA<- r0
739    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
740    GOTO_OPCODE(ip)                     @ jump to next instruction
741
742
743/* ------------------------------ */
744    .balign 64
745.L_OP_CONST_WIDE_16: /* 0x16 */
746/* File: armv5te/OP_CONST_WIDE_16.S */
747    /* const-wide/16 vAA, #+BBBB */
748    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
749    mov     r3, rINST, lsr #8           @ r3<- AA
750    mov     r1, r0, asr #31             @ r1<- ssssssss
751    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
752    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
753    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
754    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
755    GOTO_OPCODE(ip)                     @ jump to next instruction
756
757
758/* ------------------------------ */
759    .balign 64
760.L_OP_CONST_WIDE_32: /* 0x17 */
761/* File: armv5te/OP_CONST_WIDE_32.S */
762    /* const-wide/32 vAA, #+BBBBbbbb */
763    FETCH(r0, 1)                        @ r0<- 0000bbbb (low)
764    mov     r3, rINST, lsr #8           @ r3<- AA
765    FETCH_S(r2, 2)                      @ r2<- ssssBBBB (high)
766    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
767    orr     r0, r0, r2, lsl #16         @ r0<- BBBBbbbb
768    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
769    mov     r1, r0, asr #31             @ r1<- ssssssss
770    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
771    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
772    GOTO_OPCODE(ip)                     @ jump to next instruction
773
774
775/* ------------------------------ */
776    .balign 64
777.L_OP_CONST_WIDE: /* 0x18 */
778/* File: armv5te/OP_CONST_WIDE.S */
779    /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
780    FETCH(r0, 1)                        @ r0<- bbbb (low)
781    FETCH(r1, 2)                        @ r1<- BBBB (low middle)
782    FETCH(r2, 3)                        @ r2<- hhhh (high middle)
783    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb (low word)
784    FETCH(r3, 4)                        @ r3<- HHHH (high)
785    mov     r9, rINST, lsr #8           @ r9<- AA
786    orr     r1, r2, r3, lsl #16         @ r1<- HHHHhhhh (high word)
787    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
788    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
789    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
790    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
791    GOTO_OPCODE(ip)                     @ jump to next instruction
792
793
794/* ------------------------------ */
795    .balign 64
796.L_OP_CONST_WIDE_HIGH16: /* 0x19 */
797/* File: armv5te/OP_CONST_WIDE_HIGH16.S */
798    /* const-wide/high16 vAA, #+BBBB000000000000 */
799    FETCH(r1, 1)                        @ r1<- 0000BBBB (zero-extended)
800    mov     r3, rINST, lsr #8           @ r3<- AA
801    mov     r0, #0                      @ r0<- 00000000
802    mov     r1, r1, lsl #16             @ r1<- BBBB0000
803    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
804    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
805    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
806    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
807    GOTO_OPCODE(ip)                     @ jump to next instruction
808
809
810/* ------------------------------ */
811    .balign 64
812.L_OP_CONST_STRING: /* 0x1a */
813/* File: armv5te/OP_CONST_STRING.S */
814    /* const/string vAA, String@BBBB */
815    FETCH(r1, 1)                        @ r1<- BBBB
816    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
817    mov     r9, rINST, lsr #8           @ r9<- AA
818    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
819    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
820    cmp     r0, #0                      @ not yet resolved?
821    beq     .LOP_CONST_STRING_resolve
822    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
823    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
824    SET_VREG(r0, r9)                    @ vAA<- r0
825    GOTO_OPCODE(ip)                     @ jump to next instruction
826
827/* ------------------------------ */
828    .balign 64
829.L_OP_CONST_STRING_JUMBO: /* 0x1b */
830/* File: armv5te/OP_CONST_STRING_JUMBO.S */
831    /* const/string vAA, String@BBBBBBBB */
832    FETCH(r0, 1)                        @ r0<- bbbb (low)
833    FETCH(r1, 2)                        @ r1<- BBBB (high)
834    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
835    mov     r9, rINST, lsr #8           @ r9<- AA
836    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
837    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
838    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
839    cmp     r0, #0
840    beq     .LOP_CONST_STRING_JUMBO_resolve
841    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
842    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
843    SET_VREG(r0, r9)                    @ vAA<- r0
844    GOTO_OPCODE(ip)                     @ jump to next instruction
845
846/* ------------------------------ */
847    .balign 64
848.L_OP_CONST_CLASS: /* 0x1c */
849/* File: armv5te/OP_CONST_CLASS.S */
850    /* const/class vAA, Class@BBBB */
851    FETCH(r1, 1)                        @ r1<- BBBB
852    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
853    mov     r9, rINST, lsr #8           @ r9<- AA
854    ldr     r2, [r2, #offDvmDex_pResClasses]   @ r2<- dvmDex->pResClasses
855    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResClasses[BBBB]
856    cmp     r0, #0                      @ not yet resolved?
857    beq     .LOP_CONST_CLASS_resolve
858    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
859    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
860    SET_VREG(r0, r9)                    @ vAA<- r0
861    GOTO_OPCODE(ip)                     @ jump to next instruction
862
863/* ------------------------------ */
864    .balign 64
865.L_OP_MONITOR_ENTER: /* 0x1d */
866/* File: armv5te/OP_MONITOR_ENTER.S */
867    /*
868     * Synchronize on an object.
869     */
870    /* monitor-enter vAA */
871    mov     r2, rINST, lsr #8           @ r2<- AA
872    GET_VREG(r1, r2)                    @ r1<- vAA (object)
873    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
874    cmp     r1, #0                      @ null object?
875    EXPORT_PC()                         @ need for precise GC, MONITOR_TRACKING
876    beq     common_errNullObject        @ null object, throw an exception
877    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
878    bl      dvmLockObject               @ call(self, obj)
879#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */
880    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
881    ldr     r1, [r0, #offThread_exception] @ check for exception
882    cmp     r1, #0
883    bne     common_exceptionThrown      @ exception raised, bail out
884#endif
885    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
886    GOTO_OPCODE(ip)                     @ jump to next instruction
887
888
889/* ------------------------------ */
890    .balign 64
891.L_OP_MONITOR_EXIT: /* 0x1e */
892/* File: armv5te/OP_MONITOR_EXIT.S */
893    /*
894     * Unlock an object.
895     *
896     * Exceptions that occur when unlocking a monitor need to appear as
897     * if they happened at the following instruction.  See the Dalvik
898     * instruction spec.
899     */
900    /* monitor-exit vAA */
901    mov     r2, rINST, lsr #8           @ r2<- AA
902    EXPORT_PC()                         @ before fetch: export the PC
903    GET_VREG(r1, r2)                    @ r1<- vAA (object)
904    cmp     r1, #0                      @ null object?
905    beq     common_errNullObject        @ yes
906    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
907    bl      dvmUnlockObject             @ r0<- success for unlock(self, obj)
908    cmp     r0, #0                      @ failed?
909    beq     common_exceptionThrown      @ yes, exception is pending
910    FETCH_ADVANCE_INST(1)               @ before throw: advance rPC, load rINST
911    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
912    GOTO_OPCODE(ip)                     @ jump to next instruction
913
914
915/* ------------------------------ */
916    .balign 64
917.L_OP_CHECK_CAST: /* 0x1f */
918/* File: armv5te/OP_CHECK_CAST.S */
919    /*
920     * Check to see if a cast from one class to another is allowed.
921     */
922    /* check-cast vAA, class@BBBB */
923    mov     r3, rINST, lsr #8           @ r3<- AA
924    FETCH(r2, 1)                        @ r2<- BBBB
925    GET_VREG(r9, r3)                    @ r9<- object
926    ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- pDvmDex
927    cmp     r9, #0                      @ is object null?
928    ldr     r0, [r0, #offDvmDex_pResClasses]    @ r0<- pDvmDex->pResClasses
929    beq     .LOP_CHECK_CAST_okay            @ null obj, cast always succeeds
930    ldr     r1, [r0, r2, lsl #2]        @ r1<- resolved class
931    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
932    cmp     r1, #0                      @ have we resolved this before?
933    beq     .LOP_CHECK_CAST_resolve         @ not resolved, do it now
934.LOP_CHECK_CAST_resolved:
935    cmp     r0, r1                      @ same class (trivial success)?
936    bne     .LOP_CHECK_CAST_fullcheck       @ no, do full check
937.LOP_CHECK_CAST_okay:
938    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
939    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
940    GOTO_OPCODE(ip)                     @ jump to next instruction
941
942/* ------------------------------ */
943    .balign 64
944.L_OP_INSTANCE_OF: /* 0x20 */
945/* File: armv5te/OP_INSTANCE_OF.S */
946    /*
947     * Check to see if an object reference is an instance of a class.
948     *
949     * Most common situation is a non-null object, being compared against
950     * an already-resolved class.
951     */
952    /* instance-of vA, vB, class@CCCC */
953    mov     r3, rINST, lsr #12          @ r3<- B
954    mov     r9, rINST, lsr #8           @ r9<- A+
955    GET_VREG(r0, r3)                    @ r0<- vB (object)
956    and     r9, r9, #15                 @ r9<- A
957    cmp     r0, #0                      @ is object null?
958    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- pDvmDex
959    beq     .LOP_INSTANCE_OF_store           @ null obj, not an instance, store r0
960    FETCH(r3, 1)                        @ r3<- CCCC
961    ldr     r2, [r2, #offDvmDex_pResClasses]    @ r2<- pDvmDex->pResClasses
962    ldr     r1, [r2, r3, lsl #2]        @ r1<- resolved class
963    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
964    cmp     r1, #0                      @ have we resolved this before?
965    beq     .LOP_INSTANCE_OF_resolve         @ not resolved, do it now
966.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class
967    cmp     r0, r1                      @ same class (trivial success)?
968    beq     .LOP_INSTANCE_OF_trivial         @ yes, trivial finish
969    b       .LOP_INSTANCE_OF_fullcheck       @ no, do full check
970
971/* ------------------------------ */
972    .balign 64
973.L_OP_ARRAY_LENGTH: /* 0x21 */
974/* File: armv5te/OP_ARRAY_LENGTH.S */
975    /*
976     * Return the length of an array.
977     */
978    mov     r1, rINST, lsr #12          @ r1<- B
979    mov     r2, rINST, lsr #8           @ r2<- A+
980    GET_VREG(r0, r1)                    @ r0<- vB (object ref)
981    and     r2, r2, #15                 @ r2<- A
982    cmp     r0, #0                      @ is object null?
983    beq     common_errNullObject        @ yup, fail
984    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
985    ldr     r3, [r0, #offArrayObject_length]    @ r3<- array length
986    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
987    SET_VREG(r3, r2)                    @ vB<- length
988    GOTO_OPCODE(ip)                     @ jump to next instruction
989
990
991/* ------------------------------ */
992    .balign 64
993.L_OP_NEW_INSTANCE: /* 0x22 */
994/* File: armv5te/OP_NEW_INSTANCE.S */
995    /*
996     * Create a new instance of a class.
997     */
998    /* new-instance vAA, class@BBBB */
999    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1000    FETCH(r1, 1)                        @ r1<- BBBB
1001    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1002    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1003    EXPORT_PC()                         @ req'd for init, resolve, alloc
1004    cmp     r0, #0                      @ already resolved?
1005    beq     .LOP_NEW_INSTANCE_resolve         @ no, resolve it now
1006.LOP_NEW_INSTANCE_resolved:   @ r0=class
1007    ldrb    r1, [r0, #offClassObject_status]    @ r1<- ClassStatus enum
1008    cmp     r1, #CLASS_INITIALIZED      @ has class been initialized?
1009    bne     .LOP_NEW_INSTANCE_needinit        @ no, init class now
1010.LOP_NEW_INSTANCE_initialized: @ r0=class
1011    mov     r1, #ALLOC_DONT_TRACK       @ flags for alloc call
1012    bl      dvmAllocObject              @ r0<- new object
1013    b       .LOP_NEW_INSTANCE_finish          @ continue
1014
1015/* ------------------------------ */
1016    .balign 64
1017.L_OP_NEW_ARRAY: /* 0x23 */
1018/* File: armv5te/OP_NEW_ARRAY.S */
1019    /*
1020     * Allocate an array of objects, specified with the array class
1021     * and a count.
1022     *
1023     * The verifier guarantees that this is an array class, so we don't
1024     * check for it here.
1025     */
1026    /* new-array vA, vB, class@CCCC */
1027    mov     r0, rINST, lsr #12          @ r0<- B
1028    FETCH(r2, 1)                        @ r2<- CCCC
1029    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1030    GET_VREG(r1, r0)                    @ r1<- vB (array length)
1031    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1032    cmp     r1, #0                      @ check length
1033    ldr     r0, [r3, r2, lsl #2]        @ r0<- resolved class
1034    bmi     common_errNegativeArraySize @ negative length, bail
1035    cmp     r0, #0                      @ already resolved?
1036    EXPORT_PC()                         @ req'd for resolve, alloc
1037    bne     .LOP_NEW_ARRAY_finish          @ resolved, continue
1038    b       .LOP_NEW_ARRAY_resolve         @ do resolve now
1039
1040/* ------------------------------ */
1041    .balign 64
1042.L_OP_FILLED_NEW_ARRAY: /* 0x24 */
1043/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1044    /*
1045     * Create a new array with elements filled from registers.
1046     *
1047     * for: filled-new-array, filled-new-array/range
1048     */
1049    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1050    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1051    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1052    FETCH(r1, 1)                        @ r1<- BBBB
1053    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1054    EXPORT_PC()                         @ need for resolve and alloc
1055    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1056    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1057    cmp     r0, #0                      @ already resolved?
1058    bne     .LOP_FILLED_NEW_ARRAY_continue        @ yes, continue on
10598:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1060    mov     r2, #0                      @ r2<- false
1061    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1062    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1063    cmp     r0, #0                      @ got null?
1064    beq     common_exceptionThrown      @ yes, handle exception
1065    b       .LOP_FILLED_NEW_ARRAY_continue
1066
1067/* ------------------------------ */
1068    .balign 64
1069.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
1070/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */
1071/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1072    /*
1073     * Create a new array with elements filled from registers.
1074     *
1075     * for: filled-new-array, filled-new-array/range
1076     */
1077    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1078    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1079    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1080    FETCH(r1, 1)                        @ r1<- BBBB
1081    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1082    EXPORT_PC()                         @ need for resolve and alloc
1083    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1084    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1085    cmp     r0, #0                      @ already resolved?
1086    bne     .LOP_FILLED_NEW_ARRAY_RANGE_continue        @ yes, continue on
10878:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1088    mov     r2, #0                      @ r2<- false
1089    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1090    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1091    cmp     r0, #0                      @ got null?
1092    beq     common_exceptionThrown      @ yes, handle exception
1093    b       .LOP_FILLED_NEW_ARRAY_RANGE_continue
1094
1095
1096/* ------------------------------ */
1097    .balign 64
1098.L_OP_FILL_ARRAY_DATA: /* 0x26 */
1099/* File: armv5te/OP_FILL_ARRAY_DATA.S */
1100    /* fill-array-data vAA, +BBBBBBBB */
1101    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1102    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1103    mov     r3, rINST, lsr #8           @ r3<- AA
1104    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
1105    GET_VREG(r0, r3)                    @ r0<- vAA (array object)
1106    add     r1, rPC, r1, lsl #1         @ r1<- PC + BBBBbbbb*2 (array data off.)
1107    EXPORT_PC();
1108    bl      dvmInterpHandleFillArrayData@ fill the array with predefined data
1109    cmp     r0, #0                      @ 0 means an exception is thrown
1110    beq     common_exceptionThrown      @ has exception
1111    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
1112    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1113    GOTO_OPCODE(ip)                     @ jump to next instruction
1114
1115/* ------------------------------ */
1116    .balign 64
1117.L_OP_THROW: /* 0x27 */
1118/* File: armv5te/OP_THROW.S */
1119    /*
1120     * Throw an exception object in the current thread.
1121     */
1122    /* throw vAA */
1123    mov     r2, rINST, lsr #8           @ r2<- AA
1124    GET_VREG(r1, r2)                    @ r1<- vAA (exception object)
1125    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
1126    cmp     r1, #0                      @ null object?
1127    beq     common_errNullObject        @ yes, throw an NPE instead
1128    @ bypass dvmSetException, just store it
1129    str     r1, [r0, #offThread_exception]  @ thread->exception<- obj
1130    b       common_exceptionThrown
1131
1132
1133/* ------------------------------ */
1134    .balign 64
1135.L_OP_GOTO: /* 0x28 */
1136/* File: armv5te/OP_GOTO.S */
1137    /*
1138     * Unconditional branch, 8-bit offset.
1139     *
1140     * The branch distance is a signed code-unit offset, which we need to
1141     * double to get a byte offset.
1142     */
1143    /* goto +AA */
1144    mov     r0, rINST, lsl #16          @ r0<- AAxx0000
1145    movs    r9, r0, asr #24             @ r9<- ssssssAA (sign-extended)
1146    mov     r9, r9, lsl #1              @ r9<- byte offset
1147    bmi     common_backwardBranch       @ backward branch, do periodic checks
1148#if defined(WITH_JIT)
1149    GET_JIT_PROF_TABLE(r0)
1150    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1151    cmp     r0,#0
1152    bne     common_updateProfile
1153    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1154    GOTO_OPCODE(ip)                     @ jump to next instruction
1155#else
1156    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1157    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1158    GOTO_OPCODE(ip)                     @ jump to next instruction
1159#endif
1160
1161/* ------------------------------ */
1162    .balign 64
1163.L_OP_GOTO_16: /* 0x29 */
1164/* File: armv5te/OP_GOTO_16.S */
1165    /*
1166     * Unconditional branch, 16-bit offset.
1167     *
1168     * The branch distance is a signed code-unit offset, which we need to
1169     * double to get a byte offset.
1170     */
1171    /* goto/16 +AAAA */
1172    FETCH_S(r0, 1)                      @ r0<- ssssAAAA (sign-extended)
1173    movs    r9, r0, asl #1              @ r9<- byte offset, check sign
1174    bmi     common_backwardBranch       @ backward branch, do periodic checks
1175#if defined(WITH_JIT)
1176    GET_JIT_PROF_TABLE(r0)
1177    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1178    cmp     r0,#0
1179    bne     common_updateProfile
1180    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1181    GOTO_OPCODE(ip)                     @ jump to next instruction
1182#else
1183    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1184    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1185    GOTO_OPCODE(ip)                     @ jump to next instruction
1186#endif
1187
1188
1189/* ------------------------------ */
1190    .balign 64
1191.L_OP_GOTO_32: /* 0x2a */
1192/* File: armv5te/OP_GOTO_32.S */
1193    /*
1194     * Unconditional branch, 32-bit offset.
1195     *
1196     * The branch distance is a signed code-unit offset, which we need to
1197     * double to get a byte offset.
1198     *
1199     * Unlike most opcodes, this one is allowed to branch to itself, so
1200     * our "backward branch" test must be "<=0" instead of "<0".  The ORRS
1201     * instruction doesn't affect the V flag, so we need to clear it
1202     * explicitly.
1203     */
1204    /* goto/32 +AAAAAAAA */
1205    FETCH(r0, 1)                        @ r0<- aaaa (lo)
1206    FETCH(r1, 2)                        @ r1<- AAAA (hi)
1207    cmp     ip, ip                      @ (clear V flag during stall)
1208    orrs    r0, r0, r1, lsl #16         @ r0<- AAAAaaaa, check sign
1209    mov     r9, r0, asl #1              @ r9<- byte offset
1210    ble     common_backwardBranch       @ backward branch, do periodic checks
1211#if defined(WITH_JIT)
1212    GET_JIT_PROF_TABLE(r0)
1213    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1214    cmp     r0,#0
1215    bne     common_updateProfile
1216    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1217    GOTO_OPCODE(ip)                     @ jump to next instruction
1218#else
1219    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1220    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1221    GOTO_OPCODE(ip)                     @ jump to next instruction
1222#endif
1223
1224/* ------------------------------ */
1225    .balign 64
1226.L_OP_PACKED_SWITCH: /* 0x2b */
1227/* File: armv5te/OP_PACKED_SWITCH.S */
1228    /*
1229     * Handle a packed-switch or sparse-switch instruction.  In both cases
1230     * we decode it and hand it off to a helper function.
1231     *
1232     * We don't really expect backward branches in a switch statement, but
1233     * they're perfectly legal, so we check for them here.
1234     *
1235     * for: packed-switch, sparse-switch
1236     */
1237    /* op vAA, +BBBB */
1238    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1239    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1240    mov     r3, rINST, lsr #8           @ r3<- AA
1241    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1242    GET_VREG(r1, r3)                    @ r1<- vAA
1243    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1244    bl      dvmInterpHandlePackedSwitch                       @ r0<- code-unit branch offset
1245    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1246    bmi     common_backwardBranch       @ backward branch, do periodic checks
1247    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1248#if defined(WITH_JIT)
1249    GET_JIT_PROF_TABLE(r0)
1250    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1251    cmp     r0,#0
1252    bne     common_updateProfile
1253    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1254    GOTO_OPCODE(ip)                     @ jump to next instruction
1255#else
1256    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1257    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1258    GOTO_OPCODE(ip)                     @ jump to next instruction
1259#endif
1260
1261
1262/* ------------------------------ */
1263    .balign 64
1264.L_OP_SPARSE_SWITCH: /* 0x2c */
1265/* File: armv5te/OP_SPARSE_SWITCH.S */
1266/* File: armv5te/OP_PACKED_SWITCH.S */
1267    /*
1268     * Handle a packed-switch or sparse-switch instruction.  In both cases
1269     * we decode it and hand it off to a helper function.
1270     *
1271     * We don't really expect backward branches in a switch statement, but
1272     * they're perfectly legal, so we check for them here.
1273     *
1274     * for: packed-switch, sparse-switch
1275     */
1276    /* op vAA, +BBBB */
1277    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1278    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1279    mov     r3, rINST, lsr #8           @ r3<- AA
1280    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1281    GET_VREG(r1, r3)                    @ r1<- vAA
1282    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1283    bl      dvmInterpHandleSparseSwitch                       @ r0<- code-unit branch offset
1284    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1285    bmi     common_backwardBranch       @ backward branch, do periodic checks
1286    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1287#if defined(WITH_JIT)
1288    GET_JIT_PROF_TABLE(r0)
1289    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1290    cmp     r0,#0
1291    bne     common_updateProfile
1292    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1293    GOTO_OPCODE(ip)                     @ jump to next instruction
1294#else
1295    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1296    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1297    GOTO_OPCODE(ip)                     @ jump to next instruction
1298#endif
1299
1300
1301
1302/* ------------------------------ */
1303    .balign 64
1304.L_OP_CMPL_FLOAT: /* 0x2d */
1305/* File: armv5te/OP_CMPL_FLOAT.S */
1306    /*
1307     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1308     * destination register based on the results of the comparison.
1309     *
1310     * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1311     * on what value we'd like to return when one of the operands is NaN.
1312     *
1313     * The operation we're implementing is:
1314     *   if (x == y)
1315     *     return 0;
1316     *   else if (x < y)
1317     *     return -1;
1318     *   else if (x > y)
1319     *     return 1;
1320     *   else
1321     *     return {-1,1};  // one or both operands was NaN
1322     *
1323     * The straightforward implementation requires 3 calls to functions
1324     * that return a result in r0.  We can do it with two calls if our
1325     * EABI library supports __aeabi_cfcmple (only one if we want to check
1326     * for NaN directly):
1327     *   check x <= y
1328     *     if <, return -1
1329     *     if ==, return 0
1330     *   check y <= x
1331     *     if <, return 1
1332     *   return {-1,1}
1333     *
1334     * for: cmpl-float, cmpg-float
1335     */
1336    /* op vAA, vBB, vCC */
1337    FETCH(r0, 1)                        @ r0<- CCBB
1338    and     r2, r0, #255                @ r2<- BB
1339    mov     r3, r0, lsr #8              @ r3<- CC
1340    GET_VREG(r9, r2)                    @ r9<- vBB
1341    GET_VREG(r10, r3)                   @ r10<- vCC
1342    mov     r0, r9                      @ copy to arg registers
1343    mov     r1, r10
1344    bl      __aeabi_cfcmple             @ cmp <=: C clear if <, Z set if eq
1345    bhi     .LOP_CMPL_FLOAT_gt_or_nan       @ C set and Z clear, disambiguate
1346    mvncc   r1, #0                      @ (less than) r1<- -1
1347    moveq   r1, #0                      @ (equal) r1<- 0, trumps less than
1348.LOP_CMPL_FLOAT_finish:
1349    mov     r3, rINST, lsr #8           @ r3<- AA
1350    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1351    SET_VREG(r1, r3)                    @ vAA<- r1
1352    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1353    GOTO_OPCODE(ip)                     @ jump to next instruction
1354
1355/* ------------------------------ */
1356    .balign 64
1357.L_OP_CMPG_FLOAT: /* 0x2e */
1358/* File: armv5te/OP_CMPG_FLOAT.S */
1359/* File: armv5te/OP_CMPL_FLOAT.S */
1360    /*
1361     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1362     * destination register based on the results of the comparison.
1363     *
1364     * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1365     * on what value we'd like to return when one of the operands is NaN.
1366     *
1367     * The operation we're implementing is:
1368     *   if (x == y)
1369     *     return 0;
1370     *   else if (x < y)
1371     *     return -1;
1372     *   else if (x > y)
1373     *     return 1;
1374     *   else
1375     *     return {-1,1};  // one or both operands was NaN
1376     *
1377     * The straightforward implementation requires 3 calls to functions
1378     * that return a result in r0.  We can do it with two calls if our
1379     * EABI library supports __aeabi_cfcmple (only one if we want to check
1380     * for NaN directly):
1381     *   check x <= y
1382     *     if <, return -1
1383     *     if ==, return 0
1384     *   check y <= x
1385     *     if <, return 1
1386     *   return {-1,1}
1387     *
1388     * for: cmpl-float, cmpg-float
1389     */
1390    /* op vAA, vBB, vCC */
1391    FETCH(r0, 1)                        @ r0<- CCBB
1392    and     r2, r0, #255                @ r2<- BB
1393    mov     r3, r0, lsr #8              @ r3<- CC
1394    GET_VREG(r9, r2)                    @ r9<- vBB
1395    GET_VREG(r10, r3)                   @ r10<- vCC
1396    mov     r0, r9                      @ copy to arg registers
1397    mov     r1, r10
1398    bl      __aeabi_cfcmple             @ cmp <=: C clear if <, Z set if eq
1399    bhi     .LOP_CMPG_FLOAT_gt_or_nan       @ C set and Z clear, disambiguate
1400    mvncc   r1, #0                      @ (less than) r1<- -1
1401    moveq   r1, #0                      @ (equal) r1<- 0, trumps less than
1402.LOP_CMPG_FLOAT_finish:
1403    mov     r3, rINST, lsr #8           @ r3<- AA
1404    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1405    SET_VREG(r1, r3)                    @ vAA<- r1
1406    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1407    GOTO_OPCODE(ip)                     @ jump to next instruction
1408
1409
1410/* ------------------------------ */
1411    .balign 64
1412.L_OP_CMPL_DOUBLE: /* 0x2f */
1413/* File: armv5te/OP_CMPL_DOUBLE.S */
1414    /*
1415     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1416     * destination register based on the results of the comparison.
1417     *
1418     * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1419     * on what value we'd like to return when one of the operands is NaN.
1420     *
1421     * See OP_CMPL_FLOAT for an explanation.
1422     *
1423     * For: cmpl-double, cmpg-double
1424     */
1425    /* op vAA, vBB, vCC */
1426    FETCH(r0, 1)                        @ r0<- CCBB
1427    and     r9, r0, #255                @ r9<- BB
1428    mov     r10, r0, lsr #8             @ r10<- CC
1429    add     r9, rFP, r9, lsl #2         @ r9<- &fp[BB]
1430    add     r10, rFP, r10, lsl #2       @ r10<- &fp[CC]
1431    ldmia   r9, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1432    ldmia   r10, {r2-r3}                @ r2/r3<- vCC/vCC+1
1433    bl      __aeabi_cdcmple             @ cmp <=: C clear if <, Z set if eq
1434    bhi     .LOP_CMPL_DOUBLE_gt_or_nan       @ C set and Z clear, disambiguate
1435    mvncc   r1, #0                      @ (less than) r1<- -1
1436    moveq   r1, #0                      @ (equal) r1<- 0, trumps less than
1437.LOP_CMPL_DOUBLE_finish:
1438    mov     r3, rINST, lsr #8           @ r3<- AA
1439    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1440    SET_VREG(r1, r3)                    @ vAA<- r1
1441    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1442    GOTO_OPCODE(ip)                     @ jump to next instruction
1443
1444/* ------------------------------ */
1445    .balign 64
1446.L_OP_CMPG_DOUBLE: /* 0x30 */
1447/* File: armv5te/OP_CMPG_DOUBLE.S */
1448/* File: armv5te/OP_CMPL_DOUBLE.S */
1449    /*
1450     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1451     * destination register based on the results of the comparison.
1452     *
1453     * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1454     * on what value we'd like to return when one of the operands is NaN.
1455     *
1456     * See OP_CMPL_FLOAT for an explanation.
1457     *
1458     * For: cmpl-double, cmpg-double
1459     */
1460    /* op vAA, vBB, vCC */
1461    FETCH(r0, 1)                        @ r0<- CCBB
1462    and     r9, r0, #255                @ r9<- BB
1463    mov     r10, r0, lsr #8             @ r10<- CC
1464    add     r9, rFP, r9, lsl #2         @ r9<- &fp[BB]
1465    add     r10, rFP, r10, lsl #2       @ r10<- &fp[CC]
1466    ldmia   r9, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1467    ldmia   r10, {r2-r3}                @ r2/r3<- vCC/vCC+1
1468    bl      __aeabi_cdcmple             @ cmp <=: C clear if <, Z set if eq
1469    bhi     .LOP_CMPG_DOUBLE_gt_or_nan       @ C set and Z clear, disambiguate
1470    mvncc   r1, #0                      @ (less than) r1<- -1
1471    moveq   r1, #0                      @ (equal) r1<- 0, trumps less than
1472.LOP_CMPG_DOUBLE_finish:
1473    mov     r3, rINST, lsr #8           @ r3<- AA
1474    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1475    SET_VREG(r1, r3)                    @ vAA<- r1
1476    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1477    GOTO_OPCODE(ip)                     @ jump to next instruction
1478
1479
1480/* ------------------------------ */
1481    .balign 64
1482.L_OP_CMP_LONG: /* 0x31 */
1483/* File: armv5te/OP_CMP_LONG.S */
1484    /*
1485     * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
1486     * register based on the results of the comparison.
1487     *
1488     * We load the full values with LDM, but in practice many values could
1489     * be resolved by only looking at the high word.  This could be made
1490     * faster or slower by splitting the LDM into a pair of LDRs.
1491     *
1492     * If we just wanted to set condition flags, we could do this:
1493     *  subs    ip, r0, r2
1494     *  sbcs    ip, r1, r3
1495     *  subeqs  ip, r0, r2
1496     * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
1497     * integer value, which we can do with 2 conditional mov/mvn instructions
1498     * (set 1, set -1; if they're equal we already have 0 in ip), giving
1499     * us a constant 5-cycle path plus a branch at the end to the
1500     * instruction epilogue code.  The multi-compare approach below needs
1501     * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
1502     * in the worst case (the 64-bit values are equal).
1503     */
1504    /* cmp-long vAA, vBB, vCC */
1505    FETCH(r0, 1)                        @ r0<- CCBB
1506    mov     r9, rINST, lsr #8           @ r9<- AA
1507    and     r2, r0, #255                @ r2<- BB
1508    mov     r3, r0, lsr #8              @ r3<- CC
1509    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
1510    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
1511    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1512    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
1513    cmp     r1, r3                      @ compare (vBB+1, vCC+1)
1514    blt     .LOP_CMP_LONG_less            @ signed compare on high part
1515    bgt     .LOP_CMP_LONG_greater
1516    subs    r1, r0, r2                  @ r1<- r0 - r2
1517    bhi     .LOP_CMP_LONG_greater         @ unsigned compare on low part
1518    bne     .LOP_CMP_LONG_less
1519    b       .LOP_CMP_LONG_finish          @ equal; r1 already holds 0
1520
1521/* ------------------------------ */
1522    .balign 64
1523.L_OP_IF_EQ: /* 0x32 */
1524/* File: armv5te/OP_IF_EQ.S */
1525/* File: armv5te/bincmp.S */
1526    /*
1527     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1528     * fragment that specifies the *reverse* comparison to perform, e.g.
1529     * for "if-le" you would use "gt".
1530     *
1531     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1532     */
1533    /* if-cmp vA, vB, +CCCC */
1534    mov     r0, rINST, lsr #8           @ r0<- A+
1535    mov     r1, rINST, lsr #12          @ r1<- B
1536    and     r0, r0, #15
1537    GET_VREG(r3, r1)                    @ r3<- vB
1538    GET_VREG(r2, r0)                    @ r2<- vA
1539    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1540    cmp     r2, r3                      @ compare (vA, vB)
1541    bne  1f                      @ branch to 1 if comparison failed
1542    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1543    movs    r9, r9, asl #1              @ convert to bytes, check sign
1544    bmi     common_backwardBranch       @ yes, do periodic checks
15451:
1546#if defined(WITH_JIT)
1547    GET_JIT_PROF_TABLE(r0)
1548    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1549    b        common_testUpdateProfile
1550#else
1551    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1552    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1553    GOTO_OPCODE(ip)                     @ jump to next instruction
1554#endif
1555
1556
1557
1558/* ------------------------------ */
1559    .balign 64
1560.L_OP_IF_NE: /* 0x33 */
1561/* File: armv5te/OP_IF_NE.S */
1562/* File: armv5te/bincmp.S */
1563    /*
1564     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1565     * fragment that specifies the *reverse* comparison to perform, e.g.
1566     * for "if-le" you would use "gt".
1567     *
1568     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1569     */
1570    /* if-cmp vA, vB, +CCCC */
1571    mov     r0, rINST, lsr #8           @ r0<- A+
1572    mov     r1, rINST, lsr #12          @ r1<- B
1573    and     r0, r0, #15
1574    GET_VREG(r3, r1)                    @ r3<- vB
1575    GET_VREG(r2, r0)                    @ r2<- vA
1576    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1577    cmp     r2, r3                      @ compare (vA, vB)
1578    beq  1f                      @ branch to 1 if comparison failed
1579    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1580    movs    r9, r9, asl #1              @ convert to bytes, check sign
1581    bmi     common_backwardBranch       @ yes, do periodic checks
15821:
1583#if defined(WITH_JIT)
1584    GET_JIT_PROF_TABLE(r0)
1585    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1586    b        common_testUpdateProfile
1587#else
1588    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1589    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1590    GOTO_OPCODE(ip)                     @ jump to next instruction
1591#endif
1592
1593
1594
1595/* ------------------------------ */
1596    .balign 64
1597.L_OP_IF_LT: /* 0x34 */
1598/* File: armv5te/OP_IF_LT.S */
1599/* File: armv5te/bincmp.S */
1600    /*
1601     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1602     * fragment that specifies the *reverse* comparison to perform, e.g.
1603     * for "if-le" you would use "gt".
1604     *
1605     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1606     */
1607    /* if-cmp vA, vB, +CCCC */
1608    mov     r0, rINST, lsr #8           @ r0<- A+
1609    mov     r1, rINST, lsr #12          @ r1<- B
1610    and     r0, r0, #15
1611    GET_VREG(r3, r1)                    @ r3<- vB
1612    GET_VREG(r2, r0)                    @ r2<- vA
1613    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1614    cmp     r2, r3                      @ compare (vA, vB)
1615    bge  1f                      @ branch to 1 if comparison failed
1616    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1617    movs    r9, r9, asl #1              @ convert to bytes, check sign
1618    bmi     common_backwardBranch       @ yes, do periodic checks
16191:
1620#if defined(WITH_JIT)
1621    GET_JIT_PROF_TABLE(r0)
1622    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1623    b        common_testUpdateProfile
1624#else
1625    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1626    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1627    GOTO_OPCODE(ip)                     @ jump to next instruction
1628#endif
1629
1630
1631
1632/* ------------------------------ */
1633    .balign 64
1634.L_OP_IF_GE: /* 0x35 */
1635/* File: armv5te/OP_IF_GE.S */
1636/* File: armv5te/bincmp.S */
1637    /*
1638     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1639     * fragment that specifies the *reverse* comparison to perform, e.g.
1640     * for "if-le" you would use "gt".
1641     *
1642     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1643     */
1644    /* if-cmp vA, vB, +CCCC */
1645    mov     r0, rINST, lsr #8           @ r0<- A+
1646    mov     r1, rINST, lsr #12          @ r1<- B
1647    and     r0, r0, #15
1648    GET_VREG(r3, r1)                    @ r3<- vB
1649    GET_VREG(r2, r0)                    @ r2<- vA
1650    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1651    cmp     r2, r3                      @ compare (vA, vB)
1652    blt  1f                      @ branch to 1 if comparison failed
1653    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1654    movs    r9, r9, asl #1              @ convert to bytes, check sign
1655    bmi     common_backwardBranch       @ yes, do periodic checks
16561:
1657#if defined(WITH_JIT)
1658    GET_JIT_PROF_TABLE(r0)
1659    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1660    b        common_testUpdateProfile
1661#else
1662    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1663    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1664    GOTO_OPCODE(ip)                     @ jump to next instruction
1665#endif
1666
1667
1668
1669/* ------------------------------ */
1670    .balign 64
1671.L_OP_IF_GT: /* 0x36 */
1672/* File: armv5te/OP_IF_GT.S */
1673/* File: armv5te/bincmp.S */
1674    /*
1675     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1676     * fragment that specifies the *reverse* comparison to perform, e.g.
1677     * for "if-le" you would use "gt".
1678     *
1679     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1680     */
1681    /* if-cmp vA, vB, +CCCC */
1682    mov     r0, rINST, lsr #8           @ r0<- A+
1683    mov     r1, rINST, lsr #12          @ r1<- B
1684    and     r0, r0, #15
1685    GET_VREG(r3, r1)                    @ r3<- vB
1686    GET_VREG(r2, r0)                    @ r2<- vA
1687    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1688    cmp     r2, r3                      @ compare (vA, vB)
1689    ble  1f                      @ branch to 1 if comparison failed
1690    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1691    movs    r9, r9, asl #1              @ convert to bytes, check sign
1692    bmi     common_backwardBranch       @ yes, do periodic checks
16931:
1694#if defined(WITH_JIT)
1695    GET_JIT_PROF_TABLE(r0)
1696    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1697    b        common_testUpdateProfile
1698#else
1699    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1700    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1701    GOTO_OPCODE(ip)                     @ jump to next instruction
1702#endif
1703
1704
1705
1706/* ------------------------------ */
1707    .balign 64
1708.L_OP_IF_LE: /* 0x37 */
1709/* File: armv5te/OP_IF_LE.S */
1710/* File: armv5te/bincmp.S */
1711    /*
1712     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1713     * fragment that specifies the *reverse* comparison to perform, e.g.
1714     * for "if-le" you would use "gt".
1715     *
1716     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1717     */
1718    /* if-cmp vA, vB, +CCCC */
1719    mov     r0, rINST, lsr #8           @ r0<- A+
1720    mov     r1, rINST, lsr #12          @ r1<- B
1721    and     r0, r0, #15
1722    GET_VREG(r3, r1)                    @ r3<- vB
1723    GET_VREG(r2, r0)                    @ r2<- vA
1724    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1725    cmp     r2, r3                      @ compare (vA, vB)
1726    bgt  1f                      @ branch to 1 if comparison failed
1727    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1728    movs    r9, r9, asl #1              @ convert to bytes, check sign
1729    bmi     common_backwardBranch       @ yes, do periodic checks
17301:
1731#if defined(WITH_JIT)
1732    GET_JIT_PROF_TABLE(r0)
1733    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1734    b        common_testUpdateProfile
1735#else
1736    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1737    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1738    GOTO_OPCODE(ip)                     @ jump to next instruction
1739#endif
1740
1741
1742
1743/* ------------------------------ */
1744    .balign 64
1745.L_OP_IF_EQZ: /* 0x38 */
1746/* File: armv5te/OP_IF_EQZ.S */
1747/* File: armv5te/zcmp.S */
1748    /*
1749     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1750     * fragment that specifies the *reverse* comparison to perform, e.g.
1751     * for "if-le" you would use "gt".
1752     *
1753     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1754     */
1755    /* if-cmp vAA, +BBBB */
1756    mov     r0, rINST, lsr #8           @ r0<- AA
1757    GET_VREG(r2, r0)                    @ r2<- vAA
1758    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1759    cmp     r2, #0                      @ compare (vA, 0)
1760    bne  1f                      @ branch to 1 if comparison failed
1761    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1762    movs    r9, r9, asl #1              @ convert to bytes, check sign
1763    bmi     common_backwardBranch       @ backward branch, do periodic checks
17641:
1765#if defined(WITH_JIT)
1766    GET_JIT_PROF_TABLE(r0)
1767    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1768    cmp     r0,#0
1769    bne     common_updateProfile
1770    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1771    GOTO_OPCODE(ip)                     @ jump to next instruction
1772#else
1773    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1774    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1775    GOTO_OPCODE(ip)                     @ jump to next instruction
1776#endif
1777
1778
1779
1780/* ------------------------------ */
1781    .balign 64
1782.L_OP_IF_NEZ: /* 0x39 */
1783/* File: armv5te/OP_IF_NEZ.S */
1784/* File: armv5te/zcmp.S */
1785    /*
1786     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1787     * fragment that specifies the *reverse* comparison to perform, e.g.
1788     * for "if-le" you would use "gt".
1789     *
1790     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1791     */
1792    /* if-cmp vAA, +BBBB */
1793    mov     r0, rINST, lsr #8           @ r0<- AA
1794    GET_VREG(r2, r0)                    @ r2<- vAA
1795    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1796    cmp     r2, #0                      @ compare (vA, 0)
1797    beq  1f                      @ branch to 1 if comparison failed
1798    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1799    movs    r9, r9, asl #1              @ convert to bytes, check sign
1800    bmi     common_backwardBranch       @ backward branch, do periodic checks
18011:
1802#if defined(WITH_JIT)
1803    GET_JIT_PROF_TABLE(r0)
1804    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1805    cmp     r0,#0
1806    bne     common_updateProfile
1807    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1808    GOTO_OPCODE(ip)                     @ jump to next instruction
1809#else
1810    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1811    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1812    GOTO_OPCODE(ip)                     @ jump to next instruction
1813#endif
1814
1815
1816
1817/* ------------------------------ */
1818    .balign 64
1819.L_OP_IF_LTZ: /* 0x3a */
1820/* File: armv5te/OP_IF_LTZ.S */
1821/* File: armv5te/zcmp.S */
1822    /*
1823     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1824     * fragment that specifies the *reverse* comparison to perform, e.g.
1825     * for "if-le" you would use "gt".
1826     *
1827     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1828     */
1829    /* if-cmp vAA, +BBBB */
1830    mov     r0, rINST, lsr #8           @ r0<- AA
1831    GET_VREG(r2, r0)                    @ r2<- vAA
1832    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1833    cmp     r2, #0                      @ compare (vA, 0)
1834    bge  1f                      @ branch to 1 if comparison failed
1835    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1836    movs    r9, r9, asl #1              @ convert to bytes, check sign
1837    bmi     common_backwardBranch       @ backward branch, do periodic checks
18381:
1839#if defined(WITH_JIT)
1840    GET_JIT_PROF_TABLE(r0)
1841    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1842    cmp     r0,#0
1843    bne     common_updateProfile
1844    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1845    GOTO_OPCODE(ip)                     @ jump to next instruction
1846#else
1847    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1848    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1849    GOTO_OPCODE(ip)                     @ jump to next instruction
1850#endif
1851
1852
1853
1854/* ------------------------------ */
1855    .balign 64
1856.L_OP_IF_GEZ: /* 0x3b */
1857/* File: armv5te/OP_IF_GEZ.S */
1858/* File: armv5te/zcmp.S */
1859    /*
1860     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1861     * fragment that specifies the *reverse* comparison to perform, e.g.
1862     * for "if-le" you would use "gt".
1863     *
1864     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1865     */
1866    /* if-cmp vAA, +BBBB */
1867    mov     r0, rINST, lsr #8           @ r0<- AA
1868    GET_VREG(r2, r0)                    @ r2<- vAA
1869    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1870    cmp     r2, #0                      @ compare (vA, 0)
1871    blt  1f                      @ branch to 1 if comparison failed
1872    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1873    movs    r9, r9, asl #1              @ convert to bytes, check sign
1874    bmi     common_backwardBranch       @ backward branch, do periodic checks
18751:
1876#if defined(WITH_JIT)
1877    GET_JIT_PROF_TABLE(r0)
1878    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1879    cmp     r0,#0
1880    bne     common_updateProfile
1881    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1882    GOTO_OPCODE(ip)                     @ jump to next instruction
1883#else
1884    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1885    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1886    GOTO_OPCODE(ip)                     @ jump to next instruction
1887#endif
1888
1889
1890
1891/* ------------------------------ */
1892    .balign 64
1893.L_OP_IF_GTZ: /* 0x3c */
1894/* File: armv5te/OP_IF_GTZ.S */
1895/* File: armv5te/zcmp.S */
1896    /*
1897     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1898     * fragment that specifies the *reverse* comparison to perform, e.g.
1899     * for "if-le" you would use "gt".
1900     *
1901     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1902     */
1903    /* if-cmp vAA, +BBBB */
1904    mov     r0, rINST, lsr #8           @ r0<- AA
1905    GET_VREG(r2, r0)                    @ r2<- vAA
1906    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1907    cmp     r2, #0                      @ compare (vA, 0)
1908    ble  1f                      @ branch to 1 if comparison failed
1909    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1910    movs    r9, r9, asl #1              @ convert to bytes, check sign
1911    bmi     common_backwardBranch       @ backward branch, do periodic checks
19121:
1913#if defined(WITH_JIT)
1914    GET_JIT_PROF_TABLE(r0)
1915    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1916    cmp     r0,#0
1917    bne     common_updateProfile
1918    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1919    GOTO_OPCODE(ip)                     @ jump to next instruction
1920#else
1921    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1922    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1923    GOTO_OPCODE(ip)                     @ jump to next instruction
1924#endif
1925
1926
1927
1928/* ------------------------------ */
1929    .balign 64
1930.L_OP_IF_LEZ: /* 0x3d */
1931/* File: armv5te/OP_IF_LEZ.S */
1932/* File: armv5te/zcmp.S */
1933    /*
1934     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1935     * fragment that specifies the *reverse* comparison to perform, e.g.
1936     * for "if-le" you would use "gt".
1937     *
1938     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1939     */
1940    /* if-cmp vAA, +BBBB */
1941    mov     r0, rINST, lsr #8           @ r0<- AA
1942    GET_VREG(r2, r0)                    @ r2<- vAA
1943    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1944    cmp     r2, #0                      @ compare (vA, 0)
1945    bgt  1f                      @ branch to 1 if comparison failed
1946    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1947    movs    r9, r9, asl #1              @ convert to bytes, check sign
1948    bmi     common_backwardBranch       @ backward branch, do periodic checks
19491:
1950#if defined(WITH_JIT)
1951    GET_JIT_PROF_TABLE(r0)
1952    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1953    cmp     r0,#0
1954    bne     common_updateProfile
1955    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1956    GOTO_OPCODE(ip)                     @ jump to next instruction
1957#else
1958    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1959    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1960    GOTO_OPCODE(ip)                     @ jump to next instruction
1961#endif
1962
1963
1964
1965/* ------------------------------ */
1966    .balign 64
1967.L_OP_UNUSED_3E: /* 0x3e */
1968/* File: armv5te/OP_UNUSED_3E.S */
1969/* File: armv5te/unused.S */
1970    bl      common_abort
1971
1972
1973
1974/* ------------------------------ */
1975    .balign 64
1976.L_OP_UNUSED_3F: /* 0x3f */
1977/* File: armv5te/OP_UNUSED_3F.S */
1978/* File: armv5te/unused.S */
1979    bl      common_abort
1980
1981
1982
1983/* ------------------------------ */
1984    .balign 64
1985.L_OP_UNUSED_40: /* 0x40 */
1986/* File: armv5te/OP_UNUSED_40.S */
1987/* File: armv5te/unused.S */
1988    bl      common_abort
1989
1990
1991
1992/* ------------------------------ */
1993    .balign 64
1994.L_OP_UNUSED_41: /* 0x41 */
1995/* File: armv5te/OP_UNUSED_41.S */
1996/* File: armv5te/unused.S */
1997    bl      common_abort
1998
1999
2000
2001/* ------------------------------ */
2002    .balign 64
2003.L_OP_UNUSED_42: /* 0x42 */
2004/* File: armv5te/OP_UNUSED_42.S */
2005/* File: armv5te/unused.S */
2006    bl      common_abort
2007
2008
2009
2010/* ------------------------------ */
2011    .balign 64
2012.L_OP_UNUSED_43: /* 0x43 */
2013/* File: armv5te/OP_UNUSED_43.S */
2014/* File: armv5te/unused.S */
2015    bl      common_abort
2016
2017
2018
2019/* ------------------------------ */
2020    .balign 64
2021.L_OP_AGET: /* 0x44 */
2022/* File: armv5te/OP_AGET.S */
2023    /*
2024     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2025     *
2026     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2027     * instructions.  We use a pair of FETCH_Bs instead.
2028     *
2029     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2030     */
2031    /* op vAA, vBB, vCC */
2032    FETCH_B(r2, 1, 0)                   @ r2<- BB
2033    mov     r9, rINST, lsr #8           @ r9<- AA
2034    FETCH_B(r3, 1, 1)                   @ r3<- CC
2035    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2036    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2037    cmp     r0, #0                      @ null array object?
2038    beq     common_errNullObject        @ yes, bail
2039    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2040    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2041    cmp     r1, r3                      @ compare unsigned index, length
2042    bcs     common_errArrayIndex        @ index >= length, bail
2043    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2044    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2045    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2046    SET_VREG(r2, r9)                    @ vAA<- r2
2047    GOTO_OPCODE(ip)                     @ jump to next instruction
2048
2049
2050/* ------------------------------ */
2051    .balign 64
2052.L_OP_AGET_WIDE: /* 0x45 */
2053/* File: armv5te/OP_AGET_WIDE.S */
2054    /*
2055     * Array get, 64 bits.  vAA <- vBB[vCC].
2056     *
2057     * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD.
2058     */
2059    /* aget-wide vAA, vBB, vCC */
2060    FETCH(r0, 1)                        @ r0<- CCBB
2061    mov     r9, rINST, lsr #8           @ r9<- AA
2062    and     r2, r0, #255                @ r2<- BB
2063    mov     r3, r0, lsr #8              @ r3<- CC
2064    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2065    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2066    cmp     r0, #0                      @ null array object?
2067    beq     common_errNullObject        @ yes, bail
2068    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2069    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2070    cmp     r1, r3                      @ compare unsigned index, length
2071    bcc     .LOP_AGET_WIDE_finish          @ okay, continue below
2072    b       common_errArrayIndex        @ index >= length, bail
2073    @ May want to swap the order of these two branches depending on how the
2074    @ branch prediction (if any) handles conditional forward branches vs.
2075    @ unconditional forward branches.
2076
2077/* ------------------------------ */
2078    .balign 64
2079.L_OP_AGET_OBJECT: /* 0x46 */
2080/* File: armv5te/OP_AGET_OBJECT.S */
2081/* File: armv5te/OP_AGET.S */
2082    /*
2083     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2084     *
2085     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2086     * instructions.  We use a pair of FETCH_Bs instead.
2087     *
2088     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2089     */
2090    /* op vAA, vBB, vCC */
2091    FETCH_B(r2, 1, 0)                   @ r2<- BB
2092    mov     r9, rINST, lsr #8           @ r9<- AA
2093    FETCH_B(r3, 1, 1)                   @ r3<- CC
2094    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2095    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2096    cmp     r0, #0                      @ null array object?
2097    beq     common_errNullObject        @ yes, bail
2098    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2099    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2100    cmp     r1, r3                      @ compare unsigned index, length
2101    bcs     common_errArrayIndex        @ index >= length, bail
2102    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2103    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2104    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2105    SET_VREG(r2, r9)                    @ vAA<- r2
2106    GOTO_OPCODE(ip)                     @ jump to next instruction
2107
2108
2109
2110/* ------------------------------ */
2111    .balign 64
2112.L_OP_AGET_BOOLEAN: /* 0x47 */
2113/* File: armv5te/OP_AGET_BOOLEAN.S */
2114/* File: armv5te/OP_AGET.S */
2115    /*
2116     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2117     *
2118     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2119     * instructions.  We use a pair of FETCH_Bs instead.
2120     *
2121     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2122     */
2123    /* op vAA, vBB, vCC */
2124    FETCH_B(r2, 1, 0)                   @ r2<- BB
2125    mov     r9, rINST, lsr #8           @ r9<- AA
2126    FETCH_B(r3, 1, 1)                   @ r3<- CC
2127    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2128    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2129    cmp     r0, #0                      @ null array object?
2130    beq     common_errNullObject        @ yes, bail
2131    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2132    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2133    cmp     r1, r3                      @ compare unsigned index, length
2134    bcs     common_errArrayIndex        @ index >= length, bail
2135    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2136    ldrb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2137    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2138    SET_VREG(r2, r9)                    @ vAA<- r2
2139    GOTO_OPCODE(ip)                     @ jump to next instruction
2140
2141
2142
2143/* ------------------------------ */
2144    .balign 64
2145.L_OP_AGET_BYTE: /* 0x48 */
2146/* File: armv5te/OP_AGET_BYTE.S */
2147/* File: armv5te/OP_AGET.S */
2148    /*
2149     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2150     *
2151     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2152     * instructions.  We use a pair of FETCH_Bs instead.
2153     *
2154     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2155     */
2156    /* op vAA, vBB, vCC */
2157    FETCH_B(r2, 1, 0)                   @ r2<- BB
2158    mov     r9, rINST, lsr #8           @ r9<- AA
2159    FETCH_B(r3, 1, 1)                   @ r3<- CC
2160    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2161    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2162    cmp     r0, #0                      @ null array object?
2163    beq     common_errNullObject        @ yes, bail
2164    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2165    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2166    cmp     r1, r3                      @ compare unsigned index, length
2167    bcs     common_errArrayIndex        @ index >= length, bail
2168    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2169    ldrsb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2170    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2171    SET_VREG(r2, r9)                    @ vAA<- r2
2172    GOTO_OPCODE(ip)                     @ jump to next instruction
2173
2174
2175
2176/* ------------------------------ */
2177    .balign 64
2178.L_OP_AGET_CHAR: /* 0x49 */
2179/* File: armv5te/OP_AGET_CHAR.S */
2180/* File: armv5te/OP_AGET.S */
2181    /*
2182     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2183     *
2184     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2185     * instructions.  We use a pair of FETCH_Bs instead.
2186     *
2187     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2188     */
2189    /* op vAA, vBB, vCC */
2190    FETCH_B(r2, 1, 0)                   @ r2<- BB
2191    mov     r9, rINST, lsr #8           @ r9<- AA
2192    FETCH_B(r3, 1, 1)                   @ r3<- CC
2193    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2194    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2195    cmp     r0, #0                      @ null array object?
2196    beq     common_errNullObject        @ yes, bail
2197    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2198    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2199    cmp     r1, r3                      @ compare unsigned index, length
2200    bcs     common_errArrayIndex        @ index >= length, bail
2201    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2202    ldrh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2203    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2204    SET_VREG(r2, r9)                    @ vAA<- r2
2205    GOTO_OPCODE(ip)                     @ jump to next instruction
2206
2207
2208
2209/* ------------------------------ */
2210    .balign 64
2211.L_OP_AGET_SHORT: /* 0x4a */
2212/* File: armv5te/OP_AGET_SHORT.S */
2213/* File: armv5te/OP_AGET.S */
2214    /*
2215     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2216     *
2217     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2218     * instructions.  We use a pair of FETCH_Bs instead.
2219     *
2220     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2221     */
2222    /* op vAA, vBB, vCC */
2223    FETCH_B(r2, 1, 0)                   @ r2<- BB
2224    mov     r9, rINST, lsr #8           @ r9<- AA
2225    FETCH_B(r3, 1, 1)                   @ r3<- CC
2226    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2227    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2228    cmp     r0, #0                      @ null array object?
2229    beq     common_errNullObject        @ yes, bail
2230    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2231    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2232    cmp     r1, r3                      @ compare unsigned index, length
2233    bcs     common_errArrayIndex        @ index >= length, bail
2234    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2235    ldrsh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2236    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2237    SET_VREG(r2, r9)                    @ vAA<- r2
2238    GOTO_OPCODE(ip)                     @ jump to next instruction
2239
2240
2241
2242/* ------------------------------ */
2243    .balign 64
2244.L_OP_APUT: /* 0x4b */
2245/* File: armv5te/OP_APUT.S */
2246    /*
2247     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2248     *
2249     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2250     * instructions.  We use a pair of FETCH_Bs instead.
2251     *
2252     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2253     */
2254    /* op vAA, vBB, vCC */
2255    FETCH_B(r2, 1, 0)                   @ r2<- BB
2256    mov     r9, rINST, lsr #8           @ r9<- AA
2257    FETCH_B(r3, 1, 1)                   @ r3<- CC
2258    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2259    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2260    cmp     r0, #0                      @ null array object?
2261    beq     common_errNullObject        @ yes, bail
2262    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2263    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2264    cmp     r1, r3                      @ compare unsigned index, length
2265    bcs     common_errArrayIndex        @ index >= length, bail
2266    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2267    GET_VREG(r2, r9)                    @ r2<- vAA
2268    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2269    str  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2270    GOTO_OPCODE(ip)                     @ jump to next instruction
2271
2272
2273/* ------------------------------ */
2274    .balign 64
2275.L_OP_APUT_WIDE: /* 0x4c */
2276/* File: armv5te/OP_APUT_WIDE.S */
2277    /*
2278     * Array put, 64 bits.  vBB[vCC] <- vAA.
2279     *
2280     * Arrays of long/double are 64-bit aligned, so it's okay to use STRD.
2281     */
2282    /* aput-wide vAA, vBB, vCC */
2283    FETCH(r0, 1)                        @ r0<- CCBB
2284    mov     r9, rINST, lsr #8           @ r9<- AA
2285    and     r2, r0, #255                @ r2<- BB
2286    mov     r3, r0, lsr #8              @ r3<- CC
2287    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2288    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2289    cmp     r0, #0                      @ null array object?
2290    beq     common_errNullObject        @ yes, bail
2291    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2292    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2293    cmp     r1, r3                      @ compare unsigned index, length
2294    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2295    bcc     .LOP_APUT_WIDE_finish          @ okay, continue below
2296    b       common_errArrayIndex        @ index >= length, bail
2297    @ May want to swap the order of these two branches depending on how the
2298    @ branch prediction (if any) handles conditional forward branches vs.
2299    @ unconditional forward branches.
2300
2301/* ------------------------------ */
2302    .balign 64
2303.L_OP_APUT_OBJECT: /* 0x4d */
2304/* File: armv5te/OP_APUT_OBJECT.S */
2305    /*
2306     * Store an object into an array.  vBB[vCC] <- vAA.
2307     *
2308     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2309     * instructions.  We use a pair of FETCH_Bs instead.
2310     */
2311    /* op vAA, vBB, vCC */
2312    FETCH(r0, 1)                        @ r0<- CCBB
2313    mov     r9, rINST, lsr #8           @ r9<- AA
2314    and     r2, r0, #255                @ r2<- BB
2315    mov     r3, r0, lsr #8              @ r3<- CC
2316    GET_VREG(r1, r2)                    @ r1<- vBB (array object)
2317    GET_VREG(r0, r3)                    @ r0<- vCC (requested index)
2318    cmp     r1, #0                      @ null array object?
2319    GET_VREG(r9, r9)                    @ r9<- vAA
2320    beq     common_errNullObject        @ yes, bail
2321    ldr     r3, [r1, #offArrayObject_length]    @ r3<- arrayObj->length
2322    add     r10, r1, r0, lsl #2         @ r10<- arrayObj + index*width
2323    cmp     r0, r3                      @ compare unsigned index, length
2324    bcc     .LOP_APUT_OBJECT_finish          @ we're okay, continue on
2325    b       common_errArrayIndex        @ index >= length, bail
2326
2327
2328/* ------------------------------ */
2329    .balign 64
2330.L_OP_APUT_BOOLEAN: /* 0x4e */
2331/* File: armv5te/OP_APUT_BOOLEAN.S */
2332/* File: armv5te/OP_APUT.S */
2333    /*
2334     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2335     *
2336     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2337     * instructions.  We use a pair of FETCH_Bs instead.
2338     *
2339     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2340     */
2341    /* op vAA, vBB, vCC */
2342    FETCH_B(r2, 1, 0)                   @ r2<- BB
2343    mov     r9, rINST, lsr #8           @ r9<- AA
2344    FETCH_B(r3, 1, 1)                   @ r3<- CC
2345    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2346    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2347    cmp     r0, #0                      @ null array object?
2348    beq     common_errNullObject        @ yes, bail
2349    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2350    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2351    cmp     r1, r3                      @ compare unsigned index, length
2352    bcs     common_errArrayIndex        @ index >= length, bail
2353    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2354    GET_VREG(r2, r9)                    @ r2<- vAA
2355    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2356    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2357    GOTO_OPCODE(ip)                     @ jump to next instruction
2358
2359
2360
2361/* ------------------------------ */
2362    .balign 64
2363.L_OP_APUT_BYTE: /* 0x4f */
2364/* File: armv5te/OP_APUT_BYTE.S */
2365/* File: armv5te/OP_APUT.S */
2366    /*
2367     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2368     *
2369     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2370     * instructions.  We use a pair of FETCH_Bs instead.
2371     *
2372     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2373     */
2374    /* op vAA, vBB, vCC */
2375    FETCH_B(r2, 1, 0)                   @ r2<- BB
2376    mov     r9, rINST, lsr #8           @ r9<- AA
2377    FETCH_B(r3, 1, 1)                   @ r3<- CC
2378    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2379    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2380    cmp     r0, #0                      @ null array object?
2381    beq     common_errNullObject        @ yes, bail
2382    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2383    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2384    cmp     r1, r3                      @ compare unsigned index, length
2385    bcs     common_errArrayIndex        @ index >= length, bail
2386    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2387    GET_VREG(r2, r9)                    @ r2<- vAA
2388    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2389    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2390    GOTO_OPCODE(ip)                     @ jump to next instruction
2391
2392
2393
2394/* ------------------------------ */
2395    .balign 64
2396.L_OP_APUT_CHAR: /* 0x50 */
2397/* File: armv5te/OP_APUT_CHAR.S */
2398/* File: armv5te/OP_APUT.S */
2399    /*
2400     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2401     *
2402     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2403     * instructions.  We use a pair of FETCH_Bs instead.
2404     *
2405     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2406     */
2407    /* op vAA, vBB, vCC */
2408    FETCH_B(r2, 1, 0)                   @ r2<- BB
2409    mov     r9, rINST, lsr #8           @ r9<- AA
2410    FETCH_B(r3, 1, 1)                   @ r3<- CC
2411    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2412    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2413    cmp     r0, #0                      @ null array object?
2414    beq     common_errNullObject        @ yes, bail
2415    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2416    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2417    cmp     r1, r3                      @ compare unsigned index, length
2418    bcs     common_errArrayIndex        @ index >= length, bail
2419    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2420    GET_VREG(r2, r9)                    @ r2<- vAA
2421    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2422    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2423    GOTO_OPCODE(ip)                     @ jump to next instruction
2424
2425
2426
2427/* ------------------------------ */
2428    .balign 64
2429.L_OP_APUT_SHORT: /* 0x51 */
2430/* File: armv5te/OP_APUT_SHORT.S */
2431/* File: armv5te/OP_APUT.S */
2432    /*
2433     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2434     *
2435     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2436     * instructions.  We use a pair of FETCH_Bs instead.
2437     *
2438     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2439     */
2440    /* op vAA, vBB, vCC */
2441    FETCH_B(r2, 1, 0)                   @ r2<- BB
2442    mov     r9, rINST, lsr #8           @ r9<- AA
2443    FETCH_B(r3, 1, 1)                   @ r3<- CC
2444    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2445    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2446    cmp     r0, #0                      @ null array object?
2447    beq     common_errNullObject        @ yes, bail
2448    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2449    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2450    cmp     r1, r3                      @ compare unsigned index, length
2451    bcs     common_errArrayIndex        @ index >= length, bail
2452    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2453    GET_VREG(r2, r9)                    @ r2<- vAA
2454    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2455    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2456    GOTO_OPCODE(ip)                     @ jump to next instruction
2457
2458
2459
2460/* ------------------------------ */
2461    .balign 64
2462.L_OP_IGET: /* 0x52 */
2463/* File: armv5te/OP_IGET.S */
2464    /*
2465     * General 32-bit instance field get.
2466     *
2467     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2468     */
2469    /* op vA, vB, field@CCCC */
2470    mov     r0, rINST, lsr #12          @ r0<- B
2471    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2472    FETCH(r1, 1)                        @ r1<- field ref CCCC
2473    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2474    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2475    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2476    cmp     r0, #0                      @ is resolved entry null?
2477    bne     .LOP_IGET_finish          @ no, already resolved
24788:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2479    EXPORT_PC()                         @ resolve() could throw
2480    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2481    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2482    cmp     r0, #0
2483    bne     .LOP_IGET_finish
2484    b       common_exceptionThrown
2485
2486/* ------------------------------ */
2487    .balign 64
2488.L_OP_IGET_WIDE: /* 0x53 */
2489/* File: armv5te/OP_IGET_WIDE.S */
2490    /*
2491     * Wide 32-bit instance field get.
2492     */
2493    /* iget-wide vA, vB, field@CCCC */
2494    mov     r0, rINST, lsr #12          @ r0<- B
2495    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2496    FETCH(r1, 1)                        @ r1<- field ref CCCC
2497    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2498    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2499    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2500    cmp     r0, #0                      @ is resolved entry null?
2501    bne     .LOP_IGET_WIDE_finish          @ no, already resolved
25028:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2503    EXPORT_PC()                         @ resolve() could throw
2504    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2505    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2506    cmp     r0, #0
2507    bne     .LOP_IGET_WIDE_finish
2508    b       common_exceptionThrown
2509
2510/* ------------------------------ */
2511    .balign 64
2512.L_OP_IGET_OBJECT: /* 0x54 */
2513/* File: armv5te/OP_IGET_OBJECT.S */
2514/* File: armv5te/OP_IGET.S */
2515    /*
2516     * General 32-bit instance field get.
2517     *
2518     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2519     */
2520    /* op vA, vB, field@CCCC */
2521    mov     r0, rINST, lsr #12          @ r0<- B
2522    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2523    FETCH(r1, 1)                        @ r1<- field ref CCCC
2524    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2525    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2526    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2527    cmp     r0, #0                      @ is resolved entry null?
2528    bne     .LOP_IGET_OBJECT_finish          @ no, already resolved
25298:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2530    EXPORT_PC()                         @ resolve() could throw
2531    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2532    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2533    cmp     r0, #0
2534    bne     .LOP_IGET_OBJECT_finish
2535    b       common_exceptionThrown
2536
2537
2538/* ------------------------------ */
2539    .balign 64
2540.L_OP_IGET_BOOLEAN: /* 0x55 */
2541/* File: armv5te/OP_IGET_BOOLEAN.S */
2542@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" }
2543/* File: armv5te/OP_IGET.S */
2544    /*
2545     * General 32-bit instance field get.
2546     *
2547     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2548     */
2549    /* op vA, vB, field@CCCC */
2550    mov     r0, rINST, lsr #12          @ r0<- B
2551    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2552    FETCH(r1, 1)                        @ r1<- field ref CCCC
2553    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2554    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2555    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2556    cmp     r0, #0                      @ is resolved entry null?
2557    bne     .LOP_IGET_BOOLEAN_finish          @ no, already resolved
25588:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2559    EXPORT_PC()                         @ resolve() could throw
2560    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2561    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2562    cmp     r0, #0
2563    bne     .LOP_IGET_BOOLEAN_finish
2564    b       common_exceptionThrown
2565
2566
2567/* ------------------------------ */
2568    .balign 64
2569.L_OP_IGET_BYTE: /* 0x56 */
2570/* File: armv5te/OP_IGET_BYTE.S */
2571@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" }
2572/* File: armv5te/OP_IGET.S */
2573    /*
2574     * General 32-bit instance field get.
2575     *
2576     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2577     */
2578    /* op vA, vB, field@CCCC */
2579    mov     r0, rINST, lsr #12          @ r0<- B
2580    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2581    FETCH(r1, 1)                        @ r1<- field ref CCCC
2582    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2583    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2584    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2585    cmp     r0, #0                      @ is resolved entry null?
2586    bne     .LOP_IGET_BYTE_finish          @ no, already resolved
25878:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2588    EXPORT_PC()                         @ resolve() could throw
2589    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2590    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2591    cmp     r0, #0
2592    bne     .LOP_IGET_BYTE_finish
2593    b       common_exceptionThrown
2594
2595
2596/* ------------------------------ */
2597    .balign 64
2598.L_OP_IGET_CHAR: /* 0x57 */
2599/* File: armv5te/OP_IGET_CHAR.S */
2600@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" }
2601/* File: armv5te/OP_IGET.S */
2602    /*
2603     * General 32-bit instance field get.
2604     *
2605     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2606     */
2607    /* op vA, vB, field@CCCC */
2608    mov     r0, rINST, lsr #12          @ r0<- B
2609    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2610    FETCH(r1, 1)                        @ r1<- field ref CCCC
2611    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2612    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2613    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2614    cmp     r0, #0                      @ is resolved entry null?
2615    bne     .LOP_IGET_CHAR_finish          @ no, already resolved
26168:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2617    EXPORT_PC()                         @ resolve() could throw
2618    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2619    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2620    cmp     r0, #0
2621    bne     .LOP_IGET_CHAR_finish
2622    b       common_exceptionThrown
2623
2624
2625/* ------------------------------ */
2626    .balign 64
2627.L_OP_IGET_SHORT: /* 0x58 */
2628/* File: armv5te/OP_IGET_SHORT.S */
2629@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" }
2630/* File: armv5te/OP_IGET.S */
2631    /*
2632     * General 32-bit instance field get.
2633     *
2634     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2635     */
2636    /* op vA, vB, field@CCCC */
2637    mov     r0, rINST, lsr #12          @ r0<- B
2638    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2639    FETCH(r1, 1)                        @ r1<- field ref CCCC
2640    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2641    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2642    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2643    cmp     r0, #0                      @ is resolved entry null?
2644    bne     .LOP_IGET_SHORT_finish          @ no, already resolved
26458:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2646    EXPORT_PC()                         @ resolve() could throw
2647    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2648    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2649    cmp     r0, #0
2650    bne     .LOP_IGET_SHORT_finish
2651    b       common_exceptionThrown
2652
2653
2654/* ------------------------------ */
2655    .balign 64
2656.L_OP_IPUT: /* 0x59 */
2657/* File: armv5te/OP_IPUT.S */
2658    /*
2659     * General 32-bit instance field put.
2660     *
2661     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2662     */
2663    /* op vA, vB, field@CCCC */
2664    mov     r0, rINST, lsr #12          @ r0<- B
2665    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2666    FETCH(r1, 1)                        @ r1<- field ref CCCC
2667    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2668    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2669    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2670    cmp     r0, #0                      @ is resolved entry null?
2671    bne     .LOP_IPUT_finish          @ no, already resolved
26728:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2673    EXPORT_PC()                         @ resolve() could throw
2674    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2675    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2676    cmp     r0, #0                      @ success?
2677    bne     .LOP_IPUT_finish          @ yes, finish up
2678    b       common_exceptionThrown
2679
2680/* ------------------------------ */
2681    .balign 64
2682.L_OP_IPUT_WIDE: /* 0x5a */
2683/* File: armv5te/OP_IPUT_WIDE.S */
2684    /* iput-wide vA, vB, field@CCCC */
2685    mov     r0, rINST, lsr #12          @ r0<- B
2686    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2687    FETCH(r1, 1)                        @ r1<- field ref CCCC
2688    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2689    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2690    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2691    cmp     r0, #0                      @ is resolved entry null?
2692    bne     .LOP_IPUT_WIDE_finish          @ no, already resolved
26938:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2694    EXPORT_PC()                         @ resolve() could throw
2695    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2696    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2697    cmp     r0, #0                      @ success?
2698    bne     .LOP_IPUT_WIDE_finish          @ yes, finish up
2699    b       common_exceptionThrown
2700
2701/* ------------------------------ */
2702    .balign 64
2703.L_OP_IPUT_OBJECT: /* 0x5b */
2704/* File: armv5te/OP_IPUT_OBJECT.S */
2705/* File: armv5te/OP_IPUT.S */
2706    /*
2707     * General 32-bit instance field put.
2708     *
2709     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2710     */
2711    /* op vA, vB, field@CCCC */
2712    mov     r0, rINST, lsr #12          @ r0<- B
2713    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2714    FETCH(r1, 1)                        @ r1<- field ref CCCC
2715    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2716    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2717    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2718    cmp     r0, #0                      @ is resolved entry null?
2719    bne     .LOP_IPUT_OBJECT_finish          @ no, already resolved
27208:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2721    EXPORT_PC()                         @ resolve() could throw
2722    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2723    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2724    cmp     r0, #0                      @ success?
2725    bne     .LOP_IPUT_OBJECT_finish          @ yes, finish up
2726    b       common_exceptionThrown
2727
2728
2729/* ------------------------------ */
2730    .balign 64
2731.L_OP_IPUT_BOOLEAN: /* 0x5c */
2732/* File: armv5te/OP_IPUT_BOOLEAN.S */
2733@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" }
2734/* File: armv5te/OP_IPUT.S */
2735    /*
2736     * General 32-bit instance field put.
2737     *
2738     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2739     */
2740    /* op vA, vB, field@CCCC */
2741    mov     r0, rINST, lsr #12          @ r0<- B
2742    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2743    FETCH(r1, 1)                        @ r1<- field ref CCCC
2744    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2745    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2746    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2747    cmp     r0, #0                      @ is resolved entry null?
2748    bne     .LOP_IPUT_BOOLEAN_finish          @ no, already resolved
27498:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2750    EXPORT_PC()                         @ resolve() could throw
2751    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2752    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2753    cmp     r0, #0                      @ success?
2754    bne     .LOP_IPUT_BOOLEAN_finish          @ yes, finish up
2755    b       common_exceptionThrown
2756
2757
2758/* ------------------------------ */
2759    .balign 64
2760.L_OP_IPUT_BYTE: /* 0x5d */
2761/* File: armv5te/OP_IPUT_BYTE.S */
2762@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" }
2763/* File: armv5te/OP_IPUT.S */
2764    /*
2765     * General 32-bit instance field put.
2766     *
2767     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2768     */
2769    /* op vA, vB, field@CCCC */
2770    mov     r0, rINST, lsr #12          @ r0<- B
2771    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2772    FETCH(r1, 1)                        @ r1<- field ref CCCC
2773    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2774    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2775    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2776    cmp     r0, #0                      @ is resolved entry null?
2777    bne     .LOP_IPUT_BYTE_finish          @ no, already resolved
27788:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2779    EXPORT_PC()                         @ resolve() could throw
2780    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2781    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2782    cmp     r0, #0                      @ success?
2783    bne     .LOP_IPUT_BYTE_finish          @ yes, finish up
2784    b       common_exceptionThrown
2785
2786
2787/* ------------------------------ */
2788    .balign 64
2789.L_OP_IPUT_CHAR: /* 0x5e */
2790/* File: armv5te/OP_IPUT_CHAR.S */
2791@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" }
2792/* File: armv5te/OP_IPUT.S */
2793    /*
2794     * General 32-bit instance field put.
2795     *
2796     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2797     */
2798    /* op vA, vB, field@CCCC */
2799    mov     r0, rINST, lsr #12          @ r0<- B
2800    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2801    FETCH(r1, 1)                        @ r1<- field ref CCCC
2802    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2803    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2804    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2805    cmp     r0, #0                      @ is resolved entry null?
2806    bne     .LOP_IPUT_CHAR_finish          @ no, already resolved
28078:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2808    EXPORT_PC()                         @ resolve() could throw
2809    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2810    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2811    cmp     r0, #0                      @ success?
2812    bne     .LOP_IPUT_CHAR_finish          @ yes, finish up
2813    b       common_exceptionThrown
2814
2815
2816/* ------------------------------ */
2817    .balign 64
2818.L_OP_IPUT_SHORT: /* 0x5f */
2819/* File: armv5te/OP_IPUT_SHORT.S */
2820@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" }
2821/* File: armv5te/OP_IPUT.S */
2822    /*
2823     * General 32-bit instance field put.
2824     *
2825     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2826     */
2827    /* op vA, vB, field@CCCC */
2828    mov     r0, rINST, lsr #12          @ r0<- B
2829    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2830    FETCH(r1, 1)                        @ r1<- field ref CCCC
2831    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2832    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2833    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2834    cmp     r0, #0                      @ is resolved entry null?
2835    bne     .LOP_IPUT_SHORT_finish          @ no, already resolved
28368:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2837    EXPORT_PC()                         @ resolve() could throw
2838    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2839    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2840    cmp     r0, #0                      @ success?
2841    bne     .LOP_IPUT_SHORT_finish          @ yes, finish up
2842    b       common_exceptionThrown
2843
2844
2845/* ------------------------------ */
2846    .balign 64
2847.L_OP_SGET: /* 0x60 */
2848/* File: armv5te/OP_SGET.S */
2849    /*
2850     * General 32-bit SGET handler.
2851     *
2852     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2853     */
2854    /* op vAA, field@BBBB */
2855    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2856    FETCH(r1, 1)                        @ r1<- field ref BBBB
2857    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2858    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2859    cmp     r0, #0                      @ is resolved entry null?
2860    beq     .LOP_SGET_resolve         @ yes, do resolve
2861.LOP_SGET_finish: @ field ptr in r0
2862    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2863    mov     r2, rINST, lsr #8           @ r2<- AA
2864    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2865    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2866    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2867    GOTO_OPCODE(ip)                     @ jump to next instruction
2868
2869/* ------------------------------ */
2870    .balign 64
2871.L_OP_SGET_WIDE: /* 0x61 */
2872/* File: armv5te/OP_SGET_WIDE.S */
2873    /*
2874     * 64-bit SGET handler.
2875     */
2876    /* sget-wide vAA, field@BBBB */
2877    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2878    FETCH(r1, 1)                        @ r1<- field ref BBBB
2879    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2880    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2881    cmp     r0, #0                      @ is resolved entry null?
2882    beq     .LOP_SGET_WIDE_resolve         @ yes, do resolve
2883.LOP_SGET_WIDE_finish:
2884    mov     r1, rINST, lsr #8           @ r1<- AA
2885    ldrd    r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned)
2886    add     r1, rFP, r1, lsl #2         @ r1<- &fp[AA]
2887    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2888    stmia   r1, {r2-r3}                 @ vAA/vAA+1<- r2/r3
2889    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2890    GOTO_OPCODE(ip)                     @ jump to next instruction
2891
2892/* ------------------------------ */
2893    .balign 64
2894.L_OP_SGET_OBJECT: /* 0x62 */
2895/* File: armv5te/OP_SGET_OBJECT.S */
2896/* File: armv5te/OP_SGET.S */
2897    /*
2898     * General 32-bit SGET handler.
2899     *
2900     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2901     */
2902    /* op vAA, field@BBBB */
2903    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2904    FETCH(r1, 1)                        @ r1<- field ref BBBB
2905    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2906    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2907    cmp     r0, #0                      @ is resolved entry null?
2908    beq     .LOP_SGET_OBJECT_resolve         @ yes, do resolve
2909.LOP_SGET_OBJECT_finish: @ field ptr in r0
2910    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2911    mov     r2, rINST, lsr #8           @ r2<- AA
2912    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2913    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2914    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2915    GOTO_OPCODE(ip)                     @ jump to next instruction
2916
2917
2918/* ------------------------------ */
2919    .balign 64
2920.L_OP_SGET_BOOLEAN: /* 0x63 */
2921/* File: armv5te/OP_SGET_BOOLEAN.S */
2922/* File: armv5te/OP_SGET.S */
2923    /*
2924     * General 32-bit SGET handler.
2925     *
2926     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2927     */
2928    /* op vAA, field@BBBB */
2929    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2930    FETCH(r1, 1)                        @ r1<- field ref BBBB
2931    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2932    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2933    cmp     r0, #0                      @ is resolved entry null?
2934    beq     .LOP_SGET_BOOLEAN_resolve         @ yes, do resolve
2935.LOP_SGET_BOOLEAN_finish: @ field ptr in r0
2936    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2937    mov     r2, rINST, lsr #8           @ r2<- AA
2938    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2939    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2940    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2941    GOTO_OPCODE(ip)                     @ jump to next instruction
2942
2943
2944/* ------------------------------ */
2945    .balign 64
2946.L_OP_SGET_BYTE: /* 0x64 */
2947/* File: armv5te/OP_SGET_BYTE.S */
2948/* File: armv5te/OP_SGET.S */
2949    /*
2950     * General 32-bit SGET handler.
2951     *
2952     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2953     */
2954    /* op vAA, field@BBBB */
2955    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2956    FETCH(r1, 1)                        @ r1<- field ref BBBB
2957    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2958    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2959    cmp     r0, #0                      @ is resolved entry null?
2960    beq     .LOP_SGET_BYTE_resolve         @ yes, do resolve
2961.LOP_SGET_BYTE_finish: @ field ptr in r0
2962    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2963    mov     r2, rINST, lsr #8           @ r2<- AA
2964    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2965    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2966    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2967    GOTO_OPCODE(ip)                     @ jump to next instruction
2968
2969
2970/* ------------------------------ */
2971    .balign 64
2972.L_OP_SGET_CHAR: /* 0x65 */
2973/* File: armv5te/OP_SGET_CHAR.S */
2974/* File: armv5te/OP_SGET.S */
2975    /*
2976     * General 32-bit SGET handler.
2977     *
2978     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2979     */
2980    /* op vAA, field@BBBB */
2981    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2982    FETCH(r1, 1)                        @ r1<- field ref BBBB
2983    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2984    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2985    cmp     r0, #0                      @ is resolved entry null?
2986    beq     .LOP_SGET_CHAR_resolve         @ yes, do resolve
2987.LOP_SGET_CHAR_finish: @ field ptr in r0
2988    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2989    mov     r2, rINST, lsr #8           @ r2<- AA
2990    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2991    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2992    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2993    GOTO_OPCODE(ip)                     @ jump to next instruction
2994
2995
2996/* ------------------------------ */
2997    .balign 64
2998.L_OP_SGET_SHORT: /* 0x66 */
2999/* File: armv5te/OP_SGET_SHORT.S */
3000/* File: armv5te/OP_SGET.S */
3001    /*
3002     * General 32-bit SGET handler.
3003     *
3004     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
3005     */
3006    /* op vAA, field@BBBB */
3007    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3008    FETCH(r1, 1)                        @ r1<- field ref BBBB
3009    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3010    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3011    cmp     r0, #0                      @ is resolved entry null?
3012    beq     .LOP_SGET_SHORT_resolve         @ yes, do resolve
3013.LOP_SGET_SHORT_finish: @ field ptr in r0
3014    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
3015    mov     r2, rINST, lsr #8           @ r2<- AA
3016    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3017    SET_VREG(r1, r2)                    @ fp[AA]<- r1
3018    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3019    GOTO_OPCODE(ip)                     @ jump to next instruction
3020
3021
3022/* ------------------------------ */
3023    .balign 64
3024.L_OP_SPUT: /* 0x67 */
3025/* File: armv5te/OP_SPUT.S */
3026    /*
3027     * General 32-bit SPUT handler.
3028     *
3029     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3030     */
3031    /* op vAA, field@BBBB */
3032    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3033    FETCH(r1, 1)                        @ r1<- field ref BBBB
3034    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3035    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3036    cmp     r0, #0                      @ is resolved entry null?
3037    beq     .LOP_SPUT_resolve         @ yes, do resolve
3038.LOP_SPUT_finish:   @ field ptr in r0
3039    mov     r2, rINST, lsr #8           @ r2<- AA
3040    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3041    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3042    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3043    str     r1, [r0, #offStaticField_value] @ field<- vAA
3044    GOTO_OPCODE(ip)                     @ jump to next instruction
3045
3046/* ------------------------------ */
3047    .balign 64
3048.L_OP_SPUT_WIDE: /* 0x68 */
3049/* File: armv5te/OP_SPUT_WIDE.S */
3050    /*
3051     * 64-bit SPUT handler.
3052     */
3053    /* sput-wide vAA, field@BBBB */
3054    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3055    FETCH(r1, 1)                        @ r1<- field ref BBBB
3056    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3057    mov     r9, rINST, lsr #8           @ r9<- AA
3058    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3059    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
3060    cmp     r0, #0                      @ is resolved entry null?
3061    beq     .LOP_SPUT_WIDE_resolve         @ yes, do resolve
3062.LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9
3063    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3064    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
3065    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3066    strd    r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1
3067    GOTO_OPCODE(ip)                     @ jump to next instruction
3068
3069/* ------------------------------ */
3070    .balign 64
3071.L_OP_SPUT_OBJECT: /* 0x69 */
3072/* File: armv5te/OP_SPUT_OBJECT.S */
3073/* File: armv5te/OP_SPUT.S */
3074    /*
3075     * General 32-bit SPUT handler.
3076     *
3077     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3078     */
3079    /* op vAA, field@BBBB */
3080    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3081    FETCH(r1, 1)                        @ r1<- field ref BBBB
3082    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3083    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3084    cmp     r0, #0                      @ is resolved entry null?
3085    beq     .LOP_SPUT_OBJECT_resolve         @ yes, do resolve
3086.LOP_SPUT_OBJECT_finish:   @ field ptr in r0
3087    mov     r2, rINST, lsr #8           @ r2<- AA
3088    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3089    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3090    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3091    str     r1, [r0, #offStaticField_value] @ field<- vAA
3092    GOTO_OPCODE(ip)                     @ jump to next instruction
3093
3094
3095/* ------------------------------ */
3096    .balign 64
3097.L_OP_SPUT_BOOLEAN: /* 0x6a */
3098/* File: armv5te/OP_SPUT_BOOLEAN.S */
3099/* File: armv5te/OP_SPUT.S */
3100    /*
3101     * General 32-bit SPUT handler.
3102     *
3103     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3104     */
3105    /* op vAA, field@BBBB */
3106    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3107    FETCH(r1, 1)                        @ r1<- field ref BBBB
3108    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3109    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3110    cmp     r0, #0                      @ is resolved entry null?
3111    beq     .LOP_SPUT_BOOLEAN_resolve         @ yes, do resolve
3112.LOP_SPUT_BOOLEAN_finish:   @ field ptr in r0
3113    mov     r2, rINST, lsr #8           @ r2<- AA
3114    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3115    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3116    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3117    str     r1, [r0, #offStaticField_value] @ field<- vAA
3118    GOTO_OPCODE(ip)                     @ jump to next instruction
3119
3120
3121/* ------------------------------ */
3122    .balign 64
3123.L_OP_SPUT_BYTE: /* 0x6b */
3124/* File: armv5te/OP_SPUT_BYTE.S */
3125/* File: armv5te/OP_SPUT.S */
3126    /*
3127     * General 32-bit SPUT handler.
3128     *
3129     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3130     */
3131    /* op vAA, field@BBBB */
3132    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3133    FETCH(r1, 1)                        @ r1<- field ref BBBB
3134    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3135    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3136    cmp     r0, #0                      @ is resolved entry null?
3137    beq     .LOP_SPUT_BYTE_resolve         @ yes, do resolve
3138.LOP_SPUT_BYTE_finish:   @ field ptr in r0
3139    mov     r2, rINST, lsr #8           @ r2<- AA
3140    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3141    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3142    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3143    str     r1, [r0, #offStaticField_value] @ field<- vAA
3144    GOTO_OPCODE(ip)                     @ jump to next instruction
3145
3146
3147/* ------------------------------ */
3148    .balign 64
3149.L_OP_SPUT_CHAR: /* 0x6c */
3150/* File: armv5te/OP_SPUT_CHAR.S */
3151/* File: armv5te/OP_SPUT.S */
3152    /*
3153     * General 32-bit SPUT handler.
3154     *
3155     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3156     */
3157    /* op vAA, field@BBBB */
3158    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3159    FETCH(r1, 1)                        @ r1<- field ref BBBB
3160    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3161    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3162    cmp     r0, #0                      @ is resolved entry null?
3163    beq     .LOP_SPUT_CHAR_resolve         @ yes, do resolve
3164.LOP_SPUT_CHAR_finish:   @ field ptr in r0
3165    mov     r2, rINST, lsr #8           @ r2<- AA
3166    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3167    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3168    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3169    str     r1, [r0, #offStaticField_value] @ field<- vAA
3170    GOTO_OPCODE(ip)                     @ jump to next instruction
3171
3172
3173/* ------------------------------ */
3174    .balign 64
3175.L_OP_SPUT_SHORT: /* 0x6d */
3176/* File: armv5te/OP_SPUT_SHORT.S */
3177/* File: armv5te/OP_SPUT.S */
3178    /*
3179     * General 32-bit SPUT handler.
3180     *
3181     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3182     */
3183    /* op vAA, field@BBBB */
3184    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3185    FETCH(r1, 1)                        @ r1<- field ref BBBB
3186    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3187    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3188    cmp     r0, #0                      @ is resolved entry null?
3189    beq     .LOP_SPUT_SHORT_resolve         @ yes, do resolve
3190.LOP_SPUT_SHORT_finish:   @ field ptr in r0
3191    mov     r2, rINST, lsr #8           @ r2<- AA
3192    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3193    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3194    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3195    str     r1, [r0, #offStaticField_value] @ field<- vAA
3196    GOTO_OPCODE(ip)                     @ jump to next instruction
3197
3198
3199/* ------------------------------ */
3200    .balign 64
3201.L_OP_INVOKE_VIRTUAL: /* 0x6e */
3202/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3203    /*
3204     * Handle a virtual method call.
3205     *
3206     * for: invoke-virtual, invoke-virtual/range
3207     */
3208    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3209    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3210    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3211    FETCH(r1, 1)                        @ r1<- BBBB
3212    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3213    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3214    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3215    .if     (!0)
3216    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3217    .endif
3218    cmp     r0, #0                      @ already resolved?
3219    EXPORT_PC()                         @ must export for invoke
3220    bne     .LOP_INVOKE_VIRTUAL_continue        @ yes, continue on
3221    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3222    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3223    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3224    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3225    cmp     r0, #0                      @ got null?
3226    bne     .LOP_INVOKE_VIRTUAL_continue        @ no, continue
3227    b       common_exceptionThrown      @ yes, handle exception
3228
3229/* ------------------------------ */
3230    .balign 64
3231.L_OP_INVOKE_SUPER: /* 0x6f */
3232/* File: armv5te/OP_INVOKE_SUPER.S */
3233    /*
3234     * Handle a "super" method call.
3235     *
3236     * for: invoke-super, invoke-super/range
3237     */
3238    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3239    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3240    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3241    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3242    .if     (!0)
3243    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3244    .endif
3245    FETCH(r1, 1)                        @ r1<- BBBB
3246    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3247    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3248    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3249    cmp     r2, #0                      @ null "this"?
3250    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3251    beq     common_errNullObject        @ null "this", throw exception
3252    cmp     r0, #0                      @ already resolved?
3253    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3254    EXPORT_PC()                         @ must export for invoke
3255    bne     .LOP_INVOKE_SUPER_continue        @ resolved, continue on
3256    b       .LOP_INVOKE_SUPER_resolve         @ do resolve now
3257
3258/* ------------------------------ */
3259    .balign 64
3260.L_OP_INVOKE_DIRECT: /* 0x70 */
3261/* File: armv5te/OP_INVOKE_DIRECT.S */
3262    /*
3263     * Handle a direct method call.
3264     *
3265     * (We could defer the "is 'this' pointer null" test to the common
3266     * method invocation code, and use a flag to indicate that static
3267     * calls don't count.  If we do this as part of copying the arguments
3268     * out we could avoiding loading the first arg twice.)
3269     *
3270     * for: invoke-direct, invoke-direct/range
3271     */
3272    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3273    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3274    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3275    FETCH(r1, 1)                        @ r1<- BBBB
3276    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3277    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3278    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3279    .if     (!0)
3280    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3281    .endif
3282    cmp     r0, #0                      @ already resolved?
3283    EXPORT_PC()                         @ must export for invoke
3284    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3285    beq     .LOP_INVOKE_DIRECT_resolve         @ not resolved, do it now
3286.LOP_INVOKE_DIRECT_finish:
3287    cmp     r2, #0                      @ null "this" ref?
3288    bne     common_invokeMethodNoRange   @ no, continue on
3289    b       common_errNullObject        @ yes, throw exception
3290
3291/* ------------------------------ */
3292    .balign 64
3293.L_OP_INVOKE_STATIC: /* 0x71 */
3294/* File: armv5te/OP_INVOKE_STATIC.S */
3295    /*
3296     * Handle a static method call.
3297     *
3298     * for: invoke-static, invoke-static/range
3299     */
3300    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3301    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3302    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3303    FETCH(r1, 1)                        @ r1<- BBBB
3304    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3305    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3306    cmp     r0, #0                      @ already resolved?
3307    EXPORT_PC()                         @ must export for invoke
3308    bne     common_invokeMethodNoRange @ yes, continue on
33090:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3310    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3311    mov     r2, #METHOD_STATIC          @ resolver method type
3312    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3313    cmp     r0, #0                      @ got null?
3314    bne     common_invokeMethodNoRange @ no, continue
3315    b       common_exceptionThrown      @ yes, handle exception
3316
3317
3318/* ------------------------------ */
3319    .balign 64
3320.L_OP_INVOKE_INTERFACE: /* 0x72 */
3321/* File: armv5te/OP_INVOKE_INTERFACE.S */
3322    /*
3323     * Handle an interface method call.
3324     *
3325     * for: invoke-interface, invoke-interface/range
3326     */
3327    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3328    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3329    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3330    FETCH(r1, 1)                        @ r1<- BBBB
3331    .if     (!0)
3332    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3333    .endif
3334    EXPORT_PC()                         @ must export for invoke
3335    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3336    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3337    cmp     r0, #0                      @ null obj?
3338    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3339    beq     common_errNullObject        @ yes, fail
3340    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3341    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3342    cmp     r0, #0                      @ failed?
3343    beq     common_exceptionThrown      @ yes, handle exception
3344    b       common_invokeMethodNoRange @ jump to common handler
3345
3346
3347/* ------------------------------ */
3348    .balign 64
3349.L_OP_UNUSED_73: /* 0x73 */
3350/* File: armv5te/OP_UNUSED_73.S */
3351/* File: armv5te/unused.S */
3352    bl      common_abort
3353
3354
3355
3356/* ------------------------------ */
3357    .balign 64
3358.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
3359/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */
3360/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3361    /*
3362     * Handle a virtual method call.
3363     *
3364     * for: invoke-virtual, invoke-virtual/range
3365     */
3366    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3367    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3368    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3369    FETCH(r1, 1)                        @ r1<- BBBB
3370    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3371    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3372    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3373    .if     (!1)
3374    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3375    .endif
3376    cmp     r0, #0                      @ already resolved?
3377    EXPORT_PC()                         @ must export for invoke
3378    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ yes, continue on
3379    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3380    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3381    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3382    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3383    cmp     r0, #0                      @ got null?
3384    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ no, continue
3385    b       common_exceptionThrown      @ yes, handle exception
3386
3387
3388/* ------------------------------ */
3389    .balign 64
3390.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
3391/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */
3392/* File: armv5te/OP_INVOKE_SUPER.S */
3393    /*
3394     * Handle a "super" method call.
3395     *
3396     * for: invoke-super, invoke-super/range
3397     */
3398    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3399    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3400    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3401    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3402    .if     (!1)
3403    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3404    .endif
3405    FETCH(r1, 1)                        @ r1<- BBBB
3406    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3407    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3408    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3409    cmp     r2, #0                      @ null "this"?
3410    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3411    beq     common_errNullObject        @ null "this", throw exception
3412    cmp     r0, #0                      @ already resolved?
3413    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3414    EXPORT_PC()                         @ must export for invoke
3415    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ resolved, continue on
3416    b       .LOP_INVOKE_SUPER_RANGE_resolve         @ do resolve now
3417
3418
3419/* ------------------------------ */
3420    .balign 64
3421.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
3422/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */
3423/* File: armv5te/OP_INVOKE_DIRECT.S */
3424    /*
3425     * Handle a direct method call.
3426     *
3427     * (We could defer the "is 'this' pointer null" test to the common
3428     * method invocation code, and use a flag to indicate that static
3429     * calls don't count.  If we do this as part of copying the arguments
3430     * out we could avoiding loading the first arg twice.)
3431     *
3432     * for: invoke-direct, invoke-direct/range
3433     */
3434    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3435    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3436    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3437    FETCH(r1, 1)                        @ r1<- BBBB
3438    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3439    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3440    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3441    .if     (!1)
3442    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3443    .endif
3444    cmp     r0, #0                      @ already resolved?
3445    EXPORT_PC()                         @ must export for invoke
3446    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3447    beq     .LOP_INVOKE_DIRECT_RANGE_resolve         @ not resolved, do it now
3448.LOP_INVOKE_DIRECT_RANGE_finish:
3449    cmp     r2, #0                      @ null "this" ref?
3450    bne     common_invokeMethodRange   @ no, continue on
3451    b       common_errNullObject        @ yes, throw exception
3452
3453
3454/* ------------------------------ */
3455    .balign 64
3456.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
3457/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */
3458/* File: armv5te/OP_INVOKE_STATIC.S */
3459    /*
3460     * Handle a static method call.
3461     *
3462     * for: invoke-static, invoke-static/range
3463     */
3464    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3465    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3466    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3467    FETCH(r1, 1)                        @ r1<- BBBB
3468    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3469    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3470    cmp     r0, #0                      @ already resolved?
3471    EXPORT_PC()                         @ must export for invoke
3472    bne     common_invokeMethodRange @ yes, continue on
34730:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3474    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3475    mov     r2, #METHOD_STATIC          @ resolver method type
3476    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3477    cmp     r0, #0                      @ got null?
3478    bne     common_invokeMethodRange @ no, continue
3479    b       common_exceptionThrown      @ yes, handle exception
3480
3481
3482
3483/* ------------------------------ */
3484    .balign 64
3485.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
3486/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */
3487/* File: armv5te/OP_INVOKE_INTERFACE.S */
3488    /*
3489     * Handle an interface method call.
3490     *
3491     * for: invoke-interface, invoke-interface/range
3492     */
3493    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3494    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3495    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3496    FETCH(r1, 1)                        @ r1<- BBBB
3497    .if     (!1)
3498    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3499    .endif
3500    EXPORT_PC()                         @ must export for invoke
3501    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3502    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3503    cmp     r0, #0                      @ null obj?
3504    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3505    beq     common_errNullObject        @ yes, fail
3506    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3507    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3508    cmp     r0, #0                      @ failed?
3509    beq     common_exceptionThrown      @ yes, handle exception
3510    b       common_invokeMethodRange @ jump to common handler
3511
3512
3513
3514/* ------------------------------ */
3515    .balign 64
3516.L_OP_UNUSED_79: /* 0x79 */
3517/* File: armv5te/OP_UNUSED_79.S */
3518/* File: armv5te/unused.S */
3519    bl      common_abort
3520
3521
3522
3523/* ------------------------------ */
3524    .balign 64
3525.L_OP_UNUSED_7A: /* 0x7a */
3526/* File: armv5te/OP_UNUSED_7A.S */
3527/* File: armv5te/unused.S */
3528    bl      common_abort
3529
3530
3531
3532/* ------------------------------ */
3533    .balign 64
3534.L_OP_NEG_INT: /* 0x7b */
3535/* File: armv5te/OP_NEG_INT.S */
3536/* File: armv5te/unop.S */
3537    /*
3538     * Generic 32-bit unary operation.  Provide an "instr" line that
3539     * specifies an instruction that performs "result = op r0".
3540     * This could be an ARM instruction or a function call.
3541     *
3542     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3543     *      int-to-byte, int-to-char, int-to-short
3544     */
3545    /* unop vA, vB */
3546    mov     r3, rINST, lsr #12          @ r3<- B
3547    mov     r9, rINST, lsr #8           @ r9<- A+
3548    GET_VREG(r0, r3)                    @ r0<- vB
3549    and     r9, r9, #15
3550                               @ optional op; may set condition codes
3551    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3552    rsb     r0, r0, #0                              @ r0<- op, r0-r3 changed
3553    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3554    SET_VREG(r0, r9)                    @ vAA<- r0
3555    GOTO_OPCODE(ip)                     @ jump to next instruction
3556    /* 9-10 instructions */
3557
3558
3559/* ------------------------------ */
3560    .balign 64
3561.L_OP_NOT_INT: /* 0x7c */
3562/* File: armv5te/OP_NOT_INT.S */
3563/* File: armv5te/unop.S */
3564    /*
3565     * Generic 32-bit unary operation.  Provide an "instr" line that
3566     * specifies an instruction that performs "result = op r0".
3567     * This could be an ARM instruction or a function call.
3568     *
3569     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3570     *      int-to-byte, int-to-char, int-to-short
3571     */
3572    /* unop vA, vB */
3573    mov     r3, rINST, lsr #12          @ r3<- B
3574    mov     r9, rINST, lsr #8           @ r9<- A+
3575    GET_VREG(r0, r3)                    @ r0<- vB
3576    and     r9, r9, #15
3577                               @ optional op; may set condition codes
3578    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3579    mvn     r0, r0                              @ r0<- op, r0-r3 changed
3580    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3581    SET_VREG(r0, r9)                    @ vAA<- r0
3582    GOTO_OPCODE(ip)                     @ jump to next instruction
3583    /* 9-10 instructions */
3584
3585
3586/* ------------------------------ */
3587    .balign 64
3588.L_OP_NEG_LONG: /* 0x7d */
3589/* File: armv5te/OP_NEG_LONG.S */
3590/* File: armv5te/unopWide.S */
3591    /*
3592     * Generic 64-bit unary operation.  Provide an "instr" line that
3593     * specifies an instruction that performs "result = op r0/r1".
3594     * This could be an ARM instruction or a function call.
3595     *
3596     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3597     */
3598    /* unop vA, vB */
3599    mov     r9, rINST, lsr #8           @ r9<- A+
3600    mov     r3, rINST, lsr #12          @ r3<- B
3601    and     r9, r9, #15
3602    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3603    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3604    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3605    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3606    rsbs    r0, r0, #0                           @ optional op; may set condition codes
3607    rsc     r1, r1, #0                              @ r0/r1<- op, r2-r3 changed
3608    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3609    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3610    GOTO_OPCODE(ip)                     @ jump to next instruction
3611    /* 12-13 instructions */
3612
3613
3614
3615/* ------------------------------ */
3616    .balign 64
3617.L_OP_NOT_LONG: /* 0x7e */
3618/* File: armv5te/OP_NOT_LONG.S */
3619/* File: armv5te/unopWide.S */
3620    /*
3621     * Generic 64-bit unary operation.  Provide an "instr" line that
3622     * specifies an instruction that performs "result = op r0/r1".
3623     * This could be an ARM instruction or a function call.
3624     *
3625     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3626     */
3627    /* unop vA, vB */
3628    mov     r9, rINST, lsr #8           @ r9<- A+
3629    mov     r3, rINST, lsr #12          @ r3<- B
3630    and     r9, r9, #15
3631    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3632    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3633    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3634    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3635    mvn     r0, r0                           @ optional op; may set condition codes
3636    mvn     r1, r1                              @ r0/r1<- op, r2-r3 changed
3637    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3638    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3639    GOTO_OPCODE(ip)                     @ jump to next instruction
3640    /* 12-13 instructions */
3641
3642
3643
3644/* ------------------------------ */
3645    .balign 64
3646.L_OP_NEG_FLOAT: /* 0x7f */
3647/* File: armv5te/OP_NEG_FLOAT.S */
3648/* File: armv5te/unop.S */
3649    /*
3650     * Generic 32-bit unary operation.  Provide an "instr" line that
3651     * specifies an instruction that performs "result = op r0".
3652     * This could be an ARM instruction or a function call.
3653     *
3654     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3655     *      int-to-byte, int-to-char, int-to-short
3656     */
3657    /* unop vA, vB */
3658    mov     r3, rINST, lsr #12          @ r3<- B
3659    mov     r9, rINST, lsr #8           @ r9<- A+
3660    GET_VREG(r0, r3)                    @ r0<- vB
3661    and     r9, r9, #15
3662                               @ optional op; may set condition codes
3663    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3664    add     r0, r0, #0x80000000                              @ r0<- op, r0-r3 changed
3665    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3666    SET_VREG(r0, r9)                    @ vAA<- r0
3667    GOTO_OPCODE(ip)                     @ jump to next instruction
3668    /* 9-10 instructions */
3669
3670
3671/* ------------------------------ */
3672    .balign 64
3673.L_OP_NEG_DOUBLE: /* 0x80 */
3674/* File: armv5te/OP_NEG_DOUBLE.S */
3675/* File: armv5te/unopWide.S */
3676    /*
3677     * Generic 64-bit unary operation.  Provide an "instr" line that
3678     * specifies an instruction that performs "result = op r0/r1".
3679     * This could be an ARM instruction or a function call.
3680     *
3681     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3682     */
3683    /* unop vA, vB */
3684    mov     r9, rINST, lsr #8           @ r9<- A+
3685    mov     r3, rINST, lsr #12          @ r3<- B
3686    and     r9, r9, #15
3687    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3688    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3689    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3690    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3691                               @ optional op; may set condition codes
3692    add     r1, r1, #0x80000000                              @ r0/r1<- op, r2-r3 changed
3693    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3694    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3695    GOTO_OPCODE(ip)                     @ jump to next instruction
3696    /* 12-13 instructions */
3697
3698
3699
3700/* ------------------------------ */
3701    .balign 64
3702.L_OP_INT_TO_LONG: /* 0x81 */
3703/* File: armv5te/OP_INT_TO_LONG.S */
3704/* File: armv5te/unopWider.S */
3705    /*
3706     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3707     * that specifies an instruction that performs "result = op r0", where
3708     * "result" is a 64-bit quantity in r0/r1.
3709     *
3710     * For: int-to-long, int-to-double, float-to-long, float-to-double
3711     */
3712    /* unop vA, vB */
3713    mov     r9, rINST, lsr #8           @ r9<- A+
3714    mov     r3, rINST, lsr #12          @ r3<- B
3715    and     r9, r9, #15
3716    GET_VREG(r0, r3)                    @ r0<- vB
3717    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3718                               @ optional op; may set condition codes
3719    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3720    mov     r1, r0, asr #31                              @ r0<- op, r0-r3 changed
3721    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3722    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3723    GOTO_OPCODE(ip)                     @ jump to next instruction
3724    /* 10-11 instructions */
3725
3726
3727/* ------------------------------ */
3728    .balign 64
3729.L_OP_INT_TO_FLOAT: /* 0x82 */
3730/* File: armv5te/OP_INT_TO_FLOAT.S */
3731/* File: armv5te/unop.S */
3732    /*
3733     * Generic 32-bit unary operation.  Provide an "instr" line that
3734     * specifies an instruction that performs "result = op r0".
3735     * This could be an ARM instruction or a function call.
3736     *
3737     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3738     *      int-to-byte, int-to-char, int-to-short
3739     */
3740    /* unop vA, vB */
3741    mov     r3, rINST, lsr #12          @ r3<- B
3742    mov     r9, rINST, lsr #8           @ r9<- A+
3743    GET_VREG(r0, r3)                    @ r0<- vB
3744    and     r9, r9, #15
3745                               @ optional op; may set condition codes
3746    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3747    bl      __aeabi_i2f                              @ r0<- op, r0-r3 changed
3748    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3749    SET_VREG(r0, r9)                    @ vAA<- r0
3750    GOTO_OPCODE(ip)                     @ jump to next instruction
3751    /* 9-10 instructions */
3752
3753
3754/* ------------------------------ */
3755    .balign 64
3756.L_OP_INT_TO_DOUBLE: /* 0x83 */
3757/* File: armv5te/OP_INT_TO_DOUBLE.S */
3758/* File: armv5te/unopWider.S */
3759    /*
3760     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3761     * that specifies an instruction that performs "result = op r0", where
3762     * "result" is a 64-bit quantity in r0/r1.
3763     *
3764     * For: int-to-long, int-to-double, float-to-long, float-to-double
3765     */
3766    /* unop vA, vB */
3767    mov     r9, rINST, lsr #8           @ r9<- A+
3768    mov     r3, rINST, lsr #12          @ r3<- B
3769    and     r9, r9, #15
3770    GET_VREG(r0, r3)                    @ r0<- vB
3771    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3772                               @ optional op; may set condition codes
3773    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3774    bl      __aeabi_i2d                              @ r0<- op, r0-r3 changed
3775    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3776    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3777    GOTO_OPCODE(ip)                     @ jump to next instruction
3778    /* 10-11 instructions */
3779
3780
3781/* ------------------------------ */
3782    .balign 64
3783.L_OP_LONG_TO_INT: /* 0x84 */
3784/* File: armv5te/OP_LONG_TO_INT.S */
3785/* we ignore the high word, making this equivalent to a 32-bit reg move */
3786/* File: armv5te/OP_MOVE.S */
3787    /* for move, move-object, long-to-int */
3788    /* op vA, vB */
3789    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
3790    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
3791    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3792    GET_VREG(r2, r1)                    @ r2<- fp[B]
3793    and     r0, r0, #15
3794    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
3795    SET_VREG(r2, r0)                    @ fp[A]<- r2
3796    GOTO_OPCODE(ip)                     @ execute next instruction
3797
3798
3799
3800/* ------------------------------ */
3801    .balign 64
3802.L_OP_LONG_TO_FLOAT: /* 0x85 */
3803/* File: armv5te/OP_LONG_TO_FLOAT.S */
3804/* File: armv5te/unopNarrower.S */
3805    /*
3806     * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
3807     * that specifies an instruction that performs "result = op r0/r1", where
3808     * "result" is a 32-bit quantity in r0.
3809     *
3810     * For: long-to-float, double-to-int, double-to-float
3811     *
3812     * (This would work for long-to-int, but that instruction is actually
3813     * an exact match for OP_MOVE.)
3814     */
3815    /* unop vA, vB */
3816    mov     r3, rINST, lsr #12          @ r3<- B
3817    mov     r9, rINST, lsr #8           @ r9<- A+
3818    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3819    and     r9, r9, #15
3820    ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
3821    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3822                               @ optional op; may set condition codes
3823    bl      __aeabi_l2f                              @ r0<- op, r0-r3 changed
3824    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3825    SET_VREG(r0, r9)                    @ vA<- r0
3826    GOTO_OPCODE(ip)                     @ jump to next instruction
3827    /* 10-11 instructions */
3828
3829
3830/* ------------------------------ */
3831    .balign 64
3832.L_OP_LONG_TO_DOUBLE: /* 0x86 */
3833/* File: armv5te/OP_LONG_TO_DOUBLE.S */
3834/* File: armv5te/unopWide.S */
3835    /*
3836     * Generic 64-bit unary operation.  Provide an "instr" line that
3837     * specifies an instruction that performs "result = op r0/r1".
3838     * This could be an ARM instruction or a function call.
3839     *
3840     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3841     */
3842    /* unop vA, vB */
3843    mov     r9, rINST, lsr #8           @ r9<- A+
3844    mov     r3, rINST, lsr #12          @ r3<- B
3845    and     r9, r9, #15
3846    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3847    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3848    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3849    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3850                               @ optional op; may set condition codes
3851    bl      __aeabi_l2d                              @ r0/r1<- op, r2-r3 changed
3852    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3853    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3854    GOTO_OPCODE(ip)                     @ jump to next instruction
3855    /* 12-13 instructions */
3856
3857
3858
3859/* ------------------------------ */
3860    .balign 64
3861.L_OP_FLOAT_TO_INT: /* 0x87 */
3862/* File: armv5te/OP_FLOAT_TO_INT.S */
3863/* EABI appears to have Java-style conversions of +inf/-inf/NaN */
3864/* File: armv5te/unop.S */
3865    /*
3866     * Generic 32-bit unary operation.  Provide an "instr" line that
3867     * specifies an instruction that performs "result = op r0".
3868     * This could be an ARM instruction or a function call.
3869     *
3870     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3871     *      int-to-byte, int-to-char, int-to-short
3872     */
3873    /* unop vA, vB */
3874    mov     r3, rINST, lsr #12          @ r3<- B
3875    mov     r9, rINST, lsr #8           @ r9<- A+
3876    GET_VREG(r0, r3)                    @ r0<- vB
3877    and     r9, r9, #15
3878                               @ optional op; may set condition codes
3879    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3880    bl      __aeabi_f2iz                              @ r0<- op, r0-r3 changed
3881    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3882    SET_VREG(r0, r9)                    @ vAA<- r0
3883    GOTO_OPCODE(ip)                     @ jump to next instruction
3884    /* 9-10 instructions */
3885
3886
3887#if 0
3888@include "armv5te/unop.S" {"instr":"bl      f2i_doconv"}
3889@break
3890/*
3891 * Convert the float in r0 to an int in r0.
3892 *
3893 * We have to clip values to int min/max per the specification.  The
3894 * expected common case is a "reasonable" value that converts directly
3895 * to modest integer.  The EABI convert function isn't doing this for us.
3896 */
3897f2i_doconv:
3898    stmfd   sp!, {r4, lr}
3899    mov     r1, #0x4f000000             @ (float)maxint
3900    mov     r4, r0
3901    bl      __aeabi_fcmpge              @ is arg >= maxint?
3902    cmp     r0, #0                      @ nonzero == yes
3903    mvnne   r0, #0x80000000             @ return maxint (7fffffff)
3904    ldmnefd sp!, {r4, pc}
3905
3906    mov     r0, r4                      @ recover arg
3907    mov     r1, #0xcf000000             @ (float)minint
3908    bl      __aeabi_fcmple              @ is arg <= minint?
3909    cmp     r0, #0                      @ nonzero == yes
3910    movne   r0, #0x80000000             @ return minint (80000000)
3911    ldmnefd sp!, {r4, pc}
3912
3913    mov     r0, r4                      @ recover arg
3914    mov     r1, r4
3915    bl      __aeabi_fcmpeq              @ is arg == self?
3916    cmp     r0, #0                      @ zero == no
3917    ldmeqfd sp!, {r4, pc}               @ return zero for NaN
3918
3919    mov     r0, r4                      @ recover arg
3920    bl      __aeabi_f2iz                @ convert float to int
3921    ldmfd   sp!, {r4, pc}
3922#endif
3923
3924
3925/* ------------------------------ */
3926    .balign 64
3927.L_OP_FLOAT_TO_LONG: /* 0x88 */
3928/* File: armv5te/OP_FLOAT_TO_LONG.S */
3929@include "armv5te/unopWider.S" {"instr":"bl      __aeabi_f2lz"}
3930/* File: armv5te/unopWider.S */
3931    /*
3932     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3933     * that specifies an instruction that performs "result = op r0", where
3934     * "result" is a 64-bit quantity in r0/r1.
3935     *
3936     * For: int-to-long, int-to-double, float-to-long, float-to-double
3937     */
3938    /* unop vA, vB */
3939    mov     r9, rINST, lsr #8           @ r9<- A+
3940    mov     r3, rINST, lsr #12          @ r3<- B
3941    and     r9, r9, #15
3942    GET_VREG(r0, r3)                    @ r0<- vB
3943    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3944                               @ optional op; may set condition codes
3945    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3946    bl      f2l_doconv                              @ r0<- op, r0-r3 changed
3947    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3948    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3949    GOTO_OPCODE(ip)                     @ jump to next instruction
3950    /* 10-11 instructions */
3951
3952
3953
3954/* ------------------------------ */
3955    .balign 64
3956.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
3957/* File: armv5te/OP_FLOAT_TO_DOUBLE.S */
3958/* File: armv5te/unopWider.S */
3959    /*
3960     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3961     * that specifies an instruction that performs "result = op r0", where
3962     * "result" is a 64-bit quantity in r0/r1.
3963     *
3964     * For: int-to-long, int-to-double, float-to-long, float-to-double
3965     */
3966    /* unop vA, vB */
3967    mov     r9, rINST, lsr #8           @ r9<- A+
3968    mov     r3, rINST, lsr #12          @ r3<- B
3969    and     r9, r9, #15
3970    GET_VREG(r0, r3)                    @ r0<- vB
3971    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3972                               @ optional op; may set condition codes
3973    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3974    bl      __aeabi_f2d                              @ r0<- op, r0-r3 changed
3975    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3976    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3977    GOTO_OPCODE(ip)                     @ jump to next instruction
3978    /* 10-11 instructions */
3979
3980
3981/* ------------------------------ */
3982    .balign 64
3983.L_OP_DOUBLE_TO_INT: /* 0x8a */
3984/* File: armv5te/OP_DOUBLE_TO_INT.S */
3985/* EABI appears to have Java-style conversions of +inf/-inf/NaN */
3986/* File: armv5te/unopNarrower.S */
3987    /*
3988     * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
3989     * that specifies an instruction that performs "result = op r0/r1", where
3990     * "result" is a 32-bit quantity in r0.
3991     *
3992     * For: long-to-float, double-to-int, double-to-float
3993     *
3994     * (This would work for long-to-int, but that instruction is actually
3995     * an exact match for OP_MOVE.)
3996     */
3997    /* unop vA, vB */
3998    mov     r3, rINST, lsr #12          @ r3<- B
3999    mov     r9, rINST, lsr #8           @ r9<- A+
4000    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
4001    and     r9, r9, #15
4002    ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
4003    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4004                               @ optional op; may set condition codes
4005    bl      __aeabi_d2iz                              @ r0<- op, r0-r3 changed
4006    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4007    SET_VREG(r0, r9)                    @ vA<- r0
4008    GOTO_OPCODE(ip)                     @ jump to next instruction
4009    /* 10-11 instructions */
4010
4011
4012#if 0
4013@include "armv5te/unopNarrower.S" {"instr":"bl      d2i_doconv"}
4014@break
4015/*
4016 * Convert the double in r0/r1 to an int in r0.
4017 *
4018 * We have to clip values to int min/max per the specification.  The
4019 * expected common case is a "reasonable" value that converts directly
4020 * to modest integer.  The EABI convert function isn't doing this for us.
4021 */
4022d2i_doconv:
4023    stmfd   sp!, {r4, r5, lr}           @ save regs
4024    ldr     r2, .LOP_DOUBLE_TO_INT_maxlo       @ (double)maxint, lo
4025    ldr     r3, .LOP_DOUBLE_TO_INT_maxhi       @ (double)maxint, hi
4026    sub     sp, sp, #4                  @ align for EABI
4027    mov     r4, r0                      @ save r0
4028    mov     r5, r1                      @  and r1
4029    bl      __aeabi_dcmpge              @ is arg >= maxint?
4030    cmp     r0, #0                      @ nonzero == yes
4031    mvnne   r0, #0x80000000             @ return maxint (7fffffff)
4032    bne     1f
4033
4034    mov     r0, r4                      @ recover arg
4035    mov     r1, r5
4036    ldr     r3, .LOP_DOUBLE_TO_INT_min         @ (double)minint, hi
4037    mov     r2, #0                      @ (double)minint, lo
4038    bl      __aeabi_dcmple              @ is arg <= minint?
4039    cmp     r0, #0                      @ nonzero == yes
4040    movne   r0, #0x80000000             @ return minint (80000000)
4041    bne     1f
4042
4043    mov     r0, r4                      @ recover arg
4044    mov     r1, r5
4045    mov     r2, r4                      @ compare against self
4046    mov     r3, r5
4047    bl      __aeabi_dcmpeq              @ is arg == self?
4048    cmp     r0, #0                      @ zero == no
4049    beq     1f                          @ return zero for NaN
4050
4051    mov     r0, r4                      @ recover arg
4052    mov     r1, r5
4053    bl      __aeabi_d2iz                @ convert double to int
4054
40551:
4056    add     sp, sp, #4
4057    ldmfd   sp!, {r4, r5, pc}
4058
4059.LOP_DOUBLE_TO_INT_maxlo:
4060    .word   0xffc00000                  @ maxint, as a double (low word)
4061.LOP_DOUBLE_TO_INT_maxhi:
4062    .word   0x41dfffff                  @ maxint, as a double (high word)
4063.LOP_DOUBLE_TO_INT_min:
4064    .word   0xc1e00000                  @ minint, as a double (high word)
4065#endif
4066
4067
4068/* ------------------------------ */
4069    .balign 64
4070.L_OP_DOUBLE_TO_LONG: /* 0x8b */
4071/* File: armv5te/OP_DOUBLE_TO_LONG.S */
4072@include "armv5te/unopWide.S" {"instr":"bl      __aeabi_d2lz"}
4073/* File: armv5te/unopWide.S */
4074    /*
4075     * Generic 64-bit unary operation.  Provide an "instr" line that
4076     * specifies an instruction that performs "result = op r0/r1".
4077     * This could be an ARM instruction or a function call.
4078     *
4079     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
4080     */
4081    /* unop vA, vB */
4082    mov     r9, rINST, lsr #8           @ r9<- A+
4083    mov     r3, rINST, lsr #12          @ r3<- B
4084    and     r9, r9, #15
4085    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
4086    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
4087    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
4088    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4089                               @ optional op; may set condition codes
4090    bl      d2l_doconv                              @ r0/r1<- op, r2-r3 changed
4091    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4092    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
4093    GOTO_OPCODE(ip)                     @ jump to next instruction
4094    /* 12-13 instructions */
4095
4096
4097
4098
4099/* ------------------------------ */
4100    .balign 64
4101.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
4102/* File: armv5te/OP_DOUBLE_TO_FLOAT.S */
4103/* File: armv5te/unopNarrower.S */
4104    /*
4105     * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
4106     * that specifies an instruction that performs "result = op r0/r1", where
4107     * "result" is a 32-bit quantity in r0.
4108     *
4109     * For: long-to-float, double-to-int, double-to-float
4110     *
4111     * (This would work for long-to-int, but that instruction is actually
4112     * an exact match for OP_MOVE.)
4113     */
4114    /* unop vA, vB */
4115    mov     r3, rINST, lsr #12          @ r3<- B
4116    mov     r9, rINST, lsr #8           @ r9<- A+
4117    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
4118    and     r9, r9, #15
4119    ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
4120    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4121                               @ optional op; may set condition codes
4122    bl      __aeabi_d2f                              @ r0<- op, r0-r3 changed
4123    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4124    SET_VREG(r0, r9)                    @ vA<- r0
4125    GOTO_OPCODE(ip)                     @ jump to next instruction
4126    /* 10-11 instructions */
4127
4128
4129/* ------------------------------ */
4130    .balign 64
4131.L_OP_INT_TO_BYTE: /* 0x8d */
4132/* File: armv5te/OP_INT_TO_BYTE.S */
4133/* File: armv5te/unop.S */
4134    /*
4135     * Generic 32-bit unary operation.  Provide an "instr" line that
4136     * specifies an instruction that performs "result = op r0".
4137     * This could be an ARM instruction or a function call.
4138     *
4139     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4140     *      int-to-byte, int-to-char, int-to-short
4141     */
4142    /* unop vA, vB */
4143    mov     r3, rINST, lsr #12          @ r3<- B
4144    mov     r9, rINST, lsr #8           @ r9<- A+
4145    GET_VREG(r0, r3)                    @ r0<- vB
4146    and     r9, r9, #15
4147    mov     r0, r0, asl #24                           @ optional op; may set condition codes
4148    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4149    mov     r0, r0, asr #24                              @ r0<- op, r0-r3 changed
4150    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4151    SET_VREG(r0, r9)                    @ vAA<- r0
4152    GOTO_OPCODE(ip)                     @ jump to next instruction
4153    /* 9-10 instructions */
4154
4155
4156/* ------------------------------ */
4157    .balign 64
4158.L_OP_INT_TO_CHAR: /* 0x8e */
4159/* File: armv5te/OP_INT_TO_CHAR.S */
4160/* File: armv5te/unop.S */
4161    /*
4162     * Generic 32-bit unary operation.  Provide an "instr" line that
4163     * specifies an instruction that performs "result = op r0".
4164     * This could be an ARM instruction or a function call.
4165     *
4166     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4167     *      int-to-byte, int-to-char, int-to-short
4168     */
4169    /* unop vA, vB */
4170    mov     r3, rINST, lsr #12          @ r3<- B
4171    mov     r9, rINST, lsr #8           @ r9<- A+
4172    GET_VREG(r0, r3)                    @ r0<- vB
4173    and     r9, r9, #15
4174    mov     r0, r0, asl #16                           @ optional op; may set condition codes
4175    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4176    mov     r0, r0, lsr #16                              @ 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    /* 9-10 instructions */
4181
4182
4183/* ------------------------------ */
4184    .balign 64
4185.L_OP_INT_TO_SHORT: /* 0x8f */
4186/* File: armv5te/OP_INT_TO_SHORT.S */
4187/* File: armv5te/unop.S */
4188    /*
4189     * Generic 32-bit unary operation.  Provide an "instr" line that
4190     * specifies an instruction that performs "result = op r0".
4191     * This could be an ARM instruction or a function call.
4192     *
4193     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4194     *      int-to-byte, int-to-char, int-to-short
4195     */
4196    /* unop vA, vB */
4197    mov     r3, rINST, lsr #12          @ r3<- B
4198    mov     r9, rINST, lsr #8           @ r9<- A+
4199    GET_VREG(r0, r3)                    @ r0<- vB
4200    and     r9, r9, #15
4201    mov     r0, r0, asl #16                           @ optional op; may set condition codes
4202    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4203    mov     r0, r0, asr #16                              @ r0<- op, r0-r3 changed
4204    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4205    SET_VREG(r0, r9)                    @ vAA<- r0
4206    GOTO_OPCODE(ip)                     @ jump to next instruction
4207    /* 9-10 instructions */
4208
4209
4210/* ------------------------------ */
4211    .balign 64
4212.L_OP_ADD_INT: /* 0x90 */
4213/* File: armv5te/OP_ADD_INT.S */
4214/* File: armv5te/binop.S */
4215    /*
4216     * Generic 32-bit binary operation.  Provide an "instr" line that
4217     * specifies an instruction that performs "result = r0 op r1".
4218     * This could be an ARM instruction or a function call.  (If the result
4219     * comes back in a register other than r0, you can override "result".)
4220     *
4221     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4222     * vCC (r1).  Useful for integer division and modulus.  Note that we
4223     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4224     * handles it correctly.
4225     *
4226     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4227     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4228     *      mul-float, div-float, rem-float
4229     */
4230    /* binop vAA, vBB, vCC */
4231    FETCH(r0, 1)                        @ r0<- CCBB
4232    mov     r9, rINST, lsr #8           @ r9<- AA
4233    mov     r3, r0, lsr #8              @ r3<- CC
4234    and     r2, r0, #255                @ r2<- BB
4235    GET_VREG(r1, r3)                    @ r1<- vCC
4236    GET_VREG(r0, r2)                    @ r0<- vBB
4237    .if 0
4238    cmp     r1, #0                      @ is second operand zero?
4239    beq     common_errDivideByZero
4240    .endif
4241
4242    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4243                               @ optional op; may set condition codes
4244    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
4245    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4246    SET_VREG(r0, r9)               @ vAA<- r0
4247    GOTO_OPCODE(ip)                     @ jump to next instruction
4248    /* 11-14 instructions */
4249
4250
4251
4252/* ------------------------------ */
4253    .balign 64
4254.L_OP_SUB_INT: /* 0x91 */
4255/* File: armv5te/OP_SUB_INT.S */
4256/* File: armv5te/binop.S */
4257    /*
4258     * Generic 32-bit binary operation.  Provide an "instr" line that
4259     * specifies an instruction that performs "result = r0 op r1".
4260     * This could be an ARM instruction or a function call.  (If the result
4261     * comes back in a register other than r0, you can override "result".)
4262     *
4263     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4264     * vCC (r1).  Useful for integer division and modulus.  Note that we
4265     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4266     * handles it correctly.
4267     *
4268     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4269     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4270     *      mul-float, div-float, rem-float
4271     */
4272    /* binop vAA, vBB, vCC */
4273    FETCH(r0, 1)                        @ r0<- CCBB
4274    mov     r9, rINST, lsr #8           @ r9<- AA
4275    mov     r3, r0, lsr #8              @ r3<- CC
4276    and     r2, r0, #255                @ r2<- BB
4277    GET_VREG(r1, r3)                    @ r1<- vCC
4278    GET_VREG(r0, r2)                    @ r0<- vBB
4279    .if 0
4280    cmp     r1, #0                      @ is second operand zero?
4281    beq     common_errDivideByZero
4282    .endif
4283
4284    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4285                               @ optional op; may set condition codes
4286    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
4287    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4288    SET_VREG(r0, r9)               @ vAA<- r0
4289    GOTO_OPCODE(ip)                     @ jump to next instruction
4290    /* 11-14 instructions */
4291
4292
4293
4294/* ------------------------------ */
4295    .balign 64
4296.L_OP_MUL_INT: /* 0x92 */
4297/* File: armv5te/OP_MUL_INT.S */
4298/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
4299/* File: armv5te/binop.S */
4300    /*
4301     * Generic 32-bit binary operation.  Provide an "instr" line that
4302     * specifies an instruction that performs "result = r0 op r1".
4303     * This could be an ARM instruction or a function call.  (If the result
4304     * comes back in a register other than r0, you can override "result".)
4305     *
4306     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4307     * vCC (r1).  Useful for integer division and modulus.  Note that we
4308     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4309     * handles it correctly.
4310     *
4311     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4312     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4313     *      mul-float, div-float, rem-float
4314     */
4315    /* binop vAA, vBB, vCC */
4316    FETCH(r0, 1)                        @ r0<- CCBB
4317    mov     r9, rINST, lsr #8           @ r9<- AA
4318    mov     r3, r0, lsr #8              @ r3<- CC
4319    and     r2, r0, #255                @ r2<- BB
4320    GET_VREG(r1, r3)                    @ r1<- vCC
4321    GET_VREG(r0, r2)                    @ r0<- vBB
4322    .if 0
4323    cmp     r1, #0                      @ is second operand zero?
4324    beq     common_errDivideByZero
4325    .endif
4326
4327    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4328                               @ optional op; may set condition codes
4329    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
4330    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4331    SET_VREG(r0, r9)               @ vAA<- r0
4332    GOTO_OPCODE(ip)                     @ jump to next instruction
4333    /* 11-14 instructions */
4334
4335
4336
4337/* ------------------------------ */
4338    .balign 64
4339.L_OP_DIV_INT: /* 0x93 */
4340/* File: armv5te/OP_DIV_INT.S */
4341/* File: armv5te/binop.S */
4342    /*
4343     * Generic 32-bit binary operation.  Provide an "instr" line that
4344     * specifies an instruction that performs "result = r0 op r1".
4345     * This could be an ARM instruction or a function call.  (If the result
4346     * comes back in a register other than r0, you can override "result".)
4347     *
4348     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4349     * vCC (r1).  Useful for integer division and modulus.  Note that we
4350     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4351     * handles it correctly.
4352     *
4353     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4354     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4355     *      mul-float, div-float, rem-float
4356     */
4357    /* binop vAA, vBB, vCC */
4358    FETCH(r0, 1)                        @ r0<- CCBB
4359    mov     r9, rINST, lsr #8           @ r9<- AA
4360    mov     r3, r0, lsr #8              @ r3<- CC
4361    and     r2, r0, #255                @ r2<- BB
4362    GET_VREG(r1, r3)                    @ r1<- vCC
4363    GET_VREG(r0, r2)                    @ r0<- vBB
4364    .if 1
4365    cmp     r1, #0                      @ is second operand zero?
4366    beq     common_errDivideByZero
4367    .endif
4368
4369    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4370                               @ optional op; may set condition codes
4371    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
4372    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4373    SET_VREG(r0, r9)               @ vAA<- r0
4374    GOTO_OPCODE(ip)                     @ jump to next instruction
4375    /* 11-14 instructions */
4376
4377
4378
4379/* ------------------------------ */
4380    .balign 64
4381.L_OP_REM_INT: /* 0x94 */
4382/* File: armv5te/OP_REM_INT.S */
4383/* idivmod returns quotient in r0 and remainder in r1 */
4384/* File: armv5te/binop.S */
4385    /*
4386     * Generic 32-bit binary operation.  Provide an "instr" line that
4387     * specifies an instruction that performs "result = r0 op r1".
4388     * This could be an ARM instruction or a function call.  (If the result
4389     * comes back in a register other than r0, you can override "result".)
4390     *
4391     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4392     * vCC (r1).  Useful for integer division and modulus.  Note that we
4393     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4394     * handles it correctly.
4395     *
4396     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4397     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4398     *      mul-float, div-float, rem-float
4399     */
4400    /* binop vAA, vBB, vCC */
4401    FETCH(r0, 1)                        @ r0<- CCBB
4402    mov     r9, rINST, lsr #8           @ r9<- AA
4403    mov     r3, r0, lsr #8              @ r3<- CC
4404    and     r2, r0, #255                @ r2<- BB
4405    GET_VREG(r1, r3)                    @ r1<- vCC
4406    GET_VREG(r0, r2)                    @ r0<- vBB
4407    .if 1
4408    cmp     r1, #0                      @ is second operand zero?
4409    beq     common_errDivideByZero
4410    .endif
4411
4412    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4413                               @ optional op; may set condition codes
4414    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
4415    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4416    SET_VREG(r1, r9)               @ vAA<- r1
4417    GOTO_OPCODE(ip)                     @ jump to next instruction
4418    /* 11-14 instructions */
4419
4420
4421
4422/* ------------------------------ */
4423    .balign 64
4424.L_OP_AND_INT: /* 0x95 */
4425/* File: armv5te/OP_AND_INT.S */
4426/* File: armv5te/binop.S */
4427    /*
4428     * Generic 32-bit binary operation.  Provide an "instr" line that
4429     * specifies an instruction that performs "result = r0 op r1".
4430     * This could be an ARM instruction or a function call.  (If the result
4431     * comes back in a register other than r0, you can override "result".)
4432     *
4433     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4434     * vCC (r1).  Useful for integer division and modulus.  Note that we
4435     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4436     * handles it correctly.
4437     *
4438     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4439     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4440     *      mul-float, div-float, rem-float
4441     */
4442    /* binop vAA, vBB, vCC */
4443    FETCH(r0, 1)                        @ r0<- CCBB
4444    mov     r9, rINST, lsr #8           @ r9<- AA
4445    mov     r3, r0, lsr #8              @ r3<- CC
4446    and     r2, r0, #255                @ r2<- BB
4447    GET_VREG(r1, r3)                    @ r1<- vCC
4448    GET_VREG(r0, r2)                    @ r0<- vBB
4449    .if 0
4450    cmp     r1, #0                      @ is second operand zero?
4451    beq     common_errDivideByZero
4452    .endif
4453
4454    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4455                               @ optional op; may set condition codes
4456    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
4457    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4458    SET_VREG(r0, r9)               @ vAA<- r0
4459    GOTO_OPCODE(ip)                     @ jump to next instruction
4460    /* 11-14 instructions */
4461
4462
4463
4464/* ------------------------------ */
4465    .balign 64
4466.L_OP_OR_INT: /* 0x96 */
4467/* File: armv5te/OP_OR_INT.S */
4468/* File: armv5te/binop.S */
4469    /*
4470     * Generic 32-bit binary operation.  Provide an "instr" line that
4471     * specifies an instruction that performs "result = r0 op r1".
4472     * This could be an ARM instruction or a function call.  (If the result
4473     * comes back in a register other than r0, you can override "result".)
4474     *
4475     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4476     * vCC (r1).  Useful for integer division and modulus.  Note that we
4477     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4478     * handles it correctly.
4479     *
4480     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4481     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4482     *      mul-float, div-float, rem-float
4483     */
4484    /* binop vAA, vBB, vCC */
4485    FETCH(r0, 1)                        @ r0<- CCBB
4486    mov     r9, rINST, lsr #8           @ r9<- AA
4487    mov     r3, r0, lsr #8              @ r3<- CC
4488    and     r2, r0, #255                @ r2<- BB
4489    GET_VREG(r1, r3)                    @ r1<- vCC
4490    GET_VREG(r0, r2)                    @ r0<- vBB
4491    .if 0
4492    cmp     r1, #0                      @ is second operand zero?
4493    beq     common_errDivideByZero
4494    .endif
4495
4496    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4497                               @ optional op; may set condition codes
4498    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
4499    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4500    SET_VREG(r0, r9)               @ vAA<- r0
4501    GOTO_OPCODE(ip)                     @ jump to next instruction
4502    /* 11-14 instructions */
4503
4504
4505
4506/* ------------------------------ */
4507    .balign 64
4508.L_OP_XOR_INT: /* 0x97 */
4509/* File: armv5te/OP_XOR_INT.S */
4510/* File: armv5te/binop.S */
4511    /*
4512     * Generic 32-bit binary operation.  Provide an "instr" line that
4513     * specifies an instruction that performs "result = r0 op r1".
4514     * This could be an ARM instruction or a function call.  (If the result
4515     * comes back in a register other than r0, you can override "result".)
4516     *
4517     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4518     * vCC (r1).  Useful for integer division and modulus.  Note that we
4519     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4520     * handles it correctly.
4521     *
4522     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4523     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4524     *      mul-float, div-float, rem-float
4525     */
4526    /* binop vAA, vBB, vCC */
4527    FETCH(r0, 1)                        @ r0<- CCBB
4528    mov     r9, rINST, lsr #8           @ r9<- AA
4529    mov     r3, r0, lsr #8              @ r3<- CC
4530    and     r2, r0, #255                @ r2<- BB
4531    GET_VREG(r1, r3)                    @ r1<- vCC
4532    GET_VREG(r0, r2)                    @ r0<- vBB
4533    .if 0
4534    cmp     r1, #0                      @ is second operand zero?
4535    beq     common_errDivideByZero
4536    .endif
4537
4538    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4539                               @ optional op; may set condition codes
4540    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
4541    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4542    SET_VREG(r0, r9)               @ vAA<- r0
4543    GOTO_OPCODE(ip)                     @ jump to next instruction
4544    /* 11-14 instructions */
4545
4546
4547
4548/* ------------------------------ */
4549    .balign 64
4550.L_OP_SHL_INT: /* 0x98 */
4551/* File: armv5te/OP_SHL_INT.S */
4552/* File: armv5te/binop.S */
4553    /*
4554     * Generic 32-bit binary operation.  Provide an "instr" line that
4555     * specifies an instruction that performs "result = r0 op r1".
4556     * This could be an ARM instruction or a function call.  (If the result
4557     * comes back in a register other than r0, you can override "result".)
4558     *
4559     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4560     * vCC (r1).  Useful for integer division and modulus.  Note that we
4561     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4562     * handles it correctly.
4563     *
4564     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4565     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4566     *      mul-float, div-float, rem-float
4567     */
4568    /* binop vAA, vBB, vCC */
4569    FETCH(r0, 1)                        @ r0<- CCBB
4570    mov     r9, rINST, lsr #8           @ r9<- AA
4571    mov     r3, r0, lsr #8              @ r3<- CC
4572    and     r2, r0, #255                @ r2<- BB
4573    GET_VREG(r1, r3)                    @ r1<- vCC
4574    GET_VREG(r0, r2)                    @ r0<- vBB
4575    .if 0
4576    cmp     r1, #0                      @ is second operand zero?
4577    beq     common_errDivideByZero
4578    .endif
4579
4580    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4581    and     r1, r1, #31                           @ optional op; may set condition codes
4582    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
4583    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4584    SET_VREG(r0, r9)               @ vAA<- r0
4585    GOTO_OPCODE(ip)                     @ jump to next instruction
4586    /* 11-14 instructions */
4587
4588
4589
4590/* ------------------------------ */
4591    .balign 64
4592.L_OP_SHR_INT: /* 0x99 */
4593/* File: armv5te/OP_SHR_INT.S */
4594/* File: armv5te/binop.S */
4595    /*
4596     * Generic 32-bit binary operation.  Provide an "instr" line that
4597     * specifies an instruction that performs "result = r0 op r1".
4598     * This could be an ARM instruction or a function call.  (If the result
4599     * comes back in a register other than r0, you can override "result".)
4600     *
4601     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4602     * vCC (r1).  Useful for integer division and modulus.  Note that we
4603     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4604     * handles it correctly.
4605     *
4606     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4607     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4608     *      mul-float, div-float, rem-float
4609     */
4610    /* binop vAA, vBB, vCC */
4611    FETCH(r0, 1)                        @ r0<- CCBB
4612    mov     r9, rINST, lsr #8           @ r9<- AA
4613    mov     r3, r0, lsr #8              @ r3<- CC
4614    and     r2, r0, #255                @ r2<- BB
4615    GET_VREG(r1, r3)                    @ r1<- vCC
4616    GET_VREG(r0, r2)                    @ r0<- vBB
4617    .if 0
4618    cmp     r1, #0                      @ is second operand zero?
4619    beq     common_errDivideByZero
4620    .endif
4621
4622    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4623    and     r1, r1, #31                           @ optional op; may set condition codes
4624    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
4625    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4626    SET_VREG(r0, r9)               @ vAA<- r0
4627    GOTO_OPCODE(ip)                     @ jump to next instruction
4628    /* 11-14 instructions */
4629
4630
4631
4632/* ------------------------------ */
4633    .balign 64
4634.L_OP_USHR_INT: /* 0x9a */
4635/* File: armv5te/OP_USHR_INT.S */
4636/* File: armv5te/binop.S */
4637    /*
4638     * Generic 32-bit binary operation.  Provide an "instr" line that
4639     * specifies an instruction that performs "result = r0 op r1".
4640     * This could be an ARM instruction or a function call.  (If the result
4641     * comes back in a register other than r0, you can override "result".)
4642     *
4643     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4644     * vCC (r1).  Useful for integer division and modulus.  Note that we
4645     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4646     * handles it correctly.
4647     *
4648     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4649     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4650     *      mul-float, div-float, rem-float
4651     */
4652    /* binop vAA, vBB, vCC */
4653    FETCH(r0, 1)                        @ r0<- CCBB
4654    mov     r9, rINST, lsr #8           @ r9<- AA
4655    mov     r3, r0, lsr #8              @ r3<- CC
4656    and     r2, r0, #255                @ r2<- BB
4657    GET_VREG(r1, r3)                    @ r1<- vCC
4658    GET_VREG(r0, r2)                    @ r0<- vBB
4659    .if 0
4660    cmp     r1, #0                      @ is second operand zero?
4661    beq     common_errDivideByZero
4662    .endif
4663
4664    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4665    and     r1, r1, #31                           @ optional op; may set condition codes
4666    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
4667    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4668    SET_VREG(r0, r9)               @ vAA<- r0
4669    GOTO_OPCODE(ip)                     @ jump to next instruction
4670    /* 11-14 instructions */
4671
4672
4673
4674/* ------------------------------ */
4675    .balign 64
4676.L_OP_ADD_LONG: /* 0x9b */
4677/* File: armv5te/OP_ADD_LONG.S */
4678/* File: armv5te/binopWide.S */
4679    /*
4680     * Generic 64-bit binary operation.  Provide an "instr" line that
4681     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4682     * This could be an ARM instruction or a function call.  (If the result
4683     * comes back in a register other than r0, you can override "result".)
4684     *
4685     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4686     * vCC (r1).  Useful for integer division and modulus.
4687     *
4688     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4689     *      xor-long, add-double, sub-double, mul-double, div-double,
4690     *      rem-double
4691     *
4692     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4693     */
4694    /* binop vAA, vBB, vCC */
4695    FETCH(r0, 1)                        @ r0<- CCBB
4696    mov     r9, rINST, lsr #8           @ r9<- AA
4697    and     r2, r0, #255                @ r2<- BB
4698    mov     r3, r0, lsr #8              @ r3<- CC
4699    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4700    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4701    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4702    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4703    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4704    .if 0
4705    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4706    beq     common_errDivideByZero
4707    .endif
4708    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4709
4710    adds    r0, r0, r2                           @ optional op; may set condition codes
4711    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
4712    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4713    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4714    GOTO_OPCODE(ip)                     @ jump to next instruction
4715    /* 14-17 instructions */
4716
4717
4718
4719/* ------------------------------ */
4720    .balign 64
4721.L_OP_SUB_LONG: /* 0x9c */
4722/* File: armv5te/OP_SUB_LONG.S */
4723/* File: armv5te/binopWide.S */
4724    /*
4725     * Generic 64-bit binary operation.  Provide an "instr" line that
4726     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4727     * This could be an ARM instruction or a function call.  (If the result
4728     * comes back in a register other than r0, you can override "result".)
4729     *
4730     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4731     * vCC (r1).  Useful for integer division and modulus.
4732     *
4733     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4734     *      xor-long, add-double, sub-double, mul-double, div-double,
4735     *      rem-double
4736     *
4737     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4738     */
4739    /* binop vAA, vBB, vCC */
4740    FETCH(r0, 1)                        @ r0<- CCBB
4741    mov     r9, rINST, lsr #8           @ r9<- AA
4742    and     r2, r0, #255                @ r2<- BB
4743    mov     r3, r0, lsr #8              @ r3<- CC
4744    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4745    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4746    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4747    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4748    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4749    .if 0
4750    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4751    beq     common_errDivideByZero
4752    .endif
4753    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4754
4755    subs    r0, r0, r2                           @ optional op; may set condition codes
4756    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
4757    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4758    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4759    GOTO_OPCODE(ip)                     @ jump to next instruction
4760    /* 14-17 instructions */
4761
4762
4763
4764/* ------------------------------ */
4765    .balign 64
4766.L_OP_MUL_LONG: /* 0x9d */
4767/* File: armv5te/OP_MUL_LONG.S */
4768    /*
4769     * Signed 64-bit integer multiply.
4770     *
4771     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
4772     *        WX
4773     *      x YZ
4774     *  --------
4775     *     ZW ZX
4776     *  YW YX
4777     *
4778     * The low word of the result holds ZX, the high word holds
4779     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
4780     * it doesn't fit in the low 64 bits.
4781     *
4782     * Unlike most ARM math operations, multiply instructions have
4783     * restrictions on using the same register more than once (Rd and Rm
4784     * cannot be the same).
4785     */
4786    /* mul-long vAA, vBB, vCC */
4787    FETCH(r0, 1)                        @ r0<- CCBB
4788    and     r2, r0, #255                @ r2<- BB
4789    mov     r3, r0, lsr #8              @ r3<- CC
4790    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4791    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4792    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4793    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4794    mul     ip, r2, r1                  @  ip<- ZxW
4795    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
4796    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
4797    mov     r0, rINST, lsr #8           @ r0<- AA
4798    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
4799    add     r0, rFP, r0, lsl #2         @ r0<- &fp[AA]
4800    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4801    b       .LOP_MUL_LONG_finish
4802
4803/* ------------------------------ */
4804    .balign 64
4805.L_OP_DIV_LONG: /* 0x9e */
4806/* File: armv5te/OP_DIV_LONG.S */
4807/* File: armv5te/binopWide.S */
4808    /*
4809     * Generic 64-bit binary operation.  Provide an "instr" line that
4810     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4811     * This could be an ARM instruction or a function call.  (If the result
4812     * comes back in a register other than r0, you can override "result".)
4813     *
4814     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4815     * vCC (r1).  Useful for integer division and modulus.
4816     *
4817     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4818     *      xor-long, add-double, sub-double, mul-double, div-double,
4819     *      rem-double
4820     *
4821     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4822     */
4823    /* binop vAA, vBB, vCC */
4824    FETCH(r0, 1)                        @ r0<- CCBB
4825    mov     r9, rINST, lsr #8           @ r9<- AA
4826    and     r2, r0, #255                @ r2<- BB
4827    mov     r3, r0, lsr #8              @ r3<- CC
4828    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4829    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4830    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4831    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4832    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4833    .if 1
4834    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4835    beq     common_errDivideByZero
4836    .endif
4837    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4838
4839                               @ optional op; may set condition codes
4840    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4841    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4842    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4843    GOTO_OPCODE(ip)                     @ jump to next instruction
4844    /* 14-17 instructions */
4845
4846
4847
4848/* ------------------------------ */
4849    .balign 64
4850.L_OP_REM_LONG: /* 0x9f */
4851/* File: armv5te/OP_REM_LONG.S */
4852/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
4853/* File: armv5te/binopWide.S */
4854    /*
4855     * Generic 64-bit binary operation.  Provide an "instr" line that
4856     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4857     * This could be an ARM instruction or a function call.  (If the result
4858     * comes back in a register other than r0, you can override "result".)
4859     *
4860     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4861     * vCC (r1).  Useful for integer division and modulus.
4862     *
4863     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4864     *      xor-long, add-double, sub-double, mul-double, div-double,
4865     *      rem-double
4866     *
4867     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4868     */
4869    /* binop vAA, vBB, vCC */
4870    FETCH(r0, 1)                        @ r0<- CCBB
4871    mov     r9, rINST, lsr #8           @ r9<- AA
4872    and     r2, r0, #255                @ r2<- BB
4873    mov     r3, r0, lsr #8              @ r3<- CC
4874    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4875    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4876    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4877    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4878    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4879    .if 1
4880    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4881    beq     common_errDivideByZero
4882    .endif
4883    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4884
4885                               @ optional op; may set condition codes
4886    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4887    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4888    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
4889    GOTO_OPCODE(ip)                     @ jump to next instruction
4890    /* 14-17 instructions */
4891
4892
4893
4894/* ------------------------------ */
4895    .balign 64
4896.L_OP_AND_LONG: /* 0xa0 */
4897/* File: armv5te/OP_AND_LONG.S */
4898/* File: armv5te/binopWide.S */
4899    /*
4900     * Generic 64-bit binary operation.  Provide an "instr" line that
4901     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4902     * This could be an ARM instruction or a function call.  (If the result
4903     * comes back in a register other than r0, you can override "result".)
4904     *
4905     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4906     * vCC (r1).  Useful for integer division and modulus.
4907     *
4908     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4909     *      xor-long, add-double, sub-double, mul-double, div-double,
4910     *      rem-double
4911     *
4912     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4913     */
4914    /* binop vAA, vBB, vCC */
4915    FETCH(r0, 1)                        @ r0<- CCBB
4916    mov     r9, rINST, lsr #8           @ r9<- AA
4917    and     r2, r0, #255                @ r2<- BB
4918    mov     r3, r0, lsr #8              @ r3<- CC
4919    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4920    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4921    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4922    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4923    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4924    .if 0
4925    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4926    beq     common_errDivideByZero
4927    .endif
4928    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4929
4930    and     r0, r0, r2                           @ optional op; may set condition codes
4931    and     r1, r1, r3                              @ result<- op, r0-r3 changed
4932    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4933    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4934    GOTO_OPCODE(ip)                     @ jump to next instruction
4935    /* 14-17 instructions */
4936
4937
4938
4939/* ------------------------------ */
4940    .balign 64
4941.L_OP_OR_LONG: /* 0xa1 */
4942/* File: armv5te/OP_OR_LONG.S */
4943/* File: armv5te/binopWide.S */
4944    /*
4945     * Generic 64-bit binary operation.  Provide an "instr" line that
4946     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4947     * This could be an ARM instruction or a function call.  (If the result
4948     * comes back in a register other than r0, you can override "result".)
4949     *
4950     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4951     * vCC (r1).  Useful for integer division and modulus.
4952     *
4953     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4954     *      xor-long, add-double, sub-double, mul-double, div-double,
4955     *      rem-double
4956     *
4957     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4958     */
4959    /* binop vAA, vBB, vCC */
4960    FETCH(r0, 1)                        @ r0<- CCBB
4961    mov     r9, rINST, lsr #8           @ r9<- AA
4962    and     r2, r0, #255                @ r2<- BB
4963    mov     r3, r0, lsr #8              @ r3<- CC
4964    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4965    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4966    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4967    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4968    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4969    .if 0
4970    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4971    beq     common_errDivideByZero
4972    .endif
4973    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4974
4975    orr     r0, r0, r2                           @ optional op; may set condition codes
4976    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
4977    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4978    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4979    GOTO_OPCODE(ip)                     @ jump to next instruction
4980    /* 14-17 instructions */
4981
4982
4983
4984/* ------------------------------ */
4985    .balign 64
4986.L_OP_XOR_LONG: /* 0xa2 */
4987/* File: armv5te/OP_XOR_LONG.S */
4988/* File: armv5te/binopWide.S */
4989    /*
4990     * Generic 64-bit binary operation.  Provide an "instr" line that
4991     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4992     * This could be an ARM instruction or a function call.  (If the result
4993     * comes back in a register other than r0, you can override "result".)
4994     *
4995     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4996     * vCC (r1).  Useful for integer division and modulus.
4997     *
4998     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4999     *      xor-long, add-double, sub-double, mul-double, div-double,
5000     *      rem-double
5001     *
5002     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5003     */
5004    /* binop vAA, vBB, vCC */
5005    FETCH(r0, 1)                        @ r0<- CCBB
5006    mov     r9, rINST, lsr #8           @ r9<- AA
5007    and     r2, r0, #255                @ r2<- BB
5008    mov     r3, r0, lsr #8              @ r3<- CC
5009    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5010    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5011    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5012    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5013    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5014    .if 0
5015    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5016    beq     common_errDivideByZero
5017    .endif
5018    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5019
5020    eor     r0, r0, r2                           @ optional op; may set condition codes
5021    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
5022    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5023    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5024    GOTO_OPCODE(ip)                     @ jump to next instruction
5025    /* 14-17 instructions */
5026
5027
5028
5029/* ------------------------------ */
5030    .balign 64
5031.L_OP_SHL_LONG: /* 0xa3 */
5032/* File: armv5te/OP_SHL_LONG.S */
5033    /*
5034     * Long integer shift.  This is different from the generic 32/64-bit
5035     * binary operations because vAA/vBB are 64-bit but vCC (the shift
5036     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
5037     * 6 bits of the shift distance.
5038     */
5039    /* shl-long vAA, vBB, vCC */
5040    FETCH(r0, 1)                        @ r0<- CCBB
5041    mov     r9, rINST, lsr #8           @ r9<- AA
5042    and     r3, r0, #255                @ r3<- BB
5043    mov     r0, r0, lsr #8              @ r0<- CC
5044    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
5045    GET_VREG(r2, r0)                    @ r2<- vCC
5046    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5047    and     r2, r2, #63                 @ r2<- r2 & 0x3f
5048    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5049
5050    mov     r1, r1, asl r2              @  r1<- r1 << r2
5051    rsb     r3, r2, #32                 @  r3<- 32 - r2
5052    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
5053    subs    ip, r2, #32                 @  ip<- r2 - 32
5054    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
5055    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5056    b       .LOP_SHL_LONG_finish
5057
5058/* ------------------------------ */
5059    .balign 64
5060.L_OP_SHR_LONG: /* 0xa4 */
5061/* File: armv5te/OP_SHR_LONG.S */
5062    /*
5063     * Long integer shift.  This is different from the generic 32/64-bit
5064     * binary operations because vAA/vBB are 64-bit but vCC (the shift
5065     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
5066     * 6 bits of the shift distance.
5067     */
5068    /* shr-long vAA, vBB, vCC */
5069    FETCH(r0, 1)                        @ r0<- CCBB
5070    mov     r9, rINST, lsr #8           @ r9<- AA
5071    and     r3, r0, #255                @ r3<- BB
5072    mov     r0, r0, lsr #8              @ r0<- CC
5073    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
5074    GET_VREG(r2, r0)                    @ r2<- vCC
5075    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5076    and     r2, r2, #63                 @ r0<- r0 & 0x3f
5077    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5078
5079    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
5080    rsb     r3, r2, #32                 @  r3<- 32 - r2
5081    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
5082    subs    ip, r2, #32                 @  ip<- r2 - 32
5083    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
5084    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5085    b       .LOP_SHR_LONG_finish
5086
5087/* ------------------------------ */
5088    .balign 64
5089.L_OP_USHR_LONG: /* 0xa5 */
5090/* File: armv5te/OP_USHR_LONG.S */
5091    /*
5092     * Long integer shift.  This is different from the generic 32/64-bit
5093     * binary operations because vAA/vBB are 64-bit but vCC (the shift
5094     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
5095     * 6 bits of the shift distance.
5096     */
5097    /* ushr-long vAA, vBB, vCC */
5098    FETCH(r0, 1)                        @ r0<- CCBB
5099    mov     r9, rINST, lsr #8           @ r9<- AA
5100    and     r3, r0, #255                @ r3<- BB
5101    mov     r0, r0, lsr #8              @ r0<- CC
5102    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
5103    GET_VREG(r2, r0)                    @ r2<- vCC
5104    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5105    and     r2, r2, #63                 @ r0<- r0 & 0x3f
5106    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5107
5108    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
5109    rsb     r3, r2, #32                 @  r3<- 32 - r2
5110    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
5111    subs    ip, r2, #32                 @  ip<- r2 - 32
5112    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
5113    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5114    b       .LOP_USHR_LONG_finish
5115
5116/* ------------------------------ */
5117    .balign 64
5118.L_OP_ADD_FLOAT: /* 0xa6 */
5119/* File: armv5te/OP_ADD_FLOAT.S */
5120/* File: armv5te/binop.S */
5121    /*
5122     * Generic 32-bit binary operation.  Provide an "instr" line that
5123     * specifies an instruction that performs "result = r0 op r1".
5124     * This could be an ARM instruction or a function call.  (If the result
5125     * comes back in a register other than r0, you can override "result".)
5126     *
5127     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5128     * vCC (r1).  Useful for integer division and modulus.  Note that we
5129     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5130     * handles it correctly.
5131     *
5132     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5133     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5134     *      mul-float, div-float, rem-float
5135     */
5136    /* binop vAA, vBB, vCC */
5137    FETCH(r0, 1)                        @ r0<- CCBB
5138    mov     r9, rINST, lsr #8           @ r9<- AA
5139    mov     r3, r0, lsr #8              @ r3<- CC
5140    and     r2, r0, #255                @ r2<- BB
5141    GET_VREG(r1, r3)                    @ r1<- vCC
5142    GET_VREG(r0, r2)                    @ r0<- vBB
5143    .if 0
5144    cmp     r1, #0                      @ is second operand zero?
5145    beq     common_errDivideByZero
5146    .endif
5147
5148    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5149                               @ optional op; may set condition codes
5150    bl      __aeabi_fadd                              @ r0<- op, r0-r3 changed
5151    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5152    SET_VREG(r0, r9)               @ vAA<- r0
5153    GOTO_OPCODE(ip)                     @ jump to next instruction
5154    /* 11-14 instructions */
5155
5156
5157
5158/* ------------------------------ */
5159    .balign 64
5160.L_OP_SUB_FLOAT: /* 0xa7 */
5161/* File: armv5te/OP_SUB_FLOAT.S */
5162/* File: armv5te/binop.S */
5163    /*
5164     * Generic 32-bit binary operation.  Provide an "instr" line that
5165     * specifies an instruction that performs "result = r0 op r1".
5166     * This could be an ARM instruction or a function call.  (If the result
5167     * comes back in a register other than r0, you can override "result".)
5168     *
5169     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5170     * vCC (r1).  Useful for integer division and modulus.  Note that we
5171     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5172     * handles it correctly.
5173     *
5174     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5175     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5176     *      mul-float, div-float, rem-float
5177     */
5178    /* binop vAA, vBB, vCC */
5179    FETCH(r0, 1)                        @ r0<- CCBB
5180    mov     r9, rINST, lsr #8           @ r9<- AA
5181    mov     r3, r0, lsr #8              @ r3<- CC
5182    and     r2, r0, #255                @ r2<- BB
5183    GET_VREG(r1, r3)                    @ r1<- vCC
5184    GET_VREG(r0, r2)                    @ r0<- vBB
5185    .if 0
5186    cmp     r1, #0                      @ is second operand zero?
5187    beq     common_errDivideByZero
5188    .endif
5189
5190    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5191                               @ optional op; may set condition codes
5192    bl      __aeabi_fsub                              @ r0<- op, r0-r3 changed
5193    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5194    SET_VREG(r0, r9)               @ vAA<- r0
5195    GOTO_OPCODE(ip)                     @ jump to next instruction
5196    /* 11-14 instructions */
5197
5198
5199
5200/* ------------------------------ */
5201    .balign 64
5202.L_OP_MUL_FLOAT: /* 0xa8 */
5203/* File: armv5te/OP_MUL_FLOAT.S */
5204/* File: armv5te/binop.S */
5205    /*
5206     * Generic 32-bit binary operation.  Provide an "instr" line that
5207     * specifies an instruction that performs "result = r0 op r1".
5208     * This could be an ARM instruction or a function call.  (If the result
5209     * comes back in a register other than r0, you can override "result".)
5210     *
5211     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5212     * vCC (r1).  Useful for integer division and modulus.  Note that we
5213     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5214     * handles it correctly.
5215     *
5216     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5217     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5218     *      mul-float, div-float, rem-float
5219     */
5220    /* binop vAA, vBB, vCC */
5221    FETCH(r0, 1)                        @ r0<- CCBB
5222    mov     r9, rINST, lsr #8           @ r9<- AA
5223    mov     r3, r0, lsr #8              @ r3<- CC
5224    and     r2, r0, #255                @ r2<- BB
5225    GET_VREG(r1, r3)                    @ r1<- vCC
5226    GET_VREG(r0, r2)                    @ r0<- vBB
5227    .if 0
5228    cmp     r1, #0                      @ is second operand zero?
5229    beq     common_errDivideByZero
5230    .endif
5231
5232    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5233                               @ optional op; may set condition codes
5234    bl      __aeabi_fmul                              @ r0<- op, r0-r3 changed
5235    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5236    SET_VREG(r0, r9)               @ vAA<- r0
5237    GOTO_OPCODE(ip)                     @ jump to next instruction
5238    /* 11-14 instructions */
5239
5240
5241
5242/* ------------------------------ */
5243    .balign 64
5244.L_OP_DIV_FLOAT: /* 0xa9 */
5245/* File: armv5te/OP_DIV_FLOAT.S */
5246/* File: armv5te/binop.S */
5247    /*
5248     * Generic 32-bit binary operation.  Provide an "instr" line that
5249     * specifies an instruction that performs "result = r0 op r1".
5250     * This could be an ARM instruction or a function call.  (If the result
5251     * comes back in a register other than r0, you can override "result".)
5252     *
5253     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5254     * vCC (r1).  Useful for integer division and modulus.  Note that we
5255     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5256     * handles it correctly.
5257     *
5258     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5259     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5260     *      mul-float, div-float, rem-float
5261     */
5262    /* binop vAA, vBB, vCC */
5263    FETCH(r0, 1)                        @ r0<- CCBB
5264    mov     r9, rINST, lsr #8           @ r9<- AA
5265    mov     r3, r0, lsr #8              @ r3<- CC
5266    and     r2, r0, #255                @ r2<- BB
5267    GET_VREG(r1, r3)                    @ r1<- vCC
5268    GET_VREG(r0, r2)                    @ r0<- vBB
5269    .if 0
5270    cmp     r1, #0                      @ is second operand zero?
5271    beq     common_errDivideByZero
5272    .endif
5273
5274    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5275                               @ optional op; may set condition codes
5276    bl      __aeabi_fdiv                              @ r0<- op, r0-r3 changed
5277    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5278    SET_VREG(r0, r9)               @ vAA<- r0
5279    GOTO_OPCODE(ip)                     @ jump to next instruction
5280    /* 11-14 instructions */
5281
5282
5283
5284/* ------------------------------ */
5285    .balign 64
5286.L_OP_REM_FLOAT: /* 0xaa */
5287/* File: armv5te/OP_REM_FLOAT.S */
5288/* EABI doesn't define a float remainder function, but libm does */
5289/* File: armv5te/binop.S */
5290    /*
5291     * Generic 32-bit binary operation.  Provide an "instr" line that
5292     * specifies an instruction that performs "result = r0 op r1".
5293     * This could be an ARM instruction or a function call.  (If the result
5294     * comes back in a register other than r0, you can override "result".)
5295     *
5296     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5297     * vCC (r1).  Useful for integer division and modulus.  Note that we
5298     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5299     * handles it correctly.
5300     *
5301     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5302     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5303     *      mul-float, div-float, rem-float
5304     */
5305    /* binop vAA, vBB, vCC */
5306    FETCH(r0, 1)                        @ r0<- CCBB
5307    mov     r9, rINST, lsr #8           @ r9<- AA
5308    mov     r3, r0, lsr #8              @ r3<- CC
5309    and     r2, r0, #255                @ r2<- BB
5310    GET_VREG(r1, r3)                    @ r1<- vCC
5311    GET_VREG(r0, r2)                    @ r0<- vBB
5312    .if 0
5313    cmp     r1, #0                      @ is second operand zero?
5314    beq     common_errDivideByZero
5315    .endif
5316
5317    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5318                               @ optional op; may set condition codes
5319    bl      fmodf                              @ r0<- op, r0-r3 changed
5320    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5321    SET_VREG(r0, r9)               @ vAA<- r0
5322    GOTO_OPCODE(ip)                     @ jump to next instruction
5323    /* 11-14 instructions */
5324
5325
5326
5327/* ------------------------------ */
5328    .balign 64
5329.L_OP_ADD_DOUBLE: /* 0xab */
5330/* File: armv5te/OP_ADD_DOUBLE.S */
5331/* File: armv5te/binopWide.S */
5332    /*
5333     * Generic 64-bit binary operation.  Provide an "instr" line that
5334     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5335     * This could be an ARM instruction or a function call.  (If the result
5336     * comes back in a register other than r0, you can override "result".)
5337     *
5338     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5339     * vCC (r1).  Useful for integer division and modulus.
5340     *
5341     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5342     *      xor-long, add-double, sub-double, mul-double, div-double,
5343     *      rem-double
5344     *
5345     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5346     */
5347    /* binop vAA, vBB, vCC */
5348    FETCH(r0, 1)                        @ r0<- CCBB
5349    mov     r9, rINST, lsr #8           @ r9<- AA
5350    and     r2, r0, #255                @ r2<- BB
5351    mov     r3, r0, lsr #8              @ r3<- CC
5352    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5353    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5354    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5355    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5356    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5357    .if 0
5358    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5359    beq     common_errDivideByZero
5360    .endif
5361    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5362
5363                               @ optional op; may set condition codes
5364    bl      __aeabi_dadd                              @ result<- op, r0-r3 changed
5365    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5366    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5367    GOTO_OPCODE(ip)                     @ jump to next instruction
5368    /* 14-17 instructions */
5369
5370
5371
5372/* ------------------------------ */
5373    .balign 64
5374.L_OP_SUB_DOUBLE: /* 0xac */
5375/* File: armv5te/OP_SUB_DOUBLE.S */
5376/* File: armv5te/binopWide.S */
5377    /*
5378     * Generic 64-bit binary operation.  Provide an "instr" line that
5379     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5380     * This could be an ARM instruction or a function call.  (If the result
5381     * comes back in a register other than r0, you can override "result".)
5382     *
5383     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5384     * vCC (r1).  Useful for integer division and modulus.
5385     *
5386     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5387     *      xor-long, add-double, sub-double, mul-double, div-double,
5388     *      rem-double
5389     *
5390     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5391     */
5392    /* binop vAA, vBB, vCC */
5393    FETCH(r0, 1)                        @ r0<- CCBB
5394    mov     r9, rINST, lsr #8           @ r9<- AA
5395    and     r2, r0, #255                @ r2<- BB
5396    mov     r3, r0, lsr #8              @ r3<- CC
5397    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5398    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5399    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5400    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5401    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5402    .if 0
5403    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5404    beq     common_errDivideByZero
5405    .endif
5406    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5407
5408                               @ optional op; may set condition codes
5409    bl      __aeabi_dsub                              @ result<- op, r0-r3 changed
5410    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5411    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5412    GOTO_OPCODE(ip)                     @ jump to next instruction
5413    /* 14-17 instructions */
5414
5415
5416
5417/* ------------------------------ */
5418    .balign 64
5419.L_OP_MUL_DOUBLE: /* 0xad */
5420/* File: armv5te/OP_MUL_DOUBLE.S */
5421/* File: armv5te/binopWide.S */
5422    /*
5423     * Generic 64-bit binary operation.  Provide an "instr" line that
5424     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5425     * This could be an ARM instruction or a function call.  (If the result
5426     * comes back in a register other than r0, you can override "result".)
5427     *
5428     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5429     * vCC (r1).  Useful for integer division and modulus.
5430     *
5431     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5432     *      xor-long, add-double, sub-double, mul-double, div-double,
5433     *      rem-double
5434     *
5435     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5436     */
5437    /* binop vAA, vBB, vCC */
5438    FETCH(r0, 1)                        @ r0<- CCBB
5439    mov     r9, rINST, lsr #8           @ r9<- AA
5440    and     r2, r0, #255                @ r2<- BB
5441    mov     r3, r0, lsr #8              @ r3<- CC
5442    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5443    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5444    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5445    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5446    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5447    .if 0
5448    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5449    beq     common_errDivideByZero
5450    .endif
5451    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5452
5453                               @ optional op; may set condition codes
5454    bl      __aeabi_dmul                              @ result<- op, r0-r3 changed
5455    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5456    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5457    GOTO_OPCODE(ip)                     @ jump to next instruction
5458    /* 14-17 instructions */
5459
5460
5461
5462/* ------------------------------ */
5463    .balign 64
5464.L_OP_DIV_DOUBLE: /* 0xae */
5465/* File: armv5te/OP_DIV_DOUBLE.S */
5466/* File: armv5te/binopWide.S */
5467    /*
5468     * Generic 64-bit binary operation.  Provide an "instr" line that
5469     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5470     * This could be an ARM instruction or a function call.  (If the result
5471     * comes back in a register other than r0, you can override "result".)
5472     *
5473     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5474     * vCC (r1).  Useful for integer division and modulus.
5475     *
5476     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5477     *      xor-long, add-double, sub-double, mul-double, div-double,
5478     *      rem-double
5479     *
5480     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5481     */
5482    /* binop vAA, vBB, vCC */
5483    FETCH(r0, 1)                        @ r0<- CCBB
5484    mov     r9, rINST, lsr #8           @ r9<- AA
5485    and     r2, r0, #255                @ r2<- BB
5486    mov     r3, r0, lsr #8              @ r3<- CC
5487    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5488    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5489    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5490    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5491    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5492    .if 0
5493    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5494    beq     common_errDivideByZero
5495    .endif
5496    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5497
5498                               @ optional op; may set condition codes
5499    bl      __aeabi_ddiv                              @ result<- op, r0-r3 changed
5500    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5501    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5502    GOTO_OPCODE(ip)                     @ jump to next instruction
5503    /* 14-17 instructions */
5504
5505
5506
5507/* ------------------------------ */
5508    .balign 64
5509.L_OP_REM_DOUBLE: /* 0xaf */
5510/* File: armv5te/OP_REM_DOUBLE.S */
5511/* EABI doesn't define a double remainder function, but libm does */
5512/* File: armv5te/binopWide.S */
5513    /*
5514     * Generic 64-bit binary operation.  Provide an "instr" line that
5515     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5516     * This could be an ARM instruction or a function call.  (If the result
5517     * comes back in a register other than r0, you can override "result".)
5518     *
5519     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5520     * vCC (r1).  Useful for integer division and modulus.
5521     *
5522     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5523     *      xor-long, add-double, sub-double, mul-double, div-double,
5524     *      rem-double
5525     *
5526     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5527     */
5528    /* binop vAA, vBB, vCC */
5529    FETCH(r0, 1)                        @ r0<- CCBB
5530    mov     r9, rINST, lsr #8           @ r9<- AA
5531    and     r2, r0, #255                @ r2<- BB
5532    mov     r3, r0, lsr #8              @ r3<- CC
5533    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5534    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5535    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5536    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5537    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5538    .if 0
5539    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5540    beq     common_errDivideByZero
5541    .endif
5542    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5543
5544                               @ optional op; may set condition codes
5545    bl      fmod                              @ result<- op, r0-r3 changed
5546    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5547    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5548    GOTO_OPCODE(ip)                     @ jump to next instruction
5549    /* 14-17 instructions */
5550
5551
5552
5553/* ------------------------------ */
5554    .balign 64
5555.L_OP_ADD_INT_2ADDR: /* 0xb0 */
5556/* File: armv5te/OP_ADD_INT_2ADDR.S */
5557/* File: armv5te/binop2addr.S */
5558    /*
5559     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5560     * that specifies an instruction that performs "result = r0 op r1".
5561     * This could be an ARM instruction or a function call.  (If the result
5562     * comes back in a register other than r0, you can override "result".)
5563     *
5564     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5565     * vCC (r1).  Useful for integer division and modulus.
5566     *
5567     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5568     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5569     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5570     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5571     */
5572    /* binop/2addr vA, vB */
5573    mov     r9, rINST, lsr #8           @ r9<- A+
5574    mov     r3, rINST, lsr #12          @ r3<- B
5575    and     r9, r9, #15
5576    GET_VREG(r0, r9)                    @ r0<- vA
5577    GET_VREG(r1, r3)                    @ r1<- vB
5578    .if 0
5579    cmp     r1, #0                      @ is second operand zero?
5580    beq     common_errDivideByZero
5581    .endif
5582    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5583
5584                               @ optional op; may set condition codes
5585    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
5586    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5587    SET_VREG(r0, r9)               @ vAA<- r0
5588    GOTO_OPCODE(ip)                     @ jump to next instruction
5589    /* 10-13 instructions */
5590
5591
5592
5593/* ------------------------------ */
5594    .balign 64
5595.L_OP_SUB_INT_2ADDR: /* 0xb1 */
5596/* File: armv5te/OP_SUB_INT_2ADDR.S */
5597/* File: armv5te/binop2addr.S */
5598    /*
5599     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5600     * that specifies an instruction that performs "result = r0 op r1".
5601     * This could be an ARM instruction or a function call.  (If the result
5602     * comes back in a register other than r0, you can override "result".)
5603     *
5604     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5605     * vCC (r1).  Useful for integer division and modulus.
5606     *
5607     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5608     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5609     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5610     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5611     */
5612    /* binop/2addr vA, vB */
5613    mov     r9, rINST, lsr #8           @ r9<- A+
5614    mov     r3, rINST, lsr #12          @ r3<- B
5615    and     r9, r9, #15
5616    GET_VREG(r0, r9)                    @ r0<- vA
5617    GET_VREG(r1, r3)                    @ r1<- vB
5618    .if 0
5619    cmp     r1, #0                      @ is second operand zero?
5620    beq     common_errDivideByZero
5621    .endif
5622    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5623
5624                               @ optional op; may set condition codes
5625    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
5626    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5627    SET_VREG(r0, r9)               @ vAA<- r0
5628    GOTO_OPCODE(ip)                     @ jump to next instruction
5629    /* 10-13 instructions */
5630
5631
5632
5633/* ------------------------------ */
5634    .balign 64
5635.L_OP_MUL_INT_2ADDR: /* 0xb2 */
5636/* File: armv5te/OP_MUL_INT_2ADDR.S */
5637/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
5638/* File: armv5te/binop2addr.S */
5639    /*
5640     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5641     * that specifies an instruction that performs "result = r0 op r1".
5642     * This could be an ARM instruction or a function call.  (If the result
5643     * comes back in a register other than r0, you can override "result".)
5644     *
5645     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5646     * vCC (r1).  Useful for integer division and modulus.
5647     *
5648     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5649     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5650     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5651     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5652     */
5653    /* binop/2addr vA, vB */
5654    mov     r9, rINST, lsr #8           @ r9<- A+
5655    mov     r3, rINST, lsr #12          @ r3<- B
5656    and     r9, r9, #15
5657    GET_VREG(r0, r9)                    @ r0<- vA
5658    GET_VREG(r1, r3)                    @ r1<- vB
5659    .if 0
5660    cmp     r1, #0                      @ is second operand zero?
5661    beq     common_errDivideByZero
5662    .endif
5663    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5664
5665                               @ optional op; may set condition codes
5666    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
5667    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5668    SET_VREG(r0, r9)               @ vAA<- r0
5669    GOTO_OPCODE(ip)                     @ jump to next instruction
5670    /* 10-13 instructions */
5671
5672
5673
5674/* ------------------------------ */
5675    .balign 64
5676.L_OP_DIV_INT_2ADDR: /* 0xb3 */
5677/* File: armv5te/OP_DIV_INT_2ADDR.S */
5678/* File: armv5te/binop2addr.S */
5679    /*
5680     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5681     * that specifies an instruction that performs "result = r0 op r1".
5682     * This could be an ARM instruction or a function call.  (If the result
5683     * comes back in a register other than r0, you can override "result".)
5684     *
5685     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5686     * vCC (r1).  Useful for integer division and modulus.
5687     *
5688     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5689     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5690     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5691     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5692     */
5693    /* binop/2addr vA, vB */
5694    mov     r9, rINST, lsr #8           @ r9<- A+
5695    mov     r3, rINST, lsr #12          @ r3<- B
5696    and     r9, r9, #15
5697    GET_VREG(r0, r9)                    @ r0<- vA
5698    GET_VREG(r1, r3)                    @ r1<- vB
5699    .if 1
5700    cmp     r1, #0                      @ is second operand zero?
5701    beq     common_errDivideByZero
5702    .endif
5703    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5704
5705                               @ optional op; may set condition codes
5706    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
5707    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5708    SET_VREG(r0, r9)               @ vAA<- r0
5709    GOTO_OPCODE(ip)                     @ jump to next instruction
5710    /* 10-13 instructions */
5711
5712
5713
5714/* ------------------------------ */
5715    .balign 64
5716.L_OP_REM_INT_2ADDR: /* 0xb4 */
5717/* File: armv5te/OP_REM_INT_2ADDR.S */
5718/* idivmod returns quotient in r0 and remainder in r1 */
5719/* File: armv5te/binop2addr.S */
5720    /*
5721     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5722     * that specifies an instruction that performs "result = r0 op r1".
5723     * This could be an ARM instruction or a function call.  (If the result
5724     * comes back in a register other than r0, you can override "result".)
5725     *
5726     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5727     * vCC (r1).  Useful for integer division and modulus.
5728     *
5729     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5730     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5731     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5732     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5733     */
5734    /* binop/2addr vA, vB */
5735    mov     r9, rINST, lsr #8           @ r9<- A+
5736    mov     r3, rINST, lsr #12          @ r3<- B
5737    and     r9, r9, #15
5738    GET_VREG(r0, r9)                    @ r0<- vA
5739    GET_VREG(r1, r3)                    @ r1<- vB
5740    .if 1
5741    cmp     r1, #0                      @ is second operand zero?
5742    beq     common_errDivideByZero
5743    .endif
5744    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5745
5746                               @ optional op; may set condition codes
5747    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
5748    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5749    SET_VREG(r1, r9)               @ vAA<- r1
5750    GOTO_OPCODE(ip)                     @ jump to next instruction
5751    /* 10-13 instructions */
5752
5753
5754
5755/* ------------------------------ */
5756    .balign 64
5757.L_OP_AND_INT_2ADDR: /* 0xb5 */
5758/* File: armv5te/OP_AND_INT_2ADDR.S */
5759/* File: armv5te/binop2addr.S */
5760    /*
5761     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5762     * that specifies an instruction that performs "result = r0 op r1".
5763     * This could be an ARM instruction or a function call.  (If the result
5764     * comes back in a register other than r0, you can override "result".)
5765     *
5766     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5767     * vCC (r1).  Useful for integer division and modulus.
5768     *
5769     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5770     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5771     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5772     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5773     */
5774    /* binop/2addr vA, vB */
5775    mov     r9, rINST, lsr #8           @ r9<- A+
5776    mov     r3, rINST, lsr #12          @ r3<- B
5777    and     r9, r9, #15
5778    GET_VREG(r0, r9)                    @ r0<- vA
5779    GET_VREG(r1, r3)                    @ r1<- vB
5780    .if 0
5781    cmp     r1, #0                      @ is second operand zero?
5782    beq     common_errDivideByZero
5783    .endif
5784    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5785
5786                               @ optional op; may set condition codes
5787    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
5788    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5789    SET_VREG(r0, r9)               @ vAA<- r0
5790    GOTO_OPCODE(ip)                     @ jump to next instruction
5791    /* 10-13 instructions */
5792
5793
5794
5795/* ------------------------------ */
5796    .balign 64
5797.L_OP_OR_INT_2ADDR: /* 0xb6 */
5798/* File: armv5te/OP_OR_INT_2ADDR.S */
5799/* File: armv5te/binop2addr.S */
5800    /*
5801     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5802     * that specifies an instruction that performs "result = r0 op r1".
5803     * This could be an ARM instruction or a function call.  (If the result
5804     * comes back in a register other than r0, you can override "result".)
5805     *
5806     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5807     * vCC (r1).  Useful for integer division and modulus.
5808     *
5809     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5810     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5811     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5812     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5813     */
5814    /* binop/2addr vA, vB */
5815    mov     r9, rINST, lsr #8           @ r9<- A+
5816    mov     r3, rINST, lsr #12          @ r3<- B
5817    and     r9, r9, #15
5818    GET_VREG(r0, r9)                    @ r0<- vA
5819    GET_VREG(r1, r3)                    @ r1<- vB
5820    .if 0
5821    cmp     r1, #0                      @ is second operand zero?
5822    beq     common_errDivideByZero
5823    .endif
5824    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5825
5826                               @ optional op; may set condition codes
5827    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
5828    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5829    SET_VREG(r0, r9)               @ vAA<- r0
5830    GOTO_OPCODE(ip)                     @ jump to next instruction
5831    /* 10-13 instructions */
5832
5833
5834
5835/* ------------------------------ */
5836    .balign 64
5837.L_OP_XOR_INT_2ADDR: /* 0xb7 */
5838/* File: armv5te/OP_XOR_INT_2ADDR.S */
5839/* File: armv5te/binop2addr.S */
5840    /*
5841     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5842     * that specifies an instruction that performs "result = r0 op r1".
5843     * This could be an ARM instruction or a function call.  (If the result
5844     * comes back in a register other than r0, you can override "result".)
5845     *
5846     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5847     * vCC (r1).  Useful for integer division and modulus.
5848     *
5849     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5850     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5851     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5852     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5853     */
5854    /* binop/2addr vA, vB */
5855    mov     r9, rINST, lsr #8           @ r9<- A+
5856    mov     r3, rINST, lsr #12          @ r3<- B
5857    and     r9, r9, #15
5858    GET_VREG(r0, r9)                    @ r0<- vA
5859    GET_VREG(r1, r3)                    @ r1<- vB
5860    .if 0
5861    cmp     r1, #0                      @ is second operand zero?
5862    beq     common_errDivideByZero
5863    .endif
5864    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5865
5866                               @ optional op; may set condition codes
5867    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
5868    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5869    SET_VREG(r0, r9)               @ vAA<- r0
5870    GOTO_OPCODE(ip)                     @ jump to next instruction
5871    /* 10-13 instructions */
5872
5873
5874
5875/* ------------------------------ */
5876    .balign 64
5877.L_OP_SHL_INT_2ADDR: /* 0xb8 */
5878/* File: armv5te/OP_SHL_INT_2ADDR.S */
5879/* File: armv5te/binop2addr.S */
5880    /*
5881     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5882     * that specifies an instruction that performs "result = r0 op r1".
5883     * This could be an ARM instruction or a function call.  (If the result
5884     * comes back in a register other than r0, you can override "result".)
5885     *
5886     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5887     * vCC (r1).  Useful for integer division and modulus.
5888     *
5889     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5890     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5891     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5892     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5893     */
5894    /* binop/2addr vA, vB */
5895    mov     r9, rINST, lsr #8           @ r9<- A+
5896    mov     r3, rINST, lsr #12          @ r3<- B
5897    and     r9, r9, #15
5898    GET_VREG(r0, r9)                    @ r0<- vA
5899    GET_VREG(r1, r3)                    @ r1<- vB
5900    .if 0
5901    cmp     r1, #0                      @ is second operand zero?
5902    beq     common_errDivideByZero
5903    .endif
5904    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5905
5906    and     r1, r1, #31                           @ optional op; may set condition codes
5907    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
5908    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5909    SET_VREG(r0, r9)               @ vAA<- r0
5910    GOTO_OPCODE(ip)                     @ jump to next instruction
5911    /* 10-13 instructions */
5912
5913
5914
5915/* ------------------------------ */
5916    .balign 64
5917.L_OP_SHR_INT_2ADDR: /* 0xb9 */
5918/* File: armv5te/OP_SHR_INT_2ADDR.S */
5919/* File: armv5te/binop2addr.S */
5920    /*
5921     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5922     * that specifies an instruction that performs "result = r0 op r1".
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-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5930     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5931     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5932     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5933     */
5934    /* binop/2addr vA, vB */
5935    mov     r9, rINST, lsr #8           @ r9<- A+
5936    mov     r3, rINST, lsr #12          @ r3<- B
5937    and     r9, r9, #15
5938    GET_VREG(r0, r9)                    @ r0<- vA
5939    GET_VREG(r1, r3)                    @ r1<- vB
5940    .if 0
5941    cmp     r1, #0                      @ is second operand zero?
5942    beq     common_errDivideByZero
5943    .endif
5944    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5945
5946    and     r1, r1, #31                           @ optional op; may set condition codes
5947    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
5948    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5949    SET_VREG(r0, r9)               @ vAA<- r0
5950    GOTO_OPCODE(ip)                     @ jump to next instruction
5951    /* 10-13 instructions */
5952
5953
5954
5955/* ------------------------------ */
5956    .balign 64
5957.L_OP_USHR_INT_2ADDR: /* 0xba */
5958/* File: armv5te/OP_USHR_INT_2ADDR.S */
5959/* File: armv5te/binop2addr.S */
5960    /*
5961     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5962     * that specifies an instruction that performs "result = r0 op r1".
5963     * This could be an ARM instruction or a function call.  (If the result
5964     * comes back in a register other than r0, you can override "result".)
5965     *
5966     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5967     * vCC (r1).  Useful for integer division and modulus.
5968     *
5969     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5970     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5971     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5972     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5973     */
5974    /* binop/2addr vA, vB */
5975    mov     r9, rINST, lsr #8           @ r9<- A+
5976    mov     r3, rINST, lsr #12          @ r3<- B
5977    and     r9, r9, #15
5978    GET_VREG(r0, r9)                    @ r0<- vA
5979    GET_VREG(r1, r3)                    @ r1<- vB
5980    .if 0
5981    cmp     r1, #0                      @ is second operand zero?
5982    beq     common_errDivideByZero
5983    .endif
5984    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5985
5986    and     r1, r1, #31                           @ optional op; may set condition codes
5987    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
5988    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5989    SET_VREG(r0, r9)               @ vAA<- r0
5990    GOTO_OPCODE(ip)                     @ jump to next instruction
5991    /* 10-13 instructions */
5992
5993
5994
5995/* ------------------------------ */
5996    .balign 64
5997.L_OP_ADD_LONG_2ADDR: /* 0xbb */
5998/* File: armv5te/OP_ADD_LONG_2ADDR.S */
5999/* File: armv5te/binopWide2addr.S */
6000    /*
6001     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6002     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6003     * This could be an ARM instruction or a function call.  (If the result
6004     * comes back in a register other than r0, you can override "result".)
6005     *
6006     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6007     * vCC (r1).  Useful for integer division and modulus.
6008     *
6009     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6010     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6011     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6012     *      rem-double/2addr
6013     */
6014    /* binop/2addr vA, vB */
6015    mov     r9, rINST, lsr #8           @ r9<- A+
6016    mov     r1, rINST, lsr #12          @ r1<- B
6017    and     r9, r9, #15
6018    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6019    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6020    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6021    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6022    .if 0
6023    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6024    beq     common_errDivideByZero
6025    .endif
6026    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6027
6028    adds    r0, r0, r2                           @ optional op; may set condition codes
6029    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
6030    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6031    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6032    GOTO_OPCODE(ip)                     @ jump to next instruction
6033    /* 12-15 instructions */
6034
6035
6036
6037/* ------------------------------ */
6038    .balign 64
6039.L_OP_SUB_LONG_2ADDR: /* 0xbc */
6040/* File: armv5te/OP_SUB_LONG_2ADDR.S */
6041/* File: armv5te/binopWide2addr.S */
6042    /*
6043     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6044     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6045     * This could be an ARM instruction or a function call.  (If the result
6046     * comes back in a register other than r0, you can override "result".)
6047     *
6048     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6049     * vCC (r1).  Useful for integer division and modulus.
6050     *
6051     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6052     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6053     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6054     *      rem-double/2addr
6055     */
6056    /* binop/2addr vA, vB */
6057    mov     r9, rINST, lsr #8           @ r9<- A+
6058    mov     r1, rINST, lsr #12          @ r1<- B
6059    and     r9, r9, #15
6060    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6061    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6062    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6063    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6064    .if 0
6065    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6066    beq     common_errDivideByZero
6067    .endif
6068    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6069
6070    subs    r0, r0, r2                           @ optional op; may set condition codes
6071    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
6072    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6073    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6074    GOTO_OPCODE(ip)                     @ jump to next instruction
6075    /* 12-15 instructions */
6076
6077
6078
6079/* ------------------------------ */
6080    .balign 64
6081.L_OP_MUL_LONG_2ADDR: /* 0xbd */
6082/* File: armv5te/OP_MUL_LONG_2ADDR.S */
6083    /*
6084     * Signed 64-bit integer multiply, "/2addr" version.
6085     *
6086     * See OP_MUL_LONG for an explanation.
6087     *
6088     * We get a little tight on registers, so to avoid looking up &fp[A]
6089     * again we stuff it into rINST.
6090     */
6091    /* mul-long/2addr vA, vB */
6092    mov     r9, rINST, lsr #8           @ r9<- A+
6093    mov     r1, rINST, lsr #12          @ r1<- B
6094    and     r9, r9, #15
6095    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6096    add     rINST, rFP, r9, lsl #2      @ rINST<- &fp[A]
6097    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6098    ldmia   rINST, {r0-r1}              @ r0/r1<- vAA/vAA+1
6099    mul     ip, r2, r1                  @  ip<- ZxW
6100    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
6101    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
6102    mov     r0, rINST                   @ r0<- &fp[A] (free up rINST)
6103    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6104    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
6105    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6106    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
6107    GOTO_OPCODE(ip)                     @ jump to next instruction
6108
6109
6110/* ------------------------------ */
6111    .balign 64
6112.L_OP_DIV_LONG_2ADDR: /* 0xbe */
6113/* File: armv5te/OP_DIV_LONG_2ADDR.S */
6114/* File: armv5te/binopWide2addr.S */
6115    /*
6116     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6117     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6118     * This could be an ARM instruction or a function call.  (If the result
6119     * comes back in a register other than r0, you can override "result".)
6120     *
6121     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6122     * vCC (r1).  Useful for integer division and modulus.
6123     *
6124     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6125     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6126     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6127     *      rem-double/2addr
6128     */
6129    /* binop/2addr vA, vB */
6130    mov     r9, rINST, lsr #8           @ r9<- A+
6131    mov     r1, rINST, lsr #12          @ r1<- B
6132    and     r9, r9, #15
6133    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6134    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6135    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6136    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6137    .if 1
6138    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6139    beq     common_errDivideByZero
6140    .endif
6141    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6142
6143                               @ optional op; may set condition codes
6144    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
6145    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6146    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6147    GOTO_OPCODE(ip)                     @ jump to next instruction
6148    /* 12-15 instructions */
6149
6150
6151
6152/* ------------------------------ */
6153    .balign 64
6154.L_OP_REM_LONG_2ADDR: /* 0xbf */
6155/* File: armv5te/OP_REM_LONG_2ADDR.S */
6156/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
6157/* File: armv5te/binopWide2addr.S */
6158    /*
6159     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6160     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6161     * This could be an ARM instruction or a function call.  (If the result
6162     * comes back in a register other than r0, you can override "result".)
6163     *
6164     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6165     * vCC (r1).  Useful for integer division and modulus.
6166     *
6167     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6168     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6169     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6170     *      rem-double/2addr
6171     */
6172    /* binop/2addr vA, vB */
6173    mov     r9, rINST, lsr #8           @ r9<- A+
6174    mov     r1, rINST, lsr #12          @ r1<- B
6175    and     r9, r9, #15
6176    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6177    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6178    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6179    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6180    .if 1
6181    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6182    beq     common_errDivideByZero
6183    .endif
6184    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6185
6186                               @ optional op; may set condition codes
6187    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
6188    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6189    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
6190    GOTO_OPCODE(ip)                     @ jump to next instruction
6191    /* 12-15 instructions */
6192
6193
6194
6195/* ------------------------------ */
6196    .balign 64
6197.L_OP_AND_LONG_2ADDR: /* 0xc0 */
6198/* File: armv5te/OP_AND_LONG_2ADDR.S */
6199/* File: armv5te/binopWide2addr.S */
6200    /*
6201     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6202     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6203     * This could be an ARM instruction or a function call.  (If the result
6204     * comes back in a register other than r0, you can override "result".)
6205     *
6206     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6207     * vCC (r1).  Useful for integer division and modulus.
6208     *
6209     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6210     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6211     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6212     *      rem-double/2addr
6213     */
6214    /* binop/2addr vA, vB */
6215    mov     r9, rINST, lsr #8           @ r9<- A+
6216    mov     r1, rINST, lsr #12          @ r1<- B
6217    and     r9, r9, #15
6218    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6219    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6220    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6221    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6222    .if 0
6223    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6224    beq     common_errDivideByZero
6225    .endif
6226    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6227
6228    and     r0, r0, r2                           @ optional op; may set condition codes
6229    and     r1, r1, r3                              @ result<- op, r0-r3 changed
6230    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6231    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6232    GOTO_OPCODE(ip)                     @ jump to next instruction
6233    /* 12-15 instructions */
6234
6235
6236
6237/* ------------------------------ */
6238    .balign 64
6239.L_OP_OR_LONG_2ADDR: /* 0xc1 */
6240/* File: armv5te/OP_OR_LONG_2ADDR.S */
6241/* File: armv5te/binopWide2addr.S */
6242    /*
6243     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6244     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6245     * This could be an ARM instruction or a function call.  (If the result
6246     * comes back in a register other than r0, you can override "result".)
6247     *
6248     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6249     * vCC (r1).  Useful for integer division and modulus.
6250     *
6251     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6252     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6253     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6254     *      rem-double/2addr
6255     */
6256    /* binop/2addr vA, vB */
6257    mov     r9, rINST, lsr #8           @ r9<- A+
6258    mov     r1, rINST, lsr #12          @ r1<- B
6259    and     r9, r9, #15
6260    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6261    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6262    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6263    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6264    .if 0
6265    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6266    beq     common_errDivideByZero
6267    .endif
6268    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6269
6270    orr     r0, r0, r2                           @ optional op; may set condition codes
6271    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
6272    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6273    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6274    GOTO_OPCODE(ip)                     @ jump to next instruction
6275    /* 12-15 instructions */
6276
6277
6278
6279/* ------------------------------ */
6280    .balign 64
6281.L_OP_XOR_LONG_2ADDR: /* 0xc2 */
6282/* File: armv5te/OP_XOR_LONG_2ADDR.S */
6283/* File: armv5te/binopWide2addr.S */
6284    /*
6285     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6286     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6287     * This could be an ARM instruction or a function call.  (If the result
6288     * comes back in a register other than r0, you can override "result".)
6289     *
6290     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6291     * vCC (r1).  Useful for integer division and modulus.
6292     *
6293     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6294     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6295     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6296     *      rem-double/2addr
6297     */
6298    /* binop/2addr vA, vB */
6299    mov     r9, rINST, lsr #8           @ r9<- A+
6300    mov     r1, rINST, lsr #12          @ r1<- B
6301    and     r9, r9, #15
6302    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6303    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6304    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6305    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6306    .if 0
6307    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6308    beq     common_errDivideByZero
6309    .endif
6310    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6311
6312    eor     r0, r0, r2                           @ optional op; may set condition codes
6313    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
6314    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6315    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6316    GOTO_OPCODE(ip)                     @ jump to next instruction
6317    /* 12-15 instructions */
6318
6319
6320
6321/* ------------------------------ */
6322    .balign 64
6323.L_OP_SHL_LONG_2ADDR: /* 0xc3 */
6324/* File: armv5te/OP_SHL_LONG_2ADDR.S */
6325    /*
6326     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6327     * 32-bit shift distance.
6328     */
6329    /* shl-long/2addr vA, vB */
6330    mov     r9, rINST, lsr #8           @ r9<- A+
6331    mov     r3, rINST, lsr #12          @ r3<- B
6332    and     r9, r9, #15
6333    GET_VREG(r2, r3)                    @ r2<- vB
6334    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6335    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6336    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6337
6338    mov     r1, r1, asl r2              @  r1<- r1 << r2
6339    rsb     r3, r2, #32                 @  r3<- 32 - r2
6340    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
6341    subs    ip, r2, #32                 @  ip<- r2 - 32
6342    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6343    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
6344    mov     r0, r0, asl r2              @  r0<- r0 << r2
6345    b       .LOP_SHL_LONG_2ADDR_finish
6346
6347/* ------------------------------ */
6348    .balign 64
6349.L_OP_SHR_LONG_2ADDR: /* 0xc4 */
6350/* File: armv5te/OP_SHR_LONG_2ADDR.S */
6351    /*
6352     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6353     * 32-bit shift distance.
6354     */
6355    /* shr-long/2addr vA, vB */
6356    mov     r9, rINST, lsr #8           @ r9<- A+
6357    mov     r3, rINST, lsr #12          @ r3<- B
6358    and     r9, r9, #15
6359    GET_VREG(r2, r3)                    @ r2<- vB
6360    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6361    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6362    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6363
6364    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6365    rsb     r3, r2, #32                 @  r3<- 32 - r2
6366    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6367    subs    ip, r2, #32                 @  ip<- r2 - 32
6368    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6369    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
6370    mov     r1, r1, asr r2              @  r1<- r1 >> r2
6371    b       .LOP_SHR_LONG_2ADDR_finish
6372
6373/* ------------------------------ */
6374    .balign 64
6375.L_OP_USHR_LONG_2ADDR: /* 0xc5 */
6376/* File: armv5te/OP_USHR_LONG_2ADDR.S */
6377    /*
6378     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6379     * 32-bit shift distance.
6380     */
6381    /* ushr-long/2addr vA, vB */
6382    mov     r9, rINST, lsr #8           @ r9<- A+
6383    mov     r3, rINST, lsr #12          @ r3<- B
6384    and     r9, r9, #15
6385    GET_VREG(r2, r3)                    @ r2<- vB
6386    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6387    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6388    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6389
6390    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6391    rsb     r3, r2, #32                 @  r3<- 32 - r2
6392    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6393    subs    ip, r2, #32                 @  ip<- r2 - 32
6394    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6395    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
6396    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
6397    b       .LOP_USHR_LONG_2ADDR_finish
6398
6399/* ------------------------------ */
6400    .balign 64
6401.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
6402/* File: armv5te/OP_ADD_FLOAT_2ADDR.S */
6403/* File: armv5te/binop2addr.S */
6404    /*
6405     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6406     * that specifies an instruction that performs "result = r0 op r1".
6407     * This could be an ARM instruction or a function call.  (If the result
6408     * comes back in a register other than r0, you can override "result".)
6409     *
6410     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6411     * vCC (r1).  Useful for integer division and modulus.
6412     *
6413     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6414     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6415     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6416     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6417     */
6418    /* binop/2addr vA, vB */
6419    mov     r9, rINST, lsr #8           @ r9<- A+
6420    mov     r3, rINST, lsr #12          @ r3<- B
6421    and     r9, r9, #15
6422    GET_VREG(r0, r9)                    @ r0<- vA
6423    GET_VREG(r1, r3)                    @ r1<- vB
6424    .if 0
6425    cmp     r1, #0                      @ is second operand zero?
6426    beq     common_errDivideByZero
6427    .endif
6428    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6429
6430                               @ optional op; may set condition codes
6431    bl      __aeabi_fadd                              @ r0<- op, r0-r3 changed
6432    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6433    SET_VREG(r0, r9)               @ vAA<- r0
6434    GOTO_OPCODE(ip)                     @ jump to next instruction
6435    /* 10-13 instructions */
6436
6437
6438
6439/* ------------------------------ */
6440    .balign 64
6441.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
6442/* File: armv5te/OP_SUB_FLOAT_2ADDR.S */
6443/* File: armv5te/binop2addr.S */
6444    /*
6445     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6446     * that specifies an instruction that performs "result = r0 op r1".
6447     * This could be an ARM instruction or a function call.  (If the result
6448     * comes back in a register other than r0, you can override "result".)
6449     *
6450     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6451     * vCC (r1).  Useful for integer division and modulus.
6452     *
6453     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6454     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6455     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6456     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6457     */
6458    /* binop/2addr vA, vB */
6459    mov     r9, rINST, lsr #8           @ r9<- A+
6460    mov     r3, rINST, lsr #12          @ r3<- B
6461    and     r9, r9, #15
6462    GET_VREG(r0, r9)                    @ r0<- vA
6463    GET_VREG(r1, r3)                    @ r1<- vB
6464    .if 0
6465    cmp     r1, #0                      @ is second operand zero?
6466    beq     common_errDivideByZero
6467    .endif
6468    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6469
6470                               @ optional op; may set condition codes
6471    bl      __aeabi_fsub                              @ r0<- op, r0-r3 changed
6472    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6473    SET_VREG(r0, r9)               @ vAA<- r0
6474    GOTO_OPCODE(ip)                     @ jump to next instruction
6475    /* 10-13 instructions */
6476
6477
6478
6479/* ------------------------------ */
6480    .balign 64
6481.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
6482/* File: armv5te/OP_MUL_FLOAT_2ADDR.S */
6483/* File: armv5te/binop2addr.S */
6484    /*
6485     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6486     * that specifies an instruction that performs "result = r0 op r1".
6487     * This could be an ARM instruction or a function call.  (If the result
6488     * comes back in a register other than r0, you can override "result".)
6489     *
6490     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6491     * vCC (r1).  Useful for integer division and modulus.
6492     *
6493     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6494     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6495     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6496     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6497     */
6498    /* binop/2addr vA, vB */
6499    mov     r9, rINST, lsr #8           @ r9<- A+
6500    mov     r3, rINST, lsr #12          @ r3<- B
6501    and     r9, r9, #15
6502    GET_VREG(r0, r9)                    @ r0<- vA
6503    GET_VREG(r1, r3)                    @ r1<- vB
6504    .if 0
6505    cmp     r1, #0                      @ is second operand zero?
6506    beq     common_errDivideByZero
6507    .endif
6508    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6509
6510                               @ optional op; may set condition codes
6511    bl      __aeabi_fmul                              @ r0<- op, r0-r3 changed
6512    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6513    SET_VREG(r0, r9)               @ vAA<- r0
6514    GOTO_OPCODE(ip)                     @ jump to next instruction
6515    /* 10-13 instructions */
6516
6517
6518
6519/* ------------------------------ */
6520    .balign 64
6521.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
6522/* File: armv5te/OP_DIV_FLOAT_2ADDR.S */
6523/* File: armv5te/binop2addr.S */
6524    /*
6525     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6526     * that specifies an instruction that performs "result = r0 op r1".
6527     * This could be an ARM instruction or a function call.  (If the result
6528     * comes back in a register other than r0, you can override "result".)
6529     *
6530     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6531     * vCC (r1).  Useful for integer division and modulus.
6532     *
6533     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6534     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6535     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6536     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6537     */
6538    /* binop/2addr vA, vB */
6539    mov     r9, rINST, lsr #8           @ r9<- A+
6540    mov     r3, rINST, lsr #12          @ r3<- B
6541    and     r9, r9, #15
6542    GET_VREG(r0, r9)                    @ r0<- vA
6543    GET_VREG(r1, r3)                    @ r1<- vB
6544    .if 0
6545    cmp     r1, #0                      @ is second operand zero?
6546    beq     common_errDivideByZero
6547    .endif
6548    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6549
6550                               @ optional op; may set condition codes
6551    bl      __aeabi_fdiv                              @ r0<- op, r0-r3 changed
6552    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6553    SET_VREG(r0, r9)               @ vAA<- r0
6554    GOTO_OPCODE(ip)                     @ jump to next instruction
6555    /* 10-13 instructions */
6556
6557
6558
6559/* ------------------------------ */
6560    .balign 64
6561.L_OP_REM_FLOAT_2ADDR: /* 0xca */
6562/* File: armv5te/OP_REM_FLOAT_2ADDR.S */
6563/* EABI doesn't define a float remainder function, but libm does */
6564/* File: armv5te/binop2addr.S */
6565    /*
6566     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6567     * that specifies an instruction that performs "result = r0 op r1".
6568     * This could be an ARM instruction or a function call.  (If the result
6569     * comes back in a register other than r0, you can override "result".)
6570     *
6571     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6572     * vCC (r1).  Useful for integer division and modulus.
6573     *
6574     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6575     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6576     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6577     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6578     */
6579    /* binop/2addr vA, vB */
6580    mov     r9, rINST, lsr #8           @ r9<- A+
6581    mov     r3, rINST, lsr #12          @ r3<- B
6582    and     r9, r9, #15
6583    GET_VREG(r0, r9)                    @ r0<- vA
6584    GET_VREG(r1, r3)                    @ r1<- vB
6585    .if 0
6586    cmp     r1, #0                      @ is second operand zero?
6587    beq     common_errDivideByZero
6588    .endif
6589    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6590
6591                               @ optional op; may set condition codes
6592    bl      fmodf                              @ r0<- op, r0-r3 changed
6593    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6594    SET_VREG(r0, r9)               @ vAA<- r0
6595    GOTO_OPCODE(ip)                     @ jump to next instruction
6596    /* 10-13 instructions */
6597
6598
6599
6600/* ------------------------------ */
6601    .balign 64
6602.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
6603/* File: armv5te/OP_ADD_DOUBLE_2ADDR.S */
6604/* File: armv5te/binopWide2addr.S */
6605    /*
6606     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6607     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6608     * This could be an ARM instruction or a function call.  (If the result
6609     * comes back in a register other than r0, you can override "result".)
6610     *
6611     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6612     * vCC (r1).  Useful for integer division and modulus.
6613     *
6614     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6615     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6616     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6617     *      rem-double/2addr
6618     */
6619    /* binop/2addr vA, vB */
6620    mov     r9, rINST, lsr #8           @ r9<- A+
6621    mov     r1, rINST, lsr #12          @ r1<- B
6622    and     r9, r9, #15
6623    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6624    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6625    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6626    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6627    .if 0
6628    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6629    beq     common_errDivideByZero
6630    .endif
6631    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6632
6633                               @ optional op; may set condition codes
6634    bl      __aeabi_dadd                              @ result<- op, r0-r3 changed
6635    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6636    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6637    GOTO_OPCODE(ip)                     @ jump to next instruction
6638    /* 12-15 instructions */
6639
6640
6641
6642/* ------------------------------ */
6643    .balign 64
6644.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
6645/* File: armv5te/OP_SUB_DOUBLE_2ADDR.S */
6646/* File: armv5te/binopWide2addr.S */
6647    /*
6648     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6649     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6650     * This could be an ARM instruction or a function call.  (If the result
6651     * comes back in a register other than r0, you can override "result".)
6652     *
6653     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6654     * vCC (r1).  Useful for integer division and modulus.
6655     *
6656     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6657     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6658     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6659     *      rem-double/2addr
6660     */
6661    /* binop/2addr vA, vB */
6662    mov     r9, rINST, lsr #8           @ r9<- A+
6663    mov     r1, rINST, lsr #12          @ r1<- B
6664    and     r9, r9, #15
6665    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6666    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6667    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6668    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6669    .if 0
6670    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6671    beq     common_errDivideByZero
6672    .endif
6673    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6674
6675                               @ optional op; may set condition codes
6676    bl      __aeabi_dsub                              @ result<- op, r0-r3 changed
6677    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6678    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6679    GOTO_OPCODE(ip)                     @ jump to next instruction
6680    /* 12-15 instructions */
6681
6682
6683
6684/* ------------------------------ */
6685    .balign 64
6686.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
6687/* File: armv5te/OP_MUL_DOUBLE_2ADDR.S */
6688/* File: armv5te/binopWide2addr.S */
6689    /*
6690     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6691     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6692     * This could be an ARM instruction or a function call.  (If the result
6693     * comes back in a register other than r0, you can override "result".)
6694     *
6695     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6696     * vCC (r1).  Useful for integer division and modulus.
6697     *
6698     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6699     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6700     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6701     *      rem-double/2addr
6702     */
6703    /* binop/2addr vA, vB */
6704    mov     r9, rINST, lsr #8           @ r9<- A+
6705    mov     r1, rINST, lsr #12          @ r1<- B
6706    and     r9, r9, #15
6707    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6708    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6709    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6710    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6711    .if 0
6712    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6713    beq     common_errDivideByZero
6714    .endif
6715    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6716
6717                               @ optional op; may set condition codes
6718    bl      __aeabi_dmul                              @ result<- op, r0-r3 changed
6719    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6720    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6721    GOTO_OPCODE(ip)                     @ jump to next instruction
6722    /* 12-15 instructions */
6723
6724
6725
6726/* ------------------------------ */
6727    .balign 64
6728.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
6729/* File: armv5te/OP_DIV_DOUBLE_2ADDR.S */
6730/* File: armv5te/binopWide2addr.S */
6731    /*
6732     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6733     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6734     * This could be an ARM instruction or a function call.  (If the result
6735     * comes back in a register other than r0, you can override "result".)
6736     *
6737     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6738     * vCC (r1).  Useful for integer division and modulus.
6739     *
6740     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6741     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6742     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6743     *      rem-double/2addr
6744     */
6745    /* binop/2addr vA, vB */
6746    mov     r9, rINST, lsr #8           @ r9<- A+
6747    mov     r1, rINST, lsr #12          @ r1<- B
6748    and     r9, r9, #15
6749    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6750    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6751    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6752    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6753    .if 0
6754    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6755    beq     common_errDivideByZero
6756    .endif
6757    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6758
6759                               @ optional op; may set condition codes
6760    bl      __aeabi_ddiv                              @ result<- op, r0-r3 changed
6761    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6762    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6763    GOTO_OPCODE(ip)                     @ jump to next instruction
6764    /* 12-15 instructions */
6765
6766
6767
6768/* ------------------------------ */
6769    .balign 64
6770.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
6771/* File: armv5te/OP_REM_DOUBLE_2ADDR.S */
6772/* EABI doesn't define a double remainder function, but libm does */
6773/* File: armv5te/binopWide2addr.S */
6774    /*
6775     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6776     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6777     * This could be an ARM instruction or a function call.  (If the result
6778     * comes back in a register other than r0, you can override "result".)
6779     *
6780     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6781     * vCC (r1).  Useful for integer division and modulus.
6782     *
6783     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6784     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6785     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6786     *      rem-double/2addr
6787     */
6788    /* binop/2addr vA, vB */
6789    mov     r9, rINST, lsr #8           @ r9<- A+
6790    mov     r1, rINST, lsr #12          @ r1<- B
6791    and     r9, r9, #15
6792    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6793    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6794    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6795    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6796    .if 0
6797    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6798    beq     common_errDivideByZero
6799    .endif
6800    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6801
6802                               @ optional op; may set condition codes
6803    bl      fmod                              @ result<- op, r0-r3 changed
6804    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6805    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6806    GOTO_OPCODE(ip)                     @ jump to next instruction
6807    /* 12-15 instructions */
6808
6809
6810
6811/* ------------------------------ */
6812    .balign 64
6813.L_OP_ADD_INT_LIT16: /* 0xd0 */
6814/* File: armv5te/OP_ADD_INT_LIT16.S */
6815/* File: armv5te/binopLit16.S */
6816    /*
6817     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6818     * that specifies an instruction that performs "result = r0 op r1".
6819     * This could be an ARM instruction or a function call.  (If the result
6820     * comes back in a register other than r0, you can override "result".)
6821     *
6822     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6823     * vCC (r1).  Useful for integer division and modulus.
6824     *
6825     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6826     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6827     */
6828    /* binop/lit16 vA, vB, #+CCCC */
6829    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6830    mov     r2, rINST, lsr #12          @ r2<- B
6831    mov     r9, rINST, lsr #8           @ r9<- A+
6832    GET_VREG(r0, r2)                    @ r0<- vB
6833    and     r9, r9, #15
6834    .if 0
6835    cmp     r1, #0                      @ is second operand zero?
6836    beq     common_errDivideByZero
6837    .endif
6838    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6839
6840    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6841    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6842    SET_VREG(r0, r9)               @ vAA<- r0
6843    GOTO_OPCODE(ip)                     @ jump to next instruction
6844    /* 10-13 instructions */
6845
6846
6847
6848/* ------------------------------ */
6849    .balign 64
6850.L_OP_RSUB_INT: /* 0xd1 */
6851/* File: armv5te/OP_RSUB_INT.S */
6852/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
6853/* File: armv5te/binopLit16.S */
6854    /*
6855     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6856     * that specifies an instruction that performs "result = r0 op r1".
6857     * This could be an ARM instruction or a function call.  (If the result
6858     * comes back in a register other than r0, you can override "result".)
6859     *
6860     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6861     * vCC (r1).  Useful for integer division and modulus.
6862     *
6863     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6864     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6865     */
6866    /* binop/lit16 vA, vB, #+CCCC */
6867    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6868    mov     r2, rINST, lsr #12          @ r2<- B
6869    mov     r9, rINST, lsr #8           @ r9<- A+
6870    GET_VREG(r0, r2)                    @ r0<- vB
6871    and     r9, r9, #15
6872    .if 0
6873    cmp     r1, #0                      @ is second operand zero?
6874    beq     common_errDivideByZero
6875    .endif
6876    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6877
6878    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6879    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6880    SET_VREG(r0, r9)               @ vAA<- r0
6881    GOTO_OPCODE(ip)                     @ jump to next instruction
6882    /* 10-13 instructions */
6883
6884
6885
6886/* ------------------------------ */
6887    .balign 64
6888.L_OP_MUL_INT_LIT16: /* 0xd2 */
6889/* File: armv5te/OP_MUL_INT_LIT16.S */
6890/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6891/* File: armv5te/binopLit16.S */
6892    /*
6893     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6894     * that specifies an instruction that performs "result = r0 op r1".
6895     * This could be an ARM instruction or a function call.  (If the result
6896     * comes back in a register other than r0, you can override "result".)
6897     *
6898     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6899     * vCC (r1).  Useful for integer division and modulus.
6900     *
6901     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6902     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6903     */
6904    /* binop/lit16 vA, vB, #+CCCC */
6905    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6906    mov     r2, rINST, lsr #12          @ r2<- B
6907    mov     r9, rINST, lsr #8           @ r9<- A+
6908    GET_VREG(r0, r2)                    @ r0<- vB
6909    and     r9, r9, #15
6910    .if 0
6911    cmp     r1, #0                      @ is second operand zero?
6912    beq     common_errDivideByZero
6913    .endif
6914    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6915
6916    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6917    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6918    SET_VREG(r0, r9)               @ vAA<- r0
6919    GOTO_OPCODE(ip)                     @ jump to next instruction
6920    /* 10-13 instructions */
6921
6922
6923
6924/* ------------------------------ */
6925    .balign 64
6926.L_OP_DIV_INT_LIT16: /* 0xd3 */
6927/* File: armv5te/OP_DIV_INT_LIT16.S */
6928/* File: armv5te/binopLit16.S */
6929    /*
6930     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6931     * that specifies an instruction that performs "result = r0 op r1".
6932     * This could be an ARM instruction or a function call.  (If the result
6933     * comes back in a register other than r0, you can override "result".)
6934     *
6935     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6936     * vCC (r1).  Useful for integer division and modulus.
6937     *
6938     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6939     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6940     */
6941    /* binop/lit16 vA, vB, #+CCCC */
6942    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6943    mov     r2, rINST, lsr #12          @ r2<- B
6944    mov     r9, rINST, lsr #8           @ r9<- A+
6945    GET_VREG(r0, r2)                    @ r0<- vB
6946    and     r9, r9, #15
6947    .if 1
6948    cmp     r1, #0                      @ is second operand zero?
6949    beq     common_errDivideByZero
6950    .endif
6951    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6952
6953    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6954    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6955    SET_VREG(r0, r9)               @ vAA<- r0
6956    GOTO_OPCODE(ip)                     @ jump to next instruction
6957    /* 10-13 instructions */
6958
6959
6960
6961/* ------------------------------ */
6962    .balign 64
6963.L_OP_REM_INT_LIT16: /* 0xd4 */
6964/* File: armv5te/OP_REM_INT_LIT16.S */
6965/* idivmod returns quotient in r0 and remainder in r1 */
6966/* File: armv5te/binopLit16.S */
6967    /*
6968     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6969     * that specifies an instruction that performs "result = r0 op r1".
6970     * This could be an ARM instruction or a function call.  (If the result
6971     * comes back in a register other than r0, you can override "result".)
6972     *
6973     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6974     * vCC (r1).  Useful for integer division and modulus.
6975     *
6976     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6977     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6978     */
6979    /* binop/lit16 vA, vB, #+CCCC */
6980    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6981    mov     r2, rINST, lsr #12          @ r2<- B
6982    mov     r9, rINST, lsr #8           @ r9<- A+
6983    GET_VREG(r0, r2)                    @ r0<- vB
6984    and     r9, r9, #15
6985    .if 1
6986    cmp     r1, #0                      @ is second operand zero?
6987    beq     common_errDivideByZero
6988    .endif
6989    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6990
6991    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6992    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6993    SET_VREG(r1, r9)               @ vAA<- r1
6994    GOTO_OPCODE(ip)                     @ jump to next instruction
6995    /* 10-13 instructions */
6996
6997
6998
6999/* ------------------------------ */
7000    .balign 64
7001.L_OP_AND_INT_LIT16: /* 0xd5 */
7002/* File: armv5te/OP_AND_INT_LIT16.S */
7003/* File: armv5te/binopLit16.S */
7004    /*
7005     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
7006     * that specifies an instruction that performs "result = r0 op r1".
7007     * This could be an ARM instruction or a function call.  (If the result
7008     * comes back in a register other than r0, you can override "result".)
7009     *
7010     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7011     * vCC (r1).  Useful for integer division and modulus.
7012     *
7013     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
7014     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
7015     */
7016    /* binop/lit16 vA, vB, #+CCCC */
7017    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
7018    mov     r2, rINST, lsr #12          @ r2<- B
7019    mov     r9, rINST, lsr #8           @ r9<- A+
7020    GET_VREG(r0, r2)                    @ r0<- vB
7021    and     r9, r9, #15
7022    .if 0
7023    cmp     r1, #0                      @ is second operand zero?
7024    beq     common_errDivideByZero
7025    .endif
7026    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7027
7028    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
7029    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7030    SET_VREG(r0, r9)               @ vAA<- r0
7031    GOTO_OPCODE(ip)                     @ jump to next instruction
7032    /* 10-13 instructions */
7033
7034
7035
7036/* ------------------------------ */
7037    .balign 64
7038.L_OP_OR_INT_LIT16: /* 0xd6 */
7039/* File: armv5te/OP_OR_INT_LIT16.S */
7040/* File: armv5te/binopLit16.S */
7041    /*
7042     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
7043     * that specifies an instruction that performs "result = r0 op r1".
7044     * This could be an ARM instruction or a function call.  (If the result
7045     * comes back in a register other than r0, you can override "result".)
7046     *
7047     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7048     * vCC (r1).  Useful for integer division and modulus.
7049     *
7050     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
7051     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
7052     */
7053    /* binop/lit16 vA, vB, #+CCCC */
7054    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
7055    mov     r2, rINST, lsr #12          @ r2<- B
7056    mov     r9, rINST, lsr #8           @ r9<- A+
7057    GET_VREG(r0, r2)                    @ r0<- vB
7058    and     r9, r9, #15
7059    .if 0
7060    cmp     r1, #0                      @ is second operand zero?
7061    beq     common_errDivideByZero
7062    .endif
7063    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7064
7065    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
7066    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7067    SET_VREG(r0, r9)               @ vAA<- r0
7068    GOTO_OPCODE(ip)                     @ jump to next instruction
7069    /* 10-13 instructions */
7070
7071
7072
7073/* ------------------------------ */
7074    .balign 64
7075.L_OP_XOR_INT_LIT16: /* 0xd7 */
7076/* File: armv5te/OP_XOR_INT_LIT16.S */
7077/* File: armv5te/binopLit16.S */
7078    /*
7079     * Generic 32-bit "lit16" 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/lit16, rsub-int, mul-int/lit16, div-int/lit16,
7088     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
7089     */
7090    /* binop/lit16 vA, vB, #+CCCC */
7091    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
7092    mov     r2, rINST, lsr #12          @ r2<- B
7093    mov     r9, rINST, lsr #8           @ r9<- A+
7094    GET_VREG(r0, r2)                    @ r0<- vB
7095    and     r9, r9, #15
7096    .if 0
7097    cmp     r1, #0                      @ is second operand zero?
7098    beq     common_errDivideByZero
7099    .endif
7100    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7101
7102    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
7103    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7104    SET_VREG(r0, r9)               @ vAA<- r0
7105    GOTO_OPCODE(ip)                     @ jump to next instruction
7106    /* 10-13 instructions */
7107
7108
7109
7110/* ------------------------------ */
7111    .balign 64
7112.L_OP_ADD_INT_LIT8: /* 0xd8 */
7113/* File: armv5te/OP_ADD_INT_LIT8.S */
7114/* File: armv5te/binopLit8.S */
7115    /*
7116     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7117     * that specifies an instruction that performs "result = r0 op r1".
7118     * This could be an ARM instruction or a function call.  (If the result
7119     * comes back in a register other than r0, you can override "result".)
7120     *
7121     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7122     * vCC (r1).  Useful for integer division and modulus.
7123     *
7124     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7125     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7126     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7127     */
7128    /* binop/lit8 vAA, vBB, #+CC */
7129    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7130    mov     r9, rINST, lsr #8           @ r9<- AA
7131    and     r2, r3, #255                @ r2<- BB
7132    GET_VREG(r0, r2)                    @ r0<- vBB
7133    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7134    .if 0
7135    @cmp     r1, #0                      @ is second operand zero?
7136    beq     common_errDivideByZero
7137    .endif
7138    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7139
7140                               @ optional op; may set condition codes
7141    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
7142    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7143    SET_VREG(r0, r9)               @ vAA<- r0
7144    GOTO_OPCODE(ip)                     @ jump to next instruction
7145    /* 10-12 instructions */
7146
7147
7148
7149/* ------------------------------ */
7150    .balign 64
7151.L_OP_RSUB_INT_LIT8: /* 0xd9 */
7152/* File: armv5te/OP_RSUB_INT_LIT8.S */
7153/* File: armv5te/binopLit8.S */
7154    /*
7155     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7156     * that specifies an instruction that performs "result = r0 op r1".
7157     * This could be an ARM instruction or a function call.  (If the result
7158     * comes back in a register other than r0, you can override "result".)
7159     *
7160     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7161     * vCC (r1).  Useful for integer division and modulus.
7162     *
7163     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7164     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7165     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7166     */
7167    /* binop/lit8 vAA, vBB, #+CC */
7168    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7169    mov     r9, rINST, lsr #8           @ r9<- AA
7170    and     r2, r3, #255                @ r2<- BB
7171    GET_VREG(r0, r2)                    @ r0<- vBB
7172    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7173    .if 0
7174    @cmp     r1, #0                      @ is second operand zero?
7175    beq     common_errDivideByZero
7176    .endif
7177    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7178
7179                               @ optional op; may set condition codes
7180    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
7181    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7182    SET_VREG(r0, r9)               @ vAA<- r0
7183    GOTO_OPCODE(ip)                     @ jump to next instruction
7184    /* 10-12 instructions */
7185
7186
7187
7188/* ------------------------------ */
7189    .balign 64
7190.L_OP_MUL_INT_LIT8: /* 0xda */
7191/* File: armv5te/OP_MUL_INT_LIT8.S */
7192/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
7193/* File: armv5te/binopLit8.S */
7194    /*
7195     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7196     * that specifies an instruction that performs "result = r0 op r1".
7197     * This could be an ARM instruction or a function call.  (If the result
7198     * comes back in a register other than r0, you can override "result".)
7199     *
7200     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7201     * vCC (r1).  Useful for integer division and modulus.
7202     *
7203     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7204     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7205     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7206     */
7207    /* binop/lit8 vAA, vBB, #+CC */
7208    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7209    mov     r9, rINST, lsr #8           @ r9<- AA
7210    and     r2, r3, #255                @ r2<- BB
7211    GET_VREG(r0, r2)                    @ r0<- vBB
7212    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7213    .if 0
7214    @cmp     r1, #0                      @ is second operand zero?
7215    beq     common_errDivideByZero
7216    .endif
7217    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7218
7219                               @ optional op; may set condition codes
7220    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
7221    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7222    SET_VREG(r0, r9)               @ vAA<- r0
7223    GOTO_OPCODE(ip)                     @ jump to next instruction
7224    /* 10-12 instructions */
7225
7226
7227
7228/* ------------------------------ */
7229    .balign 64
7230.L_OP_DIV_INT_LIT8: /* 0xdb */
7231/* File: armv5te/OP_DIV_INT_LIT8.S */
7232/* File: armv5te/binopLit8.S */
7233    /*
7234     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7235     * that specifies an instruction that performs "result = r0 op r1".
7236     * This could be an ARM instruction or a function call.  (If the result
7237     * comes back in a register other than r0, you can override "result".)
7238     *
7239     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7240     * vCC (r1).  Useful for integer division and modulus.
7241     *
7242     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7243     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7244     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7245     */
7246    /* binop/lit8 vAA, vBB, #+CC */
7247    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7248    mov     r9, rINST, lsr #8           @ r9<- AA
7249    and     r2, r3, #255                @ r2<- BB
7250    GET_VREG(r0, r2)                    @ r0<- vBB
7251    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7252    .if 1
7253    @cmp     r1, #0                      @ is second operand zero?
7254    beq     common_errDivideByZero
7255    .endif
7256    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7257
7258                               @ optional op; may set condition codes
7259    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
7260    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7261    SET_VREG(r0, r9)               @ vAA<- r0
7262    GOTO_OPCODE(ip)                     @ jump to next instruction
7263    /* 10-12 instructions */
7264
7265
7266
7267/* ------------------------------ */
7268    .balign 64
7269.L_OP_REM_INT_LIT8: /* 0xdc */
7270/* File: armv5te/OP_REM_INT_LIT8.S */
7271/* idivmod returns quotient in r0 and remainder in r1 */
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 1
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                               @ optional op; may set condition codes
7299    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
7300    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7301    SET_VREG(r1, r9)               @ vAA<- r1
7302    GOTO_OPCODE(ip)                     @ jump to next instruction
7303    /* 10-12 instructions */
7304
7305
7306
7307/* ------------------------------ */
7308    .balign 64
7309.L_OP_AND_INT_LIT8: /* 0xdd */
7310/* File: armv5te/OP_AND_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                               @ optional op; may set condition codes
7338    and     r0, r0, 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_OR_INT_LIT8: /* 0xde */
7349/* File: armv5te/OP_OR_INT_LIT8.S */
7350/* File: armv5te/binopLit8.S */
7351    /*
7352     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7353     * that specifies an instruction that performs "result = r0 op r1".
7354     * This could be an ARM instruction or a function call.  (If the result
7355     * comes back in a register other than r0, you can override "result".)
7356     *
7357     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7358     * vCC (r1).  Useful for integer division and modulus.
7359     *
7360     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7361     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7362     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7363     */
7364    /* binop/lit8 vAA, vBB, #+CC */
7365    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7366    mov     r9, rINST, lsr #8           @ r9<- AA
7367    and     r2, r3, #255                @ r2<- BB
7368    GET_VREG(r0, r2)                    @ r0<- vBB
7369    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7370    .if 0
7371    @cmp     r1, #0                      @ is second operand zero?
7372    beq     common_errDivideByZero
7373    .endif
7374    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7375
7376                               @ optional op; may set condition codes
7377    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
7378    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7379    SET_VREG(r0, r9)               @ vAA<- r0
7380    GOTO_OPCODE(ip)                     @ jump to next instruction
7381    /* 10-12 instructions */
7382
7383
7384
7385/* ------------------------------ */
7386    .balign 64
7387.L_OP_XOR_INT_LIT8: /* 0xdf */
7388/* File: armv5te/OP_XOR_INT_LIT8.S */
7389/* File: armv5te/binopLit8.S */
7390    /*
7391     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7392     * that specifies an instruction that performs "result = r0 op r1".
7393     * This could be an ARM instruction or a function call.  (If the result
7394     * comes back in a register other than r0, you can override "result".)
7395     *
7396     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7397     * vCC (r1).  Useful for integer division and modulus.
7398     *
7399     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7400     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7401     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7402     */
7403    /* binop/lit8 vAA, vBB, #+CC */
7404    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7405    mov     r9, rINST, lsr #8           @ r9<- AA
7406    and     r2, r3, #255                @ r2<- BB
7407    GET_VREG(r0, r2)                    @ r0<- vBB
7408    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7409    .if 0
7410    @cmp     r1, #0                      @ is second operand zero?
7411    beq     common_errDivideByZero
7412    .endif
7413    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7414
7415                               @ optional op; may set condition codes
7416    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
7417    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7418    SET_VREG(r0, r9)               @ vAA<- r0
7419    GOTO_OPCODE(ip)                     @ jump to next instruction
7420    /* 10-12 instructions */
7421
7422
7423
7424/* ------------------------------ */
7425    .balign 64
7426.L_OP_SHL_INT_LIT8: /* 0xe0 */
7427/* File: armv5te/OP_SHL_INT_LIT8.S */
7428/* File: armv5te/binopLit8.S */
7429    /*
7430     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7431     * that specifies an instruction that performs "result = r0 op r1".
7432     * This could be an ARM instruction or a function call.  (If the result
7433     * comes back in a register other than r0, you can override "result".)
7434     *
7435     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7436     * vCC (r1).  Useful for integer division and modulus.
7437     *
7438     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7439     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7440     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7441     */
7442    /* binop/lit8 vAA, vBB, #+CC */
7443    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7444    mov     r9, rINST, lsr #8           @ r9<- AA
7445    and     r2, r3, #255                @ r2<- BB
7446    GET_VREG(r0, r2)                    @ r0<- vBB
7447    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7448    .if 0
7449    @cmp     r1, #0                      @ is second operand zero?
7450    beq     common_errDivideByZero
7451    .endif
7452    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7453
7454    and     r1, r1, #31                           @ optional op; may set condition codes
7455    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
7456    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7457    SET_VREG(r0, r9)               @ vAA<- r0
7458    GOTO_OPCODE(ip)                     @ jump to next instruction
7459    /* 10-12 instructions */
7460
7461
7462
7463/* ------------------------------ */
7464    .balign 64
7465.L_OP_SHR_INT_LIT8: /* 0xe1 */
7466/* File: armv5te/OP_SHR_INT_LIT8.S */
7467/* File: armv5te/binopLit8.S */
7468    /*
7469     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7470     * that specifies an instruction that performs "result = r0 op r1".
7471     * This could be an ARM instruction or a function call.  (If the result
7472     * comes back in a register other than r0, you can override "result".)
7473     *
7474     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7475     * vCC (r1).  Useful for integer division and modulus.
7476     *
7477     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7478     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7479     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7480     */
7481    /* binop/lit8 vAA, vBB, #+CC */
7482    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7483    mov     r9, rINST, lsr #8           @ r9<- AA
7484    and     r2, r3, #255                @ r2<- BB
7485    GET_VREG(r0, r2)                    @ r0<- vBB
7486    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7487    .if 0
7488    @cmp     r1, #0                      @ is second operand zero?
7489    beq     common_errDivideByZero
7490    .endif
7491    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7492
7493    and     r1, r1, #31                           @ optional op; may set condition codes
7494    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
7495    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7496    SET_VREG(r0, r9)               @ vAA<- r0
7497    GOTO_OPCODE(ip)                     @ jump to next instruction
7498    /* 10-12 instructions */
7499
7500
7501
7502/* ------------------------------ */
7503    .balign 64
7504.L_OP_USHR_INT_LIT8: /* 0xe2 */
7505/* File: armv5te/OP_USHR_INT_LIT8.S */
7506/* File: armv5te/binopLit8.S */
7507    /*
7508     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7509     * that specifies an instruction that performs "result = r0 op r1".
7510     * This could be an ARM instruction or a function call.  (If the result
7511     * comes back in a register other than r0, you can override "result".)
7512     *
7513     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7514     * vCC (r1).  Useful for integer division and modulus.
7515     *
7516     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7517     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7518     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7519     */
7520    /* binop/lit8 vAA, vBB, #+CC */
7521    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7522    mov     r9, rINST, lsr #8           @ r9<- AA
7523    and     r2, r3, #255                @ r2<- BB
7524    GET_VREG(r0, r2)                    @ r0<- vBB
7525    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7526    .if 0
7527    @cmp     r1, #0                      @ is second operand zero?
7528    beq     common_errDivideByZero
7529    .endif
7530    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7531
7532    and     r1, r1, #31                           @ optional op; may set condition codes
7533    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
7534    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7535    SET_VREG(r0, r9)               @ vAA<- r0
7536    GOTO_OPCODE(ip)                     @ jump to next instruction
7537    /* 10-12 instructions */
7538
7539
7540
7541/* ------------------------------ */
7542    .balign 64
7543.L_OP_UNUSED_E3: /* 0xe3 */
7544/* File: armv5te/OP_UNUSED_E3.S */
7545/* File: armv5te/unused.S */
7546    bl      common_abort
7547
7548
7549
7550/* ------------------------------ */
7551    .balign 64
7552.L_OP_UNUSED_E4: /* 0xe4 */
7553/* File: armv5te/OP_UNUSED_E4.S */
7554/* File: armv5te/unused.S */
7555    bl      common_abort
7556
7557
7558
7559/* ------------------------------ */
7560    .balign 64
7561.L_OP_UNUSED_E5: /* 0xe5 */
7562/* File: armv5te/OP_UNUSED_E5.S */
7563/* File: armv5te/unused.S */
7564    bl      common_abort
7565
7566
7567
7568/* ------------------------------ */
7569    .balign 64
7570.L_OP_UNUSED_E6: /* 0xe6 */
7571/* File: armv5te/OP_UNUSED_E6.S */
7572/* File: armv5te/unused.S */
7573    bl      common_abort
7574
7575
7576
7577/* ------------------------------ */
7578    .balign 64
7579.L_OP_UNUSED_E7: /* 0xe7 */
7580/* File: armv5te/OP_UNUSED_E7.S */
7581/* File: armv5te/unused.S */
7582    bl      common_abort
7583
7584
7585
7586/* ------------------------------ */
7587    .balign 64
7588.L_OP_UNUSED_E8: /* 0xe8 */
7589/* File: armv5te/OP_UNUSED_E8.S */
7590/* File: armv5te/unused.S */
7591    bl      common_abort
7592
7593
7594
7595/* ------------------------------ */
7596    .balign 64
7597.L_OP_UNUSED_E9: /* 0xe9 */
7598/* File: armv5te/OP_UNUSED_E9.S */
7599/* File: armv5te/unused.S */
7600    bl      common_abort
7601
7602
7603
7604/* ------------------------------ */
7605    .balign 64
7606.L_OP_UNUSED_EA: /* 0xea */
7607/* File: armv5te/OP_UNUSED_EA.S */
7608/* File: armv5te/unused.S */
7609    bl      common_abort
7610
7611
7612
7613/* ------------------------------ */
7614    .balign 64
7615.L_OP_UNUSED_EB: /* 0xeb */
7616/* File: armv5te/OP_UNUSED_EB.S */
7617/* File: armv5te/unused.S */
7618    bl      common_abort
7619
7620
7621
7622/* ------------------------------ */
7623    .balign 64
7624.L_OP_UNUSED_EC: /* 0xec */
7625/* File: armv5te/OP_UNUSED_EC.S */
7626/* File: armv5te/unused.S */
7627    bl      common_abort
7628
7629
7630
7631/* ------------------------------ */
7632    .balign 64
7633.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
7634/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
7635    /*
7636     * Handle a throw-verification-error instruction.  This throws an
7637     * exception for an error discovered during verification.  The
7638     * exception is indicated by AA, with some detail provided by BBBB.
7639     */
7640    /* op AA, ref@BBBB */
7641    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7642    FETCH(r2, 1)                        @ r2<- BBBB
7643    EXPORT_PC()                         @ export the PC
7644    mov     r1, rINST, lsr #8           @ r1<- AA
7645    bl      dvmThrowVerificationError   @ always throws
7646    b       common_exceptionThrown      @ handle exception
7647
7648
7649/* ------------------------------ */
7650    .balign 64
7651.L_OP_EXECUTE_INLINE: /* 0xee */
7652/* File: armv5te/OP_EXECUTE_INLINE.S */
7653    /*
7654     * Execute a "native inline" instruction.
7655     *
7656     * We need to call:
7657     *  dvmPerformInlineOp4Std(arg0, arg1, arg2, arg3, &retval, ref)
7658     *
7659     * The first four args are in r0-r3, but the last two must be pushed
7660     * onto the stack.
7661     */
7662    /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
7663    FETCH(r10, 1)                       @ r10<- BBBB
7664    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7665    EXPORT_PC()                         @ can throw
7666    sub     sp, sp, #8                  @ make room for arg(s)
7667    mov     r0, rINST, lsr #12          @ r0<- B
7668    str     r1, [sp]                    @ push &glue->retval
7669    bl      .LOP_EXECUTE_INLINE_continue        @ make call; will return after
7670    add     sp, sp, #8                  @ pop stack
7671    cmp     r0, #0                      @ test boolean result of inline
7672    beq     common_exceptionThrown      @ returned false, handle exception
7673    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7674    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7675    GOTO_OPCODE(ip)                     @ jump to next instruction
7676
7677/* ------------------------------ */
7678    .balign 64
7679.L_OP_UNUSED_EF: /* 0xef */
7680/* File: armv5te/OP_UNUSED_EF.S */
7681/* File: armv5te/unused.S */
7682    bl      common_abort
7683
7684
7685
7686/* ------------------------------ */
7687    .balign 64
7688.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
7689/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
7690    /*
7691     * invoke-direct-empty is a no-op in a "standard" interpreter.
7692     */
7693    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7694    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7695    GOTO_OPCODE(ip)                     @ execute it
7696
7697/* ------------------------------ */
7698    .balign 64
7699.L_OP_UNUSED_F1: /* 0xf1 */
7700/* File: armv5te/OP_UNUSED_F1.S */
7701/* File: armv5te/unused.S */
7702    bl      common_abort
7703
7704
7705
7706/* ------------------------------ */
7707    .balign 64
7708.L_OP_IGET_QUICK: /* 0xf2 */
7709/* File: armv5te/OP_IGET_QUICK.S */
7710    /* For: iget-quick, iget-object-quick */
7711    /* op vA, vB, offset@CCCC */
7712    mov     r2, rINST, lsr #12          @ r2<- B
7713    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7714    FETCH(r1, 1)                        @ r1<- field byte offset
7715    cmp     r3, #0                      @ check object for null
7716    mov     r2, rINST, lsr #8           @ r2<- A(+)
7717    beq     common_errNullObject        @ object was null
7718    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7719    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7720    and     r2, r2, #15
7721    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7722    SET_VREG(r0, r2)                    @ fp[A]<- r0
7723    GOTO_OPCODE(ip)                     @ jump to next instruction
7724
7725
7726/* ------------------------------ */
7727    .balign 64
7728.L_OP_IGET_WIDE_QUICK: /* 0xf3 */
7729/* File: armv5te/OP_IGET_WIDE_QUICK.S */
7730    /* iget-wide-quick vA, vB, offset@CCCC */
7731    mov     r2, rINST, lsr #12          @ r2<- B
7732    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7733    FETCH(r1, 1)                        @ r1<- field byte offset
7734    cmp     r3, #0                      @ check object for null
7735    mov     r2, rINST, lsr #8           @ r2<- A(+)
7736    beq     common_errNullObject        @ object was null
7737    ldrd    r0, [r3, r1]                @ r0<- obj.field (64 bits, aligned)
7738    and     r2, r2, #15
7739    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7740    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
7741    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7742    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
7743    GOTO_OPCODE(ip)                     @ jump to next instruction
7744
7745
7746/* ------------------------------ */
7747    .balign 64
7748.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
7749/* File: armv5te/OP_IGET_OBJECT_QUICK.S */
7750/* File: armv5te/OP_IGET_QUICK.S */
7751    /* For: iget-quick, iget-object-quick */
7752    /* op vA, vB, offset@CCCC */
7753    mov     r2, rINST, lsr #12          @ r2<- B
7754    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7755    FETCH(r1, 1)                        @ r1<- field byte offset
7756    cmp     r3, #0                      @ check object for null
7757    mov     r2, rINST, lsr #8           @ r2<- A(+)
7758    beq     common_errNullObject        @ object was null
7759    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7760    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7761    and     r2, r2, #15
7762    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7763    SET_VREG(r0, r2)                    @ fp[A]<- r0
7764    GOTO_OPCODE(ip)                     @ jump to next instruction
7765
7766
7767
7768/* ------------------------------ */
7769    .balign 64
7770.L_OP_IPUT_QUICK: /* 0xf5 */
7771/* File: armv5te/OP_IPUT_QUICK.S */
7772    /* For: iput-quick, iput-object-quick */
7773    /* op vA, vB, offset@CCCC */
7774    mov     r2, rINST, lsr #12          @ r2<- B
7775    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7776    FETCH(r1, 1)                        @ r1<- field byte offset
7777    cmp     r3, #0                      @ check object for null
7778    mov     r2, rINST, lsr #8           @ r2<- A(+)
7779    beq     common_errNullObject        @ object was null
7780    and     r2, r2, #15
7781    GET_VREG(r0, r2)                    @ r0<- fp[A]
7782    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7783    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7784    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7785    GOTO_OPCODE(ip)                     @ jump to next instruction
7786
7787
7788/* ------------------------------ */
7789    .balign 64
7790.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
7791/* File: armv5te/OP_IPUT_WIDE_QUICK.S */
7792    /* iput-wide-quick vA, vB, offset@CCCC */
7793    mov     r0, rINST, lsr #8           @ r0<- A(+)
7794    mov     r1, rINST, lsr #12          @ r1<- B
7795    and     r0, r0, #15
7796    GET_VREG(r2, r1)                    @ r2<- fp[B], the object pointer
7797    add     r3, rFP, r0, lsl #2         @ r3<- &fp[A]
7798    cmp     r2, #0                      @ check object for null
7799    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[A]
7800    beq     common_errNullObject        @ object was null
7801    FETCH(r3, 1)                        @ r3<- field byte offset
7802    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7803    strd    r0, [r2, r3]                @ obj.field (64 bits, aligned)<- r0/r1
7804    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7805    GOTO_OPCODE(ip)                     @ jump to next instruction
7806
7807
7808/* ------------------------------ */
7809    .balign 64
7810.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
7811/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
7812/* File: armv5te/OP_IPUT_QUICK.S */
7813    /* For: iput-quick, iput-object-quick */
7814    /* op vA, vB, offset@CCCC */
7815    mov     r2, rINST, lsr #12          @ r2<- B
7816    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7817    FETCH(r1, 1)                        @ r1<- field byte offset
7818    cmp     r3, #0                      @ check object for null
7819    mov     r2, rINST, lsr #8           @ r2<- A(+)
7820    beq     common_errNullObject        @ object was null
7821    and     r2, r2, #15
7822    GET_VREG(r0, r2)                    @ r0<- fp[A]
7823    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7824    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7825    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7826    GOTO_OPCODE(ip)                     @ jump to next instruction
7827
7828
7829
7830/* ------------------------------ */
7831    .balign 64
7832.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
7833/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7834    /*
7835     * Handle an optimized virtual method call.
7836     *
7837     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7838     */
7839    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7840    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7841    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7842    FETCH(r1, 1)                        @ r1<- BBBB
7843    .if     (!0)
7844    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7845    .endif
7846    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7847    cmp     r2, #0                      @ is "this" null?
7848    beq     common_errNullObject        @ null "this", throw exception
7849    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7850    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7851    EXPORT_PC()                         @ invoke must export
7852    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7853    bl      common_invokeMethodNoRange @ continue on
7854
7855/* ------------------------------ */
7856    .balign 64
7857.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
7858/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
7859/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7860    /*
7861     * Handle an optimized virtual method call.
7862     *
7863     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7864     */
7865    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7866    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7867    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7868    FETCH(r1, 1)                        @ r1<- BBBB
7869    .if     (!1)
7870    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7871    .endif
7872    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7873    cmp     r2, #0                      @ is "this" null?
7874    beq     common_errNullObject        @ null "this", throw exception
7875    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7876    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7877    EXPORT_PC()                         @ invoke must export
7878    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7879    bl      common_invokeMethodRange @ continue on
7880
7881
7882/* ------------------------------ */
7883    .balign 64
7884.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
7885/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7886    /*
7887     * Handle an optimized "super" method call.
7888     *
7889     * for: [opt] invoke-super-quick, invoke-super-quick/range
7890     */
7891    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7892    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7893    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7894    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7895    .if     (!0)
7896    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7897    .endif
7898    FETCH(r1, 1)                        @ r1<- BBBB
7899    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7900    EXPORT_PC()                         @ must export for invoke
7901    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7902    GET_VREG(r3, r10)                   @ r3<- "this"
7903    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7904    cmp     r3, #0                      @ null "this" ref?
7905    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7906    beq     common_errNullObject        @ "this" is null, throw exception
7907    bl      common_invokeMethodNoRange @ continue on
7908
7909
7910/* ------------------------------ */
7911    .balign 64
7912.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
7913/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
7914/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7915    /*
7916     * Handle an optimized "super" method call.
7917     *
7918     * for: [opt] invoke-super-quick, invoke-super-quick/range
7919     */
7920    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7921    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7922    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7923    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7924    .if     (!1)
7925    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7926    .endif
7927    FETCH(r1, 1)                        @ r1<- BBBB
7928    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7929    EXPORT_PC()                         @ must export for invoke
7930    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7931    GET_VREG(r3, r10)                   @ r3<- "this"
7932    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7933    cmp     r3, #0                      @ null "this" ref?
7934    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7935    beq     common_errNullObject        @ "this" is null, throw exception
7936    bl      common_invokeMethodRange @ continue on
7937
7938
7939
7940/* ------------------------------ */
7941    .balign 64
7942.L_OP_UNUSED_FC: /* 0xfc */
7943/* File: armv5te/OP_UNUSED_FC.S */
7944/* File: armv5te/unused.S */
7945    bl      common_abort
7946
7947
7948
7949/* ------------------------------ */
7950    .balign 64
7951.L_OP_UNUSED_FD: /* 0xfd */
7952/* File: armv5te/OP_UNUSED_FD.S */
7953/* File: armv5te/unused.S */
7954    bl      common_abort
7955
7956
7957
7958/* ------------------------------ */
7959    .balign 64
7960.L_OP_UNUSED_FE: /* 0xfe */
7961/* File: armv5te/OP_UNUSED_FE.S */
7962/* File: armv5te/unused.S */
7963    bl      common_abort
7964
7965
7966
7967/* ------------------------------ */
7968    .balign 64
7969.L_OP_UNUSED_FF: /* 0xff */
7970/* File: armv5te/OP_UNUSED_FF.S */
7971/* File: armv5te/unused.S */
7972    bl      common_abort
7973
7974
7975
7976
7977    .balign 64
7978    .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
7979    .global dvmAsmInstructionEnd
7980dvmAsmInstructionEnd:
7981
7982/*
7983 * ===========================================================================
7984 *  Sister implementations
7985 * ===========================================================================
7986 */
7987    .global dvmAsmSisterStart
7988    .type   dvmAsmSisterStart, %function
7989    .text
7990    .balign 4
7991dvmAsmSisterStart:
7992
7993/* continuation for OP_CONST_STRING */
7994
7995    /*
7996     * Continuation if the String has not yet been resolved.
7997     *  r1: BBBB (String ref)
7998     *  r9: target register
7999     */
8000.LOP_CONST_STRING_resolve:
8001    EXPORT_PC()
8002    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
8003    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
8004    bl      dvmResolveString            @ r0<- String reference
8005    cmp     r0, #0                      @ failed?
8006    beq     common_exceptionThrown      @ yup, handle the exception
8007    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8008    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8009    SET_VREG(r0, r9)                    @ vAA<- r0
8010    GOTO_OPCODE(ip)                     @ jump to next instruction
8011
8012
8013/* continuation for OP_CONST_STRING_JUMBO */
8014
8015    /*
8016     * Continuation if the String has not yet been resolved.
8017     *  r1: BBBBBBBB (String ref)
8018     *  r9: target register
8019     */
8020.LOP_CONST_STRING_JUMBO_resolve:
8021    EXPORT_PC()
8022    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
8023    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
8024    bl      dvmResolveString            @ r0<- String reference
8025    cmp     r0, #0                      @ failed?
8026    beq     common_exceptionThrown      @ yup, handle the exception
8027    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
8028    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8029    SET_VREG(r0, r9)                    @ vAA<- r0
8030    GOTO_OPCODE(ip)                     @ jump to next instruction
8031
8032
8033/* continuation for OP_CONST_CLASS */
8034
8035    /*
8036     * Continuation if the Class has not yet been resolved.
8037     *  r1: BBBB (Class ref)
8038     *  r9: target register
8039     */
8040.LOP_CONST_CLASS_resolve:
8041    EXPORT_PC()
8042    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
8043    mov     r2, #1                      @ r2<- true
8044    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
8045    bl      dvmResolveClass             @ r0<- Class reference
8046    cmp     r0, #0                      @ failed?
8047    beq     common_exceptionThrown      @ yup, handle the exception
8048    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8049    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8050    SET_VREG(r0, r9)                    @ vAA<- r0
8051    GOTO_OPCODE(ip)                     @ jump to next instruction
8052
8053
8054/* continuation for OP_CHECK_CAST */
8055
8056    /*
8057     * Trivial test failed, need to perform full check.  This is common.
8058     *  r0 holds obj->clazz
8059     *  r1 holds class resolved from BBBB
8060     *  r9 holds object
8061     */
8062.LOP_CHECK_CAST_fullcheck:
8063    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
8064    cmp     r0, #0                      @ failed?
8065    bne     .LOP_CHECK_CAST_okay            @ no, success
8066
8067    @ A cast has failed.  We need to throw a ClassCastException with the
8068    @ class of the object that failed to be cast.
8069    EXPORT_PC()                         @ about to throw
8070    ldr     r3, [r9, #offObject_clazz]  @ r3<- obj->clazz
8071    ldr     r0, .LstrClassCastExceptionPtr
8072    ldr     r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor
8073    bl      dvmThrowExceptionWithClassMessage
8074    b       common_exceptionThrown
8075
8076    /*
8077     * Resolution required.  This is the least-likely path.
8078     *
8079     *  r2 holds BBBB
8080     *  r9 holds object
8081     */
8082.LOP_CHECK_CAST_resolve:
8083    EXPORT_PC()                         @ resolve() could throw
8084    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8085    mov     r1, r2                      @ r1<- BBBB
8086    mov     r2, #0                      @ r2<- false
8087    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8088    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
8089    cmp     r0, #0                      @ got null?
8090    beq     common_exceptionThrown      @ yes, handle exception
8091    mov     r1, r0                      @ r1<- class resolved from BBB
8092    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
8093    b       .LOP_CHECK_CAST_resolved        @ pick up where we left off
8094
8095.LstrClassCastExceptionPtr:
8096    .word   .LstrClassCastException
8097
8098
8099/* continuation for OP_INSTANCE_OF */
8100
8101    /*
8102     * Trivial test failed, need to perform full check.  This is common.
8103     *  r0 holds obj->clazz
8104     *  r1 holds class resolved from BBBB
8105     *  r9 holds A
8106     */
8107.LOP_INSTANCE_OF_fullcheck:
8108    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
8109    @ fall through to OP_INSTANCE_OF_store
8110
8111    /*
8112     * r0 holds boolean result
8113     * r9 holds A
8114     */
8115.LOP_INSTANCE_OF_store:
8116    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8117    SET_VREG(r0, r9)                    @ vA<- r0
8118    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8119    GOTO_OPCODE(ip)                     @ jump to next instruction
8120
8121    /*
8122     * Trivial test succeeded, save and bail.
8123     *  r9 holds A
8124     */
8125.LOP_INSTANCE_OF_trivial:
8126    mov     r0, #1                      @ indicate success
8127    @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
8128    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8129    SET_VREG(r0, r9)                    @ vA<- r0
8130    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8131    GOTO_OPCODE(ip)                     @ jump to next instruction
8132
8133    /*
8134     * Resolution required.  This is the least-likely path.
8135     *
8136     *  r3 holds BBBB
8137     *  r9 holds A
8138     */
8139.LOP_INSTANCE_OF_resolve:
8140    EXPORT_PC()                         @ resolve() could throw
8141    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
8142    mov     r1, r3                      @ r1<- BBBB
8143    mov     r2, #1                      @ r2<- true
8144    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
8145    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
8146    cmp     r0, #0                      @ got null?
8147    beq     common_exceptionThrown      @ yes, handle exception
8148    mov     r1, r0                      @ r1<- class resolved from BBB
8149    mov     r3, rINST, lsr #12          @ r3<- B
8150    GET_VREG(r0, r3)                    @ r0<- vB (object)
8151    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
8152    b       .LOP_INSTANCE_OF_resolved        @ pick up where we left off
8153
8154
8155/* continuation for OP_NEW_INSTANCE */
8156
8157    .balign 32                          @ minimize cache lines
8158.LOP_NEW_INSTANCE_finish: @ r0=new object
8159    mov     r3, rINST, lsr #8           @ r3<- AA
8160    cmp     r0, #0                      @ failed?
8161    beq     common_exceptionThrown      @ yes, handle the exception
8162    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8163    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8164    SET_VREG(r0, r3)                    @ vAA<- r0
8165    GOTO_OPCODE(ip)                     @ jump to next instruction
8166
8167    /*
8168     * Class initialization required.
8169     *
8170     *  r0 holds class object
8171     */
8172.LOP_NEW_INSTANCE_needinit:
8173    mov     r9, r0                      @ save r0
8174    bl      dvmInitClass                @ initialize class
8175    cmp     r0, #0                      @ check boolean result
8176    mov     r0, r9                      @ restore r0
8177    bne     .LOP_NEW_INSTANCE_initialized     @ success, continue
8178    b       common_exceptionThrown      @ failed, deal with init exception
8179
8180    /*
8181     * Resolution required.  This is the least-likely path.
8182     *
8183     *  r1 holds BBBB
8184     */
8185.LOP_NEW_INSTANCE_resolve:
8186    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8187    mov     r2, #0                      @ r2<- false
8188    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8189    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
8190    cmp     r0, #0                      @ got null?
8191    bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
8192    b       common_exceptionThrown      @ yes, handle exception
8193
8194.LstrInstantiationErrorPtr:
8195    .word   .LstrInstantiationError
8196
8197
8198/* continuation for OP_NEW_ARRAY */
8199
8200
8201    /*
8202     * Resolve class.  (This is an uncommon case.)
8203     *
8204     *  r1 holds array length
8205     *  r2 holds class ref CCCC
8206     */
8207.LOP_NEW_ARRAY_resolve:
8208    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8209    mov     r9, r1                      @ r9<- length (save)
8210    mov     r1, r2                      @ r1<- CCCC
8211    mov     r2, #0                      @ r2<- false
8212    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8213    bl      dvmResolveClass             @ r0<- call(clazz, ref)
8214    cmp     r0, #0                      @ got null?
8215    mov     r1, r9                      @ r1<- length (restore)
8216    beq     common_exceptionThrown      @ yes, handle exception
8217    @ fall through to OP_NEW_ARRAY_finish
8218
8219    /*
8220     * Finish allocation.
8221     *
8222     *  r0 holds class
8223     *  r1 holds array length
8224     */
8225.LOP_NEW_ARRAY_finish:
8226    mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
8227    bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
8228    cmp     r0, #0                      @ failed?
8229    mov     r2, rINST, lsr #8           @ r2<- A+
8230    beq     common_exceptionThrown      @ yes, handle the exception
8231    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8232    and     r2, r2, #15                 @ r2<- A
8233    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8234    SET_VREG(r0, r2)                    @ vA<- r0
8235    GOTO_OPCODE(ip)                     @ jump to next instruction
8236
8237
8238/* continuation for OP_FILLED_NEW_ARRAY */
8239
8240    /*
8241     * On entry:
8242     *  r0 holds array class
8243     *  r10 holds AA or BA
8244     */
8245.LOP_FILLED_NEW_ARRAY_continue:
8246    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8247    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8248    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
8249    .if     0
8250    mov     r1, r10                     @ r1<- AA (length)
8251    .else
8252    mov     r1, r10, lsr #4             @ r1<- B (length)
8253    .endif
8254    cmp     r3, #'I'                    @ array of ints?
8255    cmpne   r3, #'L'                    @ array of objects?
8256    cmpne   r3, #'['                    @ array of arrays?
8257    mov     r9, r1                      @ save length in r9
8258    bne     .LOP_FILLED_NEW_ARRAY_notimpl         @ no, not handled yet
8259    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8260    cmp     r0, #0                      @ null return?
8261    beq     common_exceptionThrown      @ alloc failed, handle exception
8262
8263    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8264    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
8265    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8266    subs    r9, r9, #1                  @ length--, check for neg
8267    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8268    bmi     2f                          @ was zero, bail
8269
8270    @ copy values from registers into the array
8271    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8272    .if     0
8273    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
82741:  ldr     r3, [r2], #4                @ r3<- *r2++
8275    subs    r9, r9, #1                  @ count--
8276    str     r3, [r0], #4                @ *contents++ = vX
8277    bpl     1b
8278    @ continue at 2
8279    .else
8280    cmp     r9, #4                      @ length was initially 5?
8281    and     r2, r10, #15                @ r2<- A
8282    bne     1f                          @ <= 4 args, branch
8283    GET_VREG(r3, r2)                    @ r3<- vA
8284    sub     r9, r9, #1                  @ count--
8285    str     r3, [r0, #16]               @ contents[4] = vA
82861:  and     r2, r1, #15                 @ r2<- F/E/D/C
8287    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8288    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8289    subs    r9, r9, #1                  @ count--
8290    str     r3, [r0], #4                @ *contents++ = vX
8291    bpl     1b
8292    @ continue at 2
8293    .endif
8294
82952:
8296    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
8297    GOTO_OPCODE(ip)                     @ execute it
8298
8299    /*
8300     * Throw an exception indicating that we have not implemented this
8301     * mode of filled-new-array.
8302     */
8303.LOP_FILLED_NEW_ARRAY_notimpl:
8304    ldr     r0, .L_strInternalError
8305    ldr     r1, .L_strFilledNewArrayNotImpl
8306    bl      dvmThrowException
8307    b       common_exceptionThrown
8308
8309    .if     (!0)                 @ define in one or the other, not both
8310.L_strFilledNewArrayNotImpl:
8311    .word   .LstrFilledNewArrayNotImpl
8312.L_strInternalError:
8313    .word   .LstrInternalError
8314    .endif
8315
8316
8317/* continuation for OP_FILLED_NEW_ARRAY_RANGE */
8318
8319    /*
8320     * On entry:
8321     *  r0 holds array class
8322     *  r10 holds AA or BA
8323     */
8324.LOP_FILLED_NEW_ARRAY_RANGE_continue:
8325    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8326    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8327    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
8328    .if     1
8329    mov     r1, r10                     @ r1<- AA (length)
8330    .else
8331    mov     r1, r10, lsr #4             @ r1<- B (length)
8332    .endif
8333    cmp     r3, #'I'                    @ array of ints?
8334    cmpne   r3, #'L'                    @ array of objects?
8335    cmpne   r3, #'['                    @ array of arrays?
8336    mov     r9, r1                      @ save length in r9
8337    bne     .LOP_FILLED_NEW_ARRAY_RANGE_notimpl         @ no, not handled yet
8338    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8339    cmp     r0, #0                      @ null return?
8340    beq     common_exceptionThrown      @ alloc failed, handle exception
8341
8342    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8343    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
8344    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8345    subs    r9, r9, #1                  @ length--, check for neg
8346    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8347    bmi     2f                          @ was zero, bail
8348
8349    @ copy values from registers into the array
8350    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8351    .if     1
8352    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
83531:  ldr     r3, [r2], #4                @ r3<- *r2++
8354    subs    r9, r9, #1                  @ count--
8355    str     r3, [r0], #4                @ *contents++ = vX
8356    bpl     1b
8357    @ continue at 2
8358    .else
8359    cmp     r9, #4                      @ length was initially 5?
8360    and     r2, r10, #15                @ r2<- A
8361    bne     1f                          @ <= 4 args, branch
8362    GET_VREG(r3, r2)                    @ r3<- vA
8363    sub     r9, r9, #1                  @ count--
8364    str     r3, [r0, #16]               @ contents[4] = vA
83651:  and     r2, r1, #15                 @ r2<- F/E/D/C
8366    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8367    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8368    subs    r9, r9, #1                  @ count--
8369    str     r3, [r0], #4                @ *contents++ = vX
8370    bpl     1b
8371    @ continue at 2
8372    .endif
8373
83742:
8375    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
8376    GOTO_OPCODE(ip)                     @ execute it
8377
8378    /*
8379     * Throw an exception indicating that we have not implemented this
8380     * mode of filled-new-array.
8381     */
8382.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
8383    ldr     r0, .L_strInternalError
8384    ldr     r1, .L_strFilledNewArrayNotImpl
8385    bl      dvmThrowException
8386    b       common_exceptionThrown
8387
8388    .if     (!1)                 @ define in one or the other, not both
8389.L_strFilledNewArrayNotImpl:
8390    .word   .LstrFilledNewArrayNotImpl
8391.L_strInternalError:
8392    .word   .LstrInternalError
8393    .endif
8394
8395
8396/* continuation for OP_CMPL_FLOAT */
8397
8398    @ Test for NaN with a second comparison.  EABI forbids testing bit
8399    @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8400    @ make the library call.
8401.LOP_CMPL_FLOAT_gt_or_nan:
8402    mov     r1, r9                      @ reverse order
8403    mov     r0, r10
8404    bl      __aeabi_cfcmple             @ r0<- Z set if eq, C clear if <
8405    @bleq    common_abort
8406    movcc   r1, #1                      @ (greater than) r1<- 1
8407    bcc     .LOP_CMPL_FLOAT_finish
8408    mvn     r1, #0                            @ r1<- 1 or -1 for NaN
8409    b       .LOP_CMPL_FLOAT_finish
8410
8411
8412#if 0       /* "clasic" form */
8413    FETCH(r0, 1)                        @ r0<- CCBB
8414    and     r2, r0, #255                @ r2<- BB
8415    mov     r3, r0, lsr #8              @ r3<- CC
8416    GET_VREG(r9, r2)                    @ r9<- vBB
8417    GET_VREG(r10, r3)                   @ r10<- vCC
8418    mov     r0, r9                      @ r0<- vBB
8419    mov     r1, r10                     @ r1<- vCC
8420    bl      __aeabi_fcmpeq              @ r0<- (vBB == vCC)
8421    cmp     r0, #0                      @ equal?
8422    movne   r1, #0                      @ yes, result is 0
8423    bne     OP_CMPL_FLOAT_finish
8424    mov     r0, r9                      @ r0<- vBB
8425    mov     r1, r10                     @ r1<- vCC
8426    bl      __aeabi_fcmplt              @ r0<- (vBB < vCC)
8427    cmp     r0, #0                      @ less than?
8428    b       OP_CMPL_FLOAT_continue
8429@%break
8430
8431OP_CMPL_FLOAT_continue:
8432    mvnne   r1, #0                      @ yes, result is -1
8433    bne     OP_CMPL_FLOAT_finish
8434    mov     r0, r9                      @ r0<- vBB
8435    mov     r1, r10                     @ r1<- vCC
8436    bl      __aeabi_fcmpgt              @ r0<- (vBB > vCC)
8437    cmp     r0, #0                      @ greater than?
8438    beq     OP_CMPL_FLOAT_nan               @ no, must be NaN
8439    mov     r1, #1                      @ yes, result is 1
8440    @ fall through to _finish
8441
8442OP_CMPL_FLOAT_finish:
8443    mov     r3, rINST, lsr #8           @ r3<- AA
8444    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8445    SET_VREG(r1, r3)                    @ vAA<- r1
8446    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8447    GOTO_OPCODE(ip)                     @ jump to next instruction
8448
8449    /*
8450     * This is expected to be uncommon, so we double-branch (once to here,
8451     * again back to _finish).
8452     */
8453OP_CMPL_FLOAT_nan:
8454    mvn     r1, #0                            @ r1<- 1 or -1 for NaN
8455    b       OP_CMPL_FLOAT_finish
8456
8457#endif
8458
8459
8460/* continuation for OP_CMPG_FLOAT */
8461
8462    @ Test for NaN with a second comparison.  EABI forbids testing bit
8463    @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8464    @ make the library call.
8465.LOP_CMPG_FLOAT_gt_or_nan:
8466    mov     r1, r9                      @ reverse order
8467    mov     r0, r10
8468    bl      __aeabi_cfcmple             @ r0<- Z set if eq, C clear if <
8469    @bleq    common_abort
8470    movcc   r1, #1                      @ (greater than) r1<- 1
8471    bcc     .LOP_CMPG_FLOAT_finish
8472    mov     r1, #1                            @ r1<- 1 or -1 for NaN
8473    b       .LOP_CMPG_FLOAT_finish
8474
8475
8476#if 0       /* "clasic" form */
8477    FETCH(r0, 1)                        @ r0<- CCBB
8478    and     r2, r0, #255                @ r2<- BB
8479    mov     r3, r0, lsr #8              @ r3<- CC
8480    GET_VREG(r9, r2)                    @ r9<- vBB
8481    GET_VREG(r10, r3)                   @ r10<- vCC
8482    mov     r0, r9                      @ r0<- vBB
8483    mov     r1, r10                     @ r1<- vCC
8484    bl      __aeabi_fcmpeq              @ r0<- (vBB == vCC)
8485    cmp     r0, #0                      @ equal?
8486    movne   r1, #0                      @ yes, result is 0
8487    bne     OP_CMPG_FLOAT_finish
8488    mov     r0, r9                      @ r0<- vBB
8489    mov     r1, r10                     @ r1<- vCC
8490    bl      __aeabi_fcmplt              @ r0<- (vBB < vCC)
8491    cmp     r0, #0                      @ less than?
8492    b       OP_CMPG_FLOAT_continue
8493@%break
8494
8495OP_CMPG_FLOAT_continue:
8496    mvnne   r1, #0                      @ yes, result is -1
8497    bne     OP_CMPG_FLOAT_finish
8498    mov     r0, r9                      @ r0<- vBB
8499    mov     r1, r10                     @ r1<- vCC
8500    bl      __aeabi_fcmpgt              @ r0<- (vBB > vCC)
8501    cmp     r0, #0                      @ greater than?
8502    beq     OP_CMPG_FLOAT_nan               @ no, must be NaN
8503    mov     r1, #1                      @ yes, result is 1
8504    @ fall through to _finish
8505
8506OP_CMPG_FLOAT_finish:
8507    mov     r3, rINST, lsr #8           @ r3<- AA
8508    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8509    SET_VREG(r1, r3)                    @ vAA<- r1
8510    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8511    GOTO_OPCODE(ip)                     @ jump to next instruction
8512
8513    /*
8514     * This is expected to be uncommon, so we double-branch (once to here,
8515     * again back to _finish).
8516     */
8517OP_CMPG_FLOAT_nan:
8518    mov     r1, #1                            @ r1<- 1 or -1 for NaN
8519    b       OP_CMPG_FLOAT_finish
8520
8521#endif
8522
8523
8524/* continuation for OP_CMPL_DOUBLE */
8525
8526    @ Test for NaN with a second comparison.  EABI forbids testing bit
8527    @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8528    @ make the library call.
8529.LOP_CMPL_DOUBLE_gt_or_nan:
8530    ldmia   r10, {r0-r1}                @ reverse order
8531    ldmia   r9, {r2-r3}
8532    bl      __aeabi_cdcmple             @ r0<- Z set if eq, C clear if <
8533    @bleq    common_abort
8534    movcc   r1, #1                      @ (greater than) r1<- 1
8535    bcc     .LOP_CMPL_DOUBLE_finish
8536    mvn     r1, #0                            @ r1<- 1 or -1 for NaN
8537    b       .LOP_CMPL_DOUBLE_finish
8538
8539
8540/* continuation for OP_CMPG_DOUBLE */
8541
8542    @ Test for NaN with a second comparison.  EABI forbids testing bit
8543    @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8544    @ make the library call.
8545.LOP_CMPG_DOUBLE_gt_or_nan:
8546    ldmia   r10, {r0-r1}                @ reverse order
8547    ldmia   r9, {r2-r3}
8548    bl      __aeabi_cdcmple             @ r0<- Z set if eq, C clear if <
8549    @bleq    common_abort
8550    movcc   r1, #1                      @ (greater than) r1<- 1
8551    bcc     .LOP_CMPG_DOUBLE_finish
8552    mov     r1, #1                            @ r1<- 1 or -1 for NaN
8553    b       .LOP_CMPG_DOUBLE_finish
8554
8555
8556/* continuation for OP_CMP_LONG */
8557
8558.LOP_CMP_LONG_less:
8559    mvn     r1, #0                      @ r1<- -1
8560    @ Want to cond code the next mov so we can avoid branch, but don't see it;
8561    @ instead, we just replicate the tail end.
8562    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8563    SET_VREG(r1, r9)                    @ vAA<- r1
8564    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8565    GOTO_OPCODE(ip)                     @ jump to next instruction
8566
8567.LOP_CMP_LONG_greater:
8568    mov     r1, #1                      @ r1<- 1
8569    @ fall through to _finish
8570
8571.LOP_CMP_LONG_finish:
8572    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8573    SET_VREG(r1, r9)                    @ vAA<- r1
8574    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8575    GOTO_OPCODE(ip)                     @ jump to next instruction
8576
8577
8578/* continuation for OP_AGET_WIDE */
8579
8580.LOP_AGET_WIDE_finish:
8581    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8582    ldrd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8583    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
8584    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8585    stmia   r9, {r2-r3}                 @ vAA/vAA+1<- r2/r3
8586    GOTO_OPCODE(ip)                     @ jump to next instruction
8587
8588
8589/* continuation for OP_APUT_WIDE */
8590
8591.LOP_APUT_WIDE_finish:
8592    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8593    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
8594    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8595    strd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8596    GOTO_OPCODE(ip)                     @ jump to next instruction
8597
8598
8599/* continuation for OP_APUT_OBJECT */
8600    /*
8601     * On entry:
8602     *  r1 = vBB (arrayObj)
8603     *  r9 = vAA (obj)
8604     *  r10 = offset into array (vBB + vCC * width)
8605     */
8606.LOP_APUT_OBJECT_finish:
8607    cmp     r9, #0                      @ storing null reference?
8608    beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
8609    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
8610    ldr     r1, [r1, #offObject_clazz]  @ r1<- arrayObj->clazz
8611    bl      dvmCanPutArrayElement       @ test object type vs. array type
8612    cmp     r0, #0                      @ okay?
8613    beq     common_errArrayStore        @ no
8614.LOP_APUT_OBJECT_skip_check:
8615    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8616    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8617    str     r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
8618    GOTO_OPCODE(ip)                     @ jump to next instruction
8619
8620
8621/* continuation for OP_IGET */
8622
8623    /*
8624     * Currently:
8625     *  r0 holds resolved field
8626     *  r9 holds object
8627     */
8628.LOP_IGET_finish:
8629    @bl      common_squeak0
8630    cmp     r9, #0                      @ check object for null
8631    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8632    beq     common_errNullObject        @ object was null
8633    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8634    mov     r2, rINST, lsr #8           @ r2<- A+
8635    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8636    and     r2, r2, #15                 @ r2<- A
8637    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8638    SET_VREG(r0, r2)                    @ fp[A]<- r0
8639    GOTO_OPCODE(ip)                     @ jump to next instruction
8640
8641
8642/* continuation for OP_IGET_WIDE */
8643
8644    /*
8645     * Currently:
8646     *  r0 holds resolved field
8647     *  r9 holds object
8648     */
8649.LOP_IGET_WIDE_finish:
8650    cmp     r9, #0                      @ check object for null
8651    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8652    beq     common_errNullObject        @ object was null
8653    mov     r2, rINST, lsr #8           @ r2<- A+
8654    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
8655    and     r2, r2, #15                 @ r2<- A
8656    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8657    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
8658    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8659    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
8660    GOTO_OPCODE(ip)                     @ jump to next instruction
8661
8662
8663/* continuation for OP_IGET_OBJECT */
8664
8665    /*
8666     * Currently:
8667     *  r0 holds resolved field
8668     *  r9 holds object
8669     */
8670.LOP_IGET_OBJECT_finish:
8671    @bl      common_squeak0
8672    cmp     r9, #0                      @ check object for null
8673    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8674    beq     common_errNullObject        @ object was null
8675    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8676    mov     r2, rINST, lsr #8           @ r2<- A+
8677    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8678    and     r2, r2, #15                 @ r2<- A
8679    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8680    SET_VREG(r0, r2)                    @ fp[A]<- r0
8681    GOTO_OPCODE(ip)                     @ jump to next instruction
8682
8683
8684/* continuation for OP_IGET_BOOLEAN */
8685
8686    /*
8687     * Currently:
8688     *  r0 holds resolved field
8689     *  r9 holds object
8690     */
8691.LOP_IGET_BOOLEAN_finish:
8692    @bl      common_squeak1
8693    cmp     r9, #0                      @ check object for null
8694    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8695    beq     common_errNullObject        @ object was null
8696    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8697    mov     r2, rINST, lsr #8           @ r2<- A+
8698    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8699    and     r2, r2, #15                 @ r2<- A
8700    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8701    SET_VREG(r0, r2)                    @ fp[A]<- r0
8702    GOTO_OPCODE(ip)                     @ jump to next instruction
8703
8704
8705/* continuation for OP_IGET_BYTE */
8706
8707    /*
8708     * Currently:
8709     *  r0 holds resolved field
8710     *  r9 holds object
8711     */
8712.LOP_IGET_BYTE_finish:
8713    @bl      common_squeak2
8714    cmp     r9, #0                      @ check object for null
8715    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8716    beq     common_errNullObject        @ object was null
8717    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8718    mov     r2, rINST, lsr #8           @ r2<- A+
8719    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8720    and     r2, r2, #15                 @ r2<- A
8721    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8722    SET_VREG(r0, r2)                    @ fp[A]<- r0
8723    GOTO_OPCODE(ip)                     @ jump to next instruction
8724
8725
8726/* continuation for OP_IGET_CHAR */
8727
8728    /*
8729     * Currently:
8730     *  r0 holds resolved field
8731     *  r9 holds object
8732     */
8733.LOP_IGET_CHAR_finish:
8734    @bl      common_squeak3
8735    cmp     r9, #0                      @ check object for null
8736    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8737    beq     common_errNullObject        @ object was null
8738    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8739    mov     r2, rINST, lsr #8           @ r2<- A+
8740    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8741    and     r2, r2, #15                 @ r2<- A
8742    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8743    SET_VREG(r0, r2)                    @ fp[A]<- r0
8744    GOTO_OPCODE(ip)                     @ jump to next instruction
8745
8746
8747/* continuation for OP_IGET_SHORT */
8748
8749    /*
8750     * Currently:
8751     *  r0 holds resolved field
8752     *  r9 holds object
8753     */
8754.LOP_IGET_SHORT_finish:
8755    @bl      common_squeak4
8756    cmp     r9, #0                      @ check object for null
8757    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8758    beq     common_errNullObject        @ object was null
8759    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8760    mov     r2, rINST, lsr #8           @ r2<- A+
8761    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8762    and     r2, r2, #15                 @ r2<- A
8763    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8764    SET_VREG(r0, r2)                    @ fp[A]<- r0
8765    GOTO_OPCODE(ip)                     @ jump to next instruction
8766
8767
8768/* continuation for OP_IPUT */
8769
8770    /*
8771     * Currently:
8772     *  r0 holds resolved field
8773     *  r9 holds object
8774     */
8775.LOP_IPUT_finish:
8776    @bl      common_squeak0
8777    mov     r1, rINST, lsr #8           @ r1<- A+
8778    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8779    and     r1, r1, #15                 @ r1<- A
8780    cmp     r9, #0                      @ check object for null
8781    GET_VREG(r0, r1)                    @ r0<- fp[A]
8782    beq     common_errNullObject        @ object was null
8783    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8784    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8785    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8786    GOTO_OPCODE(ip)                     @ jump to next instruction
8787
8788
8789/* continuation for OP_IPUT_WIDE */
8790
8791    /*
8792     * Currently:
8793     *  r0 holds resolved field
8794     *  r9 holds object
8795     */
8796.LOP_IPUT_WIDE_finish:
8797    mov     r2, rINST, lsr #8           @ r2<- A+
8798    cmp     r9, #0                      @ check object for null
8799    and     r2, r2, #15                 @ r2<- A
8800    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8801    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
8802    beq     common_errNullObject        @ object was null
8803    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8804    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
8805    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8806    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0
8807    GOTO_OPCODE(ip)                     @ jump to next instruction
8808
8809
8810/* continuation for OP_IPUT_OBJECT */
8811
8812    /*
8813     * Currently:
8814     *  r0 holds resolved field
8815     *  r9 holds object
8816     */
8817.LOP_IPUT_OBJECT_finish:
8818    @bl      common_squeak0
8819    mov     r1, rINST, lsr #8           @ r1<- A+
8820    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8821    and     r1, r1, #15                 @ r1<- A
8822    cmp     r9, #0                      @ check object for null
8823    GET_VREG(r0, r1)                    @ r0<- fp[A]
8824    beq     common_errNullObject        @ object was null
8825    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8826    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8827    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8828    GOTO_OPCODE(ip)                     @ jump to next instruction
8829
8830
8831/* continuation for OP_IPUT_BOOLEAN */
8832
8833    /*
8834     * Currently:
8835     *  r0 holds resolved field
8836     *  r9 holds object
8837     */
8838.LOP_IPUT_BOOLEAN_finish:
8839    @bl      common_squeak1
8840    mov     r1, rINST, lsr #8           @ r1<- A+
8841    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8842    and     r1, r1, #15                 @ r1<- A
8843    cmp     r9, #0                      @ check object for null
8844    GET_VREG(r0, r1)                    @ r0<- fp[A]
8845    beq     common_errNullObject        @ object was null
8846    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8847    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8848    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8849    GOTO_OPCODE(ip)                     @ jump to next instruction
8850
8851
8852/* continuation for OP_IPUT_BYTE */
8853
8854    /*
8855     * Currently:
8856     *  r0 holds resolved field
8857     *  r9 holds object
8858     */
8859.LOP_IPUT_BYTE_finish:
8860    @bl      common_squeak2
8861    mov     r1, rINST, lsr #8           @ r1<- A+
8862    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8863    and     r1, r1, #15                 @ r1<- A
8864    cmp     r9, #0                      @ check object for null
8865    GET_VREG(r0, r1)                    @ r0<- fp[A]
8866    beq     common_errNullObject        @ object was null
8867    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8868    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8869    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8870    GOTO_OPCODE(ip)                     @ jump to next instruction
8871
8872
8873/* continuation for OP_IPUT_CHAR */
8874
8875    /*
8876     * Currently:
8877     *  r0 holds resolved field
8878     *  r9 holds object
8879     */
8880.LOP_IPUT_CHAR_finish:
8881    @bl      common_squeak3
8882    mov     r1, rINST, lsr #8           @ r1<- A+
8883    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8884    and     r1, r1, #15                 @ r1<- A
8885    cmp     r9, #0                      @ check object for null
8886    GET_VREG(r0, r1)                    @ r0<- fp[A]
8887    beq     common_errNullObject        @ object was null
8888    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8889    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8890    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8891    GOTO_OPCODE(ip)                     @ jump to next instruction
8892
8893
8894/* continuation for OP_IPUT_SHORT */
8895
8896    /*
8897     * Currently:
8898     *  r0 holds resolved field
8899     *  r9 holds object
8900     */
8901.LOP_IPUT_SHORT_finish:
8902    @bl      common_squeak4
8903    mov     r1, rINST, lsr #8           @ r1<- A+
8904    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8905    and     r1, r1, #15                 @ r1<- A
8906    cmp     r9, #0                      @ check object for null
8907    GET_VREG(r0, r1)                    @ r0<- fp[A]
8908    beq     common_errNullObject        @ object was null
8909    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8910    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8911    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8912    GOTO_OPCODE(ip)                     @ jump to next instruction
8913
8914
8915/* continuation for OP_SGET */
8916
8917    /*
8918     * Continuation if the field has not yet been resolved.
8919     *  r1: BBBB field ref
8920     */
8921.LOP_SGET_resolve:
8922    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8923    EXPORT_PC()                         @ resolve() could throw, so export now
8924    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8925    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8926    cmp     r0, #0                      @ success?
8927    bne     .LOP_SGET_finish          @ yes, finish
8928    b       common_exceptionThrown      @ no, handle exception
8929
8930
8931/* continuation for OP_SGET_WIDE */
8932
8933    /*
8934     * Continuation if the field has not yet been resolved.
8935     *  r1: BBBB field ref
8936     */
8937.LOP_SGET_WIDE_resolve:
8938    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8939    EXPORT_PC()                         @ resolve() could throw, so export now
8940    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8941    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8942    cmp     r0, #0                      @ success?
8943    bne     .LOP_SGET_WIDE_finish          @ yes, finish
8944    b       common_exceptionThrown      @ no, handle exception
8945
8946
8947/* continuation for OP_SGET_OBJECT */
8948
8949    /*
8950     * Continuation if the field has not yet been resolved.
8951     *  r1: BBBB field ref
8952     */
8953.LOP_SGET_OBJECT_resolve:
8954    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8955    EXPORT_PC()                         @ resolve() could throw, so export now
8956    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8957    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8958    cmp     r0, #0                      @ success?
8959    bne     .LOP_SGET_OBJECT_finish          @ yes, finish
8960    b       common_exceptionThrown      @ no, handle exception
8961
8962
8963/* continuation for OP_SGET_BOOLEAN */
8964
8965    /*
8966     * Continuation if the field has not yet been resolved.
8967     *  r1: BBBB field ref
8968     */
8969.LOP_SGET_BOOLEAN_resolve:
8970    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8971    EXPORT_PC()                         @ resolve() could throw, so export now
8972    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8973    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8974    cmp     r0, #0                      @ success?
8975    bne     .LOP_SGET_BOOLEAN_finish          @ yes, finish
8976    b       common_exceptionThrown      @ no, handle exception
8977
8978
8979/* continuation for OP_SGET_BYTE */
8980
8981    /*
8982     * Continuation if the field has not yet been resolved.
8983     *  r1: BBBB field ref
8984     */
8985.LOP_SGET_BYTE_resolve:
8986    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8987    EXPORT_PC()                         @ resolve() could throw, so export now
8988    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8989    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8990    cmp     r0, #0                      @ success?
8991    bne     .LOP_SGET_BYTE_finish          @ yes, finish
8992    b       common_exceptionThrown      @ no, handle exception
8993
8994
8995/* continuation for OP_SGET_CHAR */
8996
8997    /*
8998     * Continuation if the field has not yet been resolved.
8999     *  r1: BBBB field ref
9000     */
9001.LOP_SGET_CHAR_resolve:
9002    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9003    EXPORT_PC()                         @ resolve() could throw, so export now
9004    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9005    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9006    cmp     r0, #0                      @ success?
9007    bne     .LOP_SGET_CHAR_finish          @ yes, finish
9008    b       common_exceptionThrown      @ no, handle exception
9009
9010
9011/* continuation for OP_SGET_SHORT */
9012
9013    /*
9014     * Continuation if the field has not yet been resolved.
9015     *  r1: BBBB field ref
9016     */
9017.LOP_SGET_SHORT_resolve:
9018    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9019    EXPORT_PC()                         @ resolve() could throw, so export now
9020    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9021    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9022    cmp     r0, #0                      @ success?
9023    bne     .LOP_SGET_SHORT_finish          @ yes, finish
9024    b       common_exceptionThrown      @ no, handle exception
9025
9026
9027/* continuation for OP_SPUT */
9028
9029    /*
9030     * Continuation if the field has not yet been resolved.
9031     *  r1: BBBB field ref
9032     */
9033.LOP_SPUT_resolve:
9034    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9035    EXPORT_PC()                         @ resolve() could throw, so export now
9036    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9037    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9038    cmp     r0, #0                      @ success?
9039    bne     .LOP_SPUT_finish          @ yes, finish
9040    b       common_exceptionThrown      @ no, handle exception
9041
9042
9043/* continuation for OP_SPUT_WIDE */
9044
9045    /*
9046     * Continuation if the field has not yet been resolved.
9047     *  r1: BBBB field ref
9048     *  r9: &fp[AA]
9049     */
9050.LOP_SPUT_WIDE_resolve:
9051    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9052    EXPORT_PC()                         @ resolve() could throw, so export now
9053    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9054    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9055    cmp     r0, #0                      @ success?
9056    bne     .LOP_SPUT_WIDE_finish          @ yes, finish
9057    b       common_exceptionThrown      @ no, handle exception
9058
9059
9060/* continuation for OP_SPUT_OBJECT */
9061
9062    /*
9063     * Continuation if the field has not yet been resolved.
9064     *  r1: BBBB field ref
9065     */
9066.LOP_SPUT_OBJECT_resolve:
9067    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9068    EXPORT_PC()                         @ resolve() could throw, so export now
9069    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9070    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9071    cmp     r0, #0                      @ success?
9072    bne     .LOP_SPUT_OBJECT_finish          @ yes, finish
9073    b       common_exceptionThrown      @ no, handle exception
9074
9075
9076/* continuation for OP_SPUT_BOOLEAN */
9077
9078    /*
9079     * Continuation if the field has not yet been resolved.
9080     *  r1: BBBB field ref
9081     */
9082.LOP_SPUT_BOOLEAN_resolve:
9083    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9084    EXPORT_PC()                         @ resolve() could throw, so export now
9085    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9086    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9087    cmp     r0, #0                      @ success?
9088    bne     .LOP_SPUT_BOOLEAN_finish          @ yes, finish
9089    b       common_exceptionThrown      @ no, handle exception
9090
9091
9092/* continuation for OP_SPUT_BYTE */
9093
9094    /*
9095     * Continuation if the field has not yet been resolved.
9096     *  r1: BBBB field ref
9097     */
9098.LOP_SPUT_BYTE_resolve:
9099    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9100    EXPORT_PC()                         @ resolve() could throw, so export now
9101    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9102    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9103    cmp     r0, #0                      @ success?
9104    bne     .LOP_SPUT_BYTE_finish          @ yes, finish
9105    b       common_exceptionThrown      @ no, handle exception
9106
9107
9108/* continuation for OP_SPUT_CHAR */
9109
9110    /*
9111     * Continuation if the field has not yet been resolved.
9112     *  r1: BBBB field ref
9113     */
9114.LOP_SPUT_CHAR_resolve:
9115    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9116    EXPORT_PC()                         @ resolve() could throw, so export now
9117    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9118    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9119    cmp     r0, #0                      @ success?
9120    bne     .LOP_SPUT_CHAR_finish          @ yes, finish
9121    b       common_exceptionThrown      @ no, handle exception
9122
9123
9124/* continuation for OP_SPUT_SHORT */
9125
9126    /*
9127     * Continuation if the field has not yet been resolved.
9128     *  r1: BBBB field ref
9129     */
9130.LOP_SPUT_SHORT_resolve:
9131    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9132    EXPORT_PC()                         @ resolve() could throw, so export now
9133    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9134    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9135    cmp     r0, #0                      @ success?
9136    bne     .LOP_SPUT_SHORT_finish          @ yes, finish
9137    b       common_exceptionThrown      @ no, handle exception
9138
9139
9140/* continuation for OP_INVOKE_VIRTUAL */
9141
9142    /*
9143     * At this point:
9144     *  r0 = resolved base method
9145     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
9146     */
9147.LOP_INVOKE_VIRTUAL_continue:
9148    GET_VREG(r1, r10)                   @ r1<- "this" ptr
9149    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
9150    cmp     r1, #0                      @ is "this" null?
9151    beq     common_errNullObject        @ null "this", throw exception
9152    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
9153    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
9154    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
9155    bl      common_invokeMethodNoRange @ continue on
9156
9157
9158/* continuation for OP_INVOKE_SUPER */
9159
9160    /*
9161     * At this point:
9162     *  r0 = resolved base method
9163     *  r9 = method->clazz
9164     */
9165.LOP_INVOKE_SUPER_continue:
9166    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
9167    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
9168    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
9169    EXPORT_PC()                         @ must export for invoke
9170    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
9171    bcs     .LOP_INVOKE_SUPER_nsm             @ method not present in superclass
9172    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
9173    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
9174    bl      common_invokeMethodNoRange @ continue on
9175
9176.LOP_INVOKE_SUPER_resolve:
9177    mov     r0, r9                      @ r0<- method->clazz
9178    mov     r2, #METHOD_VIRTUAL         @ resolver method type
9179    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
9180    cmp     r0, #0                      @ got null?
9181    bne     .LOP_INVOKE_SUPER_continue        @ no, continue
9182    b       common_exceptionThrown      @ yes, handle exception
9183
9184    /*
9185     * Throw a NoSuchMethodError with the method name as the message.
9186     *  r0 = resolved base method
9187     */
9188.LOP_INVOKE_SUPER_nsm:
9189    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
9190    b       common_errNoSuchMethod
9191
9192
9193/* continuation for OP_INVOKE_DIRECT */
9194
9195    /*
9196     * On entry:
9197     *  r1 = reference (BBBB or CCCC)
9198     *  r10 = "this" register
9199     */
9200.LOP_INVOKE_DIRECT_resolve:
9201    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
9202    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
9203    mov     r2, #METHOD_DIRECT          @ resolver method type
9204    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
9205    cmp     r0, #0                      @ got null?
9206    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
9207    bne     .LOP_INVOKE_DIRECT_finish          @ no, continue
9208    b       common_exceptionThrown      @ yes, handle exception
9209
9210
9211/* continuation for OP_INVOKE_VIRTUAL_RANGE */
9212
9213    /*
9214     * At this point:
9215     *  r0 = resolved base method
9216     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
9217     */
9218.LOP_INVOKE_VIRTUAL_RANGE_continue:
9219    GET_VREG(r1, r10)                   @ r1<- "this" ptr
9220    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
9221    cmp     r1, #0                      @ is "this" null?
9222    beq     common_errNullObject        @ null "this", throw exception
9223    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
9224    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
9225    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
9226    bl      common_invokeMethodRange @ continue on
9227
9228
9229/* continuation for OP_INVOKE_SUPER_RANGE */
9230
9231    /*
9232     * At this point:
9233     *  r0 = resolved base method
9234     *  r9 = method->clazz
9235     */
9236.LOP_INVOKE_SUPER_RANGE_continue:
9237    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
9238    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
9239    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
9240    EXPORT_PC()                         @ must export for invoke
9241    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
9242    bcs     .LOP_INVOKE_SUPER_RANGE_nsm             @ method not present in superclass
9243    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
9244    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
9245    bl      common_invokeMethodRange @ continue on
9246
9247.LOP_INVOKE_SUPER_RANGE_resolve:
9248    mov     r0, r9                      @ r0<- method->clazz
9249    mov     r2, #METHOD_VIRTUAL         @ resolver method type
9250    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
9251    cmp     r0, #0                      @ got null?
9252    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ no, continue
9253    b       common_exceptionThrown      @ yes, handle exception
9254
9255    /*
9256     * Throw a NoSuchMethodError with the method name as the message.
9257     *  r0 = resolved base method
9258     */
9259.LOP_INVOKE_SUPER_RANGE_nsm:
9260    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
9261    b       common_errNoSuchMethod
9262
9263
9264/* continuation for OP_INVOKE_DIRECT_RANGE */
9265
9266    /*
9267     * On entry:
9268     *  r1 = reference (BBBB or CCCC)
9269     *  r10 = "this" register
9270     */
9271.LOP_INVOKE_DIRECT_RANGE_resolve:
9272    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
9273    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
9274    mov     r2, #METHOD_DIRECT          @ resolver method type
9275    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
9276    cmp     r0, #0                      @ got null?
9277    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
9278    bne     .LOP_INVOKE_DIRECT_RANGE_finish          @ no, continue
9279    b       common_exceptionThrown      @ yes, handle exception
9280
9281
9282/* continuation for OP_FLOAT_TO_LONG */
9283/*
9284 * Convert the float in r0 to a long in r0/r1.
9285 *
9286 * We have to clip values to long min/max per the specification.  The
9287 * expected common case is a "reasonable" value that converts directly
9288 * to modest integer.  The EABI convert function isn't doing this for us.
9289 */
9290f2l_doconv:
9291    stmfd   sp!, {r4, lr}
9292    mov     r1, #0x5f000000             @ (float)maxlong
9293    mov     r4, r0
9294    bl      __aeabi_fcmpge              @ is arg >= maxlong?
9295    cmp     r0, #0                      @ nonzero == yes
9296    mvnne   r0, #0                      @ return maxlong (7fffffff)
9297    mvnne   r1, #0x80000000
9298    ldmnefd sp!, {r4, pc}
9299
9300    mov     r0, r4                      @ recover arg
9301    mov     r1, #0xdf000000             @ (float)minlong
9302    bl      __aeabi_fcmple              @ is arg <= minlong?
9303    cmp     r0, #0                      @ nonzero == yes
9304    movne   r0, #0                      @ return minlong (80000000)
9305    movne   r1, #0x80000000
9306    ldmnefd sp!, {r4, pc}
9307
9308    mov     r0, r4                      @ recover arg
9309    mov     r1, r4
9310    bl      __aeabi_fcmpeq              @ is arg == self?
9311    cmp     r0, #0                      @ zero == no
9312    moveq   r1, #0                      @ return zero for NaN
9313    ldmeqfd sp!, {r4, pc}
9314
9315    mov     r0, r4                      @ recover arg
9316    bl      __aeabi_f2lz                @ convert float to long
9317    ldmfd   sp!, {r4, pc}
9318
9319
9320/* continuation for OP_DOUBLE_TO_LONG */
9321/*
9322 * Convert the double in r0/r1 to a long in r0/r1.
9323 *
9324 * We have to clip values to long min/max per the specification.  The
9325 * expected common case is a "reasonable" value that converts directly
9326 * to modest integer.  The EABI convert function isn't doing this for us.
9327 */
9328d2l_doconv:
9329    stmfd   sp!, {r4, r5, lr}           @ save regs
9330    ldr     r3, .LOP_DOUBLE_TO_LONG_max         @ (double)maxlong, hi
9331    sub     sp, sp, #4                  @ align for EABI
9332    mov     r2, #0                      @ (double)maxlong, lo
9333    mov     r4, r0                      @ save r0
9334    mov     r5, r1                      @  and r1
9335    bl      __aeabi_dcmpge              @ is arg >= maxlong?
9336    cmp     r0, #0                      @ nonzero == yes
9337    mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
9338    mvnne   r1, #0x80000000
9339    bne     1f
9340
9341    mov     r0, r4                      @ recover arg
9342    mov     r1, r5
9343    ldr     r3, .LOP_DOUBLE_TO_LONG_min         @ (double)minlong, hi
9344    mov     r2, #0                      @ (double)minlong, lo
9345    bl      __aeabi_dcmple              @ is arg <= minlong?
9346    cmp     r0, #0                      @ nonzero == yes
9347    movne   r0, #0                      @ return minlong (8000000000000000)
9348    movne   r1, #0x80000000
9349    bne     1f
9350
9351    mov     r0, r4                      @ recover arg
9352    mov     r1, r5
9353    mov     r2, r4                      @ compare against self
9354    mov     r3, r5
9355    bl      __aeabi_dcmpeq              @ is arg == self?
9356    cmp     r0, #0                      @ zero == no
9357    moveq   r1, #0                      @ return zero for NaN
9358    beq     1f
9359
9360    mov     r0, r4                      @ recover arg
9361    mov     r1, r5
9362    bl      __aeabi_d2lz                @ convert double to long
9363
93641:
9365    add     sp, sp, #4
9366    ldmfd   sp!, {r4, r5, pc}
9367
9368.LOP_DOUBLE_TO_LONG_max:
9369    .word   0x43e00000                  @ maxlong, as a double (high word)
9370.LOP_DOUBLE_TO_LONG_min:
9371    .word   0xc3e00000                  @ minlong, as a double (high word)
9372
9373
9374/* continuation for OP_MUL_LONG */
9375
9376.LOP_MUL_LONG_finish:
9377    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9378    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
9379    GOTO_OPCODE(ip)                     @ jump to next instruction
9380
9381
9382/* continuation for OP_SHL_LONG */
9383
9384.LOP_SHL_LONG_finish:
9385    mov     r0, r0, asl r2              @  r0<- r0 << r2
9386    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9387    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9388    GOTO_OPCODE(ip)                     @ jump to next instruction
9389
9390
9391/* continuation for OP_SHR_LONG */
9392
9393.LOP_SHR_LONG_finish:
9394    mov     r1, r1, asr r2              @  r1<- r1 >> r2
9395    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9396    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9397    GOTO_OPCODE(ip)                     @ jump to next instruction
9398
9399
9400/* continuation for OP_USHR_LONG */
9401
9402.LOP_USHR_LONG_finish:
9403    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
9404    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9405    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9406    GOTO_OPCODE(ip)                     @ jump to next instruction
9407
9408
9409/* continuation for OP_SHL_LONG_2ADDR */
9410
9411.LOP_SHL_LONG_2ADDR_finish:
9412    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9413    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9414    GOTO_OPCODE(ip)                     @ jump to next instruction
9415
9416
9417/* continuation for OP_SHR_LONG_2ADDR */
9418
9419.LOP_SHR_LONG_2ADDR_finish:
9420    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9421    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9422    GOTO_OPCODE(ip)                     @ jump to next instruction
9423
9424
9425/* continuation for OP_USHR_LONG_2ADDR */
9426
9427.LOP_USHR_LONG_2ADDR_finish:
9428    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9429    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9430    GOTO_OPCODE(ip)                     @ jump to next instruction
9431
9432
9433/* continuation for OP_EXECUTE_INLINE */
9434
9435    /*
9436     * Extract args, call function.
9437     *  r0 = #of args (0-4)
9438     *  r10 = call index
9439     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
9440     *
9441     * Other ideas:
9442     * - Use a jump table from the main piece to jump directly into the
9443     *   AND/LDR pairs.  Costs a data load, saves a branch.
9444     * - Have five separate pieces that do the loading, so we can work the
9445     *   interleave a little better.  Increases code size.
9446     */
9447.LOP_EXECUTE_INLINE_continue:
9448    rsb     r0, r0, #4                  @ r0<- 4-r0
9449    FETCH(r9, 2)                        @ r9<- FEDC
9450    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
9451    bl      common_abort                @ (skipped due to ARM prefetch)
94524:  and     ip, r9, #0xf000             @ isolate F
9453    ldr     r3, [rFP, ip, lsr #10]      @ r3<- vF (shift right 12, left 2)
94543:  and     ip, r9, #0x0f00             @ isolate E
9455    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vE
94562:  and     ip, r9, #0x00f0             @ isolate D
9457    ldr     r1, [rFP, ip, lsr #2]       @ r1<- vD
94581:  and     ip, r9, #0x000f             @ isolate C
9459    ldr     r0, [rFP, ip, lsl #2]       @ r0<- vC
94600:
9461    ldr     r9, .LOP_EXECUTE_INLINE_table       @ table of InlineOperation
9462    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
9463    @ (not reached)
9464
9465.LOP_EXECUTE_INLINE_table:
9466    .word   gDvmInlineOpsTable
9467
9468
9469    .size   dvmAsmSisterStart, .-dvmAsmSisterStart
9470    .global dvmAsmSisterEnd
9471dvmAsmSisterEnd:
9472
9473/* File: armv5te/footer.S */
9474
9475/*
9476 * ===========================================================================
9477 *  Common subroutines and data
9478 * ===========================================================================
9479 */
9480
9481
9482
9483    .text
9484    .align  2
9485
9486#if defined(WITH_JIT)
9487/*
9488 * Return from the translation cache to the interpreter when the compiler is
9489 * having issues translating/executing a Dalvik instruction. We have to skip
9490 * the code cache lookup otherwise it is possible to indefinitely bouce
9491 * between the interpreter and the code cache if the instruction that fails
9492 * to be compiled happens to be at a trace start.
9493 */
9494    .global dvmJitToInterpPunt
9495dvmJitToInterpPunt:
9496    mov    rPC, r0
9497#ifdef EXIT_STATS
9498    mov    r0,lr
9499    bl     dvmBumpPunt;
9500#endif
9501    EXPORT_PC()
9502    adrl   rIBASE, dvmAsmInstructionStart
9503    FETCH_INST()
9504    GET_INST_OPCODE(ip)
9505    GOTO_OPCODE(ip)
9506
9507/*
9508 * Return to the interpreter to handle a single instruction.
9509 * On entry:
9510 *    r0 <= PC
9511 *    r1 <= PC of resume instruction
9512 *    lr <= resume point in translation
9513 */
9514    .global dvmJitToInterpSingleStep
9515dvmJitToInterpSingleStep:
9516    str    lr,[rGLUE,#offGlue_jitResume]
9517    str    r1,[rGLUE,#offGlue_jitResumePC]
9518    mov    r1,#kInterpEntryInstr
9519    @ enum is 4 byte in aapcs-EABI
9520    str    r1, [rGLUE, #offGlue_entryPoint]
9521    mov    rPC,r0
9522    EXPORT_PC()
9523    adrl   rIBASE, dvmAsmInstructionStart
9524    mov    r2,#kJitSingleStep     @ Ask for single step and then revert
9525    str    r2,[rGLUE,#offGlue_jitState]
9526    mov    r1,#1                  @ set changeInterp to bail to debug interp
9527    b      common_gotoBail
9528
9529
9530/*
9531 * Return from the translation cache and immediately request
9532 * a translation for the exit target.  Commonly used following
9533 * invokes.
9534 */
9535    .global dvmJitToTraceSelect
9536dvmJitToTraceSelect:
9537    ldr    rPC,[r14, #-1]           @ get our target PC
9538    add    rINST,r14,#-5            @ save start of chain branch
9539    mov    r0,rPC
9540    bl     dvmJitGetCodeAddr        @ Is there a translation?
9541    cmp    r0,#0
9542    beq    2f
9543    mov    r1,rINST
9544    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9545    cmp    r0,#0                    @ successful chain?
9546    bxne   r0                       @ continue native execution
9547    b      toInterpreter            @ didn't chain - resume with interpreter
9548
9549/* No translation, so request one if profiling isn't disabled*/
95502:
9551    adrl   rIBASE, dvmAsmInstructionStart
9552    GET_JIT_PROF_TABLE(r0)
9553    FETCH_INST()
9554    cmp    r0, #0
9555    bne    common_selectTrace
9556    GET_INST_OPCODE(ip)
9557    GOTO_OPCODE(ip)
9558
9559/*
9560 * Return from the translation cache to the interpreter.
9561 * The return was done with a BLX from thumb mode, and
9562 * the following 32-bit word contains the target rPC value.
9563 * Note that lr (r14) will have its low-order bit set to denote
9564 * its thumb-mode origin.
9565 *
9566 * We'll need to stash our lr origin away, recover the new
9567 * target and then check to see if there is a translation available
9568 * for our new target.  If so, we do a translation chain and
9569 * go back to native execution.  Otherwise, it's back to the
9570 * interpreter (after treating this entry as a potential
9571 * trace start).
9572 */
9573    .global dvmJitToInterpNormal
9574dvmJitToInterpNormal:
9575    ldr    rPC,[r14, #-1]           @ get our target PC
9576    add    rINST,r14,#-5            @ save start of chain branch
9577#ifdef EXIT_STATS
9578    bl     dvmBumpNormal
9579#endif
9580    mov    r0,rPC
9581    bl     dvmJitGetCodeAddr        @ Is there a translation?
9582    cmp    r0,#0
9583    beq    toInterpreter            @ go if not, otherwise do chain
9584    mov    r1,rINST
9585    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9586    cmp    r0,#0                    @ successful chain?
9587    bxne   r0                       @ continue native execution
9588    b      toInterpreter            @ didn't chain - resume with interpreter
9589
9590/*
9591 * Return from the translation cache to the interpreter to do method invocation.
9592 * Check if translation exists for the callee, but don't chain to it.
9593 */
9594    .global dvmJitToInterpNoChain
9595dvmJitToInterpNoChain:
9596#ifdef EXIT_STATS
9597    bl     dvmBumpNoChain
9598#endif
9599    mov    r0,rPC
9600    bl     dvmJitGetCodeAddr        @ Is there a translation?
9601    cmp    r0,#0
9602    bxne   r0                       @ continue native execution if so
9603
9604/*
9605 * No translation, restore interpreter regs and start interpreting.
9606 * rGLUE & rFP were preserved in the translated code, and rPC has
9607 * already been restored by the time we get here.  We'll need to set
9608 * up rIBASE & rINST, and load the address of the JitTable into r0.
9609 */
9610toInterpreter:
9611    EXPORT_PC()
9612    adrl   rIBASE, dvmAsmInstructionStart
9613    FETCH_INST()
9614    GET_JIT_PROF_TABLE(r0)
9615    @ NOTE: intended fallthrough
9616/*
9617 * Common code to update potential trace start counter, and initiate
9618 * a trace-build if appropriate.  On entry, rPC should point to the
9619 * next instruction to execute, and rINST should be already loaded with
9620 * the next opcode word, and r0 holds a pointer to the jit profile
9621 * table (pJitProfTable).
9622 */
9623common_testUpdateProfile:
9624    cmp     r0,#0
9625    GET_INST_OPCODE(ip)
9626    GOTO_OPCODE_IFEQ(ip)       @ if not profiling, fallthrough otherwise */
9627
9628common_updateProfile:
9629    eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
9630    lsl     r3,r3,#23          @ shift out excess 511
9631    ldrb    r1,[r0,r3,lsr #23] @ get counter
9632    GET_INST_OPCODE(ip)
9633    subs    r1,r1,#1           @ decrement counter
9634    strb    r1,[r0,r3,lsr #23] @ and store it
9635    GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
9636
9637/*
9638 * Here, we switch to the debug interpreter to request
9639 * trace selection.  First, though, check to see if there
9640 * is already a native translation in place (and, if so,
9641 * jump to it now).
9642 */
9643    mov     r1,#255
9644    strb    r1,[r0,r3,lsr #23] @ reset counter
9645    EXPORT_PC()
9646    mov     r0,rPC
9647    bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
9648    cmp     r0,#0
9649    beq     common_selectTrace
9650    bxne    r0                          @ jump to the translation
9651common_selectTrace:
9652    mov     r2,#kJitTSelectRequest      @ ask for trace selection
9653    str     r2,[rGLUE,#offGlue_jitState]
9654    mov     r1,#1                       @ set changeInterp
9655    b       common_gotoBail
9656
9657#endif
9658
9659/*
9660 * Common code when a backward branch is taken.
9661 *
9662 * On entry:
9663 *  r9 is PC adjustment *in bytes*
9664 */
9665common_backwardBranch:
9666    mov     r0, #kInterpEntryInstr
9667    bl      common_periodicChecks
9668#if defined(WITH_JIT)
9669    GET_JIT_PROF_TABLE(r0)
9670    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9671    cmp     r0,#0
9672    bne     common_updateProfile
9673    GET_INST_OPCODE(ip)
9674    GOTO_OPCODE(ip)
9675#else
9676    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9677    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9678    GOTO_OPCODE(ip)                     @ jump to next instruction
9679#endif
9680
9681
9682/*
9683 * Need to see if the thread needs to be suspended or debugger/profiler
9684 * activity has begun.
9685 *
9686 * TODO: if JDWP isn't running, zero out pDebuggerActive pointer so we don't
9687 * have to do the second ldr.
9688 *
9689 * TODO: reduce this so we're just checking a single location.
9690 *
9691 * On entry:
9692 *  r0 is reentry type, e.g. kInterpEntryInstr
9693 *  r9 is trampoline PC adjustment *in bytes*
9694 */
9695common_periodicChecks:
9696    ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
9697
9698#if defined(WITH_DEBUGGER)
9699    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9700#endif
9701#if defined(WITH_PROFILER)
9702    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9703#endif
9704
9705    ldr     r3, [r3]                    @ r3<- suspendCount (int)
9706
9707#if defined(WITH_DEBUGGER)
9708    ldrb    r1, [r1]                    @ r1<- debuggerActive (boolean)
9709#endif
9710#if defined (WITH_PROFILER)
9711    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9712#endif
9713
9714    cmp     r3, #0                      @ suspend pending?
9715    bne     2f                          @ yes, do full suspension check
9716
9717#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
9718# if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
9719    orrs    r1, r1, r2                  @ r1<- r1 | r2
9720    cmp     r1, #0                      @ debugger attached or profiler started?
9721# elif defined(WITH_DEBUGGER)
9722    cmp     r1, #0                      @ debugger attached?
9723# elif defined(WITH_PROFILER)
9724    cmp     r2, #0                      @ profiler started?
9725# endif
9726    bne     3f                          @ debugger/profiler, switch interp
9727#endif
9728
9729    bx      lr                          @ nothing to do, return
9730
97312:  @ check suspend
9732    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9733    EXPORT_PC()                         @ need for precise GC
9734    b       dvmCheckSuspendPending      @ suspend if necessary, then return
9735
97363:  @ debugger/profiler enabled, bail out
9737    add     rPC, rPC, r9                @ update rPC
9738    str     r0, [rGLUE, #offGlue_entryPoint]
9739    mov     r1, #1                      @ "want switch" = true
9740    b       common_gotoBail
9741
9742
9743/*
9744 * The equivalent of "goto bail", this calls through the "bail handler".
9745 *
9746 * State registers will be saved to the "glue" area before bailing.
9747 *
9748 * On entry:
9749 *  r1 is "bool changeInterp", indicating if we want to switch to the
9750 *     other interpreter or just bail all the way out
9751 */
9752common_gotoBail:
9753    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9754    mov     r0, rGLUE                   @ r0<- glue ptr
9755    b       dvmMterpStdBail             @ call(glue, changeInterp)
9756
9757    @add     r1, r1, #1                  @ using (boolean+1)
9758    @add     r0, rGLUE, #offGlue_jmpBuf  @ r0<- &glue->jmpBuf
9759    @bl      _longjmp                    @ does not return
9760    @bl      common_abort
9761
9762
9763/*
9764 * Common code for method invocation with range.
9765 *
9766 * On entry:
9767 *  r0 is "Method* methodToCall", the method we're trying to call
9768 */
9769common_invokeMethodRange:
9770.LinvokeNewRange:
9771    @ prepare to copy args to "outs" area of current frame
9772    movs    r2, rINST, lsr #8           @ r2<- AA (arg count) -- test for zero
9773    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9774    beq     .LinvokeArgsDone            @ if no args, skip the rest
9775    FETCH(r1, 2)                        @ r1<- CCCC
9776
9777    @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
9778    @ (very few methods have > 10 args; could unroll for common cases)
9779    add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
9780    sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
9781    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
97821:  ldr     r1, [r3], #4                @ val = *fp++
9783    subs    r2, r2, #1                  @ count--
9784    str     r1, [r10], #4               @ *outs++ = val
9785    bne     1b                          @ ...while count != 0
9786    ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
9787    b       .LinvokeArgsDone
9788
9789/*
9790 * Common code for method invocation without range.
9791 *
9792 * On entry:
9793 *  r0 is "Method* methodToCall", the method we're trying to call
9794 */
9795common_invokeMethodNoRange:
9796.LinvokeNewNoRange:
9797    @ prepare to copy args to "outs" area of current frame
9798    movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
9799    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9800    FETCH(r1, 2)                        @ r1<- GFED (load here to hide latency)
9801    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
9802    ldrh    r3, [r0, #offMethod_outsSize]  @ r3<- methodToCall->outsSize
9803    beq     .LinvokeArgsDone
9804
9805    @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
9806.LinvokeNonRange:
9807    rsb     r2, r2, #5                  @ r2<- 5-r2
9808    add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
9809    bl      common_abort                @ (skipped due to ARM prefetch)
98105:  and     ip, rINST, #0x0f00          @ isolate A
9811    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vA (shift right 8, left 2)
9812    mov     r0, r0                      @ nop
9813    str     r2, [r10, #-4]!             @ *--outs = vA
98144:  and     ip, r1, #0xf000             @ isolate G
9815    ldr     r2, [rFP, ip, lsr #10]      @ r2<- vG (shift right 12, left 2)
9816    mov     r0, r0                      @ nop
9817    str     r2, [r10, #-4]!             @ *--outs = vG
98183:  and     ip, r1, #0x0f00             @ isolate F
9819    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vF
9820    mov     r0, r0                      @ nop
9821    str     r2, [r10, #-4]!             @ *--outs = vF
98222:  and     ip, r1, #0x00f0             @ isolate E
9823    ldr     r2, [rFP, ip, lsr #2]       @ r2<- vE
9824    mov     r0, r0                      @ nop
9825    str     r2, [r10, #-4]!             @ *--outs = vE
98261:  and     ip, r1, #0x000f             @ isolate D
9827    ldr     r2, [rFP, ip, lsl #2]       @ r2<- vD
9828    mov     r0, r0                      @ nop
9829    str     r2, [r10, #-4]!             @ *--outs = vD
98300:  @ fall through to .LinvokeArgsDone
9831
9832.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
9833    ldr     r2, [r0, #offMethod_insns]  @ r2<- method->insns
9834    ldr     rINST, [r0, #offMethod_clazz]  @ rINST<- method->clazz
9835    @ find space for the new stack frame, check for overflow
9836    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
9837    sub     r1, r1, r9, lsl #2          @ r1<- newFp (old savearea - regsSize)
9838    SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
9839@    bl      common_dumpRegs
9840    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
9841    sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
9842    cmp     r3, r9                      @ bottom < interpStackEnd?
9843    ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
9844    blt     .LstackOverflow             @ yes, this frame will overflow stack
9845
9846    @ set up newSaveArea
9847#ifdef EASY_GDB
9848    SAVEAREA_FROM_FP(ip, rFP)           @ ip<- stack save area
9849    str     ip, [r10, #offStackSaveArea_prevSave]
9850#endif
9851    str     rFP, [r10, #offStackSaveArea_prevFrame]
9852    str     rPC, [r10, #offStackSaveArea_savedPc]
9853#if defined(WITH_JIT)
9854    mov     r9, #0
9855    str     r9, [r10, #offStackSaveArea_returnAddr]
9856#endif
9857    str     r0, [r10, #offStackSaveArea_method]
9858    tst     r3, #ACC_NATIVE
9859    bne     .LinvokeNative
9860
9861    /*
9862    stmfd   sp!, {r0-r3}
9863    bl      common_printNewline
9864    mov     r0, rFP
9865    mov     r1, #0
9866    bl      dvmDumpFp
9867    ldmfd   sp!, {r0-r3}
9868    stmfd   sp!, {r0-r3}
9869    mov     r0, r1
9870    mov     r1, r10
9871    bl      dvmDumpFp
9872    bl      common_printNewline
9873    ldmfd   sp!, {r0-r3}
9874    */
9875
9876    ldrh    r9, [r2]                        @ r9 <- load INST from new PC
9877    ldr     r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
9878    mov     rPC, r2                         @ publish new rPC
9879    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
9880
9881    @ Update "glue" values for the new method
9882    @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
9883    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
9884    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
9885#if defined(WITH_JIT)
9886    GET_JIT_PROF_TABLE(r0)
9887    mov     rFP, r1                         @ fp = newFp
9888    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
9889    mov     rINST, r9                       @ publish new rINST
9890    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
9891    cmp     r0,#0
9892    bne     common_updateProfile
9893    GOTO_OPCODE(ip)                         @ jump to next instruction
9894#else
9895    mov     rFP, r1                         @ fp = newFp
9896    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
9897    mov     rINST, r9                       @ publish new rINST
9898    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
9899    GOTO_OPCODE(ip)                         @ jump to next instruction
9900#endif
9901
9902.LinvokeNative:
9903    @ Prep for the native call
9904    @ r0=methodToCall, r1=newFp, r10=newSaveArea
9905    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
9906    ldr     r9, [r3, #offThread_jniLocal_nextEntry] @ r9<- thread->refNext
9907    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
9908    str     r9, [r10, #offStackSaveArea_localRefTop] @newFp->localRefTop=refNext
9909    mov     r9, r3                      @ r9<- glue->self (preserve)
9910
9911    mov     r2, r0                      @ r2<- methodToCall
9912    mov     r0, r1                      @ r0<- newFp (points to args)
9913    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
9914
9915#ifdef ASSIST_DEBUGGER
9916    /* insert fake function header to help gdb find the stack frame */
9917    b       .Lskip
9918    .type   dalvik_mterp, %function
9919dalvik_mterp:
9920    .fnstart
9921    MTERP_ENTRY1
9922    MTERP_ENTRY2
9923.Lskip:
9924#endif
9925
9926    @mov     lr, pc                      @ set return addr
9927    @ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
9928    LDR_PC_LR "[r2, #offMethod_nativeFunc]"
9929
9930    @ native return; r9=self, r10=newSaveArea
9931    @ equivalent to dvmPopJniLocals
9932    ldr     r0, [r10, #offStackSaveArea_localRefTop] @ r0<- newSave->localRefTop
9933    ldr     r1, [r9, #offThread_exception] @ check for exception
9934    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
9935    cmp     r1, #0                      @ null?
9936    str     r0, [r9, #offThread_jniLocal_nextEntry] @ self->refNext<- r0
9937    bne     common_exceptionThrown      @ no, handle exception
9938
9939    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
9940    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9941    GOTO_OPCODE(ip)                     @ jump to next instruction
9942
9943.LstackOverflow:
9944    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
9945    bl      dvmHandleStackOverflow
9946    b       common_exceptionThrown
9947#ifdef ASSIST_DEBUGGER
9948    .fnend
9949#endif
9950
9951
9952    /*
9953     * Common code for method invocation, calling through "glue code".
9954     *
9955     * TODO: now that we have range and non-range invoke handlers, this
9956     *       needs to be split into two.  Maybe just create entry points
9957     *       that set r9 and jump here?
9958     *
9959     * On entry:
9960     *  r0 is "Method* methodToCall", the method we're trying to call
9961     *  r9 is "bool methodCallRange", indicating if this is a /range variant
9962     */
9963     .if    0
9964.LinvokeOld:
9965    sub     sp, sp, #8                  @ space for args + pad
9966    FETCH(ip, 2)                        @ ip<- FEDC or CCCC
9967    mov     r2, r0                      @ A2<- methodToCall
9968    mov     r0, rGLUE                   @ A0<- glue
9969    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9970    mov     r1, r9                      @ A1<- methodCallRange
9971    mov     r3, rINST, lsr #8           @ A3<- AA
9972    str     ip, [sp, #0]                @ A4<- ip
9973    bl      dvmMterp_invokeMethod       @ call the C invokeMethod
9974    add     sp, sp, #8                  @ remove arg area
9975    b       common_resumeAfterGlueCall  @ continue to next instruction
9976    .endif
9977
9978
9979
9980/*
9981 * Common code for handling a return instruction.
9982 *
9983 * This does not return.
9984 */
9985common_returnFromMethod:
9986.LreturnNew:
9987    mov     r0, #kInterpEntryReturn
9988    mov     r9, #0
9989    bl      common_periodicChecks
9990
9991    SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
9992    ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
9993    ldr     r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
9994    ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
9995                                        @ r2<- method we're returning to
9996    ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
9997    cmp     r2, #0                      @ is this a break frame?
9998    ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
9999    mov     r1, #0                      @ "want switch" = false
10000    beq     common_gotoBail             @ break frame, bail out completely
10001
10002    PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
10003    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
10004    ldr     r1, [r10, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
10005    str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
10006#if defined(WITH_JIT)
10007    ldr     r3, [r0, #offStackSaveArea_returnAddr] @ r3 = saveArea->returnAddr
10008    GET_JIT_PROF_TABLE(r0)
10009    mov     rPC, r9                     @ publish new rPC
10010    str     r1, [rGLUE, #offGlue_methodClassDex]
10011    cmp     r3, #0                      @ caller is compiled code
10012    blxne   r3
10013    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10014    cmp     r0,#0
10015    bne     common_updateProfile
10016    GOTO_OPCODE(ip)                     @ jump to next instruction
10017#else
10018    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10019    mov     rPC, r9                     @ publish new rPC
10020    str     r1, [rGLUE, #offGlue_methodClassDex]
10021    GOTO_OPCODE(ip)                     @ jump to next instruction
10022#endif
10023
10024    /*
10025     * Return handling, calls through "glue code".
10026     */
10027     .if    0
10028.LreturnOld:
10029    SAVE_PC_FP_TO_GLUE()                @ export state
10030    mov     r0, rGLUE                   @ arg to function
10031    bl      dvmMterp_returnFromMethod
10032    b       common_resumeAfterGlueCall
10033    .endif
10034
10035
10036/*
10037 * Somebody has thrown an exception.  Handle it.
10038 *
10039 * If the exception processing code returns to us (instead of falling
10040 * out of the interpreter), continue with whatever the next instruction
10041 * now happens to be.
10042 *
10043 * This does not return.
10044 */
10045     .global dvmMterpCommonExceptionThrown
10046dvmMterpCommonExceptionThrown:
10047common_exceptionThrown:
10048.LexceptionNew:
10049    mov     r0, #kInterpEntryThrow
10050    mov     r9, #0
10051    bl      common_periodicChecks
10052
10053#if defined(WITH_JIT)
10054    mov     r2,#kJitTSelectAbort        @ abandon trace selection in progress
10055    str     r2,[rGLUE,#offGlue_jitState]
10056#endif
10057
10058    ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
10059    ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
10060    mov     r1, r10                     @ r1<- self
10061    mov     r0, r9                      @ r0<- exception
10062    bl      dvmAddTrackedAlloc          @ don't let the exception be GCed
10063    mov     r3, #0                      @ r3<- NULL
10064    str     r3, [r10, #offThread_exception] @ self->exception = NULL
10065
10066    /* set up args and a local for "&fp" */
10067    /* (str sp, [sp, #-4]!  would be perfect here, but is discouraged) */
10068    str     rFP, [sp, #-4]!             @ *--sp = fp
10069    mov     ip, sp                      @ ip<- &fp
10070    mov     r3, #0                      @ r3<- false
10071    str     ip, [sp, #-4]!              @ *--sp = &fp
10072    ldr     r1, [rGLUE, #offGlue_method] @ r1<- glue->method
10073    mov     r0, r10                     @ r0<- self
10074    ldr     r1, [r1, #offMethod_insns]  @ r1<- method->insns
10075    mov     r2, r9                      @ r2<- exception
10076    sub     r1, rPC, r1                 @ r1<- pc - method->insns
10077    mov     r1, r1, asr #1              @ r1<- offset in code units
10078
10079    /* call, r0 gets catchRelPc (a code-unit offset) */
10080    bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
10081
10082    /* fix earlier stack overflow if necessary; may trash rFP */
10083    ldrb    r1, [r10, #offThread_stackOverflowed]
10084    cmp     r1, #0                      @ did we overflow earlier?
10085    beq     1f                          @ no, skip ahead
10086    mov     rFP, r0                     @ save relPc result in rFP
10087    mov     r0, r10                     @ r0<- self
10088    bl      dvmCleanupStackOverflow     @ call(self)
10089    mov     r0, rFP                     @ restore result
100901:
10091
10092    /* update frame pointer and check result from dvmFindCatchBlock */
10093    ldr     rFP, [sp, #4]               @ retrieve the updated rFP
10094    cmp     r0, #0                      @ is catchRelPc < 0?
10095    add     sp, sp, #8                  @ restore stack
10096    bmi     .LnotCaughtLocally
10097
10098    /* adjust locals to match self->curFrame and updated PC */
10099    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
10100    ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
10101    str     r1, [rGLUE, #offGlue_method]    @ glue->method = new method
10102    ldr     r2, [r1, #offMethod_clazz]      @ r2<- method->clazz
10103    ldr     r3, [r1, #offMethod_insns]      @ r3<- method->insns
10104    ldr     r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
10105    add     rPC, r3, r0, asl #1             @ rPC<- method->insns + catchRelPc
10106    str     r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
10107
10108    /* release the tracked alloc on the exception */
10109    mov     r0, r9                      @ r0<- exception
10110    mov     r1, r10                     @ r1<- self
10111    bl      dvmReleaseTrackedAlloc      @ release the exception
10112
10113    /* restore the exception if the handler wants it */
10114    FETCH_INST()                        @ load rINST from rPC
10115    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10116    cmp     ip, #OP_MOVE_EXCEPTION      @ is it "move-exception"?
10117    streq   r9, [r10, #offThread_exception] @ yes, restore the exception
10118    GOTO_OPCODE(ip)                     @ jump to next instruction
10119
10120.LnotCaughtLocally: @ r9=exception, r10=self
10121    /* fix stack overflow if necessary */
10122    ldrb    r1, [r10, #offThread_stackOverflowed]
10123    cmp     r1, #0                      @ did we overflow earlier?
10124    movne   r0, r10                     @ if yes: r0<- self
10125    blne    dvmCleanupStackOverflow     @ if yes: call(self)
10126
10127    @ may want to show "not caught locally" debug messages here
10128#if DVM_SHOW_EXCEPTION >= 2
10129    /* call __android_log_print(prio, tag, format, ...) */
10130    /* "Exception %s from %s:%d not caught locally" */
10131    @ dvmLineNumFromPC(method, pc - method->insns)
10132    ldr     r0, [rGLUE, #offGlue_method]
10133    ldr     r1, [r0, #offMethod_insns]
10134    sub     r1, rPC, r1
10135    asr     r1, r1, #1
10136    bl      dvmLineNumFromPC
10137    str     r0, [sp, #-4]!
10138    @ dvmGetMethodSourceFile(method)
10139    ldr     r0, [rGLUE, #offGlue_method]
10140    bl      dvmGetMethodSourceFile
10141    str     r0, [sp, #-4]!
10142    @ exception->clazz->descriptor
10143    ldr     r3, [r9, #offObject_clazz]
10144    ldr     r3, [r3, #offClassObject_descriptor]
10145    @
10146    ldr     r2, strExceptionNotCaughtLocally
10147    ldr     r1, strLogTag
10148    mov     r0, #3                      @ LOG_DEBUG
10149    bl      __android_log_print
10150#endif
10151    str     r9, [r10, #offThread_exception] @ restore exception
10152    mov     r0, r9                      @ r0<- exception
10153    mov     r1, r10                     @ r1<- self
10154    bl      dvmReleaseTrackedAlloc      @ release the exception
10155    mov     r1, #0                      @ "want switch" = false
10156    b       common_gotoBail             @ bail out
10157
10158
10159    /*
10160     * Exception handling, calls through "glue code".
10161     */
10162    .if     0
10163.LexceptionOld:
10164    SAVE_PC_FP_TO_GLUE()                @ export state
10165    mov     r0, rGLUE                   @ arg to function
10166    bl      dvmMterp_exceptionThrown
10167    b       common_resumeAfterGlueCall
10168    .endif
10169
10170
10171/*
10172 * After returning from a "glued" function, pull out the updated
10173 * values and start executing at the next instruction.
10174 */
10175common_resumeAfterGlueCall:
10176    LOAD_PC_FP_FROM_GLUE()              @ pull rPC and rFP out of glue
10177    FETCH_INST()                        @ load rINST from rPC
10178    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10179    GOTO_OPCODE(ip)                     @ jump to next instruction
10180
10181/*
10182 * Invalid array index.
10183 */
10184common_errArrayIndex:
10185    EXPORT_PC()
10186    ldr     r0, strArrayIndexException
10187    mov     r1, #0
10188    bl      dvmThrowException
10189    b       common_exceptionThrown
10190
10191/*
10192 * Invalid array value.
10193 */
10194common_errArrayStore:
10195    EXPORT_PC()
10196    ldr     r0, strArrayStoreException
10197    mov     r1, #0
10198    bl      dvmThrowException
10199    b       common_exceptionThrown
10200
10201/*
10202 * Integer divide or mod by zero.
10203 */
10204common_errDivideByZero:
10205    EXPORT_PC()
10206    ldr     r0, strArithmeticException
10207    ldr     r1, strDivideByZero
10208    bl      dvmThrowException
10209    b       common_exceptionThrown
10210
10211/*
10212 * Attempt to allocate an array with a negative size.
10213 */
10214common_errNegativeArraySize:
10215    EXPORT_PC()
10216    ldr     r0, strNegativeArraySizeException
10217    mov     r1, #0
10218    bl      dvmThrowException
10219    b       common_exceptionThrown
10220
10221/*
10222 * Invocation of a non-existent method.
10223 */
10224common_errNoSuchMethod:
10225    EXPORT_PC()
10226    ldr     r0, strNoSuchMethodError
10227    mov     r1, #0
10228    bl      dvmThrowException
10229    b       common_exceptionThrown
10230
10231/*
10232 * We encountered a null object when we weren't expecting one.  We
10233 * export the PC, throw a NullPointerException, and goto the exception
10234 * processing code.
10235 */
10236common_errNullObject:
10237    EXPORT_PC()
10238    ldr     r0, strNullPointerException
10239    mov     r1, #0
10240    bl      dvmThrowException
10241    b       common_exceptionThrown
10242
10243/*
10244 * For debugging, cause an immediate fault.  The source address will
10245 * be in lr (use a bl instruction to jump here).
10246 */
10247common_abort:
10248    ldr     pc, .LdeadFood
10249.LdeadFood:
10250    .word   0xdeadf00d
10251
10252/*
10253 * Spit out a "we were here", preserving all registers.  (The attempt
10254 * to save ip won't work, but we need to save an even number of
10255 * registers for EABI 64-bit stack alignment.)
10256 */
10257    .macro  SQUEAK num
10258common_squeak\num:
10259    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10260    ldr     r0, strSqueak
10261    mov     r1, #\num
10262    bl      printf
10263    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10264    bx      lr
10265    .endm
10266
10267    SQUEAK  0
10268    SQUEAK  1
10269    SQUEAK  2
10270    SQUEAK  3
10271    SQUEAK  4
10272    SQUEAK  5
10273
10274/*
10275 * Spit out the number in r0, preserving registers.
10276 */
10277common_printNum:
10278    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10279    mov     r1, r0
10280    ldr     r0, strSqueak
10281    bl      printf
10282    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10283    bx      lr
10284
10285/*
10286 * Print a newline, preserving registers.
10287 */
10288common_printNewline:
10289    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10290    ldr     r0, strNewline
10291    bl      printf
10292    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10293    bx      lr
10294
10295    /*
10296     * Print the 32-bit quantity in r0 as a hex value, preserving registers.
10297     */
10298common_printHex:
10299    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10300    mov     r1, r0
10301    ldr     r0, strPrintHex
10302    bl      printf
10303    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10304    bx      lr
10305
10306/*
10307 * Print the 64-bit quantity in r0-r1, preserving registers.
10308 */
10309common_printLong:
10310    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10311    mov     r3, r1
10312    mov     r2, r0
10313    ldr     r0, strPrintLong
10314    bl      printf
10315    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10316    bx      lr
10317
10318/*
10319 * Print full method info.  Pass the Method* in r0.  Preserves regs.
10320 */
10321common_printMethod:
10322    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10323    bl      dvmMterpPrintMethod
10324    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10325    bx      lr
10326
10327/*
10328 * Call a C helper function that dumps regs and possibly some
10329 * additional info.  Requires the C function to be compiled in.
10330 */
10331    .if     0
10332common_dumpRegs:
10333    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10334    bl      dvmMterpDumpArmRegs
10335    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10336    bx      lr
10337    .endif
10338
10339
10340/*
10341 * String references, must be close to the code that uses them.
10342 */
10343    .align  2
10344strArithmeticException:
10345    .word   .LstrArithmeticException
10346strArrayIndexException:
10347    .word   .LstrArrayIndexException
10348strArrayStoreException:
10349    .word   .LstrArrayStoreException
10350strDivideByZero:
10351    .word   .LstrDivideByZero
10352strNegativeArraySizeException:
10353    .word   .LstrNegativeArraySizeException
10354strNoSuchMethodError:
10355    .word   .LstrNoSuchMethodError
10356strNullPointerException:
10357    .word   .LstrNullPointerException
10358
10359strLogTag:
10360    .word   .LstrLogTag
10361strExceptionNotCaughtLocally:
10362    .word   .LstrExceptionNotCaughtLocally
10363
10364strNewline:
10365    .word   .LstrNewline
10366strSqueak:
10367    .word   .LstrSqueak
10368strPrintHex:
10369    .word   .LstrPrintHex
10370strPrintLong:
10371    .word   .LstrPrintLong
10372
10373/*
10374 * Zero-terminated ASCII string data.
10375 *
10376 * On ARM we have two choices: do like gcc does, and LDR from a .word
10377 * with the address, or use an ADR pseudo-op to get the address
10378 * directly.  ADR saves 4 bytes and an indirection, but it's using a
10379 * PC-relative addressing mode and hence has a limited range, which
10380 * makes it not work well with mergeable string sections.
10381 */
10382    .section .rodata.str1.4,"aMS",%progbits,1
10383
10384.LstrBadEntryPoint:
10385    .asciz  "Bad entry point %d\n"
10386.LstrArithmeticException:
10387    .asciz  "Ljava/lang/ArithmeticException;"
10388.LstrArrayIndexException:
10389    .asciz  "Ljava/lang/ArrayIndexOutOfBoundsException;"
10390.LstrArrayStoreException:
10391    .asciz  "Ljava/lang/ArrayStoreException;"
10392.LstrClassCastException:
10393    .asciz  "Ljava/lang/ClassCastException;"
10394.LstrDivideByZero:
10395    .asciz  "divide by zero"
10396.LstrFilledNewArrayNotImpl:
10397    .asciz  "filled-new-array only implemented for objects and 'int'"
10398.LstrInternalError:
10399    .asciz  "Ljava/lang/InternalError;"
10400.LstrInstantiationError:
10401    .asciz  "Ljava/lang/InstantiationError;"
10402.LstrNegativeArraySizeException:
10403    .asciz  "Ljava/lang/NegativeArraySizeException;"
10404.LstrNoSuchMethodError:
10405    .asciz  "Ljava/lang/NoSuchMethodError;"
10406.LstrNullPointerException:
10407    .asciz  "Ljava/lang/NullPointerException;"
10408
10409.LstrLogTag:
10410    .asciz  "mterp"
10411.LstrExceptionNotCaughtLocally:
10412    .asciz  "Exception %s from %s:%d not caught locally\n"
10413
10414.LstrNewline:
10415    .asciz  "\n"
10416.LstrSqueak:
10417    .asciz  "<%d>"
10418.LstrPrintHex:
10419    .asciz  "<0x%x>"
10420.LstrPrintLong:
10421    .asciz  "<%lld>"
10422
10423
10424