InterpAsm-armv5te-vfp.S revision d726991ba52466cde88e37aba4de2395b62477fa
1/*
2 * This file was generated automatically by gen-mterp.py for 'armv5te-vfp'.
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#define GET_JIT_THRESHOLD(_reg)     ldr     _reg,[rGLUE,#offGlue_jitThreshold]
191#endif
192
193/*
194 * Convert a virtual register index into an address.
195 */
196#define VREG_INDEX_TO_ADDR(_reg, _vreg) \
197        add     _reg, rFP, _vreg, lsl #2
198
199/*
200 * This is a #include, not a %include, because we want the C pre-processor
201 * to expand the macros into assembler assignment statements.
202 */
203#include "../common/asm-constants.h"
204
205
206/* File: armv5te/platform.S */
207/*
208 * ===========================================================================
209 *  CPU-version-specific defines
210 * ===========================================================================
211 */
212
213/*
214 * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5.  Essentially a
215 * one-way branch.
216 *
217 * May modify IP.  Does not modify LR.
218 */
219.macro  LDR_PC source
220    ldr     pc, \source
221.endm
222
223/*
224 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5.
225 * Jump to subroutine.
226 *
227 * May modify IP and LR.
228 */
229.macro  LDR_PC_LR source
230    mov     lr, pc
231    ldr     pc, \source
232.endm
233
234/*
235 * Macro for "LDMFD SP!, {...regs...,PC}".
236 *
237 * May modify IP and LR.
238 */
239.macro  LDMFD_PC regs
240    ldmfd   sp!, {\regs,pc}
241.endm
242
243
244/* File: armv5te/entry.S */
245/*
246 * Copyright (C) 2008 The Android Open Source Project
247 *
248 * Licensed under the Apache License, Version 2.0 (the "License");
249 * you may not use this file except in compliance with the License.
250 * You may obtain a copy of the License at
251 *
252 *      http://www.apache.org/licenses/LICENSE-2.0
253 *
254 * Unless required by applicable law or agreed to in writing, software
255 * distributed under the License is distributed on an "AS IS" BASIS,
256 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
257 * See the License for the specific language governing permissions and
258 * limitations under the License.
259 */
260/*
261 * Interpreter entry point.
262 */
263
264/*
265 * We don't have formal stack frames, so gdb scans upward in the code
266 * to find the start of the function (a label with the %function type),
267 * and then looks at the next few instructions to figure out what
268 * got pushed onto the stack.  From this it figures out how to restore
269 * the registers, including PC, for the previous stack frame.  If gdb
270 * sees a non-function label, it stops scanning, so either we need to
271 * have nothing but assembler-local labels between the entry point and
272 * the break, or we need to fake it out.
273 *
274 * When this is defined, we add some stuff to make gdb less confused.
275 */
276#define ASSIST_DEBUGGER 1
277
278    .text
279    .align  2
280    .global dvmMterpStdRun
281    .type   dvmMterpStdRun, %function
282
283/*
284 * On entry:
285 *  r0  MterpGlue* glue
286 *
287 * This function returns a boolean "changeInterp" value.  The return comes
288 * via a call to dvmMterpStdBail().
289 */
290dvmMterpStdRun:
291#define MTERP_ENTRY1 \
292    .save {r4-r10,fp,lr}; \
293    stmfd   sp!, {r4-r10,fp,lr}         @ save 9 regs
294#define MTERP_ENTRY2 \
295    .pad    #4; \
296    sub     sp, sp, #4                  @ align 64
297
298    .fnstart
299    MTERP_ENTRY1
300    MTERP_ENTRY2
301
302    /* save stack pointer, add magic word for debuggerd */
303    str     sp, [r0, #offGlue_bailPtr]  @ save SP for eventual return
304
305    /* set up "named" registers, figure out entry point */
306    mov     rGLUE, r0                   @ set rGLUE
307    ldrb    r1, [r0, #offGlue_entryPoint]   @ InterpEntry enum is char
308    LOAD_PC_FP_FROM_GLUE()              @ load rPC and rFP from "glue"
309    adr     rIBASE, dvmAsmInstructionStart  @ set rIBASE
310    cmp     r1, #kInterpEntryInstr      @ usual case?
311    bne     .Lnot_instr                 @ no, handle it
312
313#if defined(WITH_JIT)
314.Lno_singleStep:
315    /* Entry is always a possible trace start */
316    GET_JIT_PROF_TABLE(r0)
317    FETCH_INST()
318    cmp    r0,#0
319    bne    common_updateProfile
320    GET_INST_OPCODE(ip)
321    GOTO_OPCODE(ip)
322#else
323    /* start executing the instruction at rPC */
324    FETCH_INST()                        @ load rINST from rPC
325    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
326    GOTO_OPCODE(ip)                     @ jump to next instruction
327#endif
328
329.Lnot_instr:
330    cmp     r1, #kInterpEntryReturn     @ were we returning from a method?
331    beq     common_returnFromMethod
332
333.Lnot_return:
334    cmp     r1, #kInterpEntryThrow      @ were we throwing an exception?
335    beq     common_exceptionThrown
336
337#if defined(WITH_JIT)
338.Lnot_throw:
339    ldr     r0,[rGLUE, #offGlue_jitResume]
340    ldr     r2,[rGLUE, #offGlue_jitResumePC]
341    cmp     r1, #kInterpEntryResume     @ resuming after Jit single-step?
342    bne     .Lbad_arg
343    cmp     rPC,r2
344    bne     .Lno_singleStep             @ must have branched, don't resume
345    mov     r1, #kInterpEntryInstr
346    strb    r1, [rGLUE, #offGlue_entryPoint]
347    ldr     rINST, .LdvmCompilerTemplate
348    bx      r0                          @ re-enter the translation
349.LdvmCompilerTemplate:
350    .word   dvmCompilerTemplateStart
351#endif
352
353.Lbad_arg:
354    ldr     r0, strBadEntryPoint
355    @ r1 holds value of entryPoint
356    bl      printf
357    bl      dvmAbort
358    .fnend
359
360
361    .global dvmMterpStdBail
362    .type   dvmMterpStdBail, %function
363
364/*
365 * Restore the stack pointer and PC from the save point established on entry.
366 * This is essentially the same as a longjmp, but should be cheaper.  The
367 * last instruction causes us to return to whoever called dvmMterpStdRun.
368 *
369 * We pushed some registers on the stack in dvmMterpStdRun, then saved
370 * SP and LR.  Here we restore SP, restore the registers, and then restore
371 * LR to PC.
372 *
373 * On entry:
374 *  r0  MterpGlue* glue
375 *  r1  bool changeInterp
376 */
377dvmMterpStdBail:
378    ldr     sp, [r0, #offGlue_bailPtr]      @ sp<- saved SP
379    mov     r0, r1                          @ return the changeInterp value
380    add     sp, sp, #4                      @ un-align 64
381    LDMFD_PC "r4-r10,fp"                    @ restore 9 regs and return
382
383
384/*
385 * String references.
386 */
387strBadEntryPoint:
388    .word   .LstrBadEntryPoint
389
390
391
392    .global dvmAsmInstructionStart
393    .type   dvmAsmInstructionStart, %function
394dvmAsmInstructionStart = .L_OP_NOP
395    .text
396
397/* ------------------------------ */
398    .balign 64
399.L_OP_NOP: /* 0x00 */
400/* File: armv5te/OP_NOP.S */
401    FETCH_ADVANCE_INST(1)               @ advance to next instr, load rINST
402    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
403    GOTO_OPCODE(ip)                     @ execute it
404
405#ifdef ASSIST_DEBUGGER
406    /* insert fake function header to help gdb find the stack frame */
407    .type   dalvik_inst, %function
408dalvik_inst:
409    .fnstart
410    MTERP_ENTRY1
411    MTERP_ENTRY2
412    .fnend
413#endif
414
415
416/* ------------------------------ */
417    .balign 64
418.L_OP_MOVE: /* 0x01 */
419/* File: armv5te/OP_MOVE.S */
420    /* for move, move-object, long-to-int */
421    /* op vA, vB */
422    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
423    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
424    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
425    GET_VREG(r2, r1)                    @ r2<- fp[B]
426    and     r0, r0, #15
427    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
428    SET_VREG(r2, r0)                    @ fp[A]<- r2
429    GOTO_OPCODE(ip)                     @ execute next instruction
430
431
432/* ------------------------------ */
433    .balign 64
434.L_OP_MOVE_FROM16: /* 0x02 */
435/* File: armv5te/OP_MOVE_FROM16.S */
436    /* for: move/from16, move-object/from16 */
437    /* op vAA, vBBBB */
438    FETCH(r1, 1)                        @ r1<- BBBB
439    mov     r0, rINST, lsr #8           @ r0<- AA
440    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
441    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
442    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
443    SET_VREG(r2, r0)                    @ fp[AA]<- r2
444    GOTO_OPCODE(ip)                     @ jump to next instruction
445
446
447/* ------------------------------ */
448    .balign 64
449.L_OP_MOVE_16: /* 0x03 */
450/* File: armv5te/OP_MOVE_16.S */
451    /* for: move/16, move-object/16 */
452    /* op vAAAA, vBBBB */
453    FETCH(r1, 2)                        @ r1<- BBBB
454    FETCH(r0, 1)                        @ r0<- AAAA
455    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
456    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
457    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
458    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
459    GOTO_OPCODE(ip)                     @ jump to next instruction
460
461
462/* ------------------------------ */
463    .balign 64
464.L_OP_MOVE_WIDE: /* 0x04 */
465/* File: armv5te/OP_MOVE_WIDE.S */
466    /* move-wide vA, vB */
467    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
468    mov     r2, rINST, lsr #8           @ r2<- A(+)
469    mov     r3, rINST, lsr #12          @ r3<- B
470    and     r2, r2, #15
471    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
472    add     r2, rFP, r2, lsl #2         @ r2<- &fp[A]
473    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[B]
474    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
475    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
476    stmia   r2, {r0-r1}                 @ fp[A]<- r0/r1
477    GOTO_OPCODE(ip)                     @ jump to next instruction
478
479
480/* ------------------------------ */
481    .balign 64
482.L_OP_MOVE_WIDE_FROM16: /* 0x05 */
483/* File: armv5te/OP_MOVE_WIDE_FROM16.S */
484    /* move-wide/from16 vAA, vBBBB */
485    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
486    FETCH(r3, 1)                        @ r3<- BBBB
487    mov     r2, rINST, lsr #8           @ r2<- AA
488    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
489    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
490    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
491    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
492    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
493    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
494    GOTO_OPCODE(ip)                     @ jump to next instruction
495
496
497/* ------------------------------ */
498    .balign 64
499.L_OP_MOVE_WIDE_16: /* 0x06 */
500/* File: armv5te/OP_MOVE_WIDE_16.S */
501    /* move-wide/16 vAAAA, vBBBB */
502    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
503    FETCH(r3, 2)                        @ r3<- BBBB
504    FETCH(r2, 1)                        @ r2<- AAAA
505    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
506    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AAAA]
507    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
508    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
509    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
510    stmia   r2, {r0-r1}                 @ fp[AAAA]<- r0/r1
511    GOTO_OPCODE(ip)                     @ jump to next instruction
512
513
514/* ------------------------------ */
515    .balign 64
516.L_OP_MOVE_OBJECT: /* 0x07 */
517/* File: armv5te/OP_MOVE_OBJECT.S */
518/* File: armv5te/OP_MOVE.S */
519    /* for move, move-object, long-to-int */
520    /* op vA, vB */
521    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
522    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
523    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
524    GET_VREG(r2, r1)                    @ r2<- fp[B]
525    and     r0, r0, #15
526    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
527    SET_VREG(r2, r0)                    @ fp[A]<- r2
528    GOTO_OPCODE(ip)                     @ execute next instruction
529
530
531
532/* ------------------------------ */
533    .balign 64
534.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
535/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */
536/* File: armv5te/OP_MOVE_FROM16.S */
537    /* for: move/from16, move-object/from16 */
538    /* op vAA, vBBBB */
539    FETCH(r1, 1)                        @ r1<- BBBB
540    mov     r0, rINST, lsr #8           @ r0<- AA
541    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
542    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
543    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
544    SET_VREG(r2, r0)                    @ fp[AA]<- r2
545    GOTO_OPCODE(ip)                     @ jump to next instruction
546
547
548
549/* ------------------------------ */
550    .balign 64
551.L_OP_MOVE_OBJECT_16: /* 0x09 */
552/* File: armv5te/OP_MOVE_OBJECT_16.S */
553/* File: armv5te/OP_MOVE_16.S */
554    /* for: move/16, move-object/16 */
555    /* op vAAAA, vBBBB */
556    FETCH(r1, 2)                        @ r1<- BBBB
557    FETCH(r0, 1)                        @ r0<- AAAA
558    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
559    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
560    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
561    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
562    GOTO_OPCODE(ip)                     @ jump to next instruction
563
564
565
566/* ------------------------------ */
567    .balign 64
568.L_OP_MOVE_RESULT: /* 0x0a */
569/* File: armv5te/OP_MOVE_RESULT.S */
570    /* for: move-result, move-result-object */
571    /* op vAA */
572    mov     r2, rINST, lsr #8           @ r2<- AA
573    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
574    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
575    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
576    SET_VREG(r0, r2)                    @ fp[AA]<- r0
577    GOTO_OPCODE(ip)                     @ jump to next instruction
578
579
580/* ------------------------------ */
581    .balign 64
582.L_OP_MOVE_RESULT_WIDE: /* 0x0b */
583/* File: armv5te/OP_MOVE_RESULT_WIDE.S */
584    /* move-result-wide vAA */
585    mov     r2, rINST, lsr #8           @ r2<- AA
586    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
587    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
588    ldmia   r3, {r0-r1}                 @ r0/r1<- retval.j
589    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
590    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
591    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
592    GOTO_OPCODE(ip)                     @ jump to next instruction
593
594
595/* ------------------------------ */
596    .balign 64
597.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
598/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */
599/* File: armv5te/OP_MOVE_RESULT.S */
600    /* for: move-result, move-result-object */
601    /* op vAA */
602    mov     r2, rINST, lsr #8           @ r2<- AA
603    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
604    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
605    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
606    SET_VREG(r0, r2)                    @ fp[AA]<- r0
607    GOTO_OPCODE(ip)                     @ jump to next instruction
608
609
610
611/* ------------------------------ */
612    .balign 64
613.L_OP_MOVE_EXCEPTION: /* 0x0d */
614/* File: armv5te/OP_MOVE_EXCEPTION.S */
615    /* move-exception vAA */
616    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
617    mov     r2, rINST, lsr #8           @ r2<- AA
618    ldr     r3, [r0, #offThread_exception]  @ r3<- dvmGetException bypass
619    mov     r1, #0                      @ r1<- 0
620    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
621    SET_VREG(r3, r2)                    @ fp[AA]<- exception obj
622    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
623    str     r1, [r0, #offThread_exception]  @ dvmClearException bypass
624    GOTO_OPCODE(ip)                     @ jump to next instruction
625
626
627/* ------------------------------ */
628    .balign 64
629.L_OP_RETURN_VOID: /* 0x0e */
630/* File: armv5te/OP_RETURN_VOID.S */
631    b       common_returnFromMethod
632
633
634/* ------------------------------ */
635    .balign 64
636.L_OP_RETURN: /* 0x0f */
637/* File: armv5te/OP_RETURN.S */
638    /*
639     * Return a 32-bit value.  Copies the return value into the "glue"
640     * structure, then jumps to the return handler.
641     *
642     * for: return, return-object
643     */
644    /* op vAA */
645    mov     r2, rINST, lsr #8           @ r2<- AA
646    GET_VREG(r0, r2)                    @ r0<- vAA
647    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
648    b       common_returnFromMethod
649
650
651/* ------------------------------ */
652    .balign 64
653.L_OP_RETURN_WIDE: /* 0x10 */
654/* File: armv5te/OP_RETURN_WIDE.S */
655    /*
656     * Return a 64-bit value.  Copies the return value into the "glue"
657     * structure, then jumps to the return handler.
658     */
659    /* return-wide vAA */
660    mov     r2, rINST, lsr #8           @ r2<- AA
661    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
662    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
663    ldmia   r2, {r0-r1}                 @ r0/r1 <- vAA/vAA+1
664    stmia   r3, {r0-r1}                 @ retval<- r0/r1
665    b       common_returnFromMethod
666
667
668/* ------------------------------ */
669    .balign 64
670.L_OP_RETURN_OBJECT: /* 0x11 */
671/* File: armv5te/OP_RETURN_OBJECT.S */
672/* File: armv5te/OP_RETURN.S */
673    /*
674     * Return a 32-bit value.  Copies the return value into the "glue"
675     * structure, then jumps to the return handler.
676     *
677     * for: return, return-object
678     */
679    /* op vAA */
680    mov     r2, rINST, lsr #8           @ r2<- AA
681    GET_VREG(r0, r2)                    @ r0<- vAA
682    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
683    b       common_returnFromMethod
684
685
686
687/* ------------------------------ */
688    .balign 64
689.L_OP_CONST_4: /* 0x12 */
690/* File: armv5te/OP_CONST_4.S */
691    /* const/4 vA, #+B */
692    mov     r1, rINST, lsl #16          @ r1<- Bxxx0000
693    mov     r0, rINST, lsr #8           @ r0<- A+
694    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
695    mov     r1, r1, asr #28             @ r1<- sssssssB (sign-extended)
696    and     r0, r0, #15
697    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
698    SET_VREG(r1, r0)                    @ fp[A]<- r1
699    GOTO_OPCODE(ip)                     @ execute next instruction
700
701
702/* ------------------------------ */
703    .balign 64
704.L_OP_CONST_16: /* 0x13 */
705/* File: armv5te/OP_CONST_16.S */
706    /* const/16 vAA, #+BBBB */
707    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
708    mov     r3, rINST, lsr #8           @ r3<- AA
709    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
710    SET_VREG(r0, r3)                    @ vAA<- r0
711    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
712    GOTO_OPCODE(ip)                     @ jump to next instruction
713
714
715/* ------------------------------ */
716    .balign 64
717.L_OP_CONST: /* 0x14 */
718/* File: armv5te/OP_CONST.S */
719    /* const vAA, #+BBBBbbbb */
720    mov     r3, rINST, lsr #8           @ r3<- AA
721    FETCH(r0, 1)                        @ r0<- bbbb (low)
722    FETCH(r1, 2)                        @ r1<- BBBB (high)
723    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
724    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
725    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
726    SET_VREG(r0, r3)                    @ vAA<- r0
727    GOTO_OPCODE(ip)                     @ jump to next instruction
728
729
730/* ------------------------------ */
731    .balign 64
732.L_OP_CONST_HIGH16: /* 0x15 */
733/* File: armv5te/OP_CONST_HIGH16.S */
734    /* const/high16 vAA, #+BBBB0000 */
735    FETCH(r0, 1)                        @ r0<- 0000BBBB (zero-extended)
736    mov     r3, rINST, lsr #8           @ r3<- AA
737    mov     r0, r0, lsl #16             @ r0<- BBBB0000
738    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
739    SET_VREG(r0, r3)                    @ vAA<- r0
740    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
741    GOTO_OPCODE(ip)                     @ jump to next instruction
742
743
744/* ------------------------------ */
745    .balign 64
746.L_OP_CONST_WIDE_16: /* 0x16 */
747/* File: armv5te/OP_CONST_WIDE_16.S */
748    /* const-wide/16 vAA, #+BBBB */
749    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
750    mov     r3, rINST, lsr #8           @ r3<- AA
751    mov     r1, r0, asr #31             @ r1<- ssssssss
752    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
753    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
754    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
755    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
756    GOTO_OPCODE(ip)                     @ jump to next instruction
757
758
759/* ------------------------------ */
760    .balign 64
761.L_OP_CONST_WIDE_32: /* 0x17 */
762/* File: armv5te/OP_CONST_WIDE_32.S */
763    /* const-wide/32 vAA, #+BBBBbbbb */
764    FETCH(r0, 1)                        @ r0<- 0000bbbb (low)
765    mov     r3, rINST, lsr #8           @ r3<- AA
766    FETCH_S(r2, 2)                      @ r2<- ssssBBBB (high)
767    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
768    orr     r0, r0, r2, lsl #16         @ r0<- BBBBbbbb
769    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
770    mov     r1, r0, asr #31             @ r1<- ssssssss
771    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
772    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
773    GOTO_OPCODE(ip)                     @ jump to next instruction
774
775
776/* ------------------------------ */
777    .balign 64
778.L_OP_CONST_WIDE: /* 0x18 */
779/* File: armv5te/OP_CONST_WIDE.S */
780    /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
781    FETCH(r0, 1)                        @ r0<- bbbb (low)
782    FETCH(r1, 2)                        @ r1<- BBBB (low middle)
783    FETCH(r2, 3)                        @ r2<- hhhh (high middle)
784    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb (low word)
785    FETCH(r3, 4)                        @ r3<- HHHH (high)
786    mov     r9, rINST, lsr #8           @ r9<- AA
787    orr     r1, r2, r3, lsl #16         @ r1<- HHHHhhhh (high word)
788    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
789    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
790    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
791    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
792    GOTO_OPCODE(ip)                     @ jump to next instruction
793
794
795/* ------------------------------ */
796    .balign 64
797.L_OP_CONST_WIDE_HIGH16: /* 0x19 */
798/* File: armv5te/OP_CONST_WIDE_HIGH16.S */
799    /* const-wide/high16 vAA, #+BBBB000000000000 */
800    FETCH(r1, 1)                        @ r1<- 0000BBBB (zero-extended)
801    mov     r3, rINST, lsr #8           @ r3<- AA
802    mov     r0, #0                      @ r0<- 00000000
803    mov     r1, r1, lsl #16             @ r1<- BBBB0000
804    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
805    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
806    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
807    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
808    GOTO_OPCODE(ip)                     @ jump to next instruction
809
810
811/* ------------------------------ */
812    .balign 64
813.L_OP_CONST_STRING: /* 0x1a */
814/* File: armv5te/OP_CONST_STRING.S */
815    /* const/string vAA, String@BBBB */
816    FETCH(r1, 1)                        @ r1<- BBBB
817    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
818    mov     r9, rINST, lsr #8           @ r9<- AA
819    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
820    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
821    cmp     r0, #0                      @ not yet resolved?
822    beq     .LOP_CONST_STRING_resolve
823    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
824    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
825    SET_VREG(r0, r9)                    @ vAA<- r0
826    GOTO_OPCODE(ip)                     @ jump to next instruction
827
828/* ------------------------------ */
829    .balign 64
830.L_OP_CONST_STRING_JUMBO: /* 0x1b */
831/* File: armv5te/OP_CONST_STRING_JUMBO.S */
832    /* const/string vAA, String@BBBBBBBB */
833    FETCH(r0, 1)                        @ r0<- bbbb (low)
834    FETCH(r1, 2)                        @ r1<- BBBB (high)
835    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
836    mov     r9, rINST, lsr #8           @ r9<- AA
837    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
838    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
839    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
840    cmp     r0, #0
841    beq     .LOP_CONST_STRING_JUMBO_resolve
842    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
843    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
844    SET_VREG(r0, r9)                    @ vAA<- r0
845    GOTO_OPCODE(ip)                     @ jump to next instruction
846
847/* ------------------------------ */
848    .balign 64
849.L_OP_CONST_CLASS: /* 0x1c */
850/* File: armv5te/OP_CONST_CLASS.S */
851    /* const/class vAA, Class@BBBB */
852    FETCH(r1, 1)                        @ r1<- BBBB
853    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
854    mov     r9, rINST, lsr #8           @ r9<- AA
855    ldr     r2, [r2, #offDvmDex_pResClasses]   @ r2<- dvmDex->pResClasses
856    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResClasses[BBBB]
857    cmp     r0, #0                      @ not yet resolved?
858    beq     .LOP_CONST_CLASS_resolve
859    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
860    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
861    SET_VREG(r0, r9)                    @ vAA<- r0
862    GOTO_OPCODE(ip)                     @ jump to next instruction
863
864/* ------------------------------ */
865    .balign 64
866.L_OP_MONITOR_ENTER: /* 0x1d */
867/* File: armv5te/OP_MONITOR_ENTER.S */
868    /*
869     * Synchronize on an object.
870     */
871    /* monitor-enter vAA */
872    mov     r2, rINST, lsr #8           @ r2<- AA
873    GET_VREG(r1, r2)                    @ r1<- vAA (object)
874    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
875    cmp     r1, #0                      @ null object?
876    EXPORT_PC()                         @ need for precise GC, MONITOR_TRACKING
877    beq     common_errNullObject        @ null object, throw an exception
878    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
879    bl      dvmLockObject               @ call(self, obj)
880#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */
881    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
882    ldr     r1, [r0, #offThread_exception] @ check for exception
883    cmp     r1, #0
884    bne     common_exceptionThrown      @ exception raised, bail out
885#endif
886    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
887    GOTO_OPCODE(ip)                     @ jump to next instruction
888
889
890/* ------------------------------ */
891    .balign 64
892.L_OP_MONITOR_EXIT: /* 0x1e */
893/* File: armv5te/OP_MONITOR_EXIT.S */
894    /*
895     * Unlock an object.
896     *
897     * Exceptions that occur when unlocking a monitor need to appear as
898     * if they happened at the following instruction.  See the Dalvik
899     * instruction spec.
900     */
901    /* monitor-exit vAA */
902    mov     r2, rINST, lsr #8           @ r2<- AA
903    EXPORT_PC()                         @ before fetch: export the PC
904    GET_VREG(r1, r2)                    @ r1<- vAA (object)
905    cmp     r1, #0                      @ null object?
906    beq     common_errNullObject        @ yes
907    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
908    bl      dvmUnlockObject             @ r0<- success for unlock(self, obj)
909    cmp     r0, #0                      @ failed?
910    beq     common_exceptionThrown      @ yes, exception is pending
911    FETCH_ADVANCE_INST(1)               @ before throw: advance rPC, load rINST
912    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
913    GOTO_OPCODE(ip)                     @ jump to next instruction
914
915
916/* ------------------------------ */
917    .balign 64
918.L_OP_CHECK_CAST: /* 0x1f */
919/* File: armv5te/OP_CHECK_CAST.S */
920    /*
921     * Check to see if a cast from one class to another is allowed.
922     */
923    /* check-cast vAA, class@BBBB */
924    mov     r3, rINST, lsr #8           @ r3<- AA
925    FETCH(r2, 1)                        @ r2<- BBBB
926    GET_VREG(r9, r3)                    @ r9<- object
927    ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- pDvmDex
928    cmp     r9, #0                      @ is object null?
929    ldr     r0, [r0, #offDvmDex_pResClasses]    @ r0<- pDvmDex->pResClasses
930    beq     .LOP_CHECK_CAST_okay            @ null obj, cast always succeeds
931    ldr     r1, [r0, r2, lsl #2]        @ r1<- resolved class
932    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
933    cmp     r1, #0                      @ have we resolved this before?
934    beq     .LOP_CHECK_CAST_resolve         @ not resolved, do it now
935.LOP_CHECK_CAST_resolved:
936    cmp     r0, r1                      @ same class (trivial success)?
937    bne     .LOP_CHECK_CAST_fullcheck       @ no, do full check
938.LOP_CHECK_CAST_okay:
939    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
940    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
941    GOTO_OPCODE(ip)                     @ jump to next instruction
942
943/* ------------------------------ */
944    .balign 64
945.L_OP_INSTANCE_OF: /* 0x20 */
946/* File: armv5te/OP_INSTANCE_OF.S */
947    /*
948     * Check to see if an object reference is an instance of a class.
949     *
950     * Most common situation is a non-null object, being compared against
951     * an already-resolved class.
952     */
953    /* instance-of vA, vB, class@CCCC */
954    mov     r3, rINST, lsr #12          @ r3<- B
955    mov     r9, rINST, lsr #8           @ r9<- A+
956    GET_VREG(r0, r3)                    @ r0<- vB (object)
957    and     r9, r9, #15                 @ r9<- A
958    cmp     r0, #0                      @ is object null?
959    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- pDvmDex
960    beq     .LOP_INSTANCE_OF_store           @ null obj, not an instance, store r0
961    FETCH(r3, 1)                        @ r3<- CCCC
962    ldr     r2, [r2, #offDvmDex_pResClasses]    @ r2<- pDvmDex->pResClasses
963    ldr     r1, [r2, r3, lsl #2]        @ r1<- resolved class
964    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
965    cmp     r1, #0                      @ have we resolved this before?
966    beq     .LOP_INSTANCE_OF_resolve         @ not resolved, do it now
967.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class
968    cmp     r0, r1                      @ same class (trivial success)?
969    beq     .LOP_INSTANCE_OF_trivial         @ yes, trivial finish
970    b       .LOP_INSTANCE_OF_fullcheck       @ no, do full check
971
972/* ------------------------------ */
973    .balign 64
974.L_OP_ARRAY_LENGTH: /* 0x21 */
975/* File: armv5te/OP_ARRAY_LENGTH.S */
976    /*
977     * Return the length of an array.
978     */
979    mov     r1, rINST, lsr #12          @ r1<- B
980    mov     r2, rINST, lsr #8           @ r2<- A+
981    GET_VREG(r0, r1)                    @ r0<- vB (object ref)
982    and     r2, r2, #15                 @ r2<- A
983    cmp     r0, #0                      @ is object null?
984    beq     common_errNullObject        @ yup, fail
985    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
986    ldr     r3, [r0, #offArrayObject_length]    @ r3<- array length
987    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
988    SET_VREG(r3, r2)                    @ vB<- length
989    GOTO_OPCODE(ip)                     @ jump to next instruction
990
991
992/* ------------------------------ */
993    .balign 64
994.L_OP_NEW_INSTANCE: /* 0x22 */
995/* File: armv5te/OP_NEW_INSTANCE.S */
996    /*
997     * Create a new instance of a class.
998     */
999    /* new-instance vAA, class@BBBB */
1000    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1001    FETCH(r1, 1)                        @ r1<- BBBB
1002    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1003    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1004    EXPORT_PC()                         @ req'd for init, resolve, alloc
1005    cmp     r0, #0                      @ already resolved?
1006    beq     .LOP_NEW_INSTANCE_resolve         @ no, resolve it now
1007.LOP_NEW_INSTANCE_resolved:   @ r0=class
1008    ldrb    r1, [r0, #offClassObject_status]    @ r1<- ClassStatus enum
1009    cmp     r1, #CLASS_INITIALIZED      @ has class been initialized?
1010    bne     .LOP_NEW_INSTANCE_needinit        @ no, init class now
1011.LOP_NEW_INSTANCE_initialized: @ r0=class
1012    mov     r1, #ALLOC_DONT_TRACK       @ flags for alloc call
1013    bl      dvmAllocObject              @ r0<- new object
1014    b       .LOP_NEW_INSTANCE_finish          @ continue
1015
1016/* ------------------------------ */
1017    .balign 64
1018.L_OP_NEW_ARRAY: /* 0x23 */
1019/* File: armv5te/OP_NEW_ARRAY.S */
1020    /*
1021     * Allocate an array of objects, specified with the array class
1022     * and a count.
1023     *
1024     * The verifier guarantees that this is an array class, so we don't
1025     * check for it here.
1026     */
1027    /* new-array vA, vB, class@CCCC */
1028    mov     r0, rINST, lsr #12          @ r0<- B
1029    FETCH(r2, 1)                        @ r2<- CCCC
1030    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1031    GET_VREG(r1, r0)                    @ r1<- vB (array length)
1032    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1033    cmp     r1, #0                      @ check length
1034    ldr     r0, [r3, r2, lsl #2]        @ r0<- resolved class
1035    bmi     common_errNegativeArraySize @ negative length, bail
1036    cmp     r0, #0                      @ already resolved?
1037    EXPORT_PC()                         @ req'd for resolve, alloc
1038    bne     .LOP_NEW_ARRAY_finish          @ resolved, continue
1039    b       .LOP_NEW_ARRAY_resolve         @ do resolve now
1040
1041/* ------------------------------ */
1042    .balign 64
1043.L_OP_FILLED_NEW_ARRAY: /* 0x24 */
1044/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1045    /*
1046     * Create a new array with elements filled from registers.
1047     *
1048     * for: filled-new-array, filled-new-array/range
1049     */
1050    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1051    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1052    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1053    FETCH(r1, 1)                        @ r1<- BBBB
1054    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1055    EXPORT_PC()                         @ need for resolve and alloc
1056    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1057    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1058    cmp     r0, #0                      @ already resolved?
1059    bne     .LOP_FILLED_NEW_ARRAY_continue        @ yes, continue on
10608:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1061    mov     r2, #0                      @ r2<- false
1062    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1063    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1064    cmp     r0, #0                      @ got null?
1065    beq     common_exceptionThrown      @ yes, handle exception
1066    b       .LOP_FILLED_NEW_ARRAY_continue
1067
1068/* ------------------------------ */
1069    .balign 64
1070.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
1071/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */
1072/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1073    /*
1074     * Create a new array with elements filled from registers.
1075     *
1076     * for: filled-new-array, filled-new-array/range
1077     */
1078    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1079    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1080    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1081    FETCH(r1, 1)                        @ r1<- BBBB
1082    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1083    EXPORT_PC()                         @ need for resolve and alloc
1084    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1085    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1086    cmp     r0, #0                      @ already resolved?
1087    bne     .LOP_FILLED_NEW_ARRAY_RANGE_continue        @ yes, continue on
10888:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1089    mov     r2, #0                      @ r2<- false
1090    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1091    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1092    cmp     r0, #0                      @ got null?
1093    beq     common_exceptionThrown      @ yes, handle exception
1094    b       .LOP_FILLED_NEW_ARRAY_RANGE_continue
1095
1096
1097/* ------------------------------ */
1098    .balign 64
1099.L_OP_FILL_ARRAY_DATA: /* 0x26 */
1100/* File: armv5te/OP_FILL_ARRAY_DATA.S */
1101    /* fill-array-data vAA, +BBBBBBBB */
1102    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1103    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1104    mov     r3, rINST, lsr #8           @ r3<- AA
1105    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
1106    GET_VREG(r0, r3)                    @ r0<- vAA (array object)
1107    add     r1, rPC, r1, lsl #1         @ r1<- PC + BBBBbbbb*2 (array data off.)
1108    EXPORT_PC();
1109    bl      dvmInterpHandleFillArrayData@ fill the array with predefined data
1110    cmp     r0, #0                      @ 0 means an exception is thrown
1111    beq     common_exceptionThrown      @ has exception
1112    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
1113    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1114    GOTO_OPCODE(ip)                     @ jump to next instruction
1115
1116/* ------------------------------ */
1117    .balign 64
1118.L_OP_THROW: /* 0x27 */
1119/* File: armv5te/OP_THROW.S */
1120    /*
1121     * Throw an exception object in the current thread.
1122     */
1123    /* throw vAA */
1124    mov     r2, rINST, lsr #8           @ r2<- AA
1125    GET_VREG(r1, r2)                    @ r1<- vAA (exception object)
1126    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
1127    cmp     r1, #0                      @ null object?
1128    beq     common_errNullObject        @ yes, throw an NPE instead
1129    @ bypass dvmSetException, just store it
1130    str     r1, [r0, #offThread_exception]  @ thread->exception<- obj
1131    b       common_exceptionThrown
1132
1133
1134/* ------------------------------ */
1135    .balign 64
1136.L_OP_GOTO: /* 0x28 */
1137/* File: armv5te/OP_GOTO.S */
1138    /*
1139     * Unconditional branch, 8-bit offset.
1140     *
1141     * The branch distance is a signed code-unit offset, which we need to
1142     * double to get a byte offset.
1143     */
1144    /* goto +AA */
1145    mov     r0, rINST, lsl #16          @ r0<- AAxx0000
1146    movs    r9, r0, asr #24             @ r9<- ssssssAA (sign-extended)
1147    mov     r9, r9, lsl #1              @ r9<- byte offset
1148    bmi     common_backwardBranch       @ backward branch, do periodic checks
1149#if defined(WITH_JIT)
1150    GET_JIT_PROF_TABLE(r0)
1151    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1152    cmp     r0,#0
1153    bne     common_updateProfile
1154    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1155    GOTO_OPCODE(ip)                     @ jump to next instruction
1156#else
1157    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1158    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1159    GOTO_OPCODE(ip)                     @ jump to next instruction
1160#endif
1161
1162/* ------------------------------ */
1163    .balign 64
1164.L_OP_GOTO_16: /* 0x29 */
1165/* File: armv5te/OP_GOTO_16.S */
1166    /*
1167     * Unconditional branch, 16-bit offset.
1168     *
1169     * The branch distance is a signed code-unit offset, which we need to
1170     * double to get a byte offset.
1171     */
1172    /* goto/16 +AAAA */
1173    FETCH_S(r0, 1)                      @ r0<- ssssAAAA (sign-extended)
1174    movs    r9, r0, asl #1              @ r9<- byte offset, check sign
1175    bmi     common_backwardBranch       @ backward branch, do periodic checks
1176#if defined(WITH_JIT)
1177    GET_JIT_PROF_TABLE(r0)
1178    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1179    cmp     r0,#0
1180    bne     common_updateProfile
1181    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1182    GOTO_OPCODE(ip)                     @ jump to next instruction
1183#else
1184    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1185    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1186    GOTO_OPCODE(ip)                     @ jump to next instruction
1187#endif
1188
1189
1190/* ------------------------------ */
1191    .balign 64
1192.L_OP_GOTO_32: /* 0x2a */
1193/* File: armv5te/OP_GOTO_32.S */
1194    /*
1195     * Unconditional branch, 32-bit offset.
1196     *
1197     * The branch distance is a signed code-unit offset, which we need to
1198     * double to get a byte offset.
1199     *
1200     * Unlike most opcodes, this one is allowed to branch to itself, so
1201     * our "backward branch" test must be "<=0" instead of "<0".  The ORRS
1202     * instruction doesn't affect the V flag, so we need to clear it
1203     * explicitly.
1204     */
1205    /* goto/32 +AAAAAAAA */
1206    FETCH(r0, 1)                        @ r0<- aaaa (lo)
1207    FETCH(r1, 2)                        @ r1<- AAAA (hi)
1208    cmp     ip, ip                      @ (clear V flag during stall)
1209    orrs    r0, r0, r1, lsl #16         @ r0<- AAAAaaaa, check sign
1210    mov     r9, r0, asl #1              @ r9<- byte offset
1211    ble     common_backwardBranch       @ backward branch, do periodic checks
1212#if defined(WITH_JIT)
1213    GET_JIT_PROF_TABLE(r0)
1214    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1215    cmp     r0,#0
1216    bne     common_updateProfile
1217    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1218    GOTO_OPCODE(ip)                     @ jump to next instruction
1219#else
1220    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1221    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1222    GOTO_OPCODE(ip)                     @ jump to next instruction
1223#endif
1224
1225/* ------------------------------ */
1226    .balign 64
1227.L_OP_PACKED_SWITCH: /* 0x2b */
1228/* File: armv5te/OP_PACKED_SWITCH.S */
1229    /*
1230     * Handle a packed-switch or sparse-switch instruction.  In both cases
1231     * we decode it and hand it off to a helper function.
1232     *
1233     * We don't really expect backward branches in a switch statement, but
1234     * they're perfectly legal, so we check for them here.
1235     *
1236     * for: packed-switch, sparse-switch
1237     */
1238    /* op vAA, +BBBB */
1239    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1240    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1241    mov     r3, rINST, lsr #8           @ r3<- AA
1242    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1243    GET_VREG(r1, r3)                    @ r1<- vAA
1244    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1245    bl      dvmInterpHandlePackedSwitch                       @ r0<- code-unit branch offset
1246    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1247    bmi     common_backwardBranch       @ backward branch, do periodic checks
1248    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1249#if defined(WITH_JIT)
1250    GET_JIT_PROF_TABLE(r0)
1251    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1252    cmp     r0,#0
1253    bne     common_updateProfile
1254    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1255    GOTO_OPCODE(ip)                     @ jump to next instruction
1256#else
1257    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1258    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1259    GOTO_OPCODE(ip)                     @ jump to next instruction
1260#endif
1261
1262
1263/* ------------------------------ */
1264    .balign 64
1265.L_OP_SPARSE_SWITCH: /* 0x2c */
1266/* File: armv5te/OP_SPARSE_SWITCH.S */
1267/* File: armv5te/OP_PACKED_SWITCH.S */
1268    /*
1269     * Handle a packed-switch or sparse-switch instruction.  In both cases
1270     * we decode it and hand it off to a helper function.
1271     *
1272     * We don't really expect backward branches in a switch statement, but
1273     * they're perfectly legal, so we check for them here.
1274     *
1275     * for: packed-switch, sparse-switch
1276     */
1277    /* op vAA, +BBBB */
1278    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1279    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1280    mov     r3, rINST, lsr #8           @ r3<- AA
1281    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1282    GET_VREG(r1, r3)                    @ r1<- vAA
1283    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1284    bl      dvmInterpHandleSparseSwitch                       @ r0<- code-unit branch offset
1285    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1286    bmi     common_backwardBranch       @ backward branch, do periodic checks
1287    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1288#if defined(WITH_JIT)
1289    GET_JIT_PROF_TABLE(r0)
1290    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1291    cmp     r0,#0
1292    bne     common_updateProfile
1293    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1294    GOTO_OPCODE(ip)                     @ jump to next instruction
1295#else
1296    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1297    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1298    GOTO_OPCODE(ip)                     @ jump to next instruction
1299#endif
1300
1301
1302
1303/* ------------------------------ */
1304    .balign 64
1305.L_OP_CMPL_FLOAT: /* 0x2d */
1306/* File: arm-vfp/OP_CMPL_FLOAT.S */
1307    /*
1308     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1309     * destination register based on the results of the comparison.
1310     *
1311     * int compare(x, y) {
1312     *     if (x == y) {
1313     *         return 0;
1314     *     } else if (x > y) {
1315     *         return 1;
1316     *     } else if (x < y) {
1317     *         return -1;
1318     *     } else {
1319     *         return -1;
1320     *     }
1321     * }
1322     */
1323    /* op vAA, vBB, vCC */
1324    FETCH(r0, 1)                        @ r0<- CCBB
1325    mov     r9, rINST, lsr #8           @ r9<- AA
1326    and     r2, r0, #255                @ r2<- BB
1327    mov     r3, r0, lsr #8              @ r3<- CC
1328    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1329    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1330    flds    s0, [r2]                    @ s0<- vBB
1331    flds    s1, [r3]                    @ s1<- vCC
1332    fcmpes  s0, s1                      @ compare (vBB, vCC)
1333    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1334    mvn     r0, #0                      @ r0<- -1 (default)
1335    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1336    fmstat                              @ export status flags
1337    movgt   r0, #1                      @ (greater than) r1<- 1
1338    moveq   r0, #0                      @ (equal) r1<- 0
1339    b       .LOP_CMPL_FLOAT_finish          @ argh
1340
1341
1342/* ------------------------------ */
1343    .balign 64
1344.L_OP_CMPG_FLOAT: /* 0x2e */
1345/* File: arm-vfp/OP_CMPG_FLOAT.S */
1346    /*
1347     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1348     * destination register based on the results of the comparison.
1349     *
1350     * int compare(x, y) {
1351     *     if (x == y) {
1352     *         return 0;
1353     *     } else if (x < y) {
1354     *         return -1;
1355     *     } else if (x > y) {
1356     *         return 1;
1357     *     } else {
1358     *         return 1;
1359     *     }
1360     * }
1361     */
1362    /* op vAA, vBB, vCC */
1363    FETCH(r0, 1)                        @ r0<- CCBB
1364    mov     r9, rINST, lsr #8           @ r9<- AA
1365    and     r2, r0, #255                @ r2<- BB
1366    mov     r3, r0, lsr #8              @ r3<- CC
1367    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1368    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1369    flds    s0, [r2]                    @ s0<- vBB
1370    flds    s1, [r3]                    @ s1<- vCC
1371    fcmpes  s0, s1                      @ compare (vBB, vCC)
1372    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1373    mov     r0, #1                      @ r0<- 1 (default)
1374    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1375    fmstat                              @ export status flags
1376    mvnmi   r0, #0                      @ (less than) r1<- -1
1377    moveq   r0, #0                      @ (equal) r1<- 0
1378    b       .LOP_CMPG_FLOAT_finish          @ argh
1379
1380
1381/* ------------------------------ */
1382    .balign 64
1383.L_OP_CMPL_DOUBLE: /* 0x2f */
1384/* File: arm-vfp/OP_CMPL_DOUBLE.S */
1385    /*
1386     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1387     * destination register based on the results of the comparison.
1388     *
1389     * int compare(x, y) {
1390     *     if (x == y) {
1391     *         return 0;
1392     *     } else if (x > y) {
1393     *         return 1;
1394     *     } else if (x < y) {
1395     *         return -1;
1396     *     } else {
1397     *         return -1;
1398     *     }
1399     * }
1400     */
1401    /* op vAA, vBB, vCC */
1402    FETCH(r0, 1)                        @ r0<- CCBB
1403    mov     r9, rINST, lsr #8           @ r9<- AA
1404    and     r2, r0, #255                @ r2<- BB
1405    mov     r3, r0, lsr #8              @ r3<- CC
1406    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1407    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1408    fldd    d0, [r2]                    @ d0<- vBB
1409    fldd    d1, [r3]                    @ d1<- vCC
1410    fcmped  d0, d1                      @ compare (vBB, vCC)
1411    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1412    mvn     r0, #0                      @ r0<- -1 (default)
1413    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1414    fmstat                              @ export status flags
1415    movgt   r0, #1                      @ (greater than) r1<- 1
1416    moveq   r0, #0                      @ (equal) r1<- 0
1417    b       .LOP_CMPL_DOUBLE_finish          @ argh
1418
1419
1420/* ------------------------------ */
1421    .balign 64
1422.L_OP_CMPG_DOUBLE: /* 0x30 */
1423/* File: arm-vfp/OP_CMPG_DOUBLE.S */
1424    /*
1425     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1426     * destination register based on the results of the comparison.
1427     *
1428     * int compare(x, y) {
1429     *     if (x == y) {
1430     *         return 0;
1431     *     } else if (x < y) {
1432     *         return -1;
1433     *     } else if (x > y) {
1434     *         return 1;
1435     *     } else {
1436     *         return 1;
1437     *     }
1438     * }
1439     */
1440    /* op vAA, vBB, vCC */
1441    FETCH(r0, 1)                        @ r0<- CCBB
1442    mov     r9, rINST, lsr #8           @ r9<- AA
1443    and     r2, r0, #255                @ r2<- BB
1444    mov     r3, r0, lsr #8              @ r3<- CC
1445    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1446    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1447    fldd    d0, [r2]                    @ d0<- vBB
1448    fldd    d1, [r3]                    @ d1<- vCC
1449    fcmped  d0, d1                      @ compare (vBB, vCC)
1450    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1451    mov     r0, #1                      @ r0<- 1 (default)
1452    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1453    fmstat                              @ export status flags
1454    mvnmi   r0, #0                      @ (less than) r1<- -1
1455    moveq   r0, #0                      @ (equal) r1<- 0
1456    b       .LOP_CMPG_DOUBLE_finish          @ argh
1457
1458
1459/* ------------------------------ */
1460    .balign 64
1461.L_OP_CMP_LONG: /* 0x31 */
1462/* File: armv5te/OP_CMP_LONG.S */
1463    /*
1464     * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
1465     * register based on the results of the comparison.
1466     *
1467     * We load the full values with LDM, but in practice many values could
1468     * be resolved by only looking at the high word.  This could be made
1469     * faster or slower by splitting the LDM into a pair of LDRs.
1470     *
1471     * If we just wanted to set condition flags, we could do this:
1472     *  subs    ip, r0, r2
1473     *  sbcs    ip, r1, r3
1474     *  subeqs  ip, r0, r2
1475     * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
1476     * integer value, which we can do with 2 conditional mov/mvn instructions
1477     * (set 1, set -1; if they're equal we already have 0 in ip), giving
1478     * us a constant 5-cycle path plus a branch at the end to the
1479     * instruction epilogue code.  The multi-compare approach below needs
1480     * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
1481     * in the worst case (the 64-bit values are equal).
1482     */
1483    /* cmp-long vAA, vBB, vCC */
1484    FETCH(r0, 1)                        @ r0<- CCBB
1485    mov     r9, rINST, lsr #8           @ r9<- AA
1486    and     r2, r0, #255                @ r2<- BB
1487    mov     r3, r0, lsr #8              @ r3<- CC
1488    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
1489    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
1490    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1491    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
1492    cmp     r1, r3                      @ compare (vBB+1, vCC+1)
1493    blt     .LOP_CMP_LONG_less            @ signed compare on high part
1494    bgt     .LOP_CMP_LONG_greater
1495    subs    r1, r0, r2                  @ r1<- r0 - r2
1496    bhi     .LOP_CMP_LONG_greater         @ unsigned compare on low part
1497    bne     .LOP_CMP_LONG_less
1498    b       .LOP_CMP_LONG_finish          @ equal; r1 already holds 0
1499
1500/* ------------------------------ */
1501    .balign 64
1502.L_OP_IF_EQ: /* 0x32 */
1503/* File: armv5te/OP_IF_EQ.S */
1504/* File: armv5te/bincmp.S */
1505    /*
1506     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1507     * fragment that specifies the *reverse* comparison to perform, e.g.
1508     * for "if-le" you would use "gt".
1509     *
1510     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1511     */
1512    /* if-cmp vA, vB, +CCCC */
1513    mov     r0, rINST, lsr #8           @ r0<- A+
1514    mov     r1, rINST, lsr #12          @ r1<- B
1515    and     r0, r0, #15
1516    GET_VREG(r3, r1)                    @ r3<- vB
1517    GET_VREG(r2, r0)                    @ r2<- vA
1518    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1519    cmp     r2, r3                      @ compare (vA, vB)
1520    bne  1f                      @ branch to 1 if comparison failed
1521    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1522    movs    r9, r9, asl #1              @ convert to bytes, check sign
1523    bmi     common_backwardBranch       @ yes, do periodic checks
15241:
1525#if defined(WITH_JIT)
1526    GET_JIT_PROF_TABLE(r0)
1527    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1528    b        common_testUpdateProfile
1529#else
1530    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1531    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1532    GOTO_OPCODE(ip)                     @ jump to next instruction
1533#endif
1534
1535
1536
1537/* ------------------------------ */
1538    .balign 64
1539.L_OP_IF_NE: /* 0x33 */
1540/* File: armv5te/OP_IF_NE.S */
1541/* File: armv5te/bincmp.S */
1542    /*
1543     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1544     * fragment that specifies the *reverse* comparison to perform, e.g.
1545     * for "if-le" you would use "gt".
1546     *
1547     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1548     */
1549    /* if-cmp vA, vB, +CCCC */
1550    mov     r0, rINST, lsr #8           @ r0<- A+
1551    mov     r1, rINST, lsr #12          @ r1<- B
1552    and     r0, r0, #15
1553    GET_VREG(r3, r1)                    @ r3<- vB
1554    GET_VREG(r2, r0)                    @ r2<- vA
1555    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1556    cmp     r2, r3                      @ compare (vA, vB)
1557    beq  1f                      @ branch to 1 if comparison failed
1558    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1559    movs    r9, r9, asl #1              @ convert to bytes, check sign
1560    bmi     common_backwardBranch       @ yes, do periodic checks
15611:
1562#if defined(WITH_JIT)
1563    GET_JIT_PROF_TABLE(r0)
1564    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1565    b        common_testUpdateProfile
1566#else
1567    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1568    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1569    GOTO_OPCODE(ip)                     @ jump to next instruction
1570#endif
1571
1572
1573
1574/* ------------------------------ */
1575    .balign 64
1576.L_OP_IF_LT: /* 0x34 */
1577/* File: armv5te/OP_IF_LT.S */
1578/* File: armv5te/bincmp.S */
1579    /*
1580     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1581     * fragment that specifies the *reverse* comparison to perform, e.g.
1582     * for "if-le" you would use "gt".
1583     *
1584     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1585     */
1586    /* if-cmp vA, vB, +CCCC */
1587    mov     r0, rINST, lsr #8           @ r0<- A+
1588    mov     r1, rINST, lsr #12          @ r1<- B
1589    and     r0, r0, #15
1590    GET_VREG(r3, r1)                    @ r3<- vB
1591    GET_VREG(r2, r0)                    @ r2<- vA
1592    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1593    cmp     r2, r3                      @ compare (vA, vB)
1594    bge  1f                      @ branch to 1 if comparison failed
1595    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1596    movs    r9, r9, asl #1              @ convert to bytes, check sign
1597    bmi     common_backwardBranch       @ yes, do periodic checks
15981:
1599#if defined(WITH_JIT)
1600    GET_JIT_PROF_TABLE(r0)
1601    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1602    b        common_testUpdateProfile
1603#else
1604    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1605    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1606    GOTO_OPCODE(ip)                     @ jump to next instruction
1607#endif
1608
1609
1610
1611/* ------------------------------ */
1612    .balign 64
1613.L_OP_IF_GE: /* 0x35 */
1614/* File: armv5te/OP_IF_GE.S */
1615/* File: armv5te/bincmp.S */
1616    /*
1617     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1618     * fragment that specifies the *reverse* comparison to perform, e.g.
1619     * for "if-le" you would use "gt".
1620     *
1621     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1622     */
1623    /* if-cmp vA, vB, +CCCC */
1624    mov     r0, rINST, lsr #8           @ r0<- A+
1625    mov     r1, rINST, lsr #12          @ r1<- B
1626    and     r0, r0, #15
1627    GET_VREG(r3, r1)                    @ r3<- vB
1628    GET_VREG(r2, r0)                    @ r2<- vA
1629    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1630    cmp     r2, r3                      @ compare (vA, vB)
1631    blt  1f                      @ branch to 1 if comparison failed
1632    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1633    movs    r9, r9, asl #1              @ convert to bytes, check sign
1634    bmi     common_backwardBranch       @ yes, do periodic checks
16351:
1636#if defined(WITH_JIT)
1637    GET_JIT_PROF_TABLE(r0)
1638    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1639    b        common_testUpdateProfile
1640#else
1641    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1642    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1643    GOTO_OPCODE(ip)                     @ jump to next instruction
1644#endif
1645
1646
1647
1648/* ------------------------------ */
1649    .balign 64
1650.L_OP_IF_GT: /* 0x36 */
1651/* File: armv5te/OP_IF_GT.S */
1652/* File: armv5te/bincmp.S */
1653    /*
1654     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1655     * fragment that specifies the *reverse* comparison to perform, e.g.
1656     * for "if-le" you would use "gt".
1657     *
1658     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1659     */
1660    /* if-cmp vA, vB, +CCCC */
1661    mov     r0, rINST, lsr #8           @ r0<- A+
1662    mov     r1, rINST, lsr #12          @ r1<- B
1663    and     r0, r0, #15
1664    GET_VREG(r3, r1)                    @ r3<- vB
1665    GET_VREG(r2, r0)                    @ r2<- vA
1666    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1667    cmp     r2, r3                      @ compare (vA, vB)
1668    ble  1f                      @ branch to 1 if comparison failed
1669    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1670    movs    r9, r9, asl #1              @ convert to bytes, check sign
1671    bmi     common_backwardBranch       @ yes, do periodic checks
16721:
1673#if defined(WITH_JIT)
1674    GET_JIT_PROF_TABLE(r0)
1675    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1676    b        common_testUpdateProfile
1677#else
1678    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1679    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1680    GOTO_OPCODE(ip)                     @ jump to next instruction
1681#endif
1682
1683
1684
1685/* ------------------------------ */
1686    .balign 64
1687.L_OP_IF_LE: /* 0x37 */
1688/* File: armv5te/OP_IF_LE.S */
1689/* File: armv5te/bincmp.S */
1690    /*
1691     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1692     * fragment that specifies the *reverse* comparison to perform, e.g.
1693     * for "if-le" you would use "gt".
1694     *
1695     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1696     */
1697    /* if-cmp vA, vB, +CCCC */
1698    mov     r0, rINST, lsr #8           @ r0<- A+
1699    mov     r1, rINST, lsr #12          @ r1<- B
1700    and     r0, r0, #15
1701    GET_VREG(r3, r1)                    @ r3<- vB
1702    GET_VREG(r2, r0)                    @ r2<- vA
1703    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1704    cmp     r2, r3                      @ compare (vA, vB)
1705    bgt  1f                      @ branch to 1 if comparison failed
1706    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1707    movs    r9, r9, asl #1              @ convert to bytes, check sign
1708    bmi     common_backwardBranch       @ yes, do periodic checks
17091:
1710#if defined(WITH_JIT)
1711    GET_JIT_PROF_TABLE(r0)
1712    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1713    b        common_testUpdateProfile
1714#else
1715    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1716    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1717    GOTO_OPCODE(ip)                     @ jump to next instruction
1718#endif
1719
1720
1721
1722/* ------------------------------ */
1723    .balign 64
1724.L_OP_IF_EQZ: /* 0x38 */
1725/* File: armv5te/OP_IF_EQZ.S */
1726/* File: armv5te/zcmp.S */
1727    /*
1728     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1729     * fragment that specifies the *reverse* comparison to perform, e.g.
1730     * for "if-le" you would use "gt".
1731     *
1732     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1733     */
1734    /* if-cmp vAA, +BBBB */
1735    mov     r0, rINST, lsr #8           @ r0<- AA
1736    GET_VREG(r2, r0)                    @ r2<- vAA
1737    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1738    cmp     r2, #0                      @ compare (vA, 0)
1739    bne  1f                      @ branch to 1 if comparison failed
1740    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1741    movs    r9, r9, asl #1              @ convert to bytes, check sign
1742    bmi     common_backwardBranch       @ backward branch, do periodic checks
17431:
1744#if defined(WITH_JIT)
1745    GET_JIT_PROF_TABLE(r0)
1746    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1747    cmp     r0,#0
1748    bne     common_updateProfile
1749    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1750    GOTO_OPCODE(ip)                     @ jump to next instruction
1751#else
1752    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1753    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1754    GOTO_OPCODE(ip)                     @ jump to next instruction
1755#endif
1756
1757
1758
1759/* ------------------------------ */
1760    .balign 64
1761.L_OP_IF_NEZ: /* 0x39 */
1762/* File: armv5te/OP_IF_NEZ.S */
1763/* File: armv5te/zcmp.S */
1764    /*
1765     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1766     * fragment that specifies the *reverse* comparison to perform, e.g.
1767     * for "if-le" you would use "gt".
1768     *
1769     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1770     */
1771    /* if-cmp vAA, +BBBB */
1772    mov     r0, rINST, lsr #8           @ r0<- AA
1773    GET_VREG(r2, r0)                    @ r2<- vAA
1774    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1775    cmp     r2, #0                      @ compare (vA, 0)
1776    beq  1f                      @ branch to 1 if comparison failed
1777    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1778    movs    r9, r9, asl #1              @ convert to bytes, check sign
1779    bmi     common_backwardBranch       @ backward branch, do periodic checks
17801:
1781#if defined(WITH_JIT)
1782    GET_JIT_PROF_TABLE(r0)
1783    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1784    cmp     r0,#0
1785    bne     common_updateProfile
1786    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1787    GOTO_OPCODE(ip)                     @ jump to next instruction
1788#else
1789    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1790    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1791    GOTO_OPCODE(ip)                     @ jump to next instruction
1792#endif
1793
1794
1795
1796/* ------------------------------ */
1797    .balign 64
1798.L_OP_IF_LTZ: /* 0x3a */
1799/* File: armv5te/OP_IF_LTZ.S */
1800/* File: armv5te/zcmp.S */
1801    /*
1802     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1803     * fragment that specifies the *reverse* comparison to perform, e.g.
1804     * for "if-le" you would use "gt".
1805     *
1806     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1807     */
1808    /* if-cmp vAA, +BBBB */
1809    mov     r0, rINST, lsr #8           @ r0<- AA
1810    GET_VREG(r2, r0)                    @ r2<- vAA
1811    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1812    cmp     r2, #0                      @ compare (vA, 0)
1813    bge  1f                      @ branch to 1 if comparison failed
1814    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1815    movs    r9, r9, asl #1              @ convert to bytes, check sign
1816    bmi     common_backwardBranch       @ backward branch, do periodic checks
18171:
1818#if defined(WITH_JIT)
1819    GET_JIT_PROF_TABLE(r0)
1820    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1821    cmp     r0,#0
1822    bne     common_updateProfile
1823    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1824    GOTO_OPCODE(ip)                     @ jump to next instruction
1825#else
1826    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1827    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1828    GOTO_OPCODE(ip)                     @ jump to next instruction
1829#endif
1830
1831
1832
1833/* ------------------------------ */
1834    .balign 64
1835.L_OP_IF_GEZ: /* 0x3b */
1836/* File: armv5te/OP_IF_GEZ.S */
1837/* File: armv5te/zcmp.S */
1838    /*
1839     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1840     * fragment that specifies the *reverse* comparison to perform, e.g.
1841     * for "if-le" you would use "gt".
1842     *
1843     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1844     */
1845    /* if-cmp vAA, +BBBB */
1846    mov     r0, rINST, lsr #8           @ r0<- AA
1847    GET_VREG(r2, r0)                    @ r2<- vAA
1848    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1849    cmp     r2, #0                      @ compare (vA, 0)
1850    blt  1f                      @ branch to 1 if comparison failed
1851    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1852    movs    r9, r9, asl #1              @ convert to bytes, check sign
1853    bmi     common_backwardBranch       @ backward branch, do periodic checks
18541:
1855#if defined(WITH_JIT)
1856    GET_JIT_PROF_TABLE(r0)
1857    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1858    cmp     r0,#0
1859    bne     common_updateProfile
1860    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1861    GOTO_OPCODE(ip)                     @ jump to next instruction
1862#else
1863    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1864    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1865    GOTO_OPCODE(ip)                     @ jump to next instruction
1866#endif
1867
1868
1869
1870/* ------------------------------ */
1871    .balign 64
1872.L_OP_IF_GTZ: /* 0x3c */
1873/* File: armv5te/OP_IF_GTZ.S */
1874/* File: armv5te/zcmp.S */
1875    /*
1876     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1877     * fragment that specifies the *reverse* comparison to perform, e.g.
1878     * for "if-le" you would use "gt".
1879     *
1880     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1881     */
1882    /* if-cmp vAA, +BBBB */
1883    mov     r0, rINST, lsr #8           @ r0<- AA
1884    GET_VREG(r2, r0)                    @ r2<- vAA
1885    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1886    cmp     r2, #0                      @ compare (vA, 0)
1887    ble  1f                      @ branch to 1 if comparison failed
1888    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1889    movs    r9, r9, asl #1              @ convert to bytes, check sign
1890    bmi     common_backwardBranch       @ backward branch, do periodic checks
18911:
1892#if defined(WITH_JIT)
1893    GET_JIT_PROF_TABLE(r0)
1894    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1895    cmp     r0,#0
1896    bne     common_updateProfile
1897    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1898    GOTO_OPCODE(ip)                     @ jump to next instruction
1899#else
1900    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1901    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1902    GOTO_OPCODE(ip)                     @ jump to next instruction
1903#endif
1904
1905
1906
1907/* ------------------------------ */
1908    .balign 64
1909.L_OP_IF_LEZ: /* 0x3d */
1910/* File: armv5te/OP_IF_LEZ.S */
1911/* File: armv5te/zcmp.S */
1912    /*
1913     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1914     * fragment that specifies the *reverse* comparison to perform, e.g.
1915     * for "if-le" you would use "gt".
1916     *
1917     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1918     */
1919    /* if-cmp vAA, +BBBB */
1920    mov     r0, rINST, lsr #8           @ r0<- AA
1921    GET_VREG(r2, r0)                    @ r2<- vAA
1922    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1923    cmp     r2, #0                      @ compare (vA, 0)
1924    bgt  1f                      @ branch to 1 if comparison failed
1925    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1926    movs    r9, r9, asl #1              @ convert to bytes, check sign
1927    bmi     common_backwardBranch       @ backward branch, do periodic checks
19281:
1929#if defined(WITH_JIT)
1930    GET_JIT_PROF_TABLE(r0)
1931    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1932    cmp     r0,#0
1933    bne     common_updateProfile
1934    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1935    GOTO_OPCODE(ip)                     @ jump to next instruction
1936#else
1937    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1938    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1939    GOTO_OPCODE(ip)                     @ jump to next instruction
1940#endif
1941
1942
1943
1944/* ------------------------------ */
1945    .balign 64
1946.L_OP_UNUSED_3E: /* 0x3e */
1947/* File: armv5te/OP_UNUSED_3E.S */
1948/* File: armv5te/unused.S */
1949    bl      common_abort
1950
1951
1952
1953/* ------------------------------ */
1954    .balign 64
1955.L_OP_UNUSED_3F: /* 0x3f */
1956/* File: armv5te/OP_UNUSED_3F.S */
1957/* File: armv5te/unused.S */
1958    bl      common_abort
1959
1960
1961
1962/* ------------------------------ */
1963    .balign 64
1964.L_OP_UNUSED_40: /* 0x40 */
1965/* File: armv5te/OP_UNUSED_40.S */
1966/* File: armv5te/unused.S */
1967    bl      common_abort
1968
1969
1970
1971/* ------------------------------ */
1972    .balign 64
1973.L_OP_UNUSED_41: /* 0x41 */
1974/* File: armv5te/OP_UNUSED_41.S */
1975/* File: armv5te/unused.S */
1976    bl      common_abort
1977
1978
1979
1980/* ------------------------------ */
1981    .balign 64
1982.L_OP_UNUSED_42: /* 0x42 */
1983/* File: armv5te/OP_UNUSED_42.S */
1984/* File: armv5te/unused.S */
1985    bl      common_abort
1986
1987
1988
1989/* ------------------------------ */
1990    .balign 64
1991.L_OP_UNUSED_43: /* 0x43 */
1992/* File: armv5te/OP_UNUSED_43.S */
1993/* File: armv5te/unused.S */
1994    bl      common_abort
1995
1996
1997
1998/* ------------------------------ */
1999    .balign 64
2000.L_OP_AGET: /* 0x44 */
2001/* File: armv5te/OP_AGET.S */
2002    /*
2003     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2004     *
2005     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2006     * instructions.  We use a pair of FETCH_Bs instead.
2007     *
2008     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2009     */
2010    /* op vAA, vBB, vCC */
2011    FETCH_B(r2, 1, 0)                   @ r2<- BB
2012    mov     r9, rINST, lsr #8           @ r9<- AA
2013    FETCH_B(r3, 1, 1)                   @ r3<- CC
2014    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2015    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2016    cmp     r0, #0                      @ null array object?
2017    beq     common_errNullObject        @ yes, bail
2018    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2019    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2020    cmp     r1, r3                      @ compare unsigned index, length
2021    bcs     common_errArrayIndex        @ index >= length, bail
2022    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2023    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2024    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2025    SET_VREG(r2, r9)                    @ vAA<- r2
2026    GOTO_OPCODE(ip)                     @ jump to next instruction
2027
2028
2029/* ------------------------------ */
2030    .balign 64
2031.L_OP_AGET_WIDE: /* 0x45 */
2032/* File: armv5te/OP_AGET_WIDE.S */
2033    /*
2034     * Array get, 64 bits.  vAA <- vBB[vCC].
2035     *
2036     * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD.
2037     */
2038    /* aget-wide vAA, vBB, vCC */
2039    FETCH(r0, 1)                        @ r0<- CCBB
2040    mov     r9, rINST, lsr #8           @ r9<- AA
2041    and     r2, r0, #255                @ r2<- BB
2042    mov     r3, r0, lsr #8              @ r3<- CC
2043    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2044    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2045    cmp     r0, #0                      @ null array object?
2046    beq     common_errNullObject        @ yes, bail
2047    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2048    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2049    cmp     r1, r3                      @ compare unsigned index, length
2050    bcc     .LOP_AGET_WIDE_finish          @ okay, continue below
2051    b       common_errArrayIndex        @ index >= length, bail
2052    @ May want to swap the order of these two branches depending on how the
2053    @ branch prediction (if any) handles conditional forward branches vs.
2054    @ unconditional forward branches.
2055
2056/* ------------------------------ */
2057    .balign 64
2058.L_OP_AGET_OBJECT: /* 0x46 */
2059/* File: armv5te/OP_AGET_OBJECT.S */
2060/* File: armv5te/OP_AGET.S */
2061    /*
2062     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2063     *
2064     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2065     * instructions.  We use a pair of FETCH_Bs instead.
2066     *
2067     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2068     */
2069    /* op vAA, vBB, vCC */
2070    FETCH_B(r2, 1, 0)                   @ r2<- BB
2071    mov     r9, rINST, lsr #8           @ r9<- AA
2072    FETCH_B(r3, 1, 1)                   @ r3<- CC
2073    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2074    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2075    cmp     r0, #0                      @ null array object?
2076    beq     common_errNullObject        @ yes, bail
2077    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2078    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2079    cmp     r1, r3                      @ compare unsigned index, length
2080    bcs     common_errArrayIndex        @ index >= length, bail
2081    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2082    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2083    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2084    SET_VREG(r2, r9)                    @ vAA<- r2
2085    GOTO_OPCODE(ip)                     @ jump to next instruction
2086
2087
2088
2089/* ------------------------------ */
2090    .balign 64
2091.L_OP_AGET_BOOLEAN: /* 0x47 */
2092/* File: armv5te/OP_AGET_BOOLEAN.S */
2093/* File: armv5te/OP_AGET.S */
2094    /*
2095     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2096     *
2097     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2098     * instructions.  We use a pair of FETCH_Bs instead.
2099     *
2100     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2101     */
2102    /* op vAA, vBB, vCC */
2103    FETCH_B(r2, 1, 0)                   @ r2<- BB
2104    mov     r9, rINST, lsr #8           @ r9<- AA
2105    FETCH_B(r3, 1, 1)                   @ r3<- CC
2106    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2107    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2108    cmp     r0, #0                      @ null array object?
2109    beq     common_errNullObject        @ yes, bail
2110    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2111    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2112    cmp     r1, r3                      @ compare unsigned index, length
2113    bcs     common_errArrayIndex        @ index >= length, bail
2114    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2115    ldrb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2116    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2117    SET_VREG(r2, r9)                    @ vAA<- r2
2118    GOTO_OPCODE(ip)                     @ jump to next instruction
2119
2120
2121
2122/* ------------------------------ */
2123    .balign 64
2124.L_OP_AGET_BYTE: /* 0x48 */
2125/* File: armv5te/OP_AGET_BYTE.S */
2126/* File: armv5te/OP_AGET.S */
2127    /*
2128     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2129     *
2130     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2131     * instructions.  We use a pair of FETCH_Bs instead.
2132     *
2133     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2134     */
2135    /* op vAA, vBB, vCC */
2136    FETCH_B(r2, 1, 0)                   @ r2<- BB
2137    mov     r9, rINST, lsr #8           @ r9<- AA
2138    FETCH_B(r3, 1, 1)                   @ r3<- CC
2139    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2140    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2141    cmp     r0, #0                      @ null array object?
2142    beq     common_errNullObject        @ yes, bail
2143    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2144    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2145    cmp     r1, r3                      @ compare unsigned index, length
2146    bcs     common_errArrayIndex        @ index >= length, bail
2147    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2148    ldrsb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2149    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2150    SET_VREG(r2, r9)                    @ vAA<- r2
2151    GOTO_OPCODE(ip)                     @ jump to next instruction
2152
2153
2154
2155/* ------------------------------ */
2156    .balign 64
2157.L_OP_AGET_CHAR: /* 0x49 */
2158/* File: armv5te/OP_AGET_CHAR.S */
2159/* File: armv5te/OP_AGET.S */
2160    /*
2161     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2162     *
2163     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2164     * instructions.  We use a pair of FETCH_Bs instead.
2165     *
2166     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2167     */
2168    /* op vAA, vBB, vCC */
2169    FETCH_B(r2, 1, 0)                   @ r2<- BB
2170    mov     r9, rINST, lsr #8           @ r9<- AA
2171    FETCH_B(r3, 1, 1)                   @ r3<- CC
2172    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2173    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2174    cmp     r0, #0                      @ null array object?
2175    beq     common_errNullObject        @ yes, bail
2176    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2177    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2178    cmp     r1, r3                      @ compare unsigned index, length
2179    bcs     common_errArrayIndex        @ index >= length, bail
2180    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2181    ldrh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2182    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2183    SET_VREG(r2, r9)                    @ vAA<- r2
2184    GOTO_OPCODE(ip)                     @ jump to next instruction
2185
2186
2187
2188/* ------------------------------ */
2189    .balign 64
2190.L_OP_AGET_SHORT: /* 0x4a */
2191/* File: armv5te/OP_AGET_SHORT.S */
2192/* File: armv5te/OP_AGET.S */
2193    /*
2194     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2195     *
2196     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2197     * instructions.  We use a pair of FETCH_Bs instead.
2198     *
2199     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2200     */
2201    /* op vAA, vBB, vCC */
2202    FETCH_B(r2, 1, 0)                   @ r2<- BB
2203    mov     r9, rINST, lsr #8           @ r9<- AA
2204    FETCH_B(r3, 1, 1)                   @ r3<- CC
2205    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2206    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2207    cmp     r0, #0                      @ null array object?
2208    beq     common_errNullObject        @ yes, bail
2209    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2210    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2211    cmp     r1, r3                      @ compare unsigned index, length
2212    bcs     common_errArrayIndex        @ index >= length, bail
2213    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2214    ldrsh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2215    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2216    SET_VREG(r2, r9)                    @ vAA<- r2
2217    GOTO_OPCODE(ip)                     @ jump to next instruction
2218
2219
2220
2221/* ------------------------------ */
2222    .balign 64
2223.L_OP_APUT: /* 0x4b */
2224/* File: armv5te/OP_APUT.S */
2225    /*
2226     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2227     *
2228     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2229     * instructions.  We use a pair of FETCH_Bs instead.
2230     *
2231     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2232     */
2233    /* op vAA, vBB, vCC */
2234    FETCH_B(r2, 1, 0)                   @ r2<- BB
2235    mov     r9, rINST, lsr #8           @ r9<- AA
2236    FETCH_B(r3, 1, 1)                   @ r3<- CC
2237    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2238    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2239    cmp     r0, #0                      @ null array object?
2240    beq     common_errNullObject        @ yes, bail
2241    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2242    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2243    cmp     r1, r3                      @ compare unsigned index, length
2244    bcs     common_errArrayIndex        @ index >= length, bail
2245    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2246    GET_VREG(r2, r9)                    @ r2<- vAA
2247    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2248    str  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2249    GOTO_OPCODE(ip)                     @ jump to next instruction
2250
2251
2252/* ------------------------------ */
2253    .balign 64
2254.L_OP_APUT_WIDE: /* 0x4c */
2255/* File: armv5te/OP_APUT_WIDE.S */
2256    /*
2257     * Array put, 64 bits.  vBB[vCC] <- vAA.
2258     *
2259     * Arrays of long/double are 64-bit aligned, so it's okay to use STRD.
2260     */
2261    /* aput-wide vAA, vBB, vCC */
2262    FETCH(r0, 1)                        @ r0<- CCBB
2263    mov     r9, rINST, lsr #8           @ r9<- AA
2264    and     r2, r0, #255                @ r2<- BB
2265    mov     r3, r0, lsr #8              @ r3<- CC
2266    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2267    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2268    cmp     r0, #0                      @ null array object?
2269    beq     common_errNullObject        @ yes, bail
2270    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2271    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2272    cmp     r1, r3                      @ compare unsigned index, length
2273    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2274    bcc     .LOP_APUT_WIDE_finish          @ okay, continue below
2275    b       common_errArrayIndex        @ index >= length, bail
2276    @ May want to swap the order of these two branches depending on how the
2277    @ branch prediction (if any) handles conditional forward branches vs.
2278    @ unconditional forward branches.
2279
2280/* ------------------------------ */
2281    .balign 64
2282.L_OP_APUT_OBJECT: /* 0x4d */
2283/* File: armv5te/OP_APUT_OBJECT.S */
2284    /*
2285     * Store an object into an array.  vBB[vCC] <- vAA.
2286     *
2287     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2288     * instructions.  We use a pair of FETCH_Bs instead.
2289     */
2290    /* op vAA, vBB, vCC */
2291    FETCH(r0, 1)                        @ r0<- CCBB
2292    mov     r9, rINST, lsr #8           @ r9<- AA
2293    and     r2, r0, #255                @ r2<- BB
2294    mov     r3, r0, lsr #8              @ r3<- CC
2295    GET_VREG(r1, r2)                    @ r1<- vBB (array object)
2296    GET_VREG(r0, r3)                    @ r0<- vCC (requested index)
2297    cmp     r1, #0                      @ null array object?
2298    GET_VREG(r9, r9)                    @ r9<- vAA
2299    beq     common_errNullObject        @ yes, bail
2300    ldr     r3, [r1, #offArrayObject_length]    @ r3<- arrayObj->length
2301    add     r10, r1, r0, lsl #2         @ r10<- arrayObj + index*width
2302    cmp     r0, r3                      @ compare unsigned index, length
2303    bcc     .LOP_APUT_OBJECT_finish          @ we're okay, continue on
2304    b       common_errArrayIndex        @ index >= length, bail
2305
2306
2307/* ------------------------------ */
2308    .balign 64
2309.L_OP_APUT_BOOLEAN: /* 0x4e */
2310/* File: armv5te/OP_APUT_BOOLEAN.S */
2311/* File: armv5te/OP_APUT.S */
2312    /*
2313     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2314     *
2315     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2316     * instructions.  We use a pair of FETCH_Bs instead.
2317     *
2318     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2319     */
2320    /* op vAA, vBB, vCC */
2321    FETCH_B(r2, 1, 0)                   @ r2<- BB
2322    mov     r9, rINST, lsr #8           @ r9<- AA
2323    FETCH_B(r3, 1, 1)                   @ r3<- CC
2324    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2325    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2326    cmp     r0, #0                      @ null array object?
2327    beq     common_errNullObject        @ yes, bail
2328    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2329    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2330    cmp     r1, r3                      @ compare unsigned index, length
2331    bcs     common_errArrayIndex        @ index >= length, bail
2332    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2333    GET_VREG(r2, r9)                    @ r2<- vAA
2334    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2335    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2336    GOTO_OPCODE(ip)                     @ jump to next instruction
2337
2338
2339
2340/* ------------------------------ */
2341    .balign 64
2342.L_OP_APUT_BYTE: /* 0x4f */
2343/* File: armv5te/OP_APUT_BYTE.S */
2344/* File: armv5te/OP_APUT.S */
2345    /*
2346     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2347     *
2348     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2349     * instructions.  We use a pair of FETCH_Bs instead.
2350     *
2351     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2352     */
2353    /* op vAA, vBB, vCC */
2354    FETCH_B(r2, 1, 0)                   @ r2<- BB
2355    mov     r9, rINST, lsr #8           @ r9<- AA
2356    FETCH_B(r3, 1, 1)                   @ r3<- CC
2357    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2358    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2359    cmp     r0, #0                      @ null array object?
2360    beq     common_errNullObject        @ yes, bail
2361    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2362    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2363    cmp     r1, r3                      @ compare unsigned index, length
2364    bcs     common_errArrayIndex        @ index >= length, bail
2365    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2366    GET_VREG(r2, r9)                    @ r2<- vAA
2367    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2368    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2369    GOTO_OPCODE(ip)                     @ jump to next instruction
2370
2371
2372
2373/* ------------------------------ */
2374    .balign 64
2375.L_OP_APUT_CHAR: /* 0x50 */
2376/* File: armv5te/OP_APUT_CHAR.S */
2377/* File: armv5te/OP_APUT.S */
2378    /*
2379     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2380     *
2381     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2382     * instructions.  We use a pair of FETCH_Bs instead.
2383     *
2384     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2385     */
2386    /* op vAA, vBB, vCC */
2387    FETCH_B(r2, 1, 0)                   @ r2<- BB
2388    mov     r9, rINST, lsr #8           @ r9<- AA
2389    FETCH_B(r3, 1, 1)                   @ r3<- CC
2390    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2391    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2392    cmp     r0, #0                      @ null array object?
2393    beq     common_errNullObject        @ yes, bail
2394    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2395    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2396    cmp     r1, r3                      @ compare unsigned index, length
2397    bcs     common_errArrayIndex        @ index >= length, bail
2398    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2399    GET_VREG(r2, r9)                    @ r2<- vAA
2400    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2401    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2402    GOTO_OPCODE(ip)                     @ jump to next instruction
2403
2404
2405
2406/* ------------------------------ */
2407    .balign 64
2408.L_OP_APUT_SHORT: /* 0x51 */
2409/* File: armv5te/OP_APUT_SHORT.S */
2410/* File: armv5te/OP_APUT.S */
2411    /*
2412     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2413     *
2414     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2415     * instructions.  We use a pair of FETCH_Bs instead.
2416     *
2417     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2418     */
2419    /* op vAA, vBB, vCC */
2420    FETCH_B(r2, 1, 0)                   @ r2<- BB
2421    mov     r9, rINST, lsr #8           @ r9<- AA
2422    FETCH_B(r3, 1, 1)                   @ r3<- CC
2423    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2424    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2425    cmp     r0, #0                      @ null array object?
2426    beq     common_errNullObject        @ yes, bail
2427    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2428    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2429    cmp     r1, r3                      @ compare unsigned index, length
2430    bcs     common_errArrayIndex        @ index >= length, bail
2431    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2432    GET_VREG(r2, r9)                    @ r2<- vAA
2433    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2434    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2435    GOTO_OPCODE(ip)                     @ jump to next instruction
2436
2437
2438
2439/* ------------------------------ */
2440    .balign 64
2441.L_OP_IGET: /* 0x52 */
2442/* File: armv5te/OP_IGET.S */
2443    /*
2444     * General 32-bit instance field get.
2445     *
2446     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2447     */
2448    /* op vA, vB, field@CCCC */
2449    mov     r0, rINST, lsr #12          @ r0<- B
2450    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2451    FETCH(r1, 1)                        @ r1<- field ref CCCC
2452    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2453    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2454    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2455    cmp     r0, #0                      @ is resolved entry null?
2456    bne     .LOP_IGET_finish          @ no, already resolved
24578:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2458    EXPORT_PC()                         @ resolve() could throw
2459    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2460    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2461    cmp     r0, #0
2462    bne     .LOP_IGET_finish
2463    b       common_exceptionThrown
2464
2465/* ------------------------------ */
2466    .balign 64
2467.L_OP_IGET_WIDE: /* 0x53 */
2468/* File: armv5te/OP_IGET_WIDE.S */
2469    /*
2470     * Wide 32-bit instance field get.
2471     */
2472    /* iget-wide vA, vB, field@CCCC */
2473    mov     r0, rINST, lsr #12          @ r0<- B
2474    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2475    FETCH(r1, 1)                        @ r1<- field ref CCCC
2476    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2477    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2478    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2479    cmp     r0, #0                      @ is resolved entry null?
2480    bne     .LOP_IGET_WIDE_finish          @ no, already resolved
24818:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2482    EXPORT_PC()                         @ resolve() could throw
2483    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2484    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2485    cmp     r0, #0
2486    bne     .LOP_IGET_WIDE_finish
2487    b       common_exceptionThrown
2488
2489/* ------------------------------ */
2490    .balign 64
2491.L_OP_IGET_OBJECT: /* 0x54 */
2492/* File: armv5te/OP_IGET_OBJECT.S */
2493/* File: armv5te/OP_IGET.S */
2494    /*
2495     * General 32-bit instance field get.
2496     *
2497     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2498     */
2499    /* op vA, vB, field@CCCC */
2500    mov     r0, rINST, lsr #12          @ r0<- B
2501    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2502    FETCH(r1, 1)                        @ r1<- field ref CCCC
2503    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2504    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2505    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2506    cmp     r0, #0                      @ is resolved entry null?
2507    bne     .LOP_IGET_OBJECT_finish          @ no, already resolved
25088:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2509    EXPORT_PC()                         @ resolve() could throw
2510    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2511    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2512    cmp     r0, #0
2513    bne     .LOP_IGET_OBJECT_finish
2514    b       common_exceptionThrown
2515
2516
2517/* ------------------------------ */
2518    .balign 64
2519.L_OP_IGET_BOOLEAN: /* 0x55 */
2520/* File: armv5te/OP_IGET_BOOLEAN.S */
2521@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" }
2522/* File: armv5te/OP_IGET.S */
2523    /*
2524     * General 32-bit instance field get.
2525     *
2526     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2527     */
2528    /* op vA, vB, field@CCCC */
2529    mov     r0, rINST, lsr #12          @ r0<- B
2530    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2531    FETCH(r1, 1)                        @ r1<- field ref CCCC
2532    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2533    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2534    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2535    cmp     r0, #0                      @ is resolved entry null?
2536    bne     .LOP_IGET_BOOLEAN_finish          @ no, already resolved
25378:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2538    EXPORT_PC()                         @ resolve() could throw
2539    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2540    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2541    cmp     r0, #0
2542    bne     .LOP_IGET_BOOLEAN_finish
2543    b       common_exceptionThrown
2544
2545
2546/* ------------------------------ */
2547    .balign 64
2548.L_OP_IGET_BYTE: /* 0x56 */
2549/* File: armv5te/OP_IGET_BYTE.S */
2550@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" }
2551/* File: armv5te/OP_IGET.S */
2552    /*
2553     * General 32-bit instance field get.
2554     *
2555     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2556     */
2557    /* op vA, vB, field@CCCC */
2558    mov     r0, rINST, lsr #12          @ r0<- B
2559    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2560    FETCH(r1, 1)                        @ r1<- field ref CCCC
2561    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2562    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2563    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2564    cmp     r0, #0                      @ is resolved entry null?
2565    bne     .LOP_IGET_BYTE_finish          @ no, already resolved
25668:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2567    EXPORT_PC()                         @ resolve() could throw
2568    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2569    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2570    cmp     r0, #0
2571    bne     .LOP_IGET_BYTE_finish
2572    b       common_exceptionThrown
2573
2574
2575/* ------------------------------ */
2576    .balign 64
2577.L_OP_IGET_CHAR: /* 0x57 */
2578/* File: armv5te/OP_IGET_CHAR.S */
2579@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" }
2580/* File: armv5te/OP_IGET.S */
2581    /*
2582     * General 32-bit instance field get.
2583     *
2584     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2585     */
2586    /* op vA, vB, field@CCCC */
2587    mov     r0, rINST, lsr #12          @ r0<- B
2588    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2589    FETCH(r1, 1)                        @ r1<- field ref CCCC
2590    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2591    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2592    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2593    cmp     r0, #0                      @ is resolved entry null?
2594    bne     .LOP_IGET_CHAR_finish          @ no, already resolved
25958:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2596    EXPORT_PC()                         @ resolve() could throw
2597    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2598    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2599    cmp     r0, #0
2600    bne     .LOP_IGET_CHAR_finish
2601    b       common_exceptionThrown
2602
2603
2604/* ------------------------------ */
2605    .balign 64
2606.L_OP_IGET_SHORT: /* 0x58 */
2607/* File: armv5te/OP_IGET_SHORT.S */
2608@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" }
2609/* File: armv5te/OP_IGET.S */
2610    /*
2611     * General 32-bit instance field get.
2612     *
2613     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2614     */
2615    /* op vA, vB, field@CCCC */
2616    mov     r0, rINST, lsr #12          @ r0<- B
2617    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2618    FETCH(r1, 1)                        @ r1<- field ref CCCC
2619    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2620    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2621    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2622    cmp     r0, #0                      @ is resolved entry null?
2623    bne     .LOP_IGET_SHORT_finish          @ no, already resolved
26248:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2625    EXPORT_PC()                         @ resolve() could throw
2626    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2627    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2628    cmp     r0, #0
2629    bne     .LOP_IGET_SHORT_finish
2630    b       common_exceptionThrown
2631
2632
2633/* ------------------------------ */
2634    .balign 64
2635.L_OP_IPUT: /* 0x59 */
2636/* File: armv5te/OP_IPUT.S */
2637    /*
2638     * General 32-bit instance field put.
2639     *
2640     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2641     */
2642    /* op vA, vB, field@CCCC */
2643    mov     r0, rINST, lsr #12          @ r0<- B
2644    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2645    FETCH(r1, 1)                        @ r1<- field ref CCCC
2646    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2647    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2648    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2649    cmp     r0, #0                      @ is resolved entry null?
2650    bne     .LOP_IPUT_finish          @ no, already resolved
26518:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2652    EXPORT_PC()                         @ resolve() could throw
2653    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2654    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2655    cmp     r0, #0                      @ success?
2656    bne     .LOP_IPUT_finish          @ yes, finish up
2657    b       common_exceptionThrown
2658
2659/* ------------------------------ */
2660    .balign 64
2661.L_OP_IPUT_WIDE: /* 0x5a */
2662/* File: armv5te/OP_IPUT_WIDE.S */
2663    /* iput-wide 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<- 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_WIDE_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_WIDE_finish          @ yes, finish up
2678    b       common_exceptionThrown
2679
2680/* ------------------------------ */
2681    .balign 64
2682.L_OP_IPUT_OBJECT: /* 0x5b */
2683/* File: armv5te/OP_IPUT_OBJECT.S */
2684/* File: armv5te/OP_IPUT.S */
2685    /*
2686     * General 32-bit instance field put.
2687     *
2688     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2689     */
2690    /* op vA, vB, field@CCCC */
2691    mov     r0, rINST, lsr #12          @ r0<- B
2692    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2693    FETCH(r1, 1)                        @ r1<- field ref CCCC
2694    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2695    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2696    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2697    cmp     r0, #0                      @ is resolved entry null?
2698    bne     .LOP_IPUT_OBJECT_finish          @ no, already resolved
26998:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2700    EXPORT_PC()                         @ resolve() could throw
2701    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2702    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2703    cmp     r0, #0                      @ success?
2704    bne     .LOP_IPUT_OBJECT_finish          @ yes, finish up
2705    b       common_exceptionThrown
2706
2707
2708/* ------------------------------ */
2709    .balign 64
2710.L_OP_IPUT_BOOLEAN: /* 0x5c */
2711/* File: armv5te/OP_IPUT_BOOLEAN.S */
2712@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" }
2713/* File: armv5te/OP_IPUT.S */
2714    /*
2715     * General 32-bit instance field put.
2716     *
2717     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2718     */
2719    /* op vA, vB, field@CCCC */
2720    mov     r0, rINST, lsr #12          @ r0<- B
2721    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2722    FETCH(r1, 1)                        @ r1<- field ref CCCC
2723    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2724    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2725    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2726    cmp     r0, #0                      @ is resolved entry null?
2727    bne     .LOP_IPUT_BOOLEAN_finish          @ no, already resolved
27288:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2729    EXPORT_PC()                         @ resolve() could throw
2730    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2731    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2732    cmp     r0, #0                      @ success?
2733    bne     .LOP_IPUT_BOOLEAN_finish          @ yes, finish up
2734    b       common_exceptionThrown
2735
2736
2737/* ------------------------------ */
2738    .balign 64
2739.L_OP_IPUT_BYTE: /* 0x5d */
2740/* File: armv5te/OP_IPUT_BYTE.S */
2741@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" }
2742/* File: armv5te/OP_IPUT.S */
2743    /*
2744     * General 32-bit instance field put.
2745     *
2746     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2747     */
2748    /* op vA, vB, field@CCCC */
2749    mov     r0, rINST, lsr #12          @ r0<- B
2750    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2751    FETCH(r1, 1)                        @ r1<- field ref CCCC
2752    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2753    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2754    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2755    cmp     r0, #0                      @ is resolved entry null?
2756    bne     .LOP_IPUT_BYTE_finish          @ no, already resolved
27578:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2758    EXPORT_PC()                         @ resolve() could throw
2759    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2760    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2761    cmp     r0, #0                      @ success?
2762    bne     .LOP_IPUT_BYTE_finish          @ yes, finish up
2763    b       common_exceptionThrown
2764
2765
2766/* ------------------------------ */
2767    .balign 64
2768.L_OP_IPUT_CHAR: /* 0x5e */
2769/* File: armv5te/OP_IPUT_CHAR.S */
2770@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" }
2771/* File: armv5te/OP_IPUT.S */
2772    /*
2773     * General 32-bit instance field put.
2774     *
2775     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2776     */
2777    /* op vA, vB, field@CCCC */
2778    mov     r0, rINST, lsr #12          @ r0<- B
2779    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2780    FETCH(r1, 1)                        @ r1<- field ref CCCC
2781    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2782    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2783    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2784    cmp     r0, #0                      @ is resolved entry null?
2785    bne     .LOP_IPUT_CHAR_finish          @ no, already resolved
27868:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2787    EXPORT_PC()                         @ resolve() could throw
2788    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2789    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2790    cmp     r0, #0                      @ success?
2791    bne     .LOP_IPUT_CHAR_finish          @ yes, finish up
2792    b       common_exceptionThrown
2793
2794
2795/* ------------------------------ */
2796    .balign 64
2797.L_OP_IPUT_SHORT: /* 0x5f */
2798/* File: armv5te/OP_IPUT_SHORT.S */
2799@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" }
2800/* File: armv5te/OP_IPUT.S */
2801    /*
2802     * General 32-bit instance field put.
2803     *
2804     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2805     */
2806    /* op vA, vB, field@CCCC */
2807    mov     r0, rINST, lsr #12          @ r0<- B
2808    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2809    FETCH(r1, 1)                        @ r1<- field ref CCCC
2810    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2811    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2812    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2813    cmp     r0, #0                      @ is resolved entry null?
2814    bne     .LOP_IPUT_SHORT_finish          @ no, already resolved
28158:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2816    EXPORT_PC()                         @ resolve() could throw
2817    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2818    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2819    cmp     r0, #0                      @ success?
2820    bne     .LOP_IPUT_SHORT_finish          @ yes, finish up
2821    b       common_exceptionThrown
2822
2823
2824/* ------------------------------ */
2825    .balign 64
2826.L_OP_SGET: /* 0x60 */
2827/* File: armv5te/OP_SGET.S */
2828    /*
2829     * General 32-bit SGET handler.
2830     *
2831     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2832     */
2833    /* op vAA, field@BBBB */
2834    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2835    FETCH(r1, 1)                        @ r1<- field ref BBBB
2836    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2837    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2838    cmp     r0, #0                      @ is resolved entry null?
2839    beq     .LOP_SGET_resolve         @ yes, do resolve
2840.LOP_SGET_finish: @ field ptr in r0
2841    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2842    mov     r2, rINST, lsr #8           @ r2<- AA
2843    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2844    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2845    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2846    GOTO_OPCODE(ip)                     @ jump to next instruction
2847
2848/* ------------------------------ */
2849    .balign 64
2850.L_OP_SGET_WIDE: /* 0x61 */
2851/* File: armv5te/OP_SGET_WIDE.S */
2852    /*
2853     * 64-bit SGET handler.
2854     */
2855    /* sget-wide vAA, field@BBBB */
2856    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2857    FETCH(r1, 1)                        @ r1<- field ref BBBB
2858    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2859    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2860    cmp     r0, #0                      @ is resolved entry null?
2861    beq     .LOP_SGET_WIDE_resolve         @ yes, do resolve
2862.LOP_SGET_WIDE_finish:
2863    mov     r1, rINST, lsr #8           @ r1<- AA
2864    ldrd    r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned)
2865    add     r1, rFP, r1, lsl #2         @ r1<- &fp[AA]
2866    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2867    stmia   r1, {r2-r3}                 @ vAA/vAA+1<- r2/r3
2868    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2869    GOTO_OPCODE(ip)                     @ jump to next instruction
2870
2871/* ------------------------------ */
2872    .balign 64
2873.L_OP_SGET_OBJECT: /* 0x62 */
2874/* File: armv5te/OP_SGET_OBJECT.S */
2875/* File: armv5te/OP_SGET.S */
2876    /*
2877     * General 32-bit SGET handler.
2878     *
2879     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2880     */
2881    /* op vAA, field@BBBB */
2882    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2883    FETCH(r1, 1)                        @ r1<- field ref BBBB
2884    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2885    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2886    cmp     r0, #0                      @ is resolved entry null?
2887    beq     .LOP_SGET_OBJECT_resolve         @ yes, do resolve
2888.LOP_SGET_OBJECT_finish: @ field ptr in r0
2889    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2890    mov     r2, rINST, lsr #8           @ r2<- AA
2891    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2892    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2893    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2894    GOTO_OPCODE(ip)                     @ jump to next instruction
2895
2896
2897/* ------------------------------ */
2898    .balign 64
2899.L_OP_SGET_BOOLEAN: /* 0x63 */
2900/* File: armv5te/OP_SGET_BOOLEAN.S */
2901/* File: armv5te/OP_SGET.S */
2902    /*
2903     * General 32-bit SGET handler.
2904     *
2905     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2906     */
2907    /* op vAA, field@BBBB */
2908    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2909    FETCH(r1, 1)                        @ r1<- field ref BBBB
2910    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2911    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2912    cmp     r0, #0                      @ is resolved entry null?
2913    beq     .LOP_SGET_BOOLEAN_resolve         @ yes, do resolve
2914.LOP_SGET_BOOLEAN_finish: @ field ptr in r0
2915    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2916    mov     r2, rINST, lsr #8           @ r2<- AA
2917    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2918    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2919    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2920    GOTO_OPCODE(ip)                     @ jump to next instruction
2921
2922
2923/* ------------------------------ */
2924    .balign 64
2925.L_OP_SGET_BYTE: /* 0x64 */
2926/* File: armv5te/OP_SGET_BYTE.S */
2927/* File: armv5te/OP_SGET.S */
2928    /*
2929     * General 32-bit SGET handler.
2930     *
2931     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2932     */
2933    /* op vAA, field@BBBB */
2934    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2935    FETCH(r1, 1)                        @ r1<- field ref BBBB
2936    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2937    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2938    cmp     r0, #0                      @ is resolved entry null?
2939    beq     .LOP_SGET_BYTE_resolve         @ yes, do resolve
2940.LOP_SGET_BYTE_finish: @ field ptr in r0
2941    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2942    mov     r2, rINST, lsr #8           @ r2<- AA
2943    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2944    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2945    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2946    GOTO_OPCODE(ip)                     @ jump to next instruction
2947
2948
2949/* ------------------------------ */
2950    .balign 64
2951.L_OP_SGET_CHAR: /* 0x65 */
2952/* File: armv5te/OP_SGET_CHAR.S */
2953/* File: armv5te/OP_SGET.S */
2954    /*
2955     * General 32-bit SGET handler.
2956     *
2957     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2958     */
2959    /* op vAA, field@BBBB */
2960    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2961    FETCH(r1, 1)                        @ r1<- field ref BBBB
2962    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2963    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2964    cmp     r0, #0                      @ is resolved entry null?
2965    beq     .LOP_SGET_CHAR_resolve         @ yes, do resolve
2966.LOP_SGET_CHAR_finish: @ field ptr in r0
2967    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2968    mov     r2, rINST, lsr #8           @ r2<- AA
2969    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2970    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2971    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2972    GOTO_OPCODE(ip)                     @ jump to next instruction
2973
2974
2975/* ------------------------------ */
2976    .balign 64
2977.L_OP_SGET_SHORT: /* 0x66 */
2978/* File: armv5te/OP_SGET_SHORT.S */
2979/* File: armv5te/OP_SGET.S */
2980    /*
2981     * General 32-bit SGET handler.
2982     *
2983     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2984     */
2985    /* op vAA, field@BBBB */
2986    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2987    FETCH(r1, 1)                        @ r1<- field ref BBBB
2988    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2989    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2990    cmp     r0, #0                      @ is resolved entry null?
2991    beq     .LOP_SGET_SHORT_resolve         @ yes, do resolve
2992.LOP_SGET_SHORT_finish: @ field ptr in r0
2993    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2994    mov     r2, rINST, lsr #8           @ r2<- AA
2995    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2996    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2997    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2998    GOTO_OPCODE(ip)                     @ jump to next instruction
2999
3000
3001/* ------------------------------ */
3002    .balign 64
3003.L_OP_SPUT: /* 0x67 */
3004/* File: armv5te/OP_SPUT.S */
3005    /*
3006     * General 32-bit SPUT handler.
3007     *
3008     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3009     */
3010    /* op vAA, field@BBBB */
3011    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3012    FETCH(r1, 1)                        @ r1<- field ref BBBB
3013    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3014    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3015    cmp     r0, #0                      @ is resolved entry null?
3016    beq     .LOP_SPUT_resolve         @ yes, do resolve
3017.LOP_SPUT_finish:   @ field ptr in r0
3018    mov     r2, rINST, lsr #8           @ r2<- AA
3019    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3020    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3021    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3022    str     r1, [r0, #offStaticField_value] @ field<- vAA
3023    GOTO_OPCODE(ip)                     @ jump to next instruction
3024
3025/* ------------------------------ */
3026    .balign 64
3027.L_OP_SPUT_WIDE: /* 0x68 */
3028/* File: armv5te/OP_SPUT_WIDE.S */
3029    /*
3030     * 64-bit SPUT handler.
3031     */
3032    /* sput-wide vAA, field@BBBB */
3033    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3034    FETCH(r1, 1)                        @ r1<- field ref BBBB
3035    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3036    mov     r9, rINST, lsr #8           @ r9<- AA
3037    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3038    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
3039    cmp     r0, #0                      @ is resolved entry null?
3040    beq     .LOP_SPUT_WIDE_resolve         @ yes, do resolve
3041.LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9
3042    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3043    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
3044    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3045    strd    r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1
3046    GOTO_OPCODE(ip)                     @ jump to next instruction
3047
3048/* ------------------------------ */
3049    .balign 64
3050.L_OP_SPUT_OBJECT: /* 0x69 */
3051/* File: armv5te/OP_SPUT_OBJECT.S */
3052/* File: armv5te/OP_SPUT.S */
3053    /*
3054     * General 32-bit SPUT handler.
3055     *
3056     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3057     */
3058    /* op vAA, field@BBBB */
3059    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3060    FETCH(r1, 1)                        @ r1<- field ref BBBB
3061    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3062    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3063    cmp     r0, #0                      @ is resolved entry null?
3064    beq     .LOP_SPUT_OBJECT_resolve         @ yes, do resolve
3065.LOP_SPUT_OBJECT_finish:   @ field ptr in r0
3066    mov     r2, rINST, lsr #8           @ r2<- AA
3067    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3068    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3069    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3070    str     r1, [r0, #offStaticField_value] @ field<- vAA
3071    GOTO_OPCODE(ip)                     @ jump to next instruction
3072
3073
3074/* ------------------------------ */
3075    .balign 64
3076.L_OP_SPUT_BOOLEAN: /* 0x6a */
3077/* File: armv5te/OP_SPUT_BOOLEAN.S */
3078/* File: armv5te/OP_SPUT.S */
3079    /*
3080     * General 32-bit SPUT handler.
3081     *
3082     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3083     */
3084    /* op vAA, field@BBBB */
3085    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3086    FETCH(r1, 1)                        @ r1<- field ref BBBB
3087    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3088    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3089    cmp     r0, #0                      @ is resolved entry null?
3090    beq     .LOP_SPUT_BOOLEAN_resolve         @ yes, do resolve
3091.LOP_SPUT_BOOLEAN_finish:   @ field ptr in r0
3092    mov     r2, rINST, lsr #8           @ r2<- AA
3093    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3094    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3095    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3096    str     r1, [r0, #offStaticField_value] @ field<- vAA
3097    GOTO_OPCODE(ip)                     @ jump to next instruction
3098
3099
3100/* ------------------------------ */
3101    .balign 64
3102.L_OP_SPUT_BYTE: /* 0x6b */
3103/* File: armv5te/OP_SPUT_BYTE.S */
3104/* File: armv5te/OP_SPUT.S */
3105    /*
3106     * General 32-bit SPUT handler.
3107     *
3108     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3109     */
3110    /* op vAA, field@BBBB */
3111    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3112    FETCH(r1, 1)                        @ r1<- field ref BBBB
3113    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3114    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3115    cmp     r0, #0                      @ is resolved entry null?
3116    beq     .LOP_SPUT_BYTE_resolve         @ yes, do resolve
3117.LOP_SPUT_BYTE_finish:   @ field ptr in r0
3118    mov     r2, rINST, lsr #8           @ r2<- AA
3119    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3120    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3121    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3122    str     r1, [r0, #offStaticField_value] @ field<- vAA
3123    GOTO_OPCODE(ip)                     @ jump to next instruction
3124
3125
3126/* ------------------------------ */
3127    .balign 64
3128.L_OP_SPUT_CHAR: /* 0x6c */
3129/* File: armv5te/OP_SPUT_CHAR.S */
3130/* File: armv5te/OP_SPUT.S */
3131    /*
3132     * General 32-bit SPUT handler.
3133     *
3134     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3135     */
3136    /* op vAA, field@BBBB */
3137    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3138    FETCH(r1, 1)                        @ r1<- field ref BBBB
3139    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3140    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3141    cmp     r0, #0                      @ is resolved entry null?
3142    beq     .LOP_SPUT_CHAR_resolve         @ yes, do resolve
3143.LOP_SPUT_CHAR_finish:   @ field ptr in r0
3144    mov     r2, rINST, lsr #8           @ r2<- AA
3145    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3146    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3147    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3148    str     r1, [r0, #offStaticField_value] @ field<- vAA
3149    GOTO_OPCODE(ip)                     @ jump to next instruction
3150
3151
3152/* ------------------------------ */
3153    .balign 64
3154.L_OP_SPUT_SHORT: /* 0x6d */
3155/* File: armv5te/OP_SPUT_SHORT.S */
3156/* File: armv5te/OP_SPUT.S */
3157    /*
3158     * General 32-bit SPUT handler.
3159     *
3160     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3161     */
3162    /* op vAA, field@BBBB */
3163    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3164    FETCH(r1, 1)                        @ r1<- field ref BBBB
3165    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3166    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3167    cmp     r0, #0                      @ is resolved entry null?
3168    beq     .LOP_SPUT_SHORT_resolve         @ yes, do resolve
3169.LOP_SPUT_SHORT_finish:   @ field ptr in r0
3170    mov     r2, rINST, lsr #8           @ r2<- AA
3171    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3172    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3173    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3174    str     r1, [r0, #offStaticField_value] @ field<- vAA
3175    GOTO_OPCODE(ip)                     @ jump to next instruction
3176
3177
3178/* ------------------------------ */
3179    .balign 64
3180.L_OP_INVOKE_VIRTUAL: /* 0x6e */
3181/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3182    /*
3183     * Handle a virtual method call.
3184     *
3185     * for: invoke-virtual, invoke-virtual/range
3186     */
3187    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3188    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3189    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3190    FETCH(r1, 1)                        @ r1<- BBBB
3191    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3192    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3193    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3194    .if     (!0)
3195    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3196    .endif
3197    cmp     r0, #0                      @ already resolved?
3198    EXPORT_PC()                         @ must export for invoke
3199    bne     .LOP_INVOKE_VIRTUAL_continue        @ yes, continue on
3200    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3201    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3202    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3203    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3204    cmp     r0, #0                      @ got null?
3205    bne     .LOP_INVOKE_VIRTUAL_continue        @ no, continue
3206    b       common_exceptionThrown      @ yes, handle exception
3207
3208/* ------------------------------ */
3209    .balign 64
3210.L_OP_INVOKE_SUPER: /* 0x6f */
3211/* File: armv5te/OP_INVOKE_SUPER.S */
3212    /*
3213     * Handle a "super" method call.
3214     *
3215     * for: invoke-super, invoke-super/range
3216     */
3217    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3218    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3219    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3220    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3221    .if     (!0)
3222    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3223    .endif
3224    FETCH(r1, 1)                        @ r1<- BBBB
3225    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3226    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3227    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3228    cmp     r2, #0                      @ null "this"?
3229    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3230    beq     common_errNullObject        @ null "this", throw exception
3231    cmp     r0, #0                      @ already resolved?
3232    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3233    EXPORT_PC()                         @ must export for invoke
3234    bne     .LOP_INVOKE_SUPER_continue        @ resolved, continue on
3235    b       .LOP_INVOKE_SUPER_resolve         @ do resolve now
3236
3237/* ------------------------------ */
3238    .balign 64
3239.L_OP_INVOKE_DIRECT: /* 0x70 */
3240/* File: armv5te/OP_INVOKE_DIRECT.S */
3241    /*
3242     * Handle a direct method call.
3243     *
3244     * (We could defer the "is 'this' pointer null" test to the common
3245     * method invocation code, and use a flag to indicate that static
3246     * calls don't count.  If we do this as part of copying the arguments
3247     * out we could avoiding loading the first arg twice.)
3248     *
3249     * for: invoke-direct, invoke-direct/range
3250     */
3251    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3252    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3253    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3254    FETCH(r1, 1)                        @ r1<- BBBB
3255    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3256    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3257    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3258    .if     (!0)
3259    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3260    .endif
3261    cmp     r0, #0                      @ already resolved?
3262    EXPORT_PC()                         @ must export for invoke
3263    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3264    beq     .LOP_INVOKE_DIRECT_resolve         @ not resolved, do it now
3265.LOP_INVOKE_DIRECT_finish:
3266    cmp     r2, #0                      @ null "this" ref?
3267    bne     common_invokeMethodNoRange   @ no, continue on
3268    b       common_errNullObject        @ yes, throw exception
3269
3270/* ------------------------------ */
3271    .balign 64
3272.L_OP_INVOKE_STATIC: /* 0x71 */
3273/* File: armv5te/OP_INVOKE_STATIC.S */
3274    /*
3275     * Handle a static method call.
3276     *
3277     * for: invoke-static, invoke-static/range
3278     */
3279    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3280    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3281    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3282    FETCH(r1, 1)                        @ r1<- BBBB
3283    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3284    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3285    cmp     r0, #0                      @ already resolved?
3286    EXPORT_PC()                         @ must export for invoke
3287    bne     common_invokeMethodNoRange @ yes, continue on
32880:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3289    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3290    mov     r2, #METHOD_STATIC          @ resolver method type
3291    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3292    cmp     r0, #0                      @ got null?
3293    bne     common_invokeMethodNoRange @ no, continue
3294    b       common_exceptionThrown      @ yes, handle exception
3295
3296
3297/* ------------------------------ */
3298    .balign 64
3299.L_OP_INVOKE_INTERFACE: /* 0x72 */
3300/* File: armv5te/OP_INVOKE_INTERFACE.S */
3301    /*
3302     * Handle an interface method call.
3303     *
3304     * for: invoke-interface, invoke-interface/range
3305     */
3306    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3307    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3308    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3309    FETCH(r1, 1)                        @ r1<- BBBB
3310    .if     (!0)
3311    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3312    .endif
3313    EXPORT_PC()                         @ must export for invoke
3314    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3315    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3316    cmp     r0, #0                      @ null obj?
3317    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3318    beq     common_errNullObject        @ yes, fail
3319    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3320    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3321    cmp     r0, #0                      @ failed?
3322    beq     common_exceptionThrown      @ yes, handle exception
3323    b       common_invokeMethodNoRange @ jump to common handler
3324
3325
3326/* ------------------------------ */
3327    .balign 64
3328.L_OP_UNUSED_73: /* 0x73 */
3329/* File: armv5te/OP_UNUSED_73.S */
3330/* File: armv5te/unused.S */
3331    bl      common_abort
3332
3333
3334
3335/* ------------------------------ */
3336    .balign 64
3337.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
3338/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */
3339/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3340    /*
3341     * Handle a virtual method call.
3342     *
3343     * for: invoke-virtual, invoke-virtual/range
3344     */
3345    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3346    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3347    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3348    FETCH(r1, 1)                        @ r1<- BBBB
3349    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3350    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3351    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3352    .if     (!1)
3353    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3354    .endif
3355    cmp     r0, #0                      @ already resolved?
3356    EXPORT_PC()                         @ must export for invoke
3357    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ yes, continue on
3358    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3359    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3360    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3361    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3362    cmp     r0, #0                      @ got null?
3363    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ no, continue
3364    b       common_exceptionThrown      @ yes, handle exception
3365
3366
3367/* ------------------------------ */
3368    .balign 64
3369.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
3370/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */
3371/* File: armv5te/OP_INVOKE_SUPER.S */
3372    /*
3373     * Handle a "super" method call.
3374     *
3375     * for: invoke-super, invoke-super/range
3376     */
3377    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3378    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3379    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3380    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3381    .if     (!1)
3382    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3383    .endif
3384    FETCH(r1, 1)                        @ r1<- BBBB
3385    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3386    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3387    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3388    cmp     r2, #0                      @ null "this"?
3389    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3390    beq     common_errNullObject        @ null "this", throw exception
3391    cmp     r0, #0                      @ already resolved?
3392    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3393    EXPORT_PC()                         @ must export for invoke
3394    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ resolved, continue on
3395    b       .LOP_INVOKE_SUPER_RANGE_resolve         @ do resolve now
3396
3397
3398/* ------------------------------ */
3399    .balign 64
3400.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
3401/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */
3402/* File: armv5te/OP_INVOKE_DIRECT.S */
3403    /*
3404     * Handle a direct method call.
3405     *
3406     * (We could defer the "is 'this' pointer null" test to the common
3407     * method invocation code, and use a flag to indicate that static
3408     * calls don't count.  If we do this as part of copying the arguments
3409     * out we could avoiding loading the first arg twice.)
3410     *
3411     * for: invoke-direct, invoke-direct/range
3412     */
3413    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3414    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3415    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3416    FETCH(r1, 1)                        @ r1<- BBBB
3417    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3418    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3419    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3420    .if     (!1)
3421    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3422    .endif
3423    cmp     r0, #0                      @ already resolved?
3424    EXPORT_PC()                         @ must export for invoke
3425    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3426    beq     .LOP_INVOKE_DIRECT_RANGE_resolve         @ not resolved, do it now
3427.LOP_INVOKE_DIRECT_RANGE_finish:
3428    cmp     r2, #0                      @ null "this" ref?
3429    bne     common_invokeMethodRange   @ no, continue on
3430    b       common_errNullObject        @ yes, throw exception
3431
3432
3433/* ------------------------------ */
3434    .balign 64
3435.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
3436/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */
3437/* File: armv5te/OP_INVOKE_STATIC.S */
3438    /*
3439     * Handle a static method call.
3440     *
3441     * for: invoke-static, invoke-static/range
3442     */
3443    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3444    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3445    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3446    FETCH(r1, 1)                        @ r1<- BBBB
3447    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3448    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3449    cmp     r0, #0                      @ already resolved?
3450    EXPORT_PC()                         @ must export for invoke
3451    bne     common_invokeMethodRange @ yes, continue on
34520:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3453    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3454    mov     r2, #METHOD_STATIC          @ resolver method type
3455    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3456    cmp     r0, #0                      @ got null?
3457    bne     common_invokeMethodRange @ no, continue
3458    b       common_exceptionThrown      @ yes, handle exception
3459
3460
3461
3462/* ------------------------------ */
3463    .balign 64
3464.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
3465/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */
3466/* File: armv5te/OP_INVOKE_INTERFACE.S */
3467    /*
3468     * Handle an interface method call.
3469     *
3470     * for: invoke-interface, invoke-interface/range
3471     */
3472    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3473    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3474    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3475    FETCH(r1, 1)                        @ r1<- BBBB
3476    .if     (!1)
3477    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3478    .endif
3479    EXPORT_PC()                         @ must export for invoke
3480    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3481    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3482    cmp     r0, #0                      @ null obj?
3483    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3484    beq     common_errNullObject        @ yes, fail
3485    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3486    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3487    cmp     r0, #0                      @ failed?
3488    beq     common_exceptionThrown      @ yes, handle exception
3489    b       common_invokeMethodRange @ jump to common handler
3490
3491
3492
3493/* ------------------------------ */
3494    .balign 64
3495.L_OP_UNUSED_79: /* 0x79 */
3496/* File: armv5te/OP_UNUSED_79.S */
3497/* File: armv5te/unused.S */
3498    bl      common_abort
3499
3500
3501
3502/* ------------------------------ */
3503    .balign 64
3504.L_OP_UNUSED_7A: /* 0x7a */
3505/* File: armv5te/OP_UNUSED_7A.S */
3506/* File: armv5te/unused.S */
3507    bl      common_abort
3508
3509
3510
3511/* ------------------------------ */
3512    .balign 64
3513.L_OP_NEG_INT: /* 0x7b */
3514/* File: armv5te/OP_NEG_INT.S */
3515/* File: armv5te/unop.S */
3516    /*
3517     * Generic 32-bit unary operation.  Provide an "instr" line that
3518     * specifies an instruction that performs "result = op r0".
3519     * This could be an ARM instruction or a function call.
3520     *
3521     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3522     *      int-to-byte, int-to-char, int-to-short
3523     */
3524    /* unop vA, vB */
3525    mov     r3, rINST, lsr #12          @ r3<- B
3526    mov     r9, rINST, lsr #8           @ r9<- A+
3527    GET_VREG(r0, r3)                    @ r0<- vB
3528    and     r9, r9, #15
3529                               @ optional op; may set condition codes
3530    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3531    rsb     r0, r0, #0                              @ r0<- op, r0-r3 changed
3532    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3533    SET_VREG(r0, r9)                    @ vAA<- r0
3534    GOTO_OPCODE(ip)                     @ jump to next instruction
3535    /* 9-10 instructions */
3536
3537
3538/* ------------------------------ */
3539    .balign 64
3540.L_OP_NOT_INT: /* 0x7c */
3541/* File: armv5te/OP_NOT_INT.S */
3542/* File: armv5te/unop.S */
3543    /*
3544     * Generic 32-bit unary operation.  Provide an "instr" line that
3545     * specifies an instruction that performs "result = op r0".
3546     * This could be an ARM instruction or a function call.
3547     *
3548     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3549     *      int-to-byte, int-to-char, int-to-short
3550     */
3551    /* unop vA, vB */
3552    mov     r3, rINST, lsr #12          @ r3<- B
3553    mov     r9, rINST, lsr #8           @ r9<- A+
3554    GET_VREG(r0, r3)                    @ r0<- vB
3555    and     r9, r9, #15
3556                               @ optional op; may set condition codes
3557    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3558    mvn     r0, r0                              @ r0<- op, r0-r3 changed
3559    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3560    SET_VREG(r0, r9)                    @ vAA<- r0
3561    GOTO_OPCODE(ip)                     @ jump to next instruction
3562    /* 9-10 instructions */
3563
3564
3565/* ------------------------------ */
3566    .balign 64
3567.L_OP_NEG_LONG: /* 0x7d */
3568/* File: armv5te/OP_NEG_LONG.S */
3569/* File: armv5te/unopWide.S */
3570    /*
3571     * Generic 64-bit unary operation.  Provide an "instr" line that
3572     * specifies an instruction that performs "result = op r0/r1".
3573     * This could be an ARM instruction or a function call.
3574     *
3575     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3576     */
3577    /* unop vA, vB */
3578    mov     r9, rINST, lsr #8           @ r9<- A+
3579    mov     r3, rINST, lsr #12          @ r3<- B
3580    and     r9, r9, #15
3581    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3582    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3583    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3584    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3585    rsbs    r0, r0, #0                           @ optional op; may set condition codes
3586    rsc     r1, r1, #0                              @ r0/r1<- op, r2-r3 changed
3587    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3588    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3589    GOTO_OPCODE(ip)                     @ jump to next instruction
3590    /* 12-13 instructions */
3591
3592
3593
3594/* ------------------------------ */
3595    .balign 64
3596.L_OP_NOT_LONG: /* 0x7e */
3597/* File: armv5te/OP_NOT_LONG.S */
3598/* File: armv5te/unopWide.S */
3599    /*
3600     * Generic 64-bit unary operation.  Provide an "instr" line that
3601     * specifies an instruction that performs "result = op r0/r1".
3602     * This could be an ARM instruction or a function call.
3603     *
3604     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3605     */
3606    /* unop vA, vB */
3607    mov     r9, rINST, lsr #8           @ r9<- A+
3608    mov     r3, rINST, lsr #12          @ r3<- B
3609    and     r9, r9, #15
3610    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3611    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3612    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3613    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3614    mvn     r0, r0                           @ optional op; may set condition codes
3615    mvn     r1, r1                              @ r0/r1<- op, r2-r3 changed
3616    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3617    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3618    GOTO_OPCODE(ip)                     @ jump to next instruction
3619    /* 12-13 instructions */
3620
3621
3622
3623/* ------------------------------ */
3624    .balign 64
3625.L_OP_NEG_FLOAT: /* 0x7f */
3626/* File: armv5te/OP_NEG_FLOAT.S */
3627/* File: armv5te/unop.S */
3628    /*
3629     * Generic 32-bit unary operation.  Provide an "instr" line that
3630     * specifies an instruction that performs "result = op r0".
3631     * This could be an ARM instruction or a function call.
3632     *
3633     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3634     *      int-to-byte, int-to-char, int-to-short
3635     */
3636    /* unop vA, vB */
3637    mov     r3, rINST, lsr #12          @ r3<- B
3638    mov     r9, rINST, lsr #8           @ r9<- A+
3639    GET_VREG(r0, r3)                    @ r0<- vB
3640    and     r9, r9, #15
3641                               @ optional op; may set condition codes
3642    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3643    add     r0, r0, #0x80000000                              @ r0<- op, r0-r3 changed
3644    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3645    SET_VREG(r0, r9)                    @ vAA<- r0
3646    GOTO_OPCODE(ip)                     @ jump to next instruction
3647    /* 9-10 instructions */
3648
3649
3650/* ------------------------------ */
3651    .balign 64
3652.L_OP_NEG_DOUBLE: /* 0x80 */
3653/* File: armv5te/OP_NEG_DOUBLE.S */
3654/* File: armv5te/unopWide.S */
3655    /*
3656     * Generic 64-bit unary operation.  Provide an "instr" line that
3657     * specifies an instruction that performs "result = op r0/r1".
3658     * This could be an ARM instruction or a function call.
3659     *
3660     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3661     */
3662    /* unop vA, vB */
3663    mov     r9, rINST, lsr #8           @ r9<- A+
3664    mov     r3, rINST, lsr #12          @ r3<- B
3665    and     r9, r9, #15
3666    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3667    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3668    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3669    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3670                               @ optional op; may set condition codes
3671    add     r1, r1, #0x80000000                              @ r0/r1<- op, r2-r3 changed
3672    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3673    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3674    GOTO_OPCODE(ip)                     @ jump to next instruction
3675    /* 12-13 instructions */
3676
3677
3678
3679/* ------------------------------ */
3680    .balign 64
3681.L_OP_INT_TO_LONG: /* 0x81 */
3682/* File: armv5te/OP_INT_TO_LONG.S */
3683/* File: armv5te/unopWider.S */
3684    /*
3685     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3686     * that specifies an instruction that performs "result = op r0", where
3687     * "result" is a 64-bit quantity in r0/r1.
3688     *
3689     * For: int-to-long, int-to-double, float-to-long, float-to-double
3690     */
3691    /* unop vA, vB */
3692    mov     r9, rINST, lsr #8           @ r9<- A+
3693    mov     r3, rINST, lsr #12          @ r3<- B
3694    and     r9, r9, #15
3695    GET_VREG(r0, r3)                    @ r0<- vB
3696    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3697                               @ optional op; may set condition codes
3698    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3699    mov     r1, r0, asr #31                              @ r0<- op, r0-r3 changed
3700    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3701    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3702    GOTO_OPCODE(ip)                     @ jump to next instruction
3703    /* 10-11 instructions */
3704
3705
3706/* ------------------------------ */
3707    .balign 64
3708.L_OP_INT_TO_FLOAT: /* 0x82 */
3709/* File: arm-vfp/OP_INT_TO_FLOAT.S */
3710/* File: arm-vfp/funop.S */
3711    /*
3712     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3713     * line that specifies an instruction that performs "s1 = op s0".
3714     *
3715     * for: int-to-float, float-to-int
3716     */
3717    /* unop vA, vB */
3718    mov     r3, rINST, lsr #12          @ r3<- B
3719    mov     r9, rINST, lsr #8           @ r9<- A+
3720    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3721    flds    s0, [r3]                    @ s0<- vB
3722    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3723    and     r9, r9, #15                 @ r9<- A
3724    fsitos  s1, s0                              @ s1<- op
3725    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3726    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3727    fsts    s1, [r9]                    @ vA<- s1
3728    GOTO_OPCODE(ip)                     @ jump to next instruction
3729
3730
3731/* ------------------------------ */
3732    .balign 64
3733.L_OP_INT_TO_DOUBLE: /* 0x83 */
3734/* File: arm-vfp/OP_INT_TO_DOUBLE.S */
3735/* File: arm-vfp/funopWider.S */
3736    /*
3737     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3738     * "instr" line that specifies an instruction that performs "d0 = op s0".
3739     *
3740     * For: int-to-double, float-to-double
3741     */
3742    /* unop vA, vB */
3743    mov     r3, rINST, lsr #12          @ r3<- B
3744    mov     r9, rINST, lsr #8           @ r9<- A+
3745    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3746    flds    s0, [r3]                    @ s0<- vB
3747    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3748    and     r9, r9, #15                 @ r9<- A
3749    fsitod  d0, s0                              @ d0<- op
3750    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3751    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3752    fstd    d0, [r9]                    @ vA<- d0
3753    GOTO_OPCODE(ip)                     @ jump to next instruction
3754
3755
3756/* ------------------------------ */
3757    .balign 64
3758.L_OP_LONG_TO_INT: /* 0x84 */
3759/* File: armv5te/OP_LONG_TO_INT.S */
3760/* we ignore the high word, making this equivalent to a 32-bit reg move */
3761/* File: armv5te/OP_MOVE.S */
3762    /* for move, move-object, long-to-int */
3763    /* op vA, vB */
3764    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
3765    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
3766    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3767    GET_VREG(r2, r1)                    @ r2<- fp[B]
3768    and     r0, r0, #15
3769    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
3770    SET_VREG(r2, r0)                    @ fp[A]<- r2
3771    GOTO_OPCODE(ip)                     @ execute next instruction
3772
3773
3774
3775/* ------------------------------ */
3776    .balign 64
3777.L_OP_LONG_TO_FLOAT: /* 0x85 */
3778/* File: armv5te/OP_LONG_TO_FLOAT.S */
3779/* File: armv5te/unopNarrower.S */
3780    /*
3781     * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
3782     * that specifies an instruction that performs "result = op r0/r1", where
3783     * "result" is a 32-bit quantity in r0.
3784     *
3785     * For: long-to-float, double-to-int, double-to-float
3786     *
3787     * (This would work for long-to-int, but that instruction is actually
3788     * an exact match for OP_MOVE.)
3789     */
3790    /* unop vA, vB */
3791    mov     r3, rINST, lsr #12          @ r3<- B
3792    mov     r9, rINST, lsr #8           @ r9<- A+
3793    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3794    and     r9, r9, #15
3795    ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
3796    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3797                               @ optional op; may set condition codes
3798    bl      __aeabi_l2f                              @ r0<- op, r0-r3 changed
3799    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3800    SET_VREG(r0, r9)                    @ vA<- r0
3801    GOTO_OPCODE(ip)                     @ jump to next instruction
3802    /* 10-11 instructions */
3803
3804
3805/* ------------------------------ */
3806    .balign 64
3807.L_OP_LONG_TO_DOUBLE: /* 0x86 */
3808/* File: armv5te/OP_LONG_TO_DOUBLE.S */
3809/* File: armv5te/unopWide.S */
3810    /*
3811     * Generic 64-bit unary operation.  Provide an "instr" line that
3812     * specifies an instruction that performs "result = op r0/r1".
3813     * This could be an ARM instruction or a function call.
3814     *
3815     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3816     */
3817    /* unop vA, vB */
3818    mov     r9, rINST, lsr #8           @ r9<- A+
3819    mov     r3, rINST, lsr #12          @ r3<- B
3820    and     r9, r9, #15
3821    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3822    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3823    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3824    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3825                               @ optional op; may set condition codes
3826    bl      __aeabi_l2d                              @ r0/r1<- op, r2-r3 changed
3827    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3828    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3829    GOTO_OPCODE(ip)                     @ jump to next instruction
3830    /* 12-13 instructions */
3831
3832
3833
3834/* ------------------------------ */
3835    .balign 64
3836.L_OP_FLOAT_TO_INT: /* 0x87 */
3837/* File: arm-vfp/OP_FLOAT_TO_INT.S */
3838/* File: arm-vfp/funop.S */
3839    /*
3840     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3841     * line that specifies an instruction that performs "s1 = op s0".
3842     *
3843     * for: int-to-float, float-to-int
3844     */
3845    /* unop vA, vB */
3846    mov     r3, rINST, lsr #12          @ r3<- B
3847    mov     r9, rINST, lsr #8           @ r9<- A+
3848    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3849    flds    s0, [r3]                    @ s0<- vB
3850    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3851    and     r9, r9, #15                 @ r9<- A
3852    ftosizs s1, s0                              @ s1<- op
3853    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3854    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3855    fsts    s1, [r9]                    @ vA<- s1
3856    GOTO_OPCODE(ip)                     @ jump to next instruction
3857
3858
3859/* ------------------------------ */
3860    .balign 64
3861.L_OP_FLOAT_TO_LONG: /* 0x88 */
3862/* File: armv5te/OP_FLOAT_TO_LONG.S */
3863@include "armv5te/unopWider.S" {"instr":"bl      __aeabi_f2lz"}
3864/* File: armv5te/unopWider.S */
3865    /*
3866     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3867     * that specifies an instruction that performs "result = op r0", where
3868     * "result" is a 64-bit quantity in r0/r1.
3869     *
3870     * For: int-to-long, int-to-double, float-to-long, float-to-double
3871     */
3872    /* unop vA, vB */
3873    mov     r9, rINST, lsr #8           @ r9<- A+
3874    mov     r3, rINST, lsr #12          @ r3<- B
3875    and     r9, r9, #15
3876    GET_VREG(r0, r3)                    @ r0<- vB
3877    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3878                               @ optional op; may set condition codes
3879    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3880    bl      f2l_doconv                              @ r0<- op, r0-r3 changed
3881    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3882    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3883    GOTO_OPCODE(ip)                     @ jump to next instruction
3884    /* 10-11 instructions */
3885
3886
3887
3888/* ------------------------------ */
3889    .balign 64
3890.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
3891/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */
3892/* File: arm-vfp/funopWider.S */
3893    /*
3894     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3895     * "instr" line that specifies an instruction that performs "d0 = op s0".
3896     *
3897     * For: int-to-double, float-to-double
3898     */
3899    /* unop vA, vB */
3900    mov     r3, rINST, lsr #12          @ r3<- B
3901    mov     r9, rINST, lsr #8           @ r9<- A+
3902    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3903    flds    s0, [r3]                    @ s0<- vB
3904    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3905    and     r9, r9, #15                 @ r9<- A
3906    fcvtds  d0, s0                              @ d0<- op
3907    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3908    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3909    fstd    d0, [r9]                    @ vA<- d0
3910    GOTO_OPCODE(ip)                     @ jump to next instruction
3911
3912
3913/* ------------------------------ */
3914    .balign 64
3915.L_OP_DOUBLE_TO_INT: /* 0x8a */
3916/* File: arm-vfp/OP_DOUBLE_TO_INT.S */
3917/* File: arm-vfp/funopNarrower.S */
3918    /*
3919     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3920     * "instr" line that specifies an instruction that performs "s0 = op d0".
3921     *
3922     * For: double-to-int, double-to-float
3923     */
3924    /* unop vA, vB */
3925    mov     r3, rINST, lsr #12          @ r3<- B
3926    mov     r9, rINST, lsr #8           @ r9<- A+
3927    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3928    fldd    d0, [r3]                    @ d0<- vB
3929    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3930    and     r9, r9, #15                 @ r9<- A
3931    ftosizd  s0, d0                              @ s0<- op
3932    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3933    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3934    fsts    s0, [r9]                    @ vA<- s0
3935    GOTO_OPCODE(ip)                     @ jump to next instruction
3936
3937
3938/* ------------------------------ */
3939    .balign 64
3940.L_OP_DOUBLE_TO_LONG: /* 0x8b */
3941/* File: armv5te/OP_DOUBLE_TO_LONG.S */
3942@include "armv5te/unopWide.S" {"instr":"bl      __aeabi_d2lz"}
3943/* File: armv5te/unopWide.S */
3944    /*
3945     * Generic 64-bit unary operation.  Provide an "instr" line that
3946     * specifies an instruction that performs "result = op r0/r1".
3947     * This could be an ARM instruction or a function call.
3948     *
3949     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3950     */
3951    /* unop vA, vB */
3952    mov     r9, rINST, lsr #8           @ r9<- A+
3953    mov     r3, rINST, lsr #12          @ r3<- B
3954    and     r9, r9, #15
3955    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3956    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3957    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3958    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3959                               @ optional op; may set condition codes
3960    bl      d2l_doconv                              @ r0/r1<- op, r2-r3 changed
3961    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3962    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3963    GOTO_OPCODE(ip)                     @ jump to next instruction
3964    /* 12-13 instructions */
3965
3966
3967
3968
3969/* ------------------------------ */
3970    .balign 64
3971.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
3972/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */
3973/* File: arm-vfp/funopNarrower.S */
3974    /*
3975     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3976     * "instr" line that specifies an instruction that performs "s0 = op d0".
3977     *
3978     * For: double-to-int, double-to-float
3979     */
3980    /* unop vA, vB */
3981    mov     r3, rINST, lsr #12          @ r3<- B
3982    mov     r9, rINST, lsr #8           @ r9<- A+
3983    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3984    fldd    d0, [r3]                    @ d0<- vB
3985    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3986    and     r9, r9, #15                 @ r9<- A
3987    fcvtsd  s0, d0                              @ s0<- op
3988    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3989    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3990    fsts    s0, [r9]                    @ vA<- s0
3991    GOTO_OPCODE(ip)                     @ jump to next instruction
3992
3993
3994/* ------------------------------ */
3995    .balign 64
3996.L_OP_INT_TO_BYTE: /* 0x8d */
3997/* File: armv5te/OP_INT_TO_BYTE.S */
3998/* File: armv5te/unop.S */
3999    /*
4000     * Generic 32-bit unary operation.  Provide an "instr" line that
4001     * specifies an instruction that performs "result = op r0".
4002     * This could be an ARM instruction or a function call.
4003     *
4004     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4005     *      int-to-byte, int-to-char, int-to-short
4006     */
4007    /* unop vA, vB */
4008    mov     r3, rINST, lsr #12          @ r3<- B
4009    mov     r9, rINST, lsr #8           @ r9<- A+
4010    GET_VREG(r0, r3)                    @ r0<- vB
4011    and     r9, r9, #15
4012    mov     r0, r0, asl #24                           @ optional op; may set condition codes
4013    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4014    mov     r0, r0, asr #24                              @ r0<- op, r0-r3 changed
4015    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4016    SET_VREG(r0, r9)                    @ vAA<- r0
4017    GOTO_OPCODE(ip)                     @ jump to next instruction
4018    /* 9-10 instructions */
4019
4020
4021/* ------------------------------ */
4022    .balign 64
4023.L_OP_INT_TO_CHAR: /* 0x8e */
4024/* File: armv5te/OP_INT_TO_CHAR.S */
4025/* File: armv5te/unop.S */
4026    /*
4027     * Generic 32-bit unary operation.  Provide an "instr" line that
4028     * specifies an instruction that performs "result = op r0".
4029     * This could be an ARM instruction or a function call.
4030     *
4031     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4032     *      int-to-byte, int-to-char, int-to-short
4033     */
4034    /* unop vA, vB */
4035    mov     r3, rINST, lsr #12          @ r3<- B
4036    mov     r9, rINST, lsr #8           @ r9<- A+
4037    GET_VREG(r0, r3)                    @ r0<- vB
4038    and     r9, r9, #15
4039    mov     r0, r0, asl #16                           @ optional op; may set condition codes
4040    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4041    mov     r0, r0, lsr #16                              @ r0<- op, r0-r3 changed
4042    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4043    SET_VREG(r0, r9)                    @ vAA<- r0
4044    GOTO_OPCODE(ip)                     @ jump to next instruction
4045    /* 9-10 instructions */
4046
4047
4048/* ------------------------------ */
4049    .balign 64
4050.L_OP_INT_TO_SHORT: /* 0x8f */
4051/* File: armv5te/OP_INT_TO_SHORT.S */
4052/* File: armv5te/unop.S */
4053    /*
4054     * Generic 32-bit unary operation.  Provide an "instr" line that
4055     * specifies an instruction that performs "result = op r0".
4056     * This could be an ARM instruction or a function call.
4057     *
4058     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4059     *      int-to-byte, int-to-char, int-to-short
4060     */
4061    /* unop vA, vB */
4062    mov     r3, rINST, lsr #12          @ r3<- B
4063    mov     r9, rINST, lsr #8           @ r9<- A+
4064    GET_VREG(r0, r3)                    @ r0<- vB
4065    and     r9, r9, #15
4066    mov     r0, r0, asl #16                           @ optional op; may set condition codes
4067    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4068    mov     r0, r0, asr #16                              @ r0<- op, r0-r3 changed
4069    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4070    SET_VREG(r0, r9)                    @ vAA<- r0
4071    GOTO_OPCODE(ip)                     @ jump to next instruction
4072    /* 9-10 instructions */
4073
4074
4075/* ------------------------------ */
4076    .balign 64
4077.L_OP_ADD_INT: /* 0x90 */
4078/* File: armv5te/OP_ADD_INT.S */
4079/* File: armv5te/binop.S */
4080    /*
4081     * Generic 32-bit binary operation.  Provide an "instr" line that
4082     * specifies an instruction that performs "result = r0 op r1".
4083     * This could be an ARM instruction or a function call.  (If the result
4084     * comes back in a register other than r0, you can override "result".)
4085     *
4086     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4087     * vCC (r1).  Useful for integer division and modulus.  Note that we
4088     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4089     * handles it correctly.
4090     *
4091     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4092     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4093     *      mul-float, div-float, rem-float
4094     */
4095    /* binop vAA, vBB, vCC */
4096    FETCH(r0, 1)                        @ r0<- CCBB
4097    mov     r9, rINST, lsr #8           @ r9<- AA
4098    mov     r3, r0, lsr #8              @ r3<- CC
4099    and     r2, r0, #255                @ r2<- BB
4100    GET_VREG(r1, r3)                    @ r1<- vCC
4101    GET_VREG(r0, r2)                    @ r0<- vBB
4102    .if 0
4103    cmp     r1, #0                      @ is second operand zero?
4104    beq     common_errDivideByZero
4105    .endif
4106
4107    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4108                               @ optional op; may set condition codes
4109    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
4110    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4111    SET_VREG(r0, r9)               @ vAA<- r0
4112    GOTO_OPCODE(ip)                     @ jump to next instruction
4113    /* 11-14 instructions */
4114
4115
4116
4117/* ------------------------------ */
4118    .balign 64
4119.L_OP_SUB_INT: /* 0x91 */
4120/* File: armv5te/OP_SUB_INT.S */
4121/* File: armv5te/binop.S */
4122    /*
4123     * Generic 32-bit binary operation.  Provide an "instr" line that
4124     * specifies an instruction that performs "result = r0 op r1".
4125     * This could be an ARM instruction or a function call.  (If the result
4126     * comes back in a register other than r0, you can override "result".)
4127     *
4128     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4129     * vCC (r1).  Useful for integer division and modulus.  Note that we
4130     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4131     * handles it correctly.
4132     *
4133     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4134     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4135     *      mul-float, div-float, rem-float
4136     */
4137    /* binop vAA, vBB, vCC */
4138    FETCH(r0, 1)                        @ r0<- CCBB
4139    mov     r9, rINST, lsr #8           @ r9<- AA
4140    mov     r3, r0, lsr #8              @ r3<- CC
4141    and     r2, r0, #255                @ r2<- BB
4142    GET_VREG(r1, r3)                    @ r1<- vCC
4143    GET_VREG(r0, r2)                    @ r0<- vBB
4144    .if 0
4145    cmp     r1, #0                      @ is second operand zero?
4146    beq     common_errDivideByZero
4147    .endif
4148
4149    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4150                               @ optional op; may set condition codes
4151    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
4152    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4153    SET_VREG(r0, r9)               @ vAA<- r0
4154    GOTO_OPCODE(ip)                     @ jump to next instruction
4155    /* 11-14 instructions */
4156
4157
4158
4159/* ------------------------------ */
4160    .balign 64
4161.L_OP_MUL_INT: /* 0x92 */
4162/* File: armv5te/OP_MUL_INT.S */
4163/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
4164/* File: armv5te/binop.S */
4165    /*
4166     * Generic 32-bit binary operation.  Provide an "instr" line that
4167     * specifies an instruction that performs "result = r0 op r1".
4168     * This could be an ARM instruction or a function call.  (If the result
4169     * comes back in a register other than r0, you can override "result".)
4170     *
4171     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4172     * vCC (r1).  Useful for integer division and modulus.  Note that we
4173     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4174     * handles it correctly.
4175     *
4176     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4177     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4178     *      mul-float, div-float, rem-float
4179     */
4180    /* binop vAA, vBB, vCC */
4181    FETCH(r0, 1)                        @ r0<- CCBB
4182    mov     r9, rINST, lsr #8           @ r9<- AA
4183    mov     r3, r0, lsr #8              @ r3<- CC
4184    and     r2, r0, #255                @ r2<- BB
4185    GET_VREG(r1, r3)                    @ r1<- vCC
4186    GET_VREG(r0, r2)                    @ r0<- vBB
4187    .if 0
4188    cmp     r1, #0                      @ is second operand zero?
4189    beq     common_errDivideByZero
4190    .endif
4191
4192    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4193                               @ optional op; may set condition codes
4194    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
4195    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4196    SET_VREG(r0, r9)               @ vAA<- r0
4197    GOTO_OPCODE(ip)                     @ jump to next instruction
4198    /* 11-14 instructions */
4199
4200
4201
4202/* ------------------------------ */
4203    .balign 64
4204.L_OP_DIV_INT: /* 0x93 */
4205/* File: armv5te/OP_DIV_INT.S */
4206/* File: armv5te/binop.S */
4207    /*
4208     * Generic 32-bit binary operation.  Provide an "instr" line that
4209     * specifies an instruction that performs "result = r0 op r1".
4210     * This could be an ARM instruction or a function call.  (If the result
4211     * comes back in a register other than r0, you can override "result".)
4212     *
4213     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4214     * vCC (r1).  Useful for integer division and modulus.  Note that we
4215     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4216     * handles it correctly.
4217     *
4218     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4219     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4220     *      mul-float, div-float, rem-float
4221     */
4222    /* binop vAA, vBB, vCC */
4223    FETCH(r0, 1)                        @ r0<- CCBB
4224    mov     r9, rINST, lsr #8           @ r9<- AA
4225    mov     r3, r0, lsr #8              @ r3<- CC
4226    and     r2, r0, #255                @ r2<- BB
4227    GET_VREG(r1, r3)                    @ r1<- vCC
4228    GET_VREG(r0, r2)                    @ r0<- vBB
4229    .if 1
4230    cmp     r1, #0                      @ is second operand zero?
4231    beq     common_errDivideByZero
4232    .endif
4233
4234    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4235                               @ optional op; may set condition codes
4236    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
4237    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4238    SET_VREG(r0, r9)               @ vAA<- r0
4239    GOTO_OPCODE(ip)                     @ jump to next instruction
4240    /* 11-14 instructions */
4241
4242
4243
4244/* ------------------------------ */
4245    .balign 64
4246.L_OP_REM_INT: /* 0x94 */
4247/* File: armv5te/OP_REM_INT.S */
4248/* idivmod returns quotient in r0 and remainder in r1 */
4249/* File: armv5te/binop.S */
4250    /*
4251     * Generic 32-bit binary operation.  Provide an "instr" line that
4252     * specifies an instruction that performs "result = r0 op r1".
4253     * This could be an ARM instruction or a function call.  (If the result
4254     * comes back in a register other than r0, you can override "result".)
4255     *
4256     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4257     * vCC (r1).  Useful for integer division and modulus.  Note that we
4258     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4259     * handles it correctly.
4260     *
4261     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4262     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4263     *      mul-float, div-float, rem-float
4264     */
4265    /* binop vAA, vBB, vCC */
4266    FETCH(r0, 1)                        @ r0<- CCBB
4267    mov     r9, rINST, lsr #8           @ r9<- AA
4268    mov     r3, r0, lsr #8              @ r3<- CC
4269    and     r2, r0, #255                @ r2<- BB
4270    GET_VREG(r1, r3)                    @ r1<- vCC
4271    GET_VREG(r0, r2)                    @ r0<- vBB
4272    .if 1
4273    cmp     r1, #0                      @ is second operand zero?
4274    beq     common_errDivideByZero
4275    .endif
4276
4277    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4278                               @ optional op; may set condition codes
4279    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
4280    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4281    SET_VREG(r1, r9)               @ vAA<- r1
4282    GOTO_OPCODE(ip)                     @ jump to next instruction
4283    /* 11-14 instructions */
4284
4285
4286
4287/* ------------------------------ */
4288    .balign 64
4289.L_OP_AND_INT: /* 0x95 */
4290/* File: armv5te/OP_AND_INT.S */
4291/* File: armv5te/binop.S */
4292    /*
4293     * Generic 32-bit binary operation.  Provide an "instr" line that
4294     * specifies an instruction that performs "result = r0 op r1".
4295     * This could be an ARM instruction or a function call.  (If the result
4296     * comes back in a register other than r0, you can override "result".)
4297     *
4298     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4299     * vCC (r1).  Useful for integer division and modulus.  Note that we
4300     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4301     * handles it correctly.
4302     *
4303     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4304     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4305     *      mul-float, div-float, rem-float
4306     */
4307    /* binop vAA, vBB, vCC */
4308    FETCH(r0, 1)                        @ r0<- CCBB
4309    mov     r9, rINST, lsr #8           @ r9<- AA
4310    mov     r3, r0, lsr #8              @ r3<- CC
4311    and     r2, r0, #255                @ r2<- BB
4312    GET_VREG(r1, r3)                    @ r1<- vCC
4313    GET_VREG(r0, r2)                    @ r0<- vBB
4314    .if 0
4315    cmp     r1, #0                      @ is second operand zero?
4316    beq     common_errDivideByZero
4317    .endif
4318
4319    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4320                               @ optional op; may set condition codes
4321    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
4322    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4323    SET_VREG(r0, r9)               @ vAA<- r0
4324    GOTO_OPCODE(ip)                     @ jump to next instruction
4325    /* 11-14 instructions */
4326
4327
4328
4329/* ------------------------------ */
4330    .balign 64
4331.L_OP_OR_INT: /* 0x96 */
4332/* File: armv5te/OP_OR_INT.S */
4333/* File: armv5te/binop.S */
4334    /*
4335     * Generic 32-bit binary operation.  Provide an "instr" line that
4336     * specifies an instruction that performs "result = r0 op r1".
4337     * This could be an ARM instruction or a function call.  (If the result
4338     * comes back in a register other than r0, you can override "result".)
4339     *
4340     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4341     * vCC (r1).  Useful for integer division and modulus.  Note that we
4342     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4343     * handles it correctly.
4344     *
4345     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4346     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4347     *      mul-float, div-float, rem-float
4348     */
4349    /* binop vAA, vBB, vCC */
4350    FETCH(r0, 1)                        @ r0<- CCBB
4351    mov     r9, rINST, lsr #8           @ r9<- AA
4352    mov     r3, r0, lsr #8              @ r3<- CC
4353    and     r2, r0, #255                @ r2<- BB
4354    GET_VREG(r1, r3)                    @ r1<- vCC
4355    GET_VREG(r0, r2)                    @ r0<- vBB
4356    .if 0
4357    cmp     r1, #0                      @ is second operand zero?
4358    beq     common_errDivideByZero
4359    .endif
4360
4361    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4362                               @ optional op; may set condition codes
4363    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
4364    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4365    SET_VREG(r0, r9)               @ vAA<- r0
4366    GOTO_OPCODE(ip)                     @ jump to next instruction
4367    /* 11-14 instructions */
4368
4369
4370
4371/* ------------------------------ */
4372    .balign 64
4373.L_OP_XOR_INT: /* 0x97 */
4374/* File: armv5te/OP_XOR_INT.S */
4375/* File: armv5te/binop.S */
4376    /*
4377     * Generic 32-bit binary operation.  Provide an "instr" line that
4378     * specifies an instruction that performs "result = r0 op r1".
4379     * This could be an ARM instruction or a function call.  (If the result
4380     * comes back in a register other than r0, you can override "result".)
4381     *
4382     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4383     * vCC (r1).  Useful for integer division and modulus.  Note that we
4384     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4385     * handles it correctly.
4386     *
4387     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4388     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4389     *      mul-float, div-float, rem-float
4390     */
4391    /* binop vAA, vBB, vCC */
4392    FETCH(r0, 1)                        @ r0<- CCBB
4393    mov     r9, rINST, lsr #8           @ r9<- AA
4394    mov     r3, r0, lsr #8              @ r3<- CC
4395    and     r2, r0, #255                @ r2<- BB
4396    GET_VREG(r1, r3)                    @ r1<- vCC
4397    GET_VREG(r0, r2)                    @ r0<- vBB
4398    .if 0
4399    cmp     r1, #0                      @ is second operand zero?
4400    beq     common_errDivideByZero
4401    .endif
4402
4403    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4404                               @ optional op; may set condition codes
4405    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
4406    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4407    SET_VREG(r0, r9)               @ vAA<- r0
4408    GOTO_OPCODE(ip)                     @ jump to next instruction
4409    /* 11-14 instructions */
4410
4411
4412
4413/* ------------------------------ */
4414    .balign 64
4415.L_OP_SHL_INT: /* 0x98 */
4416/* File: armv5te/OP_SHL_INT.S */
4417/* File: armv5te/binop.S */
4418    /*
4419     * Generic 32-bit binary operation.  Provide an "instr" line that
4420     * specifies an instruction that performs "result = r0 op r1".
4421     * This could be an ARM instruction or a function call.  (If the result
4422     * comes back in a register other than r0, you can override "result".)
4423     *
4424     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4425     * vCC (r1).  Useful for integer division and modulus.  Note that we
4426     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4427     * handles it correctly.
4428     *
4429     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4430     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4431     *      mul-float, div-float, rem-float
4432     */
4433    /* binop vAA, vBB, vCC */
4434    FETCH(r0, 1)                        @ r0<- CCBB
4435    mov     r9, rINST, lsr #8           @ r9<- AA
4436    mov     r3, r0, lsr #8              @ r3<- CC
4437    and     r2, r0, #255                @ r2<- BB
4438    GET_VREG(r1, r3)                    @ r1<- vCC
4439    GET_VREG(r0, r2)                    @ r0<- vBB
4440    .if 0
4441    cmp     r1, #0                      @ is second operand zero?
4442    beq     common_errDivideByZero
4443    .endif
4444
4445    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4446    and     r1, r1, #31                           @ optional op; may set condition codes
4447    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
4448    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4449    SET_VREG(r0, r9)               @ vAA<- r0
4450    GOTO_OPCODE(ip)                     @ jump to next instruction
4451    /* 11-14 instructions */
4452
4453
4454
4455/* ------------------------------ */
4456    .balign 64
4457.L_OP_SHR_INT: /* 0x99 */
4458/* File: armv5te/OP_SHR_INT.S */
4459/* File: armv5te/binop.S */
4460    /*
4461     * Generic 32-bit binary operation.  Provide an "instr" line that
4462     * specifies an instruction that performs "result = r0 op r1".
4463     * This could be an ARM instruction or a function call.  (If the result
4464     * comes back in a register other than r0, you can override "result".)
4465     *
4466     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4467     * vCC (r1).  Useful for integer division and modulus.  Note that we
4468     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4469     * handles it correctly.
4470     *
4471     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4472     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4473     *      mul-float, div-float, rem-float
4474     */
4475    /* binop vAA, vBB, vCC */
4476    FETCH(r0, 1)                        @ r0<- CCBB
4477    mov     r9, rINST, lsr #8           @ r9<- AA
4478    mov     r3, r0, lsr #8              @ r3<- CC
4479    and     r2, r0, #255                @ r2<- BB
4480    GET_VREG(r1, r3)                    @ r1<- vCC
4481    GET_VREG(r0, r2)                    @ r0<- vBB
4482    .if 0
4483    cmp     r1, #0                      @ is second operand zero?
4484    beq     common_errDivideByZero
4485    .endif
4486
4487    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4488    and     r1, r1, #31                           @ optional op; may set condition codes
4489    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
4490    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4491    SET_VREG(r0, r9)               @ vAA<- r0
4492    GOTO_OPCODE(ip)                     @ jump to next instruction
4493    /* 11-14 instructions */
4494
4495
4496
4497/* ------------------------------ */
4498    .balign 64
4499.L_OP_USHR_INT: /* 0x9a */
4500/* File: armv5te/OP_USHR_INT.S */
4501/* File: armv5te/binop.S */
4502    /*
4503     * Generic 32-bit binary operation.  Provide an "instr" line that
4504     * specifies an instruction that performs "result = r0 op r1".
4505     * This could be an ARM instruction or a function call.  (If the result
4506     * comes back in a register other than r0, you can override "result".)
4507     *
4508     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4509     * vCC (r1).  Useful for integer division and modulus.  Note that we
4510     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4511     * handles it correctly.
4512     *
4513     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4514     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4515     *      mul-float, div-float, rem-float
4516     */
4517    /* binop vAA, vBB, vCC */
4518    FETCH(r0, 1)                        @ r0<- CCBB
4519    mov     r9, rINST, lsr #8           @ r9<- AA
4520    mov     r3, r0, lsr #8              @ r3<- CC
4521    and     r2, r0, #255                @ r2<- BB
4522    GET_VREG(r1, r3)                    @ r1<- vCC
4523    GET_VREG(r0, r2)                    @ r0<- vBB
4524    .if 0
4525    cmp     r1, #0                      @ is second operand zero?
4526    beq     common_errDivideByZero
4527    .endif
4528
4529    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4530    and     r1, r1, #31                           @ optional op; may set condition codes
4531    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
4532    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4533    SET_VREG(r0, r9)               @ vAA<- r0
4534    GOTO_OPCODE(ip)                     @ jump to next instruction
4535    /* 11-14 instructions */
4536
4537
4538
4539/* ------------------------------ */
4540    .balign 64
4541.L_OP_ADD_LONG: /* 0x9b */
4542/* File: armv5te/OP_ADD_LONG.S */
4543/* File: armv5te/binopWide.S */
4544    /*
4545     * Generic 64-bit binary operation.  Provide an "instr" line that
4546     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4547     * This could be an ARM instruction or a function call.  (If the result
4548     * comes back in a register other than r0, you can override "result".)
4549     *
4550     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4551     * vCC (r1).  Useful for integer division and modulus.
4552     *
4553     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4554     *      xor-long, add-double, sub-double, mul-double, div-double,
4555     *      rem-double
4556     *
4557     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4558     */
4559    /* binop vAA, vBB, vCC */
4560    FETCH(r0, 1)                        @ r0<- CCBB
4561    mov     r9, rINST, lsr #8           @ r9<- AA
4562    and     r2, r0, #255                @ r2<- BB
4563    mov     r3, r0, lsr #8              @ r3<- CC
4564    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4565    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4566    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4567    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4568    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4569    .if 0
4570    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4571    beq     common_errDivideByZero
4572    .endif
4573    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4574
4575    adds    r0, r0, r2                           @ optional op; may set condition codes
4576    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
4577    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4578    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4579    GOTO_OPCODE(ip)                     @ jump to next instruction
4580    /* 14-17 instructions */
4581
4582
4583
4584/* ------------------------------ */
4585    .balign 64
4586.L_OP_SUB_LONG: /* 0x9c */
4587/* File: armv5te/OP_SUB_LONG.S */
4588/* File: armv5te/binopWide.S */
4589    /*
4590     * Generic 64-bit binary operation.  Provide an "instr" line that
4591     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4592     * This could be an ARM instruction or a function call.  (If the result
4593     * comes back in a register other than r0, you can override "result".)
4594     *
4595     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4596     * vCC (r1).  Useful for integer division and modulus.
4597     *
4598     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4599     *      xor-long, add-double, sub-double, mul-double, div-double,
4600     *      rem-double
4601     *
4602     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4603     */
4604    /* binop vAA, vBB, vCC */
4605    FETCH(r0, 1)                        @ r0<- CCBB
4606    mov     r9, rINST, lsr #8           @ r9<- AA
4607    and     r2, r0, #255                @ r2<- BB
4608    mov     r3, r0, lsr #8              @ r3<- CC
4609    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4610    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4611    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4612    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4613    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4614    .if 0
4615    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4616    beq     common_errDivideByZero
4617    .endif
4618    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4619
4620    subs    r0, r0, r2                           @ optional op; may set condition codes
4621    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
4622    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4623    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4624    GOTO_OPCODE(ip)                     @ jump to next instruction
4625    /* 14-17 instructions */
4626
4627
4628
4629/* ------------------------------ */
4630    .balign 64
4631.L_OP_MUL_LONG: /* 0x9d */
4632/* File: armv5te/OP_MUL_LONG.S */
4633    /*
4634     * Signed 64-bit integer multiply.
4635     *
4636     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
4637     *        WX
4638     *      x YZ
4639     *  --------
4640     *     ZW ZX
4641     *  YW YX
4642     *
4643     * The low word of the result holds ZX, the high word holds
4644     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
4645     * it doesn't fit in the low 64 bits.
4646     *
4647     * Unlike most ARM math operations, multiply instructions have
4648     * restrictions on using the same register more than once (Rd and Rm
4649     * cannot be the same).
4650     */
4651    /* mul-long vAA, vBB, vCC */
4652    FETCH(r0, 1)                        @ r0<- CCBB
4653    and     r2, r0, #255                @ r2<- BB
4654    mov     r3, r0, lsr #8              @ r3<- CC
4655    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4656    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4657    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4658    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4659    mul     ip, r2, r1                  @  ip<- ZxW
4660    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
4661    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
4662    mov     r0, rINST, lsr #8           @ r0<- AA
4663    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
4664    add     r0, rFP, r0, lsl #2         @ r0<- &fp[AA]
4665    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4666    b       .LOP_MUL_LONG_finish
4667
4668/* ------------------------------ */
4669    .balign 64
4670.L_OP_DIV_LONG: /* 0x9e */
4671/* File: armv5te/OP_DIV_LONG.S */
4672/* File: armv5te/binopWide.S */
4673    /*
4674     * Generic 64-bit binary operation.  Provide an "instr" line that
4675     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4676     * This could be an ARM instruction or a function call.  (If the result
4677     * comes back in a register other than r0, you can override "result".)
4678     *
4679     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4680     * vCC (r1).  Useful for integer division and modulus.
4681     *
4682     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4683     *      xor-long, add-double, sub-double, mul-double, div-double,
4684     *      rem-double
4685     *
4686     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4687     */
4688    /* binop vAA, vBB, vCC */
4689    FETCH(r0, 1)                        @ r0<- CCBB
4690    mov     r9, rINST, lsr #8           @ r9<- AA
4691    and     r2, r0, #255                @ r2<- BB
4692    mov     r3, r0, lsr #8              @ r3<- CC
4693    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4694    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4695    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4696    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4697    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4698    .if 1
4699    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4700    beq     common_errDivideByZero
4701    .endif
4702    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4703
4704                               @ optional op; may set condition codes
4705    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4706    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4707    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4708    GOTO_OPCODE(ip)                     @ jump to next instruction
4709    /* 14-17 instructions */
4710
4711
4712
4713/* ------------------------------ */
4714    .balign 64
4715.L_OP_REM_LONG: /* 0x9f */
4716/* File: armv5te/OP_REM_LONG.S */
4717/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
4718/* File: armv5te/binopWide.S */
4719    /*
4720     * Generic 64-bit binary operation.  Provide an "instr" line that
4721     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4722     * This could be an ARM instruction or a function call.  (If the result
4723     * comes back in a register other than r0, you can override "result".)
4724     *
4725     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4726     * vCC (r1).  Useful for integer division and modulus.
4727     *
4728     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4729     *      xor-long, add-double, sub-double, mul-double, div-double,
4730     *      rem-double
4731     *
4732     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4733     */
4734    /* binop vAA, vBB, vCC */
4735    FETCH(r0, 1)                        @ r0<- CCBB
4736    mov     r9, rINST, lsr #8           @ r9<- AA
4737    and     r2, r0, #255                @ r2<- BB
4738    mov     r3, r0, lsr #8              @ r3<- CC
4739    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4740    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4741    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4742    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4743    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4744    .if 1
4745    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4746    beq     common_errDivideByZero
4747    .endif
4748    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4749
4750                               @ optional op; may set condition codes
4751    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4752    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4753    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
4754    GOTO_OPCODE(ip)                     @ jump to next instruction
4755    /* 14-17 instructions */
4756
4757
4758
4759/* ------------------------------ */
4760    .balign 64
4761.L_OP_AND_LONG: /* 0xa0 */
4762/* File: armv5te/OP_AND_LONG.S */
4763/* File: armv5te/binopWide.S */
4764    /*
4765     * Generic 64-bit binary operation.  Provide an "instr" line that
4766     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4767     * This could be an ARM instruction or a function call.  (If the result
4768     * comes back in a register other than r0, you can override "result".)
4769     *
4770     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4771     * vCC (r1).  Useful for integer division and modulus.
4772     *
4773     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4774     *      xor-long, add-double, sub-double, mul-double, div-double,
4775     *      rem-double
4776     *
4777     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4778     */
4779    /* binop vAA, vBB, vCC */
4780    FETCH(r0, 1)                        @ r0<- CCBB
4781    mov     r9, rINST, lsr #8           @ r9<- AA
4782    and     r2, r0, #255                @ r2<- BB
4783    mov     r3, r0, lsr #8              @ r3<- CC
4784    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4785    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4786    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4787    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4788    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4789    .if 0
4790    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4791    beq     common_errDivideByZero
4792    .endif
4793    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4794
4795    and     r0, r0, r2                           @ optional op; may set condition codes
4796    and     r1, r1, r3                              @ result<- op, r0-r3 changed
4797    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4798    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4799    GOTO_OPCODE(ip)                     @ jump to next instruction
4800    /* 14-17 instructions */
4801
4802
4803
4804/* ------------------------------ */
4805    .balign 64
4806.L_OP_OR_LONG: /* 0xa1 */
4807/* File: armv5te/OP_OR_LONG.S */
4808/* File: armv5te/binopWide.S */
4809    /*
4810     * Generic 64-bit binary operation.  Provide an "instr" line that
4811     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4812     * This could be an ARM instruction or a function call.  (If the result
4813     * comes back in a register other than r0, you can override "result".)
4814     *
4815     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4816     * vCC (r1).  Useful for integer division and modulus.
4817     *
4818     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4819     *      xor-long, add-double, sub-double, mul-double, div-double,
4820     *      rem-double
4821     *
4822     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4823     */
4824    /* binop vAA, vBB, vCC */
4825    FETCH(r0, 1)                        @ r0<- CCBB
4826    mov     r9, rINST, lsr #8           @ r9<- AA
4827    and     r2, r0, #255                @ r2<- BB
4828    mov     r3, r0, lsr #8              @ r3<- CC
4829    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4830    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4831    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4832    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4833    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4834    .if 0
4835    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4836    beq     common_errDivideByZero
4837    .endif
4838    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4839
4840    orr     r0, r0, r2                           @ optional op; may set condition codes
4841    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
4842    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4843    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4844    GOTO_OPCODE(ip)                     @ jump to next instruction
4845    /* 14-17 instructions */
4846
4847
4848
4849/* ------------------------------ */
4850    .balign 64
4851.L_OP_XOR_LONG: /* 0xa2 */
4852/* File: armv5te/OP_XOR_LONG.S */
4853/* File: armv5te/binopWide.S */
4854    /*
4855     * Generic 64-bit binary operation.  Provide an "instr" line that
4856     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4857     * This could be an ARM instruction or a function call.  (If the result
4858     * comes back in a register other than r0, you can override "result".)
4859     *
4860     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4861     * vCC (r1).  Useful for integer division and modulus.
4862     *
4863     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4864     *      xor-long, add-double, sub-double, mul-double, div-double,
4865     *      rem-double
4866     *
4867     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4868     */
4869    /* binop vAA, vBB, vCC */
4870    FETCH(r0, 1)                        @ r0<- CCBB
4871    mov     r9, rINST, lsr #8           @ r9<- AA
4872    and     r2, r0, #255                @ r2<- BB
4873    mov     r3, r0, lsr #8              @ r3<- CC
4874    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4875    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4876    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4877    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4878    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4879    .if 0
4880    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4881    beq     common_errDivideByZero
4882    .endif
4883    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4884
4885    eor     r0, r0, r2                           @ optional op; may set condition codes
4886    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
4887    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4888    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4889    GOTO_OPCODE(ip)                     @ jump to next instruction
4890    /* 14-17 instructions */
4891
4892
4893
4894/* ------------------------------ */
4895    .balign 64
4896.L_OP_SHL_LONG: /* 0xa3 */
4897/* File: armv5te/OP_SHL_LONG.S */
4898    /*
4899     * Long integer shift.  This is different from the generic 32/64-bit
4900     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4901     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4902     * 6 bits of the shift distance.
4903     */
4904    /* shl-long vAA, vBB, vCC */
4905    FETCH(r0, 1)                        @ r0<- CCBB
4906    mov     r9, rINST, lsr #8           @ r9<- AA
4907    and     r3, r0, #255                @ r3<- BB
4908    mov     r0, r0, lsr #8              @ r0<- CC
4909    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4910    GET_VREG(r2, r0)                    @ r2<- vCC
4911    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4912    and     r2, r2, #63                 @ r2<- r2 & 0x3f
4913    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4914
4915    mov     r1, r1, asl r2              @  r1<- r1 << r2
4916    rsb     r3, r2, #32                 @  r3<- 32 - r2
4917    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
4918    subs    ip, r2, #32                 @  ip<- r2 - 32
4919    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
4920    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4921    b       .LOP_SHL_LONG_finish
4922
4923/* ------------------------------ */
4924    .balign 64
4925.L_OP_SHR_LONG: /* 0xa4 */
4926/* File: armv5te/OP_SHR_LONG.S */
4927    /*
4928     * Long integer shift.  This is different from the generic 32/64-bit
4929     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4930     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4931     * 6 bits of the shift distance.
4932     */
4933    /* shr-long vAA, vBB, vCC */
4934    FETCH(r0, 1)                        @ r0<- CCBB
4935    mov     r9, rINST, lsr #8           @ r9<- AA
4936    and     r3, r0, #255                @ r3<- BB
4937    mov     r0, r0, lsr #8              @ r0<- CC
4938    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4939    GET_VREG(r2, r0)                    @ r2<- vCC
4940    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4941    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4942    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4943
4944    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4945    rsb     r3, r2, #32                 @  r3<- 32 - r2
4946    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4947    subs    ip, r2, #32                 @  ip<- r2 - 32
4948    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
4949    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4950    b       .LOP_SHR_LONG_finish
4951
4952/* ------------------------------ */
4953    .balign 64
4954.L_OP_USHR_LONG: /* 0xa5 */
4955/* File: armv5te/OP_USHR_LONG.S */
4956    /*
4957     * Long integer shift.  This is different from the generic 32/64-bit
4958     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4959     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4960     * 6 bits of the shift distance.
4961     */
4962    /* ushr-long vAA, vBB, vCC */
4963    FETCH(r0, 1)                        @ r0<- CCBB
4964    mov     r9, rINST, lsr #8           @ r9<- AA
4965    and     r3, r0, #255                @ r3<- BB
4966    mov     r0, r0, lsr #8              @ r0<- CC
4967    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4968    GET_VREG(r2, r0)                    @ r2<- vCC
4969    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4970    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4971    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4972
4973    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4974    rsb     r3, r2, #32                 @  r3<- 32 - r2
4975    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4976    subs    ip, r2, #32                 @  ip<- r2 - 32
4977    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
4978    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4979    b       .LOP_USHR_LONG_finish
4980
4981/* ------------------------------ */
4982    .balign 64
4983.L_OP_ADD_FLOAT: /* 0xa6 */
4984/* File: arm-vfp/OP_ADD_FLOAT.S */
4985/* File: arm-vfp/fbinop.S */
4986    /*
4987     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4988     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4989     * use the "softfp" ABI, this must be an instruction, not a function call.
4990     *
4991     * For: add-float, sub-float, mul-float, div-float
4992     */
4993    /* floatop vAA, vBB, vCC */
4994    FETCH(r0, 1)                        @ r0<- CCBB
4995    mov     r9, rINST, lsr #8           @ r9<- AA
4996    mov     r3, r0, lsr #8              @ r3<- CC
4997    and     r2, r0, #255                @ r2<- BB
4998    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
4999    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5000    flds    s1, [r3]                    @ s1<- vCC
5001    flds    s0, [r2]                    @ s0<- vBB
5002
5003    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5004    fadds   s2, s0, s1                              @ s2<- op
5005    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5006    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5007    fsts    s2, [r9]                    @ vAA<- s2
5008    GOTO_OPCODE(ip)                     @ jump to next instruction
5009
5010
5011/* ------------------------------ */
5012    .balign 64
5013.L_OP_SUB_FLOAT: /* 0xa7 */
5014/* File: arm-vfp/OP_SUB_FLOAT.S */
5015/* File: arm-vfp/fbinop.S */
5016    /*
5017     * Generic 32-bit floating-point operation.  Provide an "instr" line that
5018     * specifies an instruction that performs "s2 = s0 op s1".  Because we
5019     * use the "softfp" ABI, this must be an instruction, not a function call.
5020     *
5021     * For: add-float, sub-float, mul-float, div-float
5022     */
5023    /* floatop vAA, vBB, vCC */
5024    FETCH(r0, 1)                        @ r0<- CCBB
5025    mov     r9, rINST, lsr #8           @ r9<- AA
5026    mov     r3, r0, lsr #8              @ r3<- CC
5027    and     r2, r0, #255                @ r2<- BB
5028    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5029    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5030    flds    s1, [r3]                    @ s1<- vCC
5031    flds    s0, [r2]                    @ s0<- vBB
5032
5033    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5034    fsubs   s2, s0, s1                              @ s2<- op
5035    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5036    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5037    fsts    s2, [r9]                    @ vAA<- s2
5038    GOTO_OPCODE(ip)                     @ jump to next instruction
5039
5040
5041/* ------------------------------ */
5042    .balign 64
5043.L_OP_MUL_FLOAT: /* 0xa8 */
5044/* File: arm-vfp/OP_MUL_FLOAT.S */
5045/* File: arm-vfp/fbinop.S */
5046    /*
5047     * Generic 32-bit floating-point operation.  Provide an "instr" line that
5048     * specifies an instruction that performs "s2 = s0 op s1".  Because we
5049     * use the "softfp" ABI, this must be an instruction, not a function call.
5050     *
5051     * For: add-float, sub-float, mul-float, div-float
5052     */
5053    /* floatop vAA, vBB, vCC */
5054    FETCH(r0, 1)                        @ r0<- CCBB
5055    mov     r9, rINST, lsr #8           @ r9<- AA
5056    mov     r3, r0, lsr #8              @ r3<- CC
5057    and     r2, r0, #255                @ r2<- BB
5058    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5059    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5060    flds    s1, [r3]                    @ s1<- vCC
5061    flds    s0, [r2]                    @ s0<- vBB
5062
5063    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5064    fmuls   s2, s0, s1                              @ s2<- op
5065    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5066    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5067    fsts    s2, [r9]                    @ vAA<- s2
5068    GOTO_OPCODE(ip)                     @ jump to next instruction
5069
5070
5071/* ------------------------------ */
5072    .balign 64
5073.L_OP_DIV_FLOAT: /* 0xa9 */
5074/* File: arm-vfp/OP_DIV_FLOAT.S */
5075/* File: arm-vfp/fbinop.S */
5076    /*
5077     * Generic 32-bit floating-point operation.  Provide an "instr" line that
5078     * specifies an instruction that performs "s2 = s0 op s1".  Because we
5079     * use the "softfp" ABI, this must be an instruction, not a function call.
5080     *
5081     * For: add-float, sub-float, mul-float, div-float
5082     */
5083    /* floatop vAA, vBB, vCC */
5084    FETCH(r0, 1)                        @ r0<- CCBB
5085    mov     r9, rINST, lsr #8           @ r9<- AA
5086    mov     r3, r0, lsr #8              @ r3<- CC
5087    and     r2, r0, #255                @ r2<- BB
5088    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5089    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5090    flds    s1, [r3]                    @ s1<- vCC
5091    flds    s0, [r2]                    @ s0<- vBB
5092
5093    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5094    fdivs   s2, s0, s1                              @ s2<- op
5095    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5096    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5097    fsts    s2, [r9]                    @ vAA<- s2
5098    GOTO_OPCODE(ip)                     @ jump to next instruction
5099
5100
5101/* ------------------------------ */
5102    .balign 64
5103.L_OP_REM_FLOAT: /* 0xaa */
5104/* File: armv5te/OP_REM_FLOAT.S */
5105/* EABI doesn't define a float remainder function, but libm does */
5106/* File: armv5te/binop.S */
5107    /*
5108     * Generic 32-bit binary operation.  Provide an "instr" line that
5109     * specifies an instruction that performs "result = r0 op r1".
5110     * This could be an ARM instruction or a function call.  (If the result
5111     * comes back in a register other than r0, you can override "result".)
5112     *
5113     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5114     * vCC (r1).  Useful for integer division and modulus.  Note that we
5115     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5116     * handles it correctly.
5117     *
5118     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5119     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5120     *      mul-float, div-float, rem-float
5121     */
5122    /* binop vAA, vBB, vCC */
5123    FETCH(r0, 1)                        @ r0<- CCBB
5124    mov     r9, rINST, lsr #8           @ r9<- AA
5125    mov     r3, r0, lsr #8              @ r3<- CC
5126    and     r2, r0, #255                @ r2<- BB
5127    GET_VREG(r1, r3)                    @ r1<- vCC
5128    GET_VREG(r0, r2)                    @ r0<- vBB
5129    .if 0
5130    cmp     r1, #0                      @ is second operand zero?
5131    beq     common_errDivideByZero
5132    .endif
5133
5134    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5135                               @ optional op; may set condition codes
5136    bl      fmodf                              @ r0<- op, r0-r3 changed
5137    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5138    SET_VREG(r0, r9)               @ vAA<- r0
5139    GOTO_OPCODE(ip)                     @ jump to next instruction
5140    /* 11-14 instructions */
5141
5142
5143
5144/* ------------------------------ */
5145    .balign 64
5146.L_OP_ADD_DOUBLE: /* 0xab */
5147/* File: arm-vfp/OP_ADD_DOUBLE.S */
5148/* File: arm-vfp/fbinopWide.S */
5149    /*
5150     * Generic 64-bit double-precision floating point binary operation.
5151     * Provide an "instr" line that specifies an instruction that performs
5152     * "d2 = d0 op d1".
5153     *
5154     * for: add-double, sub-double, mul-double, div-double
5155     */
5156    /* doubleop vAA, vBB, vCC */
5157    FETCH(r0, 1)                        @ r0<- CCBB
5158    mov     r9, rINST, lsr #8           @ r9<- AA
5159    mov     r3, r0, lsr #8              @ r3<- CC
5160    and     r2, r0, #255                @ r2<- BB
5161    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5162    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5163    fldd    d1, [r3]                    @ d1<- vCC
5164    fldd    d0, [r2]                    @ d0<- vBB
5165
5166    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5167    faddd   d2, d0, d1                              @ s2<- op
5168    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5169    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5170    fstd    d2, [r9]                    @ vAA<- d2
5171    GOTO_OPCODE(ip)                     @ jump to next instruction
5172
5173
5174/* ------------------------------ */
5175    .balign 64
5176.L_OP_SUB_DOUBLE: /* 0xac */
5177/* File: arm-vfp/OP_SUB_DOUBLE.S */
5178/* File: arm-vfp/fbinopWide.S */
5179    /*
5180     * Generic 64-bit double-precision floating point binary operation.
5181     * Provide an "instr" line that specifies an instruction that performs
5182     * "d2 = d0 op d1".
5183     *
5184     * for: add-double, sub-double, mul-double, div-double
5185     */
5186    /* doubleop vAA, vBB, vCC */
5187    FETCH(r0, 1)                        @ r0<- CCBB
5188    mov     r9, rINST, lsr #8           @ r9<- AA
5189    mov     r3, r0, lsr #8              @ r3<- CC
5190    and     r2, r0, #255                @ r2<- BB
5191    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5192    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5193    fldd    d1, [r3]                    @ d1<- vCC
5194    fldd    d0, [r2]                    @ d0<- vBB
5195
5196    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5197    fsubd   d2, d0, d1                              @ s2<- op
5198    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5199    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5200    fstd    d2, [r9]                    @ vAA<- d2
5201    GOTO_OPCODE(ip)                     @ jump to next instruction
5202
5203
5204/* ------------------------------ */
5205    .balign 64
5206.L_OP_MUL_DOUBLE: /* 0xad */
5207/* File: arm-vfp/OP_MUL_DOUBLE.S */
5208/* File: arm-vfp/fbinopWide.S */
5209    /*
5210     * Generic 64-bit double-precision floating point binary operation.
5211     * Provide an "instr" line that specifies an instruction that performs
5212     * "d2 = d0 op d1".
5213     *
5214     * for: add-double, sub-double, mul-double, div-double
5215     */
5216    /* doubleop 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    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5222    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5223    fldd    d1, [r3]                    @ d1<- vCC
5224    fldd    d0, [r2]                    @ d0<- vBB
5225
5226    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5227    fmuld   d2, d0, d1                              @ s2<- op
5228    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5229    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5230    fstd    d2, [r9]                    @ vAA<- d2
5231    GOTO_OPCODE(ip)                     @ jump to next instruction
5232
5233
5234/* ------------------------------ */
5235    .balign 64
5236.L_OP_DIV_DOUBLE: /* 0xae */
5237/* File: arm-vfp/OP_DIV_DOUBLE.S */
5238/* File: arm-vfp/fbinopWide.S */
5239    /*
5240     * Generic 64-bit double-precision floating point binary operation.
5241     * Provide an "instr" line that specifies an instruction that performs
5242     * "d2 = d0 op d1".
5243     *
5244     * for: add-double, sub-double, mul-double, div-double
5245     */
5246    /* doubleop vAA, vBB, vCC */
5247    FETCH(r0, 1)                        @ r0<- CCBB
5248    mov     r9, rINST, lsr #8           @ r9<- AA
5249    mov     r3, r0, lsr #8              @ r3<- CC
5250    and     r2, r0, #255                @ r2<- BB
5251    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5252    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5253    fldd    d1, [r3]                    @ d1<- vCC
5254    fldd    d0, [r2]                    @ d0<- vBB
5255
5256    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5257    fdivd   d2, d0, d1                              @ s2<- op
5258    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5259    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5260    fstd    d2, [r9]                    @ vAA<- d2
5261    GOTO_OPCODE(ip)                     @ jump to next instruction
5262
5263
5264/* ------------------------------ */
5265    .balign 64
5266.L_OP_REM_DOUBLE: /* 0xaf */
5267/* File: armv5te/OP_REM_DOUBLE.S */
5268/* EABI doesn't define a double remainder function, but libm does */
5269/* File: armv5te/binopWide.S */
5270    /*
5271     * Generic 64-bit binary operation.  Provide an "instr" line that
5272     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5273     * This could be an ARM instruction or a function call.  (If the result
5274     * comes back in a register other than r0, you can override "result".)
5275     *
5276     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5277     * vCC (r1).  Useful for integer division and modulus.
5278     *
5279     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5280     *      xor-long, add-double, sub-double, mul-double, div-double,
5281     *      rem-double
5282     *
5283     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5284     */
5285    /* binop vAA, vBB, vCC */
5286    FETCH(r0, 1)                        @ r0<- CCBB
5287    mov     r9, rINST, lsr #8           @ r9<- AA
5288    and     r2, r0, #255                @ r2<- BB
5289    mov     r3, r0, lsr #8              @ r3<- CC
5290    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5291    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5292    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5293    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5294    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5295    .if 0
5296    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5297    beq     common_errDivideByZero
5298    .endif
5299    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5300
5301                               @ optional op; may set condition codes
5302    bl      fmod                              @ result<- op, r0-r3 changed
5303    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5304    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5305    GOTO_OPCODE(ip)                     @ jump to next instruction
5306    /* 14-17 instructions */
5307
5308
5309
5310/* ------------------------------ */
5311    .balign 64
5312.L_OP_ADD_INT_2ADDR: /* 0xb0 */
5313/* File: armv5te/OP_ADD_INT_2ADDR.S */
5314/* File: armv5te/binop2addr.S */
5315    /*
5316     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5317     * that specifies an instruction that performs "result = r0 op r1".
5318     * This could be an ARM instruction or a function call.  (If the result
5319     * comes back in a register other than r0, you can override "result".)
5320     *
5321     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5322     * vCC (r1).  Useful for integer division and modulus.
5323     *
5324     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5325     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5326     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5327     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5328     */
5329    /* binop/2addr vA, vB */
5330    mov     r9, rINST, lsr #8           @ r9<- A+
5331    mov     r3, rINST, lsr #12          @ r3<- B
5332    and     r9, r9, #15
5333    GET_VREG(r1, r3)                    @ r1<- vB
5334    GET_VREG(r0, r9)                    @ r0<- vA
5335    .if 0
5336    cmp     r1, #0                      @ is second operand zero?
5337    beq     common_errDivideByZero
5338    .endif
5339    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5340
5341                               @ optional op; may set condition codes
5342    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
5343    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5344    SET_VREG(r0, r9)               @ vAA<- r0
5345    GOTO_OPCODE(ip)                     @ jump to next instruction
5346    /* 10-13 instructions */
5347
5348
5349
5350/* ------------------------------ */
5351    .balign 64
5352.L_OP_SUB_INT_2ADDR: /* 0xb1 */
5353/* File: armv5te/OP_SUB_INT_2ADDR.S */
5354/* File: armv5te/binop2addr.S */
5355    /*
5356     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5357     * that specifies an instruction that performs "result = r0 op r1".
5358     * This could be an ARM instruction or a function call.  (If the result
5359     * comes back in a register other than r0, you can override "result".)
5360     *
5361     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5362     * vCC (r1).  Useful for integer division and modulus.
5363     *
5364     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5365     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5366     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5367     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5368     */
5369    /* binop/2addr vA, vB */
5370    mov     r9, rINST, lsr #8           @ r9<- A+
5371    mov     r3, rINST, lsr #12          @ r3<- B
5372    and     r9, r9, #15
5373    GET_VREG(r1, r3)                    @ r1<- vB
5374    GET_VREG(r0, r9)                    @ r0<- vA
5375    .if 0
5376    cmp     r1, #0                      @ is second operand zero?
5377    beq     common_errDivideByZero
5378    .endif
5379    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5380
5381                               @ optional op; may set condition codes
5382    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
5383    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5384    SET_VREG(r0, r9)               @ vAA<- r0
5385    GOTO_OPCODE(ip)                     @ jump to next instruction
5386    /* 10-13 instructions */
5387
5388
5389
5390/* ------------------------------ */
5391    .balign 64
5392.L_OP_MUL_INT_2ADDR: /* 0xb2 */
5393/* File: armv5te/OP_MUL_INT_2ADDR.S */
5394/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
5395/* File: armv5te/binop2addr.S */
5396    /*
5397     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5398     * that specifies an instruction that performs "result = r0 op r1".
5399     * This could be an ARM instruction or a function call.  (If the result
5400     * comes back in a register other than r0, you can override "result".)
5401     *
5402     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5403     * vCC (r1).  Useful for integer division and modulus.
5404     *
5405     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5406     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5407     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5408     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5409     */
5410    /* binop/2addr vA, vB */
5411    mov     r9, rINST, lsr #8           @ r9<- A+
5412    mov     r3, rINST, lsr #12          @ r3<- B
5413    and     r9, r9, #15
5414    GET_VREG(r1, r3)                    @ r1<- vB
5415    GET_VREG(r0, r9)                    @ r0<- vA
5416    .if 0
5417    cmp     r1, #0                      @ is second operand zero?
5418    beq     common_errDivideByZero
5419    .endif
5420    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5421
5422                               @ optional op; may set condition codes
5423    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
5424    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5425    SET_VREG(r0, r9)               @ vAA<- r0
5426    GOTO_OPCODE(ip)                     @ jump to next instruction
5427    /* 10-13 instructions */
5428
5429
5430
5431/* ------------------------------ */
5432    .balign 64
5433.L_OP_DIV_INT_2ADDR: /* 0xb3 */
5434/* File: armv5te/OP_DIV_INT_2ADDR.S */
5435/* File: armv5te/binop2addr.S */
5436    /*
5437     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5438     * that specifies an instruction that performs "result = r0 op r1".
5439     * This could be an ARM instruction or a function call.  (If the result
5440     * comes back in a register other than r0, you can override "result".)
5441     *
5442     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5443     * vCC (r1).  Useful for integer division and modulus.
5444     *
5445     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5446     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5447     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5448     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5449     */
5450    /* binop/2addr vA, vB */
5451    mov     r9, rINST, lsr #8           @ r9<- A+
5452    mov     r3, rINST, lsr #12          @ r3<- B
5453    and     r9, r9, #15
5454    GET_VREG(r1, r3)                    @ r1<- vB
5455    GET_VREG(r0, r9)                    @ r0<- vA
5456    .if 1
5457    cmp     r1, #0                      @ is second operand zero?
5458    beq     common_errDivideByZero
5459    .endif
5460    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5461
5462                               @ optional op; may set condition codes
5463    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
5464    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5465    SET_VREG(r0, r9)               @ vAA<- r0
5466    GOTO_OPCODE(ip)                     @ jump to next instruction
5467    /* 10-13 instructions */
5468
5469
5470
5471/* ------------------------------ */
5472    .balign 64
5473.L_OP_REM_INT_2ADDR: /* 0xb4 */
5474/* File: armv5te/OP_REM_INT_2ADDR.S */
5475/* idivmod returns quotient in r0 and remainder in r1 */
5476/* File: armv5te/binop2addr.S */
5477    /*
5478     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5479     * that specifies an instruction that performs "result = r0 op r1".
5480     * This could be an ARM instruction or a function call.  (If the result
5481     * comes back in a register other than r0, you can override "result".)
5482     *
5483     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5484     * vCC (r1).  Useful for integer division and modulus.
5485     *
5486     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5487     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5488     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5489     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5490     */
5491    /* binop/2addr vA, vB */
5492    mov     r9, rINST, lsr #8           @ r9<- A+
5493    mov     r3, rINST, lsr #12          @ r3<- B
5494    and     r9, r9, #15
5495    GET_VREG(r1, r3)                    @ r1<- vB
5496    GET_VREG(r0, r9)                    @ r0<- vA
5497    .if 1
5498    cmp     r1, #0                      @ is second operand zero?
5499    beq     common_errDivideByZero
5500    .endif
5501    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5502
5503                               @ optional op; may set condition codes
5504    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
5505    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5506    SET_VREG(r1, r9)               @ vAA<- r1
5507    GOTO_OPCODE(ip)                     @ jump to next instruction
5508    /* 10-13 instructions */
5509
5510
5511
5512/* ------------------------------ */
5513    .balign 64
5514.L_OP_AND_INT_2ADDR: /* 0xb5 */
5515/* File: armv5te/OP_AND_INT_2ADDR.S */
5516/* File: armv5te/binop2addr.S */
5517    /*
5518     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5519     * that specifies an instruction that performs "result = r0 op r1".
5520     * This could be an ARM instruction or a function call.  (If the result
5521     * comes back in a register other than r0, you can override "result".)
5522     *
5523     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5524     * vCC (r1).  Useful for integer division and modulus.
5525     *
5526     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5527     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5528     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5529     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5530     */
5531    /* binop/2addr vA, vB */
5532    mov     r9, rINST, lsr #8           @ r9<- A+
5533    mov     r3, rINST, lsr #12          @ r3<- B
5534    and     r9, r9, #15
5535    GET_VREG(r1, r3)                    @ r1<- vB
5536    GET_VREG(r0, r9)                    @ r0<- vA
5537    .if 0
5538    cmp     r1, #0                      @ is second operand zero?
5539    beq     common_errDivideByZero
5540    .endif
5541    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5542
5543                               @ optional op; may set condition codes
5544    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
5545    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5546    SET_VREG(r0, r9)               @ vAA<- r0
5547    GOTO_OPCODE(ip)                     @ jump to next instruction
5548    /* 10-13 instructions */
5549
5550
5551
5552/* ------------------------------ */
5553    .balign 64
5554.L_OP_OR_INT_2ADDR: /* 0xb6 */
5555/* File: armv5te/OP_OR_INT_2ADDR.S */
5556/* File: armv5te/binop2addr.S */
5557    /*
5558     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5559     * that specifies an instruction that performs "result = r0 op r1".
5560     * This could be an ARM instruction or a function call.  (If the result
5561     * comes back in a register other than r0, you can override "result".)
5562     *
5563     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5564     * vCC (r1).  Useful for integer division and modulus.
5565     *
5566     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5567     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5568     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5569     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5570     */
5571    /* binop/2addr vA, vB */
5572    mov     r9, rINST, lsr #8           @ r9<- A+
5573    mov     r3, rINST, lsr #12          @ r3<- B
5574    and     r9, r9, #15
5575    GET_VREG(r1, r3)                    @ r1<- vB
5576    GET_VREG(r0, r9)                    @ r0<- vA
5577    .if 0
5578    cmp     r1, #0                      @ is second operand zero?
5579    beq     common_errDivideByZero
5580    .endif
5581    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5582
5583                               @ optional op; may set condition codes
5584    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
5585    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5586    SET_VREG(r0, r9)               @ vAA<- r0
5587    GOTO_OPCODE(ip)                     @ jump to next instruction
5588    /* 10-13 instructions */
5589
5590
5591
5592/* ------------------------------ */
5593    .balign 64
5594.L_OP_XOR_INT_2ADDR: /* 0xb7 */
5595/* File: armv5te/OP_XOR_INT_2ADDR.S */
5596/* File: armv5te/binop2addr.S */
5597    /*
5598     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5599     * that specifies an instruction that performs "result = r0 op r1".
5600     * This could be an ARM instruction or a function call.  (If the result
5601     * comes back in a register other than r0, you can override "result".)
5602     *
5603     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5604     * vCC (r1).  Useful for integer division and modulus.
5605     *
5606     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5607     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5608     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5609     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5610     */
5611    /* binop/2addr vA, vB */
5612    mov     r9, rINST, lsr #8           @ r9<- A+
5613    mov     r3, rINST, lsr #12          @ r3<- B
5614    and     r9, r9, #15
5615    GET_VREG(r1, r3)                    @ r1<- vB
5616    GET_VREG(r0, r9)                    @ r0<- vA
5617    .if 0
5618    cmp     r1, #0                      @ is second operand zero?
5619    beq     common_errDivideByZero
5620    .endif
5621    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5622
5623                               @ optional op; may set condition codes
5624    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
5625    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5626    SET_VREG(r0, r9)               @ vAA<- r0
5627    GOTO_OPCODE(ip)                     @ jump to next instruction
5628    /* 10-13 instructions */
5629
5630
5631
5632/* ------------------------------ */
5633    .balign 64
5634.L_OP_SHL_INT_2ADDR: /* 0xb8 */
5635/* File: armv5te/OP_SHL_INT_2ADDR.S */
5636/* File: armv5te/binop2addr.S */
5637    /*
5638     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5639     * that specifies an instruction that performs "result = r0 op r1".
5640     * This could be an ARM instruction or a function call.  (If the result
5641     * comes back in a register other than r0, you can override "result".)
5642     *
5643     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5644     * vCC (r1).  Useful for integer division and modulus.
5645     *
5646     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5647     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5648     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5649     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5650     */
5651    /* binop/2addr vA, vB */
5652    mov     r9, rINST, lsr #8           @ r9<- A+
5653    mov     r3, rINST, lsr #12          @ r3<- B
5654    and     r9, r9, #15
5655    GET_VREG(r1, r3)                    @ r1<- vB
5656    GET_VREG(r0, r9)                    @ r0<- vA
5657    .if 0
5658    cmp     r1, #0                      @ is second operand zero?
5659    beq     common_errDivideByZero
5660    .endif
5661    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5662
5663    and     r1, r1, #31                           @ optional op; may set condition codes
5664    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
5665    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5666    SET_VREG(r0, r9)               @ vAA<- r0
5667    GOTO_OPCODE(ip)                     @ jump to next instruction
5668    /* 10-13 instructions */
5669
5670
5671
5672/* ------------------------------ */
5673    .balign 64
5674.L_OP_SHR_INT_2ADDR: /* 0xb9 */
5675/* File: armv5te/OP_SHR_INT_2ADDR.S */
5676/* File: armv5te/binop2addr.S */
5677    /*
5678     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5679     * that specifies an instruction that performs "result = r0 op r1".
5680     * This could be an ARM instruction or a function call.  (If the result
5681     * comes back in a register other than r0, you can override "result".)
5682     *
5683     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5684     * vCC (r1).  Useful for integer division and modulus.
5685     *
5686     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5687     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5688     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5689     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5690     */
5691    /* binop/2addr vA, vB */
5692    mov     r9, rINST, lsr #8           @ r9<- A+
5693    mov     r3, rINST, lsr #12          @ r3<- B
5694    and     r9, r9, #15
5695    GET_VREG(r1, r3)                    @ r1<- vB
5696    GET_VREG(r0, r9)                    @ r0<- vA
5697    .if 0
5698    cmp     r1, #0                      @ is second operand zero?
5699    beq     common_errDivideByZero
5700    .endif
5701    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5702
5703    and     r1, r1, #31                           @ optional op; may set condition codes
5704    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
5705    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5706    SET_VREG(r0, r9)               @ vAA<- r0
5707    GOTO_OPCODE(ip)                     @ jump to next instruction
5708    /* 10-13 instructions */
5709
5710
5711
5712/* ------------------------------ */
5713    .balign 64
5714.L_OP_USHR_INT_2ADDR: /* 0xba */
5715/* File: armv5te/OP_USHR_INT_2ADDR.S */
5716/* File: armv5te/binop2addr.S */
5717    /*
5718     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5719     * that specifies an instruction that performs "result = r0 op r1".
5720     * This could be an ARM instruction or a function call.  (If the result
5721     * comes back in a register other than r0, you can override "result".)
5722     *
5723     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5724     * vCC (r1).  Useful for integer division and modulus.
5725     *
5726     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5727     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5728     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5729     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5730     */
5731    /* binop/2addr vA, vB */
5732    mov     r9, rINST, lsr #8           @ r9<- A+
5733    mov     r3, rINST, lsr #12          @ r3<- B
5734    and     r9, r9, #15
5735    GET_VREG(r1, r3)                    @ r1<- vB
5736    GET_VREG(r0, r9)                    @ r0<- vA
5737    .if 0
5738    cmp     r1, #0                      @ is second operand zero?
5739    beq     common_errDivideByZero
5740    .endif
5741    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5742
5743    and     r1, r1, #31                           @ optional op; may set condition codes
5744    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
5745    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5746    SET_VREG(r0, r9)               @ vAA<- r0
5747    GOTO_OPCODE(ip)                     @ jump to next instruction
5748    /* 10-13 instructions */
5749
5750
5751
5752/* ------------------------------ */
5753    .balign 64
5754.L_OP_ADD_LONG_2ADDR: /* 0xbb */
5755/* File: armv5te/OP_ADD_LONG_2ADDR.S */
5756/* File: armv5te/binopWide2addr.S */
5757    /*
5758     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5759     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5760     * This could be an ARM instruction or a function call.  (If the result
5761     * comes back in a register other than r0, you can override "result".)
5762     *
5763     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5764     * vCC (r1).  Useful for integer division and modulus.
5765     *
5766     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5767     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5768     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5769     *      rem-double/2addr
5770     */
5771    /* binop/2addr vA, vB */
5772    mov     r9, rINST, lsr #8           @ r9<- A+
5773    mov     r1, rINST, lsr #12          @ r1<- B
5774    and     r9, r9, #15
5775    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5776    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5777    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5778    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5779    .if 0
5780    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5781    beq     common_errDivideByZero
5782    .endif
5783    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5784
5785    adds    r0, r0, r2                           @ optional op; may set condition codes
5786    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
5787    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5788    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5789    GOTO_OPCODE(ip)                     @ jump to next instruction
5790    /* 12-15 instructions */
5791
5792
5793
5794/* ------------------------------ */
5795    .balign 64
5796.L_OP_SUB_LONG_2ADDR: /* 0xbc */
5797/* File: armv5te/OP_SUB_LONG_2ADDR.S */
5798/* File: armv5te/binopWide2addr.S */
5799    /*
5800     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5801     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5802     * This could be an ARM instruction or a function call.  (If the result
5803     * comes back in a register other than r0, you can override "result".)
5804     *
5805     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5806     * vCC (r1).  Useful for integer division and modulus.
5807     *
5808     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5809     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5810     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5811     *      rem-double/2addr
5812     */
5813    /* binop/2addr vA, vB */
5814    mov     r9, rINST, lsr #8           @ r9<- A+
5815    mov     r1, rINST, lsr #12          @ r1<- B
5816    and     r9, r9, #15
5817    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5818    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5819    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5820    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5821    .if 0
5822    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5823    beq     common_errDivideByZero
5824    .endif
5825    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5826
5827    subs    r0, r0, r2                           @ optional op; may set condition codes
5828    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
5829    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5830    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5831    GOTO_OPCODE(ip)                     @ jump to next instruction
5832    /* 12-15 instructions */
5833
5834
5835
5836/* ------------------------------ */
5837    .balign 64
5838.L_OP_MUL_LONG_2ADDR: /* 0xbd */
5839/* File: armv5te/OP_MUL_LONG_2ADDR.S */
5840    /*
5841     * Signed 64-bit integer multiply, "/2addr" version.
5842     *
5843     * See OP_MUL_LONG for an explanation.
5844     *
5845     * We get a little tight on registers, so to avoid looking up &fp[A]
5846     * again we stuff it into rINST.
5847     */
5848    /* mul-long/2addr vA, vB */
5849    mov     r9, rINST, lsr #8           @ r9<- A+
5850    mov     r1, rINST, lsr #12          @ r1<- B
5851    and     r9, r9, #15
5852    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5853    add     rINST, rFP, r9, lsl #2      @ rINST<- &fp[A]
5854    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5855    ldmia   rINST, {r0-r1}              @ r0/r1<- vAA/vAA+1
5856    mul     ip, r2, r1                  @  ip<- ZxW
5857    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
5858    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
5859    mov     r0, rINST                   @ r0<- &fp[A] (free up rINST)
5860    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5861    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
5862    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5863    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
5864    GOTO_OPCODE(ip)                     @ jump to next instruction
5865
5866
5867/* ------------------------------ */
5868    .balign 64
5869.L_OP_DIV_LONG_2ADDR: /* 0xbe */
5870/* File: armv5te/OP_DIV_LONG_2ADDR.S */
5871/* File: armv5te/binopWide2addr.S */
5872    /*
5873     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5874     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5875     * This could be an ARM instruction or a function call.  (If the result
5876     * comes back in a register other than r0, you can override "result".)
5877     *
5878     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5879     * vCC (r1).  Useful for integer division and modulus.
5880     *
5881     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5882     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5883     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5884     *      rem-double/2addr
5885     */
5886    /* binop/2addr vA, vB */
5887    mov     r9, rINST, lsr #8           @ r9<- A+
5888    mov     r1, rINST, lsr #12          @ r1<- B
5889    and     r9, r9, #15
5890    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5891    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5892    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5893    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5894    .if 1
5895    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5896    beq     common_errDivideByZero
5897    .endif
5898    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5899
5900                               @ optional op; may set condition codes
5901    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5902    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5903    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5904    GOTO_OPCODE(ip)                     @ jump to next instruction
5905    /* 12-15 instructions */
5906
5907
5908
5909/* ------------------------------ */
5910    .balign 64
5911.L_OP_REM_LONG_2ADDR: /* 0xbf */
5912/* File: armv5te/OP_REM_LONG_2ADDR.S */
5913/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
5914/* File: armv5te/binopWide2addr.S */
5915    /*
5916     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5917     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5918     * This could be an ARM instruction or a function call.  (If the result
5919     * comes back in a register other than r0, you can override "result".)
5920     *
5921     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5922     * vCC (r1).  Useful for integer division and modulus.
5923     *
5924     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5925     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5926     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5927     *      rem-double/2addr
5928     */
5929    /* binop/2addr vA, vB */
5930    mov     r9, rINST, lsr #8           @ r9<- A+
5931    mov     r1, rINST, lsr #12          @ r1<- B
5932    and     r9, r9, #15
5933    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5934    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5935    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5936    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5937    .if 1
5938    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5939    beq     common_errDivideByZero
5940    .endif
5941    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5942
5943                               @ optional op; may set condition codes
5944    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5945    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5946    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
5947    GOTO_OPCODE(ip)                     @ jump to next instruction
5948    /* 12-15 instructions */
5949
5950
5951
5952/* ------------------------------ */
5953    .balign 64
5954.L_OP_AND_LONG_2ADDR: /* 0xc0 */
5955/* File: armv5te/OP_AND_LONG_2ADDR.S */
5956/* File: armv5te/binopWide2addr.S */
5957    /*
5958     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5959     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5960     * This could be an ARM instruction or a function call.  (If the result
5961     * comes back in a register other than r0, you can override "result".)
5962     *
5963     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5964     * vCC (r1).  Useful for integer division and modulus.
5965     *
5966     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5967     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5968     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5969     *      rem-double/2addr
5970     */
5971    /* binop/2addr vA, vB */
5972    mov     r9, rINST, lsr #8           @ r9<- A+
5973    mov     r1, rINST, lsr #12          @ r1<- B
5974    and     r9, r9, #15
5975    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5976    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5977    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5978    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5979    .if 0
5980    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5981    beq     common_errDivideByZero
5982    .endif
5983    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5984
5985    and     r0, r0, r2                           @ optional op; may set condition codes
5986    and     r1, r1, r3                              @ result<- op, r0-r3 changed
5987    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5988    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5989    GOTO_OPCODE(ip)                     @ jump to next instruction
5990    /* 12-15 instructions */
5991
5992
5993
5994/* ------------------------------ */
5995    .balign 64
5996.L_OP_OR_LONG_2ADDR: /* 0xc1 */
5997/* File: armv5te/OP_OR_LONG_2ADDR.S */
5998/* File: armv5te/binopWide2addr.S */
5999    /*
6000     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6001     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6002     * This could be an ARM instruction or a function call.  (If the result
6003     * comes back in a register other than r0, you can override "result".)
6004     *
6005     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6006     * vCC (r1).  Useful for integer division and modulus.
6007     *
6008     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6009     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6010     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6011     *      rem-double/2addr
6012     */
6013    /* binop/2addr vA, vB */
6014    mov     r9, rINST, lsr #8           @ r9<- A+
6015    mov     r1, rINST, lsr #12          @ r1<- B
6016    and     r9, r9, #15
6017    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6018    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6019    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6020    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6021    .if 0
6022    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6023    beq     common_errDivideByZero
6024    .endif
6025    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6026
6027    orr     r0, r0, r2                           @ optional op; may set condition codes
6028    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
6029    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6030    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6031    GOTO_OPCODE(ip)                     @ jump to next instruction
6032    /* 12-15 instructions */
6033
6034
6035
6036/* ------------------------------ */
6037    .balign 64
6038.L_OP_XOR_LONG_2ADDR: /* 0xc2 */
6039/* File: armv5te/OP_XOR_LONG_2ADDR.S */
6040/* File: armv5te/binopWide2addr.S */
6041    /*
6042     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6043     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6044     * This could be an ARM instruction or a function call.  (If the result
6045     * comes back in a register other than r0, you can override "result".)
6046     *
6047     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6048     * vCC (r1).  Useful for integer division and modulus.
6049     *
6050     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6051     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6052     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6053     *      rem-double/2addr
6054     */
6055    /* binop/2addr vA, vB */
6056    mov     r9, rINST, lsr #8           @ r9<- A+
6057    mov     r1, rINST, lsr #12          @ r1<- B
6058    and     r9, r9, #15
6059    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6060    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6061    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6062    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6063    .if 0
6064    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6065    beq     common_errDivideByZero
6066    .endif
6067    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6068
6069    eor     r0, r0, r2                           @ optional op; may set condition codes
6070    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
6071    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6072    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6073    GOTO_OPCODE(ip)                     @ jump to next instruction
6074    /* 12-15 instructions */
6075
6076
6077
6078/* ------------------------------ */
6079    .balign 64
6080.L_OP_SHL_LONG_2ADDR: /* 0xc3 */
6081/* File: armv5te/OP_SHL_LONG_2ADDR.S */
6082    /*
6083     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6084     * 32-bit shift distance.
6085     */
6086    /* shl-long/2addr vA, vB */
6087    mov     r9, rINST, lsr #8           @ r9<- A+
6088    mov     r3, rINST, lsr #12          @ r3<- B
6089    and     r9, r9, #15
6090    GET_VREG(r2, r3)                    @ r2<- vB
6091    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6092    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6093    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6094
6095    mov     r1, r1, asl r2              @  r1<- r1 << r2
6096    rsb     r3, r2, #32                 @  r3<- 32 - r2
6097    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
6098    subs    ip, r2, #32                 @  ip<- r2 - 32
6099    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6100    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
6101    mov     r0, r0, asl r2              @  r0<- r0 << r2
6102    b       .LOP_SHL_LONG_2ADDR_finish
6103
6104/* ------------------------------ */
6105    .balign 64
6106.L_OP_SHR_LONG_2ADDR: /* 0xc4 */
6107/* File: armv5te/OP_SHR_LONG_2ADDR.S */
6108    /*
6109     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6110     * 32-bit shift distance.
6111     */
6112    /* shr-long/2addr vA, vB */
6113    mov     r9, rINST, lsr #8           @ r9<- A+
6114    mov     r3, rINST, lsr #12          @ r3<- B
6115    and     r9, r9, #15
6116    GET_VREG(r2, r3)                    @ r2<- vB
6117    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6118    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6119    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6120
6121    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6122    rsb     r3, r2, #32                 @  r3<- 32 - r2
6123    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6124    subs    ip, r2, #32                 @  ip<- r2 - 32
6125    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6126    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
6127    mov     r1, r1, asr r2              @  r1<- r1 >> r2
6128    b       .LOP_SHR_LONG_2ADDR_finish
6129
6130/* ------------------------------ */
6131    .balign 64
6132.L_OP_USHR_LONG_2ADDR: /* 0xc5 */
6133/* File: armv5te/OP_USHR_LONG_2ADDR.S */
6134    /*
6135     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6136     * 32-bit shift distance.
6137     */
6138    /* ushr-long/2addr vA, vB */
6139    mov     r9, rINST, lsr #8           @ r9<- A+
6140    mov     r3, rINST, lsr #12          @ r3<- B
6141    and     r9, r9, #15
6142    GET_VREG(r2, r3)                    @ r2<- vB
6143    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6144    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6145    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6146
6147    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6148    rsb     r3, r2, #32                 @  r3<- 32 - r2
6149    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6150    subs    ip, r2, #32                 @  ip<- r2 - 32
6151    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6152    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
6153    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
6154    b       .LOP_USHR_LONG_2ADDR_finish
6155
6156/* ------------------------------ */
6157    .balign 64
6158.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
6159/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */
6160/* File: arm-vfp/fbinop2addr.S */
6161    /*
6162     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6163     * an "instr" line that specifies an instruction that performs
6164     * "s2 = s0 op s1".
6165     *
6166     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6167     */
6168    /* binop/2addr vA, vB */
6169    mov     r3, rINST, lsr #12          @ r3<- B
6170    mov     r9, rINST, lsr #8           @ r9<- A+
6171    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6172    and     r9, r9, #15                 @ r9<- A
6173    flds    s1, [r3]                    @ s1<- vB
6174    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6175    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6176    flds    s0, [r9]                    @ s0<- vA
6177
6178    fadds   s2, s0, s1                              @ s2<- op
6179    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6180    fsts    s2, [r9]                    @ vAA<- s2
6181    GOTO_OPCODE(ip)                     @ jump to next instruction
6182
6183
6184/* ------------------------------ */
6185    .balign 64
6186.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
6187/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */
6188/* File: arm-vfp/fbinop2addr.S */
6189    /*
6190     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6191     * an "instr" line that specifies an instruction that performs
6192     * "s2 = s0 op s1".
6193     *
6194     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6195     */
6196    /* binop/2addr vA, vB */
6197    mov     r3, rINST, lsr #12          @ r3<- B
6198    mov     r9, rINST, lsr #8           @ r9<- A+
6199    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6200    and     r9, r9, #15                 @ r9<- A
6201    flds    s1, [r3]                    @ s1<- vB
6202    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6203    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6204    flds    s0, [r9]                    @ s0<- vA
6205
6206    fsubs   s2, s0, s1                              @ s2<- op
6207    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6208    fsts    s2, [r9]                    @ vAA<- s2
6209    GOTO_OPCODE(ip)                     @ jump to next instruction
6210
6211
6212/* ------------------------------ */
6213    .balign 64
6214.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
6215/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */
6216/* File: arm-vfp/fbinop2addr.S */
6217    /*
6218     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6219     * an "instr" line that specifies an instruction that performs
6220     * "s2 = s0 op s1".
6221     *
6222     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6223     */
6224    /* binop/2addr vA, vB */
6225    mov     r3, rINST, lsr #12          @ r3<- B
6226    mov     r9, rINST, lsr #8           @ r9<- A+
6227    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6228    and     r9, r9, #15                 @ r9<- A
6229    flds    s1, [r3]                    @ s1<- vB
6230    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6231    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6232    flds    s0, [r9]                    @ s0<- vA
6233
6234    fmuls   s2, s0, s1                              @ s2<- op
6235    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6236    fsts    s2, [r9]                    @ vAA<- s2
6237    GOTO_OPCODE(ip)                     @ jump to next instruction
6238
6239
6240/* ------------------------------ */
6241    .balign 64
6242.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
6243/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */
6244/* File: arm-vfp/fbinop2addr.S */
6245    /*
6246     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6247     * an "instr" line that specifies an instruction that performs
6248     * "s2 = s0 op s1".
6249     *
6250     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6251     */
6252    /* binop/2addr vA, vB */
6253    mov     r3, rINST, lsr #12          @ r3<- B
6254    mov     r9, rINST, lsr #8           @ r9<- A+
6255    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6256    and     r9, r9, #15                 @ r9<- A
6257    flds    s1, [r3]                    @ s1<- vB
6258    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6259    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6260    flds    s0, [r9]                    @ s0<- vA
6261
6262    fdivs   s2, s0, s1                              @ s2<- op
6263    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6264    fsts    s2, [r9]                    @ vAA<- s2
6265    GOTO_OPCODE(ip)                     @ jump to next instruction
6266
6267
6268/* ------------------------------ */
6269    .balign 64
6270.L_OP_REM_FLOAT_2ADDR: /* 0xca */
6271/* File: armv5te/OP_REM_FLOAT_2ADDR.S */
6272/* EABI doesn't define a float remainder function, but libm does */
6273/* File: armv5te/binop2addr.S */
6274    /*
6275     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6276     * that specifies an instruction that performs "result = r0 op r1".
6277     * This could be an ARM instruction or a function call.  (If the result
6278     * comes back in a register other than r0, you can override "result".)
6279     *
6280     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6281     * vCC (r1).  Useful for integer division and modulus.
6282     *
6283     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6284     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6285     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6286     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6287     */
6288    /* binop/2addr vA, vB */
6289    mov     r9, rINST, lsr #8           @ r9<- A+
6290    mov     r3, rINST, lsr #12          @ r3<- B
6291    and     r9, r9, #15
6292    GET_VREG(r1, r3)                    @ r1<- vB
6293    GET_VREG(r0, r9)                    @ r0<- vA
6294    .if 0
6295    cmp     r1, #0                      @ is second operand zero?
6296    beq     common_errDivideByZero
6297    .endif
6298    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6299
6300                               @ optional op; may set condition codes
6301    bl      fmodf                              @ r0<- op, r0-r3 changed
6302    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6303    SET_VREG(r0, r9)               @ vAA<- r0
6304    GOTO_OPCODE(ip)                     @ jump to next instruction
6305    /* 10-13 instructions */
6306
6307
6308
6309/* ------------------------------ */
6310    .balign 64
6311.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
6312/* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */
6313/* File: arm-vfp/fbinopWide2addr.S */
6314    /*
6315     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6316     * an "instr" line that specifies an instruction that performs
6317     * "d2 = d0 op d1".
6318     *
6319     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6320     *      div-double/2addr
6321     */
6322    /* binop/2addr vA, vB */
6323    mov     r3, rINST, lsr #12          @ r3<- B
6324    mov     r9, rINST, lsr #8           @ r9<- A+
6325    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6326    and     r9, r9, #15                 @ r9<- A
6327    fldd    d1, [r3]                    @ d1<- vB
6328    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6329    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6330    fldd    d0, [r9]                    @ d0<- vA
6331
6332    faddd   d2, d0, d1                              @ d2<- op
6333    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6334    fstd    d2, [r9]                    @ vAA<- d2
6335    GOTO_OPCODE(ip)                     @ jump to next instruction
6336
6337
6338/* ------------------------------ */
6339    .balign 64
6340.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
6341/* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */
6342/* File: arm-vfp/fbinopWide2addr.S */
6343    /*
6344     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6345     * an "instr" line that specifies an instruction that performs
6346     * "d2 = d0 op d1".
6347     *
6348     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6349     *      div-double/2addr
6350     */
6351    /* binop/2addr vA, vB */
6352    mov     r3, rINST, lsr #12          @ r3<- B
6353    mov     r9, rINST, lsr #8           @ r9<- A+
6354    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6355    and     r9, r9, #15                 @ r9<- A
6356    fldd    d1, [r3]                    @ d1<- vB
6357    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6358    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6359    fldd    d0, [r9]                    @ d0<- vA
6360
6361    fsubd   d2, d0, d1                              @ d2<- op
6362    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6363    fstd    d2, [r9]                    @ vAA<- d2
6364    GOTO_OPCODE(ip)                     @ jump to next instruction
6365
6366
6367/* ------------------------------ */
6368    .balign 64
6369.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
6370/* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */
6371/* File: arm-vfp/fbinopWide2addr.S */
6372    /*
6373     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6374     * an "instr" line that specifies an instruction that performs
6375     * "d2 = d0 op d1".
6376     *
6377     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6378     *      div-double/2addr
6379     */
6380    /* binop/2addr vA, vB */
6381    mov     r3, rINST, lsr #12          @ r3<- B
6382    mov     r9, rINST, lsr #8           @ r9<- A+
6383    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6384    and     r9, r9, #15                 @ r9<- A
6385    fldd    d1, [r3]                    @ d1<- vB
6386    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6387    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6388    fldd    d0, [r9]                    @ d0<- vA
6389
6390    fmuld   d2, d0, d1                              @ d2<- op
6391    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6392    fstd    d2, [r9]                    @ vAA<- d2
6393    GOTO_OPCODE(ip)                     @ jump to next instruction
6394
6395
6396/* ------------------------------ */
6397    .balign 64
6398.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
6399/* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */
6400/* File: arm-vfp/fbinopWide2addr.S */
6401    /*
6402     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6403     * an "instr" line that specifies an instruction that performs
6404     * "d2 = d0 op d1".
6405     *
6406     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6407     *      div-double/2addr
6408     */
6409    /* binop/2addr vA, vB */
6410    mov     r3, rINST, lsr #12          @ r3<- B
6411    mov     r9, rINST, lsr #8           @ r9<- A+
6412    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6413    and     r9, r9, #15                 @ r9<- A
6414    fldd    d1, [r3]                    @ d1<- vB
6415    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6416    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6417    fldd    d0, [r9]                    @ d0<- vA
6418
6419    fdivd   d2, d0, d1                              @ d2<- op
6420    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6421    fstd    d2, [r9]                    @ vAA<- d2
6422    GOTO_OPCODE(ip)                     @ jump to next instruction
6423
6424
6425/* ------------------------------ */
6426    .balign 64
6427.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
6428/* File: armv5te/OP_REM_DOUBLE_2ADDR.S */
6429/* EABI doesn't define a double remainder function, but libm does */
6430/* File: armv5te/binopWide2addr.S */
6431    /*
6432     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6433     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6434     * This could be an ARM instruction or a function call.  (If the result
6435     * comes back in a register other than r0, you can override "result".)
6436     *
6437     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6438     * vCC (r1).  Useful for integer division and modulus.
6439     *
6440     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6441     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6442     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6443     *      rem-double/2addr
6444     */
6445    /* binop/2addr vA, vB */
6446    mov     r9, rINST, lsr #8           @ r9<- A+
6447    mov     r1, rINST, lsr #12          @ r1<- B
6448    and     r9, r9, #15
6449    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6450    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6451    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6452    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6453    .if 0
6454    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6455    beq     common_errDivideByZero
6456    .endif
6457    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6458
6459                               @ optional op; may set condition codes
6460    bl      fmod                              @ result<- op, r0-r3 changed
6461    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6462    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6463    GOTO_OPCODE(ip)                     @ jump to next instruction
6464    /* 12-15 instructions */
6465
6466
6467
6468/* ------------------------------ */
6469    .balign 64
6470.L_OP_ADD_INT_LIT16: /* 0xd0 */
6471/* File: armv5te/OP_ADD_INT_LIT16.S */
6472/* File: armv5te/binopLit16.S */
6473    /*
6474     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6475     * that specifies an instruction that performs "result = r0 op r1".
6476     * This could be an ARM instruction or a function call.  (If the result
6477     * comes back in a register other than r0, you can override "result".)
6478     *
6479     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6480     * vCC (r1).  Useful for integer division and modulus.
6481     *
6482     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6483     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6484     */
6485    /* binop/lit16 vA, vB, #+CCCC */
6486    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6487    mov     r2, rINST, lsr #12          @ r2<- B
6488    mov     r9, rINST, lsr #8           @ r9<- A+
6489    GET_VREG(r0, r2)                    @ r0<- vB
6490    and     r9, r9, #15
6491    .if 0
6492    cmp     r1, #0                      @ is second operand zero?
6493    beq     common_errDivideByZero
6494    .endif
6495    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6496
6497    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6498    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6499    SET_VREG(r0, r9)               @ vAA<- r0
6500    GOTO_OPCODE(ip)                     @ jump to next instruction
6501    /* 10-13 instructions */
6502
6503
6504
6505/* ------------------------------ */
6506    .balign 64
6507.L_OP_RSUB_INT: /* 0xd1 */
6508/* File: armv5te/OP_RSUB_INT.S */
6509/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
6510/* File: armv5te/binopLit16.S */
6511    /*
6512     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6513     * that specifies an instruction that performs "result = r0 op r1".
6514     * This could be an ARM instruction or a function call.  (If the result
6515     * comes back in a register other than r0, you can override "result".)
6516     *
6517     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6518     * vCC (r1).  Useful for integer division and modulus.
6519     *
6520     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6521     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6522     */
6523    /* binop/lit16 vA, vB, #+CCCC */
6524    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6525    mov     r2, rINST, lsr #12          @ r2<- B
6526    mov     r9, rINST, lsr #8           @ r9<- A+
6527    GET_VREG(r0, r2)                    @ r0<- vB
6528    and     r9, r9, #15
6529    .if 0
6530    cmp     r1, #0                      @ is second operand zero?
6531    beq     common_errDivideByZero
6532    .endif
6533    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6534
6535    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6536    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6537    SET_VREG(r0, r9)               @ vAA<- r0
6538    GOTO_OPCODE(ip)                     @ jump to next instruction
6539    /* 10-13 instructions */
6540
6541
6542
6543/* ------------------------------ */
6544    .balign 64
6545.L_OP_MUL_INT_LIT16: /* 0xd2 */
6546/* File: armv5te/OP_MUL_INT_LIT16.S */
6547/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6548/* File: armv5te/binopLit16.S */
6549    /*
6550     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6551     * that specifies an instruction that performs "result = r0 op r1".
6552     * This could be an ARM instruction or a function call.  (If the result
6553     * comes back in a register other than r0, you can override "result".)
6554     *
6555     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6556     * vCC (r1).  Useful for integer division and modulus.
6557     *
6558     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6559     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6560     */
6561    /* binop/lit16 vA, vB, #+CCCC */
6562    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6563    mov     r2, rINST, lsr #12          @ r2<- B
6564    mov     r9, rINST, lsr #8           @ r9<- A+
6565    GET_VREG(r0, r2)                    @ r0<- vB
6566    and     r9, r9, #15
6567    .if 0
6568    cmp     r1, #0                      @ is second operand zero?
6569    beq     common_errDivideByZero
6570    .endif
6571    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6572
6573    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6574    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6575    SET_VREG(r0, r9)               @ vAA<- r0
6576    GOTO_OPCODE(ip)                     @ jump to next instruction
6577    /* 10-13 instructions */
6578
6579
6580
6581/* ------------------------------ */
6582    .balign 64
6583.L_OP_DIV_INT_LIT16: /* 0xd3 */
6584/* File: armv5te/OP_DIV_INT_LIT16.S */
6585/* File: armv5te/binopLit16.S */
6586    /*
6587     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6588     * that specifies an instruction that performs "result = r0 op r1".
6589     * This could be an ARM instruction or a function call.  (If the result
6590     * comes back in a register other than r0, you can override "result".)
6591     *
6592     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6593     * vCC (r1).  Useful for integer division and modulus.
6594     *
6595     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6596     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6597     */
6598    /* binop/lit16 vA, vB, #+CCCC */
6599    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6600    mov     r2, rINST, lsr #12          @ r2<- B
6601    mov     r9, rINST, lsr #8           @ r9<- A+
6602    GET_VREG(r0, r2)                    @ r0<- vB
6603    and     r9, r9, #15
6604    .if 1
6605    cmp     r1, #0                      @ is second operand zero?
6606    beq     common_errDivideByZero
6607    .endif
6608    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6609
6610    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6611    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6612    SET_VREG(r0, r9)               @ vAA<- r0
6613    GOTO_OPCODE(ip)                     @ jump to next instruction
6614    /* 10-13 instructions */
6615
6616
6617
6618/* ------------------------------ */
6619    .balign 64
6620.L_OP_REM_INT_LIT16: /* 0xd4 */
6621/* File: armv5te/OP_REM_INT_LIT16.S */
6622/* idivmod returns quotient in r0 and remainder in r1 */
6623/* File: armv5te/binopLit16.S */
6624    /*
6625     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6626     * that specifies an instruction that performs "result = r0 op r1".
6627     * This could be an ARM instruction or a function call.  (If the result
6628     * comes back in a register other than r0, you can override "result".)
6629     *
6630     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6631     * vCC (r1).  Useful for integer division and modulus.
6632     *
6633     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6634     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6635     */
6636    /* binop/lit16 vA, vB, #+CCCC */
6637    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6638    mov     r2, rINST, lsr #12          @ r2<- B
6639    mov     r9, rINST, lsr #8           @ r9<- A+
6640    GET_VREG(r0, r2)                    @ r0<- vB
6641    and     r9, r9, #15
6642    .if 1
6643    cmp     r1, #0                      @ is second operand zero?
6644    beq     common_errDivideByZero
6645    .endif
6646    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6647
6648    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6649    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6650    SET_VREG(r1, r9)               @ vAA<- r1
6651    GOTO_OPCODE(ip)                     @ jump to next instruction
6652    /* 10-13 instructions */
6653
6654
6655
6656/* ------------------------------ */
6657    .balign 64
6658.L_OP_AND_INT_LIT16: /* 0xd5 */
6659/* File: armv5te/OP_AND_INT_LIT16.S */
6660/* File: armv5te/binopLit16.S */
6661    /*
6662     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6663     * that specifies an instruction that performs "result = r0 op r1".
6664     * This could be an ARM instruction or a function call.  (If the result
6665     * comes back in a register other than r0, you can override "result".)
6666     *
6667     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6668     * vCC (r1).  Useful for integer division and modulus.
6669     *
6670     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6671     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6672     */
6673    /* binop/lit16 vA, vB, #+CCCC */
6674    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6675    mov     r2, rINST, lsr #12          @ r2<- B
6676    mov     r9, rINST, lsr #8           @ r9<- A+
6677    GET_VREG(r0, r2)                    @ r0<- vB
6678    and     r9, r9, #15
6679    .if 0
6680    cmp     r1, #0                      @ is second operand zero?
6681    beq     common_errDivideByZero
6682    .endif
6683    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6684
6685    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6686    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6687    SET_VREG(r0, r9)               @ vAA<- r0
6688    GOTO_OPCODE(ip)                     @ jump to next instruction
6689    /* 10-13 instructions */
6690
6691
6692
6693/* ------------------------------ */
6694    .balign 64
6695.L_OP_OR_INT_LIT16: /* 0xd6 */
6696/* File: armv5te/OP_OR_INT_LIT16.S */
6697/* File: armv5te/binopLit16.S */
6698    /*
6699     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6700     * that specifies an instruction that performs "result = r0 op r1".
6701     * This could be an ARM instruction or a function call.  (If the result
6702     * comes back in a register other than r0, you can override "result".)
6703     *
6704     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6705     * vCC (r1).  Useful for integer division and modulus.
6706     *
6707     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6708     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6709     */
6710    /* binop/lit16 vA, vB, #+CCCC */
6711    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6712    mov     r2, rINST, lsr #12          @ r2<- B
6713    mov     r9, rINST, lsr #8           @ r9<- A+
6714    GET_VREG(r0, r2)                    @ r0<- vB
6715    and     r9, r9, #15
6716    .if 0
6717    cmp     r1, #0                      @ is second operand zero?
6718    beq     common_errDivideByZero
6719    .endif
6720    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6721
6722    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6723    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6724    SET_VREG(r0, r9)               @ vAA<- r0
6725    GOTO_OPCODE(ip)                     @ jump to next instruction
6726    /* 10-13 instructions */
6727
6728
6729
6730/* ------------------------------ */
6731    .balign 64
6732.L_OP_XOR_INT_LIT16: /* 0xd7 */
6733/* File: armv5te/OP_XOR_INT_LIT16.S */
6734/* File: armv5te/binopLit16.S */
6735    /*
6736     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6737     * that specifies an instruction that performs "result = r0 op r1".
6738     * This could be an ARM instruction or a function call.  (If the result
6739     * comes back in a register other than r0, you can override "result".)
6740     *
6741     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6742     * vCC (r1).  Useful for integer division and modulus.
6743     *
6744     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6745     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6746     */
6747    /* binop/lit16 vA, vB, #+CCCC */
6748    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6749    mov     r2, rINST, lsr #12          @ r2<- B
6750    mov     r9, rINST, lsr #8           @ r9<- A+
6751    GET_VREG(r0, r2)                    @ r0<- vB
6752    and     r9, r9, #15
6753    .if 0
6754    cmp     r1, #0                      @ is second operand zero?
6755    beq     common_errDivideByZero
6756    .endif
6757    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6758
6759    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
6760    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6761    SET_VREG(r0, r9)               @ vAA<- r0
6762    GOTO_OPCODE(ip)                     @ jump to next instruction
6763    /* 10-13 instructions */
6764
6765
6766
6767/* ------------------------------ */
6768    .balign 64
6769.L_OP_ADD_INT_LIT8: /* 0xd8 */
6770/* File: armv5te/OP_ADD_INT_LIT8.S */
6771/* File: armv5te/binopLit8.S */
6772    /*
6773     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6774     * that specifies an instruction that performs "result = r0 op r1".
6775     * This could be an ARM instruction or a function call.  (If the result
6776     * comes back in a register other than r0, you can override "result".)
6777     *
6778     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6779     * vCC (r1).  Useful for integer division and modulus.
6780     *
6781     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6782     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6783     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6784     */
6785    /* binop/lit8 vAA, vBB, #+CC */
6786    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6787    mov     r9, rINST, lsr #8           @ r9<- AA
6788    and     r2, r3, #255                @ r2<- BB
6789    GET_VREG(r0, r2)                    @ r0<- vBB
6790    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6791    .if 0
6792    @cmp     r1, #0                      @ is second operand zero?
6793    beq     common_errDivideByZero
6794    .endif
6795    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6796
6797                               @ optional op; may set condition codes
6798    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6799    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6800    SET_VREG(r0, r9)               @ vAA<- r0
6801    GOTO_OPCODE(ip)                     @ jump to next instruction
6802    /* 10-12 instructions */
6803
6804
6805
6806/* ------------------------------ */
6807    .balign 64
6808.L_OP_RSUB_INT_LIT8: /* 0xd9 */
6809/* File: armv5te/OP_RSUB_INT_LIT8.S */
6810/* File: armv5te/binopLit8.S */
6811    /*
6812     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6813     * that specifies an instruction that performs "result = r0 op r1".
6814     * This could be an ARM instruction or a function call.  (If the result
6815     * comes back in a register other than r0, you can override "result".)
6816     *
6817     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6818     * vCC (r1).  Useful for integer division and modulus.
6819     *
6820     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6821     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6822     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6823     */
6824    /* binop/lit8 vAA, vBB, #+CC */
6825    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6826    mov     r9, rINST, lsr #8           @ r9<- AA
6827    and     r2, r3, #255                @ r2<- BB
6828    GET_VREG(r0, r2)                    @ r0<- vBB
6829    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
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                               @ optional op; may set condition codes
6837    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6838    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6839    SET_VREG(r0, r9)               @ vAA<- r0
6840    GOTO_OPCODE(ip)                     @ jump to next instruction
6841    /* 10-12 instructions */
6842
6843
6844
6845/* ------------------------------ */
6846    .balign 64
6847.L_OP_MUL_INT_LIT8: /* 0xda */
6848/* File: armv5te/OP_MUL_INT_LIT8.S */
6849/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6850/* File: armv5te/binopLit8.S */
6851    /*
6852     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6853     * that specifies an instruction that performs "result = r0 op r1".
6854     * This could be an ARM instruction or a function call.  (If the result
6855     * comes back in a register other than r0, you can override "result".)
6856     *
6857     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6858     * vCC (r1).  Useful for integer division and modulus.
6859     *
6860     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6861     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6862     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6863     */
6864    /* binop/lit8 vAA, vBB, #+CC */
6865    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6866    mov     r9, rINST, lsr #8           @ r9<- AA
6867    and     r2, r3, #255                @ r2<- BB
6868    GET_VREG(r0, r2)                    @ r0<- vBB
6869    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6870    .if 0
6871    @cmp     r1, #0                      @ is second operand zero?
6872    beq     common_errDivideByZero
6873    .endif
6874    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6875
6876                               @ optional op; may set condition codes
6877    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6878    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6879    SET_VREG(r0, r9)               @ vAA<- r0
6880    GOTO_OPCODE(ip)                     @ jump to next instruction
6881    /* 10-12 instructions */
6882
6883
6884
6885/* ------------------------------ */
6886    .balign 64
6887.L_OP_DIV_INT_LIT8: /* 0xdb */
6888/* File: armv5te/OP_DIV_INT_LIT8.S */
6889/* File: armv5te/binopLit8.S */
6890    /*
6891     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6892     * that specifies an instruction that performs "result = r0 op r1".
6893     * This could be an ARM instruction or a function call.  (If the result
6894     * comes back in a register other than r0, you can override "result".)
6895     *
6896     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6897     * vCC (r1).  Useful for integer division and modulus.
6898     *
6899     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6900     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6901     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6902     */
6903    /* binop/lit8 vAA, vBB, #+CC */
6904    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6905    mov     r9, rINST, lsr #8           @ r9<- AA
6906    and     r2, r3, #255                @ r2<- BB
6907    GET_VREG(r0, r2)                    @ r0<- vBB
6908    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6909    .if 1
6910    @cmp     r1, #0                      @ is second operand zero?
6911    beq     common_errDivideByZero
6912    .endif
6913    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6914
6915                               @ optional op; may set condition codes
6916    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6917    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6918    SET_VREG(r0, r9)               @ vAA<- r0
6919    GOTO_OPCODE(ip)                     @ jump to next instruction
6920    /* 10-12 instructions */
6921
6922
6923
6924/* ------------------------------ */
6925    .balign 64
6926.L_OP_REM_INT_LIT8: /* 0xdc */
6927/* File: armv5te/OP_REM_INT_LIT8.S */
6928/* idivmod returns quotient in r0 and remainder in r1 */
6929/* File: armv5te/binopLit8.S */
6930    /*
6931     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6932     * that specifies an instruction that performs "result = r0 op r1".
6933     * This could be an ARM instruction or a function call.  (If the result
6934     * comes back in a register other than r0, you can override "result".)
6935     *
6936     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6937     * vCC (r1).  Useful for integer division and modulus.
6938     *
6939     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6940     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6941     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6942     */
6943    /* binop/lit8 vAA, vBB, #+CC */
6944    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6945    mov     r9, rINST, lsr #8           @ r9<- AA
6946    and     r2, r3, #255                @ r2<- BB
6947    GET_VREG(r0, r2)                    @ r0<- vBB
6948    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6949    .if 1
6950    @cmp     r1, #0                      @ is second operand zero?
6951    beq     common_errDivideByZero
6952    .endif
6953    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6954
6955                               @ optional op; may set condition codes
6956    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6957    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6958    SET_VREG(r1, r9)               @ vAA<- r1
6959    GOTO_OPCODE(ip)                     @ jump to next instruction
6960    /* 10-12 instructions */
6961
6962
6963
6964/* ------------------------------ */
6965    .balign 64
6966.L_OP_AND_INT_LIT8: /* 0xdd */
6967/* File: armv5te/OP_AND_INT_LIT8.S */
6968/* File: armv5te/binopLit8.S */
6969    /*
6970     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6971     * that specifies an instruction that performs "result = r0 op r1".
6972     * This could be an ARM instruction or a function call.  (If the result
6973     * comes back in a register other than r0, you can override "result".)
6974     *
6975     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6976     * vCC (r1).  Useful for integer division and modulus.
6977     *
6978     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6979     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6980     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6981     */
6982    /* binop/lit8 vAA, vBB, #+CC */
6983    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6984    mov     r9, rINST, lsr #8           @ r9<- AA
6985    and     r2, r3, #255                @ r2<- BB
6986    GET_VREG(r0, r2)                    @ r0<- vBB
6987    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6988    .if 0
6989    @cmp     r1, #0                      @ is second operand zero?
6990    beq     common_errDivideByZero
6991    .endif
6992    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6993
6994                               @ optional op; may set condition codes
6995    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6996    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6997    SET_VREG(r0, r9)               @ vAA<- r0
6998    GOTO_OPCODE(ip)                     @ jump to next instruction
6999    /* 10-12 instructions */
7000
7001
7002
7003/* ------------------------------ */
7004    .balign 64
7005.L_OP_OR_INT_LIT8: /* 0xde */
7006/* File: armv5te/OP_OR_INT_LIT8.S */
7007/* File: armv5te/binopLit8.S */
7008    /*
7009     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7010     * that specifies an instruction that performs "result = r0 op r1".
7011     * This could be an ARM instruction or a function call.  (If the result
7012     * comes back in a register other than r0, you can override "result".)
7013     *
7014     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7015     * vCC (r1).  Useful for integer division and modulus.
7016     *
7017     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7018     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7019     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7020     */
7021    /* binop/lit8 vAA, vBB, #+CC */
7022    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7023    mov     r9, rINST, lsr #8           @ r9<- AA
7024    and     r2, r3, #255                @ r2<- BB
7025    GET_VREG(r0, r2)                    @ r0<- vBB
7026    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7027    .if 0
7028    @cmp     r1, #0                      @ is second operand zero?
7029    beq     common_errDivideByZero
7030    .endif
7031    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7032
7033                               @ optional op; may set condition codes
7034    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
7035    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7036    SET_VREG(r0, r9)               @ vAA<- r0
7037    GOTO_OPCODE(ip)                     @ jump to next instruction
7038    /* 10-12 instructions */
7039
7040
7041
7042/* ------------------------------ */
7043    .balign 64
7044.L_OP_XOR_INT_LIT8: /* 0xdf */
7045/* File: armv5te/OP_XOR_INT_LIT8.S */
7046/* File: armv5te/binopLit8.S */
7047    /*
7048     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7049     * that specifies an instruction that performs "result = r0 op r1".
7050     * This could be an ARM instruction or a function call.  (If the result
7051     * comes back in a register other than r0, you can override "result".)
7052     *
7053     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7054     * vCC (r1).  Useful for integer division and modulus.
7055     *
7056     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7057     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7058     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7059     */
7060    /* binop/lit8 vAA, vBB, #+CC */
7061    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7062    mov     r9, rINST, lsr #8           @ r9<- AA
7063    and     r2, r3, #255                @ r2<- BB
7064    GET_VREG(r0, r2)                    @ r0<- vBB
7065    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7066    .if 0
7067    @cmp     r1, #0                      @ is second operand zero?
7068    beq     common_errDivideByZero
7069    .endif
7070    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7071
7072                               @ optional op; may set condition codes
7073    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
7074    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7075    SET_VREG(r0, r9)               @ vAA<- r0
7076    GOTO_OPCODE(ip)                     @ jump to next instruction
7077    /* 10-12 instructions */
7078
7079
7080
7081/* ------------------------------ */
7082    .balign 64
7083.L_OP_SHL_INT_LIT8: /* 0xe0 */
7084/* File: armv5te/OP_SHL_INT_LIT8.S */
7085/* File: armv5te/binopLit8.S */
7086    /*
7087     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7088     * that specifies an instruction that performs "result = r0 op r1".
7089     * This could be an ARM instruction or a function call.  (If the result
7090     * comes back in a register other than r0, you can override "result".)
7091     *
7092     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7093     * vCC (r1).  Useful for integer division and modulus.
7094     *
7095     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7096     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7097     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7098     */
7099    /* binop/lit8 vAA, vBB, #+CC */
7100    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7101    mov     r9, rINST, lsr #8           @ r9<- AA
7102    and     r2, r3, #255                @ r2<- BB
7103    GET_VREG(r0, r2)                    @ r0<- vBB
7104    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7105    .if 0
7106    @cmp     r1, #0                      @ is second operand zero?
7107    beq     common_errDivideByZero
7108    .endif
7109    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7110
7111    and     r1, r1, #31                           @ optional op; may set condition codes
7112    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
7113    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7114    SET_VREG(r0, r9)               @ vAA<- r0
7115    GOTO_OPCODE(ip)                     @ jump to next instruction
7116    /* 10-12 instructions */
7117
7118
7119
7120/* ------------------------------ */
7121    .balign 64
7122.L_OP_SHR_INT_LIT8: /* 0xe1 */
7123/* File: armv5te/OP_SHR_INT_LIT8.S */
7124/* File: armv5te/binopLit8.S */
7125    /*
7126     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7127     * that specifies an instruction that performs "result = r0 op r1".
7128     * This could be an ARM instruction or a function call.  (If the result
7129     * comes back in a register other than r0, you can override "result".)
7130     *
7131     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7132     * vCC (r1).  Useful for integer division and modulus.
7133     *
7134     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7135     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7136     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7137     */
7138    /* binop/lit8 vAA, vBB, #+CC */
7139    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7140    mov     r9, rINST, lsr #8           @ r9<- AA
7141    and     r2, r3, #255                @ r2<- BB
7142    GET_VREG(r0, r2)                    @ r0<- vBB
7143    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7144    .if 0
7145    @cmp     r1, #0                      @ is second operand zero?
7146    beq     common_errDivideByZero
7147    .endif
7148    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7149
7150    and     r1, r1, #31                           @ optional op; may set condition codes
7151    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
7152    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7153    SET_VREG(r0, r9)               @ vAA<- r0
7154    GOTO_OPCODE(ip)                     @ jump to next instruction
7155    /* 10-12 instructions */
7156
7157
7158
7159/* ------------------------------ */
7160    .balign 64
7161.L_OP_USHR_INT_LIT8: /* 0xe2 */
7162/* File: armv5te/OP_USHR_INT_LIT8.S */
7163/* File: armv5te/binopLit8.S */
7164    /*
7165     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7166     * that specifies an instruction that performs "result = r0 op r1".
7167     * This could be an ARM instruction or a function call.  (If the result
7168     * comes back in a register other than r0, you can override "result".)
7169     *
7170     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7171     * vCC (r1).  Useful for integer division and modulus.
7172     *
7173     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7174     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7175     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7176     */
7177    /* binop/lit8 vAA, vBB, #+CC */
7178    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7179    mov     r9, rINST, lsr #8           @ r9<- AA
7180    and     r2, r3, #255                @ r2<- BB
7181    GET_VREG(r0, r2)                    @ r0<- vBB
7182    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7183    .if 0
7184    @cmp     r1, #0                      @ is second operand zero?
7185    beq     common_errDivideByZero
7186    .endif
7187    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7188
7189    and     r1, r1, #31                           @ optional op; may set condition codes
7190    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
7191    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7192    SET_VREG(r0, r9)               @ vAA<- r0
7193    GOTO_OPCODE(ip)                     @ jump to next instruction
7194    /* 10-12 instructions */
7195
7196
7197
7198/* ------------------------------ */
7199    .balign 64
7200.L_OP_UNUSED_E3: /* 0xe3 */
7201/* File: armv5te/OP_UNUSED_E3.S */
7202/* File: armv5te/unused.S */
7203    bl      common_abort
7204
7205
7206
7207/* ------------------------------ */
7208    .balign 64
7209.L_OP_UNUSED_E4: /* 0xe4 */
7210/* File: armv5te/OP_UNUSED_E4.S */
7211/* File: armv5te/unused.S */
7212    bl      common_abort
7213
7214
7215
7216/* ------------------------------ */
7217    .balign 64
7218.L_OP_UNUSED_E5: /* 0xe5 */
7219/* File: armv5te/OP_UNUSED_E5.S */
7220/* File: armv5te/unused.S */
7221    bl      common_abort
7222
7223
7224
7225/* ------------------------------ */
7226    .balign 64
7227.L_OP_UNUSED_E6: /* 0xe6 */
7228/* File: armv5te/OP_UNUSED_E6.S */
7229/* File: armv5te/unused.S */
7230    bl      common_abort
7231
7232
7233
7234/* ------------------------------ */
7235    .balign 64
7236.L_OP_UNUSED_E7: /* 0xe7 */
7237/* File: armv5te/OP_UNUSED_E7.S */
7238/* File: armv5te/unused.S */
7239    bl      common_abort
7240
7241
7242
7243/* ------------------------------ */
7244    .balign 64
7245.L_OP_UNUSED_E8: /* 0xe8 */
7246/* File: armv5te/OP_UNUSED_E8.S */
7247/* File: armv5te/unused.S */
7248    bl      common_abort
7249
7250
7251
7252/* ------------------------------ */
7253    .balign 64
7254.L_OP_UNUSED_E9: /* 0xe9 */
7255/* File: armv5te/OP_UNUSED_E9.S */
7256/* File: armv5te/unused.S */
7257    bl      common_abort
7258
7259
7260
7261/* ------------------------------ */
7262    .balign 64
7263.L_OP_UNUSED_EA: /* 0xea */
7264/* File: armv5te/OP_UNUSED_EA.S */
7265/* File: armv5te/unused.S */
7266    bl      common_abort
7267
7268
7269
7270/* ------------------------------ */
7271    .balign 64
7272.L_OP_UNUSED_EB: /* 0xeb */
7273/* File: armv5te/OP_UNUSED_EB.S */
7274/* File: armv5te/unused.S */
7275    bl      common_abort
7276
7277
7278
7279/* ------------------------------ */
7280    .balign 64
7281.L_OP_UNUSED_EC: /* 0xec */
7282/* File: armv5te/OP_UNUSED_EC.S */
7283/* File: armv5te/unused.S */
7284    bl      common_abort
7285
7286
7287
7288/* ------------------------------ */
7289    .balign 64
7290.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
7291/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
7292    /*
7293     * Handle a throw-verification-error instruction.  This throws an
7294     * exception for an error discovered during verification.  The
7295     * exception is indicated by AA, with some detail provided by BBBB.
7296     */
7297    /* op AA, ref@BBBB */
7298    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7299    FETCH(r2, 1)                        @ r2<- BBBB
7300    EXPORT_PC()                         @ export the PC
7301    mov     r1, rINST, lsr #8           @ r1<- AA
7302    bl      dvmThrowVerificationError   @ always throws
7303    b       common_exceptionThrown      @ handle exception
7304
7305
7306/* ------------------------------ */
7307    .balign 64
7308.L_OP_EXECUTE_INLINE: /* 0xee */
7309/* File: armv5te/OP_EXECUTE_INLINE.S */
7310    /*
7311     * Execute a "native inline" instruction.
7312     *
7313     * We need to call:
7314     *  dvmPerformInlineOp4Std(arg0, arg1, arg2, arg3, &retval, ref)
7315     *
7316     * The first four args are in r0-r3, but the last two must be pushed
7317     * onto the stack.
7318     */
7319    /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
7320    FETCH(r10, 1)                       @ r10<- BBBB
7321    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7322    EXPORT_PC()                         @ can throw
7323    sub     sp, sp, #8                  @ make room for arg(s)
7324    mov     r0, rINST, lsr #12          @ r0<- B
7325    str     r1, [sp]                    @ push &glue->retval
7326    bl      .LOP_EXECUTE_INLINE_continue        @ make call; will return after
7327    add     sp, sp, #8                  @ pop stack
7328    cmp     r0, #0                      @ test boolean result of inline
7329    beq     common_exceptionThrown      @ returned false, handle exception
7330    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7331    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7332    GOTO_OPCODE(ip)                     @ jump to next instruction
7333
7334/* ------------------------------ */
7335    .balign 64
7336.L_OP_UNUSED_EF: /* 0xef */
7337/* File: armv5te/OP_UNUSED_EF.S */
7338/* File: armv5te/unused.S */
7339    bl      common_abort
7340
7341
7342
7343/* ------------------------------ */
7344    .balign 64
7345.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
7346/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
7347    /*
7348     * invoke-direct-empty is a no-op in a "standard" interpreter.
7349     */
7350    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7351    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7352    GOTO_OPCODE(ip)                     @ execute it
7353
7354/* ------------------------------ */
7355    .balign 64
7356.L_OP_UNUSED_F1: /* 0xf1 */
7357/* File: armv5te/OP_UNUSED_F1.S */
7358/* File: armv5te/unused.S */
7359    bl      common_abort
7360
7361
7362
7363/* ------------------------------ */
7364    .balign 64
7365.L_OP_IGET_QUICK: /* 0xf2 */
7366/* File: armv5te/OP_IGET_QUICK.S */
7367    /* For: iget-quick, iget-object-quick */
7368    /* op vA, vB, offset@CCCC */
7369    mov     r2, rINST, lsr #12          @ r2<- B
7370    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7371    FETCH(r1, 1)                        @ r1<- field byte offset
7372    cmp     r3, #0                      @ check object for null
7373    mov     r2, rINST, lsr #8           @ r2<- A(+)
7374    beq     common_errNullObject        @ object was null
7375    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7376    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7377    and     r2, r2, #15
7378    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7379    SET_VREG(r0, r2)                    @ fp[A]<- r0
7380    GOTO_OPCODE(ip)                     @ jump to next instruction
7381
7382
7383/* ------------------------------ */
7384    .balign 64
7385.L_OP_IGET_WIDE_QUICK: /* 0xf3 */
7386/* File: armv5te/OP_IGET_WIDE_QUICK.S */
7387    /* iget-wide-quick vA, vB, offset@CCCC */
7388    mov     r2, rINST, lsr #12          @ r2<- B
7389    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7390    FETCH(r1, 1)                        @ r1<- field byte offset
7391    cmp     r3, #0                      @ check object for null
7392    mov     r2, rINST, lsr #8           @ r2<- A(+)
7393    beq     common_errNullObject        @ object was null
7394    ldrd    r0, [r3, r1]                @ r0<- obj.field (64 bits, aligned)
7395    and     r2, r2, #15
7396    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7397    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
7398    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7399    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
7400    GOTO_OPCODE(ip)                     @ jump to next instruction
7401
7402
7403/* ------------------------------ */
7404    .balign 64
7405.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
7406/* File: armv5te/OP_IGET_OBJECT_QUICK.S */
7407/* File: armv5te/OP_IGET_QUICK.S */
7408    /* For: iget-quick, iget-object-quick */
7409    /* op vA, vB, offset@CCCC */
7410    mov     r2, rINST, lsr #12          @ r2<- B
7411    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7412    FETCH(r1, 1)                        @ r1<- field byte offset
7413    cmp     r3, #0                      @ check object for null
7414    mov     r2, rINST, lsr #8           @ r2<- A(+)
7415    beq     common_errNullObject        @ object was null
7416    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7417    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7418    and     r2, r2, #15
7419    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7420    SET_VREG(r0, r2)                    @ fp[A]<- r0
7421    GOTO_OPCODE(ip)                     @ jump to next instruction
7422
7423
7424
7425/* ------------------------------ */
7426    .balign 64
7427.L_OP_IPUT_QUICK: /* 0xf5 */
7428/* File: armv5te/OP_IPUT_QUICK.S */
7429    /* For: iput-quick, iput-object-quick */
7430    /* op vA, vB, offset@CCCC */
7431    mov     r2, rINST, lsr #12          @ r2<- B
7432    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7433    FETCH(r1, 1)                        @ r1<- field byte offset
7434    cmp     r3, #0                      @ check object for null
7435    mov     r2, rINST, lsr #8           @ r2<- A(+)
7436    beq     common_errNullObject        @ object was null
7437    and     r2, r2, #15
7438    GET_VREG(r0, r2)                    @ r0<- fp[A]
7439    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7440    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7441    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7442    GOTO_OPCODE(ip)                     @ jump to next instruction
7443
7444
7445/* ------------------------------ */
7446    .balign 64
7447.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
7448/* File: armv5te/OP_IPUT_WIDE_QUICK.S */
7449    /* iput-wide-quick vA, vB, offset@CCCC */
7450    mov     r0, rINST, lsr #8           @ r0<- A(+)
7451    mov     r1, rINST, lsr #12          @ r1<- B
7452    and     r0, r0, #15
7453    GET_VREG(r2, r1)                    @ r2<- fp[B], the object pointer
7454    add     r3, rFP, r0, lsl #2         @ r3<- &fp[A]
7455    cmp     r2, #0                      @ check object for null
7456    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[A]
7457    beq     common_errNullObject        @ object was null
7458    FETCH(r3, 1)                        @ r3<- field byte offset
7459    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7460    strd    r0, [r2, r3]                @ obj.field (64 bits, aligned)<- r0/r1
7461    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7462    GOTO_OPCODE(ip)                     @ jump to next instruction
7463
7464
7465/* ------------------------------ */
7466    .balign 64
7467.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
7468/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
7469/* File: armv5te/OP_IPUT_QUICK.S */
7470    /* For: iput-quick, iput-object-quick */
7471    /* op vA, vB, offset@CCCC */
7472    mov     r2, rINST, lsr #12          @ r2<- B
7473    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7474    FETCH(r1, 1)                        @ r1<- field byte offset
7475    cmp     r3, #0                      @ check object for null
7476    mov     r2, rINST, lsr #8           @ r2<- A(+)
7477    beq     common_errNullObject        @ object was null
7478    and     r2, r2, #15
7479    GET_VREG(r0, r2)                    @ r0<- fp[A]
7480    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7481    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7482    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7483    GOTO_OPCODE(ip)                     @ jump to next instruction
7484
7485
7486
7487/* ------------------------------ */
7488    .balign 64
7489.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
7490/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7491    /*
7492     * Handle an optimized virtual method call.
7493     *
7494     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7495     */
7496    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7497    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7498    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7499    FETCH(r1, 1)                        @ r1<- BBBB
7500    .if     (!0)
7501    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7502    .endif
7503    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7504    cmp     r2, #0                      @ is "this" null?
7505    beq     common_errNullObject        @ null "this", throw exception
7506    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7507    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7508    EXPORT_PC()                         @ invoke must export
7509    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7510    bl      common_invokeMethodNoRange @ continue on
7511
7512/* ------------------------------ */
7513    .balign 64
7514.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
7515/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
7516/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7517    /*
7518     * Handle an optimized virtual method call.
7519     *
7520     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7521     */
7522    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7523    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7524    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7525    FETCH(r1, 1)                        @ r1<- BBBB
7526    .if     (!1)
7527    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7528    .endif
7529    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7530    cmp     r2, #0                      @ is "this" null?
7531    beq     common_errNullObject        @ null "this", throw exception
7532    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7533    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7534    EXPORT_PC()                         @ invoke must export
7535    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7536    bl      common_invokeMethodRange @ continue on
7537
7538
7539/* ------------------------------ */
7540    .balign 64
7541.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
7542/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7543    /*
7544     * Handle an optimized "super" method call.
7545     *
7546     * for: [opt] invoke-super-quick, invoke-super-quick/range
7547     */
7548    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7549    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7550    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7551    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7552    .if     (!0)
7553    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7554    .endif
7555    FETCH(r1, 1)                        @ r1<- BBBB
7556    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7557    EXPORT_PC()                         @ must export for invoke
7558    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7559    GET_VREG(r3, r10)                   @ r3<- "this"
7560    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7561    cmp     r3, #0                      @ null "this" ref?
7562    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7563    beq     common_errNullObject        @ "this" is null, throw exception
7564    bl      common_invokeMethodNoRange @ continue on
7565
7566
7567/* ------------------------------ */
7568    .balign 64
7569.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
7570/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
7571/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7572    /*
7573     * Handle an optimized "super" method call.
7574     *
7575     * for: [opt] invoke-super-quick, invoke-super-quick/range
7576     */
7577    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7578    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7579    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7580    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7581    .if     (!1)
7582    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7583    .endif
7584    FETCH(r1, 1)                        @ r1<- BBBB
7585    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7586    EXPORT_PC()                         @ must export for invoke
7587    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7588    GET_VREG(r3, r10)                   @ r3<- "this"
7589    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7590    cmp     r3, #0                      @ null "this" ref?
7591    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7592    beq     common_errNullObject        @ "this" is null, throw exception
7593    bl      common_invokeMethodRange @ continue on
7594
7595
7596
7597/* ------------------------------ */
7598    .balign 64
7599.L_OP_UNUSED_FC: /* 0xfc */
7600/* File: armv5te/OP_UNUSED_FC.S */
7601/* File: armv5te/unused.S */
7602    bl      common_abort
7603
7604
7605
7606/* ------------------------------ */
7607    .balign 64
7608.L_OP_UNUSED_FD: /* 0xfd */
7609/* File: armv5te/OP_UNUSED_FD.S */
7610/* File: armv5te/unused.S */
7611    bl      common_abort
7612
7613
7614
7615/* ------------------------------ */
7616    .balign 64
7617.L_OP_UNUSED_FE: /* 0xfe */
7618/* File: armv5te/OP_UNUSED_FE.S */
7619/* File: armv5te/unused.S */
7620    bl      common_abort
7621
7622
7623
7624/* ------------------------------ */
7625    .balign 64
7626.L_OP_UNUSED_FF: /* 0xff */
7627/* File: armv5te/OP_UNUSED_FF.S */
7628/* File: armv5te/unused.S */
7629    bl      common_abort
7630
7631
7632
7633
7634    .balign 64
7635    .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
7636    .global dvmAsmInstructionEnd
7637dvmAsmInstructionEnd:
7638
7639/*
7640 * ===========================================================================
7641 *  Sister implementations
7642 * ===========================================================================
7643 */
7644    .global dvmAsmSisterStart
7645    .type   dvmAsmSisterStart, %function
7646    .text
7647    .balign 4
7648dvmAsmSisterStart:
7649
7650/* continuation for OP_CONST_STRING */
7651
7652    /*
7653     * Continuation if the String has not yet been resolved.
7654     *  r1: BBBB (String ref)
7655     *  r9: target register
7656     */
7657.LOP_CONST_STRING_resolve:
7658    EXPORT_PC()
7659    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7660    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7661    bl      dvmResolveString            @ r0<- String reference
7662    cmp     r0, #0                      @ failed?
7663    beq     common_exceptionThrown      @ yup, handle the exception
7664    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7665    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7666    SET_VREG(r0, r9)                    @ vAA<- r0
7667    GOTO_OPCODE(ip)                     @ jump to next instruction
7668
7669
7670/* continuation for OP_CONST_STRING_JUMBO */
7671
7672    /*
7673     * Continuation if the String has not yet been resolved.
7674     *  r1: BBBBBBBB (String ref)
7675     *  r9: target register
7676     */
7677.LOP_CONST_STRING_JUMBO_resolve:
7678    EXPORT_PC()
7679    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7680    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7681    bl      dvmResolveString            @ r0<- String reference
7682    cmp     r0, #0                      @ failed?
7683    beq     common_exceptionThrown      @ yup, handle the exception
7684    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7685    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7686    SET_VREG(r0, r9)                    @ vAA<- r0
7687    GOTO_OPCODE(ip)                     @ jump to next instruction
7688
7689
7690/* continuation for OP_CONST_CLASS */
7691
7692    /*
7693     * Continuation if the Class has not yet been resolved.
7694     *  r1: BBBB (Class ref)
7695     *  r9: target register
7696     */
7697.LOP_CONST_CLASS_resolve:
7698    EXPORT_PC()
7699    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7700    mov     r2, #1                      @ r2<- true
7701    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7702    bl      dvmResolveClass             @ r0<- Class reference
7703    cmp     r0, #0                      @ failed?
7704    beq     common_exceptionThrown      @ yup, handle the exception
7705    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7706    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7707    SET_VREG(r0, r9)                    @ vAA<- r0
7708    GOTO_OPCODE(ip)                     @ jump to next instruction
7709
7710
7711/* continuation for OP_CHECK_CAST */
7712
7713    /*
7714     * Trivial test failed, need to perform full check.  This is common.
7715     *  r0 holds obj->clazz
7716     *  r1 holds class resolved from BBBB
7717     *  r9 holds object
7718     */
7719.LOP_CHECK_CAST_fullcheck:
7720    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7721    cmp     r0, #0                      @ failed?
7722    bne     .LOP_CHECK_CAST_okay            @ no, success
7723
7724    @ A cast has failed.  We need to throw a ClassCastException with the
7725    @ class of the object that failed to be cast.
7726    EXPORT_PC()                         @ about to throw
7727    ldr     r3, [r9, #offObject_clazz]  @ r3<- obj->clazz
7728    ldr     r0, .LstrClassCastExceptionPtr
7729    ldr     r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor
7730    bl      dvmThrowExceptionWithClassMessage
7731    b       common_exceptionThrown
7732
7733    /*
7734     * Resolution required.  This is the least-likely path.
7735     *
7736     *  r2 holds BBBB
7737     *  r9 holds object
7738     */
7739.LOP_CHECK_CAST_resolve:
7740    EXPORT_PC()                         @ resolve() could throw
7741    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7742    mov     r1, r2                      @ r1<- BBBB
7743    mov     r2, #0                      @ r2<- false
7744    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7745    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7746    cmp     r0, #0                      @ got null?
7747    beq     common_exceptionThrown      @ yes, handle exception
7748    mov     r1, r0                      @ r1<- class resolved from BBB
7749    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
7750    b       .LOP_CHECK_CAST_resolved        @ pick up where we left off
7751
7752.LstrClassCastExceptionPtr:
7753    .word   .LstrClassCastException
7754
7755
7756/* continuation for OP_INSTANCE_OF */
7757
7758    /*
7759     * Trivial test failed, need to perform full check.  This is common.
7760     *  r0 holds obj->clazz
7761     *  r1 holds class resolved from BBBB
7762     *  r9 holds A
7763     */
7764.LOP_INSTANCE_OF_fullcheck:
7765    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7766    @ fall through to OP_INSTANCE_OF_store
7767
7768    /*
7769     * r0 holds boolean result
7770     * r9 holds A
7771     */
7772.LOP_INSTANCE_OF_store:
7773    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7774    SET_VREG(r0, r9)                    @ vA<- r0
7775    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7776    GOTO_OPCODE(ip)                     @ jump to next instruction
7777
7778    /*
7779     * Trivial test succeeded, save and bail.
7780     *  r9 holds A
7781     */
7782.LOP_INSTANCE_OF_trivial:
7783    mov     r0, #1                      @ indicate success
7784    @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
7785    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7786    SET_VREG(r0, r9)                    @ vA<- r0
7787    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7788    GOTO_OPCODE(ip)                     @ jump to next instruction
7789
7790    /*
7791     * Resolution required.  This is the least-likely path.
7792     *
7793     *  r3 holds BBBB
7794     *  r9 holds A
7795     */
7796.LOP_INSTANCE_OF_resolve:
7797    EXPORT_PC()                         @ resolve() could throw
7798    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7799    mov     r1, r3                      @ r1<- BBBB
7800    mov     r2, #1                      @ r2<- true
7801    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7802    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7803    cmp     r0, #0                      @ got null?
7804    beq     common_exceptionThrown      @ yes, handle exception
7805    mov     r1, r0                      @ r1<- class resolved from BBB
7806    mov     r3, rINST, lsr #12          @ r3<- B
7807    GET_VREG(r0, r3)                    @ r0<- vB (object)
7808    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
7809    b       .LOP_INSTANCE_OF_resolved        @ pick up where we left off
7810
7811
7812/* continuation for OP_NEW_INSTANCE */
7813
7814    .balign 32                          @ minimize cache lines
7815.LOP_NEW_INSTANCE_finish: @ r0=new object
7816    mov     r3, rINST, lsr #8           @ r3<- AA
7817    cmp     r0, #0                      @ failed?
7818    beq     common_exceptionThrown      @ yes, handle the exception
7819    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7820    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7821    SET_VREG(r0, r3)                    @ vAA<- r0
7822    GOTO_OPCODE(ip)                     @ jump to next instruction
7823
7824    /*
7825     * Class initialization required.
7826     *
7827     *  r0 holds class object
7828     */
7829.LOP_NEW_INSTANCE_needinit:
7830    mov     r9, r0                      @ save r0
7831    bl      dvmInitClass                @ initialize class
7832    cmp     r0, #0                      @ check boolean result
7833    mov     r0, r9                      @ restore r0
7834    bne     .LOP_NEW_INSTANCE_initialized     @ success, continue
7835    b       common_exceptionThrown      @ failed, deal with init exception
7836
7837    /*
7838     * Resolution required.  This is the least-likely path.
7839     *
7840     *  r1 holds BBBB
7841     */
7842.LOP_NEW_INSTANCE_resolve:
7843    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7844    mov     r2, #0                      @ r2<- false
7845    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7846    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7847    cmp     r0, #0                      @ got null?
7848    bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
7849    b       common_exceptionThrown      @ yes, handle exception
7850
7851.LstrInstantiationErrorPtr:
7852    .word   .LstrInstantiationError
7853
7854
7855/* continuation for OP_NEW_ARRAY */
7856
7857
7858    /*
7859     * Resolve class.  (This is an uncommon case.)
7860     *
7861     *  r1 holds array length
7862     *  r2 holds class ref CCCC
7863     */
7864.LOP_NEW_ARRAY_resolve:
7865    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7866    mov     r9, r1                      @ r9<- length (save)
7867    mov     r1, r2                      @ r1<- CCCC
7868    mov     r2, #0                      @ r2<- false
7869    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7870    bl      dvmResolveClass             @ r0<- call(clazz, ref)
7871    cmp     r0, #0                      @ got null?
7872    mov     r1, r9                      @ r1<- length (restore)
7873    beq     common_exceptionThrown      @ yes, handle exception
7874    @ fall through to OP_NEW_ARRAY_finish
7875
7876    /*
7877     * Finish allocation.
7878     *
7879     *  r0 holds class
7880     *  r1 holds array length
7881     */
7882.LOP_NEW_ARRAY_finish:
7883    mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
7884    bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
7885    cmp     r0, #0                      @ failed?
7886    mov     r2, rINST, lsr #8           @ r2<- A+
7887    beq     common_exceptionThrown      @ yes, handle the exception
7888    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7889    and     r2, r2, #15                 @ r2<- A
7890    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7891    SET_VREG(r0, r2)                    @ vA<- r0
7892    GOTO_OPCODE(ip)                     @ jump to next instruction
7893
7894
7895/* continuation for OP_FILLED_NEW_ARRAY */
7896
7897    /*
7898     * On entry:
7899     *  r0 holds array class
7900     *  r10 holds AA or BA
7901     */
7902.LOP_FILLED_NEW_ARRAY_continue:
7903    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
7904    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
7905    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
7906    .if     0
7907    mov     r1, r10                     @ r1<- AA (length)
7908    .else
7909    mov     r1, r10, lsr #4             @ r1<- B (length)
7910    .endif
7911    cmp     r3, #'I'                    @ array of ints?
7912    cmpne   r3, #'L'                    @ array of objects?
7913    cmpne   r3, #'['                    @ array of arrays?
7914    mov     r9, r1                      @ save length in r9
7915    bne     .LOP_FILLED_NEW_ARRAY_notimpl         @ no, not handled yet
7916    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
7917    cmp     r0, #0                      @ null return?
7918    beq     common_exceptionThrown      @ alloc failed, handle exception
7919
7920    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
7921    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
7922    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
7923    subs    r9, r9, #1                  @ length--, check for neg
7924    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7925    bmi     2f                          @ was zero, bail
7926
7927    @ copy values from registers into the array
7928    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
7929    .if     0
7930    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
79311:  ldr     r3, [r2], #4                @ r3<- *r2++
7932    subs    r9, r9, #1                  @ count--
7933    str     r3, [r0], #4                @ *contents++ = vX
7934    bpl     1b
7935    @ continue at 2
7936    .else
7937    cmp     r9, #4                      @ length was initially 5?
7938    and     r2, r10, #15                @ r2<- A
7939    bne     1f                          @ <= 4 args, branch
7940    GET_VREG(r3, r2)                    @ r3<- vA
7941    sub     r9, r9, #1                  @ count--
7942    str     r3, [r0, #16]               @ contents[4] = vA
79431:  and     r2, r1, #15                 @ r2<- F/E/D/C
7944    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
7945    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
7946    subs    r9, r9, #1                  @ count--
7947    str     r3, [r0], #4                @ *contents++ = vX
7948    bpl     1b
7949    @ continue at 2
7950    .endif
7951
79522:
7953    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7954    GOTO_OPCODE(ip)                     @ execute it
7955
7956    /*
7957     * Throw an exception indicating that we have not implemented this
7958     * mode of filled-new-array.
7959     */
7960.LOP_FILLED_NEW_ARRAY_notimpl:
7961    ldr     r0, .L_strInternalError
7962    ldr     r1, .L_strFilledNewArrayNotImpl
7963    bl      dvmThrowException
7964    b       common_exceptionThrown
7965
7966    .if     (!0)                 @ define in one or the other, not both
7967.L_strFilledNewArrayNotImpl:
7968    .word   .LstrFilledNewArrayNotImpl
7969.L_strInternalError:
7970    .word   .LstrInternalError
7971    .endif
7972
7973
7974/* continuation for OP_FILLED_NEW_ARRAY_RANGE */
7975
7976    /*
7977     * On entry:
7978     *  r0 holds array class
7979     *  r10 holds AA or BA
7980     */
7981.LOP_FILLED_NEW_ARRAY_RANGE_continue:
7982    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
7983    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
7984    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
7985    .if     1
7986    mov     r1, r10                     @ r1<- AA (length)
7987    .else
7988    mov     r1, r10, lsr #4             @ r1<- B (length)
7989    .endif
7990    cmp     r3, #'I'                    @ array of ints?
7991    cmpne   r3, #'L'                    @ array of objects?
7992    cmpne   r3, #'['                    @ array of arrays?
7993    mov     r9, r1                      @ save length in r9
7994    bne     .LOP_FILLED_NEW_ARRAY_RANGE_notimpl         @ no, not handled yet
7995    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
7996    cmp     r0, #0                      @ null return?
7997    beq     common_exceptionThrown      @ alloc failed, handle exception
7998
7999    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8000    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
8001    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8002    subs    r9, r9, #1                  @ length--, check for neg
8003    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8004    bmi     2f                          @ was zero, bail
8005
8006    @ copy values from registers into the array
8007    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8008    .if     1
8009    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
80101:  ldr     r3, [r2], #4                @ r3<- *r2++
8011    subs    r9, r9, #1                  @ count--
8012    str     r3, [r0], #4                @ *contents++ = vX
8013    bpl     1b
8014    @ continue at 2
8015    .else
8016    cmp     r9, #4                      @ length was initially 5?
8017    and     r2, r10, #15                @ r2<- A
8018    bne     1f                          @ <= 4 args, branch
8019    GET_VREG(r3, r2)                    @ r3<- vA
8020    sub     r9, r9, #1                  @ count--
8021    str     r3, [r0, #16]               @ contents[4] = vA
80221:  and     r2, r1, #15                 @ r2<- F/E/D/C
8023    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8024    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8025    subs    r9, r9, #1                  @ count--
8026    str     r3, [r0], #4                @ *contents++ = vX
8027    bpl     1b
8028    @ continue at 2
8029    .endif
8030
80312:
8032    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
8033    GOTO_OPCODE(ip)                     @ execute it
8034
8035    /*
8036     * Throw an exception indicating that we have not implemented this
8037     * mode of filled-new-array.
8038     */
8039.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
8040    ldr     r0, .L_strInternalError
8041    ldr     r1, .L_strFilledNewArrayNotImpl
8042    bl      dvmThrowException
8043    b       common_exceptionThrown
8044
8045    .if     (!1)                 @ define in one or the other, not both
8046.L_strFilledNewArrayNotImpl:
8047    .word   .LstrFilledNewArrayNotImpl
8048.L_strInternalError:
8049    .word   .LstrInternalError
8050    .endif
8051
8052
8053/* continuation for OP_CMPL_FLOAT */
8054.LOP_CMPL_FLOAT_finish:
8055    SET_VREG(r0, r9)                    @ vAA<- r0
8056    GOTO_OPCODE(ip)                     @ jump to next instruction
8057
8058
8059/* continuation for OP_CMPG_FLOAT */
8060.LOP_CMPG_FLOAT_finish:
8061    SET_VREG(r0, r9)                    @ vAA<- r0
8062    GOTO_OPCODE(ip)                     @ jump to next instruction
8063
8064
8065/* continuation for OP_CMPL_DOUBLE */
8066.LOP_CMPL_DOUBLE_finish:
8067    SET_VREG(r0, r9)                    @ vAA<- r0
8068    GOTO_OPCODE(ip)                     @ jump to next instruction
8069
8070
8071/* continuation for OP_CMPG_DOUBLE */
8072.LOP_CMPG_DOUBLE_finish:
8073    SET_VREG(r0, r9)                    @ vAA<- r0
8074    GOTO_OPCODE(ip)                     @ jump to next instruction
8075
8076
8077/* continuation for OP_CMP_LONG */
8078
8079.LOP_CMP_LONG_less:
8080    mvn     r1, #0                      @ r1<- -1
8081    @ Want to cond code the next mov so we can avoid branch, but don't see it;
8082    @ instead, we just replicate the tail end.
8083    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8084    SET_VREG(r1, r9)                    @ vAA<- r1
8085    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8086    GOTO_OPCODE(ip)                     @ jump to next instruction
8087
8088.LOP_CMP_LONG_greater:
8089    mov     r1, #1                      @ r1<- 1
8090    @ fall through to _finish
8091
8092.LOP_CMP_LONG_finish:
8093    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8094    SET_VREG(r1, r9)                    @ vAA<- r1
8095    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8096    GOTO_OPCODE(ip)                     @ jump to next instruction
8097
8098
8099/* continuation for OP_AGET_WIDE */
8100
8101.LOP_AGET_WIDE_finish:
8102    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8103    ldrd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8104    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
8105    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8106    stmia   r9, {r2-r3}                 @ vAA/vAA+1<- r2/r3
8107    GOTO_OPCODE(ip)                     @ jump to next instruction
8108
8109
8110/* continuation for OP_APUT_WIDE */
8111
8112.LOP_APUT_WIDE_finish:
8113    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8114    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
8115    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8116    strd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8117    GOTO_OPCODE(ip)                     @ jump to next instruction
8118
8119
8120/* continuation for OP_APUT_OBJECT */
8121    /*
8122     * On entry:
8123     *  r1 = vBB (arrayObj)
8124     *  r9 = vAA (obj)
8125     *  r10 = offset into array (vBB + vCC * width)
8126     */
8127.LOP_APUT_OBJECT_finish:
8128    cmp     r9, #0                      @ storing null reference?
8129    beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
8130    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
8131    ldr     r1, [r1, #offObject_clazz]  @ r1<- arrayObj->clazz
8132    bl      dvmCanPutArrayElement       @ test object type vs. array type
8133    cmp     r0, #0                      @ okay?
8134    beq     common_errArrayStore        @ no
8135.LOP_APUT_OBJECT_skip_check:
8136    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8137    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8138    str     r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
8139    GOTO_OPCODE(ip)                     @ jump to next instruction
8140
8141
8142/* continuation for OP_IGET */
8143
8144    /*
8145     * Currently:
8146     *  r0 holds resolved field
8147     *  r9 holds object
8148     */
8149.LOP_IGET_finish:
8150    @bl      common_squeak0
8151    cmp     r9, #0                      @ check object for null
8152    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8153    beq     common_errNullObject        @ object was null
8154    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8155    mov     r2, rINST, lsr #8           @ r2<- A+
8156    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8157    and     r2, r2, #15                 @ r2<- A
8158    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8159    SET_VREG(r0, r2)                    @ fp[A]<- r0
8160    GOTO_OPCODE(ip)                     @ jump to next instruction
8161
8162
8163/* continuation for OP_IGET_WIDE */
8164
8165    /*
8166     * Currently:
8167     *  r0 holds resolved field
8168     *  r9 holds object
8169     */
8170.LOP_IGET_WIDE_finish:
8171    cmp     r9, #0                      @ check object for null
8172    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8173    beq     common_errNullObject        @ object was null
8174    mov     r2, rINST, lsr #8           @ r2<- A+
8175    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
8176    and     r2, r2, #15                 @ r2<- A
8177    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8178    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
8179    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8180    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
8181    GOTO_OPCODE(ip)                     @ jump to next instruction
8182
8183
8184/* continuation for OP_IGET_OBJECT */
8185
8186    /*
8187     * Currently:
8188     *  r0 holds resolved field
8189     *  r9 holds object
8190     */
8191.LOP_IGET_OBJECT_finish:
8192    @bl      common_squeak0
8193    cmp     r9, #0                      @ check object for null
8194    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8195    beq     common_errNullObject        @ object was null
8196    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8197    mov     r2, rINST, lsr #8           @ r2<- A+
8198    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8199    and     r2, r2, #15                 @ r2<- A
8200    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8201    SET_VREG(r0, r2)                    @ fp[A]<- r0
8202    GOTO_OPCODE(ip)                     @ jump to next instruction
8203
8204
8205/* continuation for OP_IGET_BOOLEAN */
8206
8207    /*
8208     * Currently:
8209     *  r0 holds resolved field
8210     *  r9 holds object
8211     */
8212.LOP_IGET_BOOLEAN_finish:
8213    @bl      common_squeak1
8214    cmp     r9, #0                      @ check object for null
8215    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8216    beq     common_errNullObject        @ object was null
8217    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8218    mov     r2, rINST, lsr #8           @ r2<- A+
8219    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8220    and     r2, r2, #15                 @ r2<- A
8221    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8222    SET_VREG(r0, r2)                    @ fp[A]<- r0
8223    GOTO_OPCODE(ip)                     @ jump to next instruction
8224
8225
8226/* continuation for OP_IGET_BYTE */
8227
8228    /*
8229     * Currently:
8230     *  r0 holds resolved field
8231     *  r9 holds object
8232     */
8233.LOP_IGET_BYTE_finish:
8234    @bl      common_squeak2
8235    cmp     r9, #0                      @ check object for null
8236    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8237    beq     common_errNullObject        @ object was null
8238    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8239    mov     r2, rINST, lsr #8           @ r2<- A+
8240    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8241    and     r2, r2, #15                 @ r2<- A
8242    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8243    SET_VREG(r0, r2)                    @ fp[A]<- r0
8244    GOTO_OPCODE(ip)                     @ jump to next instruction
8245
8246
8247/* continuation for OP_IGET_CHAR */
8248
8249    /*
8250     * Currently:
8251     *  r0 holds resolved field
8252     *  r9 holds object
8253     */
8254.LOP_IGET_CHAR_finish:
8255    @bl      common_squeak3
8256    cmp     r9, #0                      @ check object for null
8257    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8258    beq     common_errNullObject        @ object was null
8259    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8260    mov     r2, rINST, lsr #8           @ r2<- A+
8261    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8262    and     r2, r2, #15                 @ r2<- A
8263    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8264    SET_VREG(r0, r2)                    @ fp[A]<- r0
8265    GOTO_OPCODE(ip)                     @ jump to next instruction
8266
8267
8268/* continuation for OP_IGET_SHORT */
8269
8270    /*
8271     * Currently:
8272     *  r0 holds resolved field
8273     *  r9 holds object
8274     */
8275.LOP_IGET_SHORT_finish:
8276    @bl      common_squeak4
8277    cmp     r9, #0                      @ check object for null
8278    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8279    beq     common_errNullObject        @ object was null
8280    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8281    mov     r2, rINST, lsr #8           @ r2<- A+
8282    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8283    and     r2, r2, #15                 @ r2<- A
8284    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8285    SET_VREG(r0, r2)                    @ fp[A]<- r0
8286    GOTO_OPCODE(ip)                     @ jump to next instruction
8287
8288
8289/* continuation for OP_IPUT */
8290
8291    /*
8292     * Currently:
8293     *  r0 holds resolved field
8294     *  r9 holds object
8295     */
8296.LOP_IPUT_finish:
8297    @bl      common_squeak0
8298    mov     r1, rINST, lsr #8           @ r1<- A+
8299    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8300    and     r1, r1, #15                 @ r1<- A
8301    cmp     r9, #0                      @ check object for null
8302    GET_VREG(r0, r1)                    @ r0<- fp[A]
8303    beq     common_errNullObject        @ object was null
8304    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8305    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8306    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8307    GOTO_OPCODE(ip)                     @ jump to next instruction
8308
8309
8310/* continuation for OP_IPUT_WIDE */
8311
8312    /*
8313     * Currently:
8314     *  r0 holds resolved field
8315     *  r9 holds object
8316     */
8317.LOP_IPUT_WIDE_finish:
8318    mov     r2, rINST, lsr #8           @ r2<- A+
8319    cmp     r9, #0                      @ check object for null
8320    and     r2, r2, #15                 @ r2<- A
8321    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8322    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
8323    beq     common_errNullObject        @ object was null
8324    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8325    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
8326    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8327    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0
8328    GOTO_OPCODE(ip)                     @ jump to next instruction
8329
8330
8331/* continuation for OP_IPUT_OBJECT */
8332
8333    /*
8334     * Currently:
8335     *  r0 holds resolved field
8336     *  r9 holds object
8337     */
8338.LOP_IPUT_OBJECT_finish:
8339    @bl      common_squeak0
8340    mov     r1, rINST, lsr #8           @ r1<- A+
8341    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8342    and     r1, r1, #15                 @ r1<- A
8343    cmp     r9, #0                      @ check object for null
8344    GET_VREG(r0, r1)                    @ r0<- fp[A]
8345    beq     common_errNullObject        @ object was null
8346    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8347    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8348    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8349    GOTO_OPCODE(ip)                     @ jump to next instruction
8350
8351
8352/* continuation for OP_IPUT_BOOLEAN */
8353
8354    /*
8355     * Currently:
8356     *  r0 holds resolved field
8357     *  r9 holds object
8358     */
8359.LOP_IPUT_BOOLEAN_finish:
8360    @bl      common_squeak1
8361    mov     r1, rINST, lsr #8           @ r1<- A+
8362    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8363    and     r1, r1, #15                 @ r1<- A
8364    cmp     r9, #0                      @ check object for null
8365    GET_VREG(r0, r1)                    @ r0<- fp[A]
8366    beq     common_errNullObject        @ object was null
8367    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8368    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8369    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8370    GOTO_OPCODE(ip)                     @ jump to next instruction
8371
8372
8373/* continuation for OP_IPUT_BYTE */
8374
8375    /*
8376     * Currently:
8377     *  r0 holds resolved field
8378     *  r9 holds object
8379     */
8380.LOP_IPUT_BYTE_finish:
8381    @bl      common_squeak2
8382    mov     r1, rINST, lsr #8           @ r1<- A+
8383    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8384    and     r1, r1, #15                 @ r1<- A
8385    cmp     r9, #0                      @ check object for null
8386    GET_VREG(r0, r1)                    @ r0<- fp[A]
8387    beq     common_errNullObject        @ object was null
8388    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8389    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8390    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8391    GOTO_OPCODE(ip)                     @ jump to next instruction
8392
8393
8394/* continuation for OP_IPUT_CHAR */
8395
8396    /*
8397     * Currently:
8398     *  r0 holds resolved field
8399     *  r9 holds object
8400     */
8401.LOP_IPUT_CHAR_finish:
8402    @bl      common_squeak3
8403    mov     r1, rINST, lsr #8           @ r1<- A+
8404    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8405    and     r1, r1, #15                 @ r1<- A
8406    cmp     r9, #0                      @ check object for null
8407    GET_VREG(r0, r1)                    @ r0<- fp[A]
8408    beq     common_errNullObject        @ object was null
8409    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8410    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8411    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8412    GOTO_OPCODE(ip)                     @ jump to next instruction
8413
8414
8415/* continuation for OP_IPUT_SHORT */
8416
8417    /*
8418     * Currently:
8419     *  r0 holds resolved field
8420     *  r9 holds object
8421     */
8422.LOP_IPUT_SHORT_finish:
8423    @bl      common_squeak4
8424    mov     r1, rINST, lsr #8           @ r1<- A+
8425    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8426    and     r1, r1, #15                 @ r1<- A
8427    cmp     r9, #0                      @ check object for null
8428    GET_VREG(r0, r1)                    @ r0<- fp[A]
8429    beq     common_errNullObject        @ object was null
8430    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8431    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8432    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8433    GOTO_OPCODE(ip)                     @ jump to next instruction
8434
8435
8436/* continuation for OP_SGET */
8437
8438    /*
8439     * Continuation if the field has not yet been resolved.
8440     *  r1: BBBB field ref
8441     */
8442.LOP_SGET_resolve:
8443    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8444    EXPORT_PC()                         @ resolve() could throw, so export now
8445    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8446    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8447    cmp     r0, #0                      @ success?
8448    bne     .LOP_SGET_finish          @ yes, finish
8449    b       common_exceptionThrown      @ no, handle exception
8450
8451
8452/* continuation for OP_SGET_WIDE */
8453
8454    /*
8455     * Continuation if the field has not yet been resolved.
8456     *  r1: BBBB field ref
8457     */
8458.LOP_SGET_WIDE_resolve:
8459    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8460    EXPORT_PC()                         @ resolve() could throw, so export now
8461    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8462    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8463    cmp     r0, #0                      @ success?
8464    bne     .LOP_SGET_WIDE_finish          @ yes, finish
8465    b       common_exceptionThrown      @ no, handle exception
8466
8467
8468/* continuation for OP_SGET_OBJECT */
8469
8470    /*
8471     * Continuation if the field has not yet been resolved.
8472     *  r1: BBBB field ref
8473     */
8474.LOP_SGET_OBJECT_resolve:
8475    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8476    EXPORT_PC()                         @ resolve() could throw, so export now
8477    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8478    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8479    cmp     r0, #0                      @ success?
8480    bne     .LOP_SGET_OBJECT_finish          @ yes, finish
8481    b       common_exceptionThrown      @ no, handle exception
8482
8483
8484/* continuation for OP_SGET_BOOLEAN */
8485
8486    /*
8487     * Continuation if the field has not yet been resolved.
8488     *  r1: BBBB field ref
8489     */
8490.LOP_SGET_BOOLEAN_resolve:
8491    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8492    EXPORT_PC()                         @ resolve() could throw, so export now
8493    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8494    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8495    cmp     r0, #0                      @ success?
8496    bne     .LOP_SGET_BOOLEAN_finish          @ yes, finish
8497    b       common_exceptionThrown      @ no, handle exception
8498
8499
8500/* continuation for OP_SGET_BYTE */
8501
8502    /*
8503     * Continuation if the field has not yet been resolved.
8504     *  r1: BBBB field ref
8505     */
8506.LOP_SGET_BYTE_resolve:
8507    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8508    EXPORT_PC()                         @ resolve() could throw, so export now
8509    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8510    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8511    cmp     r0, #0                      @ success?
8512    bne     .LOP_SGET_BYTE_finish          @ yes, finish
8513    b       common_exceptionThrown      @ no, handle exception
8514
8515
8516/* continuation for OP_SGET_CHAR */
8517
8518    /*
8519     * Continuation if the field has not yet been resolved.
8520     *  r1: BBBB field ref
8521     */
8522.LOP_SGET_CHAR_resolve:
8523    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8524    EXPORT_PC()                         @ resolve() could throw, so export now
8525    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8526    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8527    cmp     r0, #0                      @ success?
8528    bne     .LOP_SGET_CHAR_finish          @ yes, finish
8529    b       common_exceptionThrown      @ no, handle exception
8530
8531
8532/* continuation for OP_SGET_SHORT */
8533
8534    /*
8535     * Continuation if the field has not yet been resolved.
8536     *  r1: BBBB field ref
8537     */
8538.LOP_SGET_SHORT_resolve:
8539    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8540    EXPORT_PC()                         @ resolve() could throw, so export now
8541    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8542    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8543    cmp     r0, #0                      @ success?
8544    bne     .LOP_SGET_SHORT_finish          @ yes, finish
8545    b       common_exceptionThrown      @ no, handle exception
8546
8547
8548/* continuation for OP_SPUT */
8549
8550    /*
8551     * Continuation if the field has not yet been resolved.
8552     *  r1: BBBB field ref
8553     */
8554.LOP_SPUT_resolve:
8555    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8556    EXPORT_PC()                         @ resolve() could throw, so export now
8557    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8558    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8559    cmp     r0, #0                      @ success?
8560    bne     .LOP_SPUT_finish          @ yes, finish
8561    b       common_exceptionThrown      @ no, handle exception
8562
8563
8564/* continuation for OP_SPUT_WIDE */
8565
8566    /*
8567     * Continuation if the field has not yet been resolved.
8568     *  r1: BBBB field ref
8569     *  r9: &fp[AA]
8570     */
8571.LOP_SPUT_WIDE_resolve:
8572    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8573    EXPORT_PC()                         @ resolve() could throw, so export now
8574    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8575    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8576    cmp     r0, #0                      @ success?
8577    bne     .LOP_SPUT_WIDE_finish          @ yes, finish
8578    b       common_exceptionThrown      @ no, handle exception
8579
8580
8581/* continuation for OP_SPUT_OBJECT */
8582
8583    /*
8584     * Continuation if the field has not yet been resolved.
8585     *  r1: BBBB field ref
8586     */
8587.LOP_SPUT_OBJECT_resolve:
8588    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8589    EXPORT_PC()                         @ resolve() could throw, so export now
8590    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8591    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8592    cmp     r0, #0                      @ success?
8593    bne     .LOP_SPUT_OBJECT_finish          @ yes, finish
8594    b       common_exceptionThrown      @ no, handle exception
8595
8596
8597/* continuation for OP_SPUT_BOOLEAN */
8598
8599    /*
8600     * Continuation if the field has not yet been resolved.
8601     *  r1: BBBB field ref
8602     */
8603.LOP_SPUT_BOOLEAN_resolve:
8604    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8605    EXPORT_PC()                         @ resolve() could throw, so export now
8606    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8607    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8608    cmp     r0, #0                      @ success?
8609    bne     .LOP_SPUT_BOOLEAN_finish          @ yes, finish
8610    b       common_exceptionThrown      @ no, handle exception
8611
8612
8613/* continuation for OP_SPUT_BYTE */
8614
8615    /*
8616     * Continuation if the field has not yet been resolved.
8617     *  r1: BBBB field ref
8618     */
8619.LOP_SPUT_BYTE_resolve:
8620    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8621    EXPORT_PC()                         @ resolve() could throw, so export now
8622    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8623    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8624    cmp     r0, #0                      @ success?
8625    bne     .LOP_SPUT_BYTE_finish          @ yes, finish
8626    b       common_exceptionThrown      @ no, handle exception
8627
8628
8629/* continuation for OP_SPUT_CHAR */
8630
8631    /*
8632     * Continuation if the field has not yet been resolved.
8633     *  r1: BBBB field ref
8634     */
8635.LOP_SPUT_CHAR_resolve:
8636    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8637    EXPORT_PC()                         @ resolve() could throw, so export now
8638    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8639    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8640    cmp     r0, #0                      @ success?
8641    bne     .LOP_SPUT_CHAR_finish          @ yes, finish
8642    b       common_exceptionThrown      @ no, handle exception
8643
8644
8645/* continuation for OP_SPUT_SHORT */
8646
8647    /*
8648     * Continuation if the field has not yet been resolved.
8649     *  r1: BBBB field ref
8650     */
8651.LOP_SPUT_SHORT_resolve:
8652    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8653    EXPORT_PC()                         @ resolve() could throw, so export now
8654    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8655    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8656    cmp     r0, #0                      @ success?
8657    bne     .LOP_SPUT_SHORT_finish          @ yes, finish
8658    b       common_exceptionThrown      @ no, handle exception
8659
8660
8661/* continuation for OP_INVOKE_VIRTUAL */
8662
8663    /*
8664     * At this point:
8665     *  r0 = resolved base method
8666     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8667     */
8668.LOP_INVOKE_VIRTUAL_continue:
8669    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8670    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8671    cmp     r1, #0                      @ is "this" null?
8672    beq     common_errNullObject        @ null "this", throw exception
8673    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8674    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8675    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8676    bl      common_invokeMethodNoRange @ continue on
8677
8678
8679/* continuation for OP_INVOKE_SUPER */
8680
8681    /*
8682     * At this point:
8683     *  r0 = resolved base method
8684     *  r9 = method->clazz
8685     */
8686.LOP_INVOKE_SUPER_continue:
8687    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8688    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8689    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8690    EXPORT_PC()                         @ must export for invoke
8691    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8692    bcs     .LOP_INVOKE_SUPER_nsm             @ method not present in superclass
8693    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8694    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8695    bl      common_invokeMethodNoRange @ continue on
8696
8697.LOP_INVOKE_SUPER_resolve:
8698    mov     r0, r9                      @ r0<- method->clazz
8699    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8700    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8701    cmp     r0, #0                      @ got null?
8702    bne     .LOP_INVOKE_SUPER_continue        @ no, continue
8703    b       common_exceptionThrown      @ yes, handle exception
8704
8705    /*
8706     * Throw a NoSuchMethodError with the method name as the message.
8707     *  r0 = resolved base method
8708     */
8709.LOP_INVOKE_SUPER_nsm:
8710    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8711    b       common_errNoSuchMethod
8712
8713
8714/* continuation for OP_INVOKE_DIRECT */
8715
8716    /*
8717     * On entry:
8718     *  r1 = reference (BBBB or CCCC)
8719     *  r10 = "this" register
8720     */
8721.LOP_INVOKE_DIRECT_resolve:
8722    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8723    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8724    mov     r2, #METHOD_DIRECT          @ resolver method type
8725    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8726    cmp     r0, #0                      @ got null?
8727    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8728    bne     .LOP_INVOKE_DIRECT_finish          @ no, continue
8729    b       common_exceptionThrown      @ yes, handle exception
8730
8731
8732/* continuation for OP_INVOKE_VIRTUAL_RANGE */
8733
8734    /*
8735     * At this point:
8736     *  r0 = resolved base method
8737     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8738     */
8739.LOP_INVOKE_VIRTUAL_RANGE_continue:
8740    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8741    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8742    cmp     r1, #0                      @ is "this" null?
8743    beq     common_errNullObject        @ null "this", throw exception
8744    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8745    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8746    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8747    bl      common_invokeMethodRange @ continue on
8748
8749
8750/* continuation for OP_INVOKE_SUPER_RANGE */
8751
8752    /*
8753     * At this point:
8754     *  r0 = resolved base method
8755     *  r9 = method->clazz
8756     */
8757.LOP_INVOKE_SUPER_RANGE_continue:
8758    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8759    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8760    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8761    EXPORT_PC()                         @ must export for invoke
8762    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8763    bcs     .LOP_INVOKE_SUPER_RANGE_nsm             @ method not present in superclass
8764    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8765    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8766    bl      common_invokeMethodRange @ continue on
8767
8768.LOP_INVOKE_SUPER_RANGE_resolve:
8769    mov     r0, r9                      @ r0<- method->clazz
8770    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8771    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8772    cmp     r0, #0                      @ got null?
8773    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ no, continue
8774    b       common_exceptionThrown      @ yes, handle exception
8775
8776    /*
8777     * Throw a NoSuchMethodError with the method name as the message.
8778     *  r0 = resolved base method
8779     */
8780.LOP_INVOKE_SUPER_RANGE_nsm:
8781    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8782    b       common_errNoSuchMethod
8783
8784
8785/* continuation for OP_INVOKE_DIRECT_RANGE */
8786
8787    /*
8788     * On entry:
8789     *  r1 = reference (BBBB or CCCC)
8790     *  r10 = "this" register
8791     */
8792.LOP_INVOKE_DIRECT_RANGE_resolve:
8793    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8794    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8795    mov     r2, #METHOD_DIRECT          @ resolver method type
8796    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8797    cmp     r0, #0                      @ got null?
8798    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8799    bne     .LOP_INVOKE_DIRECT_RANGE_finish          @ no, continue
8800    b       common_exceptionThrown      @ yes, handle exception
8801
8802
8803/* continuation for OP_FLOAT_TO_LONG */
8804/*
8805 * Convert the float in r0 to a long in r0/r1.
8806 *
8807 * We have to clip values to long min/max per the specification.  The
8808 * expected common case is a "reasonable" value that converts directly
8809 * to modest integer.  The EABI convert function isn't doing this for us.
8810 */
8811f2l_doconv:
8812    stmfd   sp!, {r4, lr}
8813    mov     r1, #0x5f000000             @ (float)maxlong
8814    mov     r4, r0
8815    bl      __aeabi_fcmpge              @ is arg >= maxlong?
8816    cmp     r0, #0                      @ nonzero == yes
8817    mvnne   r0, #0                      @ return maxlong (7fffffff)
8818    mvnne   r1, #0x80000000
8819    ldmnefd sp!, {r4, pc}
8820
8821    mov     r0, r4                      @ recover arg
8822    mov     r1, #0xdf000000             @ (float)minlong
8823    bl      __aeabi_fcmple              @ is arg <= minlong?
8824    cmp     r0, #0                      @ nonzero == yes
8825    movne   r0, #0                      @ return minlong (80000000)
8826    movne   r1, #0x80000000
8827    ldmnefd sp!, {r4, pc}
8828
8829    mov     r0, r4                      @ recover arg
8830    mov     r1, r4
8831    bl      __aeabi_fcmpeq              @ is arg == self?
8832    cmp     r0, #0                      @ zero == no
8833    moveq   r1, #0                      @ return zero for NaN
8834    ldmeqfd sp!, {r4, pc}
8835
8836    mov     r0, r4                      @ recover arg
8837    bl      __aeabi_f2lz                @ convert float to long
8838    ldmfd   sp!, {r4, pc}
8839
8840
8841/* continuation for OP_DOUBLE_TO_LONG */
8842/*
8843 * Convert the double in r0/r1 to a long in r0/r1.
8844 *
8845 * We have to clip values to long min/max per the specification.  The
8846 * expected common case is a "reasonable" value that converts directly
8847 * to modest integer.  The EABI convert function isn't doing this for us.
8848 */
8849d2l_doconv:
8850    stmfd   sp!, {r4, r5, lr}           @ save regs
8851    mov     r3, #0x43000000             @ maxlong, as a double (high word)
8852    add     r3, #0x00e00000             @  0x43e00000
8853    mov     r2, #0                      @ maxlong, as a double (low word)
8854    sub     sp, sp, #4                  @ align for EABI
8855    mov     r4, r0                      @ save a copy of r0
8856    mov     r5, r1                      @  and r1
8857    bl      __aeabi_dcmpge              @ is arg >= maxlong?
8858    cmp     r0, #0                      @ nonzero == yes
8859    mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
8860    mvnne   r1, #0x80000000
8861    bne     1f
8862
8863    mov     r0, r4                      @ recover arg
8864    mov     r1, r5
8865    mov     r3, #0xc3000000             @ minlong, as a double (high word)
8866    add     r3, #0x00e00000             @  0xc3e00000
8867    mov     r2, #0                      @ minlong, as a double (low word)
8868    bl      __aeabi_dcmple              @ is arg <= minlong?
8869    cmp     r0, #0                      @ nonzero == yes
8870    movne   r0, #0                      @ return minlong (8000000000000000)
8871    movne   r1, #0x80000000
8872    bne     1f
8873
8874    mov     r0, r4                      @ recover arg
8875    mov     r1, r5
8876    mov     r2, r4                      @ compare against self
8877    mov     r3, r5
8878    bl      __aeabi_dcmpeq              @ is arg == self?
8879    cmp     r0, #0                      @ zero == no
8880    moveq   r1, #0                      @ return zero for NaN
8881    beq     1f
8882
8883    mov     r0, r4                      @ recover arg
8884    mov     r1, r5
8885    bl      __aeabi_d2lz                @ convert double to long
8886
88871:
8888    add     sp, sp, #4
8889    ldmfd   sp!, {r4, r5, pc}
8890
8891
8892/* continuation for OP_MUL_LONG */
8893
8894.LOP_MUL_LONG_finish:
8895    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8896    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
8897    GOTO_OPCODE(ip)                     @ jump to next instruction
8898
8899
8900/* continuation for OP_SHL_LONG */
8901
8902.LOP_SHL_LONG_finish:
8903    mov     r0, r0, asl r2              @  r0<- r0 << r2
8904    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8905    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8906    GOTO_OPCODE(ip)                     @ jump to next instruction
8907
8908
8909/* continuation for OP_SHR_LONG */
8910
8911.LOP_SHR_LONG_finish:
8912    mov     r1, r1, asr r2              @  r1<- r1 >> r2
8913    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8914    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8915    GOTO_OPCODE(ip)                     @ jump to next instruction
8916
8917
8918/* continuation for OP_USHR_LONG */
8919
8920.LOP_USHR_LONG_finish:
8921    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
8922    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8923    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8924    GOTO_OPCODE(ip)                     @ jump to next instruction
8925
8926
8927/* continuation for OP_SHL_LONG_2ADDR */
8928
8929.LOP_SHL_LONG_2ADDR_finish:
8930    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8931    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8932    GOTO_OPCODE(ip)                     @ jump to next instruction
8933
8934
8935/* continuation for OP_SHR_LONG_2ADDR */
8936
8937.LOP_SHR_LONG_2ADDR_finish:
8938    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8939    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8940    GOTO_OPCODE(ip)                     @ jump to next instruction
8941
8942
8943/* continuation for OP_USHR_LONG_2ADDR */
8944
8945.LOP_USHR_LONG_2ADDR_finish:
8946    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8947    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8948    GOTO_OPCODE(ip)                     @ jump to next instruction
8949
8950
8951/* continuation for OP_EXECUTE_INLINE */
8952
8953    /*
8954     * Extract args, call function.
8955     *  r0 = #of args (0-4)
8956     *  r10 = call index
8957     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
8958     *
8959     * Other ideas:
8960     * - Use a jump table from the main piece to jump directly into the
8961     *   AND/LDR pairs.  Costs a data load, saves a branch.
8962     * - Have five separate pieces that do the loading, so we can work the
8963     *   interleave a little better.  Increases code size.
8964     */
8965.LOP_EXECUTE_INLINE_continue:
8966    rsb     r0, r0, #4                  @ r0<- 4-r0
8967    FETCH(r9, 2)                        @ r9<- FEDC
8968    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
8969    bl      common_abort                @ (skipped due to ARM prefetch)
89704:  and     ip, r9, #0xf000             @ isolate F
8971    ldr     r3, [rFP, ip, lsr #10]      @ r3<- vF (shift right 12, left 2)
89723:  and     ip, r9, #0x0f00             @ isolate E
8973    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vE
89742:  and     ip, r9, #0x00f0             @ isolate D
8975    ldr     r1, [rFP, ip, lsr #2]       @ r1<- vD
89761:  and     ip, r9, #0x000f             @ isolate C
8977    ldr     r0, [rFP, ip, lsl #2]       @ r0<- vC
89780:
8979    ldr     r9, .LOP_EXECUTE_INLINE_table       @ table of InlineOperation
8980    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
8981    @ (not reached)
8982
8983.LOP_EXECUTE_INLINE_table:
8984    .word   gDvmInlineOpsTable
8985
8986
8987    .size   dvmAsmSisterStart, .-dvmAsmSisterStart
8988    .global dvmAsmSisterEnd
8989dvmAsmSisterEnd:
8990
8991/* File: armv5te/footer.S */
8992
8993/*
8994 * ===========================================================================
8995 *  Common subroutines and data
8996 * ===========================================================================
8997 */
8998
8999
9000
9001    .text
9002    .align  2
9003
9004#if defined(WITH_JIT)
9005#if defined(WITH_SELF_VERIFICATION)
9006    .global dvmJitToInterpPunt
9007dvmJitToInterpPunt:
9008    mov    r2,#kSVSPunt                 @ r2<- interpreter entry point
9009    b      dvmJitSelfVerificationEnd    @ doesn't return
9010
9011    .global dvmJitToInterpSingleStep
9012dvmJitToInterpSingleStep:
9013    mov    r2,#kSVSSingleStep           @ r2<- interpreter entry point
9014    b      dvmJitSelfVerificationEnd    @ doesn't return
9015
9016    .global dvmJitToTraceSelect
9017dvmJitToTraceSelect:
9018    ldr    r0,[lr, #-1]                 @ pass our target PC
9019    mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
9020    b      dvmJitSelfVerificationEnd    @ doesn't return
9021
9022    .global dvmJitToBackwardBranch
9023dvmJitToBackwardBranch:
9024    ldr    r0,[lr, #-1]                 @ pass our target PC
9025    mov    r2,#kSVSBackwardBranch       @ r2<- interpreter entry point
9026    b      dvmJitSelfVerificationEnd    @ doesn't return
9027
9028    .global dvmJitToInterpNormal
9029dvmJitToInterpNormal:
9030    ldr    r0,[lr, #-1]                 @ pass our target PC
9031    mov    r2,#kSVSNormal               @ r2<- interpreter entry point
9032    b      dvmJitSelfVerificationEnd    @ doesn't return
9033
9034    .global dvmJitToInterpNoChain
9035dvmJitToInterpNoChain:
9036    mov    r0,rPC                       @ pass our target PC
9037    mov    r2,#kSVSNoChain              @ r2<- interpreter entry point
9038    b      dvmJitSelfVerificationEnd    @ doesn't return
9039#else
9040/*
9041 * Return from the translation cache to the interpreter when the compiler is
9042 * having issues translating/executing a Dalvik instruction. We have to skip
9043 * the code cache lookup otherwise it is possible to indefinitely bouce
9044 * between the interpreter and the code cache if the instruction that fails
9045 * to be compiled happens to be at a trace start.
9046 */
9047    .global dvmJitToInterpPunt
9048dvmJitToInterpPunt:
9049    mov    rPC, r0
9050#ifdef EXIT_STATS
9051    mov    r0,lr
9052    bl     dvmBumpPunt;
9053#endif
9054    EXPORT_PC()
9055    adrl   rIBASE, dvmAsmInstructionStart
9056    FETCH_INST()
9057    GET_INST_OPCODE(ip)
9058    GOTO_OPCODE(ip)
9059
9060/*
9061 * Return to the interpreter to handle a single instruction.
9062 * On entry:
9063 *    r0 <= PC
9064 *    r1 <= PC of resume instruction
9065 *    lr <= resume point in translation
9066 */
9067    .global dvmJitToInterpSingleStep
9068dvmJitToInterpSingleStep:
9069    str    lr,[rGLUE,#offGlue_jitResume]
9070    str    r1,[rGLUE,#offGlue_jitResumePC]
9071    mov    r1,#kInterpEntryInstr
9072    @ enum is 4 byte in aapcs-EABI
9073    str    r1, [rGLUE, #offGlue_entryPoint]
9074    mov    rPC,r0
9075    EXPORT_PC()
9076    adrl   rIBASE, dvmAsmInstructionStart
9077    mov    r2,#kJitSingleStep     @ Ask for single step and then revert
9078    str    r2,[rGLUE,#offGlue_jitState]
9079    mov    r1,#1                  @ set changeInterp to bail to debug interp
9080    b      common_gotoBail
9081
9082
9083/*
9084 * Return from the translation cache and immediately request
9085 * a translation for the exit target.  Commonly used following
9086 * invokes.
9087 */
9088    .global dvmJitToTraceSelect
9089dvmJitToTraceSelect:
9090    ldr    rPC,[lr, #-1]           @ get our target PC
9091    add    rINST,lr,#-5            @ save start of chain branch
9092    mov    r0,rPC
9093    bl     dvmJitGetCodeAddr        @ Is there a translation?
9094    cmp    r0,#0
9095    beq    2f
9096    mov    r1,rINST
9097    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9098    mov    r1, rPC                  @ arg1 of translation may need this
9099    mov    lr, #0                   @ in case target is HANDLER_INTERPRET
9100    cmp    r0,#0                    @ successful chain?
9101    bxne   r0                       @ continue native execution
9102    b      toInterpreter            @ didn't chain - resume with interpreter
9103
9104/* No translation, so request one if profiling isn't disabled*/
91052:
9106    adrl   rIBASE, dvmAsmInstructionStart
9107    GET_JIT_PROF_TABLE(r0)
9108    FETCH_INST()
9109    cmp    r0, #0
9110    bne    common_selectTrace
9111    GET_INST_OPCODE(ip)
9112    GOTO_OPCODE(ip)
9113
9114/*
9115 * Return from the translation cache to the interpreter.
9116 * The return was done with a BLX from thumb mode, and
9117 * the following 32-bit word contains the target rPC value.
9118 * Note that lr (r14) will have its low-order bit set to denote
9119 * its thumb-mode origin.
9120 *
9121 * We'll need to stash our lr origin away, recover the new
9122 * target and then check to see if there is a translation available
9123 * for our new target.  If so, we do a translation chain and
9124 * go back to native execution.  Otherwise, it's back to the
9125 * interpreter (after treating this entry as a potential
9126 * trace start).
9127 */
9128    .global dvmJitToInterpNormal
9129dvmJitToInterpNormal:
9130    ldr    rPC,[lr, #-1]           @ get our target PC
9131    add    rINST,lr,#-5            @ save start of chain branch
9132#ifdef EXIT_STATS
9133    bl     dvmBumpNormal
9134#endif
9135    mov    r0,rPC
9136    bl     dvmJitGetCodeAddr        @ Is there a translation?
9137    cmp    r0,#0
9138    beq    toInterpreter            @ go if not, otherwise do chain
9139    mov    r1,rINST
9140    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9141    mov    r1, rPC                  @ arg1 of translation may need this
9142    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9143    cmp    r0,#0                    @ successful chain?
9144    bxne   r0                       @ continue native execution
9145    b      toInterpreter            @ didn't chain - resume with interpreter
9146
9147/*
9148 * Return from the translation cache to the interpreter to do method invocation.
9149 * Check if translation exists for the callee, but don't chain to it.
9150 */
9151    .global dvmJitToInterpNoChain
9152dvmJitToInterpNoChain:
9153#ifdef EXIT_STATS
9154    bl     dvmBumpNoChain
9155#endif
9156    mov    r0,rPC
9157    bl     dvmJitGetCodeAddr        @ Is there a translation?
9158    mov    r1, rPC                  @ arg1 of translation may need this
9159    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9160    cmp    r0,#0
9161    bxne   r0                       @ continue native execution if so
9162#endif
9163
9164/*
9165 * No translation, restore interpreter regs and start interpreting.
9166 * rGLUE & rFP were preserved in the translated code, and rPC has
9167 * already been restored by the time we get here.  We'll need to set
9168 * up rIBASE & rINST, and load the address of the JitTable into r0.
9169 */
9170toInterpreter:
9171    EXPORT_PC()
9172    adrl   rIBASE, dvmAsmInstructionStart
9173    FETCH_INST()
9174    GET_JIT_PROF_TABLE(r0)
9175    @ NOTE: intended fallthrough
9176/*
9177 * Common code to update potential trace start counter, and initiate
9178 * a trace-build if appropriate.  On entry, rPC should point to the
9179 * next instruction to execute, and rINST should be already loaded with
9180 * the next opcode word, and r0 holds a pointer to the jit profile
9181 * table (pJitProfTable).
9182 */
9183common_testUpdateProfile:
9184    cmp     r0,#0
9185    GET_INST_OPCODE(ip)
9186    GOTO_OPCODE_IFEQ(ip)       @ if not profiling, fallthrough otherwise */
9187
9188common_updateProfile:
9189    eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
9190    lsl     r3,r3,#23          @ shift out excess 511
9191    ldrb    r1,[r0,r3,lsr #23] @ get counter
9192    GET_INST_OPCODE(ip)
9193    subs    r1,r1,#1           @ decrement counter
9194    strb    r1,[r0,r3,lsr #23] @ and store it
9195    GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
9196
9197/*
9198 * Here, we switch to the debug interpreter to request
9199 * trace selection.  First, though, check to see if there
9200 * is already a native translation in place (and, if so,
9201 * jump to it now).
9202 */
9203    GET_JIT_THRESHOLD(r1)
9204    strb    r1,[r0,r3,lsr #23] @ reset counter
9205    EXPORT_PC()
9206    mov     r0,rPC
9207    bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
9208    mov    r1, rPC                      @ arg1 of translation may need this
9209    mov    lr, #0                       @  in case target is HANDLER_INTERPRET
9210    cmp     r0,#0
9211#if !defined(WITH_SELF_VERIFICATION)
9212    bxne    r0                          @ jump to the translation
9213#else
9214    beq     common_selectTrace
9215    /*
9216     * At this point, we have a target translation.  However, if
9217     * that translation is actually the interpret-only pseudo-translation
9218     * we want to treat it the same as no translation.
9219     */
9220    mov     r10, r0                      @ save target
9221    bl      dvmCompilerGetInterpretTemplate
9222    cmp     r0, r10                      @ special case?
9223    bne     dvmJitSelfVerificationStart  @ set up self verification
9224    GET_INST_OPCODE(ip)
9225    GOTO_OPCODE(ip)
9226    /* no return */
9227#endif
9228
9229common_selectTrace:
9230    mov     r2,#kJitTSelectRequest      @ ask for trace selection
9231    str     r2,[rGLUE,#offGlue_jitState]
9232    mov     r2,#kInterpEntryInstr       @ normal entry reason
9233    str     r2,[rGLUE,#offGlue_entryPoint]
9234    mov     r1,#1                       @ set changeInterp
9235    b       common_gotoBail
9236
9237#if defined(WITH_SELF_VERIFICATION)
9238/*
9239 * Save PC and registers to shadow memory for self verification mode
9240 * before jumping to native translation.
9241 * On entry, r10 contains the address of the target translation.
9242 */
9243dvmJitSelfVerificationStart:
9244    mov     r0,rPC                      @ r0<- program counter
9245    mov     r1,rFP                      @ r1<- frame pointer
9246    mov     r2,rGLUE                    @ r2<- InterpState pointer
9247    mov     r3,r10                      @ r3<- target translation
9248    bl      dvmSelfVerificationSaveState @ save registers to shadow space
9249    ldr     rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
9250    add     rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
9251    bx      r10                         @ jump to the translation
9252
9253/*
9254 * Restore PC, registers, and interpState to original values
9255 * before jumping back to the interpreter.
9256 */
9257dvmJitSelfVerificationEnd:
9258    mov    r1,rFP                        @ pass ending fp
9259    bl     dvmSelfVerificationRestoreState @ restore pc and fp values
9260    ldr    rPC,[r0,#offShadowSpace_startPC] @ restore PC
9261    ldr    rFP,[r0,#offShadowSpace_fp]   @ restore FP
9262    ldr    rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
9263    ldr    r1,[r0,#offShadowSpace_svState] @ get self verification state
9264    cmp    r1,#0                         @ check for punt condition
9265    beq    1f
9266    mov    r2,#kJitSelfVerification      @ ask for self verification
9267    str    r2,[rGLUE,#offGlue_jitState]
9268    mov    r2,#kInterpEntryInstr         @ normal entry reason
9269    str    r2,[rGLUE,#offGlue_entryPoint]
9270    mov    r1,#1                         @ set changeInterp
9271    b      common_gotoBail
9272
92731:                                       @ exit to interpreter without check
9274    EXPORT_PC()
9275    adrl   rIBASE, dvmAsmInstructionStart
9276    FETCH_INST()
9277    GET_INST_OPCODE(ip)
9278    GOTO_OPCODE(ip)
9279#endif
9280
9281#endif
9282
9283/*
9284 * Common code when a backward branch is taken.
9285 *
9286 * On entry:
9287 *  r9 is PC adjustment *in bytes*
9288 */
9289common_backwardBranch:
9290    mov     r0, #kInterpEntryInstr
9291    bl      common_periodicChecks
9292#if defined(WITH_JIT)
9293    GET_JIT_PROF_TABLE(r0)
9294    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9295    cmp     r0,#0
9296    bne     common_updateProfile
9297    GET_INST_OPCODE(ip)
9298    GOTO_OPCODE(ip)
9299#else
9300    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9301    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9302    GOTO_OPCODE(ip)                     @ jump to next instruction
9303#endif
9304
9305
9306/*
9307 * Need to see if the thread needs to be suspended or debugger/profiler
9308 * activity has begun.
9309 *
9310 * TODO: if JDWP isn't running, zero out pDebuggerActive pointer so we don't
9311 * have to do the second ldr.
9312 *
9313 * TODO: reduce this so we're just checking a single location.
9314 *
9315 * On entry:
9316 *  r0 is reentry type, e.g. kInterpEntryInstr
9317 *  r9 is trampoline PC adjustment *in bytes*
9318 */
9319common_periodicChecks:
9320    ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
9321
9322    @ speculatively store r0 before it is clobbered by dvmCheckSuspendPending
9323    str     r0, [rGLUE, #offGlue_entryPoint]
9324
9325#if defined(WITH_DEBUGGER)
9326    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9327#endif
9328#if defined(WITH_PROFILER)
9329    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9330#endif
9331
9332    ldr     r3, [r3]                    @ r3<- suspendCount (int)
9333
9334#if defined(WITH_DEBUGGER)
9335    ldrb    r1, [r1]                    @ r1<- debuggerActive (boolean)
9336#endif
9337#if defined (WITH_PROFILER)
9338    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9339#endif
9340
9341    cmp     r3, #0                      @ suspend pending?
9342    bne     2f                          @ yes, do full suspension check
9343
9344#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
9345# if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
9346    orrs    r1, r1, r2                  @ r1<- r1 | r2
9347    cmp     r1, #0                      @ debugger attached or profiler started?
9348# elif defined(WITH_DEBUGGER)
9349    cmp     r1, #0                      @ debugger attached?
9350# elif defined(WITH_PROFILER)
9351    cmp     r2, #0                      @ profiler started?
9352# endif
9353    bne     3f                          @ debugger/profiler, switch interp
9354#endif
9355
9356    bx      lr                          @ nothing to do, return
9357
93582:  @ check suspend
9359    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9360    EXPORT_PC()                         @ need for precise GC
9361    b       dvmCheckSuspendPending      @ suspend if necessary, then return
9362
93633:  @ debugger/profiler enabled, bail out
9364    add     rPC, rPC, r9                @ update rPC
9365    mov     r1, #1                      @ "want switch" = true
9366    b       common_gotoBail
9367
9368
9369/*
9370 * The equivalent of "goto bail", this calls through the "bail handler".
9371 *
9372 * State registers will be saved to the "glue" area before bailing.
9373 *
9374 * On entry:
9375 *  r1 is "bool changeInterp", indicating if we want to switch to the
9376 *     other interpreter or just bail all the way out
9377 */
9378common_gotoBail:
9379    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9380    mov     r0, rGLUE                   @ r0<- glue ptr
9381    b       dvmMterpStdBail             @ call(glue, changeInterp)
9382
9383    @add     r1, r1, #1                  @ using (boolean+1)
9384    @add     r0, rGLUE, #offGlue_jmpBuf  @ r0<- &glue->jmpBuf
9385    @bl      _longjmp                    @ does not return
9386    @bl      common_abort
9387
9388
9389/*
9390 * Common code for method invocation with range.
9391 *
9392 * On entry:
9393 *  r0 is "Method* methodToCall", the method we're trying to call
9394 */
9395common_invokeMethodRange:
9396.LinvokeNewRange:
9397    @ prepare to copy args to "outs" area of current frame
9398    movs    r2, rINST, lsr #8           @ r2<- AA (arg count) -- test for zero
9399    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9400    beq     .LinvokeArgsDone            @ if no args, skip the rest
9401    FETCH(r1, 2)                        @ r1<- CCCC
9402
9403    @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
9404    @ (very few methods have > 10 args; could unroll for common cases)
9405    add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
9406    sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
9407    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
94081:  ldr     r1, [r3], #4                @ val = *fp++
9409    subs    r2, r2, #1                  @ count--
9410    str     r1, [r10], #4               @ *outs++ = val
9411    bne     1b                          @ ...while count != 0
9412    ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
9413    b       .LinvokeArgsDone
9414
9415/*
9416 * Common code for method invocation without range.
9417 *
9418 * On entry:
9419 *  r0 is "Method* methodToCall", the method we're trying to call
9420 */
9421common_invokeMethodNoRange:
9422.LinvokeNewNoRange:
9423    @ prepare to copy args to "outs" area of current frame
9424    movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
9425    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9426    FETCH(r1, 2)                        @ r1<- GFED (load here to hide latency)
9427    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
9428    ldrh    r3, [r0, #offMethod_outsSize]  @ r3<- methodToCall->outsSize
9429    beq     .LinvokeArgsDone
9430
9431    @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
9432.LinvokeNonRange:
9433    rsb     r2, r2, #5                  @ r2<- 5-r2
9434    add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
9435    bl      common_abort                @ (skipped due to ARM prefetch)
94365:  and     ip, rINST, #0x0f00          @ isolate A
9437    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vA (shift right 8, left 2)
9438    mov     r0, r0                      @ nop
9439    str     r2, [r10, #-4]!             @ *--outs = vA
94404:  and     ip, r1, #0xf000             @ isolate G
9441    ldr     r2, [rFP, ip, lsr #10]      @ r2<- vG (shift right 12, left 2)
9442    mov     r0, r0                      @ nop
9443    str     r2, [r10, #-4]!             @ *--outs = vG
94443:  and     ip, r1, #0x0f00             @ isolate F
9445    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vF
9446    mov     r0, r0                      @ nop
9447    str     r2, [r10, #-4]!             @ *--outs = vF
94482:  and     ip, r1, #0x00f0             @ isolate E
9449    ldr     r2, [rFP, ip, lsr #2]       @ r2<- vE
9450    mov     r0, r0                      @ nop
9451    str     r2, [r10, #-4]!             @ *--outs = vE
94521:  and     ip, r1, #0x000f             @ isolate D
9453    ldr     r2, [rFP, ip, lsl #2]       @ r2<- vD
9454    mov     r0, r0                      @ nop
9455    str     r2, [r10, #-4]!             @ *--outs = vD
94560:  @ fall through to .LinvokeArgsDone
9457
9458.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
9459    ldr     r2, [r0, #offMethod_insns]  @ r2<- method->insns
9460    ldr     rINST, [r0, #offMethod_clazz]  @ rINST<- method->clazz
9461    @ find space for the new stack frame, check for overflow
9462    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
9463    sub     r1, r1, r9, lsl #2          @ r1<- newFp (old savearea - regsSize)
9464    SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
9465@    bl      common_dumpRegs
9466    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
9467    sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
9468    cmp     r3, r9                      @ bottom < interpStackEnd?
9469    ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
9470    blt     .LstackOverflow             @ yes, this frame will overflow stack
9471
9472    @ set up newSaveArea
9473#ifdef EASY_GDB
9474    SAVEAREA_FROM_FP(ip, rFP)           @ ip<- stack save area
9475    str     ip, [r10, #offStackSaveArea_prevSave]
9476#endif
9477    str     rFP, [r10, #offStackSaveArea_prevFrame]
9478    str     rPC, [r10, #offStackSaveArea_savedPc]
9479#if defined(WITH_JIT)
9480    mov     r9, #0
9481    str     r9, [r10, #offStackSaveArea_returnAddr]
9482#endif
9483    str     r0, [r10, #offStackSaveArea_method]
9484    tst     r3, #ACC_NATIVE
9485    bne     .LinvokeNative
9486
9487    /*
9488    stmfd   sp!, {r0-r3}
9489    bl      common_printNewline
9490    mov     r0, rFP
9491    mov     r1, #0
9492    bl      dvmDumpFp
9493    ldmfd   sp!, {r0-r3}
9494    stmfd   sp!, {r0-r3}
9495    mov     r0, r1
9496    mov     r1, r10
9497    bl      dvmDumpFp
9498    bl      common_printNewline
9499    ldmfd   sp!, {r0-r3}
9500    */
9501
9502    ldrh    r9, [r2]                        @ r9 <- load INST from new PC
9503    ldr     r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
9504    mov     rPC, r2                         @ publish new rPC
9505    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
9506
9507    @ Update "glue" values for the new method
9508    @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
9509    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
9510    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
9511#if defined(WITH_JIT)
9512    GET_JIT_PROF_TABLE(r0)
9513    mov     rFP, r1                         @ fp = newFp
9514    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
9515    mov     rINST, r9                       @ publish new rINST
9516    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
9517    cmp     r0,#0
9518    bne     common_updateProfile
9519    GOTO_OPCODE(ip)                         @ jump to next instruction
9520#else
9521    mov     rFP, r1                         @ fp = newFp
9522    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
9523    mov     rINST, r9                       @ publish new rINST
9524    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
9525    GOTO_OPCODE(ip)                         @ jump to next instruction
9526#endif
9527
9528.LinvokeNative:
9529    @ Prep for the native call
9530    @ r0=methodToCall, r1=newFp, r10=newSaveArea
9531    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
9532    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
9533    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
9534    str     r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
9535    mov     r9, r3                      @ r9<- glue->self (preserve)
9536
9537    mov     r2, r0                      @ r2<- methodToCall
9538    mov     r0, r1                      @ r0<- newFp (points to args)
9539    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
9540
9541#ifdef ASSIST_DEBUGGER
9542    /* insert fake function header to help gdb find the stack frame */
9543    b       .Lskip
9544    .type   dalvik_mterp, %function
9545dalvik_mterp:
9546    .fnstart
9547    MTERP_ENTRY1
9548    MTERP_ENTRY2
9549.Lskip:
9550#endif
9551
9552    @mov     lr, pc                      @ set return addr
9553    @ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
9554    LDR_PC_LR "[r2, #offMethod_nativeFunc]"
9555
9556    @ native return; r9=self, r10=newSaveArea
9557    @ equivalent to dvmPopJniLocals
9558    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
9559    ldr     r1, [r9, #offThread_exception] @ check for exception
9560    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
9561    cmp     r1, #0                      @ null?
9562    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
9563    bne     common_exceptionThrown      @ no, handle exception
9564
9565    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
9566    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9567    GOTO_OPCODE(ip)                     @ jump to next instruction
9568
9569.LstackOverflow:    @ r0=methodToCall
9570    mov     r1, r0                      @ r1<- methodToCall
9571    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
9572    bl      dvmHandleStackOverflow
9573    b       common_exceptionThrown
9574#ifdef ASSIST_DEBUGGER
9575    .fnend
9576#endif
9577
9578
9579    /*
9580     * Common code for method invocation, calling through "glue code".
9581     *
9582     * TODO: now that we have range and non-range invoke handlers, this
9583     *       needs to be split into two.  Maybe just create entry points
9584     *       that set r9 and jump here?
9585     *
9586     * On entry:
9587     *  r0 is "Method* methodToCall", the method we're trying to call
9588     *  r9 is "bool methodCallRange", indicating if this is a /range variant
9589     */
9590     .if    0
9591.LinvokeOld:
9592    sub     sp, sp, #8                  @ space for args + pad
9593    FETCH(ip, 2)                        @ ip<- FEDC or CCCC
9594    mov     r2, r0                      @ A2<- methodToCall
9595    mov     r0, rGLUE                   @ A0<- glue
9596    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9597    mov     r1, r9                      @ A1<- methodCallRange
9598    mov     r3, rINST, lsr #8           @ A3<- AA
9599    str     ip, [sp, #0]                @ A4<- ip
9600    bl      dvmMterp_invokeMethod       @ call the C invokeMethod
9601    add     sp, sp, #8                  @ remove arg area
9602    b       common_resumeAfterGlueCall  @ continue to next instruction
9603    .endif
9604
9605
9606
9607/*
9608 * Common code for handling a return instruction.
9609 *
9610 * This does not return.
9611 */
9612common_returnFromMethod:
9613.LreturnNew:
9614    mov     r0, #kInterpEntryReturn
9615    mov     r9, #0
9616    bl      common_periodicChecks
9617
9618    SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
9619    ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
9620    ldr     r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
9621    ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
9622                                        @ r2<- method we're returning to
9623    ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
9624    cmp     r2, #0                      @ is this a break frame?
9625    ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
9626    mov     r1, #0                      @ "want switch" = false
9627    beq     common_gotoBail             @ break frame, bail out completely
9628
9629    PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
9630    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
9631    ldr     r1, [r10, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
9632    str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
9633#if defined(WITH_JIT)
9634    ldr     r3, [r0, #offStackSaveArea_returnAddr] @ r3 = saveArea->returnAddr
9635    GET_JIT_PROF_TABLE(r0)
9636    mov     rPC, r9                     @ publish new rPC
9637    str     r1, [rGLUE, #offGlue_methodClassDex]
9638    cmp     r3, #0                      @ caller is compiled code
9639    blxne   r3
9640    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9641    cmp     r0,#0
9642    bne     common_updateProfile
9643    GOTO_OPCODE(ip)                     @ jump to next instruction
9644#else
9645    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9646    mov     rPC, r9                     @ publish new rPC
9647    str     r1, [rGLUE, #offGlue_methodClassDex]
9648    GOTO_OPCODE(ip)                     @ jump to next instruction
9649#endif
9650
9651    /*
9652     * Return handling, calls through "glue code".
9653     */
9654     .if    0
9655.LreturnOld:
9656    SAVE_PC_FP_TO_GLUE()                @ export state
9657    mov     r0, rGLUE                   @ arg to function
9658    bl      dvmMterp_returnFromMethod
9659    b       common_resumeAfterGlueCall
9660    .endif
9661
9662
9663/*
9664 * Somebody has thrown an exception.  Handle it.
9665 *
9666 * If the exception processing code returns to us (instead of falling
9667 * out of the interpreter), continue with whatever the next instruction
9668 * now happens to be.
9669 *
9670 * This does not return.
9671 */
9672     .global dvmMterpCommonExceptionThrown
9673dvmMterpCommonExceptionThrown:
9674common_exceptionThrown:
9675.LexceptionNew:
9676    mov     r0, #kInterpEntryThrow
9677    mov     r9, #0
9678    bl      common_periodicChecks
9679
9680#if defined(WITH_JIT)
9681    mov     r2,#kJitTSelectAbort        @ abandon trace selection in progress
9682    str     r2,[rGLUE,#offGlue_jitState]
9683#endif
9684
9685    ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
9686    ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
9687    mov     r1, r10                     @ r1<- self
9688    mov     r0, r9                      @ r0<- exception
9689    bl      dvmAddTrackedAlloc          @ don't let the exception be GCed
9690    mov     r3, #0                      @ r3<- NULL
9691    str     r3, [r10, #offThread_exception] @ self->exception = NULL
9692
9693    /* set up args and a local for "&fp" */
9694    /* (str sp, [sp, #-4]!  would be perfect here, but is discouraged) */
9695    str     rFP, [sp, #-4]!             @ *--sp = fp
9696    mov     ip, sp                      @ ip<- &fp
9697    mov     r3, #0                      @ r3<- false
9698    str     ip, [sp, #-4]!              @ *--sp = &fp
9699    ldr     r1, [rGLUE, #offGlue_method] @ r1<- glue->method
9700    mov     r0, r10                     @ r0<- self
9701    ldr     r1, [r1, #offMethod_insns]  @ r1<- method->insns
9702    mov     r2, r9                      @ r2<- exception
9703    sub     r1, rPC, r1                 @ r1<- pc - method->insns
9704    mov     r1, r1, asr #1              @ r1<- offset in code units
9705
9706    /* call, r0 gets catchRelPc (a code-unit offset) */
9707    bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
9708
9709    /* fix earlier stack overflow if necessary; may trash rFP */
9710    ldrb    r1, [r10, #offThread_stackOverflowed]
9711    cmp     r1, #0                      @ did we overflow earlier?
9712    beq     1f                          @ no, skip ahead
9713    mov     rFP, r0                     @ save relPc result in rFP
9714    mov     r0, r10                     @ r0<- self
9715    bl      dvmCleanupStackOverflow     @ call(self)
9716    mov     r0, rFP                     @ restore result
97171:
9718
9719    /* update frame pointer and check result from dvmFindCatchBlock */
9720    ldr     rFP, [sp, #4]               @ retrieve the updated rFP
9721    cmp     r0, #0                      @ is catchRelPc < 0?
9722    add     sp, sp, #8                  @ restore stack
9723    bmi     .LnotCaughtLocally
9724
9725    /* adjust locals to match self->curFrame and updated PC */
9726    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
9727    ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
9728    str     r1, [rGLUE, #offGlue_method]    @ glue->method = new method
9729    ldr     r2, [r1, #offMethod_clazz]      @ r2<- method->clazz
9730    ldr     r3, [r1, #offMethod_insns]      @ r3<- method->insns
9731    ldr     r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
9732    add     rPC, r3, r0, asl #1             @ rPC<- method->insns + catchRelPc
9733    str     r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
9734
9735    /* release the tracked alloc on the exception */
9736    mov     r0, r9                      @ r0<- exception
9737    mov     r1, r10                     @ r1<- self
9738    bl      dvmReleaseTrackedAlloc      @ release the exception
9739
9740    /* restore the exception if the handler wants it */
9741    FETCH_INST()                        @ load rINST from rPC
9742    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9743    cmp     ip, #OP_MOVE_EXCEPTION      @ is it "move-exception"?
9744    streq   r9, [r10, #offThread_exception] @ yes, restore the exception
9745    GOTO_OPCODE(ip)                     @ jump to next instruction
9746
9747.LnotCaughtLocally: @ r9=exception, r10=self
9748    /* fix stack overflow if necessary */
9749    ldrb    r1, [r10, #offThread_stackOverflowed]
9750    cmp     r1, #0                      @ did we overflow earlier?
9751    movne   r0, r10                     @ if yes: r0<- self
9752    blne    dvmCleanupStackOverflow     @ if yes: call(self)
9753
9754    @ may want to show "not caught locally" debug messages here
9755#if DVM_SHOW_EXCEPTION >= 2
9756    /* call __android_log_print(prio, tag, format, ...) */
9757    /* "Exception %s from %s:%d not caught locally" */
9758    @ dvmLineNumFromPC(method, pc - method->insns)
9759    ldr     r0, [rGLUE, #offGlue_method]
9760    ldr     r1, [r0, #offMethod_insns]
9761    sub     r1, rPC, r1
9762    asr     r1, r1, #1
9763    bl      dvmLineNumFromPC
9764    str     r0, [sp, #-4]!
9765    @ dvmGetMethodSourceFile(method)
9766    ldr     r0, [rGLUE, #offGlue_method]
9767    bl      dvmGetMethodSourceFile
9768    str     r0, [sp, #-4]!
9769    @ exception->clazz->descriptor
9770    ldr     r3, [r9, #offObject_clazz]
9771    ldr     r3, [r3, #offClassObject_descriptor]
9772    @
9773    ldr     r2, strExceptionNotCaughtLocally
9774    ldr     r1, strLogTag
9775    mov     r0, #3                      @ LOG_DEBUG
9776    bl      __android_log_print
9777#endif
9778    str     r9, [r10, #offThread_exception] @ restore exception
9779    mov     r0, r9                      @ r0<- exception
9780    mov     r1, r10                     @ r1<- self
9781    bl      dvmReleaseTrackedAlloc      @ release the exception
9782    mov     r1, #0                      @ "want switch" = false
9783    b       common_gotoBail             @ bail out
9784
9785
9786    /*
9787     * Exception handling, calls through "glue code".
9788     */
9789    .if     0
9790.LexceptionOld:
9791    SAVE_PC_FP_TO_GLUE()                @ export state
9792    mov     r0, rGLUE                   @ arg to function
9793    bl      dvmMterp_exceptionThrown
9794    b       common_resumeAfterGlueCall
9795    .endif
9796
9797
9798/*
9799 * After returning from a "glued" function, pull out the updated
9800 * values and start executing at the next instruction.
9801 */
9802common_resumeAfterGlueCall:
9803    LOAD_PC_FP_FROM_GLUE()              @ pull rPC and rFP out of glue
9804    FETCH_INST()                        @ load rINST from rPC
9805    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9806    GOTO_OPCODE(ip)                     @ jump to next instruction
9807
9808/*
9809 * Invalid array index.
9810 */
9811common_errArrayIndex:
9812    EXPORT_PC()
9813    ldr     r0, strArrayIndexException
9814    mov     r1, #0
9815    bl      dvmThrowException
9816    b       common_exceptionThrown
9817
9818/*
9819 * Invalid array value.
9820 */
9821common_errArrayStore:
9822    EXPORT_PC()
9823    ldr     r0, strArrayStoreException
9824    mov     r1, #0
9825    bl      dvmThrowException
9826    b       common_exceptionThrown
9827
9828/*
9829 * Integer divide or mod by zero.
9830 */
9831common_errDivideByZero:
9832    EXPORT_PC()
9833    ldr     r0, strArithmeticException
9834    ldr     r1, strDivideByZero
9835    bl      dvmThrowException
9836    b       common_exceptionThrown
9837
9838/*
9839 * Attempt to allocate an array with a negative size.
9840 */
9841common_errNegativeArraySize:
9842    EXPORT_PC()
9843    ldr     r0, strNegativeArraySizeException
9844    mov     r1, #0
9845    bl      dvmThrowException
9846    b       common_exceptionThrown
9847
9848/*
9849 * Invocation of a non-existent method.
9850 */
9851common_errNoSuchMethod:
9852    EXPORT_PC()
9853    ldr     r0, strNoSuchMethodError
9854    mov     r1, #0
9855    bl      dvmThrowException
9856    b       common_exceptionThrown
9857
9858/*
9859 * We encountered a null object when we weren't expecting one.  We
9860 * export the PC, throw a NullPointerException, and goto the exception
9861 * processing code.
9862 */
9863common_errNullObject:
9864    EXPORT_PC()
9865    ldr     r0, strNullPointerException
9866    mov     r1, #0
9867    bl      dvmThrowException
9868    b       common_exceptionThrown
9869
9870/*
9871 * For debugging, cause an immediate fault.  The source address will
9872 * be in lr (use a bl instruction to jump here).
9873 */
9874common_abort:
9875    ldr     pc, .LdeadFood
9876.LdeadFood:
9877    .word   0xdeadf00d
9878
9879/*
9880 * Spit out a "we were here", preserving all registers.  (The attempt
9881 * to save ip won't work, but we need to save an even number of
9882 * registers for EABI 64-bit stack alignment.)
9883 */
9884    .macro  SQUEAK num
9885common_squeak\num:
9886    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9887    ldr     r0, strSqueak
9888    mov     r1, #\num
9889    bl      printf
9890    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9891    bx      lr
9892    .endm
9893
9894    SQUEAK  0
9895    SQUEAK  1
9896    SQUEAK  2
9897    SQUEAK  3
9898    SQUEAK  4
9899    SQUEAK  5
9900
9901/*
9902 * Spit out the number in r0, preserving registers.
9903 */
9904common_printNum:
9905    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9906    mov     r1, r0
9907    ldr     r0, strSqueak
9908    bl      printf
9909    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9910    bx      lr
9911
9912/*
9913 * Print a newline, preserving registers.
9914 */
9915common_printNewline:
9916    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9917    ldr     r0, strNewline
9918    bl      printf
9919    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9920    bx      lr
9921
9922    /*
9923     * Print the 32-bit quantity in r0 as a hex value, preserving registers.
9924     */
9925common_printHex:
9926    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9927    mov     r1, r0
9928    ldr     r0, strPrintHex
9929    bl      printf
9930    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9931    bx      lr
9932
9933/*
9934 * Print the 64-bit quantity in r0-r1, preserving registers.
9935 */
9936common_printLong:
9937    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9938    mov     r3, r1
9939    mov     r2, r0
9940    ldr     r0, strPrintLong
9941    bl      printf
9942    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9943    bx      lr
9944
9945/*
9946 * Print full method info.  Pass the Method* in r0.  Preserves regs.
9947 */
9948common_printMethod:
9949    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9950    bl      dvmMterpPrintMethod
9951    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9952    bx      lr
9953
9954/*
9955 * Call a C helper function that dumps regs and possibly some
9956 * additional info.  Requires the C function to be compiled in.
9957 */
9958    .if     0
9959common_dumpRegs:
9960    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9961    bl      dvmMterpDumpArmRegs
9962    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9963    bx      lr
9964    .endif
9965
9966#if 0
9967/*
9968 * Experiment on VFP mode.
9969 *
9970 * uint32_t setFPSCR(uint32_t val, uint32_t mask)
9971 *
9972 * Updates the bits specified by "mask", setting them to the values in "val".
9973 */
9974setFPSCR:
9975    and     r0, r0, r1                  @ make sure no stray bits are set
9976    fmrx    r2, fpscr                   @ get VFP reg
9977    mvn     r1, r1                      @ bit-invert mask
9978    and     r2, r2, r1                  @ clear masked bits
9979    orr     r2, r2, r0                  @ set specified bits
9980    fmxr    fpscr, r2                   @ set VFP reg
9981    mov     r0, r2                      @ return new value
9982    bx      lr
9983
9984    .align  2
9985    .global dvmConfigureFP
9986    .type   dvmConfigureFP, %function
9987dvmConfigureFP:
9988    stmfd   sp!, {ip, lr}
9989    /* 0x03000000 sets DN/FZ */
9990    /* 0x00009f00 clears the six exception enable flags */
9991    bl      common_squeak0
9992    mov     r0, #0x03000000             @ r0<- 0x03000000
9993    add     r1, r0, #0x9f00             @ r1<- 0x03009f00
9994    bl      setFPSCR
9995    ldmfd   sp!, {ip, pc}
9996#endif
9997
9998
9999/*
10000 * String references, must be close to the code that uses them.
10001 */
10002    .align  2
10003strArithmeticException:
10004    .word   .LstrArithmeticException
10005strArrayIndexException:
10006    .word   .LstrArrayIndexException
10007strArrayStoreException:
10008    .word   .LstrArrayStoreException
10009strDivideByZero:
10010    .word   .LstrDivideByZero
10011strNegativeArraySizeException:
10012    .word   .LstrNegativeArraySizeException
10013strNoSuchMethodError:
10014    .word   .LstrNoSuchMethodError
10015strNullPointerException:
10016    .word   .LstrNullPointerException
10017
10018strLogTag:
10019    .word   .LstrLogTag
10020strExceptionNotCaughtLocally:
10021    .word   .LstrExceptionNotCaughtLocally
10022
10023strNewline:
10024    .word   .LstrNewline
10025strSqueak:
10026    .word   .LstrSqueak
10027strPrintHex:
10028    .word   .LstrPrintHex
10029strPrintLong:
10030    .word   .LstrPrintLong
10031
10032/*
10033 * Zero-terminated ASCII string data.
10034 *
10035 * On ARM we have two choices: do like gcc does, and LDR from a .word
10036 * with the address, or use an ADR pseudo-op to get the address
10037 * directly.  ADR saves 4 bytes and an indirection, but it's using a
10038 * PC-relative addressing mode and hence has a limited range, which
10039 * makes it not work well with mergeable string sections.
10040 */
10041    .section .rodata.str1.4,"aMS",%progbits,1
10042
10043.LstrBadEntryPoint:
10044    .asciz  "Bad entry point %d\n"
10045.LstrArithmeticException:
10046    .asciz  "Ljava/lang/ArithmeticException;"
10047.LstrArrayIndexException:
10048    .asciz  "Ljava/lang/ArrayIndexOutOfBoundsException;"
10049.LstrArrayStoreException:
10050    .asciz  "Ljava/lang/ArrayStoreException;"
10051.LstrClassCastException:
10052    .asciz  "Ljava/lang/ClassCastException;"
10053.LstrDivideByZero:
10054    .asciz  "divide by zero"
10055.LstrFilledNewArrayNotImpl:
10056    .asciz  "filled-new-array only implemented for objects and 'int'"
10057.LstrInternalError:
10058    .asciz  "Ljava/lang/InternalError;"
10059.LstrInstantiationError:
10060    .asciz  "Ljava/lang/InstantiationError;"
10061.LstrNegativeArraySizeException:
10062    .asciz  "Ljava/lang/NegativeArraySizeException;"
10063.LstrNoSuchMethodError:
10064    .asciz  "Ljava/lang/NoSuchMethodError;"
10065.LstrNullPointerException:
10066    .asciz  "Ljava/lang/NullPointerException;"
10067
10068.LstrLogTag:
10069    .asciz  "mterp"
10070.LstrExceptionNotCaughtLocally:
10071    .asciz  "Exception %s from %s:%d not caught locally\n"
10072
10073.LstrNewline:
10074    .asciz  "\n"
10075.LstrSqueak:
10076    .asciz  "<%d>"
10077.LstrPrintHex:
10078    .asciz  "<0x%x>"
10079.LstrPrintLong:
10080    .asciz  "<%lld>"
10081
10082
10083