InterpAsm-armv5te.S revision 9a8c75adb2abf551d06dbf757bff558c1feded08
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    mov     r2, #0x80000000             @ maxint, as a double (low word)
4025    mov     r2, r2, asr #9              @  0xffc00000
4026    sub     sp, sp, #4                  @ align for EABI
4027    mvn     r3, #0xbe000000             @ maxint, as a double (high word)
4028    sub     r3, r3, #0x00200000         @  0x41dfffff
4029    mov     r4, r0                      @ save a copy of r0
4030    mov     r5, r1                      @  and r1
4031    bl      __aeabi_dcmpge              @ is arg >= maxint?
4032    cmp     r0, #0                      @ nonzero == yes
4033    mvnne   r0, #0x80000000             @ return maxint (0x7fffffff)
4034    bne     1f
4035
4036    mov     r0, r4                      @ recover arg
4037    mov     r1, r5
4038    mov     r3, #0xc1000000             @ minint, as a double (high word)
4039    add     r3, r3, #0x00e00000         @  0xc1e00000
4040    mov     r2, #0                      @ minint, as a double (low word)
4041    bl      __aeabi_dcmple              @ is arg <= minint?
4042    cmp     r0, #0                      @ nonzero == yes
4043    movne   r0, #0x80000000             @ return minint (80000000)
4044    bne     1f
4045
4046    mov     r0, r4                      @ recover arg
4047    mov     r1, r5
4048    mov     r2, r4                      @ compare against self
4049    mov     r3, r5
4050    bl      __aeabi_dcmpeq              @ is arg == self?
4051    cmp     r0, #0                      @ zero == no
4052    beq     1f                          @ return zero for NaN
4053
4054    mov     r0, r4                      @ recover arg
4055    mov     r1, r5
4056    bl      __aeabi_d2iz                @ convert double to int
4057
40581:
4059    add     sp, sp, #4
4060    ldmfd   sp!, {r4, r5, pc}
4061#endif
4062
4063
4064/* ------------------------------ */
4065    .balign 64
4066.L_OP_DOUBLE_TO_LONG: /* 0x8b */
4067/* File: armv5te/OP_DOUBLE_TO_LONG.S */
4068@include "armv5te/unopWide.S" {"instr":"bl      __aeabi_d2lz"}
4069/* File: armv5te/unopWide.S */
4070    /*
4071     * Generic 64-bit unary operation.  Provide an "instr" line that
4072     * specifies an instruction that performs "result = op r0/r1".
4073     * This could be an ARM instruction or a function call.
4074     *
4075     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
4076     */
4077    /* unop vA, vB */
4078    mov     r9, rINST, lsr #8           @ r9<- A+
4079    mov     r3, rINST, lsr #12          @ r3<- B
4080    and     r9, r9, #15
4081    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
4082    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
4083    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
4084    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4085                               @ optional op; may set condition codes
4086    bl      d2l_doconv                              @ r0/r1<- op, r2-r3 changed
4087    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4088    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
4089    GOTO_OPCODE(ip)                     @ jump to next instruction
4090    /* 12-13 instructions */
4091
4092
4093
4094
4095/* ------------------------------ */
4096    .balign 64
4097.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
4098/* File: armv5te/OP_DOUBLE_TO_FLOAT.S */
4099/* File: armv5te/unopNarrower.S */
4100    /*
4101     * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
4102     * that specifies an instruction that performs "result = op r0/r1", where
4103     * "result" is a 32-bit quantity in r0.
4104     *
4105     * For: long-to-float, double-to-int, double-to-float
4106     *
4107     * (This would work for long-to-int, but that instruction is actually
4108     * an exact match for OP_MOVE.)
4109     */
4110    /* unop vA, vB */
4111    mov     r3, rINST, lsr #12          @ r3<- B
4112    mov     r9, rINST, lsr #8           @ r9<- A+
4113    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
4114    and     r9, r9, #15
4115    ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
4116    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4117                               @ optional op; may set condition codes
4118    bl      __aeabi_d2f                              @ r0<- op, r0-r3 changed
4119    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4120    SET_VREG(r0, r9)                    @ vA<- r0
4121    GOTO_OPCODE(ip)                     @ jump to next instruction
4122    /* 10-11 instructions */
4123
4124
4125/* ------------------------------ */
4126    .balign 64
4127.L_OP_INT_TO_BYTE: /* 0x8d */
4128/* File: armv5te/OP_INT_TO_BYTE.S */
4129/* File: armv5te/unop.S */
4130    /*
4131     * Generic 32-bit unary operation.  Provide an "instr" line that
4132     * specifies an instruction that performs "result = op r0".
4133     * This could be an ARM instruction or a function call.
4134     *
4135     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4136     *      int-to-byte, int-to-char, int-to-short
4137     */
4138    /* unop vA, vB */
4139    mov     r3, rINST, lsr #12          @ r3<- B
4140    mov     r9, rINST, lsr #8           @ r9<- A+
4141    GET_VREG(r0, r3)                    @ r0<- vB
4142    and     r9, r9, #15
4143    mov     r0, r0, asl #24                           @ optional op; may set condition codes
4144    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4145    mov     r0, r0, asr #24                              @ r0<- op, r0-r3 changed
4146    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4147    SET_VREG(r0, r9)                    @ vAA<- r0
4148    GOTO_OPCODE(ip)                     @ jump to next instruction
4149    /* 9-10 instructions */
4150
4151
4152/* ------------------------------ */
4153    .balign 64
4154.L_OP_INT_TO_CHAR: /* 0x8e */
4155/* File: armv5te/OP_INT_TO_CHAR.S */
4156/* File: armv5te/unop.S */
4157    /*
4158     * Generic 32-bit unary operation.  Provide an "instr" line that
4159     * specifies an instruction that performs "result = op r0".
4160     * This could be an ARM instruction or a function call.
4161     *
4162     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4163     *      int-to-byte, int-to-char, int-to-short
4164     */
4165    /* unop vA, vB */
4166    mov     r3, rINST, lsr #12          @ r3<- B
4167    mov     r9, rINST, lsr #8           @ r9<- A+
4168    GET_VREG(r0, r3)                    @ r0<- vB
4169    and     r9, r9, #15
4170    mov     r0, r0, asl #16                           @ optional op; may set condition codes
4171    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4172    mov     r0, r0, lsr #16                              @ r0<- op, r0-r3 changed
4173    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4174    SET_VREG(r0, r9)                    @ vAA<- r0
4175    GOTO_OPCODE(ip)                     @ jump to next instruction
4176    /* 9-10 instructions */
4177
4178
4179/* ------------------------------ */
4180    .balign 64
4181.L_OP_INT_TO_SHORT: /* 0x8f */
4182/* File: armv5te/OP_INT_TO_SHORT.S */
4183/* File: armv5te/unop.S */
4184    /*
4185     * Generic 32-bit unary operation.  Provide an "instr" line that
4186     * specifies an instruction that performs "result = op r0".
4187     * This could be an ARM instruction or a function call.
4188     *
4189     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4190     *      int-to-byte, int-to-char, int-to-short
4191     */
4192    /* unop vA, vB */
4193    mov     r3, rINST, lsr #12          @ r3<- B
4194    mov     r9, rINST, lsr #8           @ r9<- A+
4195    GET_VREG(r0, r3)                    @ r0<- vB
4196    and     r9, r9, #15
4197    mov     r0, r0, asl #16                           @ optional op; may set condition codes
4198    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4199    mov     r0, r0, asr #16                              @ r0<- op, r0-r3 changed
4200    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4201    SET_VREG(r0, r9)                    @ vAA<- r0
4202    GOTO_OPCODE(ip)                     @ jump to next instruction
4203    /* 9-10 instructions */
4204
4205
4206/* ------------------------------ */
4207    .balign 64
4208.L_OP_ADD_INT: /* 0x90 */
4209/* File: armv5te/OP_ADD_INT.S */
4210/* File: armv5te/binop.S */
4211    /*
4212     * Generic 32-bit binary operation.  Provide an "instr" line that
4213     * specifies an instruction that performs "result = r0 op r1".
4214     * This could be an ARM instruction or a function call.  (If the result
4215     * comes back in a register other than r0, you can override "result".)
4216     *
4217     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4218     * vCC (r1).  Useful for integer division and modulus.  Note that we
4219     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4220     * handles it correctly.
4221     *
4222     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4223     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4224     *      mul-float, div-float, rem-float
4225     */
4226    /* binop vAA, vBB, vCC */
4227    FETCH(r0, 1)                        @ r0<- CCBB
4228    mov     r9, rINST, lsr #8           @ r9<- AA
4229    mov     r3, r0, lsr #8              @ r3<- CC
4230    and     r2, r0, #255                @ r2<- BB
4231    GET_VREG(r1, r3)                    @ r1<- vCC
4232    GET_VREG(r0, r2)                    @ r0<- vBB
4233    .if 0
4234    cmp     r1, #0                      @ is second operand zero?
4235    beq     common_errDivideByZero
4236    .endif
4237
4238    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4239                               @ optional op; may set condition codes
4240    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
4241    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4242    SET_VREG(r0, r9)               @ vAA<- r0
4243    GOTO_OPCODE(ip)                     @ jump to next instruction
4244    /* 11-14 instructions */
4245
4246
4247
4248/* ------------------------------ */
4249    .balign 64
4250.L_OP_SUB_INT: /* 0x91 */
4251/* File: armv5te/OP_SUB_INT.S */
4252/* File: armv5te/binop.S */
4253    /*
4254     * Generic 32-bit binary operation.  Provide an "instr" line that
4255     * specifies an instruction that performs "result = r0 op r1".
4256     * This could be an ARM instruction or a function call.  (If the result
4257     * comes back in a register other than r0, you can override "result".)
4258     *
4259     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4260     * vCC (r1).  Useful for integer division and modulus.  Note that we
4261     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4262     * handles it correctly.
4263     *
4264     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4265     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4266     *      mul-float, div-float, rem-float
4267     */
4268    /* binop vAA, vBB, vCC */
4269    FETCH(r0, 1)                        @ r0<- CCBB
4270    mov     r9, rINST, lsr #8           @ r9<- AA
4271    mov     r3, r0, lsr #8              @ r3<- CC
4272    and     r2, r0, #255                @ r2<- BB
4273    GET_VREG(r1, r3)                    @ r1<- vCC
4274    GET_VREG(r0, r2)                    @ r0<- vBB
4275    .if 0
4276    cmp     r1, #0                      @ is second operand zero?
4277    beq     common_errDivideByZero
4278    .endif
4279
4280    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4281                               @ optional op; may set condition codes
4282    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
4283    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4284    SET_VREG(r0, r9)               @ vAA<- r0
4285    GOTO_OPCODE(ip)                     @ jump to next instruction
4286    /* 11-14 instructions */
4287
4288
4289
4290/* ------------------------------ */
4291    .balign 64
4292.L_OP_MUL_INT: /* 0x92 */
4293/* File: armv5te/OP_MUL_INT.S */
4294/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
4295/* File: armv5te/binop.S */
4296    /*
4297     * Generic 32-bit binary operation.  Provide an "instr" line that
4298     * specifies an instruction that performs "result = r0 op r1".
4299     * This could be an ARM instruction or a function call.  (If the result
4300     * comes back in a register other than r0, you can override "result".)
4301     *
4302     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4303     * vCC (r1).  Useful for integer division and modulus.  Note that we
4304     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4305     * handles it correctly.
4306     *
4307     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4308     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4309     *      mul-float, div-float, rem-float
4310     */
4311    /* binop vAA, vBB, vCC */
4312    FETCH(r0, 1)                        @ r0<- CCBB
4313    mov     r9, rINST, lsr #8           @ r9<- AA
4314    mov     r3, r0, lsr #8              @ r3<- CC
4315    and     r2, r0, #255                @ r2<- BB
4316    GET_VREG(r1, r3)                    @ r1<- vCC
4317    GET_VREG(r0, r2)                    @ r0<- vBB
4318    .if 0
4319    cmp     r1, #0                      @ is second operand zero?
4320    beq     common_errDivideByZero
4321    .endif
4322
4323    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4324                               @ optional op; may set condition codes
4325    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
4326    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4327    SET_VREG(r0, r9)               @ vAA<- r0
4328    GOTO_OPCODE(ip)                     @ jump to next instruction
4329    /* 11-14 instructions */
4330
4331
4332
4333/* ------------------------------ */
4334    .balign 64
4335.L_OP_DIV_INT: /* 0x93 */
4336/* File: armv5te/OP_DIV_INT.S */
4337/* File: armv5te/binop.S */
4338    /*
4339     * Generic 32-bit binary operation.  Provide an "instr" line that
4340     * specifies an instruction that performs "result = r0 op r1".
4341     * This could be an ARM instruction or a function call.  (If the result
4342     * comes back in a register other than r0, you can override "result".)
4343     *
4344     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4345     * vCC (r1).  Useful for integer division and modulus.  Note that we
4346     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4347     * handles it correctly.
4348     *
4349     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4350     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4351     *      mul-float, div-float, rem-float
4352     */
4353    /* binop vAA, vBB, vCC */
4354    FETCH(r0, 1)                        @ r0<- CCBB
4355    mov     r9, rINST, lsr #8           @ r9<- AA
4356    mov     r3, r0, lsr #8              @ r3<- CC
4357    and     r2, r0, #255                @ r2<- BB
4358    GET_VREG(r1, r3)                    @ r1<- vCC
4359    GET_VREG(r0, r2)                    @ r0<- vBB
4360    .if 1
4361    cmp     r1, #0                      @ is second operand zero?
4362    beq     common_errDivideByZero
4363    .endif
4364
4365    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4366                               @ optional op; may set condition codes
4367    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
4368    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4369    SET_VREG(r0, r9)               @ vAA<- r0
4370    GOTO_OPCODE(ip)                     @ jump to next instruction
4371    /* 11-14 instructions */
4372
4373
4374
4375/* ------------------------------ */
4376    .balign 64
4377.L_OP_REM_INT: /* 0x94 */
4378/* File: armv5te/OP_REM_INT.S */
4379/* idivmod returns quotient in r0 and remainder in r1 */
4380/* File: armv5te/binop.S */
4381    /*
4382     * Generic 32-bit binary operation.  Provide an "instr" line that
4383     * specifies an instruction that performs "result = r0 op r1".
4384     * This could be an ARM instruction or a function call.  (If the result
4385     * comes back in a register other than r0, you can override "result".)
4386     *
4387     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4388     * vCC (r1).  Useful for integer division and modulus.  Note that we
4389     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4390     * handles it correctly.
4391     *
4392     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4393     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4394     *      mul-float, div-float, rem-float
4395     */
4396    /* binop vAA, vBB, vCC */
4397    FETCH(r0, 1)                        @ r0<- CCBB
4398    mov     r9, rINST, lsr #8           @ r9<- AA
4399    mov     r3, r0, lsr #8              @ r3<- CC
4400    and     r2, r0, #255                @ r2<- BB
4401    GET_VREG(r1, r3)                    @ r1<- vCC
4402    GET_VREG(r0, r2)                    @ r0<- vBB
4403    .if 1
4404    cmp     r1, #0                      @ is second operand zero?
4405    beq     common_errDivideByZero
4406    .endif
4407
4408    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4409                               @ optional op; may set condition codes
4410    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
4411    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4412    SET_VREG(r1, r9)               @ vAA<- r1
4413    GOTO_OPCODE(ip)                     @ jump to next instruction
4414    /* 11-14 instructions */
4415
4416
4417
4418/* ------------------------------ */
4419    .balign 64
4420.L_OP_AND_INT: /* 0x95 */
4421/* File: armv5te/OP_AND_INT.S */
4422/* File: armv5te/binop.S */
4423    /*
4424     * Generic 32-bit binary operation.  Provide an "instr" line that
4425     * specifies an instruction that performs "result = r0 op r1".
4426     * This could be an ARM instruction or a function call.  (If the result
4427     * comes back in a register other than r0, you can override "result".)
4428     *
4429     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4430     * vCC (r1).  Useful for integer division and modulus.  Note that we
4431     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4432     * handles it correctly.
4433     *
4434     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4435     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4436     *      mul-float, div-float, rem-float
4437     */
4438    /* binop vAA, vBB, vCC */
4439    FETCH(r0, 1)                        @ r0<- CCBB
4440    mov     r9, rINST, lsr #8           @ r9<- AA
4441    mov     r3, r0, lsr #8              @ r3<- CC
4442    and     r2, r0, #255                @ r2<- BB
4443    GET_VREG(r1, r3)                    @ r1<- vCC
4444    GET_VREG(r0, r2)                    @ r0<- vBB
4445    .if 0
4446    cmp     r1, #0                      @ is second operand zero?
4447    beq     common_errDivideByZero
4448    .endif
4449
4450    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4451                               @ optional op; may set condition codes
4452    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
4453    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4454    SET_VREG(r0, r9)               @ vAA<- r0
4455    GOTO_OPCODE(ip)                     @ jump to next instruction
4456    /* 11-14 instructions */
4457
4458
4459
4460/* ------------------------------ */
4461    .balign 64
4462.L_OP_OR_INT: /* 0x96 */
4463/* File: armv5te/OP_OR_INT.S */
4464/* File: armv5te/binop.S */
4465    /*
4466     * Generic 32-bit binary operation.  Provide an "instr" line that
4467     * specifies an instruction that performs "result = r0 op r1".
4468     * This could be an ARM instruction or a function call.  (If the result
4469     * comes back in a register other than r0, you can override "result".)
4470     *
4471     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4472     * vCC (r1).  Useful for integer division and modulus.  Note that we
4473     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4474     * handles it correctly.
4475     *
4476     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4477     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4478     *      mul-float, div-float, rem-float
4479     */
4480    /* binop vAA, vBB, vCC */
4481    FETCH(r0, 1)                        @ r0<- CCBB
4482    mov     r9, rINST, lsr #8           @ r9<- AA
4483    mov     r3, r0, lsr #8              @ r3<- CC
4484    and     r2, r0, #255                @ r2<- BB
4485    GET_VREG(r1, r3)                    @ r1<- vCC
4486    GET_VREG(r0, r2)                    @ r0<- vBB
4487    .if 0
4488    cmp     r1, #0                      @ is second operand zero?
4489    beq     common_errDivideByZero
4490    .endif
4491
4492    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4493                               @ optional op; may set condition codes
4494    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
4495    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4496    SET_VREG(r0, r9)               @ vAA<- r0
4497    GOTO_OPCODE(ip)                     @ jump to next instruction
4498    /* 11-14 instructions */
4499
4500
4501
4502/* ------------------------------ */
4503    .balign 64
4504.L_OP_XOR_INT: /* 0x97 */
4505/* File: armv5te/OP_XOR_INT.S */
4506/* File: armv5te/binop.S */
4507    /*
4508     * Generic 32-bit binary operation.  Provide an "instr" line that
4509     * specifies an instruction that performs "result = r0 op r1".
4510     * This could be an ARM instruction or a function call.  (If the result
4511     * comes back in a register other than r0, you can override "result".)
4512     *
4513     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4514     * vCC (r1).  Useful for integer division and modulus.  Note that we
4515     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4516     * handles it correctly.
4517     *
4518     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4519     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4520     *      mul-float, div-float, rem-float
4521     */
4522    /* binop vAA, vBB, vCC */
4523    FETCH(r0, 1)                        @ r0<- CCBB
4524    mov     r9, rINST, lsr #8           @ r9<- AA
4525    mov     r3, r0, lsr #8              @ r3<- CC
4526    and     r2, r0, #255                @ r2<- BB
4527    GET_VREG(r1, r3)                    @ r1<- vCC
4528    GET_VREG(r0, r2)                    @ r0<- vBB
4529    .if 0
4530    cmp     r1, #0                      @ is second operand zero?
4531    beq     common_errDivideByZero
4532    .endif
4533
4534    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4535                               @ optional op; may set condition codes
4536    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
4537    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4538    SET_VREG(r0, r9)               @ vAA<- r0
4539    GOTO_OPCODE(ip)                     @ jump to next instruction
4540    /* 11-14 instructions */
4541
4542
4543
4544/* ------------------------------ */
4545    .balign 64
4546.L_OP_SHL_INT: /* 0x98 */
4547/* File: armv5te/OP_SHL_INT.S */
4548/* File: armv5te/binop.S */
4549    /*
4550     * Generic 32-bit binary operation.  Provide an "instr" line that
4551     * specifies an instruction that performs "result = r0 op r1".
4552     * This could be an ARM instruction or a function call.  (If the result
4553     * comes back in a register other than r0, you can override "result".)
4554     *
4555     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4556     * vCC (r1).  Useful for integer division and modulus.  Note that we
4557     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4558     * handles it correctly.
4559     *
4560     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4561     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4562     *      mul-float, div-float, rem-float
4563     */
4564    /* binop vAA, vBB, vCC */
4565    FETCH(r0, 1)                        @ r0<- CCBB
4566    mov     r9, rINST, lsr #8           @ r9<- AA
4567    mov     r3, r0, lsr #8              @ r3<- CC
4568    and     r2, r0, #255                @ r2<- BB
4569    GET_VREG(r1, r3)                    @ r1<- vCC
4570    GET_VREG(r0, r2)                    @ r0<- vBB
4571    .if 0
4572    cmp     r1, #0                      @ is second operand zero?
4573    beq     common_errDivideByZero
4574    .endif
4575
4576    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4577    and     r1, r1, #31                           @ optional op; may set condition codes
4578    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
4579    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4580    SET_VREG(r0, r9)               @ vAA<- r0
4581    GOTO_OPCODE(ip)                     @ jump to next instruction
4582    /* 11-14 instructions */
4583
4584
4585
4586/* ------------------------------ */
4587    .balign 64
4588.L_OP_SHR_INT: /* 0x99 */
4589/* File: armv5te/OP_SHR_INT.S */
4590/* File: armv5te/binop.S */
4591    /*
4592     * Generic 32-bit binary operation.  Provide an "instr" line that
4593     * specifies an instruction that performs "result = r0 op r1".
4594     * This could be an ARM instruction or a function call.  (If the result
4595     * comes back in a register other than r0, you can override "result".)
4596     *
4597     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4598     * vCC (r1).  Useful for integer division and modulus.  Note that we
4599     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4600     * handles it correctly.
4601     *
4602     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4603     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4604     *      mul-float, div-float, rem-float
4605     */
4606    /* binop vAA, vBB, vCC */
4607    FETCH(r0, 1)                        @ r0<- CCBB
4608    mov     r9, rINST, lsr #8           @ r9<- AA
4609    mov     r3, r0, lsr #8              @ r3<- CC
4610    and     r2, r0, #255                @ r2<- BB
4611    GET_VREG(r1, r3)                    @ r1<- vCC
4612    GET_VREG(r0, r2)                    @ r0<- vBB
4613    .if 0
4614    cmp     r1, #0                      @ is second operand zero?
4615    beq     common_errDivideByZero
4616    .endif
4617
4618    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4619    and     r1, r1, #31                           @ optional op; may set condition codes
4620    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
4621    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4622    SET_VREG(r0, r9)               @ vAA<- r0
4623    GOTO_OPCODE(ip)                     @ jump to next instruction
4624    /* 11-14 instructions */
4625
4626
4627
4628/* ------------------------------ */
4629    .balign 64
4630.L_OP_USHR_INT: /* 0x9a */
4631/* File: armv5te/OP_USHR_INT.S */
4632/* File: armv5te/binop.S */
4633    /*
4634     * Generic 32-bit binary operation.  Provide an "instr" line that
4635     * specifies an instruction that performs "result = r0 op r1".
4636     * This could be an ARM instruction or a function call.  (If the result
4637     * comes back in a register other than r0, you can override "result".)
4638     *
4639     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4640     * vCC (r1).  Useful for integer division and modulus.  Note that we
4641     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4642     * handles it correctly.
4643     *
4644     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4645     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4646     *      mul-float, div-float, rem-float
4647     */
4648    /* binop vAA, vBB, vCC */
4649    FETCH(r0, 1)                        @ r0<- CCBB
4650    mov     r9, rINST, lsr #8           @ r9<- AA
4651    mov     r3, r0, lsr #8              @ r3<- CC
4652    and     r2, r0, #255                @ r2<- BB
4653    GET_VREG(r1, r3)                    @ r1<- vCC
4654    GET_VREG(r0, r2)                    @ r0<- vBB
4655    .if 0
4656    cmp     r1, #0                      @ is second operand zero?
4657    beq     common_errDivideByZero
4658    .endif
4659
4660    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4661    and     r1, r1, #31                           @ optional op; may set condition codes
4662    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
4663    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4664    SET_VREG(r0, r9)               @ vAA<- r0
4665    GOTO_OPCODE(ip)                     @ jump to next instruction
4666    /* 11-14 instructions */
4667
4668
4669
4670/* ------------------------------ */
4671    .balign 64
4672.L_OP_ADD_LONG: /* 0x9b */
4673/* File: armv5te/OP_ADD_LONG.S */
4674/* File: armv5te/binopWide.S */
4675    /*
4676     * Generic 64-bit binary operation.  Provide an "instr" line that
4677     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4678     * This could be an ARM instruction or a function call.  (If the result
4679     * comes back in a register other than r0, you can override "result".)
4680     *
4681     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4682     * vCC (r1).  Useful for integer division and modulus.
4683     *
4684     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4685     *      xor-long, add-double, sub-double, mul-double, div-double,
4686     *      rem-double
4687     *
4688     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4689     */
4690    /* binop vAA, vBB, vCC */
4691    FETCH(r0, 1)                        @ r0<- CCBB
4692    mov     r9, rINST, lsr #8           @ r9<- AA
4693    and     r2, r0, #255                @ r2<- BB
4694    mov     r3, r0, lsr #8              @ r3<- CC
4695    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4696    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4697    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4698    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4699    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4700    .if 0
4701    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4702    beq     common_errDivideByZero
4703    .endif
4704    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4705
4706    adds    r0, r0, r2                           @ optional op; may set condition codes
4707    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
4708    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4709    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4710    GOTO_OPCODE(ip)                     @ jump to next instruction
4711    /* 14-17 instructions */
4712
4713
4714
4715/* ------------------------------ */
4716    .balign 64
4717.L_OP_SUB_LONG: /* 0x9c */
4718/* File: armv5te/OP_SUB_LONG.S */
4719/* File: armv5te/binopWide.S */
4720    /*
4721     * Generic 64-bit binary operation.  Provide an "instr" line that
4722     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4723     * This could be an ARM instruction or a function call.  (If the result
4724     * comes back in a register other than r0, you can override "result".)
4725     *
4726     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4727     * vCC (r1).  Useful for integer division and modulus.
4728     *
4729     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4730     *      xor-long, add-double, sub-double, mul-double, div-double,
4731     *      rem-double
4732     *
4733     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4734     */
4735    /* binop vAA, vBB, vCC */
4736    FETCH(r0, 1)                        @ r0<- CCBB
4737    mov     r9, rINST, lsr #8           @ r9<- AA
4738    and     r2, r0, #255                @ r2<- BB
4739    mov     r3, r0, lsr #8              @ r3<- CC
4740    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4741    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4742    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4743    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4744    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4745    .if 0
4746    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4747    beq     common_errDivideByZero
4748    .endif
4749    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4750
4751    subs    r0, r0, r2                           @ optional op; may set condition codes
4752    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
4753    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4754    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4755    GOTO_OPCODE(ip)                     @ jump to next instruction
4756    /* 14-17 instructions */
4757
4758
4759
4760/* ------------------------------ */
4761    .balign 64
4762.L_OP_MUL_LONG: /* 0x9d */
4763/* File: armv5te/OP_MUL_LONG.S */
4764    /*
4765     * Signed 64-bit integer multiply.
4766     *
4767     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
4768     *        WX
4769     *      x YZ
4770     *  --------
4771     *     ZW ZX
4772     *  YW YX
4773     *
4774     * The low word of the result holds ZX, the high word holds
4775     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
4776     * it doesn't fit in the low 64 bits.
4777     *
4778     * Unlike most ARM math operations, multiply instructions have
4779     * restrictions on using the same register more than once (Rd and Rm
4780     * cannot be the same).
4781     */
4782    /* mul-long vAA, vBB, vCC */
4783    FETCH(r0, 1)                        @ r0<- CCBB
4784    and     r2, r0, #255                @ r2<- BB
4785    mov     r3, r0, lsr #8              @ r3<- CC
4786    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4787    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4788    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4789    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4790    mul     ip, r2, r1                  @  ip<- ZxW
4791    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
4792    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
4793    mov     r0, rINST, lsr #8           @ r0<- AA
4794    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
4795    add     r0, rFP, r0, lsl #2         @ r0<- &fp[AA]
4796    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4797    b       .LOP_MUL_LONG_finish
4798
4799/* ------------------------------ */
4800    .balign 64
4801.L_OP_DIV_LONG: /* 0x9e */
4802/* File: armv5te/OP_DIV_LONG.S */
4803/* File: armv5te/binopWide.S */
4804    /*
4805     * Generic 64-bit binary operation.  Provide an "instr" line that
4806     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4807     * This could be an ARM instruction or a function call.  (If the result
4808     * comes back in a register other than r0, you can override "result".)
4809     *
4810     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4811     * vCC (r1).  Useful for integer division and modulus.
4812     *
4813     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4814     *      xor-long, add-double, sub-double, mul-double, div-double,
4815     *      rem-double
4816     *
4817     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4818     */
4819    /* binop vAA, vBB, vCC */
4820    FETCH(r0, 1)                        @ r0<- CCBB
4821    mov     r9, rINST, lsr #8           @ r9<- AA
4822    and     r2, r0, #255                @ r2<- BB
4823    mov     r3, r0, lsr #8              @ r3<- CC
4824    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4825    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4826    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4827    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4828    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4829    .if 1
4830    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4831    beq     common_errDivideByZero
4832    .endif
4833    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4834
4835                               @ optional op; may set condition codes
4836    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4837    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4838    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4839    GOTO_OPCODE(ip)                     @ jump to next instruction
4840    /* 14-17 instructions */
4841
4842
4843
4844/* ------------------------------ */
4845    .balign 64
4846.L_OP_REM_LONG: /* 0x9f */
4847/* File: armv5te/OP_REM_LONG.S */
4848/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
4849/* File: armv5te/binopWide.S */
4850    /*
4851     * Generic 64-bit binary operation.  Provide an "instr" line that
4852     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4853     * This could be an ARM instruction or a function call.  (If the result
4854     * comes back in a register other than r0, you can override "result".)
4855     *
4856     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4857     * vCC (r1).  Useful for integer division and modulus.
4858     *
4859     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4860     *      xor-long, add-double, sub-double, mul-double, div-double,
4861     *      rem-double
4862     *
4863     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4864     */
4865    /* binop vAA, vBB, vCC */
4866    FETCH(r0, 1)                        @ r0<- CCBB
4867    mov     r9, rINST, lsr #8           @ r9<- AA
4868    and     r2, r0, #255                @ r2<- BB
4869    mov     r3, r0, lsr #8              @ r3<- CC
4870    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4871    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4872    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4873    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4874    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4875    .if 1
4876    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4877    beq     common_errDivideByZero
4878    .endif
4879    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4880
4881                               @ optional op; may set condition codes
4882    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4883    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4884    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
4885    GOTO_OPCODE(ip)                     @ jump to next instruction
4886    /* 14-17 instructions */
4887
4888
4889
4890/* ------------------------------ */
4891    .balign 64
4892.L_OP_AND_LONG: /* 0xa0 */
4893/* File: armv5te/OP_AND_LONG.S */
4894/* File: armv5te/binopWide.S */
4895    /*
4896     * Generic 64-bit binary operation.  Provide an "instr" line that
4897     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4898     * This could be an ARM instruction or a function call.  (If the result
4899     * comes back in a register other than r0, you can override "result".)
4900     *
4901     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4902     * vCC (r1).  Useful for integer division and modulus.
4903     *
4904     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4905     *      xor-long, add-double, sub-double, mul-double, div-double,
4906     *      rem-double
4907     *
4908     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4909     */
4910    /* binop vAA, vBB, vCC */
4911    FETCH(r0, 1)                        @ r0<- CCBB
4912    mov     r9, rINST, lsr #8           @ r9<- AA
4913    and     r2, r0, #255                @ r2<- BB
4914    mov     r3, r0, lsr #8              @ r3<- CC
4915    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4916    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4917    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4918    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4919    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4920    .if 0
4921    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4922    beq     common_errDivideByZero
4923    .endif
4924    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4925
4926    and     r0, r0, r2                           @ optional op; may set condition codes
4927    and     r1, r1, r3                              @ result<- op, r0-r3 changed
4928    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4929    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4930    GOTO_OPCODE(ip)                     @ jump to next instruction
4931    /* 14-17 instructions */
4932
4933
4934
4935/* ------------------------------ */
4936    .balign 64
4937.L_OP_OR_LONG: /* 0xa1 */
4938/* File: armv5te/OP_OR_LONG.S */
4939/* File: armv5te/binopWide.S */
4940    /*
4941     * Generic 64-bit binary operation.  Provide an "instr" line that
4942     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4943     * This could be an ARM instruction or a function call.  (If the result
4944     * comes back in a register other than r0, you can override "result".)
4945     *
4946     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4947     * vCC (r1).  Useful for integer division and modulus.
4948     *
4949     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4950     *      xor-long, add-double, sub-double, mul-double, div-double,
4951     *      rem-double
4952     *
4953     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4954     */
4955    /* binop vAA, vBB, vCC */
4956    FETCH(r0, 1)                        @ r0<- CCBB
4957    mov     r9, rINST, lsr #8           @ r9<- AA
4958    and     r2, r0, #255                @ r2<- BB
4959    mov     r3, r0, lsr #8              @ r3<- CC
4960    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4961    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4962    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4963    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4964    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4965    .if 0
4966    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4967    beq     common_errDivideByZero
4968    .endif
4969    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4970
4971    orr     r0, r0, r2                           @ optional op; may set condition codes
4972    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
4973    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4974    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4975    GOTO_OPCODE(ip)                     @ jump to next instruction
4976    /* 14-17 instructions */
4977
4978
4979
4980/* ------------------------------ */
4981    .balign 64
4982.L_OP_XOR_LONG: /* 0xa2 */
4983/* File: armv5te/OP_XOR_LONG.S */
4984/* File: armv5te/binopWide.S */
4985    /*
4986     * Generic 64-bit binary operation.  Provide an "instr" line that
4987     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4988     * This could be an ARM instruction or a function call.  (If the result
4989     * comes back in a register other than r0, you can override "result".)
4990     *
4991     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4992     * vCC (r1).  Useful for integer division and modulus.
4993     *
4994     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4995     *      xor-long, add-double, sub-double, mul-double, div-double,
4996     *      rem-double
4997     *
4998     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4999     */
5000    /* binop vAA, vBB, vCC */
5001    FETCH(r0, 1)                        @ r0<- CCBB
5002    mov     r9, rINST, lsr #8           @ r9<- AA
5003    and     r2, r0, #255                @ r2<- BB
5004    mov     r3, r0, lsr #8              @ r3<- CC
5005    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5006    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5007    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5008    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5009    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5010    .if 0
5011    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5012    beq     common_errDivideByZero
5013    .endif
5014    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5015
5016    eor     r0, r0, r2                           @ optional op; may set condition codes
5017    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
5018    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5019    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5020    GOTO_OPCODE(ip)                     @ jump to next instruction
5021    /* 14-17 instructions */
5022
5023
5024
5025/* ------------------------------ */
5026    .balign 64
5027.L_OP_SHL_LONG: /* 0xa3 */
5028/* File: armv5te/OP_SHL_LONG.S */
5029    /*
5030     * Long integer shift.  This is different from the generic 32/64-bit
5031     * binary operations because vAA/vBB are 64-bit but vCC (the shift
5032     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
5033     * 6 bits of the shift distance.
5034     */
5035    /* shl-long vAA, vBB, vCC */
5036    FETCH(r0, 1)                        @ r0<- CCBB
5037    mov     r9, rINST, lsr #8           @ r9<- AA
5038    and     r3, r0, #255                @ r3<- BB
5039    mov     r0, r0, lsr #8              @ r0<- CC
5040    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
5041    GET_VREG(r2, r0)                    @ r2<- vCC
5042    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5043    and     r2, r2, #63                 @ r2<- r2 & 0x3f
5044    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5045
5046    mov     r1, r1, asl r2              @  r1<- r1 << r2
5047    rsb     r3, r2, #32                 @  r3<- 32 - r2
5048    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
5049    subs    ip, r2, #32                 @  ip<- r2 - 32
5050    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
5051    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5052    b       .LOP_SHL_LONG_finish
5053
5054/* ------------------------------ */
5055    .balign 64
5056.L_OP_SHR_LONG: /* 0xa4 */
5057/* File: armv5te/OP_SHR_LONG.S */
5058    /*
5059     * Long integer shift.  This is different from the generic 32/64-bit
5060     * binary operations because vAA/vBB are 64-bit but vCC (the shift
5061     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
5062     * 6 bits of the shift distance.
5063     */
5064    /* shr-long vAA, vBB, vCC */
5065    FETCH(r0, 1)                        @ r0<- CCBB
5066    mov     r9, rINST, lsr #8           @ r9<- AA
5067    and     r3, r0, #255                @ r3<- BB
5068    mov     r0, r0, lsr #8              @ r0<- CC
5069    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
5070    GET_VREG(r2, r0)                    @ r2<- vCC
5071    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5072    and     r2, r2, #63                 @ r0<- r0 & 0x3f
5073    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5074
5075    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
5076    rsb     r3, r2, #32                 @  r3<- 32 - r2
5077    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
5078    subs    ip, r2, #32                 @  ip<- r2 - 32
5079    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
5080    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5081    b       .LOP_SHR_LONG_finish
5082
5083/* ------------------------------ */
5084    .balign 64
5085.L_OP_USHR_LONG: /* 0xa5 */
5086/* File: armv5te/OP_USHR_LONG.S */
5087    /*
5088     * Long integer shift.  This is different from the generic 32/64-bit
5089     * binary operations because vAA/vBB are 64-bit but vCC (the shift
5090     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
5091     * 6 bits of the shift distance.
5092     */
5093    /* ushr-long vAA, vBB, vCC */
5094    FETCH(r0, 1)                        @ r0<- CCBB
5095    mov     r9, rINST, lsr #8           @ r9<- AA
5096    and     r3, r0, #255                @ r3<- BB
5097    mov     r0, r0, lsr #8              @ r0<- CC
5098    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
5099    GET_VREG(r2, r0)                    @ r2<- vCC
5100    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5101    and     r2, r2, #63                 @ r0<- r0 & 0x3f
5102    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5103
5104    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
5105    rsb     r3, r2, #32                 @  r3<- 32 - r2
5106    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
5107    subs    ip, r2, #32                 @  ip<- r2 - 32
5108    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
5109    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5110    b       .LOP_USHR_LONG_finish
5111
5112/* ------------------------------ */
5113    .balign 64
5114.L_OP_ADD_FLOAT: /* 0xa6 */
5115/* File: armv5te/OP_ADD_FLOAT.S */
5116/* File: armv5te/binop.S */
5117    /*
5118     * Generic 32-bit binary operation.  Provide an "instr" line that
5119     * specifies an instruction that performs "result = r0 op r1".
5120     * This could be an ARM instruction or a function call.  (If the result
5121     * comes back in a register other than r0, you can override "result".)
5122     *
5123     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5124     * vCC (r1).  Useful for integer division and modulus.  Note that we
5125     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5126     * handles it correctly.
5127     *
5128     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5129     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5130     *      mul-float, div-float, rem-float
5131     */
5132    /* binop vAA, vBB, vCC */
5133    FETCH(r0, 1)                        @ r0<- CCBB
5134    mov     r9, rINST, lsr #8           @ r9<- AA
5135    mov     r3, r0, lsr #8              @ r3<- CC
5136    and     r2, r0, #255                @ r2<- BB
5137    GET_VREG(r1, r3)                    @ r1<- vCC
5138    GET_VREG(r0, r2)                    @ r0<- vBB
5139    .if 0
5140    cmp     r1, #0                      @ is second operand zero?
5141    beq     common_errDivideByZero
5142    .endif
5143
5144    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5145                               @ optional op; may set condition codes
5146    bl      __aeabi_fadd                              @ r0<- op, r0-r3 changed
5147    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5148    SET_VREG(r0, r9)               @ vAA<- r0
5149    GOTO_OPCODE(ip)                     @ jump to next instruction
5150    /* 11-14 instructions */
5151
5152
5153
5154/* ------------------------------ */
5155    .balign 64
5156.L_OP_SUB_FLOAT: /* 0xa7 */
5157/* File: armv5te/OP_SUB_FLOAT.S */
5158/* File: armv5te/binop.S */
5159    /*
5160     * Generic 32-bit binary operation.  Provide an "instr" line that
5161     * specifies an instruction that performs "result = r0 op r1".
5162     * This could be an ARM instruction or a function call.  (If the result
5163     * comes back in a register other than r0, you can override "result".)
5164     *
5165     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5166     * vCC (r1).  Useful for integer division and modulus.  Note that we
5167     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5168     * handles it correctly.
5169     *
5170     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5171     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5172     *      mul-float, div-float, rem-float
5173     */
5174    /* binop vAA, vBB, vCC */
5175    FETCH(r0, 1)                        @ r0<- CCBB
5176    mov     r9, rINST, lsr #8           @ r9<- AA
5177    mov     r3, r0, lsr #8              @ r3<- CC
5178    and     r2, r0, #255                @ r2<- BB
5179    GET_VREG(r1, r3)                    @ r1<- vCC
5180    GET_VREG(r0, r2)                    @ r0<- vBB
5181    .if 0
5182    cmp     r1, #0                      @ is second operand zero?
5183    beq     common_errDivideByZero
5184    .endif
5185
5186    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5187                               @ optional op; may set condition codes
5188    bl      __aeabi_fsub                              @ r0<- op, r0-r3 changed
5189    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5190    SET_VREG(r0, r9)               @ vAA<- r0
5191    GOTO_OPCODE(ip)                     @ jump to next instruction
5192    /* 11-14 instructions */
5193
5194
5195
5196/* ------------------------------ */
5197    .balign 64
5198.L_OP_MUL_FLOAT: /* 0xa8 */
5199/* File: armv5te/OP_MUL_FLOAT.S */
5200/* File: armv5te/binop.S */
5201    /*
5202     * Generic 32-bit binary operation.  Provide an "instr" line that
5203     * specifies an instruction that performs "result = r0 op r1".
5204     * This could be an ARM instruction or a function call.  (If the result
5205     * comes back in a register other than r0, you can override "result".)
5206     *
5207     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5208     * vCC (r1).  Useful for integer division and modulus.  Note that we
5209     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5210     * handles it correctly.
5211     *
5212     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5213     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5214     *      mul-float, div-float, rem-float
5215     */
5216    /* binop vAA, vBB, vCC */
5217    FETCH(r0, 1)                        @ r0<- CCBB
5218    mov     r9, rINST, lsr #8           @ r9<- AA
5219    mov     r3, r0, lsr #8              @ r3<- CC
5220    and     r2, r0, #255                @ r2<- BB
5221    GET_VREG(r1, r3)                    @ r1<- vCC
5222    GET_VREG(r0, r2)                    @ r0<- vBB
5223    .if 0
5224    cmp     r1, #0                      @ is second operand zero?
5225    beq     common_errDivideByZero
5226    .endif
5227
5228    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5229                               @ optional op; may set condition codes
5230    bl      __aeabi_fmul                              @ r0<- op, r0-r3 changed
5231    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5232    SET_VREG(r0, r9)               @ vAA<- r0
5233    GOTO_OPCODE(ip)                     @ jump to next instruction
5234    /* 11-14 instructions */
5235
5236
5237
5238/* ------------------------------ */
5239    .balign 64
5240.L_OP_DIV_FLOAT: /* 0xa9 */
5241/* File: armv5te/OP_DIV_FLOAT.S */
5242/* File: armv5te/binop.S */
5243    /*
5244     * Generic 32-bit binary operation.  Provide an "instr" line that
5245     * specifies an instruction that performs "result = r0 op r1".
5246     * This could be an ARM instruction or a function call.  (If the result
5247     * comes back in a register other than r0, you can override "result".)
5248     *
5249     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5250     * vCC (r1).  Useful for integer division and modulus.  Note that we
5251     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5252     * handles it correctly.
5253     *
5254     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5255     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5256     *      mul-float, div-float, rem-float
5257     */
5258    /* binop vAA, vBB, vCC */
5259    FETCH(r0, 1)                        @ r0<- CCBB
5260    mov     r9, rINST, lsr #8           @ r9<- AA
5261    mov     r3, r0, lsr #8              @ r3<- CC
5262    and     r2, r0, #255                @ r2<- BB
5263    GET_VREG(r1, r3)                    @ r1<- vCC
5264    GET_VREG(r0, r2)                    @ r0<- vBB
5265    .if 0
5266    cmp     r1, #0                      @ is second operand zero?
5267    beq     common_errDivideByZero
5268    .endif
5269
5270    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5271                               @ optional op; may set condition codes
5272    bl      __aeabi_fdiv                              @ r0<- op, r0-r3 changed
5273    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5274    SET_VREG(r0, r9)               @ vAA<- r0
5275    GOTO_OPCODE(ip)                     @ jump to next instruction
5276    /* 11-14 instructions */
5277
5278
5279
5280/* ------------------------------ */
5281    .balign 64
5282.L_OP_REM_FLOAT: /* 0xaa */
5283/* File: armv5te/OP_REM_FLOAT.S */
5284/* EABI doesn't define a float remainder function, but libm does */
5285/* File: armv5te/binop.S */
5286    /*
5287     * Generic 32-bit binary operation.  Provide an "instr" line that
5288     * specifies an instruction that performs "result = r0 op r1".
5289     * This could be an ARM instruction or a function call.  (If the result
5290     * comes back in a register other than r0, you can override "result".)
5291     *
5292     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5293     * vCC (r1).  Useful for integer division and modulus.  Note that we
5294     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5295     * handles it correctly.
5296     *
5297     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5298     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5299     *      mul-float, div-float, rem-float
5300     */
5301    /* binop vAA, vBB, vCC */
5302    FETCH(r0, 1)                        @ r0<- CCBB
5303    mov     r9, rINST, lsr #8           @ r9<- AA
5304    mov     r3, r0, lsr #8              @ r3<- CC
5305    and     r2, r0, #255                @ r2<- BB
5306    GET_VREG(r1, r3)                    @ r1<- vCC
5307    GET_VREG(r0, r2)                    @ r0<- vBB
5308    .if 0
5309    cmp     r1, #0                      @ is second operand zero?
5310    beq     common_errDivideByZero
5311    .endif
5312
5313    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5314                               @ optional op; may set condition codes
5315    bl      fmodf                              @ r0<- op, r0-r3 changed
5316    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5317    SET_VREG(r0, r9)               @ vAA<- r0
5318    GOTO_OPCODE(ip)                     @ jump to next instruction
5319    /* 11-14 instructions */
5320
5321
5322
5323/* ------------------------------ */
5324    .balign 64
5325.L_OP_ADD_DOUBLE: /* 0xab */
5326/* File: armv5te/OP_ADD_DOUBLE.S */
5327/* File: armv5te/binopWide.S */
5328    /*
5329     * Generic 64-bit binary operation.  Provide an "instr" line that
5330     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5331     * This could be an ARM instruction or a function call.  (If the result
5332     * comes back in a register other than r0, you can override "result".)
5333     *
5334     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5335     * vCC (r1).  Useful for integer division and modulus.
5336     *
5337     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5338     *      xor-long, add-double, sub-double, mul-double, div-double,
5339     *      rem-double
5340     *
5341     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5342     */
5343    /* binop vAA, vBB, vCC */
5344    FETCH(r0, 1)                        @ r0<- CCBB
5345    mov     r9, rINST, lsr #8           @ r9<- AA
5346    and     r2, r0, #255                @ r2<- BB
5347    mov     r3, r0, lsr #8              @ r3<- CC
5348    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5349    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5350    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5351    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5352    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5353    .if 0
5354    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5355    beq     common_errDivideByZero
5356    .endif
5357    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5358
5359                               @ optional op; may set condition codes
5360    bl      __aeabi_dadd                              @ result<- op, r0-r3 changed
5361    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5362    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5363    GOTO_OPCODE(ip)                     @ jump to next instruction
5364    /* 14-17 instructions */
5365
5366
5367
5368/* ------------------------------ */
5369    .balign 64
5370.L_OP_SUB_DOUBLE: /* 0xac */
5371/* File: armv5te/OP_SUB_DOUBLE.S */
5372/* File: armv5te/binopWide.S */
5373    /*
5374     * Generic 64-bit binary operation.  Provide an "instr" line that
5375     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5376     * This could be an ARM instruction or a function call.  (If the result
5377     * comes back in a register other than r0, you can override "result".)
5378     *
5379     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5380     * vCC (r1).  Useful for integer division and modulus.
5381     *
5382     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5383     *      xor-long, add-double, sub-double, mul-double, div-double,
5384     *      rem-double
5385     *
5386     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5387     */
5388    /* binop vAA, vBB, vCC */
5389    FETCH(r0, 1)                        @ r0<- CCBB
5390    mov     r9, rINST, lsr #8           @ r9<- AA
5391    and     r2, r0, #255                @ r2<- BB
5392    mov     r3, r0, lsr #8              @ r3<- CC
5393    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5394    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5395    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5396    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5397    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5398    .if 0
5399    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5400    beq     common_errDivideByZero
5401    .endif
5402    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5403
5404                               @ optional op; may set condition codes
5405    bl      __aeabi_dsub                              @ result<- op, r0-r3 changed
5406    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5407    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5408    GOTO_OPCODE(ip)                     @ jump to next instruction
5409    /* 14-17 instructions */
5410
5411
5412
5413/* ------------------------------ */
5414    .balign 64
5415.L_OP_MUL_DOUBLE: /* 0xad */
5416/* File: armv5te/OP_MUL_DOUBLE.S */
5417/* File: armv5te/binopWide.S */
5418    /*
5419     * Generic 64-bit binary operation.  Provide an "instr" line that
5420     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5421     * This could be an ARM instruction or a function call.  (If the result
5422     * comes back in a register other than r0, you can override "result".)
5423     *
5424     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5425     * vCC (r1).  Useful for integer division and modulus.
5426     *
5427     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5428     *      xor-long, add-double, sub-double, mul-double, div-double,
5429     *      rem-double
5430     *
5431     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5432     */
5433    /* binop vAA, vBB, vCC */
5434    FETCH(r0, 1)                        @ r0<- CCBB
5435    mov     r9, rINST, lsr #8           @ r9<- AA
5436    and     r2, r0, #255                @ r2<- BB
5437    mov     r3, r0, lsr #8              @ r3<- CC
5438    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5439    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5440    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5441    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5442    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5443    .if 0
5444    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5445    beq     common_errDivideByZero
5446    .endif
5447    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5448
5449                               @ optional op; may set condition codes
5450    bl      __aeabi_dmul                              @ result<- op, r0-r3 changed
5451    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5452    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5453    GOTO_OPCODE(ip)                     @ jump to next instruction
5454    /* 14-17 instructions */
5455
5456
5457
5458/* ------------------------------ */
5459    .balign 64
5460.L_OP_DIV_DOUBLE: /* 0xae */
5461/* File: armv5te/OP_DIV_DOUBLE.S */
5462/* File: armv5te/binopWide.S */
5463    /*
5464     * Generic 64-bit binary operation.  Provide an "instr" line that
5465     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5466     * This could be an ARM instruction or a function call.  (If the result
5467     * comes back in a register other than r0, you can override "result".)
5468     *
5469     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5470     * vCC (r1).  Useful for integer division and modulus.
5471     *
5472     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5473     *      xor-long, add-double, sub-double, mul-double, div-double,
5474     *      rem-double
5475     *
5476     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5477     */
5478    /* binop vAA, vBB, vCC */
5479    FETCH(r0, 1)                        @ r0<- CCBB
5480    mov     r9, rINST, lsr #8           @ r9<- AA
5481    and     r2, r0, #255                @ r2<- BB
5482    mov     r3, r0, lsr #8              @ r3<- CC
5483    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5484    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5485    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5486    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5487    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5488    .if 0
5489    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5490    beq     common_errDivideByZero
5491    .endif
5492    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5493
5494                               @ optional op; may set condition codes
5495    bl      __aeabi_ddiv                              @ result<- op, r0-r3 changed
5496    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5497    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5498    GOTO_OPCODE(ip)                     @ jump to next instruction
5499    /* 14-17 instructions */
5500
5501
5502
5503/* ------------------------------ */
5504    .balign 64
5505.L_OP_REM_DOUBLE: /* 0xaf */
5506/* File: armv5te/OP_REM_DOUBLE.S */
5507/* EABI doesn't define a double remainder function, but libm does */
5508/* File: armv5te/binopWide.S */
5509    /*
5510     * Generic 64-bit binary operation.  Provide an "instr" line that
5511     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5512     * This could be an ARM instruction or a function call.  (If the result
5513     * comes back in a register other than r0, you can override "result".)
5514     *
5515     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5516     * vCC (r1).  Useful for integer division and modulus.
5517     *
5518     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5519     *      xor-long, add-double, sub-double, mul-double, div-double,
5520     *      rem-double
5521     *
5522     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5523     */
5524    /* binop vAA, vBB, vCC */
5525    FETCH(r0, 1)                        @ r0<- CCBB
5526    mov     r9, rINST, lsr #8           @ r9<- AA
5527    and     r2, r0, #255                @ r2<- BB
5528    mov     r3, r0, lsr #8              @ r3<- CC
5529    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5530    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5531    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5532    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5533    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5534    .if 0
5535    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5536    beq     common_errDivideByZero
5537    .endif
5538    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5539
5540                               @ optional op; may set condition codes
5541    bl      fmod                              @ result<- op, r0-r3 changed
5542    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5543    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5544    GOTO_OPCODE(ip)                     @ jump to next instruction
5545    /* 14-17 instructions */
5546
5547
5548
5549/* ------------------------------ */
5550    .balign 64
5551.L_OP_ADD_INT_2ADDR: /* 0xb0 */
5552/* File: armv5te/OP_ADD_INT_2ADDR.S */
5553/* File: armv5te/binop2addr.S */
5554    /*
5555     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5556     * that specifies an instruction that performs "result = r0 op r1".
5557     * This could be an ARM instruction or a function call.  (If the result
5558     * comes back in a register other than r0, you can override "result".)
5559     *
5560     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5561     * vCC (r1).  Useful for integer division and modulus.
5562     *
5563     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5564     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5565     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5566     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5567     */
5568    /* binop/2addr vA, vB */
5569    mov     r9, rINST, lsr #8           @ r9<- A+
5570    mov     r3, rINST, lsr #12          @ r3<- B
5571    and     r9, r9, #15
5572    GET_VREG(r1, r3)                    @ r1<- vB
5573    GET_VREG(r0, r9)                    @ r0<- vA
5574    .if 0
5575    cmp     r1, #0                      @ is second operand zero?
5576    beq     common_errDivideByZero
5577    .endif
5578    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5579
5580                               @ optional op; may set condition codes
5581    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
5582    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5583    SET_VREG(r0, r9)               @ vAA<- r0
5584    GOTO_OPCODE(ip)                     @ jump to next instruction
5585    /* 10-13 instructions */
5586
5587
5588
5589/* ------------------------------ */
5590    .balign 64
5591.L_OP_SUB_INT_2ADDR: /* 0xb1 */
5592/* File: armv5te/OP_SUB_INT_2ADDR.S */
5593/* File: armv5te/binop2addr.S */
5594    /*
5595     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5596     * that specifies an instruction that performs "result = r0 op r1".
5597     * This could be an ARM instruction or a function call.  (If the result
5598     * comes back in a register other than r0, you can override "result".)
5599     *
5600     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5601     * vCC (r1).  Useful for integer division and modulus.
5602     *
5603     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5604     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5605     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5606     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5607     */
5608    /* binop/2addr vA, vB */
5609    mov     r9, rINST, lsr #8           @ r9<- A+
5610    mov     r3, rINST, lsr #12          @ r3<- B
5611    and     r9, r9, #15
5612    GET_VREG(r1, r3)                    @ r1<- vB
5613    GET_VREG(r0, r9)                    @ r0<- vA
5614    .if 0
5615    cmp     r1, #0                      @ is second operand zero?
5616    beq     common_errDivideByZero
5617    .endif
5618    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5619
5620                               @ optional op; may set condition codes
5621    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
5622    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5623    SET_VREG(r0, r9)               @ vAA<- r0
5624    GOTO_OPCODE(ip)                     @ jump to next instruction
5625    /* 10-13 instructions */
5626
5627
5628
5629/* ------------------------------ */
5630    .balign 64
5631.L_OP_MUL_INT_2ADDR: /* 0xb2 */
5632/* File: armv5te/OP_MUL_INT_2ADDR.S */
5633/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
5634/* File: armv5te/binop2addr.S */
5635    /*
5636     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5637     * that specifies an instruction that performs "result = r0 op r1".
5638     * This could be an ARM instruction or a function call.  (If the result
5639     * comes back in a register other than r0, you can override "result".)
5640     *
5641     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5642     * vCC (r1).  Useful for integer division and modulus.
5643     *
5644     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5645     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5646     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5647     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5648     */
5649    /* binop/2addr vA, vB */
5650    mov     r9, rINST, lsr #8           @ r9<- A+
5651    mov     r3, rINST, lsr #12          @ r3<- B
5652    and     r9, r9, #15
5653    GET_VREG(r1, r3)                    @ r1<- vB
5654    GET_VREG(r0, r9)                    @ r0<- vA
5655    .if 0
5656    cmp     r1, #0                      @ is second operand zero?
5657    beq     common_errDivideByZero
5658    .endif
5659    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5660
5661                               @ optional op; may set condition codes
5662    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
5663    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5664    SET_VREG(r0, r9)               @ vAA<- r0
5665    GOTO_OPCODE(ip)                     @ jump to next instruction
5666    /* 10-13 instructions */
5667
5668
5669
5670/* ------------------------------ */
5671    .balign 64
5672.L_OP_DIV_INT_2ADDR: /* 0xb3 */
5673/* File: armv5te/OP_DIV_INT_2ADDR.S */
5674/* File: armv5te/binop2addr.S */
5675    /*
5676     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5677     * that specifies an instruction that performs "result = r0 op r1".
5678     * This could be an ARM instruction or a function call.  (If the result
5679     * comes back in a register other than r0, you can override "result".)
5680     *
5681     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5682     * vCC (r1).  Useful for integer division and modulus.
5683     *
5684     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5685     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5686     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5687     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5688     */
5689    /* binop/2addr vA, vB */
5690    mov     r9, rINST, lsr #8           @ r9<- A+
5691    mov     r3, rINST, lsr #12          @ r3<- B
5692    and     r9, r9, #15
5693    GET_VREG(r1, r3)                    @ r1<- vB
5694    GET_VREG(r0, r9)                    @ r0<- vA
5695    .if 1
5696    cmp     r1, #0                      @ is second operand zero?
5697    beq     common_errDivideByZero
5698    .endif
5699    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5700
5701                               @ optional op; may set condition codes
5702    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
5703    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5704    SET_VREG(r0, r9)               @ vAA<- r0
5705    GOTO_OPCODE(ip)                     @ jump to next instruction
5706    /* 10-13 instructions */
5707
5708
5709
5710/* ------------------------------ */
5711    .balign 64
5712.L_OP_REM_INT_2ADDR: /* 0xb4 */
5713/* File: armv5te/OP_REM_INT_2ADDR.S */
5714/* idivmod returns quotient in r0 and remainder in r1 */
5715/* File: armv5te/binop2addr.S */
5716    /*
5717     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5718     * that specifies an instruction that performs "result = r0 op r1".
5719     * This could be an ARM instruction or a function call.  (If the result
5720     * comes back in a register other than r0, you can override "result".)
5721     *
5722     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5723     * vCC (r1).  Useful for integer division and modulus.
5724     *
5725     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5726     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5727     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5728     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5729     */
5730    /* binop/2addr vA, vB */
5731    mov     r9, rINST, lsr #8           @ r9<- A+
5732    mov     r3, rINST, lsr #12          @ r3<- B
5733    and     r9, r9, #15
5734    GET_VREG(r1, r3)                    @ r1<- vB
5735    GET_VREG(r0, r9)                    @ r0<- vA
5736    .if 1
5737    cmp     r1, #0                      @ is second operand zero?
5738    beq     common_errDivideByZero
5739    .endif
5740    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5741
5742                               @ optional op; may set condition codes
5743    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
5744    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5745    SET_VREG(r1, r9)               @ vAA<- r1
5746    GOTO_OPCODE(ip)                     @ jump to next instruction
5747    /* 10-13 instructions */
5748
5749
5750
5751/* ------------------------------ */
5752    .balign 64
5753.L_OP_AND_INT_2ADDR: /* 0xb5 */
5754/* File: armv5te/OP_AND_INT_2ADDR.S */
5755/* File: armv5te/binop2addr.S */
5756    /*
5757     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5758     * that specifies an instruction that performs "result = r0 op r1".
5759     * This could be an ARM instruction or a function call.  (If the result
5760     * comes back in a register other than r0, you can override "result".)
5761     *
5762     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5763     * vCC (r1).  Useful for integer division and modulus.
5764     *
5765     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5766     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5767     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5768     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5769     */
5770    /* binop/2addr vA, vB */
5771    mov     r9, rINST, lsr #8           @ r9<- A+
5772    mov     r3, rINST, lsr #12          @ r3<- B
5773    and     r9, r9, #15
5774    GET_VREG(r1, r3)                    @ r1<- vB
5775    GET_VREG(r0, r9)                    @ r0<- vA
5776    .if 0
5777    cmp     r1, #0                      @ is second operand zero?
5778    beq     common_errDivideByZero
5779    .endif
5780    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5781
5782                               @ optional op; may set condition codes
5783    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
5784    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5785    SET_VREG(r0, r9)               @ vAA<- r0
5786    GOTO_OPCODE(ip)                     @ jump to next instruction
5787    /* 10-13 instructions */
5788
5789
5790
5791/* ------------------------------ */
5792    .balign 64
5793.L_OP_OR_INT_2ADDR: /* 0xb6 */
5794/* File: armv5te/OP_OR_INT_2ADDR.S */
5795/* File: armv5te/binop2addr.S */
5796    /*
5797     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5798     * that specifies an instruction that performs "result = r0 op r1".
5799     * This could be an ARM instruction or a function call.  (If the result
5800     * comes back in a register other than r0, you can override "result".)
5801     *
5802     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5803     * vCC (r1).  Useful for integer division and modulus.
5804     *
5805     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5806     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5807     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5808     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5809     */
5810    /* binop/2addr vA, vB */
5811    mov     r9, rINST, lsr #8           @ r9<- A+
5812    mov     r3, rINST, lsr #12          @ r3<- B
5813    and     r9, r9, #15
5814    GET_VREG(r1, r3)                    @ r1<- vB
5815    GET_VREG(r0, r9)                    @ r0<- vA
5816    .if 0
5817    cmp     r1, #0                      @ is second operand zero?
5818    beq     common_errDivideByZero
5819    .endif
5820    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5821
5822                               @ optional op; may set condition codes
5823    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
5824    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5825    SET_VREG(r0, r9)               @ vAA<- r0
5826    GOTO_OPCODE(ip)                     @ jump to next instruction
5827    /* 10-13 instructions */
5828
5829
5830
5831/* ------------------------------ */
5832    .balign 64
5833.L_OP_XOR_INT_2ADDR: /* 0xb7 */
5834/* File: armv5te/OP_XOR_INT_2ADDR.S */
5835/* File: armv5te/binop2addr.S */
5836    /*
5837     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5838     * that specifies an instruction that performs "result = r0 op r1".
5839     * This could be an ARM instruction or a function call.  (If the result
5840     * comes back in a register other than r0, you can override "result".)
5841     *
5842     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5843     * vCC (r1).  Useful for integer division and modulus.
5844     *
5845     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5846     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5847     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5848     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5849     */
5850    /* binop/2addr vA, vB */
5851    mov     r9, rINST, lsr #8           @ r9<- A+
5852    mov     r3, rINST, lsr #12          @ r3<- B
5853    and     r9, r9, #15
5854    GET_VREG(r1, r3)                    @ r1<- vB
5855    GET_VREG(r0, r9)                    @ r0<- vA
5856    .if 0
5857    cmp     r1, #0                      @ is second operand zero?
5858    beq     common_errDivideByZero
5859    .endif
5860    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5861
5862                               @ optional op; may set condition codes
5863    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
5864    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5865    SET_VREG(r0, r9)               @ vAA<- r0
5866    GOTO_OPCODE(ip)                     @ jump to next instruction
5867    /* 10-13 instructions */
5868
5869
5870
5871/* ------------------------------ */
5872    .balign 64
5873.L_OP_SHL_INT_2ADDR: /* 0xb8 */
5874/* File: armv5te/OP_SHL_INT_2ADDR.S */
5875/* File: armv5te/binop2addr.S */
5876    /*
5877     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5878     * that specifies an instruction that performs "result = r0 op r1".
5879     * This could be an ARM instruction or a function call.  (If the result
5880     * comes back in a register other than r0, you can override "result".)
5881     *
5882     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5883     * vCC (r1).  Useful for integer division and modulus.
5884     *
5885     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5886     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5887     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5888     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5889     */
5890    /* binop/2addr vA, vB */
5891    mov     r9, rINST, lsr #8           @ r9<- A+
5892    mov     r3, rINST, lsr #12          @ r3<- B
5893    and     r9, r9, #15
5894    GET_VREG(r1, r3)                    @ r1<- vB
5895    GET_VREG(r0, r9)                    @ r0<- vA
5896    .if 0
5897    cmp     r1, #0                      @ is second operand zero?
5898    beq     common_errDivideByZero
5899    .endif
5900    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5901
5902    and     r1, r1, #31                           @ optional op; may set condition codes
5903    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
5904    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5905    SET_VREG(r0, r9)               @ vAA<- r0
5906    GOTO_OPCODE(ip)                     @ jump to next instruction
5907    /* 10-13 instructions */
5908
5909
5910
5911/* ------------------------------ */
5912    .balign 64
5913.L_OP_SHR_INT_2ADDR: /* 0xb9 */
5914/* File: armv5te/OP_SHR_INT_2ADDR.S */
5915/* File: armv5te/binop2addr.S */
5916    /*
5917     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5918     * that specifies an instruction that performs "result = r0 op r1".
5919     * This could be an ARM instruction or a function call.  (If the result
5920     * comes back in a register other than r0, you can override "result".)
5921     *
5922     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5923     * vCC (r1).  Useful for integer division and modulus.
5924     *
5925     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5926     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5927     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5928     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5929     */
5930    /* binop/2addr vA, vB */
5931    mov     r9, rINST, lsr #8           @ r9<- A+
5932    mov     r3, rINST, lsr #12          @ r3<- B
5933    and     r9, r9, #15
5934    GET_VREG(r1, r3)                    @ r1<- vB
5935    GET_VREG(r0, r9)                    @ r0<- vA
5936    .if 0
5937    cmp     r1, #0                      @ is second operand zero?
5938    beq     common_errDivideByZero
5939    .endif
5940    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5941
5942    and     r1, r1, #31                           @ optional op; may set condition codes
5943    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
5944    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5945    SET_VREG(r0, r9)               @ vAA<- r0
5946    GOTO_OPCODE(ip)                     @ jump to next instruction
5947    /* 10-13 instructions */
5948
5949
5950
5951/* ------------------------------ */
5952    .balign 64
5953.L_OP_USHR_INT_2ADDR: /* 0xba */
5954/* File: armv5te/OP_USHR_INT_2ADDR.S */
5955/* File: armv5te/binop2addr.S */
5956    /*
5957     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5958     * that specifies an instruction that performs "result = r0 op r1".
5959     * This could be an ARM instruction or a function call.  (If the result
5960     * comes back in a register other than r0, you can override "result".)
5961     *
5962     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5963     * vCC (r1).  Useful for integer division and modulus.
5964     *
5965     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5966     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5967     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5968     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5969     */
5970    /* binop/2addr vA, vB */
5971    mov     r9, rINST, lsr #8           @ r9<- A+
5972    mov     r3, rINST, lsr #12          @ r3<- B
5973    and     r9, r9, #15
5974    GET_VREG(r1, r3)                    @ r1<- vB
5975    GET_VREG(r0, r9)                    @ r0<- vA
5976    .if 0
5977    cmp     r1, #0                      @ is second operand zero?
5978    beq     common_errDivideByZero
5979    .endif
5980    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5981
5982    and     r1, r1, #31                           @ optional op; may set condition codes
5983    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
5984    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5985    SET_VREG(r0, r9)               @ vAA<- r0
5986    GOTO_OPCODE(ip)                     @ jump to next instruction
5987    /* 10-13 instructions */
5988
5989
5990
5991/* ------------------------------ */
5992    .balign 64
5993.L_OP_ADD_LONG_2ADDR: /* 0xbb */
5994/* File: armv5te/OP_ADD_LONG_2ADDR.S */
5995/* File: armv5te/binopWide2addr.S */
5996    /*
5997     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5998     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5999     * This could be an ARM instruction or a function call.  (If the result
6000     * comes back in a register other than r0, you can override "result".)
6001     *
6002     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6003     * vCC (r1).  Useful for integer division and modulus.
6004     *
6005     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6006     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6007     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6008     *      rem-double/2addr
6009     */
6010    /* binop/2addr vA, vB */
6011    mov     r9, rINST, lsr #8           @ r9<- A+
6012    mov     r1, rINST, lsr #12          @ r1<- B
6013    and     r9, r9, #15
6014    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6015    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6016    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6017    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6018    .if 0
6019    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6020    beq     common_errDivideByZero
6021    .endif
6022    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6023
6024    adds    r0, r0, r2                           @ optional op; may set condition codes
6025    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
6026    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6027    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6028    GOTO_OPCODE(ip)                     @ jump to next instruction
6029    /* 12-15 instructions */
6030
6031
6032
6033/* ------------------------------ */
6034    .balign 64
6035.L_OP_SUB_LONG_2ADDR: /* 0xbc */
6036/* File: armv5te/OP_SUB_LONG_2ADDR.S */
6037/* File: armv5te/binopWide2addr.S */
6038    /*
6039     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6040     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6041     * This could be an ARM instruction or a function call.  (If the result
6042     * comes back in a register other than r0, you can override "result".)
6043     *
6044     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6045     * vCC (r1).  Useful for integer division and modulus.
6046     *
6047     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6048     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6049     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6050     *      rem-double/2addr
6051     */
6052    /* binop/2addr vA, vB */
6053    mov     r9, rINST, lsr #8           @ r9<- A+
6054    mov     r1, rINST, lsr #12          @ r1<- B
6055    and     r9, r9, #15
6056    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6057    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6058    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6059    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6060    .if 0
6061    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6062    beq     common_errDivideByZero
6063    .endif
6064    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6065
6066    subs    r0, r0, r2                           @ optional op; may set condition codes
6067    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
6068    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6069    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6070    GOTO_OPCODE(ip)                     @ jump to next instruction
6071    /* 12-15 instructions */
6072
6073
6074
6075/* ------------------------------ */
6076    .balign 64
6077.L_OP_MUL_LONG_2ADDR: /* 0xbd */
6078/* File: armv5te/OP_MUL_LONG_2ADDR.S */
6079    /*
6080     * Signed 64-bit integer multiply, "/2addr" version.
6081     *
6082     * See OP_MUL_LONG for an explanation.
6083     *
6084     * We get a little tight on registers, so to avoid looking up &fp[A]
6085     * again we stuff it into rINST.
6086     */
6087    /* mul-long/2addr vA, vB */
6088    mov     r9, rINST, lsr #8           @ r9<- A+
6089    mov     r1, rINST, lsr #12          @ r1<- B
6090    and     r9, r9, #15
6091    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6092    add     rINST, rFP, r9, lsl #2      @ rINST<- &fp[A]
6093    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6094    ldmia   rINST, {r0-r1}              @ r0/r1<- vAA/vAA+1
6095    mul     ip, r2, r1                  @  ip<- ZxW
6096    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
6097    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
6098    mov     r0, rINST                   @ r0<- &fp[A] (free up rINST)
6099    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6100    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
6101    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6102    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
6103    GOTO_OPCODE(ip)                     @ jump to next instruction
6104
6105
6106/* ------------------------------ */
6107    .balign 64
6108.L_OP_DIV_LONG_2ADDR: /* 0xbe */
6109/* File: armv5te/OP_DIV_LONG_2ADDR.S */
6110/* File: armv5te/binopWide2addr.S */
6111    /*
6112     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6113     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6114     * This could be an ARM instruction or a function call.  (If the result
6115     * comes back in a register other than r0, you can override "result".)
6116     *
6117     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6118     * vCC (r1).  Useful for integer division and modulus.
6119     *
6120     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6121     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6122     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6123     *      rem-double/2addr
6124     */
6125    /* binop/2addr vA, vB */
6126    mov     r9, rINST, lsr #8           @ r9<- A+
6127    mov     r1, rINST, lsr #12          @ r1<- B
6128    and     r9, r9, #15
6129    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6130    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6131    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6132    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6133    .if 1
6134    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6135    beq     common_errDivideByZero
6136    .endif
6137    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6138
6139                               @ optional op; may set condition codes
6140    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
6141    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6142    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6143    GOTO_OPCODE(ip)                     @ jump to next instruction
6144    /* 12-15 instructions */
6145
6146
6147
6148/* ------------------------------ */
6149    .balign 64
6150.L_OP_REM_LONG_2ADDR: /* 0xbf */
6151/* File: armv5te/OP_REM_LONG_2ADDR.S */
6152/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
6153/* File: armv5te/binopWide2addr.S */
6154    /*
6155     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6156     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6157     * This could be an ARM instruction or a function call.  (If the result
6158     * comes back in a register other than r0, you can override "result".)
6159     *
6160     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6161     * vCC (r1).  Useful for integer division and modulus.
6162     *
6163     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6164     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6165     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6166     *      rem-double/2addr
6167     */
6168    /* binop/2addr vA, vB */
6169    mov     r9, rINST, lsr #8           @ r9<- A+
6170    mov     r1, rINST, lsr #12          @ r1<- B
6171    and     r9, r9, #15
6172    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6173    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6174    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6175    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6176    .if 1
6177    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6178    beq     common_errDivideByZero
6179    .endif
6180    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6181
6182                               @ optional op; may set condition codes
6183    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
6184    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6185    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
6186    GOTO_OPCODE(ip)                     @ jump to next instruction
6187    /* 12-15 instructions */
6188
6189
6190
6191/* ------------------------------ */
6192    .balign 64
6193.L_OP_AND_LONG_2ADDR: /* 0xc0 */
6194/* File: armv5te/OP_AND_LONG_2ADDR.S */
6195/* File: armv5te/binopWide2addr.S */
6196    /*
6197     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6198     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6199     * This could be an ARM instruction or a function call.  (If the result
6200     * comes back in a register other than r0, you can override "result".)
6201     *
6202     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6203     * vCC (r1).  Useful for integer division and modulus.
6204     *
6205     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6206     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6207     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6208     *      rem-double/2addr
6209     */
6210    /* binop/2addr vA, vB */
6211    mov     r9, rINST, lsr #8           @ r9<- A+
6212    mov     r1, rINST, lsr #12          @ r1<- B
6213    and     r9, r9, #15
6214    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6215    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6216    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6217    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6218    .if 0
6219    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6220    beq     common_errDivideByZero
6221    .endif
6222    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6223
6224    and     r0, r0, r2                           @ optional op; may set condition codes
6225    and     r1, r1, r3                              @ result<- op, r0-r3 changed
6226    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6227    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6228    GOTO_OPCODE(ip)                     @ jump to next instruction
6229    /* 12-15 instructions */
6230
6231
6232
6233/* ------------------------------ */
6234    .balign 64
6235.L_OP_OR_LONG_2ADDR: /* 0xc1 */
6236/* File: armv5te/OP_OR_LONG_2ADDR.S */
6237/* File: armv5te/binopWide2addr.S */
6238    /*
6239     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6240     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6241     * This could be an ARM instruction or a function call.  (If the result
6242     * comes back in a register other than r0, you can override "result".)
6243     *
6244     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6245     * vCC (r1).  Useful for integer division and modulus.
6246     *
6247     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6248     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6249     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6250     *      rem-double/2addr
6251     */
6252    /* binop/2addr vA, vB */
6253    mov     r9, rINST, lsr #8           @ r9<- A+
6254    mov     r1, rINST, lsr #12          @ r1<- B
6255    and     r9, r9, #15
6256    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6257    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6258    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6259    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6260    .if 0
6261    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6262    beq     common_errDivideByZero
6263    .endif
6264    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6265
6266    orr     r0, r0, r2                           @ optional op; may set condition codes
6267    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
6268    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6269    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6270    GOTO_OPCODE(ip)                     @ jump to next instruction
6271    /* 12-15 instructions */
6272
6273
6274
6275/* ------------------------------ */
6276    .balign 64
6277.L_OP_XOR_LONG_2ADDR: /* 0xc2 */
6278/* File: armv5te/OP_XOR_LONG_2ADDR.S */
6279/* File: armv5te/binopWide2addr.S */
6280    /*
6281     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6282     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6283     * This could be an ARM instruction or a function call.  (If the result
6284     * comes back in a register other than r0, you can override "result".)
6285     *
6286     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6287     * vCC (r1).  Useful for integer division and modulus.
6288     *
6289     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6290     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6291     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6292     *      rem-double/2addr
6293     */
6294    /* binop/2addr vA, vB */
6295    mov     r9, rINST, lsr #8           @ r9<- A+
6296    mov     r1, rINST, lsr #12          @ r1<- B
6297    and     r9, r9, #15
6298    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6299    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6300    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6301    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6302    .if 0
6303    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6304    beq     common_errDivideByZero
6305    .endif
6306    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6307
6308    eor     r0, r0, r2                           @ optional op; may set condition codes
6309    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
6310    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6311    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6312    GOTO_OPCODE(ip)                     @ jump to next instruction
6313    /* 12-15 instructions */
6314
6315
6316
6317/* ------------------------------ */
6318    .balign 64
6319.L_OP_SHL_LONG_2ADDR: /* 0xc3 */
6320/* File: armv5te/OP_SHL_LONG_2ADDR.S */
6321    /*
6322     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6323     * 32-bit shift distance.
6324     */
6325    /* shl-long/2addr vA, vB */
6326    mov     r9, rINST, lsr #8           @ r9<- A+
6327    mov     r3, rINST, lsr #12          @ r3<- B
6328    and     r9, r9, #15
6329    GET_VREG(r2, r3)                    @ r2<- vB
6330    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6331    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6332    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6333
6334    mov     r1, r1, asl r2              @  r1<- r1 << r2
6335    rsb     r3, r2, #32                 @  r3<- 32 - r2
6336    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
6337    subs    ip, r2, #32                 @  ip<- r2 - 32
6338    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6339    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
6340    mov     r0, r0, asl r2              @  r0<- r0 << r2
6341    b       .LOP_SHL_LONG_2ADDR_finish
6342
6343/* ------------------------------ */
6344    .balign 64
6345.L_OP_SHR_LONG_2ADDR: /* 0xc4 */
6346/* File: armv5te/OP_SHR_LONG_2ADDR.S */
6347    /*
6348     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6349     * 32-bit shift distance.
6350     */
6351    /* shr-long/2addr vA, vB */
6352    mov     r9, rINST, lsr #8           @ r9<- A+
6353    mov     r3, rINST, lsr #12          @ r3<- B
6354    and     r9, r9, #15
6355    GET_VREG(r2, r3)                    @ r2<- vB
6356    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6357    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6358    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6359
6360    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6361    rsb     r3, r2, #32                 @  r3<- 32 - r2
6362    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6363    subs    ip, r2, #32                 @  ip<- r2 - 32
6364    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6365    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
6366    mov     r1, r1, asr r2              @  r1<- r1 >> r2
6367    b       .LOP_SHR_LONG_2ADDR_finish
6368
6369/* ------------------------------ */
6370    .balign 64
6371.L_OP_USHR_LONG_2ADDR: /* 0xc5 */
6372/* File: armv5te/OP_USHR_LONG_2ADDR.S */
6373    /*
6374     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6375     * 32-bit shift distance.
6376     */
6377    /* ushr-long/2addr vA, vB */
6378    mov     r9, rINST, lsr #8           @ r9<- A+
6379    mov     r3, rINST, lsr #12          @ r3<- B
6380    and     r9, r9, #15
6381    GET_VREG(r2, r3)                    @ r2<- vB
6382    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6383    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6384    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6385
6386    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6387    rsb     r3, r2, #32                 @  r3<- 32 - r2
6388    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6389    subs    ip, r2, #32                 @  ip<- r2 - 32
6390    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6391    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
6392    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
6393    b       .LOP_USHR_LONG_2ADDR_finish
6394
6395/* ------------------------------ */
6396    .balign 64
6397.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
6398/* File: armv5te/OP_ADD_FLOAT_2ADDR.S */
6399/* File: armv5te/binop2addr.S */
6400    /*
6401     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6402     * that specifies an instruction that performs "result = r0 op r1".
6403     * This could be an ARM instruction or a function call.  (If the result
6404     * comes back in a register other than r0, you can override "result".)
6405     *
6406     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6407     * vCC (r1).  Useful for integer division and modulus.
6408     *
6409     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6410     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6411     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6412     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6413     */
6414    /* binop/2addr vA, vB */
6415    mov     r9, rINST, lsr #8           @ r9<- A+
6416    mov     r3, rINST, lsr #12          @ r3<- B
6417    and     r9, r9, #15
6418    GET_VREG(r1, r3)                    @ r1<- vB
6419    GET_VREG(r0, r9)                    @ r0<- vA
6420    .if 0
6421    cmp     r1, #0                      @ is second operand zero?
6422    beq     common_errDivideByZero
6423    .endif
6424    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6425
6426                               @ optional op; may set condition codes
6427    bl      __aeabi_fadd                              @ r0<- op, r0-r3 changed
6428    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6429    SET_VREG(r0, r9)               @ vAA<- r0
6430    GOTO_OPCODE(ip)                     @ jump to next instruction
6431    /* 10-13 instructions */
6432
6433
6434
6435/* ------------------------------ */
6436    .balign 64
6437.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
6438/* File: armv5te/OP_SUB_FLOAT_2ADDR.S */
6439/* File: armv5te/binop2addr.S */
6440    /*
6441     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6442     * that specifies an instruction that performs "result = r0 op r1".
6443     * This could be an ARM instruction or a function call.  (If the result
6444     * comes back in a register other than r0, you can override "result".)
6445     *
6446     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6447     * vCC (r1).  Useful for integer division and modulus.
6448     *
6449     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6450     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6451     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6452     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6453     */
6454    /* binop/2addr vA, vB */
6455    mov     r9, rINST, lsr #8           @ r9<- A+
6456    mov     r3, rINST, lsr #12          @ r3<- B
6457    and     r9, r9, #15
6458    GET_VREG(r1, r3)                    @ r1<- vB
6459    GET_VREG(r0, r9)                    @ r0<- vA
6460    .if 0
6461    cmp     r1, #0                      @ is second operand zero?
6462    beq     common_errDivideByZero
6463    .endif
6464    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6465
6466                               @ optional op; may set condition codes
6467    bl      __aeabi_fsub                              @ r0<- op, r0-r3 changed
6468    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6469    SET_VREG(r0, r9)               @ vAA<- r0
6470    GOTO_OPCODE(ip)                     @ jump to next instruction
6471    /* 10-13 instructions */
6472
6473
6474
6475/* ------------------------------ */
6476    .balign 64
6477.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
6478/* File: armv5te/OP_MUL_FLOAT_2ADDR.S */
6479/* File: armv5te/binop2addr.S */
6480    /*
6481     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6482     * that specifies an instruction that performs "result = r0 op r1".
6483     * This could be an ARM instruction or a function call.  (If the result
6484     * comes back in a register other than r0, you can override "result".)
6485     *
6486     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6487     * vCC (r1).  Useful for integer division and modulus.
6488     *
6489     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6490     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6491     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6492     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6493     */
6494    /* binop/2addr vA, vB */
6495    mov     r9, rINST, lsr #8           @ r9<- A+
6496    mov     r3, rINST, lsr #12          @ r3<- B
6497    and     r9, r9, #15
6498    GET_VREG(r1, r3)                    @ r1<- vB
6499    GET_VREG(r0, r9)                    @ r0<- vA
6500    .if 0
6501    cmp     r1, #0                      @ is second operand zero?
6502    beq     common_errDivideByZero
6503    .endif
6504    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6505
6506                               @ optional op; may set condition codes
6507    bl      __aeabi_fmul                              @ r0<- op, r0-r3 changed
6508    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6509    SET_VREG(r0, r9)               @ vAA<- r0
6510    GOTO_OPCODE(ip)                     @ jump to next instruction
6511    /* 10-13 instructions */
6512
6513
6514
6515/* ------------------------------ */
6516    .balign 64
6517.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
6518/* File: armv5te/OP_DIV_FLOAT_2ADDR.S */
6519/* File: armv5te/binop2addr.S */
6520    /*
6521     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6522     * that specifies an instruction that performs "result = r0 op r1".
6523     * This could be an ARM instruction or a function call.  (If the result
6524     * comes back in a register other than r0, you can override "result".)
6525     *
6526     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6527     * vCC (r1).  Useful for integer division and modulus.
6528     *
6529     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6530     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6531     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6532     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6533     */
6534    /* binop/2addr vA, vB */
6535    mov     r9, rINST, lsr #8           @ r9<- A+
6536    mov     r3, rINST, lsr #12          @ r3<- B
6537    and     r9, r9, #15
6538    GET_VREG(r1, r3)                    @ r1<- vB
6539    GET_VREG(r0, r9)                    @ r0<- vA
6540    .if 0
6541    cmp     r1, #0                      @ is second operand zero?
6542    beq     common_errDivideByZero
6543    .endif
6544    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6545
6546                               @ optional op; may set condition codes
6547    bl      __aeabi_fdiv                              @ r0<- op, r0-r3 changed
6548    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6549    SET_VREG(r0, r9)               @ vAA<- r0
6550    GOTO_OPCODE(ip)                     @ jump to next instruction
6551    /* 10-13 instructions */
6552
6553
6554
6555/* ------------------------------ */
6556    .balign 64
6557.L_OP_REM_FLOAT_2ADDR: /* 0xca */
6558/* File: armv5te/OP_REM_FLOAT_2ADDR.S */
6559/* EABI doesn't define a float remainder function, but libm does */
6560/* File: armv5te/binop2addr.S */
6561    /*
6562     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6563     * that specifies an instruction that performs "result = r0 op r1".
6564     * This could be an ARM instruction or a function call.  (If the result
6565     * comes back in a register other than r0, you can override "result".)
6566     *
6567     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6568     * vCC (r1).  Useful for integer division and modulus.
6569     *
6570     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6571     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6572     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6573     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6574     */
6575    /* binop/2addr vA, vB */
6576    mov     r9, rINST, lsr #8           @ r9<- A+
6577    mov     r3, rINST, lsr #12          @ r3<- B
6578    and     r9, r9, #15
6579    GET_VREG(r1, r3)                    @ r1<- vB
6580    GET_VREG(r0, r9)                    @ r0<- vA
6581    .if 0
6582    cmp     r1, #0                      @ is second operand zero?
6583    beq     common_errDivideByZero
6584    .endif
6585    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6586
6587                               @ optional op; may set condition codes
6588    bl      fmodf                              @ r0<- op, r0-r3 changed
6589    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6590    SET_VREG(r0, r9)               @ vAA<- r0
6591    GOTO_OPCODE(ip)                     @ jump to next instruction
6592    /* 10-13 instructions */
6593
6594
6595
6596/* ------------------------------ */
6597    .balign 64
6598.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
6599/* File: armv5te/OP_ADD_DOUBLE_2ADDR.S */
6600/* File: armv5te/binopWide2addr.S */
6601    /*
6602     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6603     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6604     * This could be an ARM instruction or a function call.  (If the result
6605     * comes back in a register other than r0, you can override "result".)
6606     *
6607     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6608     * vCC (r1).  Useful for integer division and modulus.
6609     *
6610     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6611     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6612     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6613     *      rem-double/2addr
6614     */
6615    /* binop/2addr vA, vB */
6616    mov     r9, rINST, lsr #8           @ r9<- A+
6617    mov     r1, rINST, lsr #12          @ r1<- B
6618    and     r9, r9, #15
6619    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6620    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6621    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6622    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6623    .if 0
6624    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6625    beq     common_errDivideByZero
6626    .endif
6627    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6628
6629                               @ optional op; may set condition codes
6630    bl      __aeabi_dadd                              @ result<- op, r0-r3 changed
6631    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6632    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6633    GOTO_OPCODE(ip)                     @ jump to next instruction
6634    /* 12-15 instructions */
6635
6636
6637
6638/* ------------------------------ */
6639    .balign 64
6640.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
6641/* File: armv5te/OP_SUB_DOUBLE_2ADDR.S */
6642/* File: armv5te/binopWide2addr.S */
6643    /*
6644     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6645     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6646     * This could be an ARM instruction or a function call.  (If the result
6647     * comes back in a register other than r0, you can override "result".)
6648     *
6649     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6650     * vCC (r1).  Useful for integer division and modulus.
6651     *
6652     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6653     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6654     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6655     *      rem-double/2addr
6656     */
6657    /* binop/2addr vA, vB */
6658    mov     r9, rINST, lsr #8           @ r9<- A+
6659    mov     r1, rINST, lsr #12          @ r1<- B
6660    and     r9, r9, #15
6661    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6662    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6663    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6664    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6665    .if 0
6666    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6667    beq     common_errDivideByZero
6668    .endif
6669    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6670
6671                               @ optional op; may set condition codes
6672    bl      __aeabi_dsub                              @ result<- op, r0-r3 changed
6673    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6674    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6675    GOTO_OPCODE(ip)                     @ jump to next instruction
6676    /* 12-15 instructions */
6677
6678
6679
6680/* ------------------------------ */
6681    .balign 64
6682.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
6683/* File: armv5te/OP_MUL_DOUBLE_2ADDR.S */
6684/* File: armv5te/binopWide2addr.S */
6685    /*
6686     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6687     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6688     * This could be an ARM instruction or a function call.  (If the result
6689     * comes back in a register other than r0, you can override "result".)
6690     *
6691     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6692     * vCC (r1).  Useful for integer division and modulus.
6693     *
6694     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6695     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6696     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6697     *      rem-double/2addr
6698     */
6699    /* binop/2addr vA, vB */
6700    mov     r9, rINST, lsr #8           @ r9<- A+
6701    mov     r1, rINST, lsr #12          @ r1<- B
6702    and     r9, r9, #15
6703    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6704    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6705    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6706    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6707    .if 0
6708    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6709    beq     common_errDivideByZero
6710    .endif
6711    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6712
6713                               @ optional op; may set condition codes
6714    bl      __aeabi_dmul                              @ result<- op, r0-r3 changed
6715    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6716    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6717    GOTO_OPCODE(ip)                     @ jump to next instruction
6718    /* 12-15 instructions */
6719
6720
6721
6722/* ------------------------------ */
6723    .balign 64
6724.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
6725/* File: armv5te/OP_DIV_DOUBLE_2ADDR.S */
6726/* File: armv5te/binopWide2addr.S */
6727    /*
6728     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6729     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6730     * This could be an ARM instruction or a function call.  (If the result
6731     * comes back in a register other than r0, you can override "result".)
6732     *
6733     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6734     * vCC (r1).  Useful for integer division and modulus.
6735     *
6736     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6737     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6738     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6739     *      rem-double/2addr
6740     */
6741    /* binop/2addr vA, vB */
6742    mov     r9, rINST, lsr #8           @ r9<- A+
6743    mov     r1, rINST, lsr #12          @ r1<- B
6744    and     r9, r9, #15
6745    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6746    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6747    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6748    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6749    .if 0
6750    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6751    beq     common_errDivideByZero
6752    .endif
6753    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6754
6755                               @ optional op; may set condition codes
6756    bl      __aeabi_ddiv                              @ result<- op, r0-r3 changed
6757    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6758    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6759    GOTO_OPCODE(ip)                     @ jump to next instruction
6760    /* 12-15 instructions */
6761
6762
6763
6764/* ------------------------------ */
6765    .balign 64
6766.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
6767/* File: armv5te/OP_REM_DOUBLE_2ADDR.S */
6768/* EABI doesn't define a double remainder function, but libm does */
6769/* File: armv5te/binopWide2addr.S */
6770    /*
6771     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6772     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6773     * This could be an ARM instruction or a function call.  (If the result
6774     * comes back in a register other than r0, you can override "result".)
6775     *
6776     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6777     * vCC (r1).  Useful for integer division and modulus.
6778     *
6779     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6780     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6781     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6782     *      rem-double/2addr
6783     */
6784    /* binop/2addr vA, vB */
6785    mov     r9, rINST, lsr #8           @ r9<- A+
6786    mov     r1, rINST, lsr #12          @ r1<- B
6787    and     r9, r9, #15
6788    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6789    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6790    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6791    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6792    .if 0
6793    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6794    beq     common_errDivideByZero
6795    .endif
6796    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6797
6798                               @ optional op; may set condition codes
6799    bl      fmod                              @ result<- op, r0-r3 changed
6800    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6801    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6802    GOTO_OPCODE(ip)                     @ jump to next instruction
6803    /* 12-15 instructions */
6804
6805
6806
6807/* ------------------------------ */
6808    .balign 64
6809.L_OP_ADD_INT_LIT16: /* 0xd0 */
6810/* File: armv5te/OP_ADD_INT_LIT16.S */
6811/* File: armv5te/binopLit16.S */
6812    /*
6813     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6814     * that specifies an instruction that performs "result = r0 op r1".
6815     * This could be an ARM instruction or a function call.  (If the result
6816     * comes back in a register other than r0, you can override "result".)
6817     *
6818     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6819     * vCC (r1).  Useful for integer division and modulus.
6820     *
6821     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6822     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6823     */
6824    /* binop/lit16 vA, vB, #+CCCC */
6825    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6826    mov     r2, rINST, lsr #12          @ r2<- B
6827    mov     r9, rINST, lsr #8           @ r9<- A+
6828    GET_VREG(r0, r2)                    @ r0<- vB
6829    and     r9, r9, #15
6830    .if 0
6831    cmp     r1, #0                      @ is second operand zero?
6832    beq     common_errDivideByZero
6833    .endif
6834    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6835
6836    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6837    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6838    SET_VREG(r0, r9)               @ vAA<- r0
6839    GOTO_OPCODE(ip)                     @ jump to next instruction
6840    /* 10-13 instructions */
6841
6842
6843
6844/* ------------------------------ */
6845    .balign 64
6846.L_OP_RSUB_INT: /* 0xd1 */
6847/* File: armv5te/OP_RSUB_INT.S */
6848/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
6849/* File: armv5te/binopLit16.S */
6850    /*
6851     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6852     * that specifies an instruction that performs "result = r0 op r1".
6853     * This could be an ARM instruction or a function call.  (If the result
6854     * comes back in a register other than r0, you can override "result".)
6855     *
6856     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6857     * vCC (r1).  Useful for integer division and modulus.
6858     *
6859     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6860     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6861     */
6862    /* binop/lit16 vA, vB, #+CCCC */
6863    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6864    mov     r2, rINST, lsr #12          @ r2<- B
6865    mov     r9, rINST, lsr #8           @ r9<- A+
6866    GET_VREG(r0, r2)                    @ r0<- vB
6867    and     r9, r9, #15
6868    .if 0
6869    cmp     r1, #0                      @ is second operand zero?
6870    beq     common_errDivideByZero
6871    .endif
6872    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6873
6874    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6875    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6876    SET_VREG(r0, r9)               @ vAA<- r0
6877    GOTO_OPCODE(ip)                     @ jump to next instruction
6878    /* 10-13 instructions */
6879
6880
6881
6882/* ------------------------------ */
6883    .balign 64
6884.L_OP_MUL_INT_LIT16: /* 0xd2 */
6885/* File: armv5te/OP_MUL_INT_LIT16.S */
6886/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6887/* File: armv5te/binopLit16.S */
6888    /*
6889     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6890     * that specifies an instruction that performs "result = r0 op r1".
6891     * This could be an ARM instruction or a function call.  (If the result
6892     * comes back in a register other than r0, you can override "result".)
6893     *
6894     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6895     * vCC (r1).  Useful for integer division and modulus.
6896     *
6897     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6898     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6899     */
6900    /* binop/lit16 vA, vB, #+CCCC */
6901    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6902    mov     r2, rINST, lsr #12          @ r2<- B
6903    mov     r9, rINST, lsr #8           @ r9<- A+
6904    GET_VREG(r0, r2)                    @ r0<- vB
6905    and     r9, r9, #15
6906    .if 0
6907    cmp     r1, #0                      @ is second operand zero?
6908    beq     common_errDivideByZero
6909    .endif
6910    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6911
6912    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6913    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6914    SET_VREG(r0, r9)               @ vAA<- r0
6915    GOTO_OPCODE(ip)                     @ jump to next instruction
6916    /* 10-13 instructions */
6917
6918
6919
6920/* ------------------------------ */
6921    .balign 64
6922.L_OP_DIV_INT_LIT16: /* 0xd3 */
6923/* File: armv5te/OP_DIV_INT_LIT16.S */
6924/* File: armv5te/binopLit16.S */
6925    /*
6926     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6927     * that specifies an instruction that performs "result = r0 op r1".
6928     * This could be an ARM instruction or a function call.  (If the result
6929     * comes back in a register other than r0, you can override "result".)
6930     *
6931     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6932     * vCC (r1).  Useful for integer division and modulus.
6933     *
6934     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6935     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6936     */
6937    /* binop/lit16 vA, vB, #+CCCC */
6938    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6939    mov     r2, rINST, lsr #12          @ r2<- B
6940    mov     r9, rINST, lsr #8           @ r9<- A+
6941    GET_VREG(r0, r2)                    @ r0<- vB
6942    and     r9, r9, #15
6943    .if 1
6944    cmp     r1, #0                      @ is second operand zero?
6945    beq     common_errDivideByZero
6946    .endif
6947    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6948
6949    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6950    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6951    SET_VREG(r0, r9)               @ vAA<- r0
6952    GOTO_OPCODE(ip)                     @ jump to next instruction
6953    /* 10-13 instructions */
6954
6955
6956
6957/* ------------------------------ */
6958    .balign 64
6959.L_OP_REM_INT_LIT16: /* 0xd4 */
6960/* File: armv5te/OP_REM_INT_LIT16.S */
6961/* idivmod returns quotient in r0 and remainder in r1 */
6962/* File: armv5te/binopLit16.S */
6963    /*
6964     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6965     * that specifies an instruction that performs "result = r0 op r1".
6966     * This could be an ARM instruction or a function call.  (If the result
6967     * comes back in a register other than r0, you can override "result".)
6968     *
6969     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6970     * vCC (r1).  Useful for integer division and modulus.
6971     *
6972     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6973     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6974     */
6975    /* binop/lit16 vA, vB, #+CCCC */
6976    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6977    mov     r2, rINST, lsr #12          @ r2<- B
6978    mov     r9, rINST, lsr #8           @ r9<- A+
6979    GET_VREG(r0, r2)                    @ r0<- vB
6980    and     r9, r9, #15
6981    .if 1
6982    cmp     r1, #0                      @ is second operand zero?
6983    beq     common_errDivideByZero
6984    .endif
6985    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6986
6987    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6988    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6989    SET_VREG(r1, r9)               @ vAA<- r1
6990    GOTO_OPCODE(ip)                     @ jump to next instruction
6991    /* 10-13 instructions */
6992
6993
6994
6995/* ------------------------------ */
6996    .balign 64
6997.L_OP_AND_INT_LIT16: /* 0xd5 */
6998/* File: armv5te/OP_AND_INT_LIT16.S */
6999/* File: armv5te/binopLit16.S */
7000    /*
7001     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
7002     * that specifies an instruction that performs "result = r0 op r1".
7003     * This could be an ARM instruction or a function call.  (If the result
7004     * comes back in a register other than r0, you can override "result".)
7005     *
7006     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7007     * vCC (r1).  Useful for integer division and modulus.
7008     *
7009     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
7010     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
7011     */
7012    /* binop/lit16 vA, vB, #+CCCC */
7013    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
7014    mov     r2, rINST, lsr #12          @ r2<- B
7015    mov     r9, rINST, lsr #8           @ r9<- A+
7016    GET_VREG(r0, r2)                    @ r0<- vB
7017    and     r9, r9, #15
7018    .if 0
7019    cmp     r1, #0                      @ is second operand zero?
7020    beq     common_errDivideByZero
7021    .endif
7022    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7023
7024    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
7025    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7026    SET_VREG(r0, r9)               @ vAA<- r0
7027    GOTO_OPCODE(ip)                     @ jump to next instruction
7028    /* 10-13 instructions */
7029
7030
7031
7032/* ------------------------------ */
7033    .balign 64
7034.L_OP_OR_INT_LIT16: /* 0xd6 */
7035/* File: armv5te/OP_OR_INT_LIT16.S */
7036/* File: armv5te/binopLit16.S */
7037    /*
7038     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
7039     * that specifies an instruction that performs "result = r0 op r1".
7040     * This could be an ARM instruction or a function call.  (If the result
7041     * comes back in a register other than r0, you can override "result".)
7042     *
7043     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7044     * vCC (r1).  Useful for integer division and modulus.
7045     *
7046     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
7047     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
7048     */
7049    /* binop/lit16 vA, vB, #+CCCC */
7050    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
7051    mov     r2, rINST, lsr #12          @ r2<- B
7052    mov     r9, rINST, lsr #8           @ r9<- A+
7053    GET_VREG(r0, r2)                    @ r0<- vB
7054    and     r9, r9, #15
7055    .if 0
7056    cmp     r1, #0                      @ is second operand zero?
7057    beq     common_errDivideByZero
7058    .endif
7059    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7060
7061    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
7062    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7063    SET_VREG(r0, r9)               @ vAA<- r0
7064    GOTO_OPCODE(ip)                     @ jump to next instruction
7065    /* 10-13 instructions */
7066
7067
7068
7069/* ------------------------------ */
7070    .balign 64
7071.L_OP_XOR_INT_LIT16: /* 0xd7 */
7072/* File: armv5te/OP_XOR_INT_LIT16.S */
7073/* File: armv5te/binopLit16.S */
7074    /*
7075     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
7076     * that specifies an instruction that performs "result = r0 op r1".
7077     * This could be an ARM instruction or a function call.  (If the result
7078     * comes back in a register other than r0, you can override "result".)
7079     *
7080     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7081     * vCC (r1).  Useful for integer division and modulus.
7082     *
7083     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
7084     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
7085     */
7086    /* binop/lit16 vA, vB, #+CCCC */
7087    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
7088    mov     r2, rINST, lsr #12          @ r2<- B
7089    mov     r9, rINST, lsr #8           @ r9<- A+
7090    GET_VREG(r0, r2)                    @ r0<- vB
7091    and     r9, r9, #15
7092    .if 0
7093    cmp     r1, #0                      @ is second operand zero?
7094    beq     common_errDivideByZero
7095    .endif
7096    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7097
7098    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
7099    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7100    SET_VREG(r0, r9)               @ vAA<- r0
7101    GOTO_OPCODE(ip)                     @ jump to next instruction
7102    /* 10-13 instructions */
7103
7104
7105
7106/* ------------------------------ */
7107    .balign 64
7108.L_OP_ADD_INT_LIT8: /* 0xd8 */
7109/* File: armv5te/OP_ADD_INT_LIT8.S */
7110/* File: armv5te/binopLit8.S */
7111    /*
7112     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7113     * that specifies an instruction that performs "result = r0 op r1".
7114     * This could be an ARM instruction or a function call.  (If the result
7115     * comes back in a register other than r0, you can override "result".)
7116     *
7117     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7118     * vCC (r1).  Useful for integer division and modulus.
7119     *
7120     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7121     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7122     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7123     */
7124    /* binop/lit8 vAA, vBB, #+CC */
7125    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7126    mov     r9, rINST, lsr #8           @ r9<- AA
7127    and     r2, r3, #255                @ r2<- BB
7128    GET_VREG(r0, r2)                    @ r0<- vBB
7129    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7130    .if 0
7131    @cmp     r1, #0                      @ is second operand zero?
7132    beq     common_errDivideByZero
7133    .endif
7134    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7135
7136                               @ optional op; may set condition codes
7137    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
7138    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7139    SET_VREG(r0, r9)               @ vAA<- r0
7140    GOTO_OPCODE(ip)                     @ jump to next instruction
7141    /* 10-12 instructions */
7142
7143
7144
7145/* ------------------------------ */
7146    .balign 64
7147.L_OP_RSUB_INT_LIT8: /* 0xd9 */
7148/* File: armv5te/OP_RSUB_INT_LIT8.S */
7149/* File: armv5te/binopLit8.S */
7150    /*
7151     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7152     * that specifies an instruction that performs "result = r0 op r1".
7153     * This could be an ARM instruction or a function call.  (If the result
7154     * comes back in a register other than r0, you can override "result".)
7155     *
7156     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7157     * vCC (r1).  Useful for integer division and modulus.
7158     *
7159     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7160     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7161     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7162     */
7163    /* binop/lit8 vAA, vBB, #+CC */
7164    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7165    mov     r9, rINST, lsr #8           @ r9<- AA
7166    and     r2, r3, #255                @ r2<- BB
7167    GET_VREG(r0, r2)                    @ r0<- vBB
7168    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7169    .if 0
7170    @cmp     r1, #0                      @ is second operand zero?
7171    beq     common_errDivideByZero
7172    .endif
7173    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7174
7175                               @ optional op; may set condition codes
7176    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
7177    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7178    SET_VREG(r0, r9)               @ vAA<- r0
7179    GOTO_OPCODE(ip)                     @ jump to next instruction
7180    /* 10-12 instructions */
7181
7182
7183
7184/* ------------------------------ */
7185    .balign 64
7186.L_OP_MUL_INT_LIT8: /* 0xda */
7187/* File: armv5te/OP_MUL_INT_LIT8.S */
7188/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
7189/* File: armv5te/binopLit8.S */
7190    /*
7191     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7192     * that specifies an instruction that performs "result = r0 op r1".
7193     * This could be an ARM instruction or a function call.  (If the result
7194     * comes back in a register other than r0, you can override "result".)
7195     *
7196     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7197     * vCC (r1).  Useful for integer division and modulus.
7198     *
7199     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7200     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7201     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7202     */
7203    /* binop/lit8 vAA, vBB, #+CC */
7204    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7205    mov     r9, rINST, lsr #8           @ r9<- AA
7206    and     r2, r3, #255                @ r2<- BB
7207    GET_VREG(r0, r2)                    @ r0<- vBB
7208    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7209    .if 0
7210    @cmp     r1, #0                      @ is second operand zero?
7211    beq     common_errDivideByZero
7212    .endif
7213    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7214
7215                               @ optional op; may set condition codes
7216    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
7217    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7218    SET_VREG(r0, r9)               @ vAA<- r0
7219    GOTO_OPCODE(ip)                     @ jump to next instruction
7220    /* 10-12 instructions */
7221
7222
7223
7224/* ------------------------------ */
7225    .balign 64
7226.L_OP_DIV_INT_LIT8: /* 0xdb */
7227/* File: armv5te/OP_DIV_INT_LIT8.S */
7228/* File: armv5te/binopLit8.S */
7229    /*
7230     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7231     * that specifies an instruction that performs "result = r0 op r1".
7232     * This could be an ARM instruction or a function call.  (If the result
7233     * comes back in a register other than r0, you can override "result".)
7234     *
7235     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7236     * vCC (r1).  Useful for integer division and modulus.
7237     *
7238     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7239     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7240     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7241     */
7242    /* binop/lit8 vAA, vBB, #+CC */
7243    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7244    mov     r9, rINST, lsr #8           @ r9<- AA
7245    and     r2, r3, #255                @ r2<- BB
7246    GET_VREG(r0, r2)                    @ r0<- vBB
7247    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7248    .if 1
7249    @cmp     r1, #0                      @ is second operand zero?
7250    beq     common_errDivideByZero
7251    .endif
7252    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7253
7254                               @ optional op; may set condition codes
7255    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
7256    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7257    SET_VREG(r0, r9)               @ vAA<- r0
7258    GOTO_OPCODE(ip)                     @ jump to next instruction
7259    /* 10-12 instructions */
7260
7261
7262
7263/* ------------------------------ */
7264    .balign 64
7265.L_OP_REM_INT_LIT8: /* 0xdc */
7266/* File: armv5te/OP_REM_INT_LIT8.S */
7267/* idivmod returns quotient in r0 and remainder in r1 */
7268/* File: armv5te/binopLit8.S */
7269    /*
7270     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7271     * that specifies an instruction that performs "result = r0 op r1".
7272     * This could be an ARM instruction or a function call.  (If the result
7273     * comes back in a register other than r0, you can override "result".)
7274     *
7275     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7276     * vCC (r1).  Useful for integer division and modulus.
7277     *
7278     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7279     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7280     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7281     */
7282    /* binop/lit8 vAA, vBB, #+CC */
7283    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7284    mov     r9, rINST, lsr #8           @ r9<- AA
7285    and     r2, r3, #255                @ r2<- BB
7286    GET_VREG(r0, r2)                    @ r0<- vBB
7287    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7288    .if 1
7289    @cmp     r1, #0                      @ is second operand zero?
7290    beq     common_errDivideByZero
7291    .endif
7292    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7293
7294                               @ optional op; may set condition codes
7295    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
7296    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7297    SET_VREG(r1, r9)               @ vAA<- r1
7298    GOTO_OPCODE(ip)                     @ jump to next instruction
7299    /* 10-12 instructions */
7300
7301
7302
7303/* ------------------------------ */
7304    .balign 64
7305.L_OP_AND_INT_LIT8: /* 0xdd */
7306/* File: armv5te/OP_AND_INT_LIT8.S */
7307/* File: armv5te/binopLit8.S */
7308    /*
7309     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7310     * that specifies an instruction that performs "result = r0 op r1".
7311     * This could be an ARM instruction or a function call.  (If the result
7312     * comes back in a register other than r0, you can override "result".)
7313     *
7314     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7315     * vCC (r1).  Useful for integer division and modulus.
7316     *
7317     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7318     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7319     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7320     */
7321    /* binop/lit8 vAA, vBB, #+CC */
7322    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7323    mov     r9, rINST, lsr #8           @ r9<- AA
7324    and     r2, r3, #255                @ r2<- BB
7325    GET_VREG(r0, r2)                    @ r0<- vBB
7326    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7327    .if 0
7328    @cmp     r1, #0                      @ is second operand zero?
7329    beq     common_errDivideByZero
7330    .endif
7331    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7332
7333                               @ optional op; may set condition codes
7334    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
7335    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7336    SET_VREG(r0, r9)               @ vAA<- r0
7337    GOTO_OPCODE(ip)                     @ jump to next instruction
7338    /* 10-12 instructions */
7339
7340
7341
7342/* ------------------------------ */
7343    .balign 64
7344.L_OP_OR_INT_LIT8: /* 0xde */
7345/* File: armv5te/OP_OR_INT_LIT8.S */
7346/* File: armv5te/binopLit8.S */
7347    /*
7348     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7349     * that specifies an instruction that performs "result = r0 op r1".
7350     * This could be an ARM instruction or a function call.  (If the result
7351     * comes back in a register other than r0, you can override "result".)
7352     *
7353     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7354     * vCC (r1).  Useful for integer division and modulus.
7355     *
7356     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7357     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7358     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7359     */
7360    /* binop/lit8 vAA, vBB, #+CC */
7361    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7362    mov     r9, rINST, lsr #8           @ r9<- AA
7363    and     r2, r3, #255                @ r2<- BB
7364    GET_VREG(r0, r2)                    @ r0<- vBB
7365    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7366    .if 0
7367    @cmp     r1, #0                      @ is second operand zero?
7368    beq     common_errDivideByZero
7369    .endif
7370    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7371
7372                               @ optional op; may set condition codes
7373    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
7374    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7375    SET_VREG(r0, r9)               @ vAA<- r0
7376    GOTO_OPCODE(ip)                     @ jump to next instruction
7377    /* 10-12 instructions */
7378
7379
7380
7381/* ------------------------------ */
7382    .balign 64
7383.L_OP_XOR_INT_LIT8: /* 0xdf */
7384/* File: armv5te/OP_XOR_INT_LIT8.S */
7385/* File: armv5te/binopLit8.S */
7386    /*
7387     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7388     * that specifies an instruction that performs "result = r0 op r1".
7389     * This could be an ARM instruction or a function call.  (If the result
7390     * comes back in a register other than r0, you can override "result".)
7391     *
7392     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7393     * vCC (r1).  Useful for integer division and modulus.
7394     *
7395     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7396     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7397     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7398     */
7399    /* binop/lit8 vAA, vBB, #+CC */
7400    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7401    mov     r9, rINST, lsr #8           @ r9<- AA
7402    and     r2, r3, #255                @ r2<- BB
7403    GET_VREG(r0, r2)                    @ r0<- vBB
7404    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7405    .if 0
7406    @cmp     r1, #0                      @ is second operand zero?
7407    beq     common_errDivideByZero
7408    .endif
7409    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7410
7411                               @ optional op; may set condition codes
7412    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
7413    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7414    SET_VREG(r0, r9)               @ vAA<- r0
7415    GOTO_OPCODE(ip)                     @ jump to next instruction
7416    /* 10-12 instructions */
7417
7418
7419
7420/* ------------------------------ */
7421    .balign 64
7422.L_OP_SHL_INT_LIT8: /* 0xe0 */
7423/* File: armv5te/OP_SHL_INT_LIT8.S */
7424/* File: armv5te/binopLit8.S */
7425    /*
7426     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7427     * that specifies an instruction that performs "result = r0 op r1".
7428     * This could be an ARM instruction or a function call.  (If the result
7429     * comes back in a register other than r0, you can override "result".)
7430     *
7431     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7432     * vCC (r1).  Useful for integer division and modulus.
7433     *
7434     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7435     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7436     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7437     */
7438    /* binop/lit8 vAA, vBB, #+CC */
7439    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7440    mov     r9, rINST, lsr #8           @ r9<- AA
7441    and     r2, r3, #255                @ r2<- BB
7442    GET_VREG(r0, r2)                    @ r0<- vBB
7443    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7444    .if 0
7445    @cmp     r1, #0                      @ is second operand zero?
7446    beq     common_errDivideByZero
7447    .endif
7448    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7449
7450    and     r1, r1, #31                           @ optional op; may set condition codes
7451    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
7452    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7453    SET_VREG(r0, r9)               @ vAA<- r0
7454    GOTO_OPCODE(ip)                     @ jump to next instruction
7455    /* 10-12 instructions */
7456
7457
7458
7459/* ------------------------------ */
7460    .balign 64
7461.L_OP_SHR_INT_LIT8: /* 0xe1 */
7462/* File: armv5te/OP_SHR_INT_LIT8.S */
7463/* File: armv5te/binopLit8.S */
7464    /*
7465     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7466     * that specifies an instruction that performs "result = r0 op r1".
7467     * This could be an ARM instruction or a function call.  (If the result
7468     * comes back in a register other than r0, you can override "result".)
7469     *
7470     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7471     * vCC (r1).  Useful for integer division and modulus.
7472     *
7473     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7474     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7475     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7476     */
7477    /* binop/lit8 vAA, vBB, #+CC */
7478    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7479    mov     r9, rINST, lsr #8           @ r9<- AA
7480    and     r2, r3, #255                @ r2<- BB
7481    GET_VREG(r0, r2)                    @ r0<- vBB
7482    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7483    .if 0
7484    @cmp     r1, #0                      @ is second operand zero?
7485    beq     common_errDivideByZero
7486    .endif
7487    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7488
7489    and     r1, r1, #31                           @ optional op; may set condition codes
7490    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
7491    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7492    SET_VREG(r0, r9)               @ vAA<- r0
7493    GOTO_OPCODE(ip)                     @ jump to next instruction
7494    /* 10-12 instructions */
7495
7496
7497
7498/* ------------------------------ */
7499    .balign 64
7500.L_OP_USHR_INT_LIT8: /* 0xe2 */
7501/* File: armv5te/OP_USHR_INT_LIT8.S */
7502/* File: armv5te/binopLit8.S */
7503    /*
7504     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7505     * that specifies an instruction that performs "result = r0 op r1".
7506     * This could be an ARM instruction or a function call.  (If the result
7507     * comes back in a register other than r0, you can override "result".)
7508     *
7509     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7510     * vCC (r1).  Useful for integer division and modulus.
7511     *
7512     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7513     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7514     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7515     */
7516    /* binop/lit8 vAA, vBB, #+CC */
7517    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7518    mov     r9, rINST, lsr #8           @ r9<- AA
7519    and     r2, r3, #255                @ r2<- BB
7520    GET_VREG(r0, r2)                    @ r0<- vBB
7521    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7522    .if 0
7523    @cmp     r1, #0                      @ is second operand zero?
7524    beq     common_errDivideByZero
7525    .endif
7526    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7527
7528    and     r1, r1, #31                           @ optional op; may set condition codes
7529    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
7530    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7531    SET_VREG(r0, r9)               @ vAA<- r0
7532    GOTO_OPCODE(ip)                     @ jump to next instruction
7533    /* 10-12 instructions */
7534
7535
7536
7537/* ------------------------------ */
7538    .balign 64
7539.L_OP_UNUSED_E3: /* 0xe3 */
7540/* File: armv5te/OP_UNUSED_E3.S */
7541/* File: armv5te/unused.S */
7542    bl      common_abort
7543
7544
7545
7546/* ------------------------------ */
7547    .balign 64
7548.L_OP_UNUSED_E4: /* 0xe4 */
7549/* File: armv5te/OP_UNUSED_E4.S */
7550/* File: armv5te/unused.S */
7551    bl      common_abort
7552
7553
7554
7555/* ------------------------------ */
7556    .balign 64
7557.L_OP_UNUSED_E5: /* 0xe5 */
7558/* File: armv5te/OP_UNUSED_E5.S */
7559/* File: armv5te/unused.S */
7560    bl      common_abort
7561
7562
7563
7564/* ------------------------------ */
7565    .balign 64
7566.L_OP_UNUSED_E6: /* 0xe6 */
7567/* File: armv5te/OP_UNUSED_E6.S */
7568/* File: armv5te/unused.S */
7569    bl      common_abort
7570
7571
7572
7573/* ------------------------------ */
7574    .balign 64
7575.L_OP_UNUSED_E7: /* 0xe7 */
7576/* File: armv5te/OP_UNUSED_E7.S */
7577/* File: armv5te/unused.S */
7578    bl      common_abort
7579
7580
7581
7582/* ------------------------------ */
7583    .balign 64
7584.L_OP_UNUSED_E8: /* 0xe8 */
7585/* File: armv5te/OP_UNUSED_E8.S */
7586/* File: armv5te/unused.S */
7587    bl      common_abort
7588
7589
7590
7591/* ------------------------------ */
7592    .balign 64
7593.L_OP_UNUSED_E9: /* 0xe9 */
7594/* File: armv5te/OP_UNUSED_E9.S */
7595/* File: armv5te/unused.S */
7596    bl      common_abort
7597
7598
7599
7600/* ------------------------------ */
7601    .balign 64
7602.L_OP_UNUSED_EA: /* 0xea */
7603/* File: armv5te/OP_UNUSED_EA.S */
7604/* File: armv5te/unused.S */
7605    bl      common_abort
7606
7607
7608
7609/* ------------------------------ */
7610    .balign 64
7611.L_OP_UNUSED_EB: /* 0xeb */
7612/* File: armv5te/OP_UNUSED_EB.S */
7613/* File: armv5te/unused.S */
7614    bl      common_abort
7615
7616
7617
7618/* ------------------------------ */
7619    .balign 64
7620.L_OP_UNUSED_EC: /* 0xec */
7621/* File: armv5te/OP_UNUSED_EC.S */
7622/* File: armv5te/unused.S */
7623    bl      common_abort
7624
7625
7626
7627/* ------------------------------ */
7628    .balign 64
7629.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
7630/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
7631    /*
7632     * Handle a throw-verification-error instruction.  This throws an
7633     * exception for an error discovered during verification.  The
7634     * exception is indicated by AA, with some detail provided by BBBB.
7635     */
7636    /* op AA, ref@BBBB */
7637    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7638    FETCH(r2, 1)                        @ r2<- BBBB
7639    EXPORT_PC()                         @ export the PC
7640    mov     r1, rINST, lsr #8           @ r1<- AA
7641    bl      dvmThrowVerificationError   @ always throws
7642    b       common_exceptionThrown      @ handle exception
7643
7644
7645/* ------------------------------ */
7646    .balign 64
7647.L_OP_EXECUTE_INLINE: /* 0xee */
7648/* File: armv5te/OP_EXECUTE_INLINE.S */
7649    /*
7650     * Execute a "native inline" instruction.
7651     *
7652     * We need to call:
7653     *  dvmPerformInlineOp4Std(arg0, arg1, arg2, arg3, &retval, ref)
7654     *
7655     * The first four args are in r0-r3, but the last two must be pushed
7656     * onto the stack.
7657     */
7658    /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
7659    FETCH(r10, 1)                       @ r10<- BBBB
7660    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7661    EXPORT_PC()                         @ can throw
7662    sub     sp, sp, #8                  @ make room for arg(s)
7663    mov     r0, rINST, lsr #12          @ r0<- B
7664    str     r1, [sp]                    @ push &glue->retval
7665    bl      .LOP_EXECUTE_INLINE_continue        @ make call; will return after
7666    add     sp, sp, #8                  @ pop stack
7667    cmp     r0, #0                      @ test boolean result of inline
7668    beq     common_exceptionThrown      @ returned false, handle exception
7669    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7670    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7671    GOTO_OPCODE(ip)                     @ jump to next instruction
7672
7673/* ------------------------------ */
7674    .balign 64
7675.L_OP_UNUSED_EF: /* 0xef */
7676/* File: armv5te/OP_UNUSED_EF.S */
7677/* File: armv5te/unused.S */
7678    bl      common_abort
7679
7680
7681
7682/* ------------------------------ */
7683    .balign 64
7684.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
7685/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
7686    /*
7687     * invoke-direct-empty is a no-op in a "standard" interpreter.
7688     */
7689    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7690    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7691    GOTO_OPCODE(ip)                     @ execute it
7692
7693/* ------------------------------ */
7694    .balign 64
7695.L_OP_UNUSED_F1: /* 0xf1 */
7696/* File: armv5te/OP_UNUSED_F1.S */
7697/* File: armv5te/unused.S */
7698    bl      common_abort
7699
7700
7701
7702/* ------------------------------ */
7703    .balign 64
7704.L_OP_IGET_QUICK: /* 0xf2 */
7705/* File: armv5te/OP_IGET_QUICK.S */
7706    /* For: iget-quick, iget-object-quick */
7707    /* op vA, vB, offset@CCCC */
7708    mov     r2, rINST, lsr #12          @ r2<- B
7709    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7710    FETCH(r1, 1)                        @ r1<- field byte offset
7711    cmp     r3, #0                      @ check object for null
7712    mov     r2, rINST, lsr #8           @ r2<- A(+)
7713    beq     common_errNullObject        @ object was null
7714    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7715    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7716    and     r2, r2, #15
7717    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7718    SET_VREG(r0, r2)                    @ fp[A]<- r0
7719    GOTO_OPCODE(ip)                     @ jump to next instruction
7720
7721
7722/* ------------------------------ */
7723    .balign 64
7724.L_OP_IGET_WIDE_QUICK: /* 0xf3 */
7725/* File: armv5te/OP_IGET_WIDE_QUICK.S */
7726    /* iget-wide-quick vA, vB, offset@CCCC */
7727    mov     r2, rINST, lsr #12          @ r2<- B
7728    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7729    FETCH(r1, 1)                        @ r1<- field byte offset
7730    cmp     r3, #0                      @ check object for null
7731    mov     r2, rINST, lsr #8           @ r2<- A(+)
7732    beq     common_errNullObject        @ object was null
7733    ldrd    r0, [r3, r1]                @ r0<- obj.field (64 bits, aligned)
7734    and     r2, r2, #15
7735    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7736    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
7737    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7738    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
7739    GOTO_OPCODE(ip)                     @ jump to next instruction
7740
7741
7742/* ------------------------------ */
7743    .balign 64
7744.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
7745/* File: armv5te/OP_IGET_OBJECT_QUICK.S */
7746/* File: armv5te/OP_IGET_QUICK.S */
7747    /* For: iget-quick, iget-object-quick */
7748    /* op vA, vB, offset@CCCC */
7749    mov     r2, rINST, lsr #12          @ r2<- B
7750    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7751    FETCH(r1, 1)                        @ r1<- field byte offset
7752    cmp     r3, #0                      @ check object for null
7753    mov     r2, rINST, lsr #8           @ r2<- A(+)
7754    beq     common_errNullObject        @ object was null
7755    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7756    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7757    and     r2, r2, #15
7758    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7759    SET_VREG(r0, r2)                    @ fp[A]<- r0
7760    GOTO_OPCODE(ip)                     @ jump to next instruction
7761
7762
7763
7764/* ------------------------------ */
7765    .balign 64
7766.L_OP_IPUT_QUICK: /* 0xf5 */
7767/* File: armv5te/OP_IPUT_QUICK.S */
7768    /* For: iput-quick, iput-object-quick */
7769    /* op vA, vB, offset@CCCC */
7770    mov     r2, rINST, lsr #12          @ r2<- B
7771    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7772    FETCH(r1, 1)                        @ r1<- field byte offset
7773    cmp     r3, #0                      @ check object for null
7774    mov     r2, rINST, lsr #8           @ r2<- A(+)
7775    beq     common_errNullObject        @ object was null
7776    and     r2, r2, #15
7777    GET_VREG(r0, r2)                    @ r0<- fp[A]
7778    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7779    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7780    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7781    GOTO_OPCODE(ip)                     @ jump to next instruction
7782
7783
7784/* ------------------------------ */
7785    .balign 64
7786.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
7787/* File: armv5te/OP_IPUT_WIDE_QUICK.S */
7788    /* iput-wide-quick vA, vB, offset@CCCC */
7789    mov     r0, rINST, lsr #8           @ r0<- A(+)
7790    mov     r1, rINST, lsr #12          @ r1<- B
7791    and     r0, r0, #15
7792    GET_VREG(r2, r1)                    @ r2<- fp[B], the object pointer
7793    add     r3, rFP, r0, lsl #2         @ r3<- &fp[A]
7794    cmp     r2, #0                      @ check object for null
7795    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[A]
7796    beq     common_errNullObject        @ object was null
7797    FETCH(r3, 1)                        @ r3<- field byte offset
7798    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7799    strd    r0, [r2, r3]                @ obj.field (64 bits, aligned)<- r0/r1
7800    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7801    GOTO_OPCODE(ip)                     @ jump to next instruction
7802
7803
7804/* ------------------------------ */
7805    .balign 64
7806.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
7807/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
7808/* File: armv5te/OP_IPUT_QUICK.S */
7809    /* For: iput-quick, iput-object-quick */
7810    /* op vA, vB, offset@CCCC */
7811    mov     r2, rINST, lsr #12          @ r2<- B
7812    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7813    FETCH(r1, 1)                        @ r1<- field byte offset
7814    cmp     r3, #0                      @ check object for null
7815    mov     r2, rINST, lsr #8           @ r2<- A(+)
7816    beq     common_errNullObject        @ object was null
7817    and     r2, r2, #15
7818    GET_VREG(r0, r2)                    @ r0<- fp[A]
7819    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7820    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7821    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7822    GOTO_OPCODE(ip)                     @ jump to next instruction
7823
7824
7825
7826/* ------------------------------ */
7827    .balign 64
7828.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
7829/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7830    /*
7831     * Handle an optimized virtual method call.
7832     *
7833     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7834     */
7835    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7836    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7837    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7838    FETCH(r1, 1)                        @ r1<- BBBB
7839    .if     (!0)
7840    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7841    .endif
7842    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7843    cmp     r2, #0                      @ is "this" null?
7844    beq     common_errNullObject        @ null "this", throw exception
7845    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7846    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7847    EXPORT_PC()                         @ invoke must export
7848    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7849    bl      common_invokeMethodNoRange @ continue on
7850
7851/* ------------------------------ */
7852    .balign 64
7853.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
7854/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
7855/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7856    /*
7857     * Handle an optimized virtual method call.
7858     *
7859     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7860     */
7861    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7862    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7863    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7864    FETCH(r1, 1)                        @ r1<- BBBB
7865    .if     (!1)
7866    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7867    .endif
7868    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7869    cmp     r2, #0                      @ is "this" null?
7870    beq     common_errNullObject        @ null "this", throw exception
7871    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7872    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7873    EXPORT_PC()                         @ invoke must export
7874    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7875    bl      common_invokeMethodRange @ continue on
7876
7877
7878/* ------------------------------ */
7879    .balign 64
7880.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
7881/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7882    /*
7883     * Handle an optimized "super" method call.
7884     *
7885     * for: [opt] invoke-super-quick, invoke-super-quick/range
7886     */
7887    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7888    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7889    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7890    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7891    .if     (!0)
7892    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7893    .endif
7894    FETCH(r1, 1)                        @ r1<- BBBB
7895    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7896    EXPORT_PC()                         @ must export for invoke
7897    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7898    GET_VREG(r3, r10)                   @ r3<- "this"
7899    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7900    cmp     r3, #0                      @ null "this" ref?
7901    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7902    beq     common_errNullObject        @ "this" is null, throw exception
7903    bl      common_invokeMethodNoRange @ continue on
7904
7905
7906/* ------------------------------ */
7907    .balign 64
7908.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
7909/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
7910/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7911    /*
7912     * Handle an optimized "super" method call.
7913     *
7914     * for: [opt] invoke-super-quick, invoke-super-quick/range
7915     */
7916    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7917    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7918    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7919    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7920    .if     (!1)
7921    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7922    .endif
7923    FETCH(r1, 1)                        @ r1<- BBBB
7924    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7925    EXPORT_PC()                         @ must export for invoke
7926    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7927    GET_VREG(r3, r10)                   @ r3<- "this"
7928    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7929    cmp     r3, #0                      @ null "this" ref?
7930    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7931    beq     common_errNullObject        @ "this" is null, throw exception
7932    bl      common_invokeMethodRange @ continue on
7933
7934
7935
7936/* ------------------------------ */
7937    .balign 64
7938.L_OP_UNUSED_FC: /* 0xfc */
7939/* File: armv5te/OP_UNUSED_FC.S */
7940/* File: armv5te/unused.S */
7941    bl      common_abort
7942
7943
7944
7945/* ------------------------------ */
7946    .balign 64
7947.L_OP_UNUSED_FD: /* 0xfd */
7948/* File: armv5te/OP_UNUSED_FD.S */
7949/* File: armv5te/unused.S */
7950    bl      common_abort
7951
7952
7953
7954/* ------------------------------ */
7955    .balign 64
7956.L_OP_UNUSED_FE: /* 0xfe */
7957/* File: armv5te/OP_UNUSED_FE.S */
7958/* File: armv5te/unused.S */
7959    bl      common_abort
7960
7961
7962
7963/* ------------------------------ */
7964    .balign 64
7965.L_OP_UNUSED_FF: /* 0xff */
7966/* File: armv5te/OP_UNUSED_FF.S */
7967/* File: armv5te/unused.S */
7968    bl      common_abort
7969
7970
7971
7972
7973    .balign 64
7974    .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
7975    .global dvmAsmInstructionEnd
7976dvmAsmInstructionEnd:
7977
7978/*
7979 * ===========================================================================
7980 *  Sister implementations
7981 * ===========================================================================
7982 */
7983    .global dvmAsmSisterStart
7984    .type   dvmAsmSisterStart, %function
7985    .text
7986    .balign 4
7987dvmAsmSisterStart:
7988
7989/* continuation for OP_CONST_STRING */
7990
7991    /*
7992     * Continuation if the String has not yet been resolved.
7993     *  r1: BBBB (String ref)
7994     *  r9: target register
7995     */
7996.LOP_CONST_STRING_resolve:
7997    EXPORT_PC()
7998    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7999    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
8000    bl      dvmResolveString            @ r0<- String reference
8001    cmp     r0, #0                      @ failed?
8002    beq     common_exceptionThrown      @ yup, handle the exception
8003    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8004    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8005    SET_VREG(r0, r9)                    @ vAA<- r0
8006    GOTO_OPCODE(ip)                     @ jump to next instruction
8007
8008
8009/* continuation for OP_CONST_STRING_JUMBO */
8010
8011    /*
8012     * Continuation if the String has not yet been resolved.
8013     *  r1: BBBBBBBB (String ref)
8014     *  r9: target register
8015     */
8016.LOP_CONST_STRING_JUMBO_resolve:
8017    EXPORT_PC()
8018    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
8019    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
8020    bl      dvmResolveString            @ r0<- String reference
8021    cmp     r0, #0                      @ failed?
8022    beq     common_exceptionThrown      @ yup, handle the exception
8023    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
8024    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8025    SET_VREG(r0, r9)                    @ vAA<- r0
8026    GOTO_OPCODE(ip)                     @ jump to next instruction
8027
8028
8029/* continuation for OP_CONST_CLASS */
8030
8031    /*
8032     * Continuation if the Class has not yet been resolved.
8033     *  r1: BBBB (Class ref)
8034     *  r9: target register
8035     */
8036.LOP_CONST_CLASS_resolve:
8037    EXPORT_PC()
8038    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
8039    mov     r2, #1                      @ r2<- true
8040    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
8041    bl      dvmResolveClass             @ r0<- Class reference
8042    cmp     r0, #0                      @ failed?
8043    beq     common_exceptionThrown      @ yup, handle the exception
8044    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8045    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8046    SET_VREG(r0, r9)                    @ vAA<- r0
8047    GOTO_OPCODE(ip)                     @ jump to next instruction
8048
8049
8050/* continuation for OP_CHECK_CAST */
8051
8052    /*
8053     * Trivial test failed, need to perform full check.  This is common.
8054     *  r0 holds obj->clazz
8055     *  r1 holds class resolved from BBBB
8056     *  r9 holds object
8057     */
8058.LOP_CHECK_CAST_fullcheck:
8059    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
8060    cmp     r0, #0                      @ failed?
8061    bne     .LOP_CHECK_CAST_okay            @ no, success
8062
8063    @ A cast has failed.  We need to throw a ClassCastException with the
8064    @ class of the object that failed to be cast.
8065    EXPORT_PC()                         @ about to throw
8066    ldr     r3, [r9, #offObject_clazz]  @ r3<- obj->clazz
8067    ldr     r0, .LstrClassCastExceptionPtr
8068    ldr     r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor
8069    bl      dvmThrowExceptionWithClassMessage
8070    b       common_exceptionThrown
8071
8072    /*
8073     * Resolution required.  This is the least-likely path.
8074     *
8075     *  r2 holds BBBB
8076     *  r9 holds object
8077     */
8078.LOP_CHECK_CAST_resolve:
8079    EXPORT_PC()                         @ resolve() could throw
8080    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8081    mov     r1, r2                      @ r1<- BBBB
8082    mov     r2, #0                      @ r2<- false
8083    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8084    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
8085    cmp     r0, #0                      @ got null?
8086    beq     common_exceptionThrown      @ yes, handle exception
8087    mov     r1, r0                      @ r1<- class resolved from BBB
8088    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
8089    b       .LOP_CHECK_CAST_resolved        @ pick up where we left off
8090
8091.LstrClassCastExceptionPtr:
8092    .word   .LstrClassCastException
8093
8094
8095/* continuation for OP_INSTANCE_OF */
8096
8097    /*
8098     * Trivial test failed, need to perform full check.  This is common.
8099     *  r0 holds obj->clazz
8100     *  r1 holds class resolved from BBBB
8101     *  r9 holds A
8102     */
8103.LOP_INSTANCE_OF_fullcheck:
8104    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
8105    @ fall through to OP_INSTANCE_OF_store
8106
8107    /*
8108     * r0 holds boolean result
8109     * r9 holds A
8110     */
8111.LOP_INSTANCE_OF_store:
8112    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8113    SET_VREG(r0, r9)                    @ vA<- r0
8114    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8115    GOTO_OPCODE(ip)                     @ jump to next instruction
8116
8117    /*
8118     * Trivial test succeeded, save and bail.
8119     *  r9 holds A
8120     */
8121.LOP_INSTANCE_OF_trivial:
8122    mov     r0, #1                      @ indicate success
8123    @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
8124    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8125    SET_VREG(r0, r9)                    @ vA<- r0
8126    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8127    GOTO_OPCODE(ip)                     @ jump to next instruction
8128
8129    /*
8130     * Resolution required.  This is the least-likely path.
8131     *
8132     *  r3 holds BBBB
8133     *  r9 holds A
8134     */
8135.LOP_INSTANCE_OF_resolve:
8136    EXPORT_PC()                         @ resolve() could throw
8137    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
8138    mov     r1, r3                      @ r1<- BBBB
8139    mov     r2, #1                      @ r2<- true
8140    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
8141    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
8142    cmp     r0, #0                      @ got null?
8143    beq     common_exceptionThrown      @ yes, handle exception
8144    mov     r1, r0                      @ r1<- class resolved from BBB
8145    mov     r3, rINST, lsr #12          @ r3<- B
8146    GET_VREG(r0, r3)                    @ r0<- vB (object)
8147    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
8148    b       .LOP_INSTANCE_OF_resolved        @ pick up where we left off
8149
8150
8151/* continuation for OP_NEW_INSTANCE */
8152
8153    .balign 32                          @ minimize cache lines
8154.LOP_NEW_INSTANCE_finish: @ r0=new object
8155    mov     r3, rINST, lsr #8           @ r3<- AA
8156    cmp     r0, #0                      @ failed?
8157    beq     common_exceptionThrown      @ yes, handle the exception
8158    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8159    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8160    SET_VREG(r0, r3)                    @ vAA<- r0
8161    GOTO_OPCODE(ip)                     @ jump to next instruction
8162
8163    /*
8164     * Class initialization required.
8165     *
8166     *  r0 holds class object
8167     */
8168.LOP_NEW_INSTANCE_needinit:
8169    mov     r9, r0                      @ save r0
8170    bl      dvmInitClass                @ initialize class
8171    cmp     r0, #0                      @ check boolean result
8172    mov     r0, r9                      @ restore r0
8173    bne     .LOP_NEW_INSTANCE_initialized     @ success, continue
8174    b       common_exceptionThrown      @ failed, deal with init exception
8175
8176    /*
8177     * Resolution required.  This is the least-likely path.
8178     *
8179     *  r1 holds BBBB
8180     */
8181.LOP_NEW_INSTANCE_resolve:
8182    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8183    mov     r2, #0                      @ r2<- false
8184    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8185    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
8186    cmp     r0, #0                      @ got null?
8187    bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
8188    b       common_exceptionThrown      @ yes, handle exception
8189
8190.LstrInstantiationErrorPtr:
8191    .word   .LstrInstantiationError
8192
8193
8194/* continuation for OP_NEW_ARRAY */
8195
8196
8197    /*
8198     * Resolve class.  (This is an uncommon case.)
8199     *
8200     *  r1 holds array length
8201     *  r2 holds class ref CCCC
8202     */
8203.LOP_NEW_ARRAY_resolve:
8204    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8205    mov     r9, r1                      @ r9<- length (save)
8206    mov     r1, r2                      @ r1<- CCCC
8207    mov     r2, #0                      @ r2<- false
8208    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8209    bl      dvmResolveClass             @ r0<- call(clazz, ref)
8210    cmp     r0, #0                      @ got null?
8211    mov     r1, r9                      @ r1<- length (restore)
8212    beq     common_exceptionThrown      @ yes, handle exception
8213    @ fall through to OP_NEW_ARRAY_finish
8214
8215    /*
8216     * Finish allocation.
8217     *
8218     *  r0 holds class
8219     *  r1 holds array length
8220     */
8221.LOP_NEW_ARRAY_finish:
8222    mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
8223    bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
8224    cmp     r0, #0                      @ failed?
8225    mov     r2, rINST, lsr #8           @ r2<- A+
8226    beq     common_exceptionThrown      @ yes, handle the exception
8227    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8228    and     r2, r2, #15                 @ r2<- A
8229    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8230    SET_VREG(r0, r2)                    @ vA<- r0
8231    GOTO_OPCODE(ip)                     @ jump to next instruction
8232
8233
8234/* continuation for OP_FILLED_NEW_ARRAY */
8235
8236    /*
8237     * On entry:
8238     *  r0 holds array class
8239     *  r10 holds AA or BA
8240     */
8241.LOP_FILLED_NEW_ARRAY_continue:
8242    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8243    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8244    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
8245    .if     0
8246    mov     r1, r10                     @ r1<- AA (length)
8247    .else
8248    mov     r1, r10, lsr #4             @ r1<- B (length)
8249    .endif
8250    cmp     r3, #'I'                    @ array of ints?
8251    cmpne   r3, #'L'                    @ array of objects?
8252    cmpne   r3, #'['                    @ array of arrays?
8253    mov     r9, r1                      @ save length in r9
8254    bne     .LOP_FILLED_NEW_ARRAY_notimpl         @ no, not handled yet
8255    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8256    cmp     r0, #0                      @ null return?
8257    beq     common_exceptionThrown      @ alloc failed, handle exception
8258
8259    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8260    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
8261    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8262    subs    r9, r9, #1                  @ length--, check for neg
8263    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8264    bmi     2f                          @ was zero, bail
8265
8266    @ copy values from registers into the array
8267    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8268    .if     0
8269    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
82701:  ldr     r3, [r2], #4                @ r3<- *r2++
8271    subs    r9, r9, #1                  @ count--
8272    str     r3, [r0], #4                @ *contents++ = vX
8273    bpl     1b
8274    @ continue at 2
8275    .else
8276    cmp     r9, #4                      @ length was initially 5?
8277    and     r2, r10, #15                @ r2<- A
8278    bne     1f                          @ <= 4 args, branch
8279    GET_VREG(r3, r2)                    @ r3<- vA
8280    sub     r9, r9, #1                  @ count--
8281    str     r3, [r0, #16]               @ contents[4] = vA
82821:  and     r2, r1, #15                 @ r2<- F/E/D/C
8283    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8284    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8285    subs    r9, r9, #1                  @ count--
8286    str     r3, [r0], #4                @ *contents++ = vX
8287    bpl     1b
8288    @ continue at 2
8289    .endif
8290
82912:
8292    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
8293    GOTO_OPCODE(ip)                     @ execute it
8294
8295    /*
8296     * Throw an exception indicating that we have not implemented this
8297     * mode of filled-new-array.
8298     */
8299.LOP_FILLED_NEW_ARRAY_notimpl:
8300    ldr     r0, .L_strInternalError
8301    ldr     r1, .L_strFilledNewArrayNotImpl
8302    bl      dvmThrowException
8303    b       common_exceptionThrown
8304
8305    .if     (!0)                 @ define in one or the other, not both
8306.L_strFilledNewArrayNotImpl:
8307    .word   .LstrFilledNewArrayNotImpl
8308.L_strInternalError:
8309    .word   .LstrInternalError
8310    .endif
8311
8312
8313/* continuation for OP_FILLED_NEW_ARRAY_RANGE */
8314
8315    /*
8316     * On entry:
8317     *  r0 holds array class
8318     *  r10 holds AA or BA
8319     */
8320.LOP_FILLED_NEW_ARRAY_RANGE_continue:
8321    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8322    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8323    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
8324    .if     1
8325    mov     r1, r10                     @ r1<- AA (length)
8326    .else
8327    mov     r1, r10, lsr #4             @ r1<- B (length)
8328    .endif
8329    cmp     r3, #'I'                    @ array of ints?
8330    cmpne   r3, #'L'                    @ array of objects?
8331    cmpne   r3, #'['                    @ array of arrays?
8332    mov     r9, r1                      @ save length in r9
8333    bne     .LOP_FILLED_NEW_ARRAY_RANGE_notimpl         @ no, not handled yet
8334    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8335    cmp     r0, #0                      @ null return?
8336    beq     common_exceptionThrown      @ alloc failed, handle exception
8337
8338    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8339    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
8340    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8341    subs    r9, r9, #1                  @ length--, check for neg
8342    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8343    bmi     2f                          @ was zero, bail
8344
8345    @ copy values from registers into the array
8346    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8347    .if     1
8348    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
83491:  ldr     r3, [r2], #4                @ r3<- *r2++
8350    subs    r9, r9, #1                  @ count--
8351    str     r3, [r0], #4                @ *contents++ = vX
8352    bpl     1b
8353    @ continue at 2
8354    .else
8355    cmp     r9, #4                      @ length was initially 5?
8356    and     r2, r10, #15                @ r2<- A
8357    bne     1f                          @ <= 4 args, branch
8358    GET_VREG(r3, r2)                    @ r3<- vA
8359    sub     r9, r9, #1                  @ count--
8360    str     r3, [r0, #16]               @ contents[4] = vA
83611:  and     r2, r1, #15                 @ r2<- F/E/D/C
8362    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8363    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8364    subs    r9, r9, #1                  @ count--
8365    str     r3, [r0], #4                @ *contents++ = vX
8366    bpl     1b
8367    @ continue at 2
8368    .endif
8369
83702:
8371    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
8372    GOTO_OPCODE(ip)                     @ execute it
8373
8374    /*
8375     * Throw an exception indicating that we have not implemented this
8376     * mode of filled-new-array.
8377     */
8378.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
8379    ldr     r0, .L_strInternalError
8380    ldr     r1, .L_strFilledNewArrayNotImpl
8381    bl      dvmThrowException
8382    b       common_exceptionThrown
8383
8384    .if     (!1)                 @ define in one or the other, not both
8385.L_strFilledNewArrayNotImpl:
8386    .word   .LstrFilledNewArrayNotImpl
8387.L_strInternalError:
8388    .word   .LstrInternalError
8389    .endif
8390
8391
8392/* continuation for OP_CMPL_FLOAT */
8393
8394    @ Test for NaN with a second comparison.  EABI forbids testing bit
8395    @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8396    @ make the library call.
8397.LOP_CMPL_FLOAT_gt_or_nan:
8398    mov     r1, r9                      @ reverse order
8399    mov     r0, r10
8400    bl      __aeabi_cfcmple             @ r0<- Z set if eq, C clear if <
8401    @bleq    common_abort
8402    movcc   r1, #1                      @ (greater than) r1<- 1
8403    bcc     .LOP_CMPL_FLOAT_finish
8404    mvn     r1, #0                            @ r1<- 1 or -1 for NaN
8405    b       .LOP_CMPL_FLOAT_finish
8406
8407
8408#if 0       /* "clasic" form */
8409    FETCH(r0, 1)                        @ r0<- CCBB
8410    and     r2, r0, #255                @ r2<- BB
8411    mov     r3, r0, lsr #8              @ r3<- CC
8412    GET_VREG(r9, r2)                    @ r9<- vBB
8413    GET_VREG(r10, r3)                   @ r10<- vCC
8414    mov     r0, r9                      @ r0<- vBB
8415    mov     r1, r10                     @ r1<- vCC
8416    bl      __aeabi_fcmpeq              @ r0<- (vBB == vCC)
8417    cmp     r0, #0                      @ equal?
8418    movne   r1, #0                      @ yes, result is 0
8419    bne     OP_CMPL_FLOAT_finish
8420    mov     r0, r9                      @ r0<- vBB
8421    mov     r1, r10                     @ r1<- vCC
8422    bl      __aeabi_fcmplt              @ r0<- (vBB < vCC)
8423    cmp     r0, #0                      @ less than?
8424    b       OP_CMPL_FLOAT_continue
8425@%break
8426
8427OP_CMPL_FLOAT_continue:
8428    mvnne   r1, #0                      @ yes, result is -1
8429    bne     OP_CMPL_FLOAT_finish
8430    mov     r0, r9                      @ r0<- vBB
8431    mov     r1, r10                     @ r1<- vCC
8432    bl      __aeabi_fcmpgt              @ r0<- (vBB > vCC)
8433    cmp     r0, #0                      @ greater than?
8434    beq     OP_CMPL_FLOAT_nan               @ no, must be NaN
8435    mov     r1, #1                      @ yes, result is 1
8436    @ fall through to _finish
8437
8438OP_CMPL_FLOAT_finish:
8439    mov     r3, rINST, lsr #8           @ r3<- AA
8440    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8441    SET_VREG(r1, r3)                    @ vAA<- r1
8442    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8443    GOTO_OPCODE(ip)                     @ jump to next instruction
8444
8445    /*
8446     * This is expected to be uncommon, so we double-branch (once to here,
8447     * again back to _finish).
8448     */
8449OP_CMPL_FLOAT_nan:
8450    mvn     r1, #0                            @ r1<- 1 or -1 for NaN
8451    b       OP_CMPL_FLOAT_finish
8452
8453#endif
8454
8455
8456/* continuation for OP_CMPG_FLOAT */
8457
8458    @ Test for NaN with a second comparison.  EABI forbids testing bit
8459    @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8460    @ make the library call.
8461.LOP_CMPG_FLOAT_gt_or_nan:
8462    mov     r1, r9                      @ reverse order
8463    mov     r0, r10
8464    bl      __aeabi_cfcmple             @ r0<- Z set if eq, C clear if <
8465    @bleq    common_abort
8466    movcc   r1, #1                      @ (greater than) r1<- 1
8467    bcc     .LOP_CMPG_FLOAT_finish
8468    mov     r1, #1                            @ r1<- 1 or -1 for NaN
8469    b       .LOP_CMPG_FLOAT_finish
8470
8471
8472#if 0       /* "clasic" form */
8473    FETCH(r0, 1)                        @ r0<- CCBB
8474    and     r2, r0, #255                @ r2<- BB
8475    mov     r3, r0, lsr #8              @ r3<- CC
8476    GET_VREG(r9, r2)                    @ r9<- vBB
8477    GET_VREG(r10, r3)                   @ r10<- vCC
8478    mov     r0, r9                      @ r0<- vBB
8479    mov     r1, r10                     @ r1<- vCC
8480    bl      __aeabi_fcmpeq              @ r0<- (vBB == vCC)
8481    cmp     r0, #0                      @ equal?
8482    movne   r1, #0                      @ yes, result is 0
8483    bne     OP_CMPG_FLOAT_finish
8484    mov     r0, r9                      @ r0<- vBB
8485    mov     r1, r10                     @ r1<- vCC
8486    bl      __aeabi_fcmplt              @ r0<- (vBB < vCC)
8487    cmp     r0, #0                      @ less than?
8488    b       OP_CMPG_FLOAT_continue
8489@%break
8490
8491OP_CMPG_FLOAT_continue:
8492    mvnne   r1, #0                      @ yes, result is -1
8493    bne     OP_CMPG_FLOAT_finish
8494    mov     r0, r9                      @ r0<- vBB
8495    mov     r1, r10                     @ r1<- vCC
8496    bl      __aeabi_fcmpgt              @ r0<- (vBB > vCC)
8497    cmp     r0, #0                      @ greater than?
8498    beq     OP_CMPG_FLOAT_nan               @ no, must be NaN
8499    mov     r1, #1                      @ yes, result is 1
8500    @ fall through to _finish
8501
8502OP_CMPG_FLOAT_finish:
8503    mov     r3, rINST, lsr #8           @ r3<- AA
8504    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8505    SET_VREG(r1, r3)                    @ vAA<- r1
8506    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8507    GOTO_OPCODE(ip)                     @ jump to next instruction
8508
8509    /*
8510     * This is expected to be uncommon, so we double-branch (once to here,
8511     * again back to _finish).
8512     */
8513OP_CMPG_FLOAT_nan:
8514    mov     r1, #1                            @ r1<- 1 or -1 for NaN
8515    b       OP_CMPG_FLOAT_finish
8516
8517#endif
8518
8519
8520/* continuation for OP_CMPL_DOUBLE */
8521
8522    @ Test for NaN with a second comparison.  EABI forbids testing bit
8523    @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8524    @ make the library call.
8525.LOP_CMPL_DOUBLE_gt_or_nan:
8526    ldmia   r10, {r0-r1}                @ reverse order
8527    ldmia   r9, {r2-r3}
8528    bl      __aeabi_cdcmple             @ r0<- Z set if eq, C clear if <
8529    @bleq    common_abort
8530    movcc   r1, #1                      @ (greater than) r1<- 1
8531    bcc     .LOP_CMPL_DOUBLE_finish
8532    mvn     r1, #0                            @ r1<- 1 or -1 for NaN
8533    b       .LOP_CMPL_DOUBLE_finish
8534
8535
8536/* continuation for OP_CMPG_DOUBLE */
8537
8538    @ Test for NaN with a second comparison.  EABI forbids testing bit
8539    @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8540    @ make the library call.
8541.LOP_CMPG_DOUBLE_gt_or_nan:
8542    ldmia   r10, {r0-r1}                @ reverse order
8543    ldmia   r9, {r2-r3}
8544    bl      __aeabi_cdcmple             @ r0<- Z set if eq, C clear if <
8545    @bleq    common_abort
8546    movcc   r1, #1                      @ (greater than) r1<- 1
8547    bcc     .LOP_CMPG_DOUBLE_finish
8548    mov     r1, #1                            @ r1<- 1 or -1 for NaN
8549    b       .LOP_CMPG_DOUBLE_finish
8550
8551
8552/* continuation for OP_CMP_LONG */
8553
8554.LOP_CMP_LONG_less:
8555    mvn     r1, #0                      @ r1<- -1
8556    @ Want to cond code the next mov so we can avoid branch, but don't see it;
8557    @ instead, we just replicate the tail end.
8558    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8559    SET_VREG(r1, r9)                    @ vAA<- r1
8560    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8561    GOTO_OPCODE(ip)                     @ jump to next instruction
8562
8563.LOP_CMP_LONG_greater:
8564    mov     r1, #1                      @ r1<- 1
8565    @ fall through to _finish
8566
8567.LOP_CMP_LONG_finish:
8568    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8569    SET_VREG(r1, r9)                    @ vAA<- r1
8570    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8571    GOTO_OPCODE(ip)                     @ jump to next instruction
8572
8573
8574/* continuation for OP_AGET_WIDE */
8575
8576.LOP_AGET_WIDE_finish:
8577    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8578    ldrd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8579    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
8580    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8581    stmia   r9, {r2-r3}                 @ vAA/vAA+1<- r2/r3
8582    GOTO_OPCODE(ip)                     @ jump to next instruction
8583
8584
8585/* continuation for OP_APUT_WIDE */
8586
8587.LOP_APUT_WIDE_finish:
8588    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8589    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
8590    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8591    strd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8592    GOTO_OPCODE(ip)                     @ jump to next instruction
8593
8594
8595/* continuation for OP_APUT_OBJECT */
8596    /*
8597     * On entry:
8598     *  r1 = vBB (arrayObj)
8599     *  r9 = vAA (obj)
8600     *  r10 = offset into array (vBB + vCC * width)
8601     */
8602.LOP_APUT_OBJECT_finish:
8603    cmp     r9, #0                      @ storing null reference?
8604    beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
8605    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
8606    ldr     r1, [r1, #offObject_clazz]  @ r1<- arrayObj->clazz
8607    bl      dvmCanPutArrayElement       @ test object type vs. array type
8608    cmp     r0, #0                      @ okay?
8609    beq     common_errArrayStore        @ no
8610.LOP_APUT_OBJECT_skip_check:
8611    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8612    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8613    str     r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
8614    GOTO_OPCODE(ip)                     @ jump to next instruction
8615
8616
8617/* continuation for OP_IGET */
8618
8619    /*
8620     * Currently:
8621     *  r0 holds resolved field
8622     *  r9 holds object
8623     */
8624.LOP_IGET_finish:
8625    @bl      common_squeak0
8626    cmp     r9, #0                      @ check object for null
8627    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8628    beq     common_errNullObject        @ object was null
8629    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8630    mov     r2, rINST, lsr #8           @ r2<- A+
8631    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8632    and     r2, r2, #15                 @ r2<- A
8633    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8634    SET_VREG(r0, r2)                    @ fp[A]<- r0
8635    GOTO_OPCODE(ip)                     @ jump to next instruction
8636
8637
8638/* continuation for OP_IGET_WIDE */
8639
8640    /*
8641     * Currently:
8642     *  r0 holds resolved field
8643     *  r9 holds object
8644     */
8645.LOP_IGET_WIDE_finish:
8646    cmp     r9, #0                      @ check object for null
8647    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8648    beq     common_errNullObject        @ object was null
8649    mov     r2, rINST, lsr #8           @ r2<- A+
8650    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
8651    and     r2, r2, #15                 @ r2<- A
8652    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8653    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
8654    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8655    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
8656    GOTO_OPCODE(ip)                     @ jump to next instruction
8657
8658
8659/* continuation for OP_IGET_OBJECT */
8660
8661    /*
8662     * Currently:
8663     *  r0 holds resolved field
8664     *  r9 holds object
8665     */
8666.LOP_IGET_OBJECT_finish:
8667    @bl      common_squeak0
8668    cmp     r9, #0                      @ check object for null
8669    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8670    beq     common_errNullObject        @ object was null
8671    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8672    mov     r2, rINST, lsr #8           @ r2<- A+
8673    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8674    and     r2, r2, #15                 @ r2<- A
8675    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8676    SET_VREG(r0, r2)                    @ fp[A]<- r0
8677    GOTO_OPCODE(ip)                     @ jump to next instruction
8678
8679
8680/* continuation for OP_IGET_BOOLEAN */
8681
8682    /*
8683     * Currently:
8684     *  r0 holds resolved field
8685     *  r9 holds object
8686     */
8687.LOP_IGET_BOOLEAN_finish:
8688    @bl      common_squeak1
8689    cmp     r9, #0                      @ check object for null
8690    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8691    beq     common_errNullObject        @ object was null
8692    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8693    mov     r2, rINST, lsr #8           @ r2<- A+
8694    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8695    and     r2, r2, #15                 @ r2<- A
8696    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8697    SET_VREG(r0, r2)                    @ fp[A]<- r0
8698    GOTO_OPCODE(ip)                     @ jump to next instruction
8699
8700
8701/* continuation for OP_IGET_BYTE */
8702
8703    /*
8704     * Currently:
8705     *  r0 holds resolved field
8706     *  r9 holds object
8707     */
8708.LOP_IGET_BYTE_finish:
8709    @bl      common_squeak2
8710    cmp     r9, #0                      @ check object for null
8711    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8712    beq     common_errNullObject        @ object was null
8713    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8714    mov     r2, rINST, lsr #8           @ r2<- A+
8715    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8716    and     r2, r2, #15                 @ r2<- A
8717    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8718    SET_VREG(r0, r2)                    @ fp[A]<- r0
8719    GOTO_OPCODE(ip)                     @ jump to next instruction
8720
8721
8722/* continuation for OP_IGET_CHAR */
8723
8724    /*
8725     * Currently:
8726     *  r0 holds resolved field
8727     *  r9 holds object
8728     */
8729.LOP_IGET_CHAR_finish:
8730    @bl      common_squeak3
8731    cmp     r9, #0                      @ check object for null
8732    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8733    beq     common_errNullObject        @ object was null
8734    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8735    mov     r2, rINST, lsr #8           @ r2<- A+
8736    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8737    and     r2, r2, #15                 @ r2<- A
8738    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8739    SET_VREG(r0, r2)                    @ fp[A]<- r0
8740    GOTO_OPCODE(ip)                     @ jump to next instruction
8741
8742
8743/* continuation for OP_IGET_SHORT */
8744
8745    /*
8746     * Currently:
8747     *  r0 holds resolved field
8748     *  r9 holds object
8749     */
8750.LOP_IGET_SHORT_finish:
8751    @bl      common_squeak4
8752    cmp     r9, #0                      @ check object for null
8753    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8754    beq     common_errNullObject        @ object was null
8755    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8756    mov     r2, rINST, lsr #8           @ r2<- A+
8757    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8758    and     r2, r2, #15                 @ r2<- A
8759    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8760    SET_VREG(r0, r2)                    @ fp[A]<- r0
8761    GOTO_OPCODE(ip)                     @ jump to next instruction
8762
8763
8764/* continuation for OP_IPUT */
8765
8766    /*
8767     * Currently:
8768     *  r0 holds resolved field
8769     *  r9 holds object
8770     */
8771.LOP_IPUT_finish:
8772    @bl      common_squeak0
8773    mov     r1, rINST, lsr #8           @ r1<- A+
8774    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8775    and     r1, r1, #15                 @ r1<- A
8776    cmp     r9, #0                      @ check object for null
8777    GET_VREG(r0, r1)                    @ r0<- fp[A]
8778    beq     common_errNullObject        @ object was null
8779    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8780    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8781    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8782    GOTO_OPCODE(ip)                     @ jump to next instruction
8783
8784
8785/* continuation for OP_IPUT_WIDE */
8786
8787    /*
8788     * Currently:
8789     *  r0 holds resolved field
8790     *  r9 holds object
8791     */
8792.LOP_IPUT_WIDE_finish:
8793    mov     r2, rINST, lsr #8           @ r2<- A+
8794    cmp     r9, #0                      @ check object for null
8795    and     r2, r2, #15                 @ r2<- A
8796    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8797    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
8798    beq     common_errNullObject        @ object was null
8799    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8800    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
8801    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8802    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0
8803    GOTO_OPCODE(ip)                     @ jump to next instruction
8804
8805
8806/* continuation for OP_IPUT_OBJECT */
8807
8808    /*
8809     * Currently:
8810     *  r0 holds resolved field
8811     *  r9 holds object
8812     */
8813.LOP_IPUT_OBJECT_finish:
8814    @bl      common_squeak0
8815    mov     r1, rINST, lsr #8           @ r1<- A+
8816    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8817    and     r1, r1, #15                 @ r1<- A
8818    cmp     r9, #0                      @ check object for null
8819    GET_VREG(r0, r1)                    @ r0<- fp[A]
8820    beq     common_errNullObject        @ object was null
8821    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8822    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8823    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8824    GOTO_OPCODE(ip)                     @ jump to next instruction
8825
8826
8827/* continuation for OP_IPUT_BOOLEAN */
8828
8829    /*
8830     * Currently:
8831     *  r0 holds resolved field
8832     *  r9 holds object
8833     */
8834.LOP_IPUT_BOOLEAN_finish:
8835    @bl      common_squeak1
8836    mov     r1, rINST, lsr #8           @ r1<- A+
8837    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8838    and     r1, r1, #15                 @ r1<- A
8839    cmp     r9, #0                      @ check object for null
8840    GET_VREG(r0, r1)                    @ r0<- fp[A]
8841    beq     common_errNullObject        @ object was null
8842    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8843    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8844    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8845    GOTO_OPCODE(ip)                     @ jump to next instruction
8846
8847
8848/* continuation for OP_IPUT_BYTE */
8849
8850    /*
8851     * Currently:
8852     *  r0 holds resolved field
8853     *  r9 holds object
8854     */
8855.LOP_IPUT_BYTE_finish:
8856    @bl      common_squeak2
8857    mov     r1, rINST, lsr #8           @ r1<- A+
8858    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8859    and     r1, r1, #15                 @ r1<- A
8860    cmp     r9, #0                      @ check object for null
8861    GET_VREG(r0, r1)                    @ r0<- fp[A]
8862    beq     common_errNullObject        @ object was null
8863    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8864    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8865    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8866    GOTO_OPCODE(ip)                     @ jump to next instruction
8867
8868
8869/* continuation for OP_IPUT_CHAR */
8870
8871    /*
8872     * Currently:
8873     *  r0 holds resolved field
8874     *  r9 holds object
8875     */
8876.LOP_IPUT_CHAR_finish:
8877    @bl      common_squeak3
8878    mov     r1, rINST, lsr #8           @ r1<- A+
8879    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8880    and     r1, r1, #15                 @ r1<- A
8881    cmp     r9, #0                      @ check object for null
8882    GET_VREG(r0, r1)                    @ r0<- fp[A]
8883    beq     common_errNullObject        @ object was null
8884    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8885    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8886    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8887    GOTO_OPCODE(ip)                     @ jump to next instruction
8888
8889
8890/* continuation for OP_IPUT_SHORT */
8891
8892    /*
8893     * Currently:
8894     *  r0 holds resolved field
8895     *  r9 holds object
8896     */
8897.LOP_IPUT_SHORT_finish:
8898    @bl      common_squeak4
8899    mov     r1, rINST, lsr #8           @ r1<- A+
8900    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8901    and     r1, r1, #15                 @ r1<- A
8902    cmp     r9, #0                      @ check object for null
8903    GET_VREG(r0, r1)                    @ r0<- fp[A]
8904    beq     common_errNullObject        @ object was null
8905    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8906    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8907    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8908    GOTO_OPCODE(ip)                     @ jump to next instruction
8909
8910
8911/* continuation for OP_SGET */
8912
8913    /*
8914     * Continuation if the field has not yet been resolved.
8915     *  r1: BBBB field ref
8916     */
8917.LOP_SGET_resolve:
8918    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8919    EXPORT_PC()                         @ resolve() could throw, so export now
8920    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8921    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8922    cmp     r0, #0                      @ success?
8923    bne     .LOP_SGET_finish          @ yes, finish
8924    b       common_exceptionThrown      @ no, handle exception
8925
8926
8927/* continuation for OP_SGET_WIDE */
8928
8929    /*
8930     * Continuation if the field has not yet been resolved.
8931     *  r1: BBBB field ref
8932     */
8933.LOP_SGET_WIDE_resolve:
8934    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8935    EXPORT_PC()                         @ resolve() could throw, so export now
8936    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8937    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8938    cmp     r0, #0                      @ success?
8939    bne     .LOP_SGET_WIDE_finish          @ yes, finish
8940    b       common_exceptionThrown      @ no, handle exception
8941
8942
8943/* continuation for OP_SGET_OBJECT */
8944
8945    /*
8946     * Continuation if the field has not yet been resolved.
8947     *  r1: BBBB field ref
8948     */
8949.LOP_SGET_OBJECT_resolve:
8950    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8951    EXPORT_PC()                         @ resolve() could throw, so export now
8952    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8953    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8954    cmp     r0, #0                      @ success?
8955    bne     .LOP_SGET_OBJECT_finish          @ yes, finish
8956    b       common_exceptionThrown      @ no, handle exception
8957
8958
8959/* continuation for OP_SGET_BOOLEAN */
8960
8961    /*
8962     * Continuation if the field has not yet been resolved.
8963     *  r1: BBBB field ref
8964     */
8965.LOP_SGET_BOOLEAN_resolve:
8966    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8967    EXPORT_PC()                         @ resolve() could throw, so export now
8968    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8969    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8970    cmp     r0, #0                      @ success?
8971    bne     .LOP_SGET_BOOLEAN_finish          @ yes, finish
8972    b       common_exceptionThrown      @ no, handle exception
8973
8974
8975/* continuation for OP_SGET_BYTE */
8976
8977    /*
8978     * Continuation if the field has not yet been resolved.
8979     *  r1: BBBB field ref
8980     */
8981.LOP_SGET_BYTE_resolve:
8982    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8983    EXPORT_PC()                         @ resolve() could throw, so export now
8984    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8985    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8986    cmp     r0, #0                      @ success?
8987    bne     .LOP_SGET_BYTE_finish          @ yes, finish
8988    b       common_exceptionThrown      @ no, handle exception
8989
8990
8991/* continuation for OP_SGET_CHAR */
8992
8993    /*
8994     * Continuation if the field has not yet been resolved.
8995     *  r1: BBBB field ref
8996     */
8997.LOP_SGET_CHAR_resolve:
8998    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8999    EXPORT_PC()                         @ resolve() could throw, so export now
9000    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9001    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9002    cmp     r0, #0                      @ success?
9003    bne     .LOP_SGET_CHAR_finish          @ yes, finish
9004    b       common_exceptionThrown      @ no, handle exception
9005
9006
9007/* continuation for OP_SGET_SHORT */
9008
9009    /*
9010     * Continuation if the field has not yet been resolved.
9011     *  r1: BBBB field ref
9012     */
9013.LOP_SGET_SHORT_resolve:
9014    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9015    EXPORT_PC()                         @ resolve() could throw, so export now
9016    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9017    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9018    cmp     r0, #0                      @ success?
9019    bne     .LOP_SGET_SHORT_finish          @ yes, finish
9020    b       common_exceptionThrown      @ no, handle exception
9021
9022
9023/* continuation for OP_SPUT */
9024
9025    /*
9026     * Continuation if the field has not yet been resolved.
9027     *  r1: BBBB field ref
9028     */
9029.LOP_SPUT_resolve:
9030    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9031    EXPORT_PC()                         @ resolve() could throw, so export now
9032    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9033    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9034    cmp     r0, #0                      @ success?
9035    bne     .LOP_SPUT_finish          @ yes, finish
9036    b       common_exceptionThrown      @ no, handle exception
9037
9038
9039/* continuation for OP_SPUT_WIDE */
9040
9041    /*
9042     * Continuation if the field has not yet been resolved.
9043     *  r1: BBBB field ref
9044     *  r9: &fp[AA]
9045     */
9046.LOP_SPUT_WIDE_resolve:
9047    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9048    EXPORT_PC()                         @ resolve() could throw, so export now
9049    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9050    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9051    cmp     r0, #0                      @ success?
9052    bne     .LOP_SPUT_WIDE_finish          @ yes, finish
9053    b       common_exceptionThrown      @ no, handle exception
9054
9055
9056/* continuation for OP_SPUT_OBJECT */
9057
9058    /*
9059     * Continuation if the field has not yet been resolved.
9060     *  r1: BBBB field ref
9061     */
9062.LOP_SPUT_OBJECT_resolve:
9063    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9064    EXPORT_PC()                         @ resolve() could throw, so export now
9065    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9066    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9067    cmp     r0, #0                      @ success?
9068    bne     .LOP_SPUT_OBJECT_finish          @ yes, finish
9069    b       common_exceptionThrown      @ no, handle exception
9070
9071
9072/* continuation for OP_SPUT_BOOLEAN */
9073
9074    /*
9075     * Continuation if the field has not yet been resolved.
9076     *  r1: BBBB field ref
9077     */
9078.LOP_SPUT_BOOLEAN_resolve:
9079    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9080    EXPORT_PC()                         @ resolve() could throw, so export now
9081    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9082    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9083    cmp     r0, #0                      @ success?
9084    bne     .LOP_SPUT_BOOLEAN_finish          @ yes, finish
9085    b       common_exceptionThrown      @ no, handle exception
9086
9087
9088/* continuation for OP_SPUT_BYTE */
9089
9090    /*
9091     * Continuation if the field has not yet been resolved.
9092     *  r1: BBBB field ref
9093     */
9094.LOP_SPUT_BYTE_resolve:
9095    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9096    EXPORT_PC()                         @ resolve() could throw, so export now
9097    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9098    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9099    cmp     r0, #0                      @ success?
9100    bne     .LOP_SPUT_BYTE_finish          @ yes, finish
9101    b       common_exceptionThrown      @ no, handle exception
9102
9103
9104/* continuation for OP_SPUT_CHAR */
9105
9106    /*
9107     * Continuation if the field has not yet been resolved.
9108     *  r1: BBBB field ref
9109     */
9110.LOP_SPUT_CHAR_resolve:
9111    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9112    EXPORT_PC()                         @ resolve() could throw, so export now
9113    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9114    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9115    cmp     r0, #0                      @ success?
9116    bne     .LOP_SPUT_CHAR_finish          @ yes, finish
9117    b       common_exceptionThrown      @ no, handle exception
9118
9119
9120/* continuation for OP_SPUT_SHORT */
9121
9122    /*
9123     * Continuation if the field has not yet been resolved.
9124     *  r1: BBBB field ref
9125     */
9126.LOP_SPUT_SHORT_resolve:
9127    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9128    EXPORT_PC()                         @ resolve() could throw, so export now
9129    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9130    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9131    cmp     r0, #0                      @ success?
9132    bne     .LOP_SPUT_SHORT_finish          @ yes, finish
9133    b       common_exceptionThrown      @ no, handle exception
9134
9135
9136/* continuation for OP_INVOKE_VIRTUAL */
9137
9138    /*
9139     * At this point:
9140     *  r0 = resolved base method
9141     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
9142     */
9143.LOP_INVOKE_VIRTUAL_continue:
9144    GET_VREG(r1, r10)                   @ r1<- "this" ptr
9145    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
9146    cmp     r1, #0                      @ is "this" null?
9147    beq     common_errNullObject        @ null "this", throw exception
9148    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
9149    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
9150    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
9151    bl      common_invokeMethodNoRange @ continue on
9152
9153
9154/* continuation for OP_INVOKE_SUPER */
9155
9156    /*
9157     * At this point:
9158     *  r0 = resolved base method
9159     *  r9 = method->clazz
9160     */
9161.LOP_INVOKE_SUPER_continue:
9162    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
9163    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
9164    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
9165    EXPORT_PC()                         @ must export for invoke
9166    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
9167    bcs     .LOP_INVOKE_SUPER_nsm             @ method not present in superclass
9168    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
9169    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
9170    bl      common_invokeMethodNoRange @ continue on
9171
9172.LOP_INVOKE_SUPER_resolve:
9173    mov     r0, r9                      @ r0<- method->clazz
9174    mov     r2, #METHOD_VIRTUAL         @ resolver method type
9175    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
9176    cmp     r0, #0                      @ got null?
9177    bne     .LOP_INVOKE_SUPER_continue        @ no, continue
9178    b       common_exceptionThrown      @ yes, handle exception
9179
9180    /*
9181     * Throw a NoSuchMethodError with the method name as the message.
9182     *  r0 = resolved base method
9183     */
9184.LOP_INVOKE_SUPER_nsm:
9185    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
9186    b       common_errNoSuchMethod
9187
9188
9189/* continuation for OP_INVOKE_DIRECT */
9190
9191    /*
9192     * On entry:
9193     *  r1 = reference (BBBB or CCCC)
9194     *  r10 = "this" register
9195     */
9196.LOP_INVOKE_DIRECT_resolve:
9197    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
9198    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
9199    mov     r2, #METHOD_DIRECT          @ resolver method type
9200    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
9201    cmp     r0, #0                      @ got null?
9202    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
9203    bne     .LOP_INVOKE_DIRECT_finish          @ no, continue
9204    b       common_exceptionThrown      @ yes, handle exception
9205
9206
9207/* continuation for OP_INVOKE_VIRTUAL_RANGE */
9208
9209    /*
9210     * At this point:
9211     *  r0 = resolved base method
9212     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
9213     */
9214.LOP_INVOKE_VIRTUAL_RANGE_continue:
9215    GET_VREG(r1, r10)                   @ r1<- "this" ptr
9216    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
9217    cmp     r1, #0                      @ is "this" null?
9218    beq     common_errNullObject        @ null "this", throw exception
9219    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
9220    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
9221    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
9222    bl      common_invokeMethodRange @ continue on
9223
9224
9225/* continuation for OP_INVOKE_SUPER_RANGE */
9226
9227    /*
9228     * At this point:
9229     *  r0 = resolved base method
9230     *  r9 = method->clazz
9231     */
9232.LOP_INVOKE_SUPER_RANGE_continue:
9233    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
9234    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
9235    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
9236    EXPORT_PC()                         @ must export for invoke
9237    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
9238    bcs     .LOP_INVOKE_SUPER_RANGE_nsm             @ method not present in superclass
9239    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
9240    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
9241    bl      common_invokeMethodRange @ continue on
9242
9243.LOP_INVOKE_SUPER_RANGE_resolve:
9244    mov     r0, r9                      @ r0<- method->clazz
9245    mov     r2, #METHOD_VIRTUAL         @ resolver method type
9246    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
9247    cmp     r0, #0                      @ got null?
9248    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ no, continue
9249    b       common_exceptionThrown      @ yes, handle exception
9250
9251    /*
9252     * Throw a NoSuchMethodError with the method name as the message.
9253     *  r0 = resolved base method
9254     */
9255.LOP_INVOKE_SUPER_RANGE_nsm:
9256    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
9257    b       common_errNoSuchMethod
9258
9259
9260/* continuation for OP_INVOKE_DIRECT_RANGE */
9261
9262    /*
9263     * On entry:
9264     *  r1 = reference (BBBB or CCCC)
9265     *  r10 = "this" register
9266     */
9267.LOP_INVOKE_DIRECT_RANGE_resolve:
9268    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
9269    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
9270    mov     r2, #METHOD_DIRECT          @ resolver method type
9271    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
9272    cmp     r0, #0                      @ got null?
9273    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
9274    bne     .LOP_INVOKE_DIRECT_RANGE_finish          @ no, continue
9275    b       common_exceptionThrown      @ yes, handle exception
9276
9277
9278/* continuation for OP_FLOAT_TO_LONG */
9279/*
9280 * Convert the float in r0 to a long in r0/r1.
9281 *
9282 * We have to clip values to long min/max per the specification.  The
9283 * expected common case is a "reasonable" value that converts directly
9284 * to modest integer.  The EABI convert function isn't doing this for us.
9285 */
9286f2l_doconv:
9287    stmfd   sp!, {r4, lr}
9288    mov     r1, #0x5f000000             @ (float)maxlong
9289    mov     r4, r0
9290    bl      __aeabi_fcmpge              @ is arg >= maxlong?
9291    cmp     r0, #0                      @ nonzero == yes
9292    mvnne   r0, #0                      @ return maxlong (7fffffff)
9293    mvnne   r1, #0x80000000
9294    ldmnefd sp!, {r4, pc}
9295
9296    mov     r0, r4                      @ recover arg
9297    mov     r1, #0xdf000000             @ (float)minlong
9298    bl      __aeabi_fcmple              @ is arg <= minlong?
9299    cmp     r0, #0                      @ nonzero == yes
9300    movne   r0, #0                      @ return minlong (80000000)
9301    movne   r1, #0x80000000
9302    ldmnefd sp!, {r4, pc}
9303
9304    mov     r0, r4                      @ recover arg
9305    mov     r1, r4
9306    bl      __aeabi_fcmpeq              @ is arg == self?
9307    cmp     r0, #0                      @ zero == no
9308    moveq   r1, #0                      @ return zero for NaN
9309    ldmeqfd sp!, {r4, pc}
9310
9311    mov     r0, r4                      @ recover arg
9312    bl      __aeabi_f2lz                @ convert float to long
9313    ldmfd   sp!, {r4, pc}
9314
9315
9316/* continuation for OP_DOUBLE_TO_LONG */
9317/*
9318 * Convert the double in r0/r1 to a long in r0/r1.
9319 *
9320 * We have to clip values to long min/max per the specification.  The
9321 * expected common case is a "reasonable" value that converts directly
9322 * to modest integer.  The EABI convert function isn't doing this for us.
9323 */
9324d2l_doconv:
9325    stmfd   sp!, {r4, r5, lr}           @ save regs
9326    mov     r3, #0x43000000             @ maxlong, as a double (high word)
9327    add     r3, #0x00e00000             @  0x43e00000
9328    mov     r2, #0                      @ maxlong, as a double (low word)
9329    sub     sp, sp, #4                  @ align for EABI
9330    mov     r4, r0                      @ save a copy of r0
9331    mov     r5, r1                      @  and r1
9332    bl      __aeabi_dcmpge              @ is arg >= maxlong?
9333    cmp     r0, #0                      @ nonzero == yes
9334    mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
9335    mvnne   r1, #0x80000000
9336    bne     1f
9337
9338    mov     r0, r4                      @ recover arg
9339    mov     r1, r5
9340    mov     r3, #0xc3000000             @ minlong, as a double (high word)
9341    add     r3, #0x00e00000             @  0xc3e00000
9342    mov     r2, #0                      @ minlong, as a double (low word)
9343    bl      __aeabi_dcmple              @ is arg <= minlong?
9344    cmp     r0, #0                      @ nonzero == yes
9345    movne   r0, #0                      @ return minlong (8000000000000000)
9346    movne   r1, #0x80000000
9347    bne     1f
9348
9349    mov     r0, r4                      @ recover arg
9350    mov     r1, r5
9351    mov     r2, r4                      @ compare against self
9352    mov     r3, r5
9353    bl      __aeabi_dcmpeq              @ is arg == self?
9354    cmp     r0, #0                      @ zero == no
9355    moveq   r1, #0                      @ return zero for NaN
9356    beq     1f
9357
9358    mov     r0, r4                      @ recover arg
9359    mov     r1, r5
9360    bl      __aeabi_d2lz                @ convert double to long
9361
93621:
9363    add     sp, sp, #4
9364    ldmfd   sp!, {r4, r5, pc}
9365
9366
9367/* continuation for OP_MUL_LONG */
9368
9369.LOP_MUL_LONG_finish:
9370    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9371    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
9372    GOTO_OPCODE(ip)                     @ jump to next instruction
9373
9374
9375/* continuation for OP_SHL_LONG */
9376
9377.LOP_SHL_LONG_finish:
9378    mov     r0, r0, asl r2              @  r0<- r0 << r2
9379    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9380    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9381    GOTO_OPCODE(ip)                     @ jump to next instruction
9382
9383
9384/* continuation for OP_SHR_LONG */
9385
9386.LOP_SHR_LONG_finish:
9387    mov     r1, r1, asr r2              @  r1<- r1 >> r2
9388    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9389    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9390    GOTO_OPCODE(ip)                     @ jump to next instruction
9391
9392
9393/* continuation for OP_USHR_LONG */
9394
9395.LOP_USHR_LONG_finish:
9396    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
9397    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9398    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9399    GOTO_OPCODE(ip)                     @ jump to next instruction
9400
9401
9402/* continuation for OP_SHL_LONG_2ADDR */
9403
9404.LOP_SHL_LONG_2ADDR_finish:
9405    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9406    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9407    GOTO_OPCODE(ip)                     @ jump to next instruction
9408
9409
9410/* continuation for OP_SHR_LONG_2ADDR */
9411
9412.LOP_SHR_LONG_2ADDR_finish:
9413    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9414    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9415    GOTO_OPCODE(ip)                     @ jump to next instruction
9416
9417
9418/* continuation for OP_USHR_LONG_2ADDR */
9419
9420.LOP_USHR_LONG_2ADDR_finish:
9421    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9422    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9423    GOTO_OPCODE(ip)                     @ jump to next instruction
9424
9425
9426/* continuation for OP_EXECUTE_INLINE */
9427
9428    /*
9429     * Extract args, call function.
9430     *  r0 = #of args (0-4)
9431     *  r10 = call index
9432     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
9433     *
9434     * Other ideas:
9435     * - Use a jump table from the main piece to jump directly into the
9436     *   AND/LDR pairs.  Costs a data load, saves a branch.
9437     * - Have five separate pieces that do the loading, so we can work the
9438     *   interleave a little better.  Increases code size.
9439     */
9440.LOP_EXECUTE_INLINE_continue:
9441    rsb     r0, r0, #4                  @ r0<- 4-r0
9442    FETCH(r9, 2)                        @ r9<- FEDC
9443    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
9444    bl      common_abort                @ (skipped due to ARM prefetch)
94454:  and     ip, r9, #0xf000             @ isolate F
9446    ldr     r3, [rFP, ip, lsr #10]      @ r3<- vF (shift right 12, left 2)
94473:  and     ip, r9, #0x0f00             @ isolate E
9448    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vE
94492:  and     ip, r9, #0x00f0             @ isolate D
9450    ldr     r1, [rFP, ip, lsr #2]       @ r1<- vD
94511:  and     ip, r9, #0x000f             @ isolate C
9452    ldr     r0, [rFP, ip, lsl #2]       @ r0<- vC
94530:
9454    ldr     r9, .LOP_EXECUTE_INLINE_table       @ table of InlineOperation
9455    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
9456    @ (not reached)
9457
9458.LOP_EXECUTE_INLINE_table:
9459    .word   gDvmInlineOpsTable
9460
9461
9462    .size   dvmAsmSisterStart, .-dvmAsmSisterStart
9463    .global dvmAsmSisterEnd
9464dvmAsmSisterEnd:
9465
9466/* File: armv5te/footer.S */
9467
9468/*
9469 * ===========================================================================
9470 *  Common subroutines and data
9471 * ===========================================================================
9472 */
9473
9474
9475
9476    .text
9477    .align  2
9478
9479#if defined(WITH_JIT)
9480#if defined(WITH_SELF_VERIFICATION)
9481    .global dvmJitToInterpPunt
9482dvmJitToInterpPunt:
9483    mov    r2,#kSVSPunt                 @ r2<- interpreter entry point
9484    b      dvmJitSelfVerificationEnd    @ doesn't return
9485
9486    .global dvmJitToInterpSingleStep
9487dvmJitToInterpSingleStep:
9488    mov    r2,#kSVSSingleStep           @ r2<- interpreter entry point
9489    b      dvmJitSelfVerificationEnd    @ doesn't return
9490
9491    .global dvmJitToTraceSelect
9492dvmJitToTraceSelect:
9493    ldr    r0,[lr, #-1]                 @ pass our target PC
9494    mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
9495    b      dvmJitSelfVerificationEnd    @ doesn't return
9496
9497    .global dvmJitToBackwardBranch
9498dvmJitToBackwardBranch:
9499    ldr    r0,[lr, #-1]                 @ pass our target PC
9500    mov    r2,#kSVSBackwardBranch       @ r2<- interpreter entry point
9501    b      dvmJitSelfVerificationEnd    @ doesn't return
9502
9503    .global dvmJitToInterpNormal
9504dvmJitToInterpNormal:
9505    ldr    r0,[lr, #-1]                 @ pass our target PC
9506    mov    r2,#kSVSNormal               @ r2<- interpreter entry point
9507    b      dvmJitSelfVerificationEnd    @ doesn't return
9508
9509    .global dvmJitToInterpNoChain
9510dvmJitToInterpNoChain:
9511    mov    r0,rPC                       @ pass our target PC
9512    mov    r2,#kSVSNoChain              @ r2<- interpreter entry point
9513    b      dvmJitSelfVerificationEnd    @ doesn't return
9514#else
9515/*
9516 * Return from the translation cache to the interpreter when the compiler is
9517 * having issues translating/executing a Dalvik instruction. We have to skip
9518 * the code cache lookup otherwise it is possible to indefinitely bouce
9519 * between the interpreter and the code cache if the instruction that fails
9520 * to be compiled happens to be at a trace start.
9521 */
9522    .global dvmJitToInterpPunt
9523dvmJitToInterpPunt:
9524    mov    rPC, r0
9525#ifdef EXIT_STATS
9526    mov    r0,lr
9527    bl     dvmBumpPunt;
9528#endif
9529    EXPORT_PC()
9530    adrl   rIBASE, dvmAsmInstructionStart
9531    FETCH_INST()
9532    GET_INST_OPCODE(ip)
9533    GOTO_OPCODE(ip)
9534
9535/*
9536 * Return to the interpreter to handle a single instruction.
9537 * On entry:
9538 *    r0 <= PC
9539 *    r1 <= PC of resume instruction
9540 *    lr <= resume point in translation
9541 */
9542    .global dvmJitToInterpSingleStep
9543dvmJitToInterpSingleStep:
9544    str    lr,[rGLUE,#offGlue_jitResume]
9545    str    r1,[rGLUE,#offGlue_jitResumePC]
9546    mov    r1,#kInterpEntryInstr
9547    @ enum is 4 byte in aapcs-EABI
9548    str    r1, [rGLUE, #offGlue_entryPoint]
9549    mov    rPC,r0
9550    EXPORT_PC()
9551    adrl   rIBASE, dvmAsmInstructionStart
9552    mov    r2,#kJitSingleStep     @ Ask for single step and then revert
9553    str    r2,[rGLUE,#offGlue_jitState]
9554    mov    r1,#1                  @ set changeInterp to bail to debug interp
9555    b      common_gotoBail
9556
9557
9558/*
9559 * Return from the translation cache and immediately request
9560 * a translation for the exit target.  Commonly used following
9561 * invokes.
9562 */
9563    .global dvmJitToTraceSelect
9564dvmJitToTraceSelect:
9565    ldr    rPC,[lr, #-1]           @ get our target PC
9566    add    rINST,lr,#-5            @ save start of chain branch
9567    mov    r0,rPC
9568    bl     dvmJitGetCodeAddr        @ Is there a translation?
9569    cmp    r0,#0
9570    beq    2f
9571    mov    r1,rINST
9572    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9573    mov    r1, rPC                  @ arg1 of translation may need this
9574    mov    lr, #0                   @ in case target is HANDLER_INTERPRET
9575    cmp    r0,#0                    @ successful chain?
9576    bxne   r0                       @ continue native execution
9577    b      toInterpreter            @ didn't chain - resume with interpreter
9578
9579/* No translation, so request one if profiling isn't disabled*/
95802:
9581    adrl   rIBASE, dvmAsmInstructionStart
9582    GET_JIT_PROF_TABLE(r0)
9583    FETCH_INST()
9584    cmp    r0, #0
9585    bne    common_selectTrace
9586    GET_INST_OPCODE(ip)
9587    GOTO_OPCODE(ip)
9588
9589/*
9590 * Return from the translation cache to the interpreter.
9591 * The return was done with a BLX from thumb mode, and
9592 * the following 32-bit word contains the target rPC value.
9593 * Note that lr (r14) will have its low-order bit set to denote
9594 * its thumb-mode origin.
9595 *
9596 * We'll need to stash our lr origin away, recover the new
9597 * target and then check to see if there is a translation available
9598 * for our new target.  If so, we do a translation chain and
9599 * go back to native execution.  Otherwise, it's back to the
9600 * interpreter (after treating this entry as a potential
9601 * trace start).
9602 */
9603    .global dvmJitToInterpNormal
9604dvmJitToInterpNormal:
9605    ldr    rPC,[lr, #-1]           @ get our target PC
9606    add    rINST,lr,#-5            @ save start of chain branch
9607#ifdef EXIT_STATS
9608    bl     dvmBumpNormal
9609#endif
9610    mov    r0,rPC
9611    bl     dvmJitGetCodeAddr        @ Is there a translation?
9612    cmp    r0,#0
9613    beq    toInterpreter            @ go if not, otherwise do chain
9614    mov    r1,rINST
9615    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9616    mov    r1, rPC                  @ arg1 of translation may need this
9617    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9618    cmp    r0,#0                    @ successful chain?
9619    bxne   r0                       @ continue native execution
9620    b      toInterpreter            @ didn't chain - resume with interpreter
9621
9622/*
9623 * Return from the translation cache to the interpreter to do method invocation.
9624 * Check if translation exists for the callee, but don't chain to it.
9625 */
9626    .global dvmJitToInterpNoChain
9627dvmJitToInterpNoChain:
9628#ifdef EXIT_STATS
9629    bl     dvmBumpNoChain
9630#endif
9631    mov    r0,rPC
9632    bl     dvmJitGetCodeAddr        @ Is there a translation?
9633    mov    r1, rPC                  @ arg1 of translation may need this
9634    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9635    cmp    r0,#0
9636    bxne   r0                       @ continue native execution if so
9637#endif
9638
9639/*
9640 * No translation, restore interpreter regs and start interpreting.
9641 * rGLUE & rFP were preserved in the translated code, and rPC has
9642 * already been restored by the time we get here.  We'll need to set
9643 * up rIBASE & rINST, and load the address of the JitTable into r0.
9644 */
9645toInterpreter:
9646    EXPORT_PC()
9647    adrl   rIBASE, dvmAsmInstructionStart
9648    FETCH_INST()
9649    GET_JIT_PROF_TABLE(r0)
9650    @ NOTE: intended fallthrough
9651/*
9652 * Common code to update potential trace start counter, and initiate
9653 * a trace-build if appropriate.  On entry, rPC should point to the
9654 * next instruction to execute, and rINST should be already loaded with
9655 * the next opcode word, and r0 holds a pointer to the jit profile
9656 * table (pJitProfTable).
9657 */
9658common_testUpdateProfile:
9659    cmp     r0,#0
9660    GET_INST_OPCODE(ip)
9661    GOTO_OPCODE_IFEQ(ip)       @ if not profiling, fallthrough otherwise */
9662
9663common_updateProfile:
9664    eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
9665    lsl     r3,r3,#23          @ shift out excess 511
9666    ldrb    r1,[r0,r3,lsr #23] @ get counter
9667    GET_INST_OPCODE(ip)
9668    subs    r1,r1,#1           @ decrement counter
9669    strb    r1,[r0,r3,lsr #23] @ and store it
9670    GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
9671
9672/*
9673 * Here, we switch to the debug interpreter to request
9674 * trace selection.  First, though, check to see if there
9675 * is already a native translation in place (and, if so,
9676 * jump to it now).
9677 */
9678    mov     r1,#255
9679    strb    r1,[r0,r3,lsr #23] @ reset counter
9680    EXPORT_PC()
9681    mov     r0,rPC
9682    bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
9683    mov    r1, rPC                      @ arg1 of translation may need this
9684    mov    lr, #0                       @  in case target is HANDLER_INTERPRET
9685    cmp     r0,#0
9686#if !defined(WITH_SELF_VERIFICATION)
9687    bxne    r0                          @ jump to the translation
9688#else
9689    beq     common_selectTrace
9690    /*
9691     * At this point, we have a target translation.  However, if
9692     * that translation is actually the interpret-only pseudo-translation
9693     * we want to treat it the same as no translation.
9694     */
9695    mov     r10, r0                      @ save target
9696    bl      dvmCompilerGetInterpretTemplate
9697    cmp     r0, r10                      @ special case?
9698    bne     dvmJitSelfVerificationStart  @ set up self verification
9699    GET_INST_OPCODE(ip)
9700    GOTO_OPCODE(ip)
9701    /* no return */
9702#endif
9703
9704common_selectTrace:
9705    mov     r2,#kJitTSelectRequest      @ ask for trace selection
9706    str     r2,[rGLUE,#offGlue_jitState]
9707    mov     r2,#kInterpEntryInstr       @ normal entry reason
9708    str     r2,[rGLUE,#offGlue_entryPoint]
9709    mov     r1,#1                       @ set changeInterp
9710    b       common_gotoBail
9711
9712#if defined(WITH_SELF_VERIFICATION)
9713/*
9714 * Save PC and registers to shadow memory for self verification mode
9715 * before jumping to native translation.
9716 * On entry, r10 contains the address of the target translation.
9717 */
9718dvmJitSelfVerificationStart:
9719    mov     r0,rPC                      @ r0<- program counter
9720    mov     r1,rFP                      @ r1<- frame pointer
9721    mov     r2,rGLUE                    @ r2<- InterpState pointer
9722    mov     r3,r10                      @ r3<- target translation
9723    bl      dvmSelfVerificationSaveState @ save registers to shadow space
9724    ldr     rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
9725    add     rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
9726    bx      r10                         @ jump to the translation
9727
9728/*
9729 * Restore PC, registers, and interpState to original values
9730 * before jumping back to the interpreter.
9731 */
9732dvmJitSelfVerificationEnd:
9733    mov    r1,rFP                        @ pass ending fp
9734    bl     dvmSelfVerificationRestoreState @ restore pc and fp values
9735    ldr    rPC,[r0,#offShadowSpace_startPC] @ restore PC
9736    ldr    rFP,[r0,#offShadowSpace_fp]   @ restore FP
9737    ldr    rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
9738    ldr    r1,[r0,#offShadowSpace_svState] @ get self verification state
9739    cmp    r1,#0                         @ check for punt condition
9740    beq    1f
9741    mov    r2,#kJitSelfVerification      @ ask for self verification
9742    str    r2,[rGLUE,#offGlue_jitState]
9743    mov    r2,#kInterpEntryInstr         @ normal entry reason
9744    str    r2,[rGLUE,#offGlue_entryPoint]
9745    mov    r1,#1                         @ set changeInterp
9746    b      common_gotoBail
9747
97481:                                       @ exit to interpreter without check
9749    EXPORT_PC()
9750    adrl   rIBASE, dvmAsmInstructionStart
9751    FETCH_INST()
9752    GET_INST_OPCODE(ip)
9753    GOTO_OPCODE(ip)
9754#endif
9755
9756#endif
9757
9758/*
9759 * Common code when a backward branch is taken.
9760 *
9761 * On entry:
9762 *  r9 is PC adjustment *in bytes*
9763 */
9764common_backwardBranch:
9765    mov     r0, #kInterpEntryInstr
9766    bl      common_periodicChecks
9767#if defined(WITH_JIT)
9768    GET_JIT_PROF_TABLE(r0)
9769    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9770    cmp     r0,#0
9771    bne     common_updateProfile
9772    GET_INST_OPCODE(ip)
9773    GOTO_OPCODE(ip)
9774#else
9775    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9776    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9777    GOTO_OPCODE(ip)                     @ jump to next instruction
9778#endif
9779
9780
9781/*
9782 * Need to see if the thread needs to be suspended or debugger/profiler
9783 * activity has begun.
9784 *
9785 * TODO: if JDWP isn't running, zero out pDebuggerActive pointer so we don't
9786 * have to do the second ldr.
9787 *
9788 * TODO: reduce this so we're just checking a single location.
9789 *
9790 * On entry:
9791 *  r0 is reentry type, e.g. kInterpEntryInstr
9792 *  r9 is trampoline PC adjustment *in bytes*
9793 */
9794common_periodicChecks:
9795    ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
9796
9797    @ speculatively store r0 before it is clobbered by dvmCheckSuspendPending
9798    str     r0, [rGLUE, #offGlue_entryPoint]
9799
9800#if defined(WITH_DEBUGGER)
9801    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9802#endif
9803#if defined(WITH_PROFILER)
9804    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9805#endif
9806
9807    ldr     r3, [r3]                    @ r3<- suspendCount (int)
9808
9809#if defined(WITH_DEBUGGER)
9810    ldrb    r1, [r1]                    @ r1<- debuggerActive (boolean)
9811#endif
9812#if defined (WITH_PROFILER)
9813    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9814#endif
9815
9816    cmp     r3, #0                      @ suspend pending?
9817    bne     2f                          @ yes, do full suspension check
9818
9819#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
9820# if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
9821    orrs    r1, r1, r2                  @ r1<- r1 | r2
9822    cmp     r1, #0                      @ debugger attached or profiler started?
9823# elif defined(WITH_DEBUGGER)
9824    cmp     r1, #0                      @ debugger attached?
9825# elif defined(WITH_PROFILER)
9826    cmp     r2, #0                      @ profiler started?
9827# endif
9828    bne     3f                          @ debugger/profiler, switch interp
9829#endif
9830
9831    bx      lr                          @ nothing to do, return
9832
98332:  @ check suspend
9834    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9835    EXPORT_PC()                         @ need for precise GC
9836    b       dvmCheckSuspendPending      @ suspend if necessary, then return
9837
98383:  @ debugger/profiler enabled, bail out
9839    add     rPC, rPC, r9                @ update rPC
9840    mov     r1, #1                      @ "want switch" = true
9841    b       common_gotoBail
9842
9843
9844/*
9845 * The equivalent of "goto bail", this calls through the "bail handler".
9846 *
9847 * State registers will be saved to the "glue" area before bailing.
9848 *
9849 * On entry:
9850 *  r1 is "bool changeInterp", indicating if we want to switch to the
9851 *     other interpreter or just bail all the way out
9852 */
9853common_gotoBail:
9854    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9855    mov     r0, rGLUE                   @ r0<- glue ptr
9856    b       dvmMterpStdBail             @ call(glue, changeInterp)
9857
9858    @add     r1, r1, #1                  @ using (boolean+1)
9859    @add     r0, rGLUE, #offGlue_jmpBuf  @ r0<- &glue->jmpBuf
9860    @bl      _longjmp                    @ does not return
9861    @bl      common_abort
9862
9863
9864/*
9865 * Common code for method invocation with range.
9866 *
9867 * On entry:
9868 *  r0 is "Method* methodToCall", the method we're trying to call
9869 */
9870common_invokeMethodRange:
9871.LinvokeNewRange:
9872    @ prepare to copy args to "outs" area of current frame
9873    movs    r2, rINST, lsr #8           @ r2<- AA (arg count) -- test for zero
9874    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9875    beq     .LinvokeArgsDone            @ if no args, skip the rest
9876    FETCH(r1, 2)                        @ r1<- CCCC
9877
9878    @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
9879    @ (very few methods have > 10 args; could unroll for common cases)
9880    add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
9881    sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
9882    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
98831:  ldr     r1, [r3], #4                @ val = *fp++
9884    subs    r2, r2, #1                  @ count--
9885    str     r1, [r10], #4               @ *outs++ = val
9886    bne     1b                          @ ...while count != 0
9887    ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
9888    b       .LinvokeArgsDone
9889
9890/*
9891 * Common code for method invocation without range.
9892 *
9893 * On entry:
9894 *  r0 is "Method* methodToCall", the method we're trying to call
9895 */
9896common_invokeMethodNoRange:
9897.LinvokeNewNoRange:
9898    @ prepare to copy args to "outs" area of current frame
9899    movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
9900    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9901    FETCH(r1, 2)                        @ r1<- GFED (load here to hide latency)
9902    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
9903    ldrh    r3, [r0, #offMethod_outsSize]  @ r3<- methodToCall->outsSize
9904    beq     .LinvokeArgsDone
9905
9906    @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
9907.LinvokeNonRange:
9908    rsb     r2, r2, #5                  @ r2<- 5-r2
9909    add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
9910    bl      common_abort                @ (skipped due to ARM prefetch)
99115:  and     ip, rINST, #0x0f00          @ isolate A
9912    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vA (shift right 8, left 2)
9913    mov     r0, r0                      @ nop
9914    str     r2, [r10, #-4]!             @ *--outs = vA
99154:  and     ip, r1, #0xf000             @ isolate G
9916    ldr     r2, [rFP, ip, lsr #10]      @ r2<- vG (shift right 12, left 2)
9917    mov     r0, r0                      @ nop
9918    str     r2, [r10, #-4]!             @ *--outs = vG
99193:  and     ip, r1, #0x0f00             @ isolate F
9920    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vF
9921    mov     r0, r0                      @ nop
9922    str     r2, [r10, #-4]!             @ *--outs = vF
99232:  and     ip, r1, #0x00f0             @ isolate E
9924    ldr     r2, [rFP, ip, lsr #2]       @ r2<- vE
9925    mov     r0, r0                      @ nop
9926    str     r2, [r10, #-4]!             @ *--outs = vE
99271:  and     ip, r1, #0x000f             @ isolate D
9928    ldr     r2, [rFP, ip, lsl #2]       @ r2<- vD
9929    mov     r0, r0                      @ nop
9930    str     r2, [r10, #-4]!             @ *--outs = vD
99310:  @ fall through to .LinvokeArgsDone
9932
9933.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
9934    ldr     r2, [r0, #offMethod_insns]  @ r2<- method->insns
9935    ldr     rINST, [r0, #offMethod_clazz]  @ rINST<- method->clazz
9936    @ find space for the new stack frame, check for overflow
9937    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
9938    sub     r1, r1, r9, lsl #2          @ r1<- newFp (old savearea - regsSize)
9939    SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
9940@    bl      common_dumpRegs
9941    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
9942    sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
9943    cmp     r3, r9                      @ bottom < interpStackEnd?
9944    ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
9945    blt     .LstackOverflow             @ yes, this frame will overflow stack
9946
9947    @ set up newSaveArea
9948#ifdef EASY_GDB
9949    SAVEAREA_FROM_FP(ip, rFP)           @ ip<- stack save area
9950    str     ip, [r10, #offStackSaveArea_prevSave]
9951#endif
9952    str     rFP, [r10, #offStackSaveArea_prevFrame]
9953    str     rPC, [r10, #offStackSaveArea_savedPc]
9954#if defined(WITH_JIT)
9955    mov     r9, #0
9956    str     r9, [r10, #offStackSaveArea_returnAddr]
9957#endif
9958    str     r0, [r10, #offStackSaveArea_method]
9959    tst     r3, #ACC_NATIVE
9960    bne     .LinvokeNative
9961
9962    /*
9963    stmfd   sp!, {r0-r3}
9964    bl      common_printNewline
9965    mov     r0, rFP
9966    mov     r1, #0
9967    bl      dvmDumpFp
9968    ldmfd   sp!, {r0-r3}
9969    stmfd   sp!, {r0-r3}
9970    mov     r0, r1
9971    mov     r1, r10
9972    bl      dvmDumpFp
9973    bl      common_printNewline
9974    ldmfd   sp!, {r0-r3}
9975    */
9976
9977    ldrh    r9, [r2]                        @ r9 <- load INST from new PC
9978    ldr     r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
9979    mov     rPC, r2                         @ publish new rPC
9980    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
9981
9982    @ Update "glue" values for the new method
9983    @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
9984    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
9985    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
9986#if defined(WITH_JIT)
9987    GET_JIT_PROF_TABLE(r0)
9988    mov     rFP, r1                         @ fp = newFp
9989    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
9990    mov     rINST, r9                       @ publish new rINST
9991    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
9992    cmp     r0,#0
9993    bne     common_updateProfile
9994    GOTO_OPCODE(ip)                         @ jump to next instruction
9995#else
9996    mov     rFP, r1                         @ fp = newFp
9997    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
9998    mov     rINST, r9                       @ publish new rINST
9999    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
10000    GOTO_OPCODE(ip)                         @ jump to next instruction
10001#endif
10002
10003.LinvokeNative:
10004    @ Prep for the native call
10005    @ r0=methodToCall, r1=newFp, r10=newSaveArea
10006    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
10007    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
10008    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
10009    str     r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
10010    mov     r9, r3                      @ r9<- glue->self (preserve)
10011
10012    mov     r2, r0                      @ r2<- methodToCall
10013    mov     r0, r1                      @ r0<- newFp (points to args)
10014    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
10015
10016#ifdef ASSIST_DEBUGGER
10017    /* insert fake function header to help gdb find the stack frame */
10018    b       .Lskip
10019    .type   dalvik_mterp, %function
10020dalvik_mterp:
10021    .fnstart
10022    MTERP_ENTRY1
10023    MTERP_ENTRY2
10024.Lskip:
10025#endif
10026
10027    @mov     lr, pc                      @ set return addr
10028    @ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
10029    LDR_PC_LR "[r2, #offMethod_nativeFunc]"
10030
10031    @ native return; r9=self, r10=newSaveArea
10032    @ equivalent to dvmPopJniLocals
10033    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
10034    ldr     r1, [r9, #offThread_exception] @ check for exception
10035    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
10036    cmp     r1, #0                      @ null?
10037    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
10038    bne     common_exceptionThrown      @ no, handle exception
10039
10040    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
10041    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10042    GOTO_OPCODE(ip)                     @ jump to next instruction
10043
10044.LstackOverflow:    @ r0=methodToCall
10045    mov     r1, r0                      @ r1<- methodToCall
10046    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
10047    bl      dvmHandleStackOverflow
10048    b       common_exceptionThrown
10049#ifdef ASSIST_DEBUGGER
10050    .fnend
10051#endif
10052
10053
10054    /*
10055     * Common code for method invocation, calling through "glue code".
10056     *
10057     * TODO: now that we have range and non-range invoke handlers, this
10058     *       needs to be split into two.  Maybe just create entry points
10059     *       that set r9 and jump here?
10060     *
10061     * On entry:
10062     *  r0 is "Method* methodToCall", the method we're trying to call
10063     *  r9 is "bool methodCallRange", indicating if this is a /range variant
10064     */
10065     .if    0
10066.LinvokeOld:
10067    sub     sp, sp, #8                  @ space for args + pad
10068    FETCH(ip, 2)                        @ ip<- FEDC or CCCC
10069    mov     r2, r0                      @ A2<- methodToCall
10070    mov     r0, rGLUE                   @ A0<- glue
10071    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
10072    mov     r1, r9                      @ A1<- methodCallRange
10073    mov     r3, rINST, lsr #8           @ A3<- AA
10074    str     ip, [sp, #0]                @ A4<- ip
10075    bl      dvmMterp_invokeMethod       @ call the C invokeMethod
10076    add     sp, sp, #8                  @ remove arg area
10077    b       common_resumeAfterGlueCall  @ continue to next instruction
10078    .endif
10079
10080
10081
10082/*
10083 * Common code for handling a return instruction.
10084 *
10085 * This does not return.
10086 */
10087common_returnFromMethod:
10088.LreturnNew:
10089    mov     r0, #kInterpEntryReturn
10090    mov     r9, #0
10091    bl      common_periodicChecks
10092
10093    SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
10094    ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
10095    ldr     r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
10096    ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
10097                                        @ r2<- method we're returning to
10098    ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
10099    cmp     r2, #0                      @ is this a break frame?
10100    ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
10101    mov     r1, #0                      @ "want switch" = false
10102    beq     common_gotoBail             @ break frame, bail out completely
10103
10104    PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
10105    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
10106    ldr     r1, [r10, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
10107    str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
10108#if defined(WITH_JIT)
10109    ldr     r3, [r0, #offStackSaveArea_returnAddr] @ r3 = saveArea->returnAddr
10110    GET_JIT_PROF_TABLE(r0)
10111    mov     rPC, r9                     @ publish new rPC
10112    str     r1, [rGLUE, #offGlue_methodClassDex]
10113    cmp     r3, #0                      @ caller is compiled code
10114    blxne   r3
10115    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10116    cmp     r0,#0
10117    bne     common_updateProfile
10118    GOTO_OPCODE(ip)                     @ jump to next instruction
10119#else
10120    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10121    mov     rPC, r9                     @ publish new rPC
10122    str     r1, [rGLUE, #offGlue_methodClassDex]
10123    GOTO_OPCODE(ip)                     @ jump to next instruction
10124#endif
10125
10126    /*
10127     * Return handling, calls through "glue code".
10128     */
10129     .if    0
10130.LreturnOld:
10131    SAVE_PC_FP_TO_GLUE()                @ export state
10132    mov     r0, rGLUE                   @ arg to function
10133    bl      dvmMterp_returnFromMethod
10134    b       common_resumeAfterGlueCall
10135    .endif
10136
10137
10138/*
10139 * Somebody has thrown an exception.  Handle it.
10140 *
10141 * If the exception processing code returns to us (instead of falling
10142 * out of the interpreter), continue with whatever the next instruction
10143 * now happens to be.
10144 *
10145 * This does not return.
10146 */
10147     .global dvmMterpCommonExceptionThrown
10148dvmMterpCommonExceptionThrown:
10149common_exceptionThrown:
10150.LexceptionNew:
10151    mov     r0, #kInterpEntryThrow
10152    mov     r9, #0
10153    bl      common_periodicChecks
10154
10155#if defined(WITH_JIT)
10156    mov     r2,#kJitTSelectAbort        @ abandon trace selection in progress
10157    str     r2,[rGLUE,#offGlue_jitState]
10158#endif
10159
10160    ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
10161    ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
10162    mov     r1, r10                     @ r1<- self
10163    mov     r0, r9                      @ r0<- exception
10164    bl      dvmAddTrackedAlloc          @ don't let the exception be GCed
10165    mov     r3, #0                      @ r3<- NULL
10166    str     r3, [r10, #offThread_exception] @ self->exception = NULL
10167
10168    /* set up args and a local for "&fp" */
10169    /* (str sp, [sp, #-4]!  would be perfect here, but is discouraged) */
10170    str     rFP, [sp, #-4]!             @ *--sp = fp
10171    mov     ip, sp                      @ ip<- &fp
10172    mov     r3, #0                      @ r3<- false
10173    str     ip, [sp, #-4]!              @ *--sp = &fp
10174    ldr     r1, [rGLUE, #offGlue_method] @ r1<- glue->method
10175    mov     r0, r10                     @ r0<- self
10176    ldr     r1, [r1, #offMethod_insns]  @ r1<- method->insns
10177    mov     r2, r9                      @ r2<- exception
10178    sub     r1, rPC, r1                 @ r1<- pc - method->insns
10179    mov     r1, r1, asr #1              @ r1<- offset in code units
10180
10181    /* call, r0 gets catchRelPc (a code-unit offset) */
10182    bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
10183
10184    /* fix earlier stack overflow if necessary; may trash rFP */
10185    ldrb    r1, [r10, #offThread_stackOverflowed]
10186    cmp     r1, #0                      @ did we overflow earlier?
10187    beq     1f                          @ no, skip ahead
10188    mov     rFP, r0                     @ save relPc result in rFP
10189    mov     r0, r10                     @ r0<- self
10190    bl      dvmCleanupStackOverflow     @ call(self)
10191    mov     r0, rFP                     @ restore result
101921:
10193
10194    /* update frame pointer and check result from dvmFindCatchBlock */
10195    ldr     rFP, [sp, #4]               @ retrieve the updated rFP
10196    cmp     r0, #0                      @ is catchRelPc < 0?
10197    add     sp, sp, #8                  @ restore stack
10198    bmi     .LnotCaughtLocally
10199
10200    /* adjust locals to match self->curFrame and updated PC */
10201    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
10202    ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
10203    str     r1, [rGLUE, #offGlue_method]    @ glue->method = new method
10204    ldr     r2, [r1, #offMethod_clazz]      @ r2<- method->clazz
10205    ldr     r3, [r1, #offMethod_insns]      @ r3<- method->insns
10206    ldr     r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
10207    add     rPC, r3, r0, asl #1             @ rPC<- method->insns + catchRelPc
10208    str     r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
10209
10210    /* release the tracked alloc on the exception */
10211    mov     r0, r9                      @ r0<- exception
10212    mov     r1, r10                     @ r1<- self
10213    bl      dvmReleaseTrackedAlloc      @ release the exception
10214
10215    /* restore the exception if the handler wants it */
10216    FETCH_INST()                        @ load rINST from rPC
10217    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10218    cmp     ip, #OP_MOVE_EXCEPTION      @ is it "move-exception"?
10219    streq   r9, [r10, #offThread_exception] @ yes, restore the exception
10220    GOTO_OPCODE(ip)                     @ jump to next instruction
10221
10222.LnotCaughtLocally: @ r9=exception, r10=self
10223    /* fix stack overflow if necessary */
10224    ldrb    r1, [r10, #offThread_stackOverflowed]
10225    cmp     r1, #0                      @ did we overflow earlier?
10226    movne   r0, r10                     @ if yes: r0<- self
10227    blne    dvmCleanupStackOverflow     @ if yes: call(self)
10228
10229    @ may want to show "not caught locally" debug messages here
10230#if DVM_SHOW_EXCEPTION >= 2
10231    /* call __android_log_print(prio, tag, format, ...) */
10232    /* "Exception %s from %s:%d not caught locally" */
10233    @ dvmLineNumFromPC(method, pc - method->insns)
10234    ldr     r0, [rGLUE, #offGlue_method]
10235    ldr     r1, [r0, #offMethod_insns]
10236    sub     r1, rPC, r1
10237    asr     r1, r1, #1
10238    bl      dvmLineNumFromPC
10239    str     r0, [sp, #-4]!
10240    @ dvmGetMethodSourceFile(method)
10241    ldr     r0, [rGLUE, #offGlue_method]
10242    bl      dvmGetMethodSourceFile
10243    str     r0, [sp, #-4]!
10244    @ exception->clazz->descriptor
10245    ldr     r3, [r9, #offObject_clazz]
10246    ldr     r3, [r3, #offClassObject_descriptor]
10247    @
10248    ldr     r2, strExceptionNotCaughtLocally
10249    ldr     r1, strLogTag
10250    mov     r0, #3                      @ LOG_DEBUG
10251    bl      __android_log_print
10252#endif
10253    str     r9, [r10, #offThread_exception] @ restore exception
10254    mov     r0, r9                      @ r0<- exception
10255    mov     r1, r10                     @ r1<- self
10256    bl      dvmReleaseTrackedAlloc      @ release the exception
10257    mov     r1, #0                      @ "want switch" = false
10258    b       common_gotoBail             @ bail out
10259
10260
10261    /*
10262     * Exception handling, calls through "glue code".
10263     */
10264    .if     0
10265.LexceptionOld:
10266    SAVE_PC_FP_TO_GLUE()                @ export state
10267    mov     r0, rGLUE                   @ arg to function
10268    bl      dvmMterp_exceptionThrown
10269    b       common_resumeAfterGlueCall
10270    .endif
10271
10272
10273/*
10274 * After returning from a "glued" function, pull out the updated
10275 * values and start executing at the next instruction.
10276 */
10277common_resumeAfterGlueCall:
10278    LOAD_PC_FP_FROM_GLUE()              @ pull rPC and rFP out of glue
10279    FETCH_INST()                        @ load rINST from rPC
10280    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10281    GOTO_OPCODE(ip)                     @ jump to next instruction
10282
10283/*
10284 * Invalid array index.
10285 */
10286common_errArrayIndex:
10287    EXPORT_PC()
10288    ldr     r0, strArrayIndexException
10289    mov     r1, #0
10290    bl      dvmThrowException
10291    b       common_exceptionThrown
10292
10293/*
10294 * Invalid array value.
10295 */
10296common_errArrayStore:
10297    EXPORT_PC()
10298    ldr     r0, strArrayStoreException
10299    mov     r1, #0
10300    bl      dvmThrowException
10301    b       common_exceptionThrown
10302
10303/*
10304 * Integer divide or mod by zero.
10305 */
10306common_errDivideByZero:
10307    EXPORT_PC()
10308    ldr     r0, strArithmeticException
10309    ldr     r1, strDivideByZero
10310    bl      dvmThrowException
10311    b       common_exceptionThrown
10312
10313/*
10314 * Attempt to allocate an array with a negative size.
10315 */
10316common_errNegativeArraySize:
10317    EXPORT_PC()
10318    ldr     r0, strNegativeArraySizeException
10319    mov     r1, #0
10320    bl      dvmThrowException
10321    b       common_exceptionThrown
10322
10323/*
10324 * Invocation of a non-existent method.
10325 */
10326common_errNoSuchMethod:
10327    EXPORT_PC()
10328    ldr     r0, strNoSuchMethodError
10329    mov     r1, #0
10330    bl      dvmThrowException
10331    b       common_exceptionThrown
10332
10333/*
10334 * We encountered a null object when we weren't expecting one.  We
10335 * export the PC, throw a NullPointerException, and goto the exception
10336 * processing code.
10337 */
10338common_errNullObject:
10339    EXPORT_PC()
10340    ldr     r0, strNullPointerException
10341    mov     r1, #0
10342    bl      dvmThrowException
10343    b       common_exceptionThrown
10344
10345/*
10346 * For debugging, cause an immediate fault.  The source address will
10347 * be in lr (use a bl instruction to jump here).
10348 */
10349common_abort:
10350    ldr     pc, .LdeadFood
10351.LdeadFood:
10352    .word   0xdeadf00d
10353
10354/*
10355 * Spit out a "we were here", preserving all registers.  (The attempt
10356 * to save ip won't work, but we need to save an even number of
10357 * registers for EABI 64-bit stack alignment.)
10358 */
10359    .macro  SQUEAK num
10360common_squeak\num:
10361    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10362    ldr     r0, strSqueak
10363    mov     r1, #\num
10364    bl      printf
10365    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10366    bx      lr
10367    .endm
10368
10369    SQUEAK  0
10370    SQUEAK  1
10371    SQUEAK  2
10372    SQUEAK  3
10373    SQUEAK  4
10374    SQUEAK  5
10375
10376/*
10377 * Spit out the number in r0, preserving registers.
10378 */
10379common_printNum:
10380    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10381    mov     r1, r0
10382    ldr     r0, strSqueak
10383    bl      printf
10384    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10385    bx      lr
10386
10387/*
10388 * Print a newline, preserving registers.
10389 */
10390common_printNewline:
10391    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10392    ldr     r0, strNewline
10393    bl      printf
10394    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10395    bx      lr
10396
10397    /*
10398     * Print the 32-bit quantity in r0 as a hex value, preserving registers.
10399     */
10400common_printHex:
10401    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10402    mov     r1, r0
10403    ldr     r0, strPrintHex
10404    bl      printf
10405    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10406    bx      lr
10407
10408/*
10409 * Print the 64-bit quantity in r0-r1, preserving registers.
10410 */
10411common_printLong:
10412    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10413    mov     r3, r1
10414    mov     r2, r0
10415    ldr     r0, strPrintLong
10416    bl      printf
10417    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10418    bx      lr
10419
10420/*
10421 * Print full method info.  Pass the Method* in r0.  Preserves regs.
10422 */
10423common_printMethod:
10424    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10425    bl      dvmMterpPrintMethod
10426    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10427    bx      lr
10428
10429/*
10430 * Call a C helper function that dumps regs and possibly some
10431 * additional info.  Requires the C function to be compiled in.
10432 */
10433    .if     0
10434common_dumpRegs:
10435    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10436    bl      dvmMterpDumpArmRegs
10437    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10438    bx      lr
10439    .endif
10440
10441#if 0
10442/*
10443 * Experiment on VFP mode.
10444 *
10445 * uint32_t setFPSCR(uint32_t val, uint32_t mask)
10446 *
10447 * Updates the bits specified by "mask", setting them to the values in "val".
10448 */
10449setFPSCR:
10450    and     r0, r0, r1                  @ make sure no stray bits are set
10451    fmrx    r2, fpscr                   @ get VFP reg
10452    mvn     r1, r1                      @ bit-invert mask
10453    and     r2, r2, r1                  @ clear masked bits
10454    orr     r2, r2, r0                  @ set specified bits
10455    fmxr    fpscr, r2                   @ set VFP reg
10456    mov     r0, r2                      @ return new value
10457    bx      lr
10458
10459    .align  2
10460    .global dvmConfigureFP
10461    .type   dvmConfigureFP, %function
10462dvmConfigureFP:
10463    stmfd   sp!, {ip, lr}
10464    /* 0x03000000 sets DN/FZ */
10465    /* 0x00009f00 clears the six exception enable flags */
10466    bl      common_squeak0
10467    mov     r0, #0x03000000             @ r0<- 0x03000000
10468    add     r1, r0, #0x9f00             @ r1<- 0x03009f00
10469    bl      setFPSCR
10470    ldmfd   sp!, {ip, pc}
10471#endif
10472
10473
10474/*
10475 * String references, must be close to the code that uses them.
10476 */
10477    .align  2
10478strArithmeticException:
10479    .word   .LstrArithmeticException
10480strArrayIndexException:
10481    .word   .LstrArrayIndexException
10482strArrayStoreException:
10483    .word   .LstrArrayStoreException
10484strDivideByZero:
10485    .word   .LstrDivideByZero
10486strNegativeArraySizeException:
10487    .word   .LstrNegativeArraySizeException
10488strNoSuchMethodError:
10489    .word   .LstrNoSuchMethodError
10490strNullPointerException:
10491    .word   .LstrNullPointerException
10492
10493strLogTag:
10494    .word   .LstrLogTag
10495strExceptionNotCaughtLocally:
10496    .word   .LstrExceptionNotCaughtLocally
10497
10498strNewline:
10499    .word   .LstrNewline
10500strSqueak:
10501    .word   .LstrSqueak
10502strPrintHex:
10503    .word   .LstrPrintHex
10504strPrintLong:
10505    .word   .LstrPrintLong
10506
10507/*
10508 * Zero-terminated ASCII string data.
10509 *
10510 * On ARM we have two choices: do like gcc does, and LDR from a .word
10511 * with the address, or use an ADR pseudo-op to get the address
10512 * directly.  ADR saves 4 bytes and an indirection, but it's using a
10513 * PC-relative addressing mode and hence has a limited range, which
10514 * makes it not work well with mergeable string sections.
10515 */
10516    .section .rodata.str1.4,"aMS",%progbits,1
10517
10518.LstrBadEntryPoint:
10519    .asciz  "Bad entry point %d\n"
10520.LstrArithmeticException:
10521    .asciz  "Ljava/lang/ArithmeticException;"
10522.LstrArrayIndexException:
10523    .asciz  "Ljava/lang/ArrayIndexOutOfBoundsException;"
10524.LstrArrayStoreException:
10525    .asciz  "Ljava/lang/ArrayStoreException;"
10526.LstrClassCastException:
10527    .asciz  "Ljava/lang/ClassCastException;"
10528.LstrDivideByZero:
10529    .asciz  "divide by zero"
10530.LstrFilledNewArrayNotImpl:
10531    .asciz  "filled-new-array only implemented for objects and 'int'"
10532.LstrInternalError:
10533    .asciz  "Ljava/lang/InternalError;"
10534.LstrInstantiationError:
10535    .asciz  "Ljava/lang/InstantiationError;"
10536.LstrNegativeArraySizeException:
10537    .asciz  "Ljava/lang/NegativeArraySizeException;"
10538.LstrNoSuchMethodError:
10539    .asciz  "Ljava/lang/NoSuchMethodError;"
10540.LstrNullPointerException:
10541    .asciz  "Ljava/lang/NullPointerException;"
10542
10543.LstrLogTag:
10544    .asciz  "mterp"
10545.LstrExceptionNotCaughtLocally:
10546    .asciz  "Exception %s from %s:%d not caught locally\n"
10547
10548.LstrNewline:
10549    .asciz  "\n"
10550.LstrSqueak:
10551    .asciz  "<%d>"
10552.LstrPrintHex:
10553    .asciz  "<0x%x>"
10554.LstrPrintLong:
10555    .asciz  "<%lld>"
10556
10557
10558