InterpAsm-armv5te-vfp.S revision cfdeca37fcaa27c37bad5077223e4d1e87f1182e
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/*
25 * ARMv5 definitions and declarations.
26 */
27
28/*
29ARM EABI general notes:
30
31r0-r3 hold first 4 args to a method; they are not preserved across method calls
32r4-r8 are available for general use
33r9 is given special treatment in some situations, but not for us
34r10 (sl) seems to be generally available
35r11 (fp) is used by gcc (unless -fomit-frame-pointer is set)
36r12 (ip) is scratch -- not preserved across method calls
37r13 (sp) should be managed carefully in case a signal arrives
38r14 (lr) must be preserved
39r15 (pc) can be tinkered with directly
40
41r0 holds returns of <= 4 bytes
42r0-r1 hold returns of 8 bytes, low word in r0
43
44Callee must save/restore r4+ (except r12) if it modifies them.  If VFP
45is present, registers s16-s31 (a/k/a d8-d15, a/k/a q4-q7) must be preserved,
46s0-s15 (d0-d7, q0-a3) do not need to be.
47
48Stack is "full descending".  Only the arguments that don't fit in the first 4
49registers are placed on the stack.  "sp" points at the first stacked argument
50(i.e. the 5th arg).
51
52VFP: single-precision results in s0, double-precision results in d0.
53
54In the EABI, "sp" must be 64-bit aligned on entry to a function, and any
5564-bit quantities (long long, double) must be 64-bit aligned.
56*/
57
58/*
59Mterp and ARM notes:
60
61The following registers have fixed assignments:
62
63  reg nick      purpose
64  r4  rPC       interpreted program counter, used for fetching instructions
65  r5  rFP       interpreted frame pointer, used for accessing locals and args
66  r6  rGLUE     MterpGlue pointer
67  r7  rINST     first 16-bit code unit of current instruction
68  r8  rIBASE    interpreted instruction base pointer, used for computed goto
69
70Macros are provided for common operations.  Each macro MUST emit only
71one instruction to make instruction-counting easier.  They MUST NOT alter
72unspecified registers or condition codes.
73*/
74
75/* single-purpose registers, given names for clarity */
76#define rPC     r4
77#define rFP     r5
78#define rGLUE   r6
79#define rINST   r7
80#define rIBASE  r8
81
82/* save/restore the PC and/or FP from the glue struct */
83#define LOAD_PC_FROM_GLUE()     ldr     rPC, [rGLUE, #offGlue_pc]
84#define SAVE_PC_TO_GLUE()       str     rPC, [rGLUE, #offGlue_pc]
85#define LOAD_FP_FROM_GLUE()     ldr     rFP, [rGLUE, #offGlue_fp]
86#define SAVE_FP_TO_GLUE()       str     rFP, [rGLUE, #offGlue_fp]
87#define LOAD_PC_FP_FROM_GLUE()  ldmia   rGLUE, {rPC, rFP}
88#define SAVE_PC_FP_TO_GLUE()    stmia   rGLUE, {rPC, rFP}
89
90/*
91 * "export" the PC to the stack frame, f/b/o future exception objects.  Must
92 * be done *before* something calls dvmThrowException.
93 *
94 * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e.
95 * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc)
96 *
97 * It's okay to do this more than once.
98 */
99#define EXPORT_PC() \
100    str     rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)]
101
102/*
103 * Given a frame pointer, find the stack save area.
104 *
105 * In C this is "((StackSaveArea*)(_fp) -1)".
106 */
107#define SAVEAREA_FROM_FP(_reg, _fpreg) \
108    sub     _reg, _fpreg, #sizeofStackSaveArea
109
110/*
111 * Fetch the next instruction from rPC into rINST.  Does not advance rPC.
112 */
113#define FETCH_INST()            ldrh    rINST, [rPC]
114
115/*
116 * Fetch the next instruction from the specified offset.  Advances rPC
117 * to point to the next instruction.  "_count" is in 16-bit code units.
118 *
119 * Because of the limited size of immediate constants on ARM, this is only
120 * suitable for small forward movements (i.e. don't try to implement "goto"
121 * with this).
122 *
123 * This must come AFTER anything that can throw an exception, or the
124 * exception catch may miss.  (This also implies that it must come after
125 * EXPORT_PC().)
126 */
127#define FETCH_ADVANCE_INST(_count) ldrh    rINST, [rPC, #(_count*2)]!
128
129/*
130 * The operation performed here is similar to FETCH_ADVANCE_INST, except the
131 * src and dest registers are parameterized (not hard-wired to rPC and rINST).
132 */
133#define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \
134        ldrh    _dreg, [_sreg, #(_count*2)]!
135
136/*
137 * Fetch the next instruction from an offset specified by _reg.  Updates
138 * rPC to point to the next instruction.  "_reg" must specify the distance
139 * in bytes, *not* 16-bit code units, and may be a signed value.
140 *
141 * We want to write "ldrh rINST, [rPC, _reg, lsl #2]!", but some of the
142 * bits that hold the shift distance are used for the half/byte/sign flags.
143 * In some cases we can pre-double _reg for free, so we require a byte offset
144 * here.
145 */
146#define FETCH_ADVANCE_INST_RB(_reg) ldrh    rINST, [rPC, _reg]!
147
148/*
149 * Fetch a half-word code unit from an offset past the current PC.  The
150 * "_count" value is in 16-bit code units.  Does not advance rPC.
151 *
152 * The "_S" variant works the same but treats the value as signed.
153 */
154#define FETCH(_reg, _count)     ldrh    _reg, [rPC, #(_count*2)]
155#define FETCH_S(_reg, _count)   ldrsh   _reg, [rPC, #(_count*2)]
156
157/*
158 * Fetch one byte from an offset past the current PC.  Pass in the same
159 * "_count" as you would for FETCH, and an additional 0/1 indicating which
160 * byte of the halfword you want (lo/hi).
161 */
162#define FETCH_B(_reg, _count, _byte) ldrb     _reg, [rPC, #(_count*2+_byte)]
163
164/*
165 * Put the instruction's opcode field into the specified register.
166 */
167#define GET_INST_OPCODE(_reg)   and     _reg, rINST, #255
168
169/*
170 * Put the prefetched instruction's opcode field into the specified register.
171 */
172#define GET_PREFETCHED_OPCODE(_oreg, _ireg)   and     _oreg, _ireg, #255
173
174/*
175 * Begin executing the opcode in _reg.  Because this only jumps within the
176 * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork.
177 */
178#define GOTO_OPCODE(_reg)       add     pc, rIBASE, _reg, lsl #6
179#define GOTO_OPCODE_IFEQ(_reg)  addeq   pc, rIBASE, _reg, lsl #6
180#define GOTO_OPCODE_IFNE(_reg)  addne   pc, rIBASE, _reg, lsl #6
181
182/*
183 * Get/set the 32-bit value from a Dalvik register.
184 */
185#define GET_VREG(_reg, _vreg)   ldr     _reg, [rFP, _vreg, lsl #2]
186#define SET_VREG(_reg, _vreg)   str     _reg, [rFP, _vreg, lsl #2]
187
188#if defined(WITH_JIT)
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#if defined(WITH_JIT)
206#include "../common/jit-config.h"
207#endif
208
209/* File: armv5te/platform.S */
210/*
211 * ===========================================================================
212 *  CPU-version-specific defines
213 * ===========================================================================
214 */
215
216/*
217 * Macro for data memory barrier; not meaningful pre-ARMv6K.
218 */
219.macro  SMP_DMB
220.endm
221
222/*
223 * Macro for data memory barrier; not meaningful pre-ARMv6K.
224 */
225.macro  SMP_DMB_ST
226.endm
227
228/* File: armv5te/entry.S */
229/*
230 * Copyright (C) 2008 The Android Open Source Project
231 *
232 * Licensed under the Apache License, Version 2.0 (the "License");
233 * you may not use this file except in compliance with the License.
234 * You may obtain a copy of the License at
235 *
236 *      http://www.apache.org/licenses/LICENSE-2.0
237 *
238 * Unless required by applicable law or agreed to in writing, software
239 * distributed under the License is distributed on an "AS IS" BASIS,
240 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
241 * See the License for the specific language governing permissions and
242 * limitations under the License.
243 */
244/*
245 * Interpreter entry point.
246 */
247
248/*
249 * We don't have formal stack frames, so gdb scans upward in the code
250 * to find the start of the function (a label with the %function type),
251 * and then looks at the next few instructions to figure out what
252 * got pushed onto the stack.  From this it figures out how to restore
253 * the registers, including PC, for the previous stack frame.  If gdb
254 * sees a non-function label, it stops scanning, so either we need to
255 * have nothing but assembler-local labels between the entry point and
256 * the break, or we need to fake it out.
257 *
258 * When this is defined, we add some stuff to make gdb less confused.
259 */
260#define ASSIST_DEBUGGER 1
261
262    .text
263    .align  2
264    .global dvmMterpStdRun
265    .type   dvmMterpStdRun, %function
266
267/*
268 * On entry:
269 *  r0  MterpGlue* glue
270 *
271 * This function returns a boolean "changeInterp" value.  The return comes
272 * via a call to dvmMterpStdBail().
273 */
274dvmMterpStdRun:
275#define MTERP_ENTRY1 \
276    .save {r4-r10,fp,lr}; \
277    stmfd   sp!, {r4-r10,fp,lr}         @ save 9 regs
278#define MTERP_ENTRY2 \
279    .pad    #4; \
280    sub     sp, sp, #4                  @ align 64
281
282    .fnstart
283    MTERP_ENTRY1
284    MTERP_ENTRY2
285
286    /* save stack pointer, add magic word for debuggerd */
287    str     sp, [r0, #offGlue_bailPtr]  @ save SP for eventual return
288
289    /* set up "named" registers, figure out entry point */
290    mov     rGLUE, r0                   @ set rGLUE
291    ldr     r1, [r0, #offGlue_entryPoint]   @ enum is 4 bytes in aapcs-EABI
292    LOAD_PC_FP_FROM_GLUE()              @ load rPC and rFP from "glue"
293    adr     rIBASE, dvmAsmInstructionStart  @ set rIBASE
294    cmp     r1, #kInterpEntryInstr      @ usual case?
295    bne     .Lnot_instr                 @ no, handle it
296
297#if defined(WITH_JIT)
298.LentryInstr:
299    ldr     r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
300    /* Entry is always a possible trace start */
301    GET_JIT_PROF_TABLE(r0)
302    FETCH_INST()
303    mov     r1, #0                      @ prepare the value for the new state
304    str     r1, [r10, #offThread_inJitCodeCache] @ back to the interp land
305    cmp     r0,#0                       @ is profiling disabled?
306#if !defined(WITH_SELF_VERIFICATION)
307    bne     common_updateProfile        @ profiling is enabled
308#else
309    ldr     r2, [r10, #offThread_shadowSpace]   @ to find out the jit exit state
310    beq     1f                          @ profiling is disabled
311    ldr     r3, [r2, #offShadowSpace_jitExitState]  @ jit exit state
312    cmp     r3, #kSVSTraceSelect        @ hot trace following?
313    moveq   r2,#kJitTSelectRequestHot   @ ask for trace selection
314    beq     common_selectTrace          @ go build the trace
315    cmp     r3, #kSVSNoProfile          @ don't profile the next instruction?
316    beq     1f                          @ intrepret the next instruction
317    b       common_updateProfile        @ collect profiles
318#endif
3191:
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     r10,[rGLUE, #offGlue_jitResumeNPC]
340    ldr     r2,[rGLUE, #offGlue_jitResumeDPC]
341    cmp     r1, #kInterpEntryResume     @ resuming after Jit single-step?
342    bne     .Lbad_arg
343    cmp     rPC,r2
344    bne     .LentryInstr                @ must have branched, don't resume
345#if defined(WITH_SELF_VERIFICATION)
346    @ glue->entryPoint will be set in dvmSelfVerificationSaveState
347    b       jitSVShadowRunStart         @ re-enter the translation after the
348                                        @ single-stepped instruction
349    @noreturn
350#endif
351    mov     r1, #kInterpEntryInstr
352    str     r1, [rGLUE, #offGlue_entryPoint]
353    bx      r10                         @ re-enter the translation
354#endif
355
356.Lbad_arg:
357    ldr     r0, strBadEntryPoint
358    @ r1 holds value of entryPoint
359    bl      printf
360    bl      dvmAbort
361    .fnend
362
363
364    .global dvmMterpStdBail
365    .type   dvmMterpStdBail, %function
366
367/*
368 * Restore the stack pointer and PC from the save point established on entry.
369 * This is essentially the same as a longjmp, but should be cheaper.  The
370 * last instruction causes us to return to whoever called dvmMterpStdRun.
371 *
372 * We pushed some registers on the stack in dvmMterpStdRun, then saved
373 * SP and LR.  Here we restore SP, restore the registers, and then restore
374 * LR to PC.
375 *
376 * On entry:
377 *  r0  MterpGlue* glue
378 *  r1  bool changeInterp
379 */
380dvmMterpStdBail:
381    ldr     sp, [r0, #offGlue_bailPtr]      @ sp<- saved SP
382    mov     r0, r1                          @ return the changeInterp value
383    add     sp, sp, #4                      @ un-align 64
384    ldmfd   sp!, {r4-r10,fp,pc}             @ restore 9 regs and return
385
386
387/*
388 * String references.
389 */
390strBadEntryPoint:
391    .word   .LstrBadEntryPoint
392
393
394    .global dvmAsmInstructionStart
395    .type   dvmAsmInstructionStart, %function
396dvmAsmInstructionStart = .L_OP_NOP
397    .text
398
399/* ------------------------------ */
400    .balign 64
401.L_OP_NOP: /* 0x00 */
402/* File: armv5te/OP_NOP.S */
403    FETCH_ADVANCE_INST(1)               @ advance to next instr, load rINST
404    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
405    GOTO_OPCODE(ip)                     @ execute it
406
407#ifdef ASSIST_DEBUGGER
408    /* insert fake function header to help gdb find the stack frame */
409    .type   dalvik_inst, %function
410dalvik_inst:
411    .fnstart
412    MTERP_ENTRY1
413    MTERP_ENTRY2
414    .fnend
415#endif
416
417/* ------------------------------ */
418    .balign 64
419.L_OP_MOVE: /* 0x01 */
420/* File: armv5te/OP_MOVE.S */
421    /* for move, move-object, long-to-int */
422    /* op vA, vB */
423    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
424    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
425    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
426    GET_VREG(r2, r1)                    @ r2<- fp[B]
427    and     r0, r0, #15
428    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
429    SET_VREG(r2, r0)                    @ fp[A]<- r2
430    GOTO_OPCODE(ip)                     @ execute next instruction
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    .balign 64
448.L_OP_MOVE_16: /* 0x03 */
449/* File: armv5te/OP_MOVE_16.S */
450    /* for: move/16, move-object/16 */
451    /* op vAAAA, vBBBB */
452    FETCH(r1, 2)                        @ r1<- BBBB
453    FETCH(r0, 1)                        @ r0<- AAAA
454    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
455    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
456    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
457    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
458    GOTO_OPCODE(ip)                     @ jump to next instruction
459
460/* ------------------------------ */
461    .balign 64
462.L_OP_MOVE_WIDE: /* 0x04 */
463/* File: armv5te/OP_MOVE_WIDE.S */
464    /* move-wide vA, vB */
465    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
466    mov     r2, rINST, lsr #8           @ r2<- A(+)
467    mov     r3, rINST, lsr #12          @ r3<- B
468    and     r2, r2, #15
469    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
470    add     r2, rFP, r2, lsl #2         @ r2<- &fp[A]
471    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[B]
472    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
473    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
474    stmia   r2, {r0-r1}                 @ fp[A]<- r0/r1
475    GOTO_OPCODE(ip)                     @ jump to next instruction
476
477/* ------------------------------ */
478    .balign 64
479.L_OP_MOVE_WIDE_FROM16: /* 0x05 */
480/* File: armv5te/OP_MOVE_WIDE_FROM16.S */
481    /* move-wide/from16 vAA, vBBBB */
482    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
483    FETCH(r3, 1)                        @ r3<- BBBB
484    mov     r2, rINST, lsr #8           @ r2<- AA
485    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
486    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
487    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
488    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
489    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
490    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
491    GOTO_OPCODE(ip)                     @ jump to next instruction
492
493/* ------------------------------ */
494    .balign 64
495.L_OP_MOVE_WIDE_16: /* 0x06 */
496/* File: armv5te/OP_MOVE_WIDE_16.S */
497    /* move-wide/16 vAAAA, vBBBB */
498    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
499    FETCH(r3, 2)                        @ r3<- BBBB
500    FETCH(r2, 1)                        @ r2<- AAAA
501    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
502    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AAAA]
503    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
504    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
505    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
506    stmia   r2, {r0-r1}                 @ fp[AAAA]<- r0/r1
507    GOTO_OPCODE(ip)                     @ jump to next instruction
508
509/* ------------------------------ */
510    .balign 64
511.L_OP_MOVE_OBJECT: /* 0x07 */
512/* File: armv5te/OP_MOVE_OBJECT.S */
513/* File: armv5te/OP_MOVE.S */
514    /* for move, move-object, long-to-int */
515    /* op vA, vB */
516    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
517    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
518    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
519    GET_VREG(r2, r1)                    @ r2<- fp[B]
520    and     r0, r0, #15
521    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
522    SET_VREG(r2, r0)                    @ fp[A]<- r2
523    GOTO_OPCODE(ip)                     @ execute next instruction
524
525
526/* ------------------------------ */
527    .balign 64
528.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
529/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */
530/* File: armv5te/OP_MOVE_FROM16.S */
531    /* for: move/from16, move-object/from16 */
532    /* op vAA, vBBBB */
533    FETCH(r1, 1)                        @ r1<- BBBB
534    mov     r0, rINST, lsr #8           @ r0<- AA
535    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
536    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
537    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
538    SET_VREG(r2, r0)                    @ fp[AA]<- r2
539    GOTO_OPCODE(ip)                     @ jump to next instruction
540
541
542/* ------------------------------ */
543    .balign 64
544.L_OP_MOVE_OBJECT_16: /* 0x09 */
545/* File: armv5te/OP_MOVE_OBJECT_16.S */
546/* File: armv5te/OP_MOVE_16.S */
547    /* for: move/16, move-object/16 */
548    /* op vAAAA, vBBBB */
549    FETCH(r1, 2)                        @ r1<- BBBB
550    FETCH(r0, 1)                        @ r0<- AAAA
551    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
552    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
553    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
554    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
555    GOTO_OPCODE(ip)                     @ jump to next instruction
556
557
558/* ------------------------------ */
559    .balign 64
560.L_OP_MOVE_RESULT: /* 0x0a */
561/* File: armv5te/OP_MOVE_RESULT.S */
562    /* for: move-result, move-result-object */
563    /* op vAA */
564    mov     r2, rINST, lsr #8           @ r2<- AA
565    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
566    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
567    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
568    SET_VREG(r0, r2)                    @ fp[AA]<- r0
569    GOTO_OPCODE(ip)                     @ jump to next instruction
570
571/* ------------------------------ */
572    .balign 64
573.L_OP_MOVE_RESULT_WIDE: /* 0x0b */
574/* File: armv5te/OP_MOVE_RESULT_WIDE.S */
575    /* move-result-wide vAA */
576    mov     r2, rINST, lsr #8           @ r2<- AA
577    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
578    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
579    ldmia   r3, {r0-r1}                 @ r0/r1<- retval.j
580    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
581    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
582    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
583    GOTO_OPCODE(ip)                     @ jump to next instruction
584
585/* ------------------------------ */
586    .balign 64
587.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
588/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */
589/* File: armv5te/OP_MOVE_RESULT.S */
590    /* for: move-result, move-result-object */
591    /* op vAA */
592    mov     r2, rINST, lsr #8           @ r2<- AA
593    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
594    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
595    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
596    SET_VREG(r0, r2)                    @ fp[AA]<- r0
597    GOTO_OPCODE(ip)                     @ jump to next instruction
598
599
600/* ------------------------------ */
601    .balign 64
602.L_OP_MOVE_EXCEPTION: /* 0x0d */
603/* File: armv5te/OP_MOVE_EXCEPTION.S */
604    /* move-exception vAA */
605    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
606    mov     r2, rINST, lsr #8           @ r2<- AA
607    ldr     r3, [r0, #offThread_exception]  @ r3<- dvmGetException bypass
608    mov     r1, #0                      @ r1<- 0
609    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
610    SET_VREG(r3, r2)                    @ fp[AA]<- exception obj
611    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
612    str     r1, [r0, #offThread_exception]  @ dvmClearException bypass
613    GOTO_OPCODE(ip)                     @ jump to next instruction
614
615/* ------------------------------ */
616    .balign 64
617.L_OP_RETURN_VOID: /* 0x0e */
618/* File: armv5te/OP_RETURN_VOID.S */
619    b       common_returnFromMethod
620
621/* ------------------------------ */
622    .balign 64
623.L_OP_RETURN: /* 0x0f */
624/* File: armv5te/OP_RETURN.S */
625    /*
626     * Return a 32-bit value.  Copies the return value into the "glue"
627     * structure, then jumps to the return handler.
628     *
629     * for: return, return-object
630     */
631    /* op vAA */
632    mov     r2, rINST, lsr #8           @ r2<- AA
633    GET_VREG(r0, r2)                    @ r0<- vAA
634    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
635    b       common_returnFromMethod
636
637/* ------------------------------ */
638    .balign 64
639.L_OP_RETURN_WIDE: /* 0x10 */
640/* File: armv5te/OP_RETURN_WIDE.S */
641    /*
642     * Return a 64-bit value.  Copies the return value into the "glue"
643     * structure, then jumps to the return handler.
644     */
645    /* return-wide vAA */
646    mov     r2, rINST, lsr #8           @ r2<- AA
647    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
648    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
649    ldmia   r2, {r0-r1}                 @ r0/r1 <- vAA/vAA+1
650    stmia   r3, {r0-r1}                 @ retval<- r0/r1
651    b       common_returnFromMethod
652
653/* ------------------------------ */
654    .balign 64
655.L_OP_RETURN_OBJECT: /* 0x11 */
656/* File: armv5te/OP_RETURN_OBJECT.S */
657/* File: armv5te/OP_RETURN.S */
658    /*
659     * Return a 32-bit value.  Copies the return value into the "glue"
660     * structure, then jumps to the return handler.
661     *
662     * for: return, return-object
663     */
664    /* op vAA */
665    mov     r2, rINST, lsr #8           @ r2<- AA
666    GET_VREG(r0, r2)                    @ r0<- vAA
667    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
668    b       common_returnFromMethod
669
670
671/* ------------------------------ */
672    .balign 64
673.L_OP_CONST_4: /* 0x12 */
674/* File: armv5te/OP_CONST_4.S */
675    /* const/4 vA, #+B */
676    mov     r1, rINST, lsl #16          @ r1<- Bxxx0000
677    mov     r0, rINST, lsr #8           @ r0<- A+
678    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
679    mov     r1, r1, asr #28             @ r1<- sssssssB (sign-extended)
680    and     r0, r0, #15
681    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
682    SET_VREG(r1, r0)                    @ fp[A]<- r1
683    GOTO_OPCODE(ip)                     @ execute next instruction
684
685/* ------------------------------ */
686    .balign 64
687.L_OP_CONST_16: /* 0x13 */
688/* File: armv5te/OP_CONST_16.S */
689    /* const/16 vAA, #+BBBB */
690    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
691    mov     r3, rINST, lsr #8           @ r3<- AA
692    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
693    SET_VREG(r0, r3)                    @ vAA<- r0
694    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
695    GOTO_OPCODE(ip)                     @ jump to next instruction
696
697/* ------------------------------ */
698    .balign 64
699.L_OP_CONST: /* 0x14 */
700/* File: armv5te/OP_CONST.S */
701    /* const vAA, #+BBBBbbbb */
702    mov     r3, rINST, lsr #8           @ r3<- AA
703    FETCH(r0, 1)                        @ r0<- bbbb (low)
704    FETCH(r1, 2)                        @ r1<- BBBB (high)
705    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
706    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
707    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
708    SET_VREG(r0, r3)                    @ vAA<- r0
709    GOTO_OPCODE(ip)                     @ jump to next instruction
710
711/* ------------------------------ */
712    .balign 64
713.L_OP_CONST_HIGH16: /* 0x15 */
714/* File: armv5te/OP_CONST_HIGH16.S */
715    /* const/high16 vAA, #+BBBB0000 */
716    FETCH(r0, 1)                        @ r0<- 0000BBBB (zero-extended)
717    mov     r3, rINST, lsr #8           @ r3<- AA
718    mov     r0, r0, lsl #16             @ r0<- BBBB0000
719    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
720    SET_VREG(r0, r3)                    @ vAA<- r0
721    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
722    GOTO_OPCODE(ip)                     @ jump to next instruction
723
724/* ------------------------------ */
725    .balign 64
726.L_OP_CONST_WIDE_16: /* 0x16 */
727/* File: armv5te/OP_CONST_WIDE_16.S */
728    /* const-wide/16 vAA, #+BBBB */
729    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
730    mov     r3, rINST, lsr #8           @ r3<- AA
731    mov     r1, r0, asr #31             @ r1<- ssssssss
732    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
733    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
734    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
735    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
736    GOTO_OPCODE(ip)                     @ jump to next instruction
737
738/* ------------------------------ */
739    .balign 64
740.L_OP_CONST_WIDE_32: /* 0x17 */
741/* File: armv5te/OP_CONST_WIDE_32.S */
742    /* const-wide/32 vAA, #+BBBBbbbb */
743    FETCH(r0, 1)                        @ r0<- 0000bbbb (low)
744    mov     r3, rINST, lsr #8           @ r3<- AA
745    FETCH_S(r2, 2)                      @ r2<- ssssBBBB (high)
746    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
747    orr     r0, r0, r2, lsl #16         @ r0<- BBBBbbbb
748    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
749    mov     r1, r0, asr #31             @ r1<- ssssssss
750    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
751    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
752    GOTO_OPCODE(ip)                     @ jump to next instruction
753
754/* ------------------------------ */
755    .balign 64
756.L_OP_CONST_WIDE: /* 0x18 */
757/* File: armv5te/OP_CONST_WIDE.S */
758    /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
759    FETCH(r0, 1)                        @ r0<- bbbb (low)
760    FETCH(r1, 2)                        @ r1<- BBBB (low middle)
761    FETCH(r2, 3)                        @ r2<- hhhh (high middle)
762    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb (low word)
763    FETCH(r3, 4)                        @ r3<- HHHH (high)
764    mov     r9, rINST, lsr #8           @ r9<- AA
765    orr     r1, r2, r3, lsl #16         @ r1<- HHHHhhhh (high word)
766    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
767    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
768    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
769    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
770    GOTO_OPCODE(ip)                     @ jump to next instruction
771
772/* ------------------------------ */
773    .balign 64
774.L_OP_CONST_WIDE_HIGH16: /* 0x19 */
775/* File: armv5te/OP_CONST_WIDE_HIGH16.S */
776    /* const-wide/high16 vAA, #+BBBB000000000000 */
777    FETCH(r1, 1)                        @ r1<- 0000BBBB (zero-extended)
778    mov     r3, rINST, lsr #8           @ r3<- AA
779    mov     r0, #0                      @ r0<- 00000000
780    mov     r1, r1, lsl #16             @ r1<- BBBB0000
781    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
782    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
783    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
784    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
785    GOTO_OPCODE(ip)                     @ jump to next instruction
786
787/* ------------------------------ */
788    .balign 64
789.L_OP_CONST_STRING: /* 0x1a */
790/* File: armv5te/OP_CONST_STRING.S */
791    /* const/string vAA, String@BBBB */
792    FETCH(r1, 1)                        @ r1<- BBBB
793    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
794    mov     r9, rINST, lsr #8           @ r9<- AA
795    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
796    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
797    cmp     r0, #0                      @ not yet resolved?
798    beq     .LOP_CONST_STRING_resolve
799    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
800    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
801    SET_VREG(r0, r9)                    @ vAA<- r0
802    GOTO_OPCODE(ip)                     @ jump to next instruction
803
804/* ------------------------------ */
805    .balign 64
806.L_OP_CONST_STRING_JUMBO: /* 0x1b */
807/* File: armv5te/OP_CONST_STRING_JUMBO.S */
808    /* const/string vAA, String@BBBBBBBB */
809    FETCH(r0, 1)                        @ r0<- bbbb (low)
810    FETCH(r1, 2)                        @ r1<- BBBB (high)
811    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
812    mov     r9, rINST, lsr #8           @ r9<- AA
813    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
814    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
815    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
816    cmp     r0, #0
817    beq     .LOP_CONST_STRING_JUMBO_resolve
818    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
819    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
820    SET_VREG(r0, r9)                    @ vAA<- r0
821    GOTO_OPCODE(ip)                     @ jump to next instruction
822
823/* ------------------------------ */
824    .balign 64
825.L_OP_CONST_CLASS: /* 0x1c */
826/* File: armv5te/OP_CONST_CLASS.S */
827    /* const/class vAA, Class@BBBB */
828    FETCH(r1, 1)                        @ r1<- BBBB
829    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
830    mov     r9, rINST, lsr #8           @ r9<- AA
831    ldr     r2, [r2, #offDvmDex_pResClasses]   @ r2<- dvmDex->pResClasses
832    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResClasses[BBBB]
833    cmp     r0, #0                      @ not yet resolved?
834    beq     .LOP_CONST_CLASS_resolve
835    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
836    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
837    SET_VREG(r0, r9)                    @ vAA<- r0
838    GOTO_OPCODE(ip)                     @ jump to next instruction
839
840/* ------------------------------ */
841    .balign 64
842.L_OP_MONITOR_ENTER: /* 0x1d */
843/* File: armv5te/OP_MONITOR_ENTER.S */
844    /*
845     * Synchronize on an object.
846     */
847    /* monitor-enter vAA */
848    mov     r2, rINST, lsr #8           @ r2<- AA
849    GET_VREG(r1, r2)                    @ r1<- vAA (object)
850    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
851    cmp     r1, #0                      @ null object?
852    EXPORT_PC()                         @ need for precise GC, MONITOR_TRACKING
853    beq     common_errNullObject        @ null object, throw an exception
854    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
855    bl      dvmLockObject               @ call(self, obj)
856#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */
857    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
858    ldr     r1, [r0, #offThread_exception] @ check for exception
859    cmp     r1, #0
860    bne     common_exceptionThrown      @ exception raised, bail out
861#endif
862    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
863    GOTO_OPCODE(ip)                     @ jump to next instruction
864
865/* ------------------------------ */
866    .balign 64
867.L_OP_MONITOR_EXIT: /* 0x1e */
868/* File: armv5te/OP_MONITOR_EXIT.S */
869    /*
870     * Unlock an object.
871     *
872     * Exceptions that occur when unlocking a monitor need to appear as
873     * if they happened at the following instruction.  See the Dalvik
874     * instruction spec.
875     */
876    /* monitor-exit vAA */
877    mov     r2, rINST, lsr #8           @ r2<- AA
878    EXPORT_PC()                         @ before fetch: export the PC
879    GET_VREG(r1, r2)                    @ r1<- vAA (object)
880    cmp     r1, #0                      @ null object?
881    beq     1f                          @ yes
882    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
883    bl      dvmUnlockObject             @ r0<- success for unlock(self, obj)
884    cmp     r0, #0                      @ failed?
885    FETCH_ADVANCE_INST(1)               @ before throw: advance rPC, load rINST
886    beq     common_exceptionThrown      @ yes, exception is pending
887    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
888    GOTO_OPCODE(ip)                     @ jump to next instruction
8891:
890    FETCH_ADVANCE_INST(1)               @ advance before throw
891    b      common_errNullObject
892
893/* ------------------------------ */
894    .balign 64
895.L_OP_CHECK_CAST: /* 0x1f */
896/* File: armv5te/OP_CHECK_CAST.S */
897    /*
898     * Check to see if a cast from one class to another is allowed.
899     */
900    /* check-cast vAA, class@BBBB */
901    mov     r3, rINST, lsr #8           @ r3<- AA
902    FETCH(r2, 1)                        @ r2<- BBBB
903    GET_VREG(r9, r3)                    @ r9<- object
904    ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- pDvmDex
905    cmp     r9, #0                      @ is object null?
906    ldr     r0, [r0, #offDvmDex_pResClasses]    @ r0<- pDvmDex->pResClasses
907    beq     .LOP_CHECK_CAST_okay            @ null obj, cast always succeeds
908    ldr     r1, [r0, r2, lsl #2]        @ r1<- resolved class
909    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
910    cmp     r1, #0                      @ have we resolved this before?
911    beq     .LOP_CHECK_CAST_resolve         @ not resolved, do it now
912.LOP_CHECK_CAST_resolved:
913    cmp     r0, r1                      @ same class (trivial success)?
914    bne     .LOP_CHECK_CAST_fullcheck       @ no, do full check
915.LOP_CHECK_CAST_okay:
916    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
917    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
918    GOTO_OPCODE(ip)                     @ jump to next instruction
919
920/* ------------------------------ */
921    .balign 64
922.L_OP_INSTANCE_OF: /* 0x20 */
923/* File: armv5te/OP_INSTANCE_OF.S */
924    /*
925     * Check to see if an object reference is an instance of a class.
926     *
927     * Most common situation is a non-null object, being compared against
928     * an already-resolved class.
929     */
930    /* instance-of vA, vB, class@CCCC */
931    mov     r3, rINST, lsr #12          @ r3<- B
932    mov     r9, rINST, lsr #8           @ r9<- A+
933    GET_VREG(r0, r3)                    @ r0<- vB (object)
934    and     r9, r9, #15                 @ r9<- A
935    cmp     r0, #0                      @ is object null?
936    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- pDvmDex
937    beq     .LOP_INSTANCE_OF_store           @ null obj, not an instance, store r0
938    FETCH(r3, 1)                        @ r3<- CCCC
939    ldr     r2, [r2, #offDvmDex_pResClasses]    @ r2<- pDvmDex->pResClasses
940    ldr     r1, [r2, r3, lsl #2]        @ r1<- resolved class
941    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
942    cmp     r1, #0                      @ have we resolved this before?
943    beq     .LOP_INSTANCE_OF_resolve         @ not resolved, do it now
944.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class
945    cmp     r0, r1                      @ same class (trivial success)?
946    beq     .LOP_INSTANCE_OF_trivial         @ yes, trivial finish
947    b       .LOP_INSTANCE_OF_fullcheck       @ no, do full check
948
949/* ------------------------------ */
950    .balign 64
951.L_OP_ARRAY_LENGTH: /* 0x21 */
952/* File: armv5te/OP_ARRAY_LENGTH.S */
953    /*
954     * Return the length of an array.
955     */
956    mov     r1, rINST, lsr #12          @ r1<- B
957    mov     r2, rINST, lsr #8           @ r2<- A+
958    GET_VREG(r0, r1)                    @ r0<- vB (object ref)
959    and     r2, r2, #15                 @ r2<- A
960    cmp     r0, #0                      @ is object null?
961    beq     common_errNullObject        @ yup, fail
962    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
963    ldr     r3, [r0, #offArrayObject_length]    @ r3<- array length
964    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
965    SET_VREG(r3, r2)                    @ vB<- length
966    GOTO_OPCODE(ip)                     @ jump to next instruction
967
968/* ------------------------------ */
969    .balign 64
970.L_OP_NEW_INSTANCE: /* 0x22 */
971/* File: armv5te/OP_NEW_INSTANCE.S */
972    /*
973     * Create a new instance of a class.
974     */
975    /* new-instance vAA, class@BBBB */
976    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
977    FETCH(r1, 1)                        @ r1<- BBBB
978    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
979    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
980    EXPORT_PC()                         @ req'd for init, resolve, alloc
981    cmp     r0, #0                      @ already resolved?
982    beq     .LOP_NEW_INSTANCE_resolve         @ no, resolve it now
983.LOP_NEW_INSTANCE_resolved:   @ r0=class
984    ldrb    r1, [r0, #offClassObject_status]    @ r1<- ClassStatus enum
985    cmp     r1, #CLASS_INITIALIZED      @ has class been initialized?
986    bne     .LOP_NEW_INSTANCE_needinit        @ no, init class now
987.LOP_NEW_INSTANCE_initialized: @ r0=class
988    mov     r1, #ALLOC_DONT_TRACK       @ flags for alloc call
989    bl      dvmAllocObject              @ r0<- new object
990    b       .LOP_NEW_INSTANCE_finish          @ continue
991
992/* ------------------------------ */
993    .balign 64
994.L_OP_NEW_ARRAY: /* 0x23 */
995/* File: armv5te/OP_NEW_ARRAY.S */
996    /*
997     * Allocate an array of objects, specified with the array class
998     * and a count.
999     *
1000     * The verifier guarantees that this is an array class, so we don't
1001     * check for it here.
1002     */
1003    /* new-array vA, vB, class@CCCC */
1004    mov     r0, rINST, lsr #12          @ r0<- B
1005    FETCH(r2, 1)                        @ r2<- CCCC
1006    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1007    GET_VREG(r1, r0)                    @ r1<- vB (array length)
1008    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1009    cmp     r1, #0                      @ check length
1010    ldr     r0, [r3, r2, lsl #2]        @ r0<- resolved class
1011    bmi     common_errNegativeArraySize @ negative length, bail
1012    cmp     r0, #0                      @ already resolved?
1013    EXPORT_PC()                         @ req'd for resolve, alloc
1014    bne     .LOP_NEW_ARRAY_finish          @ resolved, continue
1015    b       .LOP_NEW_ARRAY_resolve         @ do resolve now
1016
1017/* ------------------------------ */
1018    .balign 64
1019.L_OP_FILLED_NEW_ARRAY: /* 0x24 */
1020/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1021    /*
1022     * Create a new array with elements filled from registers.
1023     *
1024     * for: filled-new-array, filled-new-array/range
1025     */
1026    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1027    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1028    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1029    FETCH(r1, 1)                        @ r1<- BBBB
1030    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1031    EXPORT_PC()                         @ need for resolve and alloc
1032    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1033    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1034    cmp     r0, #0                      @ already resolved?
1035    bne     .LOP_FILLED_NEW_ARRAY_continue        @ yes, continue on
10368:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1037    mov     r2, #0                      @ r2<- false
1038    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1039    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1040    cmp     r0, #0                      @ got null?
1041    beq     common_exceptionThrown      @ yes, handle exception
1042    b       .LOP_FILLED_NEW_ARRAY_continue
1043
1044/* ------------------------------ */
1045    .balign 64
1046.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
1047/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */
1048/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1049    /*
1050     * Create a new array with elements filled from registers.
1051     *
1052     * for: filled-new-array, filled-new-array/range
1053     */
1054    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1055    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1056    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1057    FETCH(r1, 1)                        @ r1<- BBBB
1058    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1059    EXPORT_PC()                         @ need for resolve and alloc
1060    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1061    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1062    cmp     r0, #0                      @ already resolved?
1063    bne     .LOP_FILLED_NEW_ARRAY_RANGE_continue        @ yes, continue on
10648:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1065    mov     r2, #0                      @ r2<- false
1066    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1067    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1068    cmp     r0, #0                      @ got null?
1069    beq     common_exceptionThrown      @ yes, handle exception
1070    b       .LOP_FILLED_NEW_ARRAY_RANGE_continue
1071
1072
1073/* ------------------------------ */
1074    .balign 64
1075.L_OP_FILL_ARRAY_DATA: /* 0x26 */
1076/* File: armv5te/OP_FILL_ARRAY_DATA.S */
1077    /* fill-array-data vAA, +BBBBBBBB */
1078    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1079    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1080    mov     r3, rINST, lsr #8           @ r3<- AA
1081    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
1082    GET_VREG(r0, r3)                    @ r0<- vAA (array object)
1083    add     r1, rPC, r1, lsl #1         @ r1<- PC + BBBBbbbb*2 (array data off.)
1084    EXPORT_PC();
1085    bl      dvmInterpHandleFillArrayData@ fill the array with predefined data
1086    cmp     r0, #0                      @ 0 means an exception is thrown
1087    beq     common_exceptionThrown      @ has exception
1088    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
1089    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1090    GOTO_OPCODE(ip)                     @ jump to next instruction
1091
1092/* ------------------------------ */
1093    .balign 64
1094.L_OP_THROW: /* 0x27 */
1095/* File: armv5te/OP_THROW.S */
1096    /*
1097     * Throw an exception object in the current thread.
1098     */
1099    /* throw vAA */
1100    mov     r2, rINST, lsr #8           @ r2<- AA
1101    GET_VREG(r1, r2)                    @ r1<- vAA (exception object)
1102    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
1103    EXPORT_PC()                         @ exception handler can throw
1104    cmp     r1, #0                      @ null object?
1105    beq     common_errNullObject        @ yes, throw an NPE instead
1106    @ bypass dvmSetException, just store it
1107    str     r1, [r0, #offThread_exception]  @ thread->exception<- obj
1108    b       common_exceptionThrown
1109
1110/* ------------------------------ */
1111    .balign 64
1112.L_OP_GOTO: /* 0x28 */
1113/* File: armv5te/OP_GOTO.S */
1114    /*
1115     * Unconditional branch, 8-bit offset.
1116     *
1117     * The branch distance is a signed code-unit offset, which we need to
1118     * double to get a byte offset.
1119     */
1120    /* goto +AA */
1121    mov     r0, rINST, lsl #16          @ r0<- AAxx0000
1122    movs    r9, r0, asr #24             @ r9<- ssssssAA (sign-extended)
1123    mov     r9, r9, lsl #1              @ r9<- byte offset
1124    bmi     common_backwardBranch       @ backward branch, do periodic checks
1125#if defined(WITH_JIT)
1126    GET_JIT_PROF_TABLE(r0)
1127    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1128    cmp     r0,#0
1129    bne     common_updateProfile
1130    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1131    GOTO_OPCODE(ip)                     @ jump to next instruction
1132#else
1133    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1134    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1135    GOTO_OPCODE(ip)                     @ jump to next instruction
1136#endif
1137
1138/* ------------------------------ */
1139    .balign 64
1140.L_OP_GOTO_16: /* 0x29 */
1141/* File: armv5te/OP_GOTO_16.S */
1142    /*
1143     * Unconditional branch, 16-bit offset.
1144     *
1145     * The branch distance is a signed code-unit offset, which we need to
1146     * double to get a byte offset.
1147     */
1148    /* goto/16 +AAAA */
1149    FETCH_S(r0, 1)                      @ r0<- ssssAAAA (sign-extended)
1150    movs    r9, r0, asl #1              @ r9<- byte offset, check sign
1151    bmi     common_backwardBranch       @ backward branch, do periodic checks
1152#if defined(WITH_JIT)
1153    GET_JIT_PROF_TABLE(r0)
1154    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1155    cmp     r0,#0
1156    bne     common_updateProfile
1157    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1158    GOTO_OPCODE(ip)                     @ jump to next instruction
1159#else
1160    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1161    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1162    GOTO_OPCODE(ip)                     @ jump to next instruction
1163#endif
1164
1165/* ------------------------------ */
1166    .balign 64
1167.L_OP_GOTO_32: /* 0x2a */
1168/* File: armv5te/OP_GOTO_32.S */
1169    /*
1170     * Unconditional branch, 32-bit offset.
1171     *
1172     * The branch distance is a signed code-unit offset, which we need to
1173     * double to get a byte offset.
1174     *
1175     * Unlike most opcodes, this one is allowed to branch to itself, so
1176     * our "backward branch" test must be "<=0" instead of "<0".  The ORRS
1177     * instruction doesn't affect the V flag, so we need to clear it
1178     * explicitly.
1179     */
1180    /* goto/32 +AAAAAAAA */
1181    FETCH(r0, 1)                        @ r0<- aaaa (lo)
1182    FETCH(r1, 2)                        @ r1<- AAAA (hi)
1183    cmp     ip, ip                      @ (clear V flag during stall)
1184    orrs    r0, r0, r1, lsl #16         @ r0<- AAAAaaaa, check sign
1185    mov     r9, r0, asl #1              @ r9<- byte offset
1186    ble     common_backwardBranch       @ backward branch, do periodic checks
1187#if defined(WITH_JIT)
1188    GET_JIT_PROF_TABLE(r0)
1189    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1190    cmp     r0,#0
1191    bne     common_updateProfile
1192    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1193    GOTO_OPCODE(ip)                     @ jump to next instruction
1194#else
1195    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1196    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1197    GOTO_OPCODE(ip)                     @ jump to next instruction
1198#endif
1199
1200/* ------------------------------ */
1201    .balign 64
1202.L_OP_PACKED_SWITCH: /* 0x2b */
1203/* File: armv5te/OP_PACKED_SWITCH.S */
1204    /*
1205     * Handle a packed-switch or sparse-switch instruction.  In both cases
1206     * we decode it and hand it off to a helper function.
1207     *
1208     * We don't really expect backward branches in a switch statement, but
1209     * they're perfectly legal, so we check for them here.
1210     *
1211     * for: packed-switch, sparse-switch
1212     */
1213    /* op vAA, +BBBB */
1214    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1215    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1216    mov     r3, rINST, lsr #8           @ r3<- AA
1217    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1218    GET_VREG(r1, r3)                    @ r1<- vAA
1219    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1220    bl      dvmInterpHandlePackedSwitch                       @ r0<- code-unit branch offset
1221    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1222    bmi     common_backwardBranch       @ backward branch, do periodic checks
1223    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1224#if defined(WITH_JIT)
1225    GET_JIT_PROF_TABLE(r0)
1226    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1227    cmp     r0,#0
1228    bne     common_updateProfile
1229    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1230    GOTO_OPCODE(ip)                     @ jump to next instruction
1231#else
1232    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1233    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1234    GOTO_OPCODE(ip)                     @ jump to next instruction
1235#endif
1236
1237/* ------------------------------ */
1238    .balign 64
1239.L_OP_SPARSE_SWITCH: /* 0x2c */
1240/* File: armv5te/OP_SPARSE_SWITCH.S */
1241/* File: armv5te/OP_PACKED_SWITCH.S */
1242    /*
1243     * Handle a packed-switch or sparse-switch instruction.  In both cases
1244     * we decode it and hand it off to a helper function.
1245     *
1246     * We don't really expect backward branches in a switch statement, but
1247     * they're perfectly legal, so we check for them here.
1248     *
1249     * for: packed-switch, sparse-switch
1250     */
1251    /* op vAA, +BBBB */
1252    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1253    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1254    mov     r3, rINST, lsr #8           @ r3<- AA
1255    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1256    GET_VREG(r1, r3)                    @ r1<- vAA
1257    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1258    bl      dvmInterpHandleSparseSwitch                       @ r0<- code-unit branch offset
1259    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1260    bmi     common_backwardBranch       @ backward branch, do periodic checks
1261    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1262#if defined(WITH_JIT)
1263    GET_JIT_PROF_TABLE(r0)
1264    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1265    cmp     r0,#0
1266    bne     common_updateProfile
1267    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1268    GOTO_OPCODE(ip)                     @ jump to next instruction
1269#else
1270    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1271    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1272    GOTO_OPCODE(ip)                     @ jump to next instruction
1273#endif
1274
1275
1276/* ------------------------------ */
1277    .balign 64
1278.L_OP_CMPL_FLOAT: /* 0x2d */
1279/* File: arm-vfp/OP_CMPL_FLOAT.S */
1280    /*
1281     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1282     * destination register based on the results of the comparison.
1283     *
1284     * int compare(x, y) {
1285     *     if (x == y) {
1286     *         return 0;
1287     *     } else if (x > y) {
1288     *         return 1;
1289     *     } else if (x < y) {
1290     *         return -1;
1291     *     } else {
1292     *         return -1;
1293     *     }
1294     * }
1295     */
1296    /* op vAA, vBB, vCC */
1297    FETCH(r0, 1)                        @ r0<- CCBB
1298    mov     r9, rINST, lsr #8           @ r9<- AA
1299    and     r2, r0, #255                @ r2<- BB
1300    mov     r3, r0, lsr #8              @ r3<- CC
1301    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1302    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1303    flds    s0, [r2]                    @ s0<- vBB
1304    flds    s1, [r3]                    @ s1<- vCC
1305    fcmpes  s0, s1                      @ compare (vBB, vCC)
1306    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1307    mvn     r0, #0                      @ r0<- -1 (default)
1308    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1309    fmstat                              @ export status flags
1310    movgt   r0, #1                      @ (greater than) r1<- 1
1311    moveq   r0, #0                      @ (equal) r1<- 0
1312    b       .LOP_CMPL_FLOAT_finish          @ argh
1313
1314
1315/* ------------------------------ */
1316    .balign 64
1317.L_OP_CMPG_FLOAT: /* 0x2e */
1318/* File: arm-vfp/OP_CMPG_FLOAT.S */
1319    /*
1320     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1321     * destination register based on the results of the comparison.
1322     *
1323     * int compare(x, y) {
1324     *     if (x == y) {
1325     *         return 0;
1326     *     } else if (x < y) {
1327     *         return -1;
1328     *     } else if (x > y) {
1329     *         return 1;
1330     *     } else {
1331     *         return 1;
1332     *     }
1333     * }
1334     */
1335    /* op vAA, vBB, vCC */
1336    FETCH(r0, 1)                        @ r0<- CCBB
1337    mov     r9, rINST, lsr #8           @ r9<- AA
1338    and     r2, r0, #255                @ r2<- BB
1339    mov     r3, r0, lsr #8              @ r3<- CC
1340    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1341    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1342    flds    s0, [r2]                    @ s0<- vBB
1343    flds    s1, [r3]                    @ s1<- vCC
1344    fcmpes  s0, s1                      @ compare (vBB, vCC)
1345    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1346    mov     r0, #1                      @ r0<- 1 (default)
1347    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1348    fmstat                              @ export status flags
1349    mvnmi   r0, #0                      @ (less than) r1<- -1
1350    moveq   r0, #0                      @ (equal) r1<- 0
1351    b       .LOP_CMPG_FLOAT_finish          @ argh
1352
1353
1354/* ------------------------------ */
1355    .balign 64
1356.L_OP_CMPL_DOUBLE: /* 0x2f */
1357/* File: arm-vfp/OP_CMPL_DOUBLE.S */
1358    /*
1359     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1360     * destination register based on the results of the comparison.
1361     *
1362     * int compare(x, y) {
1363     *     if (x == y) {
1364     *         return 0;
1365     *     } else if (x > y) {
1366     *         return 1;
1367     *     } else if (x < y) {
1368     *         return -1;
1369     *     } else {
1370     *         return -1;
1371     *     }
1372     * }
1373     */
1374    /* op vAA, vBB, vCC */
1375    FETCH(r0, 1)                        @ r0<- CCBB
1376    mov     r9, rINST, lsr #8           @ r9<- AA
1377    and     r2, r0, #255                @ r2<- BB
1378    mov     r3, r0, lsr #8              @ r3<- CC
1379    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1380    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1381    fldd    d0, [r2]                    @ d0<- vBB
1382    fldd    d1, [r3]                    @ d1<- vCC
1383    fcmped  d0, d1                      @ compare (vBB, vCC)
1384    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1385    mvn     r0, #0                      @ r0<- -1 (default)
1386    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1387    fmstat                              @ export status flags
1388    movgt   r0, #1                      @ (greater than) r1<- 1
1389    moveq   r0, #0                      @ (equal) r1<- 0
1390    b       .LOP_CMPL_DOUBLE_finish          @ argh
1391
1392
1393/* ------------------------------ */
1394    .balign 64
1395.L_OP_CMPG_DOUBLE: /* 0x30 */
1396/* File: arm-vfp/OP_CMPG_DOUBLE.S */
1397    /*
1398     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1399     * destination register based on the results of the comparison.
1400     *
1401     * int compare(x, y) {
1402     *     if (x == y) {
1403     *         return 0;
1404     *     } else if (x < y) {
1405     *         return -1;
1406     *     } else if (x > y) {
1407     *         return 1;
1408     *     } else {
1409     *         return 1;
1410     *     }
1411     * }
1412     */
1413    /* op vAA, vBB, vCC */
1414    FETCH(r0, 1)                        @ r0<- CCBB
1415    mov     r9, rINST, lsr #8           @ r9<- AA
1416    and     r2, r0, #255                @ r2<- BB
1417    mov     r3, r0, lsr #8              @ r3<- CC
1418    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1419    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1420    fldd    d0, [r2]                    @ d0<- vBB
1421    fldd    d1, [r3]                    @ d1<- vCC
1422    fcmped  d0, d1                      @ compare (vBB, vCC)
1423    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1424    mov     r0, #1                      @ r0<- 1 (default)
1425    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1426    fmstat                              @ export status flags
1427    mvnmi   r0, #0                      @ (less than) r1<- -1
1428    moveq   r0, #0                      @ (equal) r1<- 0
1429    b       .LOP_CMPG_DOUBLE_finish          @ argh
1430
1431
1432/* ------------------------------ */
1433    .balign 64
1434.L_OP_CMP_LONG: /* 0x31 */
1435/* File: armv5te/OP_CMP_LONG.S */
1436    /*
1437     * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
1438     * register based on the results of the comparison.
1439     *
1440     * We load the full values with LDM, but in practice many values could
1441     * be resolved by only looking at the high word.  This could be made
1442     * faster or slower by splitting the LDM into a pair of LDRs.
1443     *
1444     * If we just wanted to set condition flags, we could do this:
1445     *  subs    ip, r0, r2
1446     *  sbcs    ip, r1, r3
1447     *  subeqs  ip, r0, r2
1448     * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
1449     * integer value, which we can do with 2 conditional mov/mvn instructions
1450     * (set 1, set -1; if they're equal we already have 0 in ip), giving
1451     * us a constant 5-cycle path plus a branch at the end to the
1452     * instruction epilogue code.  The multi-compare approach below needs
1453     * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
1454     * in the worst case (the 64-bit values are equal).
1455     */
1456    /* cmp-long vAA, vBB, vCC */
1457    FETCH(r0, 1)                        @ r0<- CCBB
1458    mov     r9, rINST, lsr #8           @ r9<- AA
1459    and     r2, r0, #255                @ r2<- BB
1460    mov     r3, r0, lsr #8              @ r3<- CC
1461    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
1462    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
1463    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1464    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
1465    cmp     r1, r3                      @ compare (vBB+1, vCC+1)
1466    blt     .LOP_CMP_LONG_less            @ signed compare on high part
1467    bgt     .LOP_CMP_LONG_greater
1468    subs    r1, r0, r2                  @ r1<- r0 - r2
1469    bhi     .LOP_CMP_LONG_greater         @ unsigned compare on low part
1470    bne     .LOP_CMP_LONG_less
1471    b       .LOP_CMP_LONG_finish          @ equal; r1 already holds 0
1472
1473/* ------------------------------ */
1474    .balign 64
1475.L_OP_IF_EQ: /* 0x32 */
1476/* File: armv5te/OP_IF_EQ.S */
1477/* File: armv5te/bincmp.S */
1478    /*
1479     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1480     * fragment that specifies the *reverse* comparison to perform, e.g.
1481     * for "if-le" you would use "gt".
1482     *
1483     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1484     */
1485    /* if-cmp vA, vB, +CCCC */
1486    mov     r0, rINST, lsr #8           @ r0<- A+
1487    mov     r1, rINST, lsr #12          @ r1<- B
1488    and     r0, r0, #15
1489    GET_VREG(r3, r1)                    @ r3<- vB
1490    GET_VREG(r2, r0)                    @ r2<- vA
1491    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1492    cmp     r2, r3                      @ compare (vA, vB)
1493    bne  1f                      @ branch to 1 if comparison failed
1494    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1495    movs    r9, r9, asl #1              @ convert to bytes, check sign
1496    bmi     common_backwardBranch       @ yes, do periodic checks
14971:
1498#if defined(WITH_JIT)
1499    GET_JIT_PROF_TABLE(r0)
1500    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1501    b        common_testUpdateProfile
1502#else
1503    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1504    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1505    GOTO_OPCODE(ip)                     @ jump to next instruction
1506#endif
1507
1508
1509/* ------------------------------ */
1510    .balign 64
1511.L_OP_IF_NE: /* 0x33 */
1512/* File: armv5te/OP_IF_NE.S */
1513/* File: armv5te/bincmp.S */
1514    /*
1515     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1516     * fragment that specifies the *reverse* comparison to perform, e.g.
1517     * for "if-le" you would use "gt".
1518     *
1519     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1520     */
1521    /* if-cmp vA, vB, +CCCC */
1522    mov     r0, rINST, lsr #8           @ r0<- A+
1523    mov     r1, rINST, lsr #12          @ r1<- B
1524    and     r0, r0, #15
1525    GET_VREG(r3, r1)                    @ r3<- vB
1526    GET_VREG(r2, r0)                    @ r2<- vA
1527    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1528    cmp     r2, r3                      @ compare (vA, vB)
1529    beq  1f                      @ branch to 1 if comparison failed
1530    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1531    movs    r9, r9, asl #1              @ convert to bytes, check sign
1532    bmi     common_backwardBranch       @ yes, do periodic checks
15331:
1534#if defined(WITH_JIT)
1535    GET_JIT_PROF_TABLE(r0)
1536    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1537    b        common_testUpdateProfile
1538#else
1539    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1540    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1541    GOTO_OPCODE(ip)                     @ jump to next instruction
1542#endif
1543
1544
1545/* ------------------------------ */
1546    .balign 64
1547.L_OP_IF_LT: /* 0x34 */
1548/* File: armv5te/OP_IF_LT.S */
1549/* File: armv5te/bincmp.S */
1550    /*
1551     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1552     * fragment that specifies the *reverse* comparison to perform, e.g.
1553     * for "if-le" you would use "gt".
1554     *
1555     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1556     */
1557    /* if-cmp vA, vB, +CCCC */
1558    mov     r0, rINST, lsr #8           @ r0<- A+
1559    mov     r1, rINST, lsr #12          @ r1<- B
1560    and     r0, r0, #15
1561    GET_VREG(r3, r1)                    @ r3<- vB
1562    GET_VREG(r2, r0)                    @ r2<- vA
1563    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1564    cmp     r2, r3                      @ compare (vA, vB)
1565    bge  1f                      @ branch to 1 if comparison failed
1566    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1567    movs    r9, r9, asl #1              @ convert to bytes, check sign
1568    bmi     common_backwardBranch       @ yes, do periodic checks
15691:
1570#if defined(WITH_JIT)
1571    GET_JIT_PROF_TABLE(r0)
1572    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1573    b        common_testUpdateProfile
1574#else
1575    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1576    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1577    GOTO_OPCODE(ip)                     @ jump to next instruction
1578#endif
1579
1580
1581/* ------------------------------ */
1582    .balign 64
1583.L_OP_IF_GE: /* 0x35 */
1584/* File: armv5te/OP_IF_GE.S */
1585/* File: armv5te/bincmp.S */
1586    /*
1587     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1588     * fragment that specifies the *reverse* comparison to perform, e.g.
1589     * for "if-le" you would use "gt".
1590     *
1591     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1592     */
1593    /* if-cmp vA, vB, +CCCC */
1594    mov     r0, rINST, lsr #8           @ r0<- A+
1595    mov     r1, rINST, lsr #12          @ r1<- B
1596    and     r0, r0, #15
1597    GET_VREG(r3, r1)                    @ r3<- vB
1598    GET_VREG(r2, r0)                    @ r2<- vA
1599    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1600    cmp     r2, r3                      @ compare (vA, vB)
1601    blt  1f                      @ branch to 1 if comparison failed
1602    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1603    movs    r9, r9, asl #1              @ convert to bytes, check sign
1604    bmi     common_backwardBranch       @ yes, do periodic checks
16051:
1606#if defined(WITH_JIT)
1607    GET_JIT_PROF_TABLE(r0)
1608    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1609    b        common_testUpdateProfile
1610#else
1611    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1612    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1613    GOTO_OPCODE(ip)                     @ jump to next instruction
1614#endif
1615
1616
1617/* ------------------------------ */
1618    .balign 64
1619.L_OP_IF_GT: /* 0x36 */
1620/* File: armv5te/OP_IF_GT.S */
1621/* File: armv5te/bincmp.S */
1622    /*
1623     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1624     * fragment that specifies the *reverse* comparison to perform, e.g.
1625     * for "if-le" you would use "gt".
1626     *
1627     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1628     */
1629    /* if-cmp vA, vB, +CCCC */
1630    mov     r0, rINST, lsr #8           @ r0<- A+
1631    mov     r1, rINST, lsr #12          @ r1<- B
1632    and     r0, r0, #15
1633    GET_VREG(r3, r1)                    @ r3<- vB
1634    GET_VREG(r2, r0)                    @ r2<- vA
1635    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1636    cmp     r2, r3                      @ compare (vA, vB)
1637    ble  1f                      @ branch to 1 if comparison failed
1638    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1639    movs    r9, r9, asl #1              @ convert to bytes, check sign
1640    bmi     common_backwardBranch       @ yes, do periodic checks
16411:
1642#if defined(WITH_JIT)
1643    GET_JIT_PROF_TABLE(r0)
1644    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1645    b        common_testUpdateProfile
1646#else
1647    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1648    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1649    GOTO_OPCODE(ip)                     @ jump to next instruction
1650#endif
1651
1652
1653/* ------------------------------ */
1654    .balign 64
1655.L_OP_IF_LE: /* 0x37 */
1656/* File: armv5te/OP_IF_LE.S */
1657/* File: armv5te/bincmp.S */
1658    /*
1659     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1660     * fragment that specifies the *reverse* comparison to perform, e.g.
1661     * for "if-le" you would use "gt".
1662     *
1663     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1664     */
1665    /* if-cmp vA, vB, +CCCC */
1666    mov     r0, rINST, lsr #8           @ r0<- A+
1667    mov     r1, rINST, lsr #12          @ r1<- B
1668    and     r0, r0, #15
1669    GET_VREG(r3, r1)                    @ r3<- vB
1670    GET_VREG(r2, r0)                    @ r2<- vA
1671    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1672    cmp     r2, r3                      @ compare (vA, vB)
1673    bgt  1f                      @ branch to 1 if comparison failed
1674    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1675    movs    r9, r9, asl #1              @ convert to bytes, check sign
1676    bmi     common_backwardBranch       @ yes, do periodic checks
16771:
1678#if defined(WITH_JIT)
1679    GET_JIT_PROF_TABLE(r0)
1680    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1681    b        common_testUpdateProfile
1682#else
1683    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1684    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1685    GOTO_OPCODE(ip)                     @ jump to next instruction
1686#endif
1687
1688
1689/* ------------------------------ */
1690    .balign 64
1691.L_OP_IF_EQZ: /* 0x38 */
1692/* File: armv5te/OP_IF_EQZ.S */
1693/* File: armv5te/zcmp.S */
1694    /*
1695     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1696     * fragment that specifies the *reverse* comparison to perform, e.g.
1697     * for "if-le" you would use "gt".
1698     *
1699     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1700     */
1701    /* if-cmp vAA, +BBBB */
1702    mov     r0, rINST, lsr #8           @ r0<- AA
1703    GET_VREG(r2, r0)                    @ r2<- vAA
1704    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1705    cmp     r2, #0                      @ compare (vA, 0)
1706    bne  1f                      @ branch to 1 if comparison failed
1707    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1708    movs    r9, r9, asl #1              @ convert to bytes, check sign
1709    bmi     common_backwardBranch       @ backward branch, do periodic checks
17101:
1711#if defined(WITH_JIT)
1712    GET_JIT_PROF_TABLE(r0)
1713    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1714    cmp     r0,#0
1715    bne     common_updateProfile
1716    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1717    GOTO_OPCODE(ip)                     @ jump to next instruction
1718#else
1719    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1720    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1721    GOTO_OPCODE(ip)                     @ jump to next instruction
1722#endif
1723
1724
1725/* ------------------------------ */
1726    .balign 64
1727.L_OP_IF_NEZ: /* 0x39 */
1728/* File: armv5te/OP_IF_NEZ.S */
1729/* File: armv5te/zcmp.S */
1730    /*
1731     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1732     * fragment that specifies the *reverse* comparison to perform, e.g.
1733     * for "if-le" you would use "gt".
1734     *
1735     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1736     */
1737    /* if-cmp vAA, +BBBB */
1738    mov     r0, rINST, lsr #8           @ r0<- AA
1739    GET_VREG(r2, r0)                    @ r2<- vAA
1740    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1741    cmp     r2, #0                      @ compare (vA, 0)
1742    beq  1f                      @ branch to 1 if comparison failed
1743    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1744    movs    r9, r9, asl #1              @ convert to bytes, check sign
1745    bmi     common_backwardBranch       @ backward branch, do periodic checks
17461:
1747#if defined(WITH_JIT)
1748    GET_JIT_PROF_TABLE(r0)
1749    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1750    cmp     r0,#0
1751    bne     common_updateProfile
1752    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1753    GOTO_OPCODE(ip)                     @ jump to next instruction
1754#else
1755    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1756    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1757    GOTO_OPCODE(ip)                     @ jump to next instruction
1758#endif
1759
1760
1761/* ------------------------------ */
1762    .balign 64
1763.L_OP_IF_LTZ: /* 0x3a */
1764/* File: armv5te/OP_IF_LTZ.S */
1765/* File: armv5te/zcmp.S */
1766    /*
1767     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1768     * fragment that specifies the *reverse* comparison to perform, e.g.
1769     * for "if-le" you would use "gt".
1770     *
1771     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1772     */
1773    /* if-cmp vAA, +BBBB */
1774    mov     r0, rINST, lsr #8           @ r0<- AA
1775    GET_VREG(r2, r0)                    @ r2<- vAA
1776    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1777    cmp     r2, #0                      @ compare (vA, 0)
1778    bge  1f                      @ branch to 1 if comparison failed
1779    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1780    movs    r9, r9, asl #1              @ convert to bytes, check sign
1781    bmi     common_backwardBranch       @ backward branch, do periodic checks
17821:
1783#if defined(WITH_JIT)
1784    GET_JIT_PROF_TABLE(r0)
1785    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1786    cmp     r0,#0
1787    bne     common_updateProfile
1788    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1789    GOTO_OPCODE(ip)                     @ jump to next instruction
1790#else
1791    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1792    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1793    GOTO_OPCODE(ip)                     @ jump to next instruction
1794#endif
1795
1796
1797/* ------------------------------ */
1798    .balign 64
1799.L_OP_IF_GEZ: /* 0x3b */
1800/* File: armv5te/OP_IF_GEZ.S */
1801/* File: armv5te/zcmp.S */
1802    /*
1803     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1804     * fragment that specifies the *reverse* comparison to perform, e.g.
1805     * for "if-le" you would use "gt".
1806     *
1807     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1808     */
1809    /* if-cmp vAA, +BBBB */
1810    mov     r0, rINST, lsr #8           @ r0<- AA
1811    GET_VREG(r2, r0)                    @ r2<- vAA
1812    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1813    cmp     r2, #0                      @ compare (vA, 0)
1814    blt  1f                      @ branch to 1 if comparison failed
1815    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1816    movs    r9, r9, asl #1              @ convert to bytes, check sign
1817    bmi     common_backwardBranch       @ backward branch, do periodic checks
18181:
1819#if defined(WITH_JIT)
1820    GET_JIT_PROF_TABLE(r0)
1821    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1822    cmp     r0,#0
1823    bne     common_updateProfile
1824    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1825    GOTO_OPCODE(ip)                     @ jump to next instruction
1826#else
1827    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1828    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1829    GOTO_OPCODE(ip)                     @ jump to next instruction
1830#endif
1831
1832
1833/* ------------------------------ */
1834    .balign 64
1835.L_OP_IF_GTZ: /* 0x3c */
1836/* File: armv5te/OP_IF_GTZ.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    ble  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    .balign 64
1871.L_OP_IF_LEZ: /* 0x3d */
1872/* File: armv5te/OP_IF_LEZ.S */
1873/* File: armv5te/zcmp.S */
1874    /*
1875     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1876     * fragment that specifies the *reverse* comparison to perform, e.g.
1877     * for "if-le" you would use "gt".
1878     *
1879     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1880     */
1881    /* if-cmp vAA, +BBBB */
1882    mov     r0, rINST, lsr #8           @ r0<- AA
1883    GET_VREG(r2, r0)                    @ r2<- vAA
1884    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1885    cmp     r2, #0                      @ compare (vA, 0)
1886    bgt  1f                      @ branch to 1 if comparison failed
1887    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1888    movs    r9, r9, asl #1              @ convert to bytes, check sign
1889    bmi     common_backwardBranch       @ backward branch, do periodic checks
18901:
1891#if defined(WITH_JIT)
1892    GET_JIT_PROF_TABLE(r0)
1893    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1894    cmp     r0,#0
1895    bne     common_updateProfile
1896    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1897    GOTO_OPCODE(ip)                     @ jump to next instruction
1898#else
1899    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1900    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1901    GOTO_OPCODE(ip)                     @ jump to next instruction
1902#endif
1903
1904
1905/* ------------------------------ */
1906    .balign 64
1907.L_OP_UNUSED_3E: /* 0x3e */
1908/* File: armv5te/OP_UNUSED_3E.S */
1909/* File: armv5te/unused.S */
1910    bl      common_abort
1911
1912
1913/* ------------------------------ */
1914    .balign 64
1915.L_OP_UNUSED_3F: /* 0x3f */
1916/* File: armv5te/OP_UNUSED_3F.S */
1917/* File: armv5te/unused.S */
1918    bl      common_abort
1919
1920
1921/* ------------------------------ */
1922    .balign 64
1923.L_OP_UNUSED_40: /* 0x40 */
1924/* File: armv5te/OP_UNUSED_40.S */
1925/* File: armv5te/unused.S */
1926    bl      common_abort
1927
1928
1929/* ------------------------------ */
1930    .balign 64
1931.L_OP_UNUSED_41: /* 0x41 */
1932/* File: armv5te/OP_UNUSED_41.S */
1933/* File: armv5te/unused.S */
1934    bl      common_abort
1935
1936
1937/* ------------------------------ */
1938    .balign 64
1939.L_OP_UNUSED_42: /* 0x42 */
1940/* File: armv5te/OP_UNUSED_42.S */
1941/* File: armv5te/unused.S */
1942    bl      common_abort
1943
1944
1945/* ------------------------------ */
1946    .balign 64
1947.L_OP_UNUSED_43: /* 0x43 */
1948/* File: armv5te/OP_UNUSED_43.S */
1949/* File: armv5te/unused.S */
1950    bl      common_abort
1951
1952
1953/* ------------------------------ */
1954    .balign 64
1955.L_OP_AGET: /* 0x44 */
1956/* File: armv5te/OP_AGET.S */
1957    /*
1958     * Array get, 32 bits or less.  vAA <- vBB[vCC].
1959     *
1960     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
1961     * instructions.  We use a pair of FETCH_Bs instead.
1962     *
1963     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1964     */
1965    /* op vAA, vBB, vCC */
1966    FETCH_B(r2, 1, 0)                   @ r2<- BB
1967    mov     r9, rINST, lsr #8           @ r9<- AA
1968    FETCH_B(r3, 1, 1)                   @ r3<- CC
1969    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
1970    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
1971    cmp     r0, #0                      @ null array object?
1972    beq     common_errNullObject        @ yes, bail
1973    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
1974    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
1975    cmp     r1, r3                      @ compare unsigned index, length
1976    bcs     common_errArrayIndex        @ index >= length, bail
1977    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1978    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
1979    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1980    SET_VREG(r2, r9)                    @ vAA<- r2
1981    GOTO_OPCODE(ip)                     @ jump to next instruction
1982
1983/* ------------------------------ */
1984    .balign 64
1985.L_OP_AGET_WIDE: /* 0x45 */
1986/* File: armv5te/OP_AGET_WIDE.S */
1987    /*
1988     * Array get, 64 bits.  vAA <- vBB[vCC].
1989     *
1990     * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD.
1991     */
1992    /* aget-wide vAA, vBB, vCC */
1993    FETCH(r0, 1)                        @ r0<- CCBB
1994    mov     r9, rINST, lsr #8           @ r9<- AA
1995    and     r2, r0, #255                @ r2<- BB
1996    mov     r3, r0, lsr #8              @ r3<- CC
1997    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
1998    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
1999    cmp     r0, #0                      @ null array object?
2000    beq     common_errNullObject        @ yes, bail
2001    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2002    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2003    cmp     r1, r3                      @ compare unsigned index, length
2004    bcc     .LOP_AGET_WIDE_finish          @ okay, continue below
2005    b       common_errArrayIndex        @ index >= length, bail
2006    @ May want to swap the order of these two branches depending on how the
2007    @ branch prediction (if any) handles conditional forward branches vs.
2008    @ unconditional forward branches.
2009
2010/* ------------------------------ */
2011    .balign 64
2012.L_OP_AGET_OBJECT: /* 0x46 */
2013/* File: armv5te/OP_AGET_OBJECT.S */
2014/* File: armv5te/OP_AGET.S */
2015    /*
2016     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2017     *
2018     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2019     * instructions.  We use a pair of FETCH_Bs instead.
2020     *
2021     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2022     */
2023    /* op vAA, vBB, vCC */
2024    FETCH_B(r2, 1, 0)                   @ r2<- BB
2025    mov     r9, rINST, lsr #8           @ r9<- AA
2026    FETCH_B(r3, 1, 1)                   @ r3<- CC
2027    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2028    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2029    cmp     r0, #0                      @ null array object?
2030    beq     common_errNullObject        @ yes, bail
2031    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2032    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2033    cmp     r1, r3                      @ compare unsigned index, length
2034    bcs     common_errArrayIndex        @ index >= length, bail
2035    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2036    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2037    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2038    SET_VREG(r2, r9)                    @ vAA<- r2
2039    GOTO_OPCODE(ip)                     @ jump to next instruction
2040
2041
2042/* ------------------------------ */
2043    .balign 64
2044.L_OP_AGET_BOOLEAN: /* 0x47 */
2045/* File: armv5te/OP_AGET_BOOLEAN.S */
2046/* File: armv5te/OP_AGET.S */
2047    /*
2048     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2049     *
2050     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2051     * instructions.  We use a pair of FETCH_Bs instead.
2052     *
2053     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2054     */
2055    /* op vAA, vBB, vCC */
2056    FETCH_B(r2, 1, 0)                   @ r2<- BB
2057    mov     r9, rINST, lsr #8           @ r9<- AA
2058    FETCH_B(r3, 1, 1)                   @ r3<- CC
2059    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2060    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2061    cmp     r0, #0                      @ null array object?
2062    beq     common_errNullObject        @ yes, bail
2063    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2064    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2065    cmp     r1, r3                      @ compare unsigned index, length
2066    bcs     common_errArrayIndex        @ index >= length, bail
2067    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2068    ldrb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2069    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2070    SET_VREG(r2, r9)                    @ vAA<- r2
2071    GOTO_OPCODE(ip)                     @ jump to next instruction
2072
2073
2074/* ------------------------------ */
2075    .balign 64
2076.L_OP_AGET_BYTE: /* 0x48 */
2077/* File: armv5te/OP_AGET_BYTE.S */
2078/* File: armv5te/OP_AGET.S */
2079    /*
2080     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2081     *
2082     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2083     * instructions.  We use a pair of FETCH_Bs instead.
2084     *
2085     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2086     */
2087    /* op vAA, vBB, vCC */
2088    FETCH_B(r2, 1, 0)                   @ r2<- BB
2089    mov     r9, rINST, lsr #8           @ r9<- AA
2090    FETCH_B(r3, 1, 1)                   @ r3<- CC
2091    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2092    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2093    cmp     r0, #0                      @ null array object?
2094    beq     common_errNullObject        @ yes, bail
2095    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2096    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2097    cmp     r1, r3                      @ compare unsigned index, length
2098    bcs     common_errArrayIndex        @ index >= length, bail
2099    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2100    ldrsb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2101    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2102    SET_VREG(r2, r9)                    @ vAA<- r2
2103    GOTO_OPCODE(ip)                     @ jump to next instruction
2104
2105
2106/* ------------------------------ */
2107    .balign 64
2108.L_OP_AGET_CHAR: /* 0x49 */
2109/* File: armv5te/OP_AGET_CHAR.S */
2110/* File: armv5te/OP_AGET.S */
2111    /*
2112     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2113     *
2114     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2115     * instructions.  We use a pair of FETCH_Bs instead.
2116     *
2117     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2118     */
2119    /* op vAA, vBB, vCC */
2120    FETCH_B(r2, 1, 0)                   @ r2<- BB
2121    mov     r9, rINST, lsr #8           @ r9<- AA
2122    FETCH_B(r3, 1, 1)                   @ r3<- CC
2123    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2124    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2125    cmp     r0, #0                      @ null array object?
2126    beq     common_errNullObject        @ yes, bail
2127    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2128    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2129    cmp     r1, r3                      @ compare unsigned index, length
2130    bcs     common_errArrayIndex        @ index >= length, bail
2131    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2132    ldrh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2133    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2134    SET_VREG(r2, r9)                    @ vAA<- r2
2135    GOTO_OPCODE(ip)                     @ jump to next instruction
2136
2137
2138/* ------------------------------ */
2139    .balign 64
2140.L_OP_AGET_SHORT: /* 0x4a */
2141/* File: armv5te/OP_AGET_SHORT.S */
2142/* File: armv5te/OP_AGET.S */
2143    /*
2144     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2145     *
2146     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2147     * instructions.  We use a pair of FETCH_Bs instead.
2148     *
2149     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2150     */
2151    /* op vAA, vBB, vCC */
2152    FETCH_B(r2, 1, 0)                   @ r2<- BB
2153    mov     r9, rINST, lsr #8           @ r9<- AA
2154    FETCH_B(r3, 1, 1)                   @ r3<- CC
2155    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2156    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2157    cmp     r0, #0                      @ null array object?
2158    beq     common_errNullObject        @ yes, bail
2159    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2160    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2161    cmp     r1, r3                      @ compare unsigned index, length
2162    bcs     common_errArrayIndex        @ index >= length, bail
2163    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2164    ldrsh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2165    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2166    SET_VREG(r2, r9)                    @ vAA<- r2
2167    GOTO_OPCODE(ip)                     @ jump to next instruction
2168
2169
2170/* ------------------------------ */
2171    .balign 64
2172.L_OP_APUT: /* 0x4b */
2173/* File: armv5te/OP_APUT.S */
2174    /*
2175     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2176     *
2177     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2178     * instructions.  We use a pair of FETCH_Bs instead.
2179     *
2180     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2181     */
2182    /* op vAA, vBB, vCC */
2183    FETCH_B(r2, 1, 0)                   @ r2<- BB
2184    mov     r9, rINST, lsr #8           @ r9<- AA
2185    FETCH_B(r3, 1, 1)                   @ r3<- CC
2186    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2187    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2188    cmp     r0, #0                      @ null array object?
2189    beq     common_errNullObject        @ yes, bail
2190    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2191    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2192    cmp     r1, r3                      @ compare unsigned index, length
2193    bcs     common_errArrayIndex        @ index >= length, bail
2194    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2195    GET_VREG(r2, r9)                    @ r2<- vAA
2196    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2197    str  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2198    GOTO_OPCODE(ip)                     @ jump to next instruction
2199
2200/* ------------------------------ */
2201    .balign 64
2202.L_OP_APUT_WIDE: /* 0x4c */
2203/* File: armv5te/OP_APUT_WIDE.S */
2204    /*
2205     * Array put, 64 bits.  vBB[vCC] <- vAA.
2206     *
2207     * Arrays of long/double are 64-bit aligned, so it's okay to use STRD.
2208     */
2209    /* aput-wide vAA, vBB, vCC */
2210    FETCH(r0, 1)                        @ r0<- CCBB
2211    mov     r9, rINST, lsr #8           @ r9<- AA
2212    and     r2, r0, #255                @ r2<- BB
2213    mov     r3, r0, lsr #8              @ r3<- CC
2214    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2215    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2216    cmp     r0, #0                      @ null array object?
2217    beq     common_errNullObject        @ yes, bail
2218    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2219    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2220    cmp     r1, r3                      @ compare unsigned index, length
2221    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2222    bcc     .LOP_APUT_WIDE_finish          @ okay, continue below
2223    b       common_errArrayIndex        @ index >= length, bail
2224    @ May want to swap the order of these two branches depending on how the
2225    @ branch prediction (if any) handles conditional forward branches vs.
2226    @ unconditional forward branches.
2227
2228/* ------------------------------ */
2229    .balign 64
2230.L_OP_APUT_OBJECT: /* 0x4d */
2231/* File: armv5te/OP_APUT_OBJECT.S */
2232    /*
2233     * Store an object into an array.  vBB[vCC] <- vAA.
2234     */
2235    /* op vAA, vBB, vCC */
2236    FETCH(r0, 1)                        @ r0<- CCBB
2237    mov     r9, rINST, lsr #8           @ r9<- AA
2238    and     r2, r0, #255                @ r2<- BB
2239    mov     r3, r0, lsr #8              @ r3<- CC
2240    GET_VREG(rINST, r2)                 @ rINST<- vBB (array object)
2241    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2242    cmp     rINST, #0                   @ null array object?
2243    GET_VREG(r9, r9)                    @ r9<- vAA
2244    beq     common_errNullObject        @ yes, bail
2245    ldr     r3, [rINST, #offArrayObject_length]   @ r3<- arrayObj->length
2246    add     r10, rINST, r1, lsl #2      @ r10<- arrayObj + index*width
2247    cmp     r1, r3                      @ compare unsigned index, length
2248    bcc     .LOP_APUT_OBJECT_finish          @ we're okay, continue on
2249    b       common_errArrayIndex        @ index >= length, bail
2250
2251
2252/* ------------------------------ */
2253    .balign 64
2254.L_OP_APUT_BOOLEAN: /* 0x4e */
2255/* File: armv5te/OP_APUT_BOOLEAN.S */
2256/* File: armv5te/OP_APUT.S */
2257    /*
2258     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2259     *
2260     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2261     * instructions.  We use a pair of FETCH_Bs instead.
2262     *
2263     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2264     */
2265    /* op vAA, vBB, vCC */
2266    FETCH_B(r2, 1, 0)                   @ r2<- BB
2267    mov     r9, rINST, lsr #8           @ r9<- AA
2268    FETCH_B(r3, 1, 1)                   @ r3<- CC
2269    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2270    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2271    cmp     r0, #0                      @ null array object?
2272    beq     common_errNullObject        @ yes, bail
2273    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2274    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2275    cmp     r1, r3                      @ compare unsigned index, length
2276    bcs     common_errArrayIndex        @ index >= length, bail
2277    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2278    GET_VREG(r2, r9)                    @ r2<- vAA
2279    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2280    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2281    GOTO_OPCODE(ip)                     @ jump to next instruction
2282
2283
2284/* ------------------------------ */
2285    .balign 64
2286.L_OP_APUT_BYTE: /* 0x4f */
2287/* File: armv5te/OP_APUT_BYTE.S */
2288/* File: armv5te/OP_APUT.S */
2289    /*
2290     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2291     *
2292     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2293     * instructions.  We use a pair of FETCH_Bs instead.
2294     *
2295     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2296     */
2297    /* op vAA, vBB, vCC */
2298    FETCH_B(r2, 1, 0)                   @ r2<- BB
2299    mov     r9, rINST, lsr #8           @ r9<- AA
2300    FETCH_B(r3, 1, 1)                   @ r3<- CC
2301    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2302    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2303    cmp     r0, #0                      @ null array object?
2304    beq     common_errNullObject        @ yes, bail
2305    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2306    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2307    cmp     r1, r3                      @ compare unsigned index, length
2308    bcs     common_errArrayIndex        @ index >= length, bail
2309    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2310    GET_VREG(r2, r9)                    @ r2<- vAA
2311    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2312    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2313    GOTO_OPCODE(ip)                     @ jump to next instruction
2314
2315
2316/* ------------------------------ */
2317    .balign 64
2318.L_OP_APUT_CHAR: /* 0x50 */
2319/* File: armv5te/OP_APUT_CHAR.S */
2320/* File: armv5te/OP_APUT.S */
2321    /*
2322     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2323     *
2324     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2325     * instructions.  We use a pair of FETCH_Bs instead.
2326     *
2327     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2328     */
2329    /* op vAA, vBB, vCC */
2330    FETCH_B(r2, 1, 0)                   @ r2<- BB
2331    mov     r9, rINST, lsr #8           @ r9<- AA
2332    FETCH_B(r3, 1, 1)                   @ r3<- CC
2333    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2334    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2335    cmp     r0, #0                      @ null array object?
2336    beq     common_errNullObject        @ yes, bail
2337    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2338    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2339    cmp     r1, r3                      @ compare unsigned index, length
2340    bcs     common_errArrayIndex        @ index >= length, bail
2341    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2342    GET_VREG(r2, r9)                    @ r2<- vAA
2343    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2344    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2345    GOTO_OPCODE(ip)                     @ jump to next instruction
2346
2347
2348/* ------------------------------ */
2349    .balign 64
2350.L_OP_APUT_SHORT: /* 0x51 */
2351/* File: armv5te/OP_APUT_SHORT.S */
2352/* File: armv5te/OP_APUT.S */
2353    /*
2354     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2355     *
2356     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2357     * instructions.  We use a pair of FETCH_Bs instead.
2358     *
2359     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2360     */
2361    /* op vAA, vBB, vCC */
2362    FETCH_B(r2, 1, 0)                   @ r2<- BB
2363    mov     r9, rINST, lsr #8           @ r9<- AA
2364    FETCH_B(r3, 1, 1)                   @ r3<- CC
2365    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2366    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2367    cmp     r0, #0                      @ null array object?
2368    beq     common_errNullObject        @ yes, bail
2369    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2370    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2371    cmp     r1, r3                      @ compare unsigned index, length
2372    bcs     common_errArrayIndex        @ index >= length, bail
2373    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2374    GET_VREG(r2, r9)                    @ r2<- vAA
2375    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2376    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2377    GOTO_OPCODE(ip)                     @ jump to next instruction
2378
2379
2380/* ------------------------------ */
2381    .balign 64
2382.L_OP_IGET: /* 0x52 */
2383/* File: armv5te/OP_IGET.S */
2384    /*
2385     * General 32-bit instance field get.
2386     *
2387     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2388     */
2389    /* op vA, vB, field@CCCC */
2390    mov     r0, rINST, lsr #12          @ r0<- B
2391    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2392    FETCH(r1, 1)                        @ r1<- field ref CCCC
2393    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2394    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2395    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2396    cmp     r0, #0                      @ is resolved entry null?
2397    bne     .LOP_IGET_finish          @ no, already resolved
23988:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2399    EXPORT_PC()                         @ resolve() could throw
2400    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2401    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2402    cmp     r0, #0
2403    bne     .LOP_IGET_finish
2404    b       common_exceptionThrown
2405
2406/* ------------------------------ */
2407    .balign 64
2408.L_OP_IGET_WIDE: /* 0x53 */
2409/* File: armv5te/OP_IGET_WIDE.S */
2410    /*
2411     * Wide 32-bit instance field get.
2412     */
2413    /* iget-wide vA, vB, field@CCCC */
2414    mov     r0, rINST, lsr #12          @ r0<- B
2415    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2416    FETCH(r1, 1)                        @ r1<- field ref CCCC
2417    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2418    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2419    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2420    cmp     r0, #0                      @ is resolved entry null?
2421    bne     .LOP_IGET_WIDE_finish          @ no, already resolved
24228:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2423    EXPORT_PC()                         @ resolve() could throw
2424    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2425    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2426    cmp     r0, #0
2427    bne     .LOP_IGET_WIDE_finish
2428    b       common_exceptionThrown
2429
2430/* ------------------------------ */
2431    .balign 64
2432.L_OP_IGET_OBJECT: /* 0x54 */
2433/* File: armv5te/OP_IGET_OBJECT.S */
2434/* File: armv5te/OP_IGET.S */
2435    /*
2436     * General 32-bit instance field get.
2437     *
2438     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2439     */
2440    /* op vA, vB, field@CCCC */
2441    mov     r0, rINST, lsr #12          @ r0<- B
2442    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2443    FETCH(r1, 1)                        @ r1<- field ref CCCC
2444    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2445    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2446    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2447    cmp     r0, #0                      @ is resolved entry null?
2448    bne     .LOP_IGET_OBJECT_finish          @ no, already resolved
24498:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2450    EXPORT_PC()                         @ resolve() could throw
2451    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2452    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2453    cmp     r0, #0
2454    bne     .LOP_IGET_OBJECT_finish
2455    b       common_exceptionThrown
2456
2457
2458/* ------------------------------ */
2459    .balign 64
2460.L_OP_IGET_BOOLEAN: /* 0x55 */
2461/* File: armv5te/OP_IGET_BOOLEAN.S */
2462@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" }
2463/* File: armv5te/OP_IGET.S */
2464    /*
2465     * General 32-bit instance field get.
2466     *
2467     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2468     */
2469    /* op vA, vB, field@CCCC */
2470    mov     r0, rINST, lsr #12          @ r0<- B
2471    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2472    FETCH(r1, 1)                        @ r1<- field ref CCCC
2473    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2474    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2475    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2476    cmp     r0, #0                      @ is resolved entry null?
2477    bne     .LOP_IGET_BOOLEAN_finish          @ no, already resolved
24788:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2479    EXPORT_PC()                         @ resolve() could throw
2480    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2481    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2482    cmp     r0, #0
2483    bne     .LOP_IGET_BOOLEAN_finish
2484    b       common_exceptionThrown
2485
2486
2487/* ------------------------------ */
2488    .balign 64
2489.L_OP_IGET_BYTE: /* 0x56 */
2490/* File: armv5te/OP_IGET_BYTE.S */
2491@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" }
2492/* File: armv5te/OP_IGET.S */
2493    /*
2494     * General 32-bit instance field get.
2495     *
2496     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2497     */
2498    /* op vA, vB, field@CCCC */
2499    mov     r0, rINST, lsr #12          @ r0<- B
2500    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2501    FETCH(r1, 1)                        @ r1<- field ref CCCC
2502    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2503    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2504    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2505    cmp     r0, #0                      @ is resolved entry null?
2506    bne     .LOP_IGET_BYTE_finish          @ no, already resolved
25078:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2508    EXPORT_PC()                         @ resolve() could throw
2509    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2510    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2511    cmp     r0, #0
2512    bne     .LOP_IGET_BYTE_finish
2513    b       common_exceptionThrown
2514
2515
2516/* ------------------------------ */
2517    .balign 64
2518.L_OP_IGET_CHAR: /* 0x57 */
2519/* File: armv5te/OP_IGET_CHAR.S */
2520@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" }
2521/* File: armv5te/OP_IGET.S */
2522    /*
2523     * General 32-bit instance field get.
2524     *
2525     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2526     */
2527    /* op vA, vB, field@CCCC */
2528    mov     r0, rINST, lsr #12          @ r0<- B
2529    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2530    FETCH(r1, 1)                        @ r1<- field ref CCCC
2531    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2532    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2533    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2534    cmp     r0, #0                      @ is resolved entry null?
2535    bne     .LOP_IGET_CHAR_finish          @ no, already resolved
25368:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2537    EXPORT_PC()                         @ resolve() could throw
2538    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2539    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2540    cmp     r0, #0
2541    bne     .LOP_IGET_CHAR_finish
2542    b       common_exceptionThrown
2543
2544
2545/* ------------------------------ */
2546    .balign 64
2547.L_OP_IGET_SHORT: /* 0x58 */
2548/* File: armv5te/OP_IGET_SHORT.S */
2549@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" }
2550/* File: armv5te/OP_IGET.S */
2551    /*
2552     * General 32-bit instance field get.
2553     *
2554     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2555     */
2556    /* op vA, vB, field@CCCC */
2557    mov     r0, rINST, lsr #12          @ r0<- B
2558    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2559    FETCH(r1, 1)                        @ r1<- field ref CCCC
2560    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2561    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2562    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2563    cmp     r0, #0                      @ is resolved entry null?
2564    bne     .LOP_IGET_SHORT_finish          @ no, already resolved
25658:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2566    EXPORT_PC()                         @ resolve() could throw
2567    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2568    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2569    cmp     r0, #0
2570    bne     .LOP_IGET_SHORT_finish
2571    b       common_exceptionThrown
2572
2573
2574/* ------------------------------ */
2575    .balign 64
2576.L_OP_IPUT: /* 0x59 */
2577/* File: armv5te/OP_IPUT.S */
2578    /*
2579     * General 32-bit instance field put.
2580     *
2581     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2582     */
2583    /* op vA, vB, field@CCCC */
2584    mov     r0, rINST, lsr #12          @ r0<- B
2585    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2586    FETCH(r1, 1)                        @ r1<- field ref CCCC
2587    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2588    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2589    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2590    cmp     r0, #0                      @ is resolved entry null?
2591    bne     .LOP_IPUT_finish          @ no, already resolved
25928:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2593    EXPORT_PC()                         @ resolve() could throw
2594    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2595    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2596    cmp     r0, #0                      @ success?
2597    bne     .LOP_IPUT_finish          @ yes, finish up
2598    b       common_exceptionThrown
2599
2600/* ------------------------------ */
2601    .balign 64
2602.L_OP_IPUT_WIDE: /* 0x5a */
2603/* File: armv5te/OP_IPUT_WIDE.S */
2604    /* iput-wide vA, vB, field@CCCC */
2605    mov     r0, rINST, lsr #12          @ r0<- B
2606    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2607    FETCH(r1, 1)                        @ r1<- field ref CCCC
2608    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2609    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2610    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2611    cmp     r0, #0                      @ is resolved entry null?
2612    bne     .LOP_IPUT_WIDE_finish          @ no, already resolved
26138:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2614    EXPORT_PC()                         @ resolve() could throw
2615    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2616    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2617    cmp     r0, #0                      @ success?
2618    bne     .LOP_IPUT_WIDE_finish          @ yes, finish up
2619    b       common_exceptionThrown
2620
2621/* ------------------------------ */
2622    .balign 64
2623.L_OP_IPUT_OBJECT: /* 0x5b */
2624/* File: armv5te/OP_IPUT_OBJECT.S */
2625    /*
2626     * 32-bit instance field put.
2627     *
2628     * for: iput-object, iput-object-volatile
2629     */
2630    /* op vA, vB, field@CCCC */
2631    mov     r0, rINST, lsr #12          @ r0<- B
2632    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2633    FETCH(r1, 1)                        @ r1<- field ref CCCC
2634    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2635    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2636    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2637    cmp     r0, #0                      @ is resolved entry null?
2638    bne     .LOP_IPUT_OBJECT_finish          @ no, already resolved
26398:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2640    EXPORT_PC()                         @ resolve() could throw
2641    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2642    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2643    cmp     r0, #0                      @ success?
2644    bne     .LOP_IPUT_OBJECT_finish          @ yes, finish up
2645    b       common_exceptionThrown
2646
2647/* ------------------------------ */
2648    .balign 64
2649.L_OP_IPUT_BOOLEAN: /* 0x5c */
2650/* File: armv5te/OP_IPUT_BOOLEAN.S */
2651@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" }
2652/* File: armv5te/OP_IPUT.S */
2653    /*
2654     * General 32-bit instance field put.
2655     *
2656     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2657     */
2658    /* op vA, vB, field@CCCC */
2659    mov     r0, rINST, lsr #12          @ r0<- B
2660    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2661    FETCH(r1, 1)                        @ r1<- field ref CCCC
2662    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2663    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2664    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2665    cmp     r0, #0                      @ is resolved entry null?
2666    bne     .LOP_IPUT_BOOLEAN_finish          @ no, already resolved
26678:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2668    EXPORT_PC()                         @ resolve() could throw
2669    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2670    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2671    cmp     r0, #0                      @ success?
2672    bne     .LOP_IPUT_BOOLEAN_finish          @ yes, finish up
2673    b       common_exceptionThrown
2674
2675
2676/* ------------------------------ */
2677    .balign 64
2678.L_OP_IPUT_BYTE: /* 0x5d */
2679/* File: armv5te/OP_IPUT_BYTE.S */
2680@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" }
2681/* File: armv5te/OP_IPUT.S */
2682    /*
2683     * General 32-bit instance field put.
2684     *
2685     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2686     */
2687    /* op vA, vB, field@CCCC */
2688    mov     r0, rINST, lsr #12          @ r0<- B
2689    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2690    FETCH(r1, 1)                        @ r1<- field ref CCCC
2691    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2692    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2693    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2694    cmp     r0, #0                      @ is resolved entry null?
2695    bne     .LOP_IPUT_BYTE_finish          @ no, already resolved
26968:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2697    EXPORT_PC()                         @ resolve() could throw
2698    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2699    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2700    cmp     r0, #0                      @ success?
2701    bne     .LOP_IPUT_BYTE_finish          @ yes, finish up
2702    b       common_exceptionThrown
2703
2704
2705/* ------------------------------ */
2706    .balign 64
2707.L_OP_IPUT_CHAR: /* 0x5e */
2708/* File: armv5te/OP_IPUT_CHAR.S */
2709@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" }
2710/* File: armv5te/OP_IPUT.S */
2711    /*
2712     * General 32-bit instance field put.
2713     *
2714     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2715     */
2716    /* op vA, vB, field@CCCC */
2717    mov     r0, rINST, lsr #12          @ r0<- B
2718    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2719    FETCH(r1, 1)                        @ r1<- field ref CCCC
2720    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2721    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2722    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2723    cmp     r0, #0                      @ is resolved entry null?
2724    bne     .LOP_IPUT_CHAR_finish          @ no, already resolved
27258:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2726    EXPORT_PC()                         @ resolve() could throw
2727    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2728    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2729    cmp     r0, #0                      @ success?
2730    bne     .LOP_IPUT_CHAR_finish          @ yes, finish up
2731    b       common_exceptionThrown
2732
2733
2734/* ------------------------------ */
2735    .balign 64
2736.L_OP_IPUT_SHORT: /* 0x5f */
2737/* File: armv5te/OP_IPUT_SHORT.S */
2738@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" }
2739/* File: armv5te/OP_IPUT.S */
2740    /*
2741     * General 32-bit instance field put.
2742     *
2743     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2744     */
2745    /* op vA, vB, field@CCCC */
2746    mov     r0, rINST, lsr #12          @ r0<- B
2747    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2748    FETCH(r1, 1)                        @ r1<- field ref CCCC
2749    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2750    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2751    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2752    cmp     r0, #0                      @ is resolved entry null?
2753    bne     .LOP_IPUT_SHORT_finish          @ no, already resolved
27548:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2755    EXPORT_PC()                         @ resolve() could throw
2756    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2757    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2758    cmp     r0, #0                      @ success?
2759    bne     .LOP_IPUT_SHORT_finish          @ yes, finish up
2760    b       common_exceptionThrown
2761
2762
2763/* ------------------------------ */
2764    .balign 64
2765.L_OP_SGET: /* 0x60 */
2766/* File: armv5te/OP_SGET.S */
2767    /*
2768     * General 32-bit SGET handler.
2769     *
2770     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2771     */
2772    /* op vAA, field@BBBB */
2773    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2774    FETCH(r1, 1)                        @ r1<- field ref BBBB
2775    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2776    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2777    cmp     r0, #0                      @ is resolved entry null?
2778    beq     .LOP_SGET_resolve         @ yes, do resolve
2779.LOP_SGET_finish: @ field ptr in r0
2780    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2781    @ no-op                             @ acquiring load
2782    mov     r2, rINST, lsr #8           @ r2<- AA
2783    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2784    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2785    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2786    GOTO_OPCODE(ip)                     @ jump to next instruction
2787
2788/* ------------------------------ */
2789    .balign 64
2790.L_OP_SGET_WIDE: /* 0x61 */
2791/* File: armv5te/OP_SGET_WIDE.S */
2792    /*
2793     * 64-bit SGET handler.
2794     */
2795    /* sget-wide vAA, field@BBBB */
2796    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2797    FETCH(r1, 1)                        @ r1<- field ref BBBB
2798    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2799    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2800    cmp     r0, #0                      @ is resolved entry null?
2801    beq     .LOP_SGET_WIDE_resolve         @ yes, do resolve
2802.LOP_SGET_WIDE_finish:
2803    mov     r9, rINST, lsr #8           @ r9<- AA
2804    .if 0
2805    add     r0, r0, #offStaticField_value @ r0<- pointer to data
2806    bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
2807    .else
2808    ldrd    r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
2809    .endif
2810    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2811    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2812    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
2813    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2814    GOTO_OPCODE(ip)                     @ jump to next instruction
2815
2816/* ------------------------------ */
2817    .balign 64
2818.L_OP_SGET_OBJECT: /* 0x62 */
2819/* File: armv5te/OP_SGET_OBJECT.S */
2820/* File: armv5te/OP_SGET.S */
2821    /*
2822     * General 32-bit SGET handler.
2823     *
2824     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2825     */
2826    /* op vAA, field@BBBB */
2827    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2828    FETCH(r1, 1)                        @ r1<- field ref BBBB
2829    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2830    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2831    cmp     r0, #0                      @ is resolved entry null?
2832    beq     .LOP_SGET_OBJECT_resolve         @ yes, do resolve
2833.LOP_SGET_OBJECT_finish: @ field ptr in r0
2834    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2835    @ no-op                             @ acquiring load
2836    mov     r2, rINST, lsr #8           @ r2<- AA
2837    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2838    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2839    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2840    GOTO_OPCODE(ip)                     @ jump to next instruction
2841
2842
2843/* ------------------------------ */
2844    .balign 64
2845.L_OP_SGET_BOOLEAN: /* 0x63 */
2846/* File: armv5te/OP_SGET_BOOLEAN.S */
2847/* File: armv5te/OP_SGET.S */
2848    /*
2849     * General 32-bit SGET handler.
2850     *
2851     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2852     */
2853    /* op vAA, field@BBBB */
2854    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2855    FETCH(r1, 1)                        @ r1<- field ref BBBB
2856    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2857    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2858    cmp     r0, #0                      @ is resolved entry null?
2859    beq     .LOP_SGET_BOOLEAN_resolve         @ yes, do resolve
2860.LOP_SGET_BOOLEAN_finish: @ field ptr in r0
2861    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2862    @ no-op                             @ acquiring load
2863    mov     r2, rINST, lsr #8           @ r2<- AA
2864    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2865    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2866    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2867    GOTO_OPCODE(ip)                     @ jump to next instruction
2868
2869
2870/* ------------------------------ */
2871    .balign 64
2872.L_OP_SGET_BYTE: /* 0x64 */
2873/* File: armv5te/OP_SGET_BYTE.S */
2874/* File: armv5te/OP_SGET.S */
2875    /*
2876     * General 32-bit SGET handler.
2877     *
2878     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2879     */
2880    /* op vAA, field@BBBB */
2881    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2882    FETCH(r1, 1)                        @ r1<- field ref BBBB
2883    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2884    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2885    cmp     r0, #0                      @ is resolved entry null?
2886    beq     .LOP_SGET_BYTE_resolve         @ yes, do resolve
2887.LOP_SGET_BYTE_finish: @ field ptr in r0
2888    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2889    @ no-op                             @ acquiring load
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_CHAR: /* 0x65 */
2900/* File: armv5te/OP_SGET_CHAR.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_CHAR_resolve         @ yes, do resolve
2914.LOP_SGET_CHAR_finish: @ field ptr in r0
2915    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2916    @ no-op                             @ acquiring load
2917    mov     r2, rINST, lsr #8           @ r2<- AA
2918    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2919    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2920    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2921    GOTO_OPCODE(ip)                     @ jump to next instruction
2922
2923
2924/* ------------------------------ */
2925    .balign 64
2926.L_OP_SGET_SHORT: /* 0x66 */
2927/* File: armv5te/OP_SGET_SHORT.S */
2928/* File: armv5te/OP_SGET.S */
2929    /*
2930     * General 32-bit SGET handler.
2931     *
2932     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2933     */
2934    /* op vAA, field@BBBB */
2935    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2936    FETCH(r1, 1)                        @ r1<- field ref BBBB
2937    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2938    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2939    cmp     r0, #0                      @ is resolved entry null?
2940    beq     .LOP_SGET_SHORT_resolve         @ yes, do resolve
2941.LOP_SGET_SHORT_finish: @ field ptr in r0
2942    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2943    @ no-op                             @ acquiring load
2944    mov     r2, rINST, lsr #8           @ r2<- AA
2945    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2946    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2947    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2948    GOTO_OPCODE(ip)                     @ jump to next instruction
2949
2950
2951/* ------------------------------ */
2952    .balign 64
2953.L_OP_SPUT: /* 0x67 */
2954/* File: armv5te/OP_SPUT.S */
2955    /*
2956     * General 32-bit SPUT handler.
2957     *
2958     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
2959     */
2960    /* op vAA, field@BBBB */
2961    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2962    FETCH(r1, 1)                        @ r1<- field ref BBBB
2963    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2964    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2965    cmp     r0, #0                      @ is resolved entry null?
2966    beq     .LOP_SPUT_resolve         @ yes, do resolve
2967.LOP_SPUT_finish:   @ field ptr in r0
2968    mov     r2, rINST, lsr #8           @ r2<- AA
2969    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2970    GET_VREG(r1, r2)                    @ r1<- fp[AA]
2971    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2972    @ no-op                             @ releasing store
2973    str     r1, [r0, #offStaticField_value] @ field<- vAA
2974    GOTO_OPCODE(ip)                     @ jump to next instruction
2975
2976/* ------------------------------ */
2977    .balign 64
2978.L_OP_SPUT_WIDE: /* 0x68 */
2979/* File: armv5te/OP_SPUT_WIDE.S */
2980    /*
2981     * 64-bit SPUT handler.
2982     */
2983    /* sput-wide vAA, field@BBBB */
2984    ldr     r0, [rGLUE, #offGlue_methodClassDex]  @ r0<- DvmDex
2985    FETCH(r1, 1)                        @ r1<- field ref BBBB
2986    ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
2987    mov     r9, rINST, lsr #8           @ r9<- AA
2988    ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
2989    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2990    cmp     r2, #0                      @ is resolved entry null?
2991    beq     .LOP_SPUT_WIDE_resolve         @ yes, do resolve
2992.LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9
2993    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2994    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
2995    GET_INST_OPCODE(r10)                @ extract opcode from rINST
2996    .if 0
2997    add     r2, r2, #offStaticField_value @ r2<- pointer to data
2998    bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
2999    .else
3000    strd    r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
3001    .endif
3002    GOTO_OPCODE(r10)                    @ jump to next instruction
3003
3004/* ------------------------------ */
3005    .balign 64
3006.L_OP_SPUT_OBJECT: /* 0x69 */
3007/* File: armv5te/OP_SPUT_OBJECT.S */
3008    /*
3009     * 32-bit SPUT handler for objects
3010     *
3011     * for: sput-object, sput-object-volatile
3012     */
3013    /* op vAA, field@BBBB */
3014    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3015    FETCH(r1, 1)                        @ r1<- field ref BBBB
3016    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3017    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3018    cmp     r0, #0                      @ is resolved entry null?
3019    bne     .LOP_SPUT_OBJECT_finish          @ no, continue
3020    ldr     r9, [rGLUE, #offGlue_method]    @ r9<- current method
3021    EXPORT_PC()                         @ resolve() could throw, so export now
3022    ldr     r0, [r9, #offMethod_clazz]  @ r0<- method->clazz
3023    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
3024    cmp     r0, #0                      @ success?
3025    bne     .LOP_SPUT_OBJECT_finish          @ yes, finish
3026    b       common_exceptionThrown      @ no, handle exception
3027
3028
3029/* ------------------------------ */
3030    .balign 64
3031.L_OP_SPUT_BOOLEAN: /* 0x6a */
3032/* File: armv5te/OP_SPUT_BOOLEAN.S */
3033/* File: armv5te/OP_SPUT.S */
3034    /*
3035     * General 32-bit SPUT handler.
3036     *
3037     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3038     */
3039    /* op vAA, field@BBBB */
3040    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3041    FETCH(r1, 1)                        @ r1<- field ref BBBB
3042    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3043    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3044    cmp     r0, #0                      @ is resolved entry null?
3045    beq     .LOP_SPUT_BOOLEAN_resolve         @ yes, do resolve
3046.LOP_SPUT_BOOLEAN_finish:   @ field ptr in r0
3047    mov     r2, rINST, lsr #8           @ r2<- AA
3048    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3049    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3050    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3051    @ no-op                             @ releasing store
3052    str     r1, [r0, #offStaticField_value] @ field<- vAA
3053    GOTO_OPCODE(ip)                     @ jump to next instruction
3054
3055
3056/* ------------------------------ */
3057    .balign 64
3058.L_OP_SPUT_BYTE: /* 0x6b */
3059/* File: armv5te/OP_SPUT_BYTE.S */
3060/* File: armv5te/OP_SPUT.S */
3061    /*
3062     * General 32-bit SPUT handler.
3063     *
3064     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3065     */
3066    /* op vAA, field@BBBB */
3067    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3068    FETCH(r1, 1)                        @ r1<- field ref BBBB
3069    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3070    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3071    cmp     r0, #0                      @ is resolved entry null?
3072    beq     .LOP_SPUT_BYTE_resolve         @ yes, do resolve
3073.LOP_SPUT_BYTE_finish:   @ field ptr in r0
3074    mov     r2, rINST, lsr #8           @ r2<- AA
3075    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3076    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3077    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3078    @ no-op                             @ releasing store
3079    str     r1, [r0, #offStaticField_value] @ field<- vAA
3080    GOTO_OPCODE(ip)                     @ jump to next instruction
3081
3082
3083/* ------------------------------ */
3084    .balign 64
3085.L_OP_SPUT_CHAR: /* 0x6c */
3086/* File: armv5te/OP_SPUT_CHAR.S */
3087/* File: armv5te/OP_SPUT.S */
3088    /*
3089     * General 32-bit SPUT handler.
3090     *
3091     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3092     */
3093    /* op vAA, field@BBBB */
3094    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3095    FETCH(r1, 1)                        @ r1<- field ref BBBB
3096    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3097    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3098    cmp     r0, #0                      @ is resolved entry null?
3099    beq     .LOP_SPUT_CHAR_resolve         @ yes, do resolve
3100.LOP_SPUT_CHAR_finish:   @ field ptr in r0
3101    mov     r2, rINST, lsr #8           @ r2<- AA
3102    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3103    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3104    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3105    @ no-op                             @ releasing store
3106    str     r1, [r0, #offStaticField_value] @ field<- vAA
3107    GOTO_OPCODE(ip)                     @ jump to next instruction
3108
3109
3110/* ------------------------------ */
3111    .balign 64
3112.L_OP_SPUT_SHORT: /* 0x6d */
3113/* File: armv5te/OP_SPUT_SHORT.S */
3114/* File: armv5te/OP_SPUT.S */
3115    /*
3116     * General 32-bit SPUT handler.
3117     *
3118     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3119     */
3120    /* op vAA, field@BBBB */
3121    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3122    FETCH(r1, 1)                        @ r1<- field ref BBBB
3123    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3124    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3125    cmp     r0, #0                      @ is resolved entry null?
3126    beq     .LOP_SPUT_SHORT_resolve         @ yes, do resolve
3127.LOP_SPUT_SHORT_finish:   @ field ptr in r0
3128    mov     r2, rINST, lsr #8           @ r2<- AA
3129    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3130    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3131    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3132    @ no-op                             @ releasing store
3133    str     r1, [r0, #offStaticField_value] @ field<- vAA
3134    GOTO_OPCODE(ip)                     @ jump to next instruction
3135
3136
3137/* ------------------------------ */
3138    .balign 64
3139.L_OP_INVOKE_VIRTUAL: /* 0x6e */
3140/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3141    /*
3142     * Handle a virtual method call.
3143     *
3144     * for: invoke-virtual, invoke-virtual/range
3145     */
3146    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3147    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3148    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3149    FETCH(r1, 1)                        @ r1<- BBBB
3150    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3151    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3152    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3153    .if     (!0)
3154    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3155    .endif
3156    cmp     r0, #0                      @ already resolved?
3157    EXPORT_PC()                         @ must export for invoke
3158    bne     .LOP_INVOKE_VIRTUAL_continue        @ yes, continue on
3159    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3160    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3161    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3162    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3163    cmp     r0, #0                      @ got null?
3164    bne     .LOP_INVOKE_VIRTUAL_continue        @ no, continue
3165    b       common_exceptionThrown      @ yes, handle exception
3166
3167/* ------------------------------ */
3168    .balign 64
3169.L_OP_INVOKE_SUPER: /* 0x6f */
3170/* File: armv5te/OP_INVOKE_SUPER.S */
3171    /*
3172     * Handle a "super" method call.
3173     *
3174     * for: invoke-super, invoke-super/range
3175     */
3176    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3177    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3178    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3179    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3180    .if     (!0)
3181    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3182    .endif
3183    FETCH(r1, 1)                        @ r1<- BBBB
3184    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3185    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3186    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3187    cmp     r2, #0                      @ null "this"?
3188    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3189    beq     common_errNullObject        @ null "this", throw exception
3190    cmp     r0, #0                      @ already resolved?
3191    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3192    EXPORT_PC()                         @ must export for invoke
3193    bne     .LOP_INVOKE_SUPER_continue        @ resolved, continue on
3194    b       .LOP_INVOKE_SUPER_resolve         @ do resolve now
3195
3196/* ------------------------------ */
3197    .balign 64
3198.L_OP_INVOKE_DIRECT: /* 0x70 */
3199/* File: armv5te/OP_INVOKE_DIRECT.S */
3200    /*
3201     * Handle a direct method call.
3202     *
3203     * (We could defer the "is 'this' pointer null" test to the common
3204     * method invocation code, and use a flag to indicate that static
3205     * calls don't count.  If we do this as part of copying the arguments
3206     * out we could avoiding loading the first arg twice.)
3207     *
3208     * for: invoke-direct, invoke-direct/range
3209     */
3210    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3211    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3212    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3213    FETCH(r1, 1)                        @ r1<- BBBB
3214    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3215    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3216    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3217    .if     (!0)
3218    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3219    .endif
3220    cmp     r0, #0                      @ already resolved?
3221    EXPORT_PC()                         @ must export for invoke
3222    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3223    beq     .LOP_INVOKE_DIRECT_resolve         @ not resolved, do it now
3224.LOP_INVOKE_DIRECT_finish:
3225    cmp     r2, #0                      @ null "this" ref?
3226    bne     common_invokeMethodNoRange   @ no, continue on
3227    b       common_errNullObject        @ yes, throw exception
3228
3229/* ------------------------------ */
3230    .balign 64
3231.L_OP_INVOKE_STATIC: /* 0x71 */
3232/* File: armv5te/OP_INVOKE_STATIC.S */
3233    /*
3234     * Handle a static method call.
3235     *
3236     * for: invoke-static, invoke-static/range
3237     */
3238    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3239    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3240    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3241    FETCH(r1, 1)                        @ r1<- BBBB
3242    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3243    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3244    cmp     r0, #0                      @ already resolved?
3245    EXPORT_PC()                         @ must export for invoke
3246    bne     common_invokeMethodNoRange @ yes, continue on
32470:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3248    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3249    mov     r2, #METHOD_STATIC          @ resolver method type
3250    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3251    cmp     r0, #0                      @ got null?
3252    bne     common_invokeMethodNoRange @ no, continue
3253    b       common_exceptionThrown      @ yes, handle exception
3254
3255/* ------------------------------ */
3256    .balign 64
3257.L_OP_INVOKE_INTERFACE: /* 0x72 */
3258/* File: armv5te/OP_INVOKE_INTERFACE.S */
3259    /*
3260     * Handle an interface method call.
3261     *
3262     * for: invoke-interface, invoke-interface/range
3263     */
3264    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3265    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3266    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3267    FETCH(r1, 1)                        @ r1<- BBBB
3268    .if     (!0)
3269    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3270    .endif
3271    EXPORT_PC()                         @ must export for invoke
3272    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3273    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3274    cmp     r0, #0                      @ null obj?
3275    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3276    beq     common_errNullObject        @ yes, fail
3277    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3278    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3279    cmp     r0, #0                      @ failed?
3280    beq     common_exceptionThrown      @ yes, handle exception
3281    b       common_invokeMethodNoRange @ jump to common handler
3282
3283/* ------------------------------ */
3284    .balign 64
3285.L_OP_UNUSED_73: /* 0x73 */
3286/* File: armv5te/OP_UNUSED_73.S */
3287/* File: armv5te/unused.S */
3288    bl      common_abort
3289
3290
3291/* ------------------------------ */
3292    .balign 64
3293.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
3294/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */
3295/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3296    /*
3297     * Handle a virtual method call.
3298     *
3299     * for: invoke-virtual, invoke-virtual/range
3300     */
3301    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3302    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3303    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3304    FETCH(r1, 1)                        @ r1<- BBBB
3305    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3306    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3307    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3308    .if     (!1)
3309    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3310    .endif
3311    cmp     r0, #0                      @ already resolved?
3312    EXPORT_PC()                         @ must export for invoke
3313    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ yes, continue on
3314    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3315    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3316    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3317    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3318    cmp     r0, #0                      @ got null?
3319    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ no, continue
3320    b       common_exceptionThrown      @ yes, handle exception
3321
3322
3323/* ------------------------------ */
3324    .balign 64
3325.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
3326/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */
3327/* File: armv5te/OP_INVOKE_SUPER.S */
3328    /*
3329     * Handle a "super" method call.
3330     *
3331     * for: invoke-super, invoke-super/range
3332     */
3333    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3334    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3335    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3336    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3337    .if     (!1)
3338    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3339    .endif
3340    FETCH(r1, 1)                        @ r1<- BBBB
3341    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3342    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3343    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3344    cmp     r2, #0                      @ null "this"?
3345    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3346    beq     common_errNullObject        @ null "this", throw exception
3347    cmp     r0, #0                      @ already resolved?
3348    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3349    EXPORT_PC()                         @ must export for invoke
3350    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ resolved, continue on
3351    b       .LOP_INVOKE_SUPER_RANGE_resolve         @ do resolve now
3352
3353
3354/* ------------------------------ */
3355    .balign 64
3356.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
3357/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */
3358/* File: armv5te/OP_INVOKE_DIRECT.S */
3359    /*
3360     * Handle a direct method call.
3361     *
3362     * (We could defer the "is 'this' pointer null" test to the common
3363     * method invocation code, and use a flag to indicate that static
3364     * calls don't count.  If we do this as part of copying the arguments
3365     * out we could avoiding loading the first arg twice.)
3366     *
3367     * for: invoke-direct, invoke-direct/range
3368     */
3369    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3370    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3371    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3372    FETCH(r1, 1)                        @ r1<- BBBB
3373    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3374    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3375    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3376    .if     (!1)
3377    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3378    .endif
3379    cmp     r0, #0                      @ already resolved?
3380    EXPORT_PC()                         @ must export for invoke
3381    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3382    beq     .LOP_INVOKE_DIRECT_RANGE_resolve         @ not resolved, do it now
3383.LOP_INVOKE_DIRECT_RANGE_finish:
3384    cmp     r2, #0                      @ null "this" ref?
3385    bne     common_invokeMethodRange   @ no, continue on
3386    b       common_errNullObject        @ yes, throw exception
3387
3388
3389/* ------------------------------ */
3390    .balign 64
3391.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
3392/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */
3393/* File: armv5te/OP_INVOKE_STATIC.S */
3394    /*
3395     * Handle a static method call.
3396     *
3397     * for: invoke-static, invoke-static/range
3398     */
3399    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3400    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3401    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3402    FETCH(r1, 1)                        @ r1<- BBBB
3403    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3404    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3405    cmp     r0, #0                      @ already resolved?
3406    EXPORT_PC()                         @ must export for invoke
3407    bne     common_invokeMethodRange @ yes, continue on
34080:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3409    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3410    mov     r2, #METHOD_STATIC          @ resolver method type
3411    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3412    cmp     r0, #0                      @ got null?
3413    bne     common_invokeMethodRange @ no, continue
3414    b       common_exceptionThrown      @ yes, handle exception
3415
3416
3417/* ------------------------------ */
3418    .balign 64
3419.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
3420/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */
3421/* File: armv5te/OP_INVOKE_INTERFACE.S */
3422    /*
3423     * Handle an interface method call.
3424     *
3425     * for: invoke-interface, invoke-interface/range
3426     */
3427    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3428    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3429    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3430    FETCH(r1, 1)                        @ r1<- BBBB
3431    .if     (!1)
3432    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3433    .endif
3434    EXPORT_PC()                         @ must export for invoke
3435    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3436    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3437    cmp     r0, #0                      @ null obj?
3438    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3439    beq     common_errNullObject        @ yes, fail
3440    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3441    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3442    cmp     r0, #0                      @ failed?
3443    beq     common_exceptionThrown      @ yes, handle exception
3444    b       common_invokeMethodRange @ jump to common handler
3445
3446
3447/* ------------------------------ */
3448    .balign 64
3449.L_OP_UNUSED_79: /* 0x79 */
3450/* File: armv5te/OP_UNUSED_79.S */
3451/* File: armv5te/unused.S */
3452    bl      common_abort
3453
3454
3455/* ------------------------------ */
3456    .balign 64
3457.L_OP_UNUSED_7A: /* 0x7a */
3458/* File: armv5te/OP_UNUSED_7A.S */
3459/* File: armv5te/unused.S */
3460    bl      common_abort
3461
3462
3463/* ------------------------------ */
3464    .balign 64
3465.L_OP_NEG_INT: /* 0x7b */
3466/* File: armv5te/OP_NEG_INT.S */
3467/* File: armv5te/unop.S */
3468    /*
3469     * Generic 32-bit unary operation.  Provide an "instr" line that
3470     * specifies an instruction that performs "result = op r0".
3471     * This could be an ARM instruction or a function call.
3472     *
3473     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3474     *      int-to-byte, int-to-char, int-to-short
3475     */
3476    /* unop vA, vB */
3477    mov     r3, rINST, lsr #12          @ r3<- B
3478    mov     r9, rINST, lsr #8           @ r9<- A+
3479    GET_VREG(r0, r3)                    @ r0<- vB
3480    and     r9, r9, #15
3481                               @ optional op; may set condition codes
3482    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3483    rsb     r0, r0, #0                              @ r0<- op, r0-r3 changed
3484    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3485    SET_VREG(r0, r9)                    @ vAA<- r0
3486    GOTO_OPCODE(ip)                     @ jump to next instruction
3487    /* 9-10 instructions */
3488
3489
3490/* ------------------------------ */
3491    .balign 64
3492.L_OP_NOT_INT: /* 0x7c */
3493/* File: armv5te/OP_NOT_INT.S */
3494/* File: armv5te/unop.S */
3495    /*
3496     * Generic 32-bit unary operation.  Provide an "instr" line that
3497     * specifies an instruction that performs "result = op r0".
3498     * This could be an ARM instruction or a function call.
3499     *
3500     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3501     *      int-to-byte, int-to-char, int-to-short
3502     */
3503    /* unop vA, vB */
3504    mov     r3, rINST, lsr #12          @ r3<- B
3505    mov     r9, rINST, lsr #8           @ r9<- A+
3506    GET_VREG(r0, r3)                    @ r0<- vB
3507    and     r9, r9, #15
3508                               @ optional op; may set condition codes
3509    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3510    mvn     r0, r0                              @ r0<- op, r0-r3 changed
3511    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3512    SET_VREG(r0, r9)                    @ vAA<- r0
3513    GOTO_OPCODE(ip)                     @ jump to next instruction
3514    /* 9-10 instructions */
3515
3516
3517/* ------------------------------ */
3518    .balign 64
3519.L_OP_NEG_LONG: /* 0x7d */
3520/* File: armv5te/OP_NEG_LONG.S */
3521/* File: armv5te/unopWide.S */
3522    /*
3523     * Generic 64-bit unary operation.  Provide an "instr" line that
3524     * specifies an instruction that performs "result = op r0/r1".
3525     * This could be an ARM instruction or a function call.
3526     *
3527     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3528     */
3529    /* unop vA, vB */
3530    mov     r9, rINST, lsr #8           @ r9<- A+
3531    mov     r3, rINST, lsr #12          @ r3<- B
3532    and     r9, r9, #15
3533    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3534    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3535    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3536    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3537    rsbs    r0, r0, #0                           @ optional op; may set condition codes
3538    rsc     r1, r1, #0                              @ r0/r1<- op, r2-r3 changed
3539    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3540    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3541    GOTO_OPCODE(ip)                     @ jump to next instruction
3542    /* 12-13 instructions */
3543
3544
3545/* ------------------------------ */
3546    .balign 64
3547.L_OP_NOT_LONG: /* 0x7e */
3548/* File: armv5te/OP_NOT_LONG.S */
3549/* File: armv5te/unopWide.S */
3550    /*
3551     * Generic 64-bit unary operation.  Provide an "instr" line that
3552     * specifies an instruction that performs "result = op r0/r1".
3553     * This could be an ARM instruction or a function call.
3554     *
3555     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3556     */
3557    /* unop vA, vB */
3558    mov     r9, rINST, lsr #8           @ r9<- A+
3559    mov     r3, rINST, lsr #12          @ r3<- B
3560    and     r9, r9, #15
3561    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3562    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3563    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3564    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3565    mvn     r0, r0                           @ optional op; may set condition codes
3566    mvn     r1, r1                              @ r0/r1<- op, r2-r3 changed
3567    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3568    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3569    GOTO_OPCODE(ip)                     @ jump to next instruction
3570    /* 12-13 instructions */
3571
3572
3573/* ------------------------------ */
3574    .balign 64
3575.L_OP_NEG_FLOAT: /* 0x7f */
3576/* File: armv5te/OP_NEG_FLOAT.S */
3577/* File: armv5te/unop.S */
3578    /*
3579     * Generic 32-bit unary operation.  Provide an "instr" line that
3580     * specifies an instruction that performs "result = op r0".
3581     * This could be an ARM instruction or a function call.
3582     *
3583     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3584     *      int-to-byte, int-to-char, int-to-short
3585     */
3586    /* unop vA, vB */
3587    mov     r3, rINST, lsr #12          @ r3<- B
3588    mov     r9, rINST, lsr #8           @ r9<- A+
3589    GET_VREG(r0, r3)                    @ r0<- vB
3590    and     r9, r9, #15
3591                               @ optional op; may set condition codes
3592    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3593    add     r0, r0, #0x80000000                              @ r0<- op, r0-r3 changed
3594    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3595    SET_VREG(r0, r9)                    @ vAA<- r0
3596    GOTO_OPCODE(ip)                     @ jump to next instruction
3597    /* 9-10 instructions */
3598
3599
3600/* ------------------------------ */
3601    .balign 64
3602.L_OP_NEG_DOUBLE: /* 0x80 */
3603/* File: armv5te/OP_NEG_DOUBLE.S */
3604/* File: armv5te/unopWide.S */
3605    /*
3606     * Generic 64-bit unary operation.  Provide an "instr" line that
3607     * specifies an instruction that performs "result = op r0/r1".
3608     * This could be an ARM instruction or a function call.
3609     *
3610     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3611     */
3612    /* unop vA, vB */
3613    mov     r9, rINST, lsr #8           @ r9<- A+
3614    mov     r3, rINST, lsr #12          @ r3<- B
3615    and     r9, r9, #15
3616    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3617    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3618    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3619    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3620                               @ optional op; may set condition codes
3621    add     r1, r1, #0x80000000                              @ r0/r1<- op, r2-r3 changed
3622    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3623    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3624    GOTO_OPCODE(ip)                     @ jump to next instruction
3625    /* 12-13 instructions */
3626
3627
3628/* ------------------------------ */
3629    .balign 64
3630.L_OP_INT_TO_LONG: /* 0x81 */
3631/* File: armv5te/OP_INT_TO_LONG.S */
3632/* File: armv5te/unopWider.S */
3633    /*
3634     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3635     * that specifies an instruction that performs "result = op r0", where
3636     * "result" is a 64-bit quantity in r0/r1.
3637     *
3638     * For: int-to-long, int-to-double, float-to-long, float-to-double
3639     */
3640    /* unop vA, vB */
3641    mov     r9, rINST, lsr #8           @ r9<- A+
3642    mov     r3, rINST, lsr #12          @ r3<- B
3643    and     r9, r9, #15
3644    GET_VREG(r0, r3)                    @ r0<- vB
3645    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3646                               @ optional op; may set condition codes
3647    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3648    mov     r1, r0, asr #31                              @ r0<- op, r0-r3 changed
3649    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3650    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3651    GOTO_OPCODE(ip)                     @ jump to next instruction
3652    /* 10-11 instructions */
3653
3654
3655/* ------------------------------ */
3656    .balign 64
3657.L_OP_INT_TO_FLOAT: /* 0x82 */
3658/* File: arm-vfp/OP_INT_TO_FLOAT.S */
3659/* File: arm-vfp/funop.S */
3660    /*
3661     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3662     * line that specifies an instruction that performs "s1 = op s0".
3663     *
3664     * for: int-to-float, float-to-int
3665     */
3666    /* unop vA, vB */
3667    mov     r3, rINST, lsr #12          @ r3<- B
3668    mov     r9, rINST, lsr #8           @ r9<- A+
3669    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3670    flds    s0, [r3]                    @ s0<- vB
3671    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3672    and     r9, r9, #15                 @ r9<- A
3673    fsitos  s1, s0                              @ s1<- op
3674    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3675    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3676    fsts    s1, [r9]                    @ vA<- s1
3677    GOTO_OPCODE(ip)                     @ jump to next instruction
3678
3679
3680/* ------------------------------ */
3681    .balign 64
3682.L_OP_INT_TO_DOUBLE: /* 0x83 */
3683/* File: arm-vfp/OP_INT_TO_DOUBLE.S */
3684/* File: arm-vfp/funopWider.S */
3685    /*
3686     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3687     * "instr" line that specifies an instruction that performs "d0 = op s0".
3688     *
3689     * For: int-to-double, float-to-double
3690     */
3691    /* unop vA, vB */
3692    mov     r3, rINST, lsr #12          @ r3<- B
3693    mov     r9, rINST, lsr #8           @ r9<- A+
3694    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3695    flds    s0, [r3]                    @ s0<- vB
3696    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3697    and     r9, r9, #15                 @ r9<- A
3698    fsitod  d0, s0                              @ d0<- op
3699    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3700    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3701    fstd    d0, [r9]                    @ vA<- d0
3702    GOTO_OPCODE(ip)                     @ jump to next instruction
3703
3704
3705/* ------------------------------ */
3706    .balign 64
3707.L_OP_LONG_TO_INT: /* 0x84 */
3708/* File: armv5te/OP_LONG_TO_INT.S */
3709/* we ignore the high word, making this equivalent to a 32-bit reg move */
3710/* File: armv5te/OP_MOVE.S */
3711    /* for move, move-object, long-to-int */
3712    /* op vA, vB */
3713    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
3714    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
3715    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3716    GET_VREG(r2, r1)                    @ r2<- fp[B]
3717    and     r0, r0, #15
3718    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
3719    SET_VREG(r2, r0)                    @ fp[A]<- r2
3720    GOTO_OPCODE(ip)                     @ execute next instruction
3721
3722
3723/* ------------------------------ */
3724    .balign 64
3725.L_OP_LONG_TO_FLOAT: /* 0x85 */
3726/* File: armv5te/OP_LONG_TO_FLOAT.S */
3727/* File: armv5te/unopNarrower.S */
3728    /*
3729     * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
3730     * that specifies an instruction that performs "result = op r0/r1", where
3731     * "result" is a 32-bit quantity in r0.
3732     *
3733     * For: long-to-float, double-to-int, double-to-float
3734     *
3735     * (This would work for long-to-int, but that instruction is actually
3736     * an exact match for OP_MOVE.)
3737     */
3738    /* unop vA, vB */
3739    mov     r3, rINST, lsr #12          @ r3<- B
3740    mov     r9, rINST, lsr #8           @ r9<- A+
3741    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3742    and     r9, r9, #15
3743    ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
3744    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3745                               @ optional op; may set condition codes
3746    bl      __aeabi_l2f                              @ r0<- op, r0-r3 changed
3747    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3748    SET_VREG(r0, r9)                    @ vA<- r0
3749    GOTO_OPCODE(ip)                     @ jump to next instruction
3750    /* 10-11 instructions */
3751
3752
3753/* ------------------------------ */
3754    .balign 64
3755.L_OP_LONG_TO_DOUBLE: /* 0x86 */
3756/* File: armv5te/OP_LONG_TO_DOUBLE.S */
3757/* File: armv5te/unopWide.S */
3758    /*
3759     * Generic 64-bit unary operation.  Provide an "instr" line that
3760     * specifies an instruction that performs "result = op r0/r1".
3761     * This could be an ARM instruction or a function call.
3762     *
3763     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3764     */
3765    /* unop vA, vB */
3766    mov     r9, rINST, lsr #8           @ r9<- A+
3767    mov     r3, rINST, lsr #12          @ r3<- B
3768    and     r9, r9, #15
3769    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3770    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3771    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3772    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3773                               @ optional op; may set condition codes
3774    bl      __aeabi_l2d                              @ r0/r1<- op, r2-r3 changed
3775    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3776    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3777    GOTO_OPCODE(ip)                     @ jump to next instruction
3778    /* 12-13 instructions */
3779
3780
3781/* ------------------------------ */
3782    .balign 64
3783.L_OP_FLOAT_TO_INT: /* 0x87 */
3784/* File: arm-vfp/OP_FLOAT_TO_INT.S */
3785/* File: arm-vfp/funop.S */
3786    /*
3787     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3788     * line that specifies an instruction that performs "s1 = op s0".
3789     *
3790     * for: int-to-float, float-to-int
3791     */
3792    /* unop vA, vB */
3793    mov     r3, rINST, lsr #12          @ r3<- B
3794    mov     r9, rINST, lsr #8           @ r9<- A+
3795    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3796    flds    s0, [r3]                    @ s0<- vB
3797    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3798    and     r9, r9, #15                 @ r9<- A
3799    ftosizs s1, s0                              @ s1<- op
3800    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3801    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3802    fsts    s1, [r9]                    @ vA<- s1
3803    GOTO_OPCODE(ip)                     @ jump to next instruction
3804
3805
3806/* ------------------------------ */
3807    .balign 64
3808.L_OP_FLOAT_TO_LONG: /* 0x88 */
3809/* File: armv5te/OP_FLOAT_TO_LONG.S */
3810@include "armv5te/unopWider.S" {"instr":"bl      __aeabi_f2lz"}
3811/* File: armv5te/unopWider.S */
3812    /*
3813     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3814     * that specifies an instruction that performs "result = op r0", where
3815     * "result" is a 64-bit quantity in r0/r1.
3816     *
3817     * For: int-to-long, int-to-double, float-to-long, float-to-double
3818     */
3819    /* unop vA, vB */
3820    mov     r9, rINST, lsr #8           @ r9<- A+
3821    mov     r3, rINST, lsr #12          @ r3<- B
3822    and     r9, r9, #15
3823    GET_VREG(r0, r3)                    @ r0<- vB
3824    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3825                               @ optional op; may set condition codes
3826    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3827    bl      f2l_doconv                              @ r0<- op, r0-r3 changed
3828    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3829    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3830    GOTO_OPCODE(ip)                     @ jump to next instruction
3831    /* 10-11 instructions */
3832
3833
3834
3835/* ------------------------------ */
3836    .balign 64
3837.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
3838/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */
3839/* File: arm-vfp/funopWider.S */
3840    /*
3841     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3842     * "instr" line that specifies an instruction that performs "d0 = op s0".
3843     *
3844     * For: int-to-double, float-to-double
3845     */
3846    /* unop vA, vB */
3847    mov     r3, rINST, lsr #12          @ r3<- B
3848    mov     r9, rINST, lsr #8           @ r9<- A+
3849    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3850    flds    s0, [r3]                    @ s0<- vB
3851    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3852    and     r9, r9, #15                 @ r9<- A
3853    fcvtds  d0, s0                              @ d0<- op
3854    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3855    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3856    fstd    d0, [r9]                    @ vA<- d0
3857    GOTO_OPCODE(ip)                     @ jump to next instruction
3858
3859
3860/* ------------------------------ */
3861    .balign 64
3862.L_OP_DOUBLE_TO_INT: /* 0x8a */
3863/* File: arm-vfp/OP_DOUBLE_TO_INT.S */
3864/* File: arm-vfp/funopNarrower.S */
3865    /*
3866     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3867     * "instr" line that specifies an instruction that performs "s0 = op d0".
3868     *
3869     * For: double-to-int, double-to-float
3870     */
3871    /* unop vA, vB */
3872    mov     r3, rINST, lsr #12          @ r3<- B
3873    mov     r9, rINST, lsr #8           @ r9<- A+
3874    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3875    fldd    d0, [r3]                    @ d0<- vB
3876    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3877    and     r9, r9, #15                 @ r9<- A
3878    ftosizd  s0, d0                              @ s0<- op
3879    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3880    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3881    fsts    s0, [r9]                    @ vA<- s0
3882    GOTO_OPCODE(ip)                     @ jump to next instruction
3883
3884
3885/* ------------------------------ */
3886    .balign 64
3887.L_OP_DOUBLE_TO_LONG: /* 0x8b */
3888/* File: armv5te/OP_DOUBLE_TO_LONG.S */
3889@include "armv5te/unopWide.S" {"instr":"bl      __aeabi_d2lz"}
3890/* File: armv5te/unopWide.S */
3891    /*
3892     * Generic 64-bit unary operation.  Provide an "instr" line that
3893     * specifies an instruction that performs "result = op r0/r1".
3894     * This could be an ARM instruction or a function call.
3895     *
3896     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3897     */
3898    /* unop vA, vB */
3899    mov     r9, rINST, lsr #8           @ r9<- A+
3900    mov     r3, rINST, lsr #12          @ r3<- B
3901    and     r9, r9, #15
3902    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3903    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3904    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3905    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3906                               @ optional op; may set condition codes
3907    bl      d2l_doconv                              @ r0/r1<- op, r2-r3 changed
3908    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3909    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3910    GOTO_OPCODE(ip)                     @ jump to next instruction
3911    /* 12-13 instructions */
3912
3913
3914
3915/* ------------------------------ */
3916    .balign 64
3917.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
3918/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */
3919/* File: arm-vfp/funopNarrower.S */
3920    /*
3921     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3922     * "instr" line that specifies an instruction that performs "s0 = op d0".
3923     *
3924     * For: double-to-int, double-to-float
3925     */
3926    /* unop vA, vB */
3927    mov     r3, rINST, lsr #12          @ r3<- B
3928    mov     r9, rINST, lsr #8           @ r9<- A+
3929    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3930    fldd    d0, [r3]                    @ d0<- vB
3931    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3932    and     r9, r9, #15                 @ r9<- A
3933    fcvtsd  s0, d0                              @ s0<- op
3934    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3935    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3936    fsts    s0, [r9]                    @ vA<- s0
3937    GOTO_OPCODE(ip)                     @ jump to next instruction
3938
3939
3940/* ------------------------------ */
3941    .balign 64
3942.L_OP_INT_TO_BYTE: /* 0x8d */
3943/* File: armv5te/OP_INT_TO_BYTE.S */
3944/* File: armv5te/unop.S */
3945    /*
3946     * Generic 32-bit unary operation.  Provide an "instr" line that
3947     * specifies an instruction that performs "result = op r0".
3948     * This could be an ARM instruction or a function call.
3949     *
3950     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3951     *      int-to-byte, int-to-char, int-to-short
3952     */
3953    /* unop vA, vB */
3954    mov     r3, rINST, lsr #12          @ r3<- B
3955    mov     r9, rINST, lsr #8           @ r9<- A+
3956    GET_VREG(r0, r3)                    @ r0<- vB
3957    and     r9, r9, #15
3958    mov     r0, r0, asl #24                           @ optional op; may set condition codes
3959    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3960    mov     r0, r0, asr #24                              @ r0<- op, r0-r3 changed
3961    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3962    SET_VREG(r0, r9)                    @ vAA<- r0
3963    GOTO_OPCODE(ip)                     @ jump to next instruction
3964    /* 9-10 instructions */
3965
3966
3967/* ------------------------------ */
3968    .balign 64
3969.L_OP_INT_TO_CHAR: /* 0x8e */
3970/* File: armv5te/OP_INT_TO_CHAR.S */
3971/* File: armv5te/unop.S */
3972    /*
3973     * Generic 32-bit unary operation.  Provide an "instr" line that
3974     * specifies an instruction that performs "result = op r0".
3975     * This could be an ARM instruction or a function call.
3976     *
3977     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3978     *      int-to-byte, int-to-char, int-to-short
3979     */
3980    /* unop vA, vB */
3981    mov     r3, rINST, lsr #12          @ r3<- B
3982    mov     r9, rINST, lsr #8           @ r9<- A+
3983    GET_VREG(r0, r3)                    @ r0<- vB
3984    and     r9, r9, #15
3985    mov     r0, r0, asl #16                           @ optional op; may set condition codes
3986    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3987    mov     r0, r0, lsr #16                              @ r0<- op, r0-r3 changed
3988    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3989    SET_VREG(r0, r9)                    @ vAA<- r0
3990    GOTO_OPCODE(ip)                     @ jump to next instruction
3991    /* 9-10 instructions */
3992
3993
3994/* ------------------------------ */
3995    .balign 64
3996.L_OP_INT_TO_SHORT: /* 0x8f */
3997/* File: armv5te/OP_INT_TO_SHORT.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 #16                           @ optional op; may set condition codes
4013    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4014    mov     r0, r0, asr #16                              @ 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_ADD_INT: /* 0x90 */
4024/* File: armv5te/OP_ADD_INT.S */
4025/* File: armv5te/binop.S */
4026    /*
4027     * Generic 32-bit binary operation.  Provide an "instr" line that
4028     * specifies an instruction that performs "result = r0 op r1".
4029     * This could be an ARM instruction or a function call.  (If the result
4030     * comes back in a register other than r0, you can override "result".)
4031     *
4032     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4033     * vCC (r1).  Useful for integer division and modulus.  Note that we
4034     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4035     * handles it correctly.
4036     *
4037     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4038     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4039     *      mul-float, div-float, rem-float
4040     */
4041    /* binop vAA, vBB, vCC */
4042    FETCH(r0, 1)                        @ r0<- CCBB
4043    mov     r9, rINST, lsr #8           @ r9<- AA
4044    mov     r3, r0, lsr #8              @ r3<- CC
4045    and     r2, r0, #255                @ r2<- BB
4046    GET_VREG(r1, r3)                    @ r1<- vCC
4047    GET_VREG(r0, r2)                    @ r0<- vBB
4048    .if 0
4049    cmp     r1, #0                      @ is second operand zero?
4050    beq     common_errDivideByZero
4051    .endif
4052
4053    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4054                               @ optional op; may set condition codes
4055    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
4056    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4057    SET_VREG(r0, r9)               @ vAA<- r0
4058    GOTO_OPCODE(ip)                     @ jump to next instruction
4059    /* 11-14 instructions */
4060
4061
4062/* ------------------------------ */
4063    .balign 64
4064.L_OP_SUB_INT: /* 0x91 */
4065/* File: armv5te/OP_SUB_INT.S */
4066/* File: armv5te/binop.S */
4067    /*
4068     * Generic 32-bit binary operation.  Provide an "instr" line that
4069     * specifies an instruction that performs "result = r0 op r1".
4070     * This could be an ARM instruction or a function call.  (If the result
4071     * comes back in a register other than r0, you can override "result".)
4072     *
4073     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4074     * vCC (r1).  Useful for integer division and modulus.  Note that we
4075     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4076     * handles it correctly.
4077     *
4078     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4079     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4080     *      mul-float, div-float, rem-float
4081     */
4082    /* binop vAA, vBB, vCC */
4083    FETCH(r0, 1)                        @ r0<- CCBB
4084    mov     r9, rINST, lsr #8           @ r9<- AA
4085    mov     r3, r0, lsr #8              @ r3<- CC
4086    and     r2, r0, #255                @ r2<- BB
4087    GET_VREG(r1, r3)                    @ r1<- vCC
4088    GET_VREG(r0, r2)                    @ r0<- vBB
4089    .if 0
4090    cmp     r1, #0                      @ is second operand zero?
4091    beq     common_errDivideByZero
4092    .endif
4093
4094    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4095                               @ optional op; may set condition codes
4096    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
4097    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4098    SET_VREG(r0, r9)               @ vAA<- r0
4099    GOTO_OPCODE(ip)                     @ jump to next instruction
4100    /* 11-14 instructions */
4101
4102
4103/* ------------------------------ */
4104    .balign 64
4105.L_OP_MUL_INT: /* 0x92 */
4106/* File: armv5te/OP_MUL_INT.S */
4107/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
4108/* File: armv5te/binop.S */
4109    /*
4110     * Generic 32-bit binary operation.  Provide an "instr" line that
4111     * specifies an instruction that performs "result = r0 op r1".
4112     * This could be an ARM instruction or a function call.  (If the result
4113     * comes back in a register other than r0, you can override "result".)
4114     *
4115     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4116     * vCC (r1).  Useful for integer division and modulus.  Note that we
4117     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4118     * handles it correctly.
4119     *
4120     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4121     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4122     *      mul-float, div-float, rem-float
4123     */
4124    /* binop vAA, vBB, vCC */
4125    FETCH(r0, 1)                        @ r0<- CCBB
4126    mov     r9, rINST, lsr #8           @ r9<- AA
4127    mov     r3, r0, lsr #8              @ r3<- CC
4128    and     r2, r0, #255                @ r2<- BB
4129    GET_VREG(r1, r3)                    @ r1<- vCC
4130    GET_VREG(r0, r2)                    @ r0<- vBB
4131    .if 0
4132    cmp     r1, #0                      @ is second operand zero?
4133    beq     common_errDivideByZero
4134    .endif
4135
4136    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4137                               @ optional op; may set condition codes
4138    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
4139    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4140    SET_VREG(r0, r9)               @ vAA<- r0
4141    GOTO_OPCODE(ip)                     @ jump to next instruction
4142    /* 11-14 instructions */
4143
4144
4145/* ------------------------------ */
4146    .balign 64
4147.L_OP_DIV_INT: /* 0x93 */
4148/* File: armv5te/OP_DIV_INT.S */
4149/* File: armv5te/binop.S */
4150    /*
4151     * Generic 32-bit binary operation.  Provide an "instr" line that
4152     * specifies an instruction that performs "result = r0 op r1".
4153     * This could be an ARM instruction or a function call.  (If the result
4154     * comes back in a register other than r0, you can override "result".)
4155     *
4156     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4157     * vCC (r1).  Useful for integer division and modulus.  Note that we
4158     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4159     * handles it correctly.
4160     *
4161     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4162     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4163     *      mul-float, div-float, rem-float
4164     */
4165    /* binop vAA, vBB, vCC */
4166    FETCH(r0, 1)                        @ r0<- CCBB
4167    mov     r9, rINST, lsr #8           @ r9<- AA
4168    mov     r3, r0, lsr #8              @ r3<- CC
4169    and     r2, r0, #255                @ r2<- BB
4170    GET_VREG(r1, r3)                    @ r1<- vCC
4171    GET_VREG(r0, r2)                    @ r0<- vBB
4172    .if 1
4173    cmp     r1, #0                      @ is second operand zero?
4174    beq     common_errDivideByZero
4175    .endif
4176
4177    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4178                               @ optional op; may set condition codes
4179    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
4180    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4181    SET_VREG(r0, r9)               @ vAA<- r0
4182    GOTO_OPCODE(ip)                     @ jump to next instruction
4183    /* 11-14 instructions */
4184
4185
4186/* ------------------------------ */
4187    .balign 64
4188.L_OP_REM_INT: /* 0x94 */
4189/* File: armv5te/OP_REM_INT.S */
4190/* idivmod returns quotient in r0 and remainder in r1 */
4191/* File: armv5te/binop.S */
4192    /*
4193     * Generic 32-bit binary operation.  Provide an "instr" line that
4194     * specifies an instruction that performs "result = r0 op r1".
4195     * This could be an ARM instruction or a function call.  (If the result
4196     * comes back in a register other than r0, you can override "result".)
4197     *
4198     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4199     * vCC (r1).  Useful for integer division and modulus.  Note that we
4200     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4201     * handles it correctly.
4202     *
4203     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4204     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4205     *      mul-float, div-float, rem-float
4206     */
4207    /* binop vAA, vBB, vCC */
4208    FETCH(r0, 1)                        @ r0<- CCBB
4209    mov     r9, rINST, lsr #8           @ r9<- AA
4210    mov     r3, r0, lsr #8              @ r3<- CC
4211    and     r2, r0, #255                @ r2<- BB
4212    GET_VREG(r1, r3)                    @ r1<- vCC
4213    GET_VREG(r0, r2)                    @ r0<- vBB
4214    .if 1
4215    cmp     r1, #0                      @ is second operand zero?
4216    beq     common_errDivideByZero
4217    .endif
4218
4219    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4220                               @ optional op; may set condition codes
4221    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
4222    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4223    SET_VREG(r1, r9)               @ vAA<- r1
4224    GOTO_OPCODE(ip)                     @ jump to next instruction
4225    /* 11-14 instructions */
4226
4227
4228/* ------------------------------ */
4229    .balign 64
4230.L_OP_AND_INT: /* 0x95 */
4231/* File: armv5te/OP_AND_INT.S */
4232/* File: armv5te/binop.S */
4233    /*
4234     * Generic 32-bit binary operation.  Provide an "instr" line that
4235     * specifies an instruction that performs "result = r0 op r1".
4236     * This could be an ARM instruction or a function call.  (If the result
4237     * comes back in a register other than r0, you can override "result".)
4238     *
4239     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4240     * vCC (r1).  Useful for integer division and modulus.  Note that we
4241     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4242     * handles it correctly.
4243     *
4244     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4245     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4246     *      mul-float, div-float, rem-float
4247     */
4248    /* binop vAA, vBB, vCC */
4249    FETCH(r0, 1)                        @ r0<- CCBB
4250    mov     r9, rINST, lsr #8           @ r9<- AA
4251    mov     r3, r0, lsr #8              @ r3<- CC
4252    and     r2, r0, #255                @ r2<- BB
4253    GET_VREG(r1, r3)                    @ r1<- vCC
4254    GET_VREG(r0, r2)                    @ r0<- vBB
4255    .if 0
4256    cmp     r1, #0                      @ is second operand zero?
4257    beq     common_errDivideByZero
4258    .endif
4259
4260    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4261                               @ optional op; may set condition codes
4262    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
4263    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4264    SET_VREG(r0, r9)               @ vAA<- r0
4265    GOTO_OPCODE(ip)                     @ jump to next instruction
4266    /* 11-14 instructions */
4267
4268
4269/* ------------------------------ */
4270    .balign 64
4271.L_OP_OR_INT: /* 0x96 */
4272/* File: armv5te/OP_OR_INT.S */
4273/* File: armv5te/binop.S */
4274    /*
4275     * Generic 32-bit binary operation.  Provide an "instr" line that
4276     * specifies an instruction that performs "result = r0 op r1".
4277     * This could be an ARM instruction or a function call.  (If the result
4278     * comes back in a register other than r0, you can override "result".)
4279     *
4280     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4281     * vCC (r1).  Useful for integer division and modulus.  Note that we
4282     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4283     * handles it correctly.
4284     *
4285     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4286     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4287     *      mul-float, div-float, rem-float
4288     */
4289    /* binop vAA, vBB, vCC */
4290    FETCH(r0, 1)                        @ r0<- CCBB
4291    mov     r9, rINST, lsr #8           @ r9<- AA
4292    mov     r3, r0, lsr #8              @ r3<- CC
4293    and     r2, r0, #255                @ r2<- BB
4294    GET_VREG(r1, r3)                    @ r1<- vCC
4295    GET_VREG(r0, r2)                    @ r0<- vBB
4296    .if 0
4297    cmp     r1, #0                      @ is second operand zero?
4298    beq     common_errDivideByZero
4299    .endif
4300
4301    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4302                               @ optional op; may set condition codes
4303    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
4304    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4305    SET_VREG(r0, r9)               @ vAA<- r0
4306    GOTO_OPCODE(ip)                     @ jump to next instruction
4307    /* 11-14 instructions */
4308
4309
4310/* ------------------------------ */
4311    .balign 64
4312.L_OP_XOR_INT: /* 0x97 */
4313/* File: armv5te/OP_XOR_INT.S */
4314/* File: armv5te/binop.S */
4315    /*
4316     * Generic 32-bit binary operation.  Provide an "instr" line that
4317     * specifies an instruction that performs "result = r0 op r1".
4318     * This could be an ARM instruction or a function call.  (If the result
4319     * comes back in a register other than r0, you can override "result".)
4320     *
4321     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4322     * vCC (r1).  Useful for integer division and modulus.  Note that we
4323     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4324     * handles it correctly.
4325     *
4326     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4327     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4328     *      mul-float, div-float, rem-float
4329     */
4330    /* binop vAA, vBB, vCC */
4331    FETCH(r0, 1)                        @ r0<- CCBB
4332    mov     r9, rINST, lsr #8           @ r9<- AA
4333    mov     r3, r0, lsr #8              @ r3<- CC
4334    and     r2, r0, #255                @ r2<- BB
4335    GET_VREG(r1, r3)                    @ r1<- vCC
4336    GET_VREG(r0, r2)                    @ r0<- vBB
4337    .if 0
4338    cmp     r1, #0                      @ is second operand zero?
4339    beq     common_errDivideByZero
4340    .endif
4341
4342    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4343                               @ optional op; may set condition codes
4344    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
4345    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4346    SET_VREG(r0, r9)               @ vAA<- r0
4347    GOTO_OPCODE(ip)                     @ jump to next instruction
4348    /* 11-14 instructions */
4349
4350
4351/* ------------------------------ */
4352    .balign 64
4353.L_OP_SHL_INT: /* 0x98 */
4354/* File: armv5te/OP_SHL_INT.S */
4355/* File: armv5te/binop.S */
4356    /*
4357     * Generic 32-bit binary operation.  Provide an "instr" line that
4358     * specifies an instruction that performs "result = r0 op r1".
4359     * This could be an ARM instruction or a function call.  (If the result
4360     * comes back in a register other than r0, you can override "result".)
4361     *
4362     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4363     * vCC (r1).  Useful for integer division and modulus.  Note that we
4364     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4365     * handles it correctly.
4366     *
4367     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4368     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4369     *      mul-float, div-float, rem-float
4370     */
4371    /* binop vAA, vBB, vCC */
4372    FETCH(r0, 1)                        @ r0<- CCBB
4373    mov     r9, rINST, lsr #8           @ r9<- AA
4374    mov     r3, r0, lsr #8              @ r3<- CC
4375    and     r2, r0, #255                @ r2<- BB
4376    GET_VREG(r1, r3)                    @ r1<- vCC
4377    GET_VREG(r0, r2)                    @ r0<- vBB
4378    .if 0
4379    cmp     r1, #0                      @ is second operand zero?
4380    beq     common_errDivideByZero
4381    .endif
4382
4383    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4384    and     r1, r1, #31                           @ optional op; may set condition codes
4385    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
4386    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4387    SET_VREG(r0, r9)               @ vAA<- r0
4388    GOTO_OPCODE(ip)                     @ jump to next instruction
4389    /* 11-14 instructions */
4390
4391
4392/* ------------------------------ */
4393    .balign 64
4394.L_OP_SHR_INT: /* 0x99 */
4395/* File: armv5te/OP_SHR_INT.S */
4396/* File: armv5te/binop.S */
4397    /*
4398     * Generic 32-bit binary operation.  Provide an "instr" line that
4399     * specifies an instruction that performs "result = r0 op r1".
4400     * This could be an ARM instruction or a function call.  (If the result
4401     * comes back in a register other than r0, you can override "result".)
4402     *
4403     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4404     * vCC (r1).  Useful for integer division and modulus.  Note that we
4405     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4406     * handles it correctly.
4407     *
4408     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4409     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4410     *      mul-float, div-float, rem-float
4411     */
4412    /* binop vAA, vBB, vCC */
4413    FETCH(r0, 1)                        @ r0<- CCBB
4414    mov     r9, rINST, lsr #8           @ r9<- AA
4415    mov     r3, r0, lsr #8              @ r3<- CC
4416    and     r2, r0, #255                @ r2<- BB
4417    GET_VREG(r1, r3)                    @ r1<- vCC
4418    GET_VREG(r0, r2)                    @ r0<- vBB
4419    .if 0
4420    cmp     r1, #0                      @ is second operand zero?
4421    beq     common_errDivideByZero
4422    .endif
4423
4424    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4425    and     r1, r1, #31                           @ optional op; may set condition codes
4426    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
4427    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4428    SET_VREG(r0, r9)               @ vAA<- r0
4429    GOTO_OPCODE(ip)                     @ jump to next instruction
4430    /* 11-14 instructions */
4431
4432
4433/* ------------------------------ */
4434    .balign 64
4435.L_OP_USHR_INT: /* 0x9a */
4436/* File: armv5te/OP_USHR_INT.S */
4437/* File: armv5te/binop.S */
4438    /*
4439     * Generic 32-bit binary operation.  Provide an "instr" line that
4440     * specifies an instruction that performs "result = r0 op r1".
4441     * This could be an ARM instruction or a function call.  (If the result
4442     * comes back in a register other than r0, you can override "result".)
4443     *
4444     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4445     * vCC (r1).  Useful for integer division and modulus.  Note that we
4446     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4447     * handles it correctly.
4448     *
4449     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4450     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4451     *      mul-float, div-float, rem-float
4452     */
4453    /* binop vAA, vBB, vCC */
4454    FETCH(r0, 1)                        @ r0<- CCBB
4455    mov     r9, rINST, lsr #8           @ r9<- AA
4456    mov     r3, r0, lsr #8              @ r3<- CC
4457    and     r2, r0, #255                @ r2<- BB
4458    GET_VREG(r1, r3)                    @ r1<- vCC
4459    GET_VREG(r0, r2)                    @ r0<- vBB
4460    .if 0
4461    cmp     r1, #0                      @ is second operand zero?
4462    beq     common_errDivideByZero
4463    .endif
4464
4465    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4466    and     r1, r1, #31                           @ optional op; may set condition codes
4467    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
4468    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4469    SET_VREG(r0, r9)               @ vAA<- r0
4470    GOTO_OPCODE(ip)                     @ jump to next instruction
4471    /* 11-14 instructions */
4472
4473
4474/* ------------------------------ */
4475    .balign 64
4476.L_OP_ADD_LONG: /* 0x9b */
4477/* File: armv5te/OP_ADD_LONG.S */
4478/* File: armv5te/binopWide.S */
4479    /*
4480     * Generic 64-bit binary operation.  Provide an "instr" line that
4481     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4482     * This could be an ARM instruction or a function call.  (If the result
4483     * comes back in a register other than r0, you can override "result".)
4484     *
4485     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4486     * vCC (r1).  Useful for integer division and modulus.
4487     *
4488     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4489     *      xor-long, add-double, sub-double, mul-double, div-double,
4490     *      rem-double
4491     *
4492     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4493     */
4494    /* binop vAA, vBB, vCC */
4495    FETCH(r0, 1)                        @ r0<- CCBB
4496    mov     r9, rINST, lsr #8           @ r9<- AA
4497    and     r2, r0, #255                @ r2<- BB
4498    mov     r3, r0, lsr #8              @ r3<- CC
4499    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4500    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4501    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4502    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4503    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4504    .if 0
4505    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4506    beq     common_errDivideByZero
4507    .endif
4508    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4509
4510    adds    r0, r0, r2                           @ optional op; may set condition codes
4511    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
4512    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4513    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4514    GOTO_OPCODE(ip)                     @ jump to next instruction
4515    /* 14-17 instructions */
4516
4517
4518/* ------------------------------ */
4519    .balign 64
4520.L_OP_SUB_LONG: /* 0x9c */
4521/* File: armv5te/OP_SUB_LONG.S */
4522/* File: armv5te/binopWide.S */
4523    /*
4524     * Generic 64-bit binary operation.  Provide an "instr" line that
4525     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4526     * This could be an ARM instruction or a function call.  (If the result
4527     * comes back in a register other than r0, you can override "result".)
4528     *
4529     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4530     * vCC (r1).  Useful for integer division and modulus.
4531     *
4532     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4533     *      xor-long, add-double, sub-double, mul-double, div-double,
4534     *      rem-double
4535     *
4536     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4537     */
4538    /* binop vAA, vBB, vCC */
4539    FETCH(r0, 1)                        @ r0<- CCBB
4540    mov     r9, rINST, lsr #8           @ r9<- AA
4541    and     r2, r0, #255                @ r2<- BB
4542    mov     r3, r0, lsr #8              @ r3<- CC
4543    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4544    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4545    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4546    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4547    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4548    .if 0
4549    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4550    beq     common_errDivideByZero
4551    .endif
4552    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4553
4554    subs    r0, r0, r2                           @ optional op; may set condition codes
4555    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
4556    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4557    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4558    GOTO_OPCODE(ip)                     @ jump to next instruction
4559    /* 14-17 instructions */
4560
4561
4562/* ------------------------------ */
4563    .balign 64
4564.L_OP_MUL_LONG: /* 0x9d */
4565/* File: armv5te/OP_MUL_LONG.S */
4566    /*
4567     * Signed 64-bit integer multiply.
4568     *
4569     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
4570     *        WX
4571     *      x YZ
4572     *  --------
4573     *     ZW ZX
4574     *  YW YX
4575     *
4576     * The low word of the result holds ZX, the high word holds
4577     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
4578     * it doesn't fit in the low 64 bits.
4579     *
4580     * Unlike most ARM math operations, multiply instructions have
4581     * restrictions on using the same register more than once (Rd and Rm
4582     * cannot be the same).
4583     */
4584    /* mul-long vAA, vBB, vCC */
4585    FETCH(r0, 1)                        @ r0<- CCBB
4586    and     r2, r0, #255                @ r2<- BB
4587    mov     r3, r0, lsr #8              @ r3<- CC
4588    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4589    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4590    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4591    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4592    mul     ip, r2, r1                  @  ip<- ZxW
4593    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
4594    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
4595    mov     r0, rINST, lsr #8           @ r0<- AA
4596    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
4597    add     r0, rFP, r0, lsl #2         @ r0<- &fp[AA]
4598    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4599    b       .LOP_MUL_LONG_finish
4600
4601/* ------------------------------ */
4602    .balign 64
4603.L_OP_DIV_LONG: /* 0x9e */
4604/* File: armv5te/OP_DIV_LONG.S */
4605/* File: armv5te/binopWide.S */
4606    /*
4607     * Generic 64-bit binary operation.  Provide an "instr" line that
4608     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4609     * This could be an ARM instruction or a function call.  (If the result
4610     * comes back in a register other than r0, you can override "result".)
4611     *
4612     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4613     * vCC (r1).  Useful for integer division and modulus.
4614     *
4615     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4616     *      xor-long, add-double, sub-double, mul-double, div-double,
4617     *      rem-double
4618     *
4619     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4620     */
4621    /* binop vAA, vBB, vCC */
4622    FETCH(r0, 1)                        @ r0<- CCBB
4623    mov     r9, rINST, lsr #8           @ r9<- AA
4624    and     r2, r0, #255                @ r2<- BB
4625    mov     r3, r0, lsr #8              @ r3<- CC
4626    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4627    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4628    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4629    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4630    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4631    .if 1
4632    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4633    beq     common_errDivideByZero
4634    .endif
4635    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4636
4637                               @ optional op; may set condition codes
4638    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4639    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4640    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4641    GOTO_OPCODE(ip)                     @ jump to next instruction
4642    /* 14-17 instructions */
4643
4644
4645/* ------------------------------ */
4646    .balign 64
4647.L_OP_REM_LONG: /* 0x9f */
4648/* File: armv5te/OP_REM_LONG.S */
4649/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
4650/* File: armv5te/binopWide.S */
4651    /*
4652     * Generic 64-bit binary operation.  Provide an "instr" line that
4653     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4654     * This could be an ARM instruction or a function call.  (If the result
4655     * comes back in a register other than r0, you can override "result".)
4656     *
4657     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4658     * vCC (r1).  Useful for integer division and modulus.
4659     *
4660     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4661     *      xor-long, add-double, sub-double, mul-double, div-double,
4662     *      rem-double
4663     *
4664     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4665     */
4666    /* binop vAA, vBB, vCC */
4667    FETCH(r0, 1)                        @ r0<- CCBB
4668    mov     r9, rINST, lsr #8           @ r9<- AA
4669    and     r2, r0, #255                @ r2<- BB
4670    mov     r3, r0, lsr #8              @ r3<- CC
4671    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4672    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4673    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4674    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4675    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4676    .if 1
4677    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4678    beq     common_errDivideByZero
4679    .endif
4680    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4681
4682                               @ optional op; may set condition codes
4683    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4684    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4685    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
4686    GOTO_OPCODE(ip)                     @ jump to next instruction
4687    /* 14-17 instructions */
4688
4689
4690/* ------------------------------ */
4691    .balign 64
4692.L_OP_AND_LONG: /* 0xa0 */
4693/* File: armv5te/OP_AND_LONG.S */
4694/* File: armv5te/binopWide.S */
4695    /*
4696     * Generic 64-bit binary operation.  Provide an "instr" line that
4697     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4698     * This could be an ARM instruction or a function call.  (If the result
4699     * comes back in a register other than r0, you can override "result".)
4700     *
4701     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4702     * vCC (r1).  Useful for integer division and modulus.
4703     *
4704     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4705     *      xor-long, add-double, sub-double, mul-double, div-double,
4706     *      rem-double
4707     *
4708     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4709     */
4710    /* binop vAA, vBB, vCC */
4711    FETCH(r0, 1)                        @ r0<- CCBB
4712    mov     r9, rINST, lsr #8           @ r9<- AA
4713    and     r2, r0, #255                @ r2<- BB
4714    mov     r3, r0, lsr #8              @ r3<- CC
4715    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4716    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4717    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4718    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4719    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4720    .if 0
4721    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4722    beq     common_errDivideByZero
4723    .endif
4724    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4725
4726    and     r0, r0, r2                           @ optional op; may set condition codes
4727    and     r1, r1, r3                              @ result<- op, r0-r3 changed
4728    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4729    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4730    GOTO_OPCODE(ip)                     @ jump to next instruction
4731    /* 14-17 instructions */
4732
4733
4734/* ------------------------------ */
4735    .balign 64
4736.L_OP_OR_LONG: /* 0xa1 */
4737/* File: armv5te/OP_OR_LONG.S */
4738/* File: armv5te/binopWide.S */
4739    /*
4740     * Generic 64-bit binary operation.  Provide an "instr" line that
4741     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4742     * This could be an ARM instruction or a function call.  (If the result
4743     * comes back in a register other than r0, you can override "result".)
4744     *
4745     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4746     * vCC (r1).  Useful for integer division and modulus.
4747     *
4748     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4749     *      xor-long, add-double, sub-double, mul-double, div-double,
4750     *      rem-double
4751     *
4752     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4753     */
4754    /* binop vAA, vBB, vCC */
4755    FETCH(r0, 1)                        @ r0<- CCBB
4756    mov     r9, rINST, lsr #8           @ r9<- AA
4757    and     r2, r0, #255                @ r2<- BB
4758    mov     r3, r0, lsr #8              @ r3<- CC
4759    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4760    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4761    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4762    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4763    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4764    .if 0
4765    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4766    beq     common_errDivideByZero
4767    .endif
4768    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4769
4770    orr     r0, r0, r2                           @ optional op; may set condition codes
4771    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
4772    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4773    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4774    GOTO_OPCODE(ip)                     @ jump to next instruction
4775    /* 14-17 instructions */
4776
4777
4778/* ------------------------------ */
4779    .balign 64
4780.L_OP_XOR_LONG: /* 0xa2 */
4781/* File: armv5te/OP_XOR_LONG.S */
4782/* File: armv5te/binopWide.S */
4783    /*
4784     * Generic 64-bit binary operation.  Provide an "instr" line that
4785     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4786     * This could be an ARM instruction or a function call.  (If the result
4787     * comes back in a register other than r0, you can override "result".)
4788     *
4789     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4790     * vCC (r1).  Useful for integer division and modulus.
4791     *
4792     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4793     *      xor-long, add-double, sub-double, mul-double, div-double,
4794     *      rem-double
4795     *
4796     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4797     */
4798    /* binop vAA, vBB, vCC */
4799    FETCH(r0, 1)                        @ r0<- CCBB
4800    mov     r9, rINST, lsr #8           @ r9<- AA
4801    and     r2, r0, #255                @ r2<- BB
4802    mov     r3, r0, lsr #8              @ r3<- CC
4803    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4804    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4805    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4806    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4807    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4808    .if 0
4809    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4810    beq     common_errDivideByZero
4811    .endif
4812    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4813
4814    eor     r0, r0, r2                           @ optional op; may set condition codes
4815    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
4816    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4817    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4818    GOTO_OPCODE(ip)                     @ jump to next instruction
4819    /* 14-17 instructions */
4820
4821
4822/* ------------------------------ */
4823    .balign 64
4824.L_OP_SHL_LONG: /* 0xa3 */
4825/* File: armv5te/OP_SHL_LONG.S */
4826    /*
4827     * Long integer shift.  This is different from the generic 32/64-bit
4828     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4829     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4830     * 6 bits of the shift distance.
4831     */
4832    /* shl-long vAA, vBB, vCC */
4833    FETCH(r0, 1)                        @ r0<- CCBB
4834    mov     r9, rINST, lsr #8           @ r9<- AA
4835    and     r3, r0, #255                @ r3<- BB
4836    mov     r0, r0, lsr #8              @ r0<- CC
4837    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4838    GET_VREG(r2, r0)                    @ r2<- vCC
4839    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4840    and     r2, r2, #63                 @ r2<- r2 & 0x3f
4841    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4842
4843    mov     r1, r1, asl r2              @  r1<- r1 << r2
4844    rsb     r3, r2, #32                 @  r3<- 32 - r2
4845    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
4846    subs    ip, r2, #32                 @  ip<- r2 - 32
4847    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
4848    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4849    b       .LOP_SHL_LONG_finish
4850
4851/* ------------------------------ */
4852    .balign 64
4853.L_OP_SHR_LONG: /* 0xa4 */
4854/* File: armv5te/OP_SHR_LONG.S */
4855    /*
4856     * Long integer shift.  This is different from the generic 32/64-bit
4857     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4858     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4859     * 6 bits of the shift distance.
4860     */
4861    /* shr-long vAA, vBB, vCC */
4862    FETCH(r0, 1)                        @ r0<- CCBB
4863    mov     r9, rINST, lsr #8           @ r9<- AA
4864    and     r3, r0, #255                @ r3<- BB
4865    mov     r0, r0, lsr #8              @ r0<- CC
4866    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4867    GET_VREG(r2, r0)                    @ r2<- vCC
4868    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4869    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4870    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4871
4872    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4873    rsb     r3, r2, #32                 @  r3<- 32 - r2
4874    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4875    subs    ip, r2, #32                 @  ip<- r2 - 32
4876    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
4877    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4878    b       .LOP_SHR_LONG_finish
4879
4880/* ------------------------------ */
4881    .balign 64
4882.L_OP_USHR_LONG: /* 0xa5 */
4883/* File: armv5te/OP_USHR_LONG.S */
4884    /*
4885     * Long integer shift.  This is different from the generic 32/64-bit
4886     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4887     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4888     * 6 bits of the shift distance.
4889     */
4890    /* ushr-long vAA, vBB, vCC */
4891    FETCH(r0, 1)                        @ r0<- CCBB
4892    mov     r9, rINST, lsr #8           @ r9<- AA
4893    and     r3, r0, #255                @ r3<- BB
4894    mov     r0, r0, lsr #8              @ r0<- CC
4895    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4896    GET_VREG(r2, r0)                    @ r2<- vCC
4897    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4898    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4899    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4900
4901    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4902    rsb     r3, r2, #32                 @  r3<- 32 - r2
4903    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4904    subs    ip, r2, #32                 @  ip<- r2 - 32
4905    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
4906    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4907    b       .LOP_USHR_LONG_finish
4908
4909/* ------------------------------ */
4910    .balign 64
4911.L_OP_ADD_FLOAT: /* 0xa6 */
4912/* File: arm-vfp/OP_ADD_FLOAT.S */
4913/* File: arm-vfp/fbinop.S */
4914    /*
4915     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4916     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4917     * use the "softfp" ABI, this must be an instruction, not a function call.
4918     *
4919     * For: add-float, sub-float, mul-float, div-float
4920     */
4921    /* floatop vAA, vBB, vCC */
4922    FETCH(r0, 1)                        @ r0<- CCBB
4923    mov     r9, rINST, lsr #8           @ r9<- AA
4924    mov     r3, r0, lsr #8              @ r3<- CC
4925    and     r2, r0, #255                @ r2<- BB
4926    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
4927    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
4928    flds    s1, [r3]                    @ s1<- vCC
4929    flds    s0, [r2]                    @ s0<- vBB
4930
4931    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4932    fadds   s2, s0, s1                              @ s2<- op
4933    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4934    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
4935    fsts    s2, [r9]                    @ vAA<- s2
4936    GOTO_OPCODE(ip)                     @ jump to next instruction
4937
4938
4939/* ------------------------------ */
4940    .balign 64
4941.L_OP_SUB_FLOAT: /* 0xa7 */
4942/* File: arm-vfp/OP_SUB_FLOAT.S */
4943/* File: arm-vfp/fbinop.S */
4944    /*
4945     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4946     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4947     * use the "softfp" ABI, this must be an instruction, not a function call.
4948     *
4949     * For: add-float, sub-float, mul-float, div-float
4950     */
4951    /* floatop vAA, vBB, vCC */
4952    FETCH(r0, 1)                        @ r0<- CCBB
4953    mov     r9, rINST, lsr #8           @ r9<- AA
4954    mov     r3, r0, lsr #8              @ r3<- CC
4955    and     r2, r0, #255                @ r2<- BB
4956    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
4957    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
4958    flds    s1, [r3]                    @ s1<- vCC
4959    flds    s0, [r2]                    @ s0<- vBB
4960
4961    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4962    fsubs   s2, s0, s1                              @ s2<- op
4963    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4964    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
4965    fsts    s2, [r9]                    @ vAA<- s2
4966    GOTO_OPCODE(ip)                     @ jump to next instruction
4967
4968
4969/* ------------------------------ */
4970    .balign 64
4971.L_OP_MUL_FLOAT: /* 0xa8 */
4972/* File: arm-vfp/OP_MUL_FLOAT.S */
4973/* File: arm-vfp/fbinop.S */
4974    /*
4975     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4976     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4977     * use the "softfp" ABI, this must be an instruction, not a function call.
4978     *
4979     * For: add-float, sub-float, mul-float, div-float
4980     */
4981    /* floatop vAA, vBB, vCC */
4982    FETCH(r0, 1)                        @ r0<- CCBB
4983    mov     r9, rINST, lsr #8           @ r9<- AA
4984    mov     r3, r0, lsr #8              @ r3<- CC
4985    and     r2, r0, #255                @ r2<- BB
4986    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
4987    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
4988    flds    s1, [r3]                    @ s1<- vCC
4989    flds    s0, [r2]                    @ s0<- vBB
4990
4991    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4992    fmuls   s2, s0, s1                              @ s2<- op
4993    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4994    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
4995    fsts    s2, [r9]                    @ vAA<- s2
4996    GOTO_OPCODE(ip)                     @ jump to next instruction
4997
4998
4999/* ------------------------------ */
5000    .balign 64
5001.L_OP_DIV_FLOAT: /* 0xa9 */
5002/* File: arm-vfp/OP_DIV_FLOAT.S */
5003/* File: arm-vfp/fbinop.S */
5004    /*
5005     * Generic 32-bit floating-point operation.  Provide an "instr" line that
5006     * specifies an instruction that performs "s2 = s0 op s1".  Because we
5007     * use the "softfp" ABI, this must be an instruction, not a function call.
5008     *
5009     * For: add-float, sub-float, mul-float, div-float
5010     */
5011    /* floatop vAA, vBB, vCC */
5012    FETCH(r0, 1)                        @ r0<- CCBB
5013    mov     r9, rINST, lsr #8           @ r9<- AA
5014    mov     r3, r0, lsr #8              @ r3<- CC
5015    and     r2, r0, #255                @ r2<- BB
5016    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5017    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5018    flds    s1, [r3]                    @ s1<- vCC
5019    flds    s0, [r2]                    @ s0<- vBB
5020
5021    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5022    fdivs   s2, s0, s1                              @ s2<- op
5023    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5024    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5025    fsts    s2, [r9]                    @ vAA<- s2
5026    GOTO_OPCODE(ip)                     @ jump to next instruction
5027
5028
5029/* ------------------------------ */
5030    .balign 64
5031.L_OP_REM_FLOAT: /* 0xaa */
5032/* File: armv5te/OP_REM_FLOAT.S */
5033/* EABI doesn't define a float remainder function, but libm does */
5034/* File: armv5te/binop.S */
5035    /*
5036     * Generic 32-bit binary operation.  Provide an "instr" line that
5037     * specifies an instruction that performs "result = r0 op r1".
5038     * This could be an ARM instruction or a function call.  (If the result
5039     * comes back in a register other than r0, you can override "result".)
5040     *
5041     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5042     * vCC (r1).  Useful for integer division and modulus.  Note that we
5043     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5044     * handles it correctly.
5045     *
5046     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5047     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5048     *      mul-float, div-float, rem-float
5049     */
5050    /* binop vAA, vBB, vCC */
5051    FETCH(r0, 1)                        @ r0<- CCBB
5052    mov     r9, rINST, lsr #8           @ r9<- AA
5053    mov     r3, r0, lsr #8              @ r3<- CC
5054    and     r2, r0, #255                @ r2<- BB
5055    GET_VREG(r1, r3)                    @ r1<- vCC
5056    GET_VREG(r0, r2)                    @ r0<- vBB
5057    .if 0
5058    cmp     r1, #0                      @ is second operand zero?
5059    beq     common_errDivideByZero
5060    .endif
5061
5062    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5063                               @ optional op; may set condition codes
5064    bl      fmodf                              @ r0<- op, r0-r3 changed
5065    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5066    SET_VREG(r0, r9)               @ vAA<- r0
5067    GOTO_OPCODE(ip)                     @ jump to next instruction
5068    /* 11-14 instructions */
5069
5070
5071/* ------------------------------ */
5072    .balign 64
5073.L_OP_ADD_DOUBLE: /* 0xab */
5074/* File: arm-vfp/OP_ADD_DOUBLE.S */
5075/* File: arm-vfp/fbinopWide.S */
5076    /*
5077     * Generic 64-bit double-precision floating point binary operation.
5078     * Provide an "instr" line that specifies an instruction that performs
5079     * "d2 = d0 op d1".
5080     *
5081     * for: add-double, sub-double, mul-double, div-double
5082     */
5083    /* doubleop 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    fldd    d1, [r3]                    @ d1<- vCC
5091    fldd    d0, [r2]                    @ d0<- vBB
5092
5093    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5094    faddd   d2, d0, d1                              @ s2<- op
5095    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5096    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5097    fstd    d2, [r9]                    @ vAA<- d2
5098    GOTO_OPCODE(ip)                     @ jump to next instruction
5099
5100
5101/* ------------------------------ */
5102    .balign 64
5103.L_OP_SUB_DOUBLE: /* 0xac */
5104/* File: arm-vfp/OP_SUB_DOUBLE.S */
5105/* File: arm-vfp/fbinopWide.S */
5106    /*
5107     * Generic 64-bit double-precision floating point binary operation.
5108     * Provide an "instr" line that specifies an instruction that performs
5109     * "d2 = d0 op d1".
5110     *
5111     * for: add-double, sub-double, mul-double, div-double
5112     */
5113    /* doubleop vAA, vBB, vCC */
5114    FETCH(r0, 1)                        @ r0<- CCBB
5115    mov     r9, rINST, lsr #8           @ r9<- AA
5116    mov     r3, r0, lsr #8              @ r3<- CC
5117    and     r2, r0, #255                @ r2<- BB
5118    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5119    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5120    fldd    d1, [r3]                    @ d1<- vCC
5121    fldd    d0, [r2]                    @ d0<- vBB
5122
5123    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5124    fsubd   d2, d0, d1                              @ s2<- op
5125    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5126    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5127    fstd    d2, [r9]                    @ vAA<- d2
5128    GOTO_OPCODE(ip)                     @ jump to next instruction
5129
5130
5131/* ------------------------------ */
5132    .balign 64
5133.L_OP_MUL_DOUBLE: /* 0xad */
5134/* File: arm-vfp/OP_MUL_DOUBLE.S */
5135/* File: arm-vfp/fbinopWide.S */
5136    /*
5137     * Generic 64-bit double-precision floating point binary operation.
5138     * Provide an "instr" line that specifies an instruction that performs
5139     * "d2 = d0 op d1".
5140     *
5141     * for: add-double, sub-double, mul-double, div-double
5142     */
5143    /* doubleop vAA, vBB, vCC */
5144    FETCH(r0, 1)                        @ r0<- CCBB
5145    mov     r9, rINST, lsr #8           @ r9<- AA
5146    mov     r3, r0, lsr #8              @ r3<- CC
5147    and     r2, r0, #255                @ r2<- BB
5148    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5149    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5150    fldd    d1, [r3]                    @ d1<- vCC
5151    fldd    d0, [r2]                    @ d0<- vBB
5152
5153    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5154    fmuld   d2, d0, d1                              @ s2<- op
5155    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5156    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5157    fstd    d2, [r9]                    @ vAA<- d2
5158    GOTO_OPCODE(ip)                     @ jump to next instruction
5159
5160
5161/* ------------------------------ */
5162    .balign 64
5163.L_OP_DIV_DOUBLE: /* 0xae */
5164/* File: arm-vfp/OP_DIV_DOUBLE.S */
5165/* File: arm-vfp/fbinopWide.S */
5166    /*
5167     * Generic 64-bit double-precision floating point binary operation.
5168     * Provide an "instr" line that specifies an instruction that performs
5169     * "d2 = d0 op d1".
5170     *
5171     * for: add-double, sub-double, mul-double, div-double
5172     */
5173    /* doubleop vAA, vBB, vCC */
5174    FETCH(r0, 1)                        @ r0<- CCBB
5175    mov     r9, rINST, lsr #8           @ r9<- AA
5176    mov     r3, r0, lsr #8              @ r3<- CC
5177    and     r2, r0, #255                @ r2<- BB
5178    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5179    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5180    fldd    d1, [r3]                    @ d1<- vCC
5181    fldd    d0, [r2]                    @ d0<- vBB
5182
5183    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5184    fdivd   d2, d0, d1                              @ s2<- op
5185    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5186    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5187    fstd    d2, [r9]                    @ vAA<- d2
5188    GOTO_OPCODE(ip)                     @ jump to next instruction
5189
5190
5191/* ------------------------------ */
5192    .balign 64
5193.L_OP_REM_DOUBLE: /* 0xaf */
5194/* File: armv5te/OP_REM_DOUBLE.S */
5195/* EABI doesn't define a double remainder function, but libm does */
5196/* File: armv5te/binopWide.S */
5197    /*
5198     * Generic 64-bit binary operation.  Provide an "instr" line that
5199     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5200     * This could be an ARM instruction or a function call.  (If the result
5201     * comes back in a register other than r0, you can override "result".)
5202     *
5203     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5204     * vCC (r1).  Useful for integer division and modulus.
5205     *
5206     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5207     *      xor-long, add-double, sub-double, mul-double, div-double,
5208     *      rem-double
5209     *
5210     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5211     */
5212    /* binop vAA, vBB, vCC */
5213    FETCH(r0, 1)                        @ r0<- CCBB
5214    mov     r9, rINST, lsr #8           @ r9<- AA
5215    and     r2, r0, #255                @ r2<- BB
5216    mov     r3, r0, lsr #8              @ r3<- CC
5217    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5218    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5219    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5220    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5221    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5222    .if 0
5223    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5224    beq     common_errDivideByZero
5225    .endif
5226    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5227
5228                               @ optional op; may set condition codes
5229    bl      fmod                              @ result<- op, r0-r3 changed
5230    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5231    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5232    GOTO_OPCODE(ip)                     @ jump to next instruction
5233    /* 14-17 instructions */
5234
5235
5236/* ------------------------------ */
5237    .balign 64
5238.L_OP_ADD_INT_2ADDR: /* 0xb0 */
5239/* File: armv5te/OP_ADD_INT_2ADDR.S */
5240/* File: armv5te/binop2addr.S */
5241    /*
5242     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5243     * that specifies an instruction that performs "result = r0 op r1".
5244     * This could be an ARM instruction or a function call.  (If the result
5245     * comes back in a register other than r0, you can override "result".)
5246     *
5247     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5248     * vCC (r1).  Useful for integer division and modulus.
5249     *
5250     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5251     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5252     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5253     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5254     */
5255    /* binop/2addr vA, vB */
5256    mov     r9, rINST, lsr #8           @ r9<- A+
5257    mov     r3, rINST, lsr #12          @ r3<- B
5258    and     r9, r9, #15
5259    GET_VREG(r1, r3)                    @ r1<- vB
5260    GET_VREG(r0, r9)                    @ r0<- vA
5261    .if 0
5262    cmp     r1, #0                      @ is second operand zero?
5263    beq     common_errDivideByZero
5264    .endif
5265    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5266
5267                               @ optional op; may set condition codes
5268    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
5269    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5270    SET_VREG(r0, r9)               @ vAA<- r0
5271    GOTO_OPCODE(ip)                     @ jump to next instruction
5272    /* 10-13 instructions */
5273
5274
5275/* ------------------------------ */
5276    .balign 64
5277.L_OP_SUB_INT_2ADDR: /* 0xb1 */
5278/* File: armv5te/OP_SUB_INT_2ADDR.S */
5279/* File: armv5te/binop2addr.S */
5280    /*
5281     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5282     * that specifies an instruction that performs "result = r0 op r1".
5283     * This could be an ARM instruction or a function call.  (If the result
5284     * comes back in a register other than r0, you can override "result".)
5285     *
5286     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5287     * vCC (r1).  Useful for integer division and modulus.
5288     *
5289     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5290     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5291     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5292     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5293     */
5294    /* binop/2addr vA, vB */
5295    mov     r9, rINST, lsr #8           @ r9<- A+
5296    mov     r3, rINST, lsr #12          @ r3<- B
5297    and     r9, r9, #15
5298    GET_VREG(r1, r3)                    @ r1<- vB
5299    GET_VREG(r0, r9)                    @ r0<- vA
5300    .if 0
5301    cmp     r1, #0                      @ is second operand zero?
5302    beq     common_errDivideByZero
5303    .endif
5304    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5305
5306                               @ optional op; may set condition codes
5307    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
5308    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5309    SET_VREG(r0, r9)               @ vAA<- r0
5310    GOTO_OPCODE(ip)                     @ jump to next instruction
5311    /* 10-13 instructions */
5312
5313
5314/* ------------------------------ */
5315    .balign 64
5316.L_OP_MUL_INT_2ADDR: /* 0xb2 */
5317/* File: armv5te/OP_MUL_INT_2ADDR.S */
5318/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
5319/* File: armv5te/binop2addr.S */
5320    /*
5321     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5322     * that specifies an instruction that performs "result = r0 op r1".
5323     * This could be an ARM instruction or a function call.  (If the result
5324     * comes back in a register other than r0, you can override "result".)
5325     *
5326     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5327     * vCC (r1).  Useful for integer division and modulus.
5328     *
5329     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5330     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5331     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5332     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5333     */
5334    /* binop/2addr vA, vB */
5335    mov     r9, rINST, lsr #8           @ r9<- A+
5336    mov     r3, rINST, lsr #12          @ r3<- B
5337    and     r9, r9, #15
5338    GET_VREG(r1, r3)                    @ r1<- vB
5339    GET_VREG(r0, r9)                    @ r0<- vA
5340    .if 0
5341    cmp     r1, #0                      @ is second operand zero?
5342    beq     common_errDivideByZero
5343    .endif
5344    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5345
5346                               @ optional op; may set condition codes
5347    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
5348    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5349    SET_VREG(r0, r9)               @ vAA<- r0
5350    GOTO_OPCODE(ip)                     @ jump to next instruction
5351    /* 10-13 instructions */
5352
5353
5354/* ------------------------------ */
5355    .balign 64
5356.L_OP_DIV_INT_2ADDR: /* 0xb3 */
5357/* File: armv5te/OP_DIV_INT_2ADDR.S */
5358/* File: armv5te/binop2addr.S */
5359    /*
5360     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5361     * that specifies an instruction that performs "result = r0 op r1".
5362     * This could be an ARM instruction or a function call.  (If the result
5363     * comes back in a register other than r0, you can override "result".)
5364     *
5365     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5366     * vCC (r1).  Useful for integer division and modulus.
5367     *
5368     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5369     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5370     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5371     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5372     */
5373    /* binop/2addr vA, vB */
5374    mov     r9, rINST, lsr #8           @ r9<- A+
5375    mov     r3, rINST, lsr #12          @ r3<- B
5376    and     r9, r9, #15
5377    GET_VREG(r1, r3)                    @ r1<- vB
5378    GET_VREG(r0, r9)                    @ r0<- vA
5379    .if 1
5380    cmp     r1, #0                      @ is second operand zero?
5381    beq     common_errDivideByZero
5382    .endif
5383    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5384
5385                               @ optional op; may set condition codes
5386    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
5387    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5388    SET_VREG(r0, r9)               @ vAA<- r0
5389    GOTO_OPCODE(ip)                     @ jump to next instruction
5390    /* 10-13 instructions */
5391
5392
5393/* ------------------------------ */
5394    .balign 64
5395.L_OP_REM_INT_2ADDR: /* 0xb4 */
5396/* File: armv5te/OP_REM_INT_2ADDR.S */
5397/* idivmod returns quotient in r0 and remainder in r1 */
5398/* File: armv5te/binop2addr.S */
5399    /*
5400     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5401     * that specifies an instruction that performs "result = r0 op r1".
5402     * This could be an ARM instruction or a function call.  (If the result
5403     * comes back in a register other than r0, you can override "result".)
5404     *
5405     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5406     * vCC (r1).  Useful for integer division and modulus.
5407     *
5408     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5409     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5410     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5411     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5412     */
5413    /* binop/2addr vA, vB */
5414    mov     r9, rINST, lsr #8           @ r9<- A+
5415    mov     r3, rINST, lsr #12          @ r3<- B
5416    and     r9, r9, #15
5417    GET_VREG(r1, r3)                    @ r1<- vB
5418    GET_VREG(r0, r9)                    @ r0<- vA
5419    .if 1
5420    cmp     r1, #0                      @ is second operand zero?
5421    beq     common_errDivideByZero
5422    .endif
5423    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5424
5425                               @ optional op; may set condition codes
5426    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
5427    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5428    SET_VREG(r1, r9)               @ vAA<- r1
5429    GOTO_OPCODE(ip)                     @ jump to next instruction
5430    /* 10-13 instructions */
5431
5432
5433/* ------------------------------ */
5434    .balign 64
5435.L_OP_AND_INT_2ADDR: /* 0xb5 */
5436/* File: armv5te/OP_AND_INT_2ADDR.S */
5437/* File: armv5te/binop2addr.S */
5438    /*
5439     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5440     * that specifies an instruction that performs "result = r0 op r1".
5441     * This could be an ARM instruction or a function call.  (If the result
5442     * comes back in a register other than r0, you can override "result".)
5443     *
5444     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5445     * vCC (r1).  Useful for integer division and modulus.
5446     *
5447     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5448     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5449     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5450     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5451     */
5452    /* binop/2addr vA, vB */
5453    mov     r9, rINST, lsr #8           @ r9<- A+
5454    mov     r3, rINST, lsr #12          @ r3<- B
5455    and     r9, r9, #15
5456    GET_VREG(r1, r3)                    @ r1<- vB
5457    GET_VREG(r0, r9)                    @ r0<- vA
5458    .if 0
5459    cmp     r1, #0                      @ is second operand zero?
5460    beq     common_errDivideByZero
5461    .endif
5462    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5463
5464                               @ optional op; may set condition codes
5465    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
5466    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5467    SET_VREG(r0, r9)               @ vAA<- r0
5468    GOTO_OPCODE(ip)                     @ jump to next instruction
5469    /* 10-13 instructions */
5470
5471
5472/* ------------------------------ */
5473    .balign 64
5474.L_OP_OR_INT_2ADDR: /* 0xb6 */
5475/* File: armv5te/OP_OR_INT_2ADDR.S */
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 0
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    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
5505    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5506    SET_VREG(r0, r9)               @ vAA<- r0
5507    GOTO_OPCODE(ip)                     @ jump to next instruction
5508    /* 10-13 instructions */
5509
5510
5511/* ------------------------------ */
5512    .balign 64
5513.L_OP_XOR_INT_2ADDR: /* 0xb7 */
5514/* File: armv5te/OP_XOR_INT_2ADDR.S */
5515/* File: armv5te/binop2addr.S */
5516    /*
5517     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5518     * that specifies an instruction that performs "result = r0 op r1".
5519     * This could be an ARM instruction or a function call.  (If the result
5520     * comes back in a register other than r0, you can override "result".)
5521     *
5522     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5523     * vCC (r1).  Useful for integer division and modulus.
5524     *
5525     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5526     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5527     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5528     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5529     */
5530    /* binop/2addr vA, vB */
5531    mov     r9, rINST, lsr #8           @ r9<- A+
5532    mov     r3, rINST, lsr #12          @ r3<- B
5533    and     r9, r9, #15
5534    GET_VREG(r1, r3)                    @ r1<- vB
5535    GET_VREG(r0, r9)                    @ r0<- vA
5536    .if 0
5537    cmp     r1, #0                      @ is second operand zero?
5538    beq     common_errDivideByZero
5539    .endif
5540    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5541
5542                               @ optional op; may set condition codes
5543    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
5544    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5545    SET_VREG(r0, r9)               @ vAA<- r0
5546    GOTO_OPCODE(ip)                     @ jump to next instruction
5547    /* 10-13 instructions */
5548
5549
5550/* ------------------------------ */
5551    .balign 64
5552.L_OP_SHL_INT_2ADDR: /* 0xb8 */
5553/* File: armv5te/OP_SHL_INT_2ADDR.S */
5554/* File: armv5te/binop2addr.S */
5555    /*
5556     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5557     * that specifies an instruction that performs "result = r0 op r1".
5558     * This could be an ARM instruction or a function call.  (If the result
5559     * comes back in a register other than r0, you can override "result".)
5560     *
5561     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5562     * vCC (r1).  Useful for integer division and modulus.
5563     *
5564     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5565     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5566     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5567     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5568     */
5569    /* binop/2addr vA, vB */
5570    mov     r9, rINST, lsr #8           @ r9<- A+
5571    mov     r3, rINST, lsr #12          @ r3<- B
5572    and     r9, r9, #15
5573    GET_VREG(r1, r3)                    @ r1<- vB
5574    GET_VREG(r0, r9)                    @ r0<- vA
5575    .if 0
5576    cmp     r1, #0                      @ is second operand zero?
5577    beq     common_errDivideByZero
5578    .endif
5579    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5580
5581    and     r1, r1, #31                           @ optional op; may set condition codes
5582    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
5583    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5584    SET_VREG(r0, r9)               @ vAA<- r0
5585    GOTO_OPCODE(ip)                     @ jump to next instruction
5586    /* 10-13 instructions */
5587
5588
5589/* ------------------------------ */
5590    .balign 64
5591.L_OP_SHR_INT_2ADDR: /* 0xb9 */
5592/* File: armv5te/OP_SHR_INT_2ADDR.S */
5593/* File: armv5te/binop2addr.S */
5594    /*
5595     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5596     * that specifies an instruction that performs "result = r0 op r1".
5597     * This could be an ARM instruction or a function call.  (If the result
5598     * comes back in a register other than r0, you can override "result".)
5599     *
5600     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5601     * vCC (r1).  Useful for integer division and modulus.
5602     *
5603     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5604     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5605     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5606     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5607     */
5608    /* binop/2addr vA, vB */
5609    mov     r9, rINST, lsr #8           @ r9<- A+
5610    mov     r3, rINST, lsr #12          @ r3<- B
5611    and     r9, r9, #15
5612    GET_VREG(r1, r3)                    @ r1<- vB
5613    GET_VREG(r0, r9)                    @ r0<- vA
5614    .if 0
5615    cmp     r1, #0                      @ is second operand zero?
5616    beq     common_errDivideByZero
5617    .endif
5618    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5619
5620    and     r1, r1, #31                           @ optional op; may set condition codes
5621    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
5622    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5623    SET_VREG(r0, r9)               @ vAA<- r0
5624    GOTO_OPCODE(ip)                     @ jump to next instruction
5625    /* 10-13 instructions */
5626
5627
5628/* ------------------------------ */
5629    .balign 64
5630.L_OP_USHR_INT_2ADDR: /* 0xba */
5631/* File: armv5te/OP_USHR_INT_2ADDR.S */
5632/* File: armv5te/binop2addr.S */
5633    /*
5634     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5635     * that specifies an instruction that performs "result = r0 op r1".
5636     * This could be an ARM instruction or a function call.  (If the result
5637     * comes back in a register other than r0, you can override "result".)
5638     *
5639     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5640     * vCC (r1).  Useful for integer division and modulus.
5641     *
5642     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5643     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5644     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5645     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5646     */
5647    /* binop/2addr vA, vB */
5648    mov     r9, rINST, lsr #8           @ r9<- A+
5649    mov     r3, rINST, lsr #12          @ r3<- B
5650    and     r9, r9, #15
5651    GET_VREG(r1, r3)                    @ r1<- vB
5652    GET_VREG(r0, r9)                    @ r0<- vA
5653    .if 0
5654    cmp     r1, #0                      @ is second operand zero?
5655    beq     common_errDivideByZero
5656    .endif
5657    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5658
5659    and     r1, r1, #31                           @ optional op; may set condition codes
5660    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
5661    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5662    SET_VREG(r0, r9)               @ vAA<- r0
5663    GOTO_OPCODE(ip)                     @ jump to next instruction
5664    /* 10-13 instructions */
5665
5666
5667/* ------------------------------ */
5668    .balign 64
5669.L_OP_ADD_LONG_2ADDR: /* 0xbb */
5670/* File: armv5te/OP_ADD_LONG_2ADDR.S */
5671/* File: armv5te/binopWide2addr.S */
5672    /*
5673     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5674     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5675     * This could be an ARM instruction or a function call.  (If the result
5676     * comes back in a register other than r0, you can override "result".)
5677     *
5678     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5679     * vCC (r1).  Useful for integer division and modulus.
5680     *
5681     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5682     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5683     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5684     *      rem-double/2addr
5685     */
5686    /* binop/2addr vA, vB */
5687    mov     r9, rINST, lsr #8           @ r9<- A+
5688    mov     r1, rINST, lsr #12          @ r1<- B
5689    and     r9, r9, #15
5690    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5691    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5692    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5693    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5694    .if 0
5695    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5696    beq     common_errDivideByZero
5697    .endif
5698    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5699
5700    adds    r0, r0, r2                           @ optional op; may set condition codes
5701    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
5702    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5703    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5704    GOTO_OPCODE(ip)                     @ jump to next instruction
5705    /* 12-15 instructions */
5706
5707
5708/* ------------------------------ */
5709    .balign 64
5710.L_OP_SUB_LONG_2ADDR: /* 0xbc */
5711/* File: armv5te/OP_SUB_LONG_2ADDR.S */
5712/* File: armv5te/binopWide2addr.S */
5713    /*
5714     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5715     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5716     * This could be an ARM instruction or a function call.  (If the result
5717     * comes back in a register other than r0, you can override "result".)
5718     *
5719     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5720     * vCC (r1).  Useful for integer division and modulus.
5721     *
5722     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5723     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5724     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5725     *      rem-double/2addr
5726     */
5727    /* binop/2addr vA, vB */
5728    mov     r9, rINST, lsr #8           @ r9<- A+
5729    mov     r1, rINST, lsr #12          @ r1<- B
5730    and     r9, r9, #15
5731    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5732    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5733    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5734    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5735    .if 0
5736    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5737    beq     common_errDivideByZero
5738    .endif
5739    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5740
5741    subs    r0, r0, r2                           @ optional op; may set condition codes
5742    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
5743    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5744    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5745    GOTO_OPCODE(ip)                     @ jump to next instruction
5746    /* 12-15 instructions */
5747
5748
5749/* ------------------------------ */
5750    .balign 64
5751.L_OP_MUL_LONG_2ADDR: /* 0xbd */
5752/* File: armv5te/OP_MUL_LONG_2ADDR.S */
5753    /*
5754     * Signed 64-bit integer multiply, "/2addr" version.
5755     *
5756     * See OP_MUL_LONG for an explanation.
5757     *
5758     * We get a little tight on registers, so to avoid looking up &fp[A]
5759     * again we stuff it into rINST.
5760     */
5761    /* mul-long/2addr vA, vB */
5762    mov     r9, rINST, lsr #8           @ r9<- A+
5763    mov     r1, rINST, lsr #12          @ r1<- B
5764    and     r9, r9, #15
5765    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5766    add     rINST, rFP, r9, lsl #2      @ rINST<- &fp[A]
5767    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5768    ldmia   rINST, {r0-r1}              @ r0/r1<- vAA/vAA+1
5769    mul     ip, r2, r1                  @  ip<- ZxW
5770    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
5771    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
5772    mov     r0, rINST                   @ r0<- &fp[A] (free up rINST)
5773    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5774    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
5775    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5776    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
5777    GOTO_OPCODE(ip)                     @ jump to next instruction
5778
5779/* ------------------------------ */
5780    .balign 64
5781.L_OP_DIV_LONG_2ADDR: /* 0xbe */
5782/* File: armv5te/OP_DIV_LONG_2ADDR.S */
5783/* File: armv5te/binopWide2addr.S */
5784    /*
5785     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5786     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5787     * This could be an ARM instruction or a function call.  (If the result
5788     * comes back in a register other than r0, you can override "result".)
5789     *
5790     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5791     * vCC (r1).  Useful for integer division and modulus.
5792     *
5793     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5794     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5795     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5796     *      rem-double/2addr
5797     */
5798    /* binop/2addr vA, vB */
5799    mov     r9, rINST, lsr #8           @ r9<- A+
5800    mov     r1, rINST, lsr #12          @ r1<- B
5801    and     r9, r9, #15
5802    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5803    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5804    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5805    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5806    .if 1
5807    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5808    beq     common_errDivideByZero
5809    .endif
5810    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5811
5812                               @ optional op; may set condition codes
5813    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5814    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5815    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5816    GOTO_OPCODE(ip)                     @ jump to next instruction
5817    /* 12-15 instructions */
5818
5819
5820/* ------------------------------ */
5821    .balign 64
5822.L_OP_REM_LONG_2ADDR: /* 0xbf */
5823/* File: armv5te/OP_REM_LONG_2ADDR.S */
5824/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
5825/* File: armv5te/binopWide2addr.S */
5826    /*
5827     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5828     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5829     * This could be an ARM instruction or a function call.  (If the result
5830     * comes back in a register other than r0, you can override "result".)
5831     *
5832     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5833     * vCC (r1).  Useful for integer division and modulus.
5834     *
5835     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5836     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5837     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5838     *      rem-double/2addr
5839     */
5840    /* binop/2addr vA, vB */
5841    mov     r9, rINST, lsr #8           @ r9<- A+
5842    mov     r1, rINST, lsr #12          @ r1<- B
5843    and     r9, r9, #15
5844    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5845    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5846    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5847    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5848    .if 1
5849    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5850    beq     common_errDivideByZero
5851    .endif
5852    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5853
5854                               @ optional op; may set condition codes
5855    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5856    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5857    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
5858    GOTO_OPCODE(ip)                     @ jump to next instruction
5859    /* 12-15 instructions */
5860
5861
5862/* ------------------------------ */
5863    .balign 64
5864.L_OP_AND_LONG_2ADDR: /* 0xc0 */
5865/* File: armv5te/OP_AND_LONG_2ADDR.S */
5866/* File: armv5te/binopWide2addr.S */
5867    /*
5868     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5869     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5870     * This could be an ARM instruction or a function call.  (If the result
5871     * comes back in a register other than r0, you can override "result".)
5872     *
5873     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5874     * vCC (r1).  Useful for integer division and modulus.
5875     *
5876     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5877     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5878     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5879     *      rem-double/2addr
5880     */
5881    /* binop/2addr vA, vB */
5882    mov     r9, rINST, lsr #8           @ r9<- A+
5883    mov     r1, rINST, lsr #12          @ r1<- B
5884    and     r9, r9, #15
5885    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5886    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5887    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5888    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5889    .if 0
5890    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5891    beq     common_errDivideByZero
5892    .endif
5893    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5894
5895    and     r0, r0, r2                           @ optional op; may set condition codes
5896    and     r1, r1, r3                              @ result<- op, r0-r3 changed
5897    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5898    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5899    GOTO_OPCODE(ip)                     @ jump to next instruction
5900    /* 12-15 instructions */
5901
5902
5903/* ------------------------------ */
5904    .balign 64
5905.L_OP_OR_LONG_2ADDR: /* 0xc1 */
5906/* File: armv5te/OP_OR_LONG_2ADDR.S */
5907/* File: armv5te/binopWide2addr.S */
5908    /*
5909     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5910     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5911     * This could be an ARM instruction or a function call.  (If the result
5912     * comes back in a register other than r0, you can override "result".)
5913     *
5914     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5915     * vCC (r1).  Useful for integer division and modulus.
5916     *
5917     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5918     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5919     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5920     *      rem-double/2addr
5921     */
5922    /* binop/2addr vA, vB */
5923    mov     r9, rINST, lsr #8           @ r9<- A+
5924    mov     r1, rINST, lsr #12          @ r1<- B
5925    and     r9, r9, #15
5926    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5927    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5928    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5929    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5930    .if 0
5931    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5932    beq     common_errDivideByZero
5933    .endif
5934    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5935
5936    orr     r0, r0, r2                           @ optional op; may set condition codes
5937    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
5938    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5939    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5940    GOTO_OPCODE(ip)                     @ jump to next instruction
5941    /* 12-15 instructions */
5942
5943
5944/* ------------------------------ */
5945    .balign 64
5946.L_OP_XOR_LONG_2ADDR: /* 0xc2 */
5947/* File: armv5te/OP_XOR_LONG_2ADDR.S */
5948/* File: armv5te/binopWide2addr.S */
5949    /*
5950     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5951     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5952     * This could be an ARM instruction or a function call.  (If the result
5953     * comes back in a register other than r0, you can override "result".)
5954     *
5955     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5956     * vCC (r1).  Useful for integer division and modulus.
5957     *
5958     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5959     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5960     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5961     *      rem-double/2addr
5962     */
5963    /* binop/2addr vA, vB */
5964    mov     r9, rINST, lsr #8           @ r9<- A+
5965    mov     r1, rINST, lsr #12          @ r1<- B
5966    and     r9, r9, #15
5967    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5968    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5969    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5970    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5971    .if 0
5972    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5973    beq     common_errDivideByZero
5974    .endif
5975    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5976
5977    eor     r0, r0, r2                           @ optional op; may set condition codes
5978    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
5979    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5980    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5981    GOTO_OPCODE(ip)                     @ jump to next instruction
5982    /* 12-15 instructions */
5983
5984
5985/* ------------------------------ */
5986    .balign 64
5987.L_OP_SHL_LONG_2ADDR: /* 0xc3 */
5988/* File: armv5te/OP_SHL_LONG_2ADDR.S */
5989    /*
5990     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
5991     * 32-bit shift distance.
5992     */
5993    /* shl-long/2addr vA, vB */
5994    mov     r9, rINST, lsr #8           @ r9<- A+
5995    mov     r3, rINST, lsr #12          @ r3<- B
5996    and     r9, r9, #15
5997    GET_VREG(r2, r3)                    @ r2<- vB
5998    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5999    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6000    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6001
6002    mov     r1, r1, asl r2              @  r1<- r1 << r2
6003    rsb     r3, r2, #32                 @  r3<- 32 - r2
6004    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
6005    subs    ip, r2, #32                 @  ip<- r2 - 32
6006    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6007    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
6008    mov     r0, r0, asl r2              @  r0<- r0 << r2
6009    b       .LOP_SHL_LONG_2ADDR_finish
6010
6011/* ------------------------------ */
6012    .balign 64
6013.L_OP_SHR_LONG_2ADDR: /* 0xc4 */
6014/* File: armv5te/OP_SHR_LONG_2ADDR.S */
6015    /*
6016     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6017     * 32-bit shift distance.
6018     */
6019    /* shr-long/2addr vA, vB */
6020    mov     r9, rINST, lsr #8           @ r9<- A+
6021    mov     r3, rINST, lsr #12          @ r3<- B
6022    and     r9, r9, #15
6023    GET_VREG(r2, r3)                    @ r2<- vB
6024    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6025    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6026    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6027
6028    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6029    rsb     r3, r2, #32                 @  r3<- 32 - r2
6030    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6031    subs    ip, r2, #32                 @  ip<- r2 - 32
6032    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6033    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
6034    mov     r1, r1, asr r2              @  r1<- r1 >> r2
6035    b       .LOP_SHR_LONG_2ADDR_finish
6036
6037/* ------------------------------ */
6038    .balign 64
6039.L_OP_USHR_LONG_2ADDR: /* 0xc5 */
6040/* File: armv5te/OP_USHR_LONG_2ADDR.S */
6041    /*
6042     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6043     * 32-bit shift distance.
6044     */
6045    /* ushr-long/2addr vA, vB */
6046    mov     r9, rINST, lsr #8           @ r9<- A+
6047    mov     r3, rINST, lsr #12          @ r3<- B
6048    and     r9, r9, #15
6049    GET_VREG(r2, r3)                    @ r2<- vB
6050    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6051    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6052    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6053
6054    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6055    rsb     r3, r2, #32                 @  r3<- 32 - r2
6056    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6057    subs    ip, r2, #32                 @  ip<- r2 - 32
6058    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6059    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
6060    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
6061    b       .LOP_USHR_LONG_2ADDR_finish
6062
6063/* ------------------------------ */
6064    .balign 64
6065.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
6066/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */
6067/* File: arm-vfp/fbinop2addr.S */
6068    /*
6069     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6070     * an "instr" line that specifies an instruction that performs
6071     * "s2 = s0 op s1".
6072     *
6073     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6074     */
6075    /* binop/2addr vA, vB */
6076    mov     r3, rINST, lsr #12          @ r3<- B
6077    mov     r9, rINST, lsr #8           @ r9<- A+
6078    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6079    and     r9, r9, #15                 @ r9<- A
6080    flds    s1, [r3]                    @ s1<- vB
6081    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6082    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6083    flds    s0, [r9]                    @ s0<- vA
6084
6085    fadds   s2, s0, s1                              @ s2<- op
6086    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6087    fsts    s2, [r9]                    @ vAA<- s2
6088    GOTO_OPCODE(ip)                     @ jump to next instruction
6089
6090
6091/* ------------------------------ */
6092    .balign 64
6093.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
6094/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */
6095/* File: arm-vfp/fbinop2addr.S */
6096    /*
6097     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6098     * an "instr" line that specifies an instruction that performs
6099     * "s2 = s0 op s1".
6100     *
6101     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6102     */
6103    /* binop/2addr vA, vB */
6104    mov     r3, rINST, lsr #12          @ r3<- B
6105    mov     r9, rINST, lsr #8           @ r9<- A+
6106    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6107    and     r9, r9, #15                 @ r9<- A
6108    flds    s1, [r3]                    @ s1<- vB
6109    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6110    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6111    flds    s0, [r9]                    @ s0<- vA
6112
6113    fsubs   s2, s0, s1                              @ s2<- op
6114    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6115    fsts    s2, [r9]                    @ vAA<- s2
6116    GOTO_OPCODE(ip)                     @ jump to next instruction
6117
6118
6119/* ------------------------------ */
6120    .balign 64
6121.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
6122/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */
6123/* File: arm-vfp/fbinop2addr.S */
6124    /*
6125     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6126     * an "instr" line that specifies an instruction that performs
6127     * "s2 = s0 op s1".
6128     *
6129     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6130     */
6131    /* binop/2addr vA, vB */
6132    mov     r3, rINST, lsr #12          @ r3<- B
6133    mov     r9, rINST, lsr #8           @ r9<- A+
6134    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6135    and     r9, r9, #15                 @ r9<- A
6136    flds    s1, [r3]                    @ s1<- vB
6137    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6138    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6139    flds    s0, [r9]                    @ s0<- vA
6140
6141    fmuls   s2, s0, s1                              @ s2<- op
6142    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6143    fsts    s2, [r9]                    @ vAA<- s2
6144    GOTO_OPCODE(ip)                     @ jump to next instruction
6145
6146
6147/* ------------------------------ */
6148    .balign 64
6149.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
6150/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */
6151/* File: arm-vfp/fbinop2addr.S */
6152    /*
6153     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6154     * an "instr" line that specifies an instruction that performs
6155     * "s2 = s0 op s1".
6156     *
6157     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6158     */
6159    /* binop/2addr vA, vB */
6160    mov     r3, rINST, lsr #12          @ r3<- B
6161    mov     r9, rINST, lsr #8           @ r9<- A+
6162    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6163    and     r9, r9, #15                 @ r9<- A
6164    flds    s1, [r3]                    @ s1<- vB
6165    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6166    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6167    flds    s0, [r9]                    @ s0<- vA
6168
6169    fdivs   s2, s0, s1                              @ s2<- op
6170    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6171    fsts    s2, [r9]                    @ vAA<- s2
6172    GOTO_OPCODE(ip)                     @ jump to next instruction
6173
6174
6175/* ------------------------------ */
6176    .balign 64
6177.L_OP_REM_FLOAT_2ADDR: /* 0xca */
6178/* File: armv5te/OP_REM_FLOAT_2ADDR.S */
6179/* EABI doesn't define a float remainder function, but libm does */
6180/* File: armv5te/binop2addr.S */
6181    /*
6182     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6183     * that specifies an instruction that performs "result = r0 op r1".
6184     * This could be an ARM instruction or a function call.  (If the result
6185     * comes back in a register other than r0, you can override "result".)
6186     *
6187     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6188     * vCC (r1).  Useful for integer division and modulus.
6189     *
6190     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6191     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6192     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6193     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6194     */
6195    /* binop/2addr vA, vB */
6196    mov     r9, rINST, lsr #8           @ r9<- A+
6197    mov     r3, rINST, lsr #12          @ r3<- B
6198    and     r9, r9, #15
6199    GET_VREG(r1, r3)                    @ r1<- vB
6200    GET_VREG(r0, r9)                    @ r0<- vA
6201    .if 0
6202    cmp     r1, #0                      @ is second operand zero?
6203    beq     common_errDivideByZero
6204    .endif
6205    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6206
6207                               @ optional op; may set condition codes
6208    bl      fmodf                              @ r0<- op, r0-r3 changed
6209    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6210    SET_VREG(r0, r9)               @ vAA<- r0
6211    GOTO_OPCODE(ip)                     @ jump to next instruction
6212    /* 10-13 instructions */
6213
6214
6215/* ------------------------------ */
6216    .balign 64
6217.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
6218/* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */
6219/* File: arm-vfp/fbinopWide2addr.S */
6220    /*
6221     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6222     * an "instr" line that specifies an instruction that performs
6223     * "d2 = d0 op d1".
6224     *
6225     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6226     *      div-double/2addr
6227     */
6228    /* binop/2addr vA, vB */
6229    mov     r3, rINST, lsr #12          @ r3<- B
6230    mov     r9, rINST, lsr #8           @ r9<- A+
6231    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6232    and     r9, r9, #15                 @ r9<- A
6233    fldd    d1, [r3]                    @ d1<- vB
6234    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6235    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6236    fldd    d0, [r9]                    @ d0<- vA
6237
6238    faddd   d2, d0, d1                              @ d2<- op
6239    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6240    fstd    d2, [r9]                    @ vAA<- d2
6241    GOTO_OPCODE(ip)                     @ jump to next instruction
6242
6243
6244/* ------------------------------ */
6245    .balign 64
6246.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
6247/* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */
6248/* File: arm-vfp/fbinopWide2addr.S */
6249    /*
6250     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6251     * an "instr" line that specifies an instruction that performs
6252     * "d2 = d0 op d1".
6253     *
6254     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6255     *      div-double/2addr
6256     */
6257    /* binop/2addr vA, vB */
6258    mov     r3, rINST, lsr #12          @ r3<- B
6259    mov     r9, rINST, lsr #8           @ r9<- A+
6260    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6261    and     r9, r9, #15                 @ r9<- A
6262    fldd    d1, [r3]                    @ d1<- vB
6263    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6264    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6265    fldd    d0, [r9]                    @ d0<- vA
6266
6267    fsubd   d2, d0, d1                              @ d2<- op
6268    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6269    fstd    d2, [r9]                    @ vAA<- d2
6270    GOTO_OPCODE(ip)                     @ jump to next instruction
6271
6272
6273/* ------------------------------ */
6274    .balign 64
6275.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
6276/* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */
6277/* File: arm-vfp/fbinopWide2addr.S */
6278    /*
6279     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6280     * an "instr" line that specifies an instruction that performs
6281     * "d2 = d0 op d1".
6282     *
6283     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6284     *      div-double/2addr
6285     */
6286    /* binop/2addr vA, vB */
6287    mov     r3, rINST, lsr #12          @ r3<- B
6288    mov     r9, rINST, lsr #8           @ r9<- A+
6289    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6290    and     r9, r9, #15                 @ r9<- A
6291    fldd    d1, [r3]                    @ d1<- vB
6292    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6293    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6294    fldd    d0, [r9]                    @ d0<- vA
6295
6296    fmuld   d2, d0, d1                              @ d2<- op
6297    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6298    fstd    d2, [r9]                    @ vAA<- d2
6299    GOTO_OPCODE(ip)                     @ jump to next instruction
6300
6301
6302/* ------------------------------ */
6303    .balign 64
6304.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
6305/* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */
6306/* File: arm-vfp/fbinopWide2addr.S */
6307    /*
6308     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6309     * an "instr" line that specifies an instruction that performs
6310     * "d2 = d0 op d1".
6311     *
6312     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6313     *      div-double/2addr
6314     */
6315    /* binop/2addr vA, vB */
6316    mov     r3, rINST, lsr #12          @ r3<- B
6317    mov     r9, rINST, lsr #8           @ r9<- A+
6318    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6319    and     r9, r9, #15                 @ r9<- A
6320    fldd    d1, [r3]                    @ d1<- vB
6321    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6322    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6323    fldd    d0, [r9]                    @ d0<- vA
6324
6325    fdivd   d2, d0, d1                              @ d2<- op
6326    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6327    fstd    d2, [r9]                    @ vAA<- d2
6328    GOTO_OPCODE(ip)                     @ jump to next instruction
6329
6330
6331/* ------------------------------ */
6332    .balign 64
6333.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
6334/* File: armv5te/OP_REM_DOUBLE_2ADDR.S */
6335/* EABI doesn't define a double remainder function, but libm does */
6336/* File: armv5te/binopWide2addr.S */
6337    /*
6338     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6339     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6340     * This could be an ARM instruction or a function call.  (If the result
6341     * comes back in a register other than r0, you can override "result".)
6342     *
6343     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6344     * vCC (r1).  Useful for integer division and modulus.
6345     *
6346     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6347     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6348     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6349     *      rem-double/2addr
6350     */
6351    /* binop/2addr vA, vB */
6352    mov     r9, rINST, lsr #8           @ r9<- A+
6353    mov     r1, rINST, lsr #12          @ r1<- B
6354    and     r9, r9, #15
6355    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6356    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6357    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6358    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6359    .if 0
6360    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6361    beq     common_errDivideByZero
6362    .endif
6363    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6364
6365                               @ optional op; may set condition codes
6366    bl      fmod                              @ result<- op, r0-r3 changed
6367    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6368    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6369    GOTO_OPCODE(ip)                     @ jump to next instruction
6370    /* 12-15 instructions */
6371
6372
6373/* ------------------------------ */
6374    .balign 64
6375.L_OP_ADD_INT_LIT16: /* 0xd0 */
6376/* File: armv5te/OP_ADD_INT_LIT16.S */
6377/* File: armv5te/binopLit16.S */
6378    /*
6379     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6380     * that specifies an instruction that performs "result = r0 op r1".
6381     * This could be an ARM instruction or a function call.  (If the result
6382     * comes back in a register other than r0, you can override "result".)
6383     *
6384     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6385     * vCC (r1).  Useful for integer division and modulus.
6386     *
6387     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6388     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6389     */
6390    /* binop/lit16 vA, vB, #+CCCC */
6391    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6392    mov     r2, rINST, lsr #12          @ r2<- B
6393    mov     r9, rINST, lsr #8           @ r9<- A+
6394    GET_VREG(r0, r2)                    @ r0<- vB
6395    and     r9, r9, #15
6396    .if 0
6397    cmp     r1, #0                      @ is second operand zero?
6398    beq     common_errDivideByZero
6399    .endif
6400    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6401
6402    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6403    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6404    SET_VREG(r0, r9)               @ vAA<- r0
6405    GOTO_OPCODE(ip)                     @ jump to next instruction
6406    /* 10-13 instructions */
6407
6408
6409/* ------------------------------ */
6410    .balign 64
6411.L_OP_RSUB_INT: /* 0xd1 */
6412/* File: armv5te/OP_RSUB_INT.S */
6413/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
6414/* File: armv5te/binopLit16.S */
6415    /*
6416     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6417     * that specifies an instruction that performs "result = r0 op r1".
6418     * This could be an ARM instruction or a function call.  (If the result
6419     * comes back in a register other than r0, you can override "result".)
6420     *
6421     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6422     * vCC (r1).  Useful for integer division and modulus.
6423     *
6424     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6425     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6426     */
6427    /* binop/lit16 vA, vB, #+CCCC */
6428    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6429    mov     r2, rINST, lsr #12          @ r2<- B
6430    mov     r9, rINST, lsr #8           @ r9<- A+
6431    GET_VREG(r0, r2)                    @ r0<- vB
6432    and     r9, r9, #15
6433    .if 0
6434    cmp     r1, #0                      @ is second operand zero?
6435    beq     common_errDivideByZero
6436    .endif
6437    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6438
6439    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6440    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6441    SET_VREG(r0, r9)               @ vAA<- r0
6442    GOTO_OPCODE(ip)                     @ jump to next instruction
6443    /* 10-13 instructions */
6444
6445
6446/* ------------------------------ */
6447    .balign 64
6448.L_OP_MUL_INT_LIT16: /* 0xd2 */
6449/* File: armv5te/OP_MUL_INT_LIT16.S */
6450/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6451/* File: armv5te/binopLit16.S */
6452    /*
6453     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6454     * that specifies an instruction that performs "result = r0 op r1".
6455     * This could be an ARM instruction or a function call.  (If the result
6456     * comes back in a register other than r0, you can override "result".)
6457     *
6458     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6459     * vCC (r1).  Useful for integer division and modulus.
6460     *
6461     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6462     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6463     */
6464    /* binop/lit16 vA, vB, #+CCCC */
6465    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6466    mov     r2, rINST, lsr #12          @ r2<- B
6467    mov     r9, rINST, lsr #8           @ r9<- A+
6468    GET_VREG(r0, r2)                    @ r0<- vB
6469    and     r9, r9, #15
6470    .if 0
6471    cmp     r1, #0                      @ is second operand zero?
6472    beq     common_errDivideByZero
6473    .endif
6474    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6475
6476    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6477    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6478    SET_VREG(r0, r9)               @ vAA<- r0
6479    GOTO_OPCODE(ip)                     @ jump to next instruction
6480    /* 10-13 instructions */
6481
6482
6483/* ------------------------------ */
6484    .balign 64
6485.L_OP_DIV_INT_LIT16: /* 0xd3 */
6486/* File: armv5te/OP_DIV_INT_LIT16.S */
6487/* File: armv5te/binopLit16.S */
6488    /*
6489     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6490     * that specifies an instruction that performs "result = r0 op r1".
6491     * This could be an ARM instruction or a function call.  (If the result
6492     * comes back in a register other than r0, you can override "result".)
6493     *
6494     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6495     * vCC (r1).  Useful for integer division and modulus.
6496     *
6497     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6498     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6499     */
6500    /* binop/lit16 vA, vB, #+CCCC */
6501    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6502    mov     r2, rINST, lsr #12          @ r2<- B
6503    mov     r9, rINST, lsr #8           @ r9<- A+
6504    GET_VREG(r0, r2)                    @ r0<- vB
6505    and     r9, r9, #15
6506    .if 1
6507    cmp     r1, #0                      @ is second operand zero?
6508    beq     common_errDivideByZero
6509    .endif
6510    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6511
6512    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6513    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6514    SET_VREG(r0, r9)               @ vAA<- r0
6515    GOTO_OPCODE(ip)                     @ jump to next instruction
6516    /* 10-13 instructions */
6517
6518
6519/* ------------------------------ */
6520    .balign 64
6521.L_OP_REM_INT_LIT16: /* 0xd4 */
6522/* File: armv5te/OP_REM_INT_LIT16.S */
6523/* idivmod returns quotient in r0 and remainder in r1 */
6524/* File: armv5te/binopLit16.S */
6525    /*
6526     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6527     * that specifies an instruction that performs "result = r0 op r1".
6528     * This could be an ARM instruction or a function call.  (If the result
6529     * comes back in a register other than r0, you can override "result".)
6530     *
6531     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6532     * vCC (r1).  Useful for integer division and modulus.
6533     *
6534     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6535     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6536     */
6537    /* binop/lit16 vA, vB, #+CCCC */
6538    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6539    mov     r2, rINST, lsr #12          @ r2<- B
6540    mov     r9, rINST, lsr #8           @ r9<- A+
6541    GET_VREG(r0, r2)                    @ r0<- vB
6542    and     r9, r9, #15
6543    .if 1
6544    cmp     r1, #0                      @ is second operand zero?
6545    beq     common_errDivideByZero
6546    .endif
6547    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6548
6549    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6550    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6551    SET_VREG(r1, r9)               @ vAA<- r1
6552    GOTO_OPCODE(ip)                     @ jump to next instruction
6553    /* 10-13 instructions */
6554
6555
6556/* ------------------------------ */
6557    .balign 64
6558.L_OP_AND_INT_LIT16: /* 0xd5 */
6559/* File: armv5te/OP_AND_INT_LIT16.S */
6560/* File: armv5te/binopLit16.S */
6561    /*
6562     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6563     * that specifies an instruction that performs "result = r0 op r1".
6564     * This could be an ARM instruction or a function call.  (If the result
6565     * comes back in a register other than r0, you can override "result".)
6566     *
6567     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6568     * vCC (r1).  Useful for integer division and modulus.
6569     *
6570     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6571     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6572     */
6573    /* binop/lit16 vA, vB, #+CCCC */
6574    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6575    mov     r2, rINST, lsr #12          @ r2<- B
6576    mov     r9, rINST, lsr #8           @ r9<- A+
6577    GET_VREG(r0, r2)                    @ r0<- vB
6578    and     r9, r9, #15
6579    .if 0
6580    cmp     r1, #0                      @ is second operand zero?
6581    beq     common_errDivideByZero
6582    .endif
6583    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6584
6585    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6586    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6587    SET_VREG(r0, r9)               @ vAA<- r0
6588    GOTO_OPCODE(ip)                     @ jump to next instruction
6589    /* 10-13 instructions */
6590
6591
6592/* ------------------------------ */
6593    .balign 64
6594.L_OP_OR_INT_LIT16: /* 0xd6 */
6595/* File: armv5te/OP_OR_INT_LIT16.S */
6596/* File: armv5te/binopLit16.S */
6597    /*
6598     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6599     * that specifies an instruction that performs "result = r0 op r1".
6600     * This could be an ARM instruction or a function call.  (If the result
6601     * comes back in a register other than r0, you can override "result".)
6602     *
6603     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6604     * vCC (r1).  Useful for integer division and modulus.
6605     *
6606     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6607     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6608     */
6609    /* binop/lit16 vA, vB, #+CCCC */
6610    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6611    mov     r2, rINST, lsr #12          @ r2<- B
6612    mov     r9, rINST, lsr #8           @ r9<- A+
6613    GET_VREG(r0, r2)                    @ r0<- vB
6614    and     r9, r9, #15
6615    .if 0
6616    cmp     r1, #0                      @ is second operand zero?
6617    beq     common_errDivideByZero
6618    .endif
6619    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6620
6621    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6622    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6623    SET_VREG(r0, r9)               @ vAA<- r0
6624    GOTO_OPCODE(ip)                     @ jump to next instruction
6625    /* 10-13 instructions */
6626
6627
6628/* ------------------------------ */
6629    .balign 64
6630.L_OP_XOR_INT_LIT16: /* 0xd7 */
6631/* File: armv5te/OP_XOR_INT_LIT16.S */
6632/* File: armv5te/binopLit16.S */
6633    /*
6634     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6635     * that specifies an instruction that performs "result = r0 op r1".
6636     * This could be an ARM instruction or a function call.  (If the result
6637     * comes back in a register other than r0, you can override "result".)
6638     *
6639     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6640     * vCC (r1).  Useful for integer division and modulus.
6641     *
6642     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6643     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6644     */
6645    /* binop/lit16 vA, vB, #+CCCC */
6646    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6647    mov     r2, rINST, lsr #12          @ r2<- B
6648    mov     r9, rINST, lsr #8           @ r9<- A+
6649    GET_VREG(r0, r2)                    @ r0<- vB
6650    and     r9, r9, #15
6651    .if 0
6652    cmp     r1, #0                      @ is second operand zero?
6653    beq     common_errDivideByZero
6654    .endif
6655    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6656
6657    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
6658    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6659    SET_VREG(r0, r9)               @ vAA<- r0
6660    GOTO_OPCODE(ip)                     @ jump to next instruction
6661    /* 10-13 instructions */
6662
6663
6664/* ------------------------------ */
6665    .balign 64
6666.L_OP_ADD_INT_LIT8: /* 0xd8 */
6667/* File: armv5te/OP_ADD_INT_LIT8.S */
6668/* File: armv5te/binopLit8.S */
6669    /*
6670     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6671     * that specifies an instruction that performs "result = r0 op r1".
6672     * This could be an ARM instruction or a function call.  (If the result
6673     * comes back in a register other than r0, you can override "result".)
6674     *
6675     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6676     * vCC (r1).  Useful for integer division and modulus.
6677     *
6678     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6679     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6680     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6681     */
6682    /* binop/lit8 vAA, vBB, #+CC */
6683    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6684    mov     r9, rINST, lsr #8           @ r9<- AA
6685    and     r2, r3, #255                @ r2<- BB
6686    GET_VREG(r0, r2)                    @ r0<- vBB
6687    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6688    .if 0
6689    @cmp     r1, #0                      @ is second operand zero?
6690    beq     common_errDivideByZero
6691    .endif
6692    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6693
6694                               @ optional op; may set condition codes
6695    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6696    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6697    SET_VREG(r0, r9)               @ vAA<- r0
6698    GOTO_OPCODE(ip)                     @ jump to next instruction
6699    /* 10-12 instructions */
6700
6701
6702/* ------------------------------ */
6703    .balign 64
6704.L_OP_RSUB_INT_LIT8: /* 0xd9 */
6705/* File: armv5te/OP_RSUB_INT_LIT8.S */
6706/* File: armv5te/binopLit8.S */
6707    /*
6708     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6709     * that specifies an instruction that performs "result = r0 op r1".
6710     * This could be an ARM instruction or a function call.  (If the result
6711     * comes back in a register other than r0, you can override "result".)
6712     *
6713     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6714     * vCC (r1).  Useful for integer division and modulus.
6715     *
6716     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6717     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6718     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6719     */
6720    /* binop/lit8 vAA, vBB, #+CC */
6721    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6722    mov     r9, rINST, lsr #8           @ r9<- AA
6723    and     r2, r3, #255                @ r2<- BB
6724    GET_VREG(r0, r2)                    @ r0<- vBB
6725    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6726    .if 0
6727    @cmp     r1, #0                      @ is second operand zero?
6728    beq     common_errDivideByZero
6729    .endif
6730    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6731
6732                               @ optional op; may set condition codes
6733    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6734    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6735    SET_VREG(r0, r9)               @ vAA<- r0
6736    GOTO_OPCODE(ip)                     @ jump to next instruction
6737    /* 10-12 instructions */
6738
6739
6740/* ------------------------------ */
6741    .balign 64
6742.L_OP_MUL_INT_LIT8: /* 0xda */
6743/* File: armv5te/OP_MUL_INT_LIT8.S */
6744/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6745/* File: armv5te/binopLit8.S */
6746    /*
6747     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6748     * that specifies an instruction that performs "result = r0 op r1".
6749     * This could be an ARM instruction or a function call.  (If the result
6750     * comes back in a register other than r0, you can override "result".)
6751     *
6752     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6753     * vCC (r1).  Useful for integer division and modulus.
6754     *
6755     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6756     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6757     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6758     */
6759    /* binop/lit8 vAA, vBB, #+CC */
6760    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6761    mov     r9, rINST, lsr #8           @ r9<- AA
6762    and     r2, r3, #255                @ r2<- BB
6763    GET_VREG(r0, r2)                    @ r0<- vBB
6764    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6765    .if 0
6766    @cmp     r1, #0                      @ is second operand zero?
6767    beq     common_errDivideByZero
6768    .endif
6769    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6770
6771                               @ optional op; may set condition codes
6772    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6773    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6774    SET_VREG(r0, r9)               @ vAA<- r0
6775    GOTO_OPCODE(ip)                     @ jump to next instruction
6776    /* 10-12 instructions */
6777
6778
6779/* ------------------------------ */
6780    .balign 64
6781.L_OP_DIV_INT_LIT8: /* 0xdb */
6782/* File: armv5te/OP_DIV_INT_LIT8.S */
6783/* File: armv5te/binopLit8.S */
6784    /*
6785     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6786     * that specifies an instruction that performs "result = r0 op r1".
6787     * This could be an ARM instruction or a function call.  (If the result
6788     * comes back in a register other than r0, you can override "result".)
6789     *
6790     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6791     * vCC (r1).  Useful for integer division and modulus.
6792     *
6793     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6794     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6795     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6796     */
6797    /* binop/lit8 vAA, vBB, #+CC */
6798    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6799    mov     r9, rINST, lsr #8           @ r9<- AA
6800    and     r2, r3, #255                @ r2<- BB
6801    GET_VREG(r0, r2)                    @ r0<- vBB
6802    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6803    .if 1
6804    @cmp     r1, #0                      @ is second operand zero?
6805    beq     common_errDivideByZero
6806    .endif
6807    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6808
6809                               @ optional op; may set condition codes
6810    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6811    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6812    SET_VREG(r0, r9)               @ vAA<- r0
6813    GOTO_OPCODE(ip)                     @ jump to next instruction
6814    /* 10-12 instructions */
6815
6816
6817/* ------------------------------ */
6818    .balign 64
6819.L_OP_REM_INT_LIT8: /* 0xdc */
6820/* File: armv5te/OP_REM_INT_LIT8.S */
6821/* idivmod returns quotient in r0 and remainder in r1 */
6822/* File: armv5te/binopLit8.S */
6823    /*
6824     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6825     * that specifies an instruction that performs "result = r0 op r1".
6826     * This could be an ARM instruction or a function call.  (If the result
6827     * comes back in a register other than r0, you can override "result".)
6828     *
6829     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6830     * vCC (r1).  Useful for integer division and modulus.
6831     *
6832     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6833     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6834     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6835     */
6836    /* binop/lit8 vAA, vBB, #+CC */
6837    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6838    mov     r9, rINST, lsr #8           @ r9<- AA
6839    and     r2, r3, #255                @ r2<- BB
6840    GET_VREG(r0, r2)                    @ r0<- vBB
6841    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6842    .if 1
6843    @cmp     r1, #0                      @ is second operand zero?
6844    beq     common_errDivideByZero
6845    .endif
6846    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6847
6848                               @ optional op; may set condition codes
6849    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6850    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6851    SET_VREG(r1, r9)               @ vAA<- r1
6852    GOTO_OPCODE(ip)                     @ jump to next instruction
6853    /* 10-12 instructions */
6854
6855
6856/* ------------------------------ */
6857    .balign 64
6858.L_OP_AND_INT_LIT8: /* 0xdd */
6859/* File: armv5te/OP_AND_INT_LIT8.S */
6860/* File: armv5te/binopLit8.S */
6861    /*
6862     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6863     * that specifies an instruction that performs "result = r0 op r1".
6864     * This could be an ARM instruction or a function call.  (If the result
6865     * comes back in a register other than r0, you can override "result".)
6866     *
6867     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6868     * vCC (r1).  Useful for integer division and modulus.
6869     *
6870     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6871     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6872     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6873     */
6874    /* binop/lit8 vAA, vBB, #+CC */
6875    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6876    mov     r9, rINST, lsr #8           @ r9<- AA
6877    and     r2, r3, #255                @ r2<- BB
6878    GET_VREG(r0, r2)                    @ r0<- vBB
6879    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6880    .if 0
6881    @cmp     r1, #0                      @ is second operand zero?
6882    beq     common_errDivideByZero
6883    .endif
6884    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6885
6886                               @ optional op; may set condition codes
6887    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6888    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6889    SET_VREG(r0, r9)               @ vAA<- r0
6890    GOTO_OPCODE(ip)                     @ jump to next instruction
6891    /* 10-12 instructions */
6892
6893
6894/* ------------------------------ */
6895    .balign 64
6896.L_OP_OR_INT_LIT8: /* 0xde */
6897/* File: armv5te/OP_OR_INT_LIT8.S */
6898/* File: armv5te/binopLit8.S */
6899    /*
6900     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6901     * that specifies an instruction that performs "result = r0 op r1".
6902     * This could be an ARM instruction or a function call.  (If the result
6903     * comes back in a register other than r0, you can override "result".)
6904     *
6905     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6906     * vCC (r1).  Useful for integer division and modulus.
6907     *
6908     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6909     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6910     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6911     */
6912    /* binop/lit8 vAA, vBB, #+CC */
6913    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6914    mov     r9, rINST, lsr #8           @ r9<- AA
6915    and     r2, r3, #255                @ r2<- BB
6916    GET_VREG(r0, r2)                    @ r0<- vBB
6917    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6918    .if 0
6919    @cmp     r1, #0                      @ is second operand zero?
6920    beq     common_errDivideByZero
6921    .endif
6922    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6923
6924                               @ optional op; may set condition codes
6925    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6926    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6927    SET_VREG(r0, r9)               @ vAA<- r0
6928    GOTO_OPCODE(ip)                     @ jump to next instruction
6929    /* 10-12 instructions */
6930
6931
6932/* ------------------------------ */
6933    .balign 64
6934.L_OP_XOR_INT_LIT8: /* 0xdf */
6935/* File: armv5te/OP_XOR_INT_LIT8.S */
6936/* File: armv5te/binopLit8.S */
6937    /*
6938     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6939     * that specifies an instruction that performs "result = r0 op r1".
6940     * This could be an ARM instruction or a function call.  (If the result
6941     * comes back in a register other than r0, you can override "result".)
6942     *
6943     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6944     * vCC (r1).  Useful for integer division and modulus.
6945     *
6946     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6947     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6948     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6949     */
6950    /* binop/lit8 vAA, vBB, #+CC */
6951    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6952    mov     r9, rINST, lsr #8           @ r9<- AA
6953    and     r2, r3, #255                @ r2<- BB
6954    GET_VREG(r0, r2)                    @ r0<- vBB
6955    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6956    .if 0
6957    @cmp     r1, #0                      @ is second operand zero?
6958    beq     common_errDivideByZero
6959    .endif
6960    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6961
6962                               @ optional op; may set condition codes
6963    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
6964    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6965    SET_VREG(r0, r9)               @ vAA<- r0
6966    GOTO_OPCODE(ip)                     @ jump to next instruction
6967    /* 10-12 instructions */
6968
6969
6970/* ------------------------------ */
6971    .balign 64
6972.L_OP_SHL_INT_LIT8: /* 0xe0 */
6973/* File: armv5te/OP_SHL_INT_LIT8.S */
6974/* File: armv5te/binopLit8.S */
6975    /*
6976     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6977     * that specifies an instruction that performs "result = r0 op r1".
6978     * This could be an ARM instruction or a function call.  (If the result
6979     * comes back in a register other than r0, you can override "result".)
6980     *
6981     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6982     * vCC (r1).  Useful for integer division and modulus.
6983     *
6984     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6985     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6986     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6987     */
6988    /* binop/lit8 vAA, vBB, #+CC */
6989    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6990    mov     r9, rINST, lsr #8           @ r9<- AA
6991    and     r2, r3, #255                @ r2<- BB
6992    GET_VREG(r0, r2)                    @ r0<- vBB
6993    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6994    .if 0
6995    @cmp     r1, #0                      @ is second operand zero?
6996    beq     common_errDivideByZero
6997    .endif
6998    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6999
7000    and     r1, r1, #31                           @ optional op; may set condition codes
7001    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
7002    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7003    SET_VREG(r0, r9)               @ vAA<- r0
7004    GOTO_OPCODE(ip)                     @ jump to next instruction
7005    /* 10-12 instructions */
7006
7007
7008/* ------------------------------ */
7009    .balign 64
7010.L_OP_SHR_INT_LIT8: /* 0xe1 */
7011/* File: armv5te/OP_SHR_INT_LIT8.S */
7012/* File: armv5te/binopLit8.S */
7013    /*
7014     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7015     * that specifies an instruction that performs "result = r0 op r1".
7016     * This could be an ARM instruction or a function call.  (If the result
7017     * comes back in a register other than r0, you can override "result".)
7018     *
7019     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7020     * vCC (r1).  Useful for integer division and modulus.
7021     *
7022     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7023     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7024     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7025     */
7026    /* binop/lit8 vAA, vBB, #+CC */
7027    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7028    mov     r9, rINST, lsr #8           @ r9<- AA
7029    and     r2, r3, #255                @ r2<- BB
7030    GET_VREG(r0, r2)                    @ r0<- vBB
7031    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7032    .if 0
7033    @cmp     r1, #0                      @ is second operand zero?
7034    beq     common_errDivideByZero
7035    .endif
7036    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7037
7038    and     r1, r1, #31                           @ optional op; may set condition codes
7039    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
7040    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7041    SET_VREG(r0, r9)               @ vAA<- r0
7042    GOTO_OPCODE(ip)                     @ jump to next instruction
7043    /* 10-12 instructions */
7044
7045
7046/* ------------------------------ */
7047    .balign 64
7048.L_OP_USHR_INT_LIT8: /* 0xe2 */
7049/* File: armv5te/OP_USHR_INT_LIT8.S */
7050/* File: armv5te/binopLit8.S */
7051    /*
7052     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7053     * that specifies an instruction that performs "result = r0 op r1".
7054     * This could be an ARM instruction or a function call.  (If the result
7055     * comes back in a register other than r0, you can override "result".)
7056     *
7057     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7058     * vCC (r1).  Useful for integer division and modulus.
7059     *
7060     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7061     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7062     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7063     */
7064    /* binop/lit8 vAA, vBB, #+CC */
7065    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7066    mov     r9, rINST, lsr #8           @ r9<- AA
7067    and     r2, r3, #255                @ r2<- BB
7068    GET_VREG(r0, r2)                    @ r0<- vBB
7069    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7070    .if 0
7071    @cmp     r1, #0                      @ is second operand zero?
7072    beq     common_errDivideByZero
7073    .endif
7074    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7075
7076    and     r1, r1, #31                           @ optional op; may set condition codes
7077    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
7078    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7079    SET_VREG(r0, r9)               @ vAA<- r0
7080    GOTO_OPCODE(ip)                     @ jump to next instruction
7081    /* 10-12 instructions */
7082
7083
7084/* ------------------------------ */
7085    .balign 64
7086.L_OP_IGET_VOLATILE: /* 0xe3 */
7087/* File: armv5te/OP_IGET_VOLATILE.S */
7088/* File: armv5te/OP_IGET.S */
7089    /*
7090     * General 32-bit instance field get.
7091     *
7092     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
7093     */
7094    /* op vA, vB, field@CCCC */
7095    mov     r0, rINST, lsr #12          @ r0<- B
7096    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7097    FETCH(r1, 1)                        @ r1<- field ref CCCC
7098    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7099    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7100    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7101    cmp     r0, #0                      @ is resolved entry null?
7102    bne     .LOP_IGET_VOLATILE_finish          @ no, already resolved
71038:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7104    EXPORT_PC()                         @ resolve() could throw
7105    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7106    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7107    cmp     r0, #0
7108    bne     .LOP_IGET_VOLATILE_finish
7109    b       common_exceptionThrown
7110
7111
7112/* ------------------------------ */
7113    .balign 64
7114.L_OP_IPUT_VOLATILE: /* 0xe4 */
7115/* File: armv5te/OP_IPUT_VOLATILE.S */
7116/* File: armv5te/OP_IPUT.S */
7117    /*
7118     * General 32-bit instance field put.
7119     *
7120     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
7121     */
7122    /* op vA, vB, field@CCCC */
7123    mov     r0, rINST, lsr #12          @ r0<- B
7124    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7125    FETCH(r1, 1)                        @ r1<- field ref CCCC
7126    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7127    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7128    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7129    cmp     r0, #0                      @ is resolved entry null?
7130    bne     .LOP_IPUT_VOLATILE_finish          @ no, already resolved
71318:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7132    EXPORT_PC()                         @ resolve() could throw
7133    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7134    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7135    cmp     r0, #0                      @ success?
7136    bne     .LOP_IPUT_VOLATILE_finish          @ yes, finish up
7137    b       common_exceptionThrown
7138
7139
7140/* ------------------------------ */
7141    .balign 64
7142.L_OP_SGET_VOLATILE: /* 0xe5 */
7143/* File: armv5te/OP_SGET_VOLATILE.S */
7144/* File: armv5te/OP_SGET.S */
7145    /*
7146     * General 32-bit SGET handler.
7147     *
7148     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
7149     */
7150    /* op vAA, field@BBBB */
7151    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7152    FETCH(r1, 1)                        @ r1<- field ref BBBB
7153    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7154    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7155    cmp     r0, #0                      @ is resolved entry null?
7156    beq     .LOP_SGET_VOLATILE_resolve         @ yes, do resolve
7157.LOP_SGET_VOLATILE_finish: @ field ptr in r0
7158    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
7159    SMP_DMB                            @ acquiring load
7160    mov     r2, rINST, lsr #8           @ r2<- AA
7161    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7162    SET_VREG(r1, r2)                    @ fp[AA]<- r1
7163    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7164    GOTO_OPCODE(ip)                     @ jump to next instruction
7165
7166
7167/* ------------------------------ */
7168    .balign 64
7169.L_OP_SPUT_VOLATILE: /* 0xe6 */
7170/* File: armv5te/OP_SPUT_VOLATILE.S */
7171/* File: armv5te/OP_SPUT.S */
7172    /*
7173     * General 32-bit SPUT handler.
7174     *
7175     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
7176     */
7177    /* op vAA, field@BBBB */
7178    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7179    FETCH(r1, 1)                        @ r1<- field ref BBBB
7180    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7181    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7182    cmp     r0, #0                      @ is resolved entry null?
7183    beq     .LOP_SPUT_VOLATILE_resolve         @ yes, do resolve
7184.LOP_SPUT_VOLATILE_finish:   @ field ptr in r0
7185    mov     r2, rINST, lsr #8           @ r2<- AA
7186    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7187    GET_VREG(r1, r2)                    @ r1<- fp[AA]
7188    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7189    SMP_DMB                            @ releasing store
7190    str     r1, [r0, #offStaticField_value] @ field<- vAA
7191    GOTO_OPCODE(ip)                     @ jump to next instruction
7192
7193
7194/* ------------------------------ */
7195    .balign 64
7196.L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */
7197/* File: armv5te/OP_IGET_OBJECT_VOLATILE.S */
7198/* File: armv5te/OP_IGET.S */
7199    /*
7200     * General 32-bit instance field get.
7201     *
7202     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
7203     */
7204    /* op vA, vB, field@CCCC */
7205    mov     r0, rINST, lsr #12          @ r0<- B
7206    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7207    FETCH(r1, 1)                        @ r1<- field ref CCCC
7208    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7209    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7210    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7211    cmp     r0, #0                      @ is resolved entry null?
7212    bne     .LOP_IGET_OBJECT_VOLATILE_finish          @ no, already resolved
72138:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7214    EXPORT_PC()                         @ resolve() could throw
7215    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7216    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7217    cmp     r0, #0
7218    bne     .LOP_IGET_OBJECT_VOLATILE_finish
7219    b       common_exceptionThrown
7220
7221
7222/* ------------------------------ */
7223    .balign 64
7224.L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */
7225/* File: armv5te/OP_IGET_WIDE_VOLATILE.S */
7226/* File: armv5te/OP_IGET_WIDE.S */
7227    /*
7228     * Wide 32-bit instance field get.
7229     */
7230    /* iget-wide vA, vB, field@CCCC */
7231    mov     r0, rINST, lsr #12          @ r0<- B
7232    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7233    FETCH(r1, 1)                        @ r1<- field ref CCCC
7234    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
7235    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7236    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7237    cmp     r0, #0                      @ is resolved entry null?
7238    bne     .LOP_IGET_WIDE_VOLATILE_finish          @ no, already resolved
72398:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
7240    EXPORT_PC()                         @ resolve() could throw
7241    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7242    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7243    cmp     r0, #0
7244    bne     .LOP_IGET_WIDE_VOLATILE_finish
7245    b       common_exceptionThrown
7246
7247
7248/* ------------------------------ */
7249    .balign 64
7250.L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */
7251/* File: armv5te/OP_IPUT_WIDE_VOLATILE.S */
7252/* File: armv5te/OP_IPUT_WIDE.S */
7253    /* iput-wide vA, vB, field@CCCC */
7254    mov     r0, rINST, lsr #12          @ r0<- B
7255    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7256    FETCH(r1, 1)                        @ r1<- field ref CCCC
7257    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
7258    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7259    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7260    cmp     r0, #0                      @ is resolved entry null?
7261    bne     .LOP_IPUT_WIDE_VOLATILE_finish          @ no, already resolved
72628:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
7263    EXPORT_PC()                         @ resolve() could throw
7264    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7265    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7266    cmp     r0, #0                      @ success?
7267    bne     .LOP_IPUT_WIDE_VOLATILE_finish          @ yes, finish up
7268    b       common_exceptionThrown
7269
7270
7271/* ------------------------------ */
7272    .balign 64
7273.L_OP_SGET_WIDE_VOLATILE: /* 0xea */
7274/* File: armv5te/OP_SGET_WIDE_VOLATILE.S */
7275/* File: armv5te/OP_SGET_WIDE.S */
7276    /*
7277     * 64-bit SGET handler.
7278     */
7279    /* sget-wide vAA, field@BBBB */
7280    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7281    FETCH(r1, 1)                        @ r1<- field ref BBBB
7282    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7283    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7284    cmp     r0, #0                      @ is resolved entry null?
7285    beq     .LOP_SGET_WIDE_VOLATILE_resolve         @ yes, do resolve
7286.LOP_SGET_WIDE_VOLATILE_finish:
7287    mov     r9, rINST, lsr #8           @ r9<- AA
7288    .if 1
7289    add     r0, r0, #offStaticField_value @ r0<- pointer to data
7290    bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
7291    .else
7292    ldrd    r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
7293    .endif
7294    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
7295    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7296    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
7297    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7298    GOTO_OPCODE(ip)                     @ jump to next instruction
7299
7300
7301/* ------------------------------ */
7302    .balign 64
7303.L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */
7304/* File: armv5te/OP_SPUT_WIDE_VOLATILE.S */
7305/* File: armv5te/OP_SPUT_WIDE.S */
7306    /*
7307     * 64-bit SPUT handler.
7308     */
7309    /* sput-wide vAA, field@BBBB */
7310    ldr     r0, [rGLUE, #offGlue_methodClassDex]  @ r0<- DvmDex
7311    FETCH(r1, 1)                        @ r1<- field ref BBBB
7312    ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
7313    mov     r9, rINST, lsr #8           @ r9<- AA
7314    ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
7315    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
7316    cmp     r2, #0                      @ is resolved entry null?
7317    beq     .LOP_SPUT_WIDE_VOLATILE_resolve         @ yes, do resolve
7318.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9
7319    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7320    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
7321    GET_INST_OPCODE(r10)                @ extract opcode from rINST
7322    .if 1
7323    add     r2, r2, #offStaticField_value @ r2<- pointer to data
7324    bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
7325    .else
7326    strd    r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
7327    .endif
7328    GOTO_OPCODE(r10)                    @ jump to next instruction
7329
7330
7331/* ------------------------------ */
7332    .balign 64
7333.L_OP_BREAKPOINT: /* 0xec */
7334/* File: armv5te/OP_BREAKPOINT.S */
7335/* File: armv5te/unused.S */
7336    bl      common_abort
7337
7338
7339/* ------------------------------ */
7340    .balign 64
7341.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
7342/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
7343    /*
7344     * Handle a throw-verification-error instruction.  This throws an
7345     * exception for an error discovered during verification.  The
7346     * exception is indicated by AA, with some detail provided by BBBB.
7347     */
7348    /* op AA, ref@BBBB */
7349    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7350    FETCH(r2, 1)                        @ r2<- BBBB
7351    EXPORT_PC()                         @ export the PC
7352    mov     r1, rINST, lsr #8           @ r1<- AA
7353    bl      dvmThrowVerificationError   @ always throws
7354    b       common_exceptionThrown      @ handle exception
7355
7356/* ------------------------------ */
7357    .balign 64
7358.L_OP_EXECUTE_INLINE: /* 0xee */
7359/* File: armv5te/OP_EXECUTE_INLINE.S */
7360    /*
7361     * Execute a "native inline" instruction.
7362     *
7363     * We need to call an InlineOp4Func:
7364     *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7365     *
7366     * The first four args are in r0-r3, pointer to return value storage
7367     * is on the stack.  The function's return value is a flag that tells
7368     * us if an exception was thrown.
7369     */
7370    /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
7371    FETCH(r10, 1)                       @ r10<- BBBB
7372    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7373    EXPORT_PC()                         @ can throw
7374    sub     sp, sp, #8                  @ make room for arg, +64 bit align
7375    mov     r0, rINST, lsr #12          @ r0<- B
7376    str     r1, [sp]                    @ push &glue->retval
7377    bl      .LOP_EXECUTE_INLINE_continue        @ make call; will return after
7378    add     sp, sp, #8                  @ pop stack
7379    cmp     r0, #0                      @ test boolean result of inline
7380    beq     common_exceptionThrown      @ returned false, handle exception
7381    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7382    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7383    GOTO_OPCODE(ip)                     @ jump to next instruction
7384
7385/* ------------------------------ */
7386    .balign 64
7387.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */
7388/* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */
7389    /*
7390     * Execute a "native inline" instruction, using "/range" semantics.
7391     * Same idea as execute-inline, but we get the args differently.
7392     *
7393     * We need to call an InlineOp4Func:
7394     *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7395     *
7396     * The first four args are in r0-r3, pointer to return value storage
7397     * is on the stack.  The function's return value is a flag that tells
7398     * us if an exception was thrown.
7399     */
7400    /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */
7401    FETCH(r10, 1)                       @ r10<- BBBB
7402    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7403    EXPORT_PC()                         @ can throw
7404    sub     sp, sp, #8                  @ make room for arg, +64 bit align
7405    mov     r0, rINST, lsr #8           @ r0<- AA
7406    str     r1, [sp]                    @ push &glue->retval
7407    bl      .LOP_EXECUTE_INLINE_RANGE_continue        @ make call; will return after
7408    add     sp, sp, #8                  @ pop stack
7409    cmp     r0, #0                      @ test boolean result of inline
7410    beq     common_exceptionThrown      @ returned false, handle exception
7411    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7412    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7413    GOTO_OPCODE(ip)                     @ jump to next instruction
7414
7415/* ------------------------------ */
7416    .balign 64
7417.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
7418/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
7419    /*
7420     * invoke-direct-empty is a no-op in a "standard" interpreter.
7421     */
7422    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7423    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7424    GOTO_OPCODE(ip)                     @ execute it
7425
7426/* ------------------------------ */
7427    .balign 64
7428.L_OP_RETURN_VOID_BARRIER: /* 0xf1 */
7429/* File: armv5te/OP_RETURN_VOID_BARRIER.S */
7430    SMP_DMB_ST
7431    b       common_returnFromMethod
7432
7433/* ------------------------------ */
7434    .balign 64
7435.L_OP_IGET_QUICK: /* 0xf2 */
7436/* File: armv5te/OP_IGET_QUICK.S */
7437    /* For: iget-quick, iget-object-quick */
7438    /* op vA, vB, offset@CCCC */
7439    mov     r2, rINST, lsr #12          @ r2<- B
7440    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7441    FETCH(r1, 1)                        @ r1<- field byte offset
7442    cmp     r3, #0                      @ check object for null
7443    mov     r2, rINST, lsr #8           @ r2<- A(+)
7444    beq     common_errNullObject        @ object was null
7445    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7446    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7447    and     r2, r2, #15
7448    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7449    SET_VREG(r0, r2)                    @ fp[A]<- r0
7450    GOTO_OPCODE(ip)                     @ jump to next instruction
7451
7452/* ------------------------------ */
7453    .balign 64
7454.L_OP_IGET_WIDE_QUICK: /* 0xf3 */
7455/* File: armv5te/OP_IGET_WIDE_QUICK.S */
7456    /* iget-wide-quick vA, vB, offset@CCCC */
7457    mov     r2, rINST, lsr #12          @ r2<- B
7458    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7459    FETCH(ip, 1)                        @ ip<- field byte offset
7460    cmp     r3, #0                      @ check object for null
7461    mov     r2, rINST, lsr #8           @ r2<- A(+)
7462    beq     common_errNullObject        @ object was null
7463    ldrd    r0, [r3, ip]                @ r0<- obj.field (64 bits, aligned)
7464    and     r2, r2, #15
7465    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7466    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
7467    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7468    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
7469    GOTO_OPCODE(ip)                     @ jump to next instruction
7470
7471/* ------------------------------ */
7472    .balign 64
7473.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
7474/* File: armv5te/OP_IGET_OBJECT_QUICK.S */
7475/* File: armv5te/OP_IGET_QUICK.S */
7476    /* For: iget-quick, iget-object-quick */
7477    /* op vA, vB, offset@CCCC */
7478    mov     r2, rINST, lsr #12          @ r2<- B
7479    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7480    FETCH(r1, 1)                        @ r1<- field byte offset
7481    cmp     r3, #0                      @ check object for null
7482    mov     r2, rINST, lsr #8           @ r2<- A(+)
7483    beq     common_errNullObject        @ object was null
7484    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7485    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7486    and     r2, r2, #15
7487    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7488    SET_VREG(r0, r2)                    @ fp[A]<- r0
7489    GOTO_OPCODE(ip)                     @ jump to next instruction
7490
7491
7492/* ------------------------------ */
7493    .balign 64
7494.L_OP_IPUT_QUICK: /* 0xf5 */
7495/* File: armv5te/OP_IPUT_QUICK.S */
7496    /* For: iput-quick */
7497    /* op vA, vB, offset@CCCC */
7498    mov     r2, rINST, lsr #12          @ r2<- B
7499    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7500    FETCH(r1, 1)                        @ r1<- field byte offset
7501    cmp     r3, #0                      @ check object for null
7502    mov     r2, rINST, lsr #8           @ r2<- A(+)
7503    beq     common_errNullObject        @ object was null
7504    and     r2, r2, #15
7505    GET_VREG(r0, r2)                    @ r0<- fp[A]
7506    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7507    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7508    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7509    GOTO_OPCODE(ip)                     @ jump to next instruction
7510
7511/* ------------------------------ */
7512    .balign 64
7513.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
7514/* File: armv5te/OP_IPUT_WIDE_QUICK.S */
7515    /* iput-wide-quick vA, vB, offset@CCCC */
7516    mov     r0, rINST, lsr #8           @ r0<- A(+)
7517    mov     r1, rINST, lsr #12          @ r1<- B
7518    and     r0, r0, #15
7519    GET_VREG(r2, r1)                    @ r2<- fp[B], the object pointer
7520    add     r3, rFP, r0, lsl #2         @ r3<- &fp[A]
7521    cmp     r2, #0                      @ check object for null
7522    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[A]
7523    beq     common_errNullObject        @ object was null
7524    FETCH(r3, 1)                        @ r3<- field byte offset
7525    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7526    strd    r0, [r2, r3]                @ obj.field (64 bits, aligned)<- r0/r1
7527    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7528    GOTO_OPCODE(ip)                     @ jump to next instruction
7529
7530/* ------------------------------ */
7531    .balign 64
7532.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
7533/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
7534    /* For: iput-object-quick */
7535    /* op vA, vB, offset@CCCC */
7536    mov     r2, rINST, lsr #12          @ r2<- B
7537    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7538    FETCH(r1, 1)                        @ r1<- field byte offset
7539    cmp     r3, #0                      @ check object for null
7540    mov     r2, rINST, lsr #8           @ r2<- A(+)
7541    beq     common_errNullObject        @ object was null
7542    and     r2, r2, #15
7543    GET_VREG(r0, r2)                    @ r0<- fp[A]
7544    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
7545    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7546    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7547    cmp     r0, #0
7548    strneb  r2, [r2, r3, lsr #GC_CARD_SHIFT] @ mark card based on obj head
7549    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7550    GOTO_OPCODE(ip)                     @ jump to next instruction
7551
7552/* ------------------------------ */
7553    .balign 64
7554.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
7555/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7556    /*
7557     * Handle an optimized virtual method call.
7558     *
7559     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7560     */
7561    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7562    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7563    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7564    FETCH(r1, 1)                        @ r1<- BBBB
7565    .if     (!0)
7566    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7567    .endif
7568    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7569    cmp     r2, #0                      @ is "this" null?
7570    beq     common_errNullObject        @ null "this", throw exception
7571    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7572    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7573    EXPORT_PC()                         @ invoke must export
7574    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7575    bl      common_invokeMethodNoRange @ continue on
7576
7577/* ------------------------------ */
7578    .balign 64
7579.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
7580/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
7581/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7582    /*
7583     * Handle an optimized virtual method call.
7584     *
7585     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7586     */
7587    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7588    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7589    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7590    FETCH(r1, 1)                        @ r1<- BBBB
7591    .if     (!1)
7592    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7593    .endif
7594    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7595    cmp     r2, #0                      @ is "this" null?
7596    beq     common_errNullObject        @ null "this", throw exception
7597    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7598    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7599    EXPORT_PC()                         @ invoke must export
7600    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7601    bl      common_invokeMethodRange @ continue on
7602
7603
7604/* ------------------------------ */
7605    .balign 64
7606.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
7607/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7608    /*
7609     * Handle an optimized "super" method call.
7610     *
7611     * for: [opt] invoke-super-quick, invoke-super-quick/range
7612     */
7613    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7614    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7615    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7616    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7617    .if     (!0)
7618    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7619    .endif
7620    FETCH(r1, 1)                        @ r1<- BBBB
7621    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7622    EXPORT_PC()                         @ must export for invoke
7623    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7624    GET_VREG(r3, r10)                   @ r3<- "this"
7625    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7626    cmp     r3, #0                      @ null "this" ref?
7627    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7628    beq     common_errNullObject        @ "this" is null, throw exception
7629    bl      common_invokeMethodNoRange @ continue on
7630
7631/* ------------------------------ */
7632    .balign 64
7633.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
7634/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
7635/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7636    /*
7637     * Handle an optimized "super" method call.
7638     *
7639     * for: [opt] invoke-super-quick, invoke-super-quick/range
7640     */
7641    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7642    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7643    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7644    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7645    .if     (!1)
7646    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7647    .endif
7648    FETCH(r1, 1)                        @ r1<- BBBB
7649    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7650    EXPORT_PC()                         @ must export for invoke
7651    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7652    GET_VREG(r3, r10)                   @ r3<- "this"
7653    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7654    cmp     r3, #0                      @ null "this" ref?
7655    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7656    beq     common_errNullObject        @ "this" is null, throw exception
7657    bl      common_invokeMethodRange @ continue on
7658
7659
7660/* ------------------------------ */
7661    .balign 64
7662.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */
7663/* File: armv5te/OP_IPUT_OBJECT_VOLATILE.S */
7664/* File: armv5te/OP_IPUT_OBJECT.S */
7665    /*
7666     * 32-bit instance field put.
7667     *
7668     * for: iput-object, iput-object-volatile
7669     */
7670    /* op vA, vB, field@CCCC */
7671    mov     r0, rINST, lsr #12          @ r0<- B
7672    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7673    FETCH(r1, 1)                        @ r1<- field ref CCCC
7674    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7675    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7676    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7677    cmp     r0, #0                      @ is resolved entry null?
7678    bne     .LOP_IPUT_OBJECT_VOLATILE_finish          @ no, already resolved
76798:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7680    EXPORT_PC()                         @ resolve() could throw
7681    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7682    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7683    cmp     r0, #0                      @ success?
7684    bne     .LOP_IPUT_OBJECT_VOLATILE_finish          @ yes, finish up
7685    b       common_exceptionThrown
7686
7687
7688/* ------------------------------ */
7689    .balign 64
7690.L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */
7691/* File: armv5te/OP_SGET_OBJECT_VOLATILE.S */
7692/* File: armv5te/OP_SGET.S */
7693    /*
7694     * General 32-bit SGET handler.
7695     *
7696     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
7697     */
7698    /* op vAA, field@BBBB */
7699    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7700    FETCH(r1, 1)                        @ r1<- field ref BBBB
7701    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7702    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7703    cmp     r0, #0                      @ is resolved entry null?
7704    beq     .LOP_SGET_OBJECT_VOLATILE_resolve         @ yes, do resolve
7705.LOP_SGET_OBJECT_VOLATILE_finish: @ field ptr in r0
7706    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
7707    SMP_DMB                            @ acquiring load
7708    mov     r2, rINST, lsr #8           @ r2<- AA
7709    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7710    SET_VREG(r1, r2)                    @ fp[AA]<- r1
7711    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7712    GOTO_OPCODE(ip)                     @ jump to next instruction
7713
7714
7715/* ------------------------------ */
7716    .balign 64
7717.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */
7718/* File: armv5te/OP_SPUT_OBJECT_VOLATILE.S */
7719/* File: armv5te/OP_SPUT_OBJECT.S */
7720    /*
7721     * 32-bit SPUT handler for objects
7722     *
7723     * for: sput-object, sput-object-volatile
7724     */
7725    /* op vAA, field@BBBB */
7726    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7727    FETCH(r1, 1)                        @ r1<- field ref BBBB
7728    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7729    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7730    cmp     r0, #0                      @ is resolved entry null?
7731    bne     .LOP_SPUT_OBJECT_VOLATILE_finish          @ no, continue
7732    ldr     r9, [rGLUE, #offGlue_method]    @ r9<- current method
7733    EXPORT_PC()                         @ resolve() could throw, so export now
7734    ldr     r0, [r9, #offMethod_clazz]  @ r0<- method->clazz
7735    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
7736    cmp     r0, #0                      @ success?
7737    bne     .LOP_SPUT_OBJECT_VOLATILE_finish          @ yes, finish
7738    b       common_exceptionThrown      @ no, handle exception
7739
7740
7741
7742/* ------------------------------ */
7743    .balign 64
7744.L_OP_DISPATCH_FF: /* 0xff */
7745/* File: armv5te/OP_DISPATCH_FF.S */
7746    mov     ip, rINST, lsr #8           @ r9<- extended opcode
7747    add     ip, ip, #256                @ add offset for extended opcodes
7748    GOTO_OPCODE(ip)                     @ go to proper extended handler
7749
7750
7751/* ------------------------------ */
7752    .balign 64
7753.L_OP_CONST_CLASS_JUMBO: /* 0x100 */
7754/* File: armv5te/OP_CONST_CLASS_JUMBO.S */
7755    /* const-class/jumbo vBBBB, Class@AAAAAAAA */
7756    FETCH(r0, 1)                        @ r0<- aaaa (lo)
7757    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
7758    FETCH(r1, 2)                        @ r1<- AAAA (hi)
7759    ldr     r2, [r2, #offDvmDex_pResClasses]   @ r2<- dvmDex->pResClasses
7760    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
7761    FETCH(r9, 3)                        @ r9<- BBBB
7762    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResClasses[AAAAaaaa]
7763    cmp     r0, #0                      @ not yet resolved?
7764    beq     .LOP_CONST_CLASS_JUMBO_resolve
7765    FETCH_ADVANCE_INST(4)               @ advance rPC, load rINST
7766    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7767    SET_VREG(r0, r9)                    @ vBBBB<- r0
7768    GOTO_OPCODE(ip)                     @ jump to next instruction
7769
7770/* ------------------------------ */
7771    .balign 64
7772.L_OP_CHECK_CAST_JUMBO: /* 0x101 */
7773/* File: armv5te/OP_CHECK_CAST_JUMBO.S */
7774    /*
7775     * Check to see if a cast from one class to another is allowed.
7776     */
7777    /* check-cast/jumbo vBBBB, class@AAAAAAAA */
7778    FETCH(r0, 1)                        @ r0<- aaaa (lo)
7779    FETCH(r2, 2)                        @ r2<- AAAA (hi)
7780    FETCH(r3, 3)                        @ r3<- BBBB
7781    orr     r2, r0, r2, lsl #16         @ r2<- AAAAaaaa
7782    GET_VREG(r9, r3)                    @ r9<- object
7783    ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- pDvmDex
7784    cmp     r9, #0                      @ is object null?
7785    ldr     r0, [r0, #offDvmDex_pResClasses]    @ r0<- pDvmDex->pResClasses
7786    beq     .LOP_CHECK_CAST_JUMBO_okay            @ null obj, cast always succeeds
7787    ldr     r1, [r0, r2, lsl #2]        @ r1<- resolved class
7788    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
7789    cmp     r1, #0                      @ have we resolved this before?
7790    beq     .LOP_CHECK_CAST_JUMBO_resolve         @ not resolved, do it now
7791.LOP_CHECK_CAST_JUMBO_resolved:
7792    cmp     r0, r1                      @ same class (trivial success)?
7793    bne     .LOP_CHECK_CAST_JUMBO_fullcheck       @ no, do full check
7794    b       .LOP_CHECK_CAST_JUMBO_okay            @ yes, finish up
7795
7796/* ------------------------------ */
7797    .balign 64
7798.L_OP_INSTANCE_OF_JUMBO: /* 0x102 */
7799/* File: armv5te/OP_INSTANCE_OF_JUMBO.S */
7800    /*
7801     * Check to see if an object reference is an instance of a class.
7802     *
7803     * Most common situation is a non-null object, being compared against
7804     * an already-resolved class.
7805     *
7806     * TODO: convert most of this into a common subroutine, shared with
7807     *       OP_INSTANCE_OF.S.
7808     */
7809    /* instance-of/jumbo vBBBB, vCCCC, class@AAAAAAAA */
7810    FETCH(r3, 4)                        @ r3<- vCCCC
7811    FETCH(r9, 3)                        @ r9<- vBBBB
7812    GET_VREG(r0, r3)                    @ r0<- vCCCC (object)
7813    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- pDvmDex
7814    cmp     r0, #0                      @ is object null?
7815    beq     .LOP_INSTANCE_OF_JUMBO_store           @ null obj, not an instance, store r0
7816    FETCH(r1, 1)                        @ r1<- aaaa (lo)
7817    FETCH(r3, 2)                        @ r3<- AAAA (hi)
7818    ldr     r2, [r2, #offDvmDex_pResClasses]    @ r2<- pDvmDex->pResClasses
7819    orr     r3, r1, r3, lsl #16         @ r3<- AAAAaaaa
7820    ldr     r1, [r2, r3, lsl #2]        @ r1<- resolved class
7821    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
7822    cmp     r1, #0                      @ have we resolved this before?
7823    beq     .LOP_INSTANCE_OF_JUMBO_resolve         @ not resolved, do it now
7824    b       .LOP_INSTANCE_OF_JUMBO_resolved        @ resolved, continue
7825
7826/* ------------------------------ */
7827    .balign 64
7828.L_OP_NEW_INSTANCE_JUMBO: /* 0x103 */
7829/* File: armv5te/OP_NEW_INSTANCE_JUMBO.S */
7830    /*
7831     * Create a new instance of a class.
7832     */
7833    /* new-instance/jumbo vBBBB, class@AAAAAAAA */
7834    FETCH(r0, 1)                        @ r0<- aaaa (lo)
7835    FETCH(r1, 2)                        @ r1<- AAAA (hi)
7836    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
7837    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
7838    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
7839    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
7840    EXPORT_PC()                         @ req'd for init, resolve, alloc
7841    cmp     r0, #0                      @ already resolved?
7842    beq     .LOP_NEW_INSTANCE_JUMBO_resolve         @ no, resolve it now
7843.LOP_NEW_INSTANCE_JUMBO_resolved:   @ r0=class
7844    ldrb    r1, [r0, #offClassObject_status]    @ r1<- ClassStatus enum
7845    cmp     r1, #CLASS_INITIALIZED      @ has class been initialized?
7846    bne     .LOP_NEW_INSTANCE_JUMBO_needinit        @ no, init class now
7847.LOP_NEW_INSTANCE_JUMBO_initialized: @ r0=class
7848    mov     r1, #ALLOC_DONT_TRACK       @ flags for alloc call
7849    bl      dvmAllocObject              @ r0<- new object
7850    b       .LOP_NEW_INSTANCE_JUMBO_finish          @ continue
7851
7852/* ------------------------------ */
7853    .balign 64
7854.L_OP_NEW_ARRAY_JUMBO: /* 0x104 */
7855/* File: armv5te/OP_NEW_ARRAY_JUMBO.S */
7856    /*
7857     * Allocate an array of objects, specified with the array class
7858     * and a count.
7859     *
7860     * The verifier guarantees that this is an array class, so we don't
7861     * check for it here.
7862     */
7863    /* new-array/jumbo vBBBB, vCCCC, class@AAAAAAAA */
7864    FETCH(r2, 1)                        @ r2<- aaaa (lo)
7865    FETCH(r3, 2)                        @ r3<- AAAA (hi)
7866    FETCH(r0, 4)                        @ r0<- vCCCC
7867    orr     r2, r2, r3, lsl #16         @ r2<- AAAAaaaa
7868    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
7869    GET_VREG(r1, r0)                    @ r1<- vCCCC (array length)
7870    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
7871    cmp     r1, #0                      @ check length
7872    ldr     r0, [r3, r2, lsl #2]        @ r0<- resolved class
7873    bmi     common_errNegativeArraySize @ negative length, bail
7874    cmp     r0, #0                      @ already resolved?
7875    EXPORT_PC()                         @ req'd for resolve, alloc
7876    bne     .LOP_NEW_ARRAY_JUMBO_finish          @ resolved, continue
7877    b       .LOP_NEW_ARRAY_JUMBO_resolve         @ do resolve now
7878
7879/* ------------------------------ */
7880    .balign 64
7881.L_OP_FILLED_NEW_ARRAY_JUMBO: /* 0x105 */
7882/* File: armv5te/OP_FILLED_NEW_ARRAY_JUMBO.S */
7883    /*
7884     * Create a new array with elements filled from registers.
7885     *
7886     * TODO: convert most of this into a common subroutine, shared with
7887     *       OP_FILLED_NEW_ARRAY.S.
7888     */
7889    /* filled-new-array/jumbo {vCCCC..v(CCCC+BBBB-1)}, type@AAAAAAAA */
7890    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
7891    FETCH(r0, 1)                        @ r0<- aaaa (lo)
7892    FETCH(r1, 2)                        @ r1<- AAAA (hi)
7893    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
7894    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
7895    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
7896    EXPORT_PC()                         @ need for resolve and alloc
7897    cmp     r0, #0                      @ already resolved?
7898    bne     .LOP_FILLED_NEW_ARRAY_JUMBO_continue        @ yes, continue on
78998:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7900    mov     r2, #0                      @ r2<- false
7901    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7902    bl      dvmResolveClass             @ r0<- call(clazz, ref)
7903    cmp     r0, #0                      @ got null?
7904    beq     common_exceptionThrown      @ yes, handle exception
7905    b       .LOP_FILLED_NEW_ARRAY_JUMBO_continue
7906
7907/* ------------------------------ */
7908    .balign 64
7909.L_OP_IGET_JUMBO: /* 0x106 */
7910/* File: armv5te/OP_IGET_JUMBO.S */
7911    /*
7912     * Jumbo 32-bit instance field get.
7913     *
7914     * for: iget/jumbo, iget-object/jumbo, iget-boolean/jumbo, iget-byte/jumbo,
7915     *      iget-char/jumbo, iget-short/jumbo
7916     */
7917    /* exop vBBBB, vCCCC, field@AAAAAAAA */
7918    FETCH(r1, 1)                        @ r1<- aaaa (lo)
7919    FETCH(r2, 2)                        @ r2<- AAAA (hi)
7920    FETCH(r0, 4)                        @ r0<- CCCC
7921    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7922    orr     r1, r1, r2, lsl #16         @ r1<- AAAAaaaa
7923    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7924    GET_VREG(r9, r0)                    @ r9<- fp[CCCC], the object pointer
7925    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7926    cmp     r0, #0                      @ is resolved entry null?
7927    bne     .LOP_IGET_JUMBO_finish          @ no, already resolved
79288:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7929    EXPORT_PC()                         @ resolve() could throw
7930    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7931    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7932    b       .LOP_IGET_JUMBO_resolved        @ resolved, continue
7933
7934/* ------------------------------ */
7935    .balign 64
7936.L_OP_IGET_WIDE_JUMBO: /* 0x107 */
7937/* File: armv5te/OP_IGET_WIDE_JUMBO.S */
7938    /*
7939     * Jumbo 64-bit instance field get.
7940     */
7941    /* iget-wide/jumbo vBBBB, vCCCC, field@AAAAAAAA */
7942    FETCH(r1, 1)                        @ r1<- aaaa (lo)
7943    FETCH(r2, 2)                        @ r2<- AAAA (hi)
7944    FETCH(r0, 4)                        @ r0<- CCCC
7945    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7946    orr     r1, r1, r2, lsl #16         @ r1<- AAAAaaaa
7947    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
7948    GET_VREG(r9, r0)                    @ r9<- fp[CCCC], the object pointer
7949    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7950    cmp     r0, #0                      @ is resolved entry null?
7951    bne     .LOP_IGET_WIDE_JUMBO_finish          @ no, already resolved
79528:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
7953    EXPORT_PC()                         @ resolve() could throw
7954    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7955    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7956    b       .LOP_IGET_WIDE_JUMBO_resolved        @ resolved, continue
7957
7958/* ------------------------------ */
7959    .balign 64
7960.L_OP_IGET_OBJECT_JUMBO: /* 0x108 */
7961/* File: armv5te/OP_IGET_OBJECT_JUMBO.S */
7962/* File: armv5te/OP_IGET_JUMBO.S */
7963    /*
7964     * Jumbo 32-bit instance field get.
7965     *
7966     * for: iget/jumbo, iget-object/jumbo, iget-boolean/jumbo, iget-byte/jumbo,
7967     *      iget-char/jumbo, iget-short/jumbo
7968     */
7969    /* exop vBBBB, vCCCC, field@AAAAAAAA */
7970    FETCH(r1, 1)                        @ r1<- aaaa (lo)
7971    FETCH(r2, 2)                        @ r2<- AAAA (hi)
7972    FETCH(r0, 4)                        @ r0<- CCCC
7973    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7974    orr     r1, r1, r2, lsl #16         @ r1<- AAAAaaaa
7975    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7976    GET_VREG(r9, r0)                    @ r9<- fp[CCCC], the object pointer
7977    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7978    cmp     r0, #0                      @ is resolved entry null?
7979    bne     .LOP_IGET_OBJECT_JUMBO_finish          @ no, already resolved
79808:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7981    EXPORT_PC()                         @ resolve() could throw
7982    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7983    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7984    b       .LOP_IGET_OBJECT_JUMBO_resolved        @ resolved, continue
7985
7986
7987/* ------------------------------ */
7988    .balign 64
7989.L_OP_IGET_BOOLEAN_JUMBO: /* 0x109 */
7990/* File: armv5te/OP_IGET_BOOLEAN_JUMBO.S */
7991@include "armv5te/OP_IGET_JUMBO.S" { "load":"ldrb", "sqnum":"1" }
7992/* File: armv5te/OP_IGET_JUMBO.S */
7993    /*
7994     * Jumbo 32-bit instance field get.
7995     *
7996     * for: iget/jumbo, iget-object/jumbo, iget-boolean/jumbo, iget-byte/jumbo,
7997     *      iget-char/jumbo, iget-short/jumbo
7998     */
7999    /* exop vBBBB, vCCCC, field@AAAAAAAA */
8000    FETCH(r1, 1)                        @ r1<- aaaa (lo)
8001    FETCH(r2, 2)                        @ r2<- AAAA (hi)
8002    FETCH(r0, 4)                        @ r0<- CCCC
8003    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
8004    orr     r1, r1, r2, lsl #16         @ r1<- AAAAaaaa
8005    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
8006    GET_VREG(r9, r0)                    @ r9<- fp[CCCC], the object pointer
8007    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
8008    cmp     r0, #0                      @ is resolved entry null?
8009    bne     .LOP_IGET_BOOLEAN_JUMBO_finish          @ no, already resolved
80108:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8011    EXPORT_PC()                         @ resolve() could throw
8012    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8013    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
8014    b       .LOP_IGET_BOOLEAN_JUMBO_resolved        @ resolved, continue
8015
8016
8017/* ------------------------------ */
8018    .balign 64
8019.L_OP_IGET_BYTE_JUMBO: /* 0x10a */
8020/* File: armv5te/OP_IGET_BYTE_JUMBO.S */
8021@include "armv5te/OP_IGET_JUMBO.S" { "load":"ldrsb", "sqnum":"2" }
8022/* File: armv5te/OP_IGET_JUMBO.S */
8023    /*
8024     * Jumbo 32-bit instance field get.
8025     *
8026     * for: iget/jumbo, iget-object/jumbo, iget-boolean/jumbo, iget-byte/jumbo,
8027     *      iget-char/jumbo, iget-short/jumbo
8028     */
8029    /* exop vBBBB, vCCCC, field@AAAAAAAA */
8030    FETCH(r1, 1)                        @ r1<- aaaa (lo)
8031    FETCH(r2, 2)                        @ r2<- AAAA (hi)
8032    FETCH(r0, 4)                        @ r0<- CCCC
8033    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
8034    orr     r1, r1, r2, lsl #16         @ r1<- AAAAaaaa
8035    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
8036    GET_VREG(r9, r0)                    @ r9<- fp[CCCC], the object pointer
8037    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
8038    cmp     r0, #0                      @ is resolved entry null?
8039    bne     .LOP_IGET_BYTE_JUMBO_finish          @ no, already resolved
80408:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8041    EXPORT_PC()                         @ resolve() could throw
8042    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8043    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
8044    b       .LOP_IGET_BYTE_JUMBO_resolved        @ resolved, continue
8045
8046
8047/* ------------------------------ */
8048    .balign 64
8049.L_OP_IGET_CHAR_JUMBO: /* 0x10b */
8050/* File: armv5te/OP_IGET_CHAR_JUMBO.S */
8051@include "armv5te/OP_IGET_JUMBO.S" { "load":"ldrh", "sqnum":"3" }
8052/* File: armv5te/OP_IGET_JUMBO.S */
8053    /*
8054     * Jumbo 32-bit instance field get.
8055     *
8056     * for: iget/jumbo, iget-object/jumbo, iget-boolean/jumbo, iget-byte/jumbo,
8057     *      iget-char/jumbo, iget-short/jumbo
8058     */
8059    /* exop vBBBB, vCCCC, field@AAAAAAAA */
8060    FETCH(r1, 1)                        @ r1<- aaaa (lo)
8061    FETCH(r2, 2)                        @ r2<- AAAA (hi)
8062    FETCH(r0, 4)                        @ r0<- CCCC
8063    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
8064    orr     r1, r1, r2, lsl #16         @ r1<- AAAAaaaa
8065    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
8066    GET_VREG(r9, r0)                    @ r9<- fp[CCCC], the object pointer
8067    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
8068    cmp     r0, #0                      @ is resolved entry null?
8069    bne     .LOP_IGET_CHAR_JUMBO_finish          @ no, already resolved
80708:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8071    EXPORT_PC()                         @ resolve() could throw
8072    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8073    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
8074    b       .LOP_IGET_CHAR_JUMBO_resolved        @ resolved, continue
8075
8076
8077/* ------------------------------ */
8078    .balign 64
8079.L_OP_IGET_SHORT_JUMBO: /* 0x10c */
8080/* File: armv5te/OP_IGET_SHORT_JUMBO.S */
8081@include "armv5te/OP_IGET_JUMBO.S" { "load":"ldrsh", "sqnum":"4" }
8082/* File: armv5te/OP_IGET_JUMBO.S */
8083    /*
8084     * Jumbo 32-bit instance field get.
8085     *
8086     * for: iget/jumbo, iget-object/jumbo, iget-boolean/jumbo, iget-byte/jumbo,
8087     *      iget-char/jumbo, iget-short/jumbo
8088     */
8089    /* exop vBBBB, vCCCC, field@AAAAAAAA */
8090    FETCH(r1, 1)                        @ r1<- aaaa (lo)
8091    FETCH(r2, 2)                        @ r2<- AAAA (hi)
8092    FETCH(r0, 4)                        @ r0<- CCCC
8093    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
8094    orr     r1, r1, r2, lsl #16         @ r1<- AAAAaaaa
8095    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
8096    GET_VREG(r9, r0)                    @ r9<- fp[CCCC], the object pointer
8097    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
8098    cmp     r0, #0                      @ is resolved entry null?
8099    bne     .LOP_IGET_SHORT_JUMBO_finish          @ no, already resolved
81008:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8101    EXPORT_PC()                         @ resolve() could throw
8102    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8103    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
8104    b       .LOP_IGET_SHORT_JUMBO_resolved        @ resolved, continue
8105
8106
8107/* ------------------------------ */
8108    .balign 64
8109.L_OP_IPUT_JUMBO: /* 0x10d */
8110/* File: armv5te/OP_IPUT_JUMBO.S */
8111    /*
8112     * Jumbo 32-bit instance field put.
8113     *
8114     * for: iput/jumbo, iput-boolean/jumbo, iput-byte/jumbo, iput-char/jumbo,
8115     *      iput-short/jumbo
8116     */
8117    /* exop vBBBB, vCCCC, field@AAAAAAAA */
8118    FETCH(r1, 1)                        @ r1<- aaaa (lo)
8119    FETCH(r2, 2)                        @ r2<- AAAA (hi)
8120    FETCH(r0, 4)                        @ r0<- CCCC
8121    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
8122    orr     r1, r1, r2, lsl #16         @ r1<- AAAAaaaa
8123    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
8124    GET_VREG(r9, r0)                    @ r9<- fp[CCCC], the object pointer
8125    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
8126    cmp     r0, #0                      @ is resolved entry null?
8127    bne     .LOP_IPUT_JUMBO_finish          @ no, already resolved
81288:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8129    EXPORT_PC()                         @ resolve() could throw
8130    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8131    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
8132    b       .LOP_IPUT_JUMBO_resolved        @ resolved, continue
8133
8134/* ------------------------------ */
8135    .balign 64
8136.L_OP_IPUT_WIDE_JUMBO: /* 0x10e */
8137/* File: armv5te/OP_IPUT_WIDE_JUMBO.S */
8138    /* iput-wide/jumbo vBBBB, vCCCC, field@AAAAAAAA */
8139    FETCH(r1, 1)                        @ r1<- aaaa (lo)
8140    FETCH(r2, 2)                        @ r2<- AAAA (hi)
8141    FETCH(r0, 4)                        @ r0<- CCCC
8142    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
8143    orr     r1, r1, r2, lsl #16         @ r1<- AAAAaaaa
8144    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
8145    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
8146    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
8147    cmp     r0, #0                      @ is resolved entry null?
8148    bne     .LOP_IPUT_WIDE_JUMBO_finish          @ no, already resolved
81498:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
8150    EXPORT_PC()                         @ resolve() could throw
8151    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8152    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
8153    b       .LOP_IPUT_WIDE_JUMBO_resolved        @ resolved, continue
8154
8155/* ------------------------------ */
8156    .balign 64
8157.L_OP_IPUT_OBJECT_JUMBO: /* 0x10f */
8158/* File: armv5te/OP_IPUT_OBJECT_JUMBO.S */
8159    /*
8160     * Jumbo 32-bit instance field put.
8161     */
8162    /* iput-object/jumbo vBBBB, vCCCC, field@AAAAAAAA */
8163    FETCH(r1, 1)                        @ r1<- aaaa (lo)
8164    FETCH(r2, 2)                        @ r2<- AAAA (hi)
8165    FETCH(r0, 4)                        @ r0<- CCCC
8166    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
8167    orr     r1, r1, r2, lsl #16         @ r1<- AAAAaaaa
8168    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
8169    GET_VREG(r9, r0)                    @ r9<- fp[CCCC], the object pointer
8170    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
8171    cmp     r0, #0                      @ is resolved entry null?
8172    bne     .LOP_IPUT_OBJECT_JUMBO_finish          @ no, already resolved
81738:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8174    EXPORT_PC()                         @ resolve() could throw
8175    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8176    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
8177    b       .LOP_IPUT_OBJECT_JUMBO_resolved        @ resolved, continue
8178
8179/* ------------------------------ */
8180    .balign 64
8181.L_OP_IPUT_BOOLEAN_JUMBO: /* 0x110 */
8182/* File: armv5te/OP_IPUT_BOOLEAN_JUMBO.S */
8183@include "armv5te/OP_IPUT_JUMBO.S" { "store":"strb", "sqnum":"1" }
8184/* File: armv5te/OP_IPUT_JUMBO.S */
8185    /*
8186     * Jumbo 32-bit instance field put.
8187     *
8188     * for: iput/jumbo, iput-boolean/jumbo, iput-byte/jumbo, iput-char/jumbo,
8189     *      iput-short/jumbo
8190     */
8191    /* exop vBBBB, vCCCC, field@AAAAAAAA */
8192    FETCH(r1, 1)                        @ r1<- aaaa (lo)
8193    FETCH(r2, 2)                        @ r2<- AAAA (hi)
8194    FETCH(r0, 4)                        @ r0<- CCCC
8195    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
8196    orr     r1, r1, r2, lsl #16         @ r1<- AAAAaaaa
8197    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
8198    GET_VREG(r9, r0)                    @ r9<- fp[CCCC], the object pointer
8199    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
8200    cmp     r0, #0                      @ is resolved entry null?
8201    bne     .LOP_IPUT_BOOLEAN_JUMBO_finish          @ no, already resolved
82028:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8203    EXPORT_PC()                         @ resolve() could throw
8204    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8205    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
8206    b       .LOP_IPUT_BOOLEAN_JUMBO_resolved        @ resolved, continue
8207
8208
8209/* ------------------------------ */
8210    .balign 64
8211.L_OP_IPUT_BYTE_JUMBO: /* 0x111 */
8212/* File: armv5te/OP_IPUT_BYTE_JUMBO.S */
8213@include "armv5te/OP_IPUT_JUMBO.S" { "store":"strb", "sqnum":"2" }
8214/* File: armv5te/OP_IPUT_JUMBO.S */
8215    /*
8216     * Jumbo 32-bit instance field put.
8217     *
8218     * for: iput/jumbo, iput-boolean/jumbo, iput-byte/jumbo, iput-char/jumbo,
8219     *      iput-short/jumbo
8220     */
8221    /* exop vBBBB, vCCCC, field@AAAAAAAA */
8222    FETCH(r1, 1)                        @ r1<- aaaa (lo)
8223    FETCH(r2, 2)                        @ r2<- AAAA (hi)
8224    FETCH(r0, 4)                        @ r0<- CCCC
8225    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
8226    orr     r1, r1, r2, lsl #16         @ r1<- AAAAaaaa
8227    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
8228    GET_VREG(r9, r0)                    @ r9<- fp[CCCC], the object pointer
8229    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
8230    cmp     r0, #0                      @ is resolved entry null?
8231    bne     .LOP_IPUT_BYTE_JUMBO_finish          @ no, already resolved
82328:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8233    EXPORT_PC()                         @ resolve() could throw
8234    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8235    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
8236    b       .LOP_IPUT_BYTE_JUMBO_resolved        @ resolved, continue
8237
8238
8239/* ------------------------------ */
8240    .balign 64
8241.L_OP_IPUT_CHAR_JUMBO: /* 0x112 */
8242/* File: armv5te/OP_IPUT_CHAR_JUMBO.S */
8243@include "armv5te/OP_IPUT_JUMBO.S" { "store":"strh", "sqnum":"3" }
8244/* File: armv5te/OP_IPUT_JUMBO.S */
8245    /*
8246     * Jumbo 32-bit instance field put.
8247     *
8248     * for: iput/jumbo, iput-boolean/jumbo, iput-byte/jumbo, iput-char/jumbo,
8249     *      iput-short/jumbo
8250     */
8251    /* exop vBBBB, vCCCC, field@AAAAAAAA */
8252    FETCH(r1, 1)                        @ r1<- aaaa (lo)
8253    FETCH(r2, 2)                        @ r2<- AAAA (hi)
8254    FETCH(r0, 4)                        @ r0<- CCCC
8255    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
8256    orr     r1, r1, r2, lsl #16         @ r1<- AAAAaaaa
8257    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
8258    GET_VREG(r9, r0)                    @ r9<- fp[CCCC], the object pointer
8259    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
8260    cmp     r0, #0                      @ is resolved entry null?
8261    bne     .LOP_IPUT_CHAR_JUMBO_finish          @ no, already resolved
82628:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8263    EXPORT_PC()                         @ resolve() could throw
8264    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8265    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
8266    b       .LOP_IPUT_CHAR_JUMBO_resolved        @ resolved, continue
8267
8268
8269/* ------------------------------ */
8270    .balign 64
8271.L_OP_IPUT_SHORT_JUMBO: /* 0x113 */
8272/* File: armv5te/OP_IPUT_SHORT_JUMBO.S */
8273@include "armv5te/OP_IPUT_JUMBO.S" { "store":"strh", "sqnum":"4" }
8274/* File: armv5te/OP_IPUT_JUMBO.S */
8275    /*
8276     * Jumbo 32-bit instance field put.
8277     *
8278     * for: iput/jumbo, iput-boolean/jumbo, iput-byte/jumbo, iput-char/jumbo,
8279     *      iput-short/jumbo
8280     */
8281    /* exop vBBBB, vCCCC, field@AAAAAAAA */
8282    FETCH(r1, 1)                        @ r1<- aaaa (lo)
8283    FETCH(r2, 2)                        @ r2<- AAAA (hi)
8284    FETCH(r0, 4)                        @ r0<- CCCC
8285    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
8286    orr     r1, r1, r2, lsl #16         @ r1<- AAAAaaaa
8287    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
8288    GET_VREG(r9, r0)                    @ r9<- fp[CCCC], the object pointer
8289    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
8290    cmp     r0, #0                      @ is resolved entry null?
8291    bne     .LOP_IPUT_SHORT_JUMBO_finish          @ no, already resolved
82928:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8293    EXPORT_PC()                         @ resolve() could throw
8294    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8295    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
8296    b       .LOP_IPUT_SHORT_JUMBO_resolved        @ resolved, continue
8297
8298
8299/* ------------------------------ */
8300    .balign 64
8301.L_OP_SGET_JUMBO: /* 0x114 */
8302/* File: armv5te/OP_SGET_JUMBO.S */
8303    /*
8304     * Jumbo 32-bit SGET handler.
8305     *
8306     * for: sget/jumbo, sget-object/jumbo, sget-boolean/jumbo, sget-byte/jumbo,
8307     *      sget-char/jumbo, sget-short/jumbo
8308     */
8309    /* exop vBBBB, field@AAAAAAAA */
8310    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
8311    FETCH(r0, 1)                        @ r0<- aaaa (lo)
8312    FETCH(r1, 2)                        @ r1<- AAAA (hi)
8313    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
8314    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
8315    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
8316    cmp     r0, #0                      @ is resolved entry null?
8317    beq     .LOP_SGET_JUMBO_resolve         @ yes, do resolve
8318.LOP_SGET_JUMBO_finish: @ field ptr in r0
8319    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
8320    @ no-op                             @ acquiring load
8321    FETCH(r2, 3)                        @ r2<- BBBB
8322    FETCH_ADVANCE_INST(4)               @ advance rPC, load rINST
8323    SET_VREG(r1, r2)                    @ fp[BBBB]<- r1
8324    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8325    GOTO_OPCODE(ip)                     @ jump to next instruction
8326
8327/* ------------------------------ */
8328    .balign 64
8329.L_OP_SGET_WIDE_JUMBO: /* 0x115 */
8330/* File: armv5te/OP_SGET_WIDE_JUMBO.S */
8331    /*
8332     * Jumbo 64-bit SGET handler.
8333     */
8334    /* sget-wide/jumbo vBBBB, field@AAAAAAAA */
8335    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
8336    FETCH(r0, 1)                        @ r0<- aaaa (lo)
8337    FETCH(r1, 2)                        @ r1<- AAAA (hi)
8338    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
8339    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
8340    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
8341    cmp     r0, #0                      @ is resolved entry null?
8342    beq     .LOP_SGET_WIDE_JUMBO_resolve         @ yes, do resolve
8343.LOP_SGET_WIDE_JUMBO_finish:
8344    FETCH(r9, 3)                        @ r9<- BBBB
8345    ldrd    r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
8346    add     r9, rFP, r9, lsl #2         @ r9<- &fp[BBBB]
8347    FETCH_ADVANCE_INST(4)               @ advance rPC, load rINST
8348    stmia   r9, {r0-r1}                 @ vBBBB/vBBBB+1<- r0/r1
8349    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8350    GOTO_OPCODE(ip)                     @ jump to next instruction
8351
8352/* ------------------------------ */
8353    .balign 64
8354.L_OP_SGET_OBJECT_JUMBO: /* 0x116 */
8355/* File: armv5te/OP_SGET_OBJECT_JUMBO.S */
8356/* File: armv5te/OP_SGET_JUMBO.S */
8357    /*
8358     * Jumbo 32-bit SGET handler.
8359     *
8360     * for: sget/jumbo, sget-object/jumbo, sget-boolean/jumbo, sget-byte/jumbo,
8361     *      sget-char/jumbo, sget-short/jumbo
8362     */
8363    /* exop vBBBB, field@AAAAAAAA */
8364    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
8365    FETCH(r0, 1)                        @ r0<- aaaa (lo)
8366    FETCH(r1, 2)                        @ r1<- AAAA (hi)
8367    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
8368    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
8369    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
8370    cmp     r0, #0                      @ is resolved entry null?
8371    beq     .LOP_SGET_OBJECT_JUMBO_resolve         @ yes, do resolve
8372.LOP_SGET_OBJECT_JUMBO_finish: @ field ptr in r0
8373    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
8374    @ no-op                             @ acquiring load
8375    FETCH(r2, 3)                        @ r2<- BBBB
8376    FETCH_ADVANCE_INST(4)               @ advance rPC, load rINST
8377    SET_VREG(r1, r2)                    @ fp[BBBB]<- r1
8378    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8379    GOTO_OPCODE(ip)                     @ jump to next instruction
8380
8381
8382/* ------------------------------ */
8383    .balign 64
8384.L_OP_SGET_BOOLEAN_JUMBO: /* 0x117 */
8385/* File: armv5te/OP_SGET_BOOLEAN_JUMBO.S */
8386/* File: armv5te/OP_SGET_JUMBO.S */
8387    /*
8388     * Jumbo 32-bit SGET handler.
8389     *
8390     * for: sget/jumbo, sget-object/jumbo, sget-boolean/jumbo, sget-byte/jumbo,
8391     *      sget-char/jumbo, sget-short/jumbo
8392     */
8393    /* exop vBBBB, field@AAAAAAAA */
8394    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
8395    FETCH(r0, 1)                        @ r0<- aaaa (lo)
8396    FETCH(r1, 2)                        @ r1<- AAAA (hi)
8397    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
8398    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
8399    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
8400    cmp     r0, #0                      @ is resolved entry null?
8401    beq     .LOP_SGET_BOOLEAN_JUMBO_resolve         @ yes, do resolve
8402.LOP_SGET_BOOLEAN_JUMBO_finish: @ field ptr in r0
8403    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
8404    @ no-op                             @ acquiring load
8405    FETCH(r2, 3)                        @ r2<- BBBB
8406    FETCH_ADVANCE_INST(4)               @ advance rPC, load rINST
8407    SET_VREG(r1, r2)                    @ fp[BBBB]<- r1
8408    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8409    GOTO_OPCODE(ip)                     @ jump to next instruction
8410
8411
8412/* ------------------------------ */
8413    .balign 64
8414.L_OP_SGET_BYTE_JUMBO: /* 0x118 */
8415/* File: armv5te/OP_SGET_BYTE_JUMBO.S */
8416/* File: armv5te/OP_SGET_JUMBO.S */
8417    /*
8418     * Jumbo 32-bit SGET handler.
8419     *
8420     * for: sget/jumbo, sget-object/jumbo, sget-boolean/jumbo, sget-byte/jumbo,
8421     *      sget-char/jumbo, sget-short/jumbo
8422     */
8423    /* exop vBBBB, field@AAAAAAAA */
8424    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
8425    FETCH(r0, 1)                        @ r0<- aaaa (lo)
8426    FETCH(r1, 2)                        @ r1<- AAAA (hi)
8427    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
8428    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
8429    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
8430    cmp     r0, #0                      @ is resolved entry null?
8431    beq     .LOP_SGET_BYTE_JUMBO_resolve         @ yes, do resolve
8432.LOP_SGET_BYTE_JUMBO_finish: @ field ptr in r0
8433    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
8434    @ no-op                             @ acquiring load
8435    FETCH(r2, 3)                        @ r2<- BBBB
8436    FETCH_ADVANCE_INST(4)               @ advance rPC, load rINST
8437    SET_VREG(r1, r2)                    @ fp[BBBB]<- r1
8438    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8439    GOTO_OPCODE(ip)                     @ jump to next instruction
8440
8441
8442/* ------------------------------ */
8443    .balign 64
8444.L_OP_SGET_CHAR_JUMBO: /* 0x119 */
8445/* File: armv5te/OP_SGET_CHAR_JUMBO.S */
8446/* File: armv5te/OP_SGET_JUMBO.S */
8447    /*
8448     * Jumbo 32-bit SGET handler.
8449     *
8450     * for: sget/jumbo, sget-object/jumbo, sget-boolean/jumbo, sget-byte/jumbo,
8451     *      sget-char/jumbo, sget-short/jumbo
8452     */
8453    /* exop vBBBB, field@AAAAAAAA */
8454    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
8455    FETCH(r0, 1)                        @ r0<- aaaa (lo)
8456    FETCH(r1, 2)                        @ r1<- AAAA (hi)
8457    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
8458    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
8459    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
8460    cmp     r0, #0                      @ is resolved entry null?
8461    beq     .LOP_SGET_CHAR_JUMBO_resolve         @ yes, do resolve
8462.LOP_SGET_CHAR_JUMBO_finish: @ field ptr in r0
8463    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
8464    @ no-op                             @ acquiring load
8465    FETCH(r2, 3)                        @ r2<- BBBB
8466    FETCH_ADVANCE_INST(4)               @ advance rPC, load rINST
8467    SET_VREG(r1, r2)                    @ fp[BBBB]<- r1
8468    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8469    GOTO_OPCODE(ip)                     @ jump to next instruction
8470
8471
8472/* ------------------------------ */
8473    .balign 64
8474.L_OP_SGET_SHORT_JUMBO: /* 0x11a */
8475/* File: armv5te/OP_SGET_SHORT_JUMBO.S */
8476/* File: armv5te/OP_SGET_JUMBO.S */
8477    /*
8478     * Jumbo 32-bit SGET handler.
8479     *
8480     * for: sget/jumbo, sget-object/jumbo, sget-boolean/jumbo, sget-byte/jumbo,
8481     *      sget-char/jumbo, sget-short/jumbo
8482     */
8483    /* exop vBBBB, field@AAAAAAAA */
8484    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
8485    FETCH(r0, 1)                        @ r0<- aaaa (lo)
8486    FETCH(r1, 2)                        @ r1<- AAAA (hi)
8487    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
8488    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
8489    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
8490    cmp     r0, #0                      @ is resolved entry null?
8491    beq     .LOP_SGET_SHORT_JUMBO_resolve         @ yes, do resolve
8492.LOP_SGET_SHORT_JUMBO_finish: @ field ptr in r0
8493    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
8494    @ no-op                             @ acquiring load
8495    FETCH(r2, 3)                        @ r2<- BBBB
8496    FETCH_ADVANCE_INST(4)               @ advance rPC, load rINST
8497    SET_VREG(r1, r2)                    @ fp[BBBB]<- r1
8498    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8499    GOTO_OPCODE(ip)                     @ jump to next instruction
8500
8501
8502/* ------------------------------ */
8503    .balign 64
8504.L_OP_SPUT_JUMBO: /* 0x11b */
8505/* File: armv5te/OP_SPUT_JUMBO.S */
8506    /*
8507     * Jumbo 32-bit SPUT handler.
8508     *
8509     * for: sput/jumbo, sput-boolean/jumbo, sput-byte/jumbo, sput-char/jumbo,
8510     *      sput-short/jumbo
8511     */
8512    /* exop vBBBB, field@AAAAAAAA */
8513    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
8514    FETCH(r0, 1)                        @ r0<- aaaa (lo)
8515    FETCH(r1, 2)                        @ r1<- AAAA (hi)
8516    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
8517    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
8518    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
8519    cmp     r0, #0                      @ is resolved entry null?
8520    beq     .LOP_SPUT_JUMBO_resolve         @ yes, do resolve
8521.LOP_SPUT_JUMBO_finish:   @ field ptr in r0
8522    FETCH(r2, 3)                        @ r2<- BBBB
8523    FETCH_ADVANCE_INST(4)               @ advance rPC, load rINST
8524    GET_VREG(r1, r2)                    @ r1<- fp[BBBB]
8525    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8526    @ no-op                             @ releasing store
8527    str     r1, [r0, #offStaticField_value] @ field<- vBBBB
8528    GOTO_OPCODE(ip)                     @ jump to next instruction
8529
8530/* ------------------------------ */
8531    .balign 64
8532.L_OP_SPUT_WIDE_JUMBO: /* 0x11c */
8533/* File: armv5te/OP_SPUT_WIDE_JUMBO.S */
8534    /*
8535     * Jumbo 64-bit SPUT handler.
8536     */
8537    /* sput-wide/jumbo vBBBB, field@AAAAAAAA */
8538    ldr     r0, [rGLUE, #offGlue_methodClassDex]  @ r0<- DvmDex
8539    FETCH(r1, 1)                        @ r1<- aaaa (lo)
8540    FETCH(r2, 2)                        @ r2<- AAAA (hi)
8541    ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
8542    orr     r1, r1, r2, lsl #16         @ r1<- AAAAaaaa
8543    FETCH(r9, 3)                        @ r9<- BBBB
8544    ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
8545    add     r9, rFP, r9, lsl #2         @ r9<- &fp[BBBB]
8546    cmp     r2, #0                      @ is resolved entry null?
8547    beq     .LOP_SPUT_WIDE_JUMBO_resolve         @ yes, do resolve
8548.LOP_SPUT_WIDE_JUMBO_finish: @ field ptr in r2, BBBB in r9
8549    FETCH_ADVANCE_INST(4)               @ advance rPC, load rINST
8550    ldmia   r9, {r0-r1}                 @ r0/r1<- vBBBB/vBBBB+1
8551    GET_INST_OPCODE(r10)                @ extract opcode from rINST
8552    strd    r0, [r2, #offStaticField_value] @ field<- vBBBB/vBBBB+1
8553    GOTO_OPCODE(r10)                    @ jump to next instruction
8554
8555/* ------------------------------ */
8556    .balign 64
8557.L_OP_SPUT_OBJECT_JUMBO: /* 0x11d */
8558/* File: armv5te/OP_SPUT_OBJECT_JUMBO.S */
8559    /*
8560     * Jumbo 32-bit SPUT handler for objects
8561     */
8562    /* sput-object/jumbo vBBBB, field@AAAAAAAA */
8563    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
8564    FETCH(r0, 1)                        @ r0<- aaaa (lo)
8565    FETCH(r1, 2)                        @ r1<- AAAA (hi)
8566    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
8567    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
8568    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
8569    cmp     r0, #0                      @ is resolved entry null?
8570    bne     .LOP_SPUT_OBJECT_JUMBO_finish          @ no, continue
8571    ldr     r9, [rGLUE, #offGlue_method]    @ r9<- current method
8572    EXPORT_PC()                         @ resolve() could throw, so export now
8573    ldr     r0, [r9, #offMethod_clazz]  @ r0<- method->clazz
8574    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8575    cmp     r0, #0                      @ success?
8576    bne     .LOP_SPUT_OBJECT_JUMBO_finish          @ yes, finish
8577    b       common_exceptionThrown      @ no, handle exception
8578
8579/* ------------------------------ */
8580    .balign 64
8581.L_OP_SPUT_BOOLEAN_JUMBO: /* 0x11e */
8582/* File: armv5te/OP_SPUT_BOOLEAN_JUMBO.S */
8583/* File: armv5te/OP_SPUT_JUMBO.S */
8584    /*
8585     * Jumbo 32-bit SPUT handler.
8586     *
8587     * for: sput/jumbo, sput-boolean/jumbo, sput-byte/jumbo, sput-char/jumbo,
8588     *      sput-short/jumbo
8589     */
8590    /* exop vBBBB, field@AAAAAAAA */
8591    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
8592    FETCH(r0, 1)                        @ r0<- aaaa (lo)
8593    FETCH(r1, 2)                        @ r1<- AAAA (hi)
8594    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
8595    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
8596    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
8597    cmp     r0, #0                      @ is resolved entry null?
8598    beq     .LOP_SPUT_BOOLEAN_JUMBO_resolve         @ yes, do resolve
8599.LOP_SPUT_BOOLEAN_JUMBO_finish:   @ field ptr in r0
8600    FETCH(r2, 3)                        @ r2<- BBBB
8601    FETCH_ADVANCE_INST(4)               @ advance rPC, load rINST
8602    GET_VREG(r1, r2)                    @ r1<- fp[BBBB]
8603    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8604    @ no-op                             @ releasing store
8605    str     r1, [r0, #offStaticField_value] @ field<- vBBBB
8606    GOTO_OPCODE(ip)                     @ jump to next instruction
8607
8608
8609/* ------------------------------ */
8610    .balign 64
8611.L_OP_SPUT_BYTE_JUMBO: /* 0x11f */
8612/* File: armv5te/OP_SPUT_BYTE_JUMBO.S */
8613/* File: armv5te/OP_SPUT_JUMBO.S */
8614    /*
8615     * Jumbo 32-bit SPUT handler.
8616     *
8617     * for: sput/jumbo, sput-boolean/jumbo, sput-byte/jumbo, sput-char/jumbo,
8618     *      sput-short/jumbo
8619     */
8620    /* exop vBBBB, field@AAAAAAAA */
8621    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
8622    FETCH(r0, 1)                        @ r0<- aaaa (lo)
8623    FETCH(r1, 2)                        @ r1<- AAAA (hi)
8624    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
8625    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
8626    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
8627    cmp     r0, #0                      @ is resolved entry null?
8628    beq     .LOP_SPUT_BYTE_JUMBO_resolve         @ yes, do resolve
8629.LOP_SPUT_BYTE_JUMBO_finish:   @ field ptr in r0
8630    FETCH(r2, 3)                        @ r2<- BBBB
8631    FETCH_ADVANCE_INST(4)               @ advance rPC, load rINST
8632    GET_VREG(r1, r2)                    @ r1<- fp[BBBB]
8633    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8634    @ no-op                             @ releasing store
8635    str     r1, [r0, #offStaticField_value] @ field<- vBBBB
8636    GOTO_OPCODE(ip)                     @ jump to next instruction
8637
8638
8639/* ------------------------------ */
8640    .balign 64
8641.L_OP_SPUT_CHAR_JUMBO: /* 0x120 */
8642/* File: armv5te/OP_SPUT_CHAR_JUMBO.S */
8643/* File: armv5te/OP_SPUT_JUMBO.S */
8644    /*
8645     * Jumbo 32-bit SPUT handler.
8646     *
8647     * for: sput/jumbo, sput-boolean/jumbo, sput-byte/jumbo, sput-char/jumbo,
8648     *      sput-short/jumbo
8649     */
8650    /* exop vBBBB, field@AAAAAAAA */
8651    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
8652    FETCH(r0, 1)                        @ r0<- aaaa (lo)
8653    FETCH(r1, 2)                        @ r1<- AAAA (hi)
8654    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
8655    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
8656    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
8657    cmp     r0, #0                      @ is resolved entry null?
8658    beq     .LOP_SPUT_CHAR_JUMBO_resolve         @ yes, do resolve
8659.LOP_SPUT_CHAR_JUMBO_finish:   @ field ptr in r0
8660    FETCH(r2, 3)                        @ r2<- BBBB
8661    FETCH_ADVANCE_INST(4)               @ advance rPC, load rINST
8662    GET_VREG(r1, r2)                    @ r1<- fp[BBBB]
8663    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8664    @ no-op                             @ releasing store
8665    str     r1, [r0, #offStaticField_value] @ field<- vBBBB
8666    GOTO_OPCODE(ip)                     @ jump to next instruction
8667
8668
8669/* ------------------------------ */
8670    .balign 64
8671.L_OP_SPUT_SHORT_JUMBO: /* 0x121 */
8672/* File: armv5te/OP_SPUT_SHORT_JUMBO.S */
8673/* File: armv5te/OP_SPUT_JUMBO.S */
8674    /*
8675     * Jumbo 32-bit SPUT handler.
8676     *
8677     * for: sput/jumbo, sput-boolean/jumbo, sput-byte/jumbo, sput-char/jumbo,
8678     *      sput-short/jumbo
8679     */
8680    /* exop vBBBB, field@AAAAAAAA */
8681    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
8682    FETCH(r0, 1)                        @ r0<- aaaa (lo)
8683    FETCH(r1, 2)                        @ r1<- AAAA (hi)
8684    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
8685    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
8686    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
8687    cmp     r0, #0                      @ is resolved entry null?
8688    beq     .LOP_SPUT_SHORT_JUMBO_resolve         @ yes, do resolve
8689.LOP_SPUT_SHORT_JUMBO_finish:   @ field ptr in r0
8690    FETCH(r2, 3)                        @ r2<- BBBB
8691    FETCH_ADVANCE_INST(4)               @ advance rPC, load rINST
8692    GET_VREG(r1, r2)                    @ r1<- fp[BBBB]
8693    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8694    @ no-op                             @ releasing store
8695    str     r1, [r0, #offStaticField_value] @ field<- vBBBB
8696    GOTO_OPCODE(ip)                     @ jump to next instruction
8697
8698
8699/* ------------------------------ */
8700    .balign 64
8701.L_OP_INVOKE_VIRTUAL_JUMBO: /* 0x122 */
8702/* File: armv5te/OP_INVOKE_VIRTUAL_JUMBO.S */
8703    /*
8704     * Handle a virtual method call.
8705     */
8706    /* invoke-virtual/jumbo {vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA */
8707    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
8708    FETCH(r0, 1)                        @ r1<- aaaa (lo)
8709    FETCH(r1, 2)                        @ r1<- AAAA (hi)
8710    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
8711    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
8712    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
8713    cmp     r0, #0                      @ already resolved?
8714    EXPORT_PC()                         @ must export for invoke
8715    bne     .LOP_INVOKE_VIRTUAL_JUMBO_continue        @ yes, continue on
8716    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8717    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8718    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8719    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8720    cmp     r0, #0                      @ got null?
8721    bne     .LOP_INVOKE_VIRTUAL_JUMBO_continue        @ no, continue
8722    b       common_exceptionThrown      @ yes, handle exception
8723
8724/* ------------------------------ */
8725    .balign 64
8726.L_OP_INVOKE_SUPER_JUMBO: /* 0x123 */
8727/* File: armv5te/OP_INVOKE_SUPER_JUMBO.S */
8728    /*
8729     * Handle a "super" method call.
8730     */
8731    /* invoke-super/jumbo {vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA */
8732    FETCH(r10, 4)                       @ r10<- CCCC
8733    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
8734    FETCH(r0, 1)                        @ r1<- aaaa (lo)
8735    FETCH(r1, 2)                        @ r1<- AAAA (hi)
8736    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
8737    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
8738    GET_VREG(r2, r10)                   @ r2<- "this" ptr
8739    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
8740    cmp     r2, #0                      @ null "this"?
8741    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
8742    beq     common_errNullObject        @ null "this", throw exception
8743    cmp     r0, #0                      @ already resolved?
8744    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
8745    EXPORT_PC()                         @ must export for invoke
8746    bne     .LOP_INVOKE_SUPER_JUMBO_continue        @ resolved, continue on
8747    b       .LOP_INVOKE_SUPER_JUMBO_resolve         @ do resolve now
8748
8749/* ------------------------------ */
8750    .balign 64
8751.L_OP_INVOKE_DIRECT_JUMBO: /* 0x124 */
8752/* File: armv5te/OP_INVOKE_DIRECT_JUMBO.S */
8753    /*
8754     * Handle a direct method call.
8755     *
8756     * (We could defer the "is 'this' pointer null" test to the common
8757     * method invocation code, and use a flag to indicate that static
8758     * calls don't count.  If we do this as part of copying the arguments
8759     * out we could avoiding loading the first arg twice.)
8760     *
8761     */
8762    /* invoke-direct/jumbo {vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA */
8763    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
8764    FETCH(r0, 1)                        @ r1<- aaaa (lo)
8765    FETCH(r1, 2)                        @ r1<- AAAA (hi)
8766    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
8767    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
8768    FETCH(r10, 4)                       @ r10<- CCCC
8769    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
8770    cmp     r0, #0                      @ already resolved?
8771    EXPORT_PC()                         @ must export for invoke
8772    GET_VREG(r2, r10)                   @ r2<- "this" ptr
8773    beq     .LOP_INVOKE_DIRECT_JUMBO_resolve         @ not resolved, do it now
8774.LOP_INVOKE_DIRECT_JUMBO_finish:
8775    cmp     r2, #0                      @ null "this" ref?
8776    bne     common_invokeMethodJumbo    @ no, continue on
8777    b       common_errNullObject        @ yes, throw exception
8778
8779/* ------------------------------ */
8780    .balign 64
8781.L_OP_INVOKE_STATIC_JUMBO: /* 0x125 */
8782/* File: armv5te/OP_INVOKE_STATIC_JUMBO.S */
8783    /*
8784     * Handle a static method call.
8785     */
8786    /* invoke-static/jumbo {vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA */
8787    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
8788    FETCH(r0, 1)                        @ r1<- aaaa (lo)
8789    FETCH(r1, 2)                        @ r1<- AAAA (hi)
8790    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
8791    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
8792    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
8793    cmp     r0, #0                      @ already resolved?
8794    EXPORT_PC()                         @ must export for invoke
8795    bne     common_invokeMethodJumbo    @ yes, continue on
87960:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8797    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8798    mov     r2, #METHOD_STATIC          @ resolver method type
8799    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8800    cmp     r0, #0                      @ got null?
8801    bne     common_invokeMethodJumbo    @ no, continue
8802    b       common_exceptionThrown      @ yes, handle exception
8803
8804/* ------------------------------ */
8805    .balign 64
8806.L_OP_INVOKE_INTERFACE_JUMBO: /* 0x126 */
8807/* File: armv5te/OP_INVOKE_INTERFACE_JUMBO.S */
8808    /*
8809     * Handle an interface method call.
8810     */
8811    /* invoke-interface/jumbo {vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA */
8812    FETCH(r2, 4)                        @ r2<- CCCC
8813    FETCH(r0, 1)                        @ r0<- aaaa (lo)
8814    FETCH(r1, 2)                        @ r1<- AAAA (hi)
8815    EXPORT_PC()                         @ must export for invoke
8816    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
8817    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
8818    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
8819    cmp     r0, #0                      @ null obj?
8820    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
8821    beq     common_errNullObject        @ yes, fail
8822    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
8823    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
8824    cmp     r0, #0                      @ failed?
8825    beq     common_exceptionThrown      @ yes, handle exception
8826    b       common_invokeMethodJumbo    @ jump to common handler
8827
8828/* ------------------------------ */
8829    .balign 64
8830.L_OP_UNUSED_27FF: /* 0x127 */
8831/* File: armv5te/OP_UNUSED_27FF.S */
8832/* File: armv5te/unused.S */
8833    bl      common_abort
8834
8835
8836/* ------------------------------ */
8837    .balign 64
8838.L_OP_UNUSED_28FF: /* 0x128 */
8839/* File: armv5te/OP_UNUSED_28FF.S */
8840/* File: armv5te/unused.S */
8841    bl      common_abort
8842
8843
8844/* ------------------------------ */
8845    .balign 64
8846.L_OP_UNUSED_29FF: /* 0x129 */
8847/* File: armv5te/OP_UNUSED_29FF.S */
8848/* File: armv5te/unused.S */
8849    bl      common_abort
8850
8851
8852/* ------------------------------ */
8853    .balign 64
8854.L_OP_UNUSED_2AFF: /* 0x12a */
8855/* File: armv5te/OP_UNUSED_2AFF.S */
8856/* File: armv5te/unused.S */
8857    bl      common_abort
8858
8859
8860/* ------------------------------ */
8861    .balign 64
8862.L_OP_UNUSED_2BFF: /* 0x12b */
8863/* File: armv5te/OP_UNUSED_2BFF.S */
8864/* File: armv5te/unused.S */
8865    bl      common_abort
8866
8867
8868/* ------------------------------ */
8869    .balign 64
8870.L_OP_UNUSED_2CFF: /* 0x12c */
8871/* File: armv5te/OP_UNUSED_2CFF.S */
8872/* File: armv5te/unused.S */
8873    bl      common_abort
8874
8875
8876/* ------------------------------ */
8877    .balign 64
8878.L_OP_UNUSED_2DFF: /* 0x12d */
8879/* File: armv5te/OP_UNUSED_2DFF.S */
8880/* File: armv5te/unused.S */
8881    bl      common_abort
8882
8883
8884/* ------------------------------ */
8885    .balign 64
8886.L_OP_UNUSED_2EFF: /* 0x12e */
8887/* File: armv5te/OP_UNUSED_2EFF.S */
8888/* File: armv5te/unused.S */
8889    bl      common_abort
8890
8891
8892/* ------------------------------ */
8893    .balign 64
8894.L_OP_UNUSED_2FFF: /* 0x12f */
8895/* File: armv5te/OP_UNUSED_2FFF.S */
8896/* File: armv5te/unused.S */
8897    bl      common_abort
8898
8899
8900/* ------------------------------ */
8901    .balign 64
8902.L_OP_UNUSED_30FF: /* 0x130 */
8903/* File: armv5te/OP_UNUSED_30FF.S */
8904/* File: armv5te/unused.S */
8905    bl      common_abort
8906
8907
8908/* ------------------------------ */
8909    .balign 64
8910.L_OP_UNUSED_31FF: /* 0x131 */
8911/* File: armv5te/OP_UNUSED_31FF.S */
8912/* File: armv5te/unused.S */
8913    bl      common_abort
8914
8915
8916/* ------------------------------ */
8917    .balign 64
8918.L_OP_UNUSED_32FF: /* 0x132 */
8919/* File: armv5te/OP_UNUSED_32FF.S */
8920/* File: armv5te/unused.S */
8921    bl      common_abort
8922
8923
8924/* ------------------------------ */
8925    .balign 64
8926.L_OP_UNUSED_33FF: /* 0x133 */
8927/* File: armv5te/OP_UNUSED_33FF.S */
8928/* File: armv5te/unused.S */
8929    bl      common_abort
8930
8931
8932/* ------------------------------ */
8933    .balign 64
8934.L_OP_UNUSED_34FF: /* 0x134 */
8935/* File: armv5te/OP_UNUSED_34FF.S */
8936/* File: armv5te/unused.S */
8937    bl      common_abort
8938
8939
8940/* ------------------------------ */
8941    .balign 64
8942.L_OP_UNUSED_35FF: /* 0x135 */
8943/* File: armv5te/OP_UNUSED_35FF.S */
8944/* File: armv5te/unused.S */
8945    bl      common_abort
8946
8947
8948/* ------------------------------ */
8949    .balign 64
8950.L_OP_UNUSED_36FF: /* 0x136 */
8951/* File: armv5te/OP_UNUSED_36FF.S */
8952/* File: armv5te/unused.S */
8953    bl      common_abort
8954
8955
8956/* ------------------------------ */
8957    .balign 64
8958.L_OP_UNUSED_37FF: /* 0x137 */
8959/* File: armv5te/OP_UNUSED_37FF.S */
8960/* File: armv5te/unused.S */
8961    bl      common_abort
8962
8963
8964/* ------------------------------ */
8965    .balign 64
8966.L_OP_UNUSED_38FF: /* 0x138 */
8967/* File: armv5te/OP_UNUSED_38FF.S */
8968/* File: armv5te/unused.S */
8969    bl      common_abort
8970
8971
8972/* ------------------------------ */
8973    .balign 64
8974.L_OP_UNUSED_39FF: /* 0x139 */
8975/* File: armv5te/OP_UNUSED_39FF.S */
8976/* File: armv5te/unused.S */
8977    bl      common_abort
8978
8979
8980/* ------------------------------ */
8981    .balign 64
8982.L_OP_UNUSED_3AFF: /* 0x13a */
8983/* File: armv5te/OP_UNUSED_3AFF.S */
8984/* File: armv5te/unused.S */
8985    bl      common_abort
8986
8987
8988/* ------------------------------ */
8989    .balign 64
8990.L_OP_UNUSED_3BFF: /* 0x13b */
8991/* File: armv5te/OP_UNUSED_3BFF.S */
8992/* File: armv5te/unused.S */
8993    bl      common_abort
8994
8995
8996/* ------------------------------ */
8997    .balign 64
8998.L_OP_UNUSED_3CFF: /* 0x13c */
8999/* File: armv5te/OP_UNUSED_3CFF.S */
9000/* File: armv5te/unused.S */
9001    bl      common_abort
9002
9003
9004/* ------------------------------ */
9005    .balign 64
9006.L_OP_UNUSED_3DFF: /* 0x13d */
9007/* File: armv5te/OP_UNUSED_3DFF.S */
9008/* File: armv5te/unused.S */
9009    bl      common_abort
9010
9011
9012/* ------------------------------ */
9013    .balign 64
9014.L_OP_UNUSED_3EFF: /* 0x13e */
9015/* File: armv5te/OP_UNUSED_3EFF.S */
9016/* File: armv5te/unused.S */
9017    bl      common_abort
9018
9019
9020/* ------------------------------ */
9021    .balign 64
9022.L_OP_UNUSED_3FFF: /* 0x13f */
9023/* File: armv5te/OP_UNUSED_3FFF.S */
9024/* File: armv5te/unused.S */
9025    bl      common_abort
9026
9027
9028/* ------------------------------ */
9029    .balign 64
9030.L_OP_UNUSED_40FF: /* 0x140 */
9031/* File: armv5te/OP_UNUSED_40FF.S */
9032/* File: armv5te/unused.S */
9033    bl      common_abort
9034
9035
9036/* ------------------------------ */
9037    .balign 64
9038.L_OP_UNUSED_41FF: /* 0x141 */
9039/* File: armv5te/OP_UNUSED_41FF.S */
9040/* File: armv5te/unused.S */
9041    bl      common_abort
9042
9043
9044/* ------------------------------ */
9045    .balign 64
9046.L_OP_UNUSED_42FF: /* 0x142 */
9047/* File: armv5te/OP_UNUSED_42FF.S */
9048/* File: armv5te/unused.S */
9049    bl      common_abort
9050
9051
9052/* ------------------------------ */
9053    .balign 64
9054.L_OP_UNUSED_43FF: /* 0x143 */
9055/* File: armv5te/OP_UNUSED_43FF.S */
9056/* File: armv5te/unused.S */
9057    bl      common_abort
9058
9059
9060/* ------------------------------ */
9061    .balign 64
9062.L_OP_UNUSED_44FF: /* 0x144 */
9063/* File: armv5te/OP_UNUSED_44FF.S */
9064/* File: armv5te/unused.S */
9065    bl      common_abort
9066
9067
9068/* ------------------------------ */
9069    .balign 64
9070.L_OP_UNUSED_45FF: /* 0x145 */
9071/* File: armv5te/OP_UNUSED_45FF.S */
9072/* File: armv5te/unused.S */
9073    bl      common_abort
9074
9075
9076/* ------------------------------ */
9077    .balign 64
9078.L_OP_UNUSED_46FF: /* 0x146 */
9079/* File: armv5te/OP_UNUSED_46FF.S */
9080/* File: armv5te/unused.S */
9081    bl      common_abort
9082
9083
9084/* ------------------------------ */
9085    .balign 64
9086.L_OP_UNUSED_47FF: /* 0x147 */
9087/* File: armv5te/OP_UNUSED_47FF.S */
9088/* File: armv5te/unused.S */
9089    bl      common_abort
9090
9091
9092/* ------------------------------ */
9093    .balign 64
9094.L_OP_UNUSED_48FF: /* 0x148 */
9095/* File: armv5te/OP_UNUSED_48FF.S */
9096/* File: armv5te/unused.S */
9097    bl      common_abort
9098
9099
9100/* ------------------------------ */
9101    .balign 64
9102.L_OP_UNUSED_49FF: /* 0x149 */
9103/* File: armv5te/OP_UNUSED_49FF.S */
9104/* File: armv5te/unused.S */
9105    bl      common_abort
9106
9107
9108/* ------------------------------ */
9109    .balign 64
9110.L_OP_UNUSED_4AFF: /* 0x14a */
9111/* File: armv5te/OP_UNUSED_4AFF.S */
9112/* File: armv5te/unused.S */
9113    bl      common_abort
9114
9115
9116/* ------------------------------ */
9117    .balign 64
9118.L_OP_UNUSED_4BFF: /* 0x14b */
9119/* File: armv5te/OP_UNUSED_4BFF.S */
9120/* File: armv5te/unused.S */
9121    bl      common_abort
9122
9123
9124/* ------------------------------ */
9125    .balign 64
9126.L_OP_UNUSED_4CFF: /* 0x14c */
9127/* File: armv5te/OP_UNUSED_4CFF.S */
9128/* File: armv5te/unused.S */
9129    bl      common_abort
9130
9131
9132/* ------------------------------ */
9133    .balign 64
9134.L_OP_UNUSED_4DFF: /* 0x14d */
9135/* File: armv5te/OP_UNUSED_4DFF.S */
9136/* File: armv5te/unused.S */
9137    bl      common_abort
9138
9139
9140/* ------------------------------ */
9141    .balign 64
9142.L_OP_UNUSED_4EFF: /* 0x14e */
9143/* File: armv5te/OP_UNUSED_4EFF.S */
9144/* File: armv5te/unused.S */
9145    bl      common_abort
9146
9147
9148/* ------------------------------ */
9149    .balign 64
9150.L_OP_UNUSED_4FFF: /* 0x14f */
9151/* File: armv5te/OP_UNUSED_4FFF.S */
9152/* File: armv5te/unused.S */
9153    bl      common_abort
9154
9155
9156/* ------------------------------ */
9157    .balign 64
9158.L_OP_UNUSED_50FF: /* 0x150 */
9159/* File: armv5te/OP_UNUSED_50FF.S */
9160/* File: armv5te/unused.S */
9161    bl      common_abort
9162
9163
9164/* ------------------------------ */
9165    .balign 64
9166.L_OP_UNUSED_51FF: /* 0x151 */
9167/* File: armv5te/OP_UNUSED_51FF.S */
9168/* File: armv5te/unused.S */
9169    bl      common_abort
9170
9171
9172/* ------------------------------ */
9173    .balign 64
9174.L_OP_UNUSED_52FF: /* 0x152 */
9175/* File: armv5te/OP_UNUSED_52FF.S */
9176/* File: armv5te/unused.S */
9177    bl      common_abort
9178
9179
9180/* ------------------------------ */
9181    .balign 64
9182.L_OP_UNUSED_53FF: /* 0x153 */
9183/* File: armv5te/OP_UNUSED_53FF.S */
9184/* File: armv5te/unused.S */
9185    bl      common_abort
9186
9187
9188/* ------------------------------ */
9189    .balign 64
9190.L_OP_UNUSED_54FF: /* 0x154 */
9191/* File: armv5te/OP_UNUSED_54FF.S */
9192/* File: armv5te/unused.S */
9193    bl      common_abort
9194
9195
9196/* ------------------------------ */
9197    .balign 64
9198.L_OP_UNUSED_55FF: /* 0x155 */
9199/* File: armv5te/OP_UNUSED_55FF.S */
9200/* File: armv5te/unused.S */
9201    bl      common_abort
9202
9203
9204/* ------------------------------ */
9205    .balign 64
9206.L_OP_UNUSED_56FF: /* 0x156 */
9207/* File: armv5te/OP_UNUSED_56FF.S */
9208/* File: armv5te/unused.S */
9209    bl      common_abort
9210
9211
9212/* ------------------------------ */
9213    .balign 64
9214.L_OP_UNUSED_57FF: /* 0x157 */
9215/* File: armv5te/OP_UNUSED_57FF.S */
9216/* File: armv5te/unused.S */
9217    bl      common_abort
9218
9219
9220/* ------------------------------ */
9221    .balign 64
9222.L_OP_UNUSED_58FF: /* 0x158 */
9223/* File: armv5te/OP_UNUSED_58FF.S */
9224/* File: armv5te/unused.S */
9225    bl      common_abort
9226
9227
9228/* ------------------------------ */
9229    .balign 64
9230.L_OP_UNUSED_59FF: /* 0x159 */
9231/* File: armv5te/OP_UNUSED_59FF.S */
9232/* File: armv5te/unused.S */
9233    bl      common_abort
9234
9235
9236/* ------------------------------ */
9237    .balign 64
9238.L_OP_UNUSED_5AFF: /* 0x15a */
9239/* File: armv5te/OP_UNUSED_5AFF.S */
9240/* File: armv5te/unused.S */
9241    bl      common_abort
9242
9243
9244/* ------------------------------ */
9245    .balign 64
9246.L_OP_UNUSED_5BFF: /* 0x15b */
9247/* File: armv5te/OP_UNUSED_5BFF.S */
9248/* File: armv5te/unused.S */
9249    bl      common_abort
9250
9251
9252/* ------------------------------ */
9253    .balign 64
9254.L_OP_UNUSED_5CFF: /* 0x15c */
9255/* File: armv5te/OP_UNUSED_5CFF.S */
9256/* File: armv5te/unused.S */
9257    bl      common_abort
9258
9259
9260/* ------------------------------ */
9261    .balign 64
9262.L_OP_UNUSED_5DFF: /* 0x15d */
9263/* File: armv5te/OP_UNUSED_5DFF.S */
9264/* File: armv5te/unused.S */
9265    bl      common_abort
9266
9267
9268/* ------------------------------ */
9269    .balign 64
9270.L_OP_UNUSED_5EFF: /* 0x15e */
9271/* File: armv5te/OP_UNUSED_5EFF.S */
9272/* File: armv5te/unused.S */
9273    bl      common_abort
9274
9275
9276/* ------------------------------ */
9277    .balign 64
9278.L_OP_UNUSED_5FFF: /* 0x15f */
9279/* File: armv5te/OP_UNUSED_5FFF.S */
9280/* File: armv5te/unused.S */
9281    bl      common_abort
9282
9283
9284/* ------------------------------ */
9285    .balign 64
9286.L_OP_UNUSED_60FF: /* 0x160 */
9287/* File: armv5te/OP_UNUSED_60FF.S */
9288/* File: armv5te/unused.S */
9289    bl      common_abort
9290
9291
9292/* ------------------------------ */
9293    .balign 64
9294.L_OP_UNUSED_61FF: /* 0x161 */
9295/* File: armv5te/OP_UNUSED_61FF.S */
9296/* File: armv5te/unused.S */
9297    bl      common_abort
9298
9299
9300/* ------------------------------ */
9301    .balign 64
9302.L_OP_UNUSED_62FF: /* 0x162 */
9303/* File: armv5te/OP_UNUSED_62FF.S */
9304/* File: armv5te/unused.S */
9305    bl      common_abort
9306
9307
9308/* ------------------------------ */
9309    .balign 64
9310.L_OP_UNUSED_63FF: /* 0x163 */
9311/* File: armv5te/OP_UNUSED_63FF.S */
9312/* File: armv5te/unused.S */
9313    bl      common_abort
9314
9315
9316/* ------------------------------ */
9317    .balign 64
9318.L_OP_UNUSED_64FF: /* 0x164 */
9319/* File: armv5te/OP_UNUSED_64FF.S */
9320/* File: armv5te/unused.S */
9321    bl      common_abort
9322
9323
9324/* ------------------------------ */
9325    .balign 64
9326.L_OP_UNUSED_65FF: /* 0x165 */
9327/* File: armv5te/OP_UNUSED_65FF.S */
9328/* File: armv5te/unused.S */
9329    bl      common_abort
9330
9331
9332/* ------------------------------ */
9333    .balign 64
9334.L_OP_UNUSED_66FF: /* 0x166 */
9335/* File: armv5te/OP_UNUSED_66FF.S */
9336/* File: armv5te/unused.S */
9337    bl      common_abort
9338
9339
9340/* ------------------------------ */
9341    .balign 64
9342.L_OP_UNUSED_67FF: /* 0x167 */
9343/* File: armv5te/OP_UNUSED_67FF.S */
9344/* File: armv5te/unused.S */
9345    bl      common_abort
9346
9347
9348/* ------------------------------ */
9349    .balign 64
9350.L_OP_UNUSED_68FF: /* 0x168 */
9351/* File: armv5te/OP_UNUSED_68FF.S */
9352/* File: armv5te/unused.S */
9353    bl      common_abort
9354
9355
9356/* ------------------------------ */
9357    .balign 64
9358.L_OP_UNUSED_69FF: /* 0x169 */
9359/* File: armv5te/OP_UNUSED_69FF.S */
9360/* File: armv5te/unused.S */
9361    bl      common_abort
9362
9363
9364/* ------------------------------ */
9365    .balign 64
9366.L_OP_UNUSED_6AFF: /* 0x16a */
9367/* File: armv5te/OP_UNUSED_6AFF.S */
9368/* File: armv5te/unused.S */
9369    bl      common_abort
9370
9371
9372/* ------------------------------ */
9373    .balign 64
9374.L_OP_UNUSED_6BFF: /* 0x16b */
9375/* File: armv5te/OP_UNUSED_6BFF.S */
9376/* File: armv5te/unused.S */
9377    bl      common_abort
9378
9379
9380/* ------------------------------ */
9381    .balign 64
9382.L_OP_UNUSED_6CFF: /* 0x16c */
9383/* File: armv5te/OP_UNUSED_6CFF.S */
9384/* File: armv5te/unused.S */
9385    bl      common_abort
9386
9387
9388/* ------------------------------ */
9389    .balign 64
9390.L_OP_UNUSED_6DFF: /* 0x16d */
9391/* File: armv5te/OP_UNUSED_6DFF.S */
9392/* File: armv5te/unused.S */
9393    bl      common_abort
9394
9395
9396/* ------------------------------ */
9397    .balign 64
9398.L_OP_UNUSED_6EFF: /* 0x16e */
9399/* File: armv5te/OP_UNUSED_6EFF.S */
9400/* File: armv5te/unused.S */
9401    bl      common_abort
9402
9403
9404/* ------------------------------ */
9405    .balign 64
9406.L_OP_UNUSED_6FFF: /* 0x16f */
9407/* File: armv5te/OP_UNUSED_6FFF.S */
9408/* File: armv5te/unused.S */
9409    bl      common_abort
9410
9411
9412/* ------------------------------ */
9413    .balign 64
9414.L_OP_UNUSED_70FF: /* 0x170 */
9415/* File: armv5te/OP_UNUSED_70FF.S */
9416/* File: armv5te/unused.S */
9417    bl      common_abort
9418
9419
9420/* ------------------------------ */
9421    .balign 64
9422.L_OP_UNUSED_71FF: /* 0x171 */
9423/* File: armv5te/OP_UNUSED_71FF.S */
9424/* File: armv5te/unused.S */
9425    bl      common_abort
9426
9427
9428/* ------------------------------ */
9429    .balign 64
9430.L_OP_UNUSED_72FF: /* 0x172 */
9431/* File: armv5te/OP_UNUSED_72FF.S */
9432/* File: armv5te/unused.S */
9433    bl      common_abort
9434
9435
9436/* ------------------------------ */
9437    .balign 64
9438.L_OP_UNUSED_73FF: /* 0x173 */
9439/* File: armv5te/OP_UNUSED_73FF.S */
9440/* File: armv5te/unused.S */
9441    bl      common_abort
9442
9443
9444/* ------------------------------ */
9445    .balign 64
9446.L_OP_UNUSED_74FF: /* 0x174 */
9447/* File: armv5te/OP_UNUSED_74FF.S */
9448/* File: armv5te/unused.S */
9449    bl      common_abort
9450
9451
9452/* ------------------------------ */
9453    .balign 64
9454.L_OP_UNUSED_75FF: /* 0x175 */
9455/* File: armv5te/OP_UNUSED_75FF.S */
9456/* File: armv5te/unused.S */
9457    bl      common_abort
9458
9459
9460/* ------------------------------ */
9461    .balign 64
9462.L_OP_UNUSED_76FF: /* 0x176 */
9463/* File: armv5te/OP_UNUSED_76FF.S */
9464/* File: armv5te/unused.S */
9465    bl      common_abort
9466
9467
9468/* ------------------------------ */
9469    .balign 64
9470.L_OP_UNUSED_77FF: /* 0x177 */
9471/* File: armv5te/OP_UNUSED_77FF.S */
9472/* File: armv5te/unused.S */
9473    bl      common_abort
9474
9475
9476/* ------------------------------ */
9477    .balign 64
9478.L_OP_UNUSED_78FF: /* 0x178 */
9479/* File: armv5te/OP_UNUSED_78FF.S */
9480/* File: armv5te/unused.S */
9481    bl      common_abort
9482
9483
9484/* ------------------------------ */
9485    .balign 64
9486.L_OP_UNUSED_79FF: /* 0x179 */
9487/* File: armv5te/OP_UNUSED_79FF.S */
9488/* File: armv5te/unused.S */
9489    bl      common_abort
9490
9491
9492/* ------------------------------ */
9493    .balign 64
9494.L_OP_UNUSED_7AFF: /* 0x17a */
9495/* File: armv5te/OP_UNUSED_7AFF.S */
9496/* File: armv5te/unused.S */
9497    bl      common_abort
9498
9499
9500/* ------------------------------ */
9501    .balign 64
9502.L_OP_UNUSED_7BFF: /* 0x17b */
9503/* File: armv5te/OP_UNUSED_7BFF.S */
9504/* File: armv5te/unused.S */
9505    bl      common_abort
9506
9507
9508/* ------------------------------ */
9509    .balign 64
9510.L_OP_UNUSED_7CFF: /* 0x17c */
9511/* File: armv5te/OP_UNUSED_7CFF.S */
9512/* File: armv5te/unused.S */
9513    bl      common_abort
9514
9515
9516/* ------------------------------ */
9517    .balign 64
9518.L_OP_UNUSED_7DFF: /* 0x17d */
9519/* File: armv5te/OP_UNUSED_7DFF.S */
9520/* File: armv5te/unused.S */
9521    bl      common_abort
9522
9523
9524/* ------------------------------ */
9525    .balign 64
9526.L_OP_UNUSED_7EFF: /* 0x17e */
9527/* File: armv5te/OP_UNUSED_7EFF.S */
9528/* File: armv5te/unused.S */
9529    bl      common_abort
9530
9531
9532/* ------------------------------ */
9533    .balign 64
9534.L_OP_UNUSED_7FFF: /* 0x17f */
9535/* File: armv5te/OP_UNUSED_7FFF.S */
9536/* File: armv5te/unused.S */
9537    bl      common_abort
9538
9539
9540/* ------------------------------ */
9541    .balign 64
9542.L_OP_UNUSED_80FF: /* 0x180 */
9543/* File: armv5te/OP_UNUSED_80FF.S */
9544/* File: armv5te/unused.S */
9545    bl      common_abort
9546
9547
9548/* ------------------------------ */
9549    .balign 64
9550.L_OP_UNUSED_81FF: /* 0x181 */
9551/* File: armv5te/OP_UNUSED_81FF.S */
9552/* File: armv5te/unused.S */
9553    bl      common_abort
9554
9555
9556/* ------------------------------ */
9557    .balign 64
9558.L_OP_UNUSED_82FF: /* 0x182 */
9559/* File: armv5te/OP_UNUSED_82FF.S */
9560/* File: armv5te/unused.S */
9561    bl      common_abort
9562
9563
9564/* ------------------------------ */
9565    .balign 64
9566.L_OP_UNUSED_83FF: /* 0x183 */
9567/* File: armv5te/OP_UNUSED_83FF.S */
9568/* File: armv5te/unused.S */
9569    bl      common_abort
9570
9571
9572/* ------------------------------ */
9573    .balign 64
9574.L_OP_UNUSED_84FF: /* 0x184 */
9575/* File: armv5te/OP_UNUSED_84FF.S */
9576/* File: armv5te/unused.S */
9577    bl      common_abort
9578
9579
9580/* ------------------------------ */
9581    .balign 64
9582.L_OP_UNUSED_85FF: /* 0x185 */
9583/* File: armv5te/OP_UNUSED_85FF.S */
9584/* File: armv5te/unused.S */
9585    bl      common_abort
9586
9587
9588/* ------------------------------ */
9589    .balign 64
9590.L_OP_UNUSED_86FF: /* 0x186 */
9591/* File: armv5te/OP_UNUSED_86FF.S */
9592/* File: armv5te/unused.S */
9593    bl      common_abort
9594
9595
9596/* ------------------------------ */
9597    .balign 64
9598.L_OP_UNUSED_87FF: /* 0x187 */
9599/* File: armv5te/OP_UNUSED_87FF.S */
9600/* File: armv5te/unused.S */
9601    bl      common_abort
9602
9603
9604/* ------------------------------ */
9605    .balign 64
9606.L_OP_UNUSED_88FF: /* 0x188 */
9607/* File: armv5te/OP_UNUSED_88FF.S */
9608/* File: armv5te/unused.S */
9609    bl      common_abort
9610
9611
9612/* ------------------------------ */
9613    .balign 64
9614.L_OP_UNUSED_89FF: /* 0x189 */
9615/* File: armv5te/OP_UNUSED_89FF.S */
9616/* File: armv5te/unused.S */
9617    bl      common_abort
9618
9619
9620/* ------------------------------ */
9621    .balign 64
9622.L_OP_UNUSED_8AFF: /* 0x18a */
9623/* File: armv5te/OP_UNUSED_8AFF.S */
9624/* File: armv5te/unused.S */
9625    bl      common_abort
9626
9627
9628/* ------------------------------ */
9629    .balign 64
9630.L_OP_UNUSED_8BFF: /* 0x18b */
9631/* File: armv5te/OP_UNUSED_8BFF.S */
9632/* File: armv5te/unused.S */
9633    bl      common_abort
9634
9635
9636/* ------------------------------ */
9637    .balign 64
9638.L_OP_UNUSED_8CFF: /* 0x18c */
9639/* File: armv5te/OP_UNUSED_8CFF.S */
9640/* File: armv5te/unused.S */
9641    bl      common_abort
9642
9643
9644/* ------------------------------ */
9645    .balign 64
9646.L_OP_UNUSED_8DFF: /* 0x18d */
9647/* File: armv5te/OP_UNUSED_8DFF.S */
9648/* File: armv5te/unused.S */
9649    bl      common_abort
9650
9651
9652/* ------------------------------ */
9653    .balign 64
9654.L_OP_UNUSED_8EFF: /* 0x18e */
9655/* File: armv5te/OP_UNUSED_8EFF.S */
9656/* File: armv5te/unused.S */
9657    bl      common_abort
9658
9659
9660/* ------------------------------ */
9661    .balign 64
9662.L_OP_UNUSED_8FFF: /* 0x18f */
9663/* File: armv5te/OP_UNUSED_8FFF.S */
9664/* File: armv5te/unused.S */
9665    bl      common_abort
9666
9667
9668/* ------------------------------ */
9669    .balign 64
9670.L_OP_UNUSED_90FF: /* 0x190 */
9671/* File: armv5te/OP_UNUSED_90FF.S */
9672/* File: armv5te/unused.S */
9673    bl      common_abort
9674
9675
9676/* ------------------------------ */
9677    .balign 64
9678.L_OP_UNUSED_91FF: /* 0x191 */
9679/* File: armv5te/OP_UNUSED_91FF.S */
9680/* File: armv5te/unused.S */
9681    bl      common_abort
9682
9683
9684/* ------------------------------ */
9685    .balign 64
9686.L_OP_UNUSED_92FF: /* 0x192 */
9687/* File: armv5te/OP_UNUSED_92FF.S */
9688/* File: armv5te/unused.S */
9689    bl      common_abort
9690
9691
9692/* ------------------------------ */
9693    .balign 64
9694.L_OP_UNUSED_93FF: /* 0x193 */
9695/* File: armv5te/OP_UNUSED_93FF.S */
9696/* File: armv5te/unused.S */
9697    bl      common_abort
9698
9699
9700/* ------------------------------ */
9701    .balign 64
9702.L_OP_UNUSED_94FF: /* 0x194 */
9703/* File: armv5te/OP_UNUSED_94FF.S */
9704/* File: armv5te/unused.S */
9705    bl      common_abort
9706
9707
9708/* ------------------------------ */
9709    .balign 64
9710.L_OP_UNUSED_95FF: /* 0x195 */
9711/* File: armv5te/OP_UNUSED_95FF.S */
9712/* File: armv5te/unused.S */
9713    bl      common_abort
9714
9715
9716/* ------------------------------ */
9717    .balign 64
9718.L_OP_UNUSED_96FF: /* 0x196 */
9719/* File: armv5te/OP_UNUSED_96FF.S */
9720/* File: armv5te/unused.S */
9721    bl      common_abort
9722
9723
9724/* ------------------------------ */
9725    .balign 64
9726.L_OP_UNUSED_97FF: /* 0x197 */
9727/* File: armv5te/OP_UNUSED_97FF.S */
9728/* File: armv5te/unused.S */
9729    bl      common_abort
9730
9731
9732/* ------------------------------ */
9733    .balign 64
9734.L_OP_UNUSED_98FF: /* 0x198 */
9735/* File: armv5te/OP_UNUSED_98FF.S */
9736/* File: armv5te/unused.S */
9737    bl      common_abort
9738
9739
9740/* ------------------------------ */
9741    .balign 64
9742.L_OP_UNUSED_99FF: /* 0x199 */
9743/* File: armv5te/OP_UNUSED_99FF.S */
9744/* File: armv5te/unused.S */
9745    bl      common_abort
9746
9747
9748/* ------------------------------ */
9749    .balign 64
9750.L_OP_UNUSED_9AFF: /* 0x19a */
9751/* File: armv5te/OP_UNUSED_9AFF.S */
9752/* File: armv5te/unused.S */
9753    bl      common_abort
9754
9755
9756/* ------------------------------ */
9757    .balign 64
9758.L_OP_UNUSED_9BFF: /* 0x19b */
9759/* File: armv5te/OP_UNUSED_9BFF.S */
9760/* File: armv5te/unused.S */
9761    bl      common_abort
9762
9763
9764/* ------------------------------ */
9765    .balign 64
9766.L_OP_UNUSED_9CFF: /* 0x19c */
9767/* File: armv5te/OP_UNUSED_9CFF.S */
9768/* File: armv5te/unused.S */
9769    bl      common_abort
9770
9771
9772/* ------------------------------ */
9773    .balign 64
9774.L_OP_UNUSED_9DFF: /* 0x19d */
9775/* File: armv5te/OP_UNUSED_9DFF.S */
9776/* File: armv5te/unused.S */
9777    bl      common_abort
9778
9779
9780/* ------------------------------ */
9781    .balign 64
9782.L_OP_UNUSED_9EFF: /* 0x19e */
9783/* File: armv5te/OP_UNUSED_9EFF.S */
9784/* File: armv5te/unused.S */
9785    bl      common_abort
9786
9787
9788/* ------------------------------ */
9789    .balign 64
9790.L_OP_UNUSED_9FFF: /* 0x19f */
9791/* File: armv5te/OP_UNUSED_9FFF.S */
9792/* File: armv5te/unused.S */
9793    bl      common_abort
9794
9795
9796/* ------------------------------ */
9797    .balign 64
9798.L_OP_UNUSED_A0FF: /* 0x1a0 */
9799/* File: armv5te/OP_UNUSED_A0FF.S */
9800/* File: armv5te/unused.S */
9801    bl      common_abort
9802
9803
9804/* ------------------------------ */
9805    .balign 64
9806.L_OP_UNUSED_A1FF: /* 0x1a1 */
9807/* File: armv5te/OP_UNUSED_A1FF.S */
9808/* File: armv5te/unused.S */
9809    bl      common_abort
9810
9811
9812/* ------------------------------ */
9813    .balign 64
9814.L_OP_UNUSED_A2FF: /* 0x1a2 */
9815/* File: armv5te/OP_UNUSED_A2FF.S */
9816/* File: armv5te/unused.S */
9817    bl      common_abort
9818
9819
9820/* ------------------------------ */
9821    .balign 64
9822.L_OP_UNUSED_A3FF: /* 0x1a3 */
9823/* File: armv5te/OP_UNUSED_A3FF.S */
9824/* File: armv5te/unused.S */
9825    bl      common_abort
9826
9827
9828/* ------------------------------ */
9829    .balign 64
9830.L_OP_UNUSED_A4FF: /* 0x1a4 */
9831/* File: armv5te/OP_UNUSED_A4FF.S */
9832/* File: armv5te/unused.S */
9833    bl      common_abort
9834
9835
9836/* ------------------------------ */
9837    .balign 64
9838.L_OP_UNUSED_A5FF: /* 0x1a5 */
9839/* File: armv5te/OP_UNUSED_A5FF.S */
9840/* File: armv5te/unused.S */
9841    bl      common_abort
9842
9843
9844/* ------------------------------ */
9845    .balign 64
9846.L_OP_UNUSED_A6FF: /* 0x1a6 */
9847/* File: armv5te/OP_UNUSED_A6FF.S */
9848/* File: armv5te/unused.S */
9849    bl      common_abort
9850
9851
9852/* ------------------------------ */
9853    .balign 64
9854.L_OP_UNUSED_A7FF: /* 0x1a7 */
9855/* File: armv5te/OP_UNUSED_A7FF.S */
9856/* File: armv5te/unused.S */
9857    bl      common_abort
9858
9859
9860/* ------------------------------ */
9861    .balign 64
9862.L_OP_UNUSED_A8FF: /* 0x1a8 */
9863/* File: armv5te/OP_UNUSED_A8FF.S */
9864/* File: armv5te/unused.S */
9865    bl      common_abort
9866
9867
9868/* ------------------------------ */
9869    .balign 64
9870.L_OP_UNUSED_A9FF: /* 0x1a9 */
9871/* File: armv5te/OP_UNUSED_A9FF.S */
9872/* File: armv5te/unused.S */
9873    bl      common_abort
9874
9875
9876/* ------------------------------ */
9877    .balign 64
9878.L_OP_UNUSED_AAFF: /* 0x1aa */
9879/* File: armv5te/OP_UNUSED_AAFF.S */
9880/* File: armv5te/unused.S */
9881    bl      common_abort
9882
9883
9884/* ------------------------------ */
9885    .balign 64
9886.L_OP_UNUSED_ABFF: /* 0x1ab */
9887/* File: armv5te/OP_UNUSED_ABFF.S */
9888/* File: armv5te/unused.S */
9889    bl      common_abort
9890
9891
9892/* ------------------------------ */
9893    .balign 64
9894.L_OP_UNUSED_ACFF: /* 0x1ac */
9895/* File: armv5te/OP_UNUSED_ACFF.S */
9896/* File: armv5te/unused.S */
9897    bl      common_abort
9898
9899
9900/* ------------------------------ */
9901    .balign 64
9902.L_OP_UNUSED_ADFF: /* 0x1ad */
9903/* File: armv5te/OP_UNUSED_ADFF.S */
9904/* File: armv5te/unused.S */
9905    bl      common_abort
9906
9907
9908/* ------------------------------ */
9909    .balign 64
9910.L_OP_UNUSED_AEFF: /* 0x1ae */
9911/* File: armv5te/OP_UNUSED_AEFF.S */
9912/* File: armv5te/unused.S */
9913    bl      common_abort
9914
9915
9916/* ------------------------------ */
9917    .balign 64
9918.L_OP_UNUSED_AFFF: /* 0x1af */
9919/* File: armv5te/OP_UNUSED_AFFF.S */
9920/* File: armv5te/unused.S */
9921    bl      common_abort
9922
9923
9924/* ------------------------------ */
9925    .balign 64
9926.L_OP_UNUSED_B0FF: /* 0x1b0 */
9927/* File: armv5te/OP_UNUSED_B0FF.S */
9928/* File: armv5te/unused.S */
9929    bl      common_abort
9930
9931
9932/* ------------------------------ */
9933    .balign 64
9934.L_OP_UNUSED_B1FF: /* 0x1b1 */
9935/* File: armv5te/OP_UNUSED_B1FF.S */
9936/* File: armv5te/unused.S */
9937    bl      common_abort
9938
9939
9940/* ------------------------------ */
9941    .balign 64
9942.L_OP_UNUSED_B2FF: /* 0x1b2 */
9943/* File: armv5te/OP_UNUSED_B2FF.S */
9944/* File: armv5te/unused.S */
9945    bl      common_abort
9946
9947
9948/* ------------------------------ */
9949    .balign 64
9950.L_OP_UNUSED_B3FF: /* 0x1b3 */
9951/* File: armv5te/OP_UNUSED_B3FF.S */
9952/* File: armv5te/unused.S */
9953    bl      common_abort
9954
9955
9956/* ------------------------------ */
9957    .balign 64
9958.L_OP_UNUSED_B4FF: /* 0x1b4 */
9959/* File: armv5te/OP_UNUSED_B4FF.S */
9960/* File: armv5te/unused.S */
9961    bl      common_abort
9962
9963
9964/* ------------------------------ */
9965    .balign 64
9966.L_OP_UNUSED_B5FF: /* 0x1b5 */
9967/* File: armv5te/OP_UNUSED_B5FF.S */
9968/* File: armv5te/unused.S */
9969    bl      common_abort
9970
9971
9972/* ------------------------------ */
9973    .balign 64
9974.L_OP_UNUSED_B6FF: /* 0x1b6 */
9975/* File: armv5te/OP_UNUSED_B6FF.S */
9976/* File: armv5te/unused.S */
9977    bl      common_abort
9978
9979
9980/* ------------------------------ */
9981    .balign 64
9982.L_OP_UNUSED_B7FF: /* 0x1b7 */
9983/* File: armv5te/OP_UNUSED_B7FF.S */
9984/* File: armv5te/unused.S */
9985    bl      common_abort
9986
9987
9988/* ------------------------------ */
9989    .balign 64
9990.L_OP_UNUSED_B8FF: /* 0x1b8 */
9991/* File: armv5te/OP_UNUSED_B8FF.S */
9992/* File: armv5te/unused.S */
9993    bl      common_abort
9994
9995
9996/* ------------------------------ */
9997    .balign 64
9998.L_OP_UNUSED_B9FF: /* 0x1b9 */
9999/* File: armv5te/OP_UNUSED_B9FF.S */
10000/* File: armv5te/unused.S */
10001    bl      common_abort
10002
10003
10004/* ------------------------------ */
10005    .balign 64
10006.L_OP_UNUSED_BAFF: /* 0x1ba */
10007/* File: armv5te/OP_UNUSED_BAFF.S */
10008/* File: armv5te/unused.S */
10009    bl      common_abort
10010
10011
10012/* ------------------------------ */
10013    .balign 64
10014.L_OP_UNUSED_BBFF: /* 0x1bb */
10015/* File: armv5te/OP_UNUSED_BBFF.S */
10016/* File: armv5te/unused.S */
10017    bl      common_abort
10018
10019
10020/* ------------------------------ */
10021    .balign 64
10022.L_OP_UNUSED_BCFF: /* 0x1bc */
10023/* File: armv5te/OP_UNUSED_BCFF.S */
10024/* File: armv5te/unused.S */
10025    bl      common_abort
10026
10027
10028/* ------------------------------ */
10029    .balign 64
10030.L_OP_UNUSED_BDFF: /* 0x1bd */
10031/* File: armv5te/OP_UNUSED_BDFF.S */
10032/* File: armv5te/unused.S */
10033    bl      common_abort
10034
10035
10036/* ------------------------------ */
10037    .balign 64
10038.L_OP_UNUSED_BEFF: /* 0x1be */
10039/* File: armv5te/OP_UNUSED_BEFF.S */
10040/* File: armv5te/unused.S */
10041    bl      common_abort
10042
10043
10044/* ------------------------------ */
10045    .balign 64
10046.L_OP_UNUSED_BFFF: /* 0x1bf */
10047/* File: armv5te/OP_UNUSED_BFFF.S */
10048/* File: armv5te/unused.S */
10049    bl      common_abort
10050
10051
10052/* ------------------------------ */
10053    .balign 64
10054.L_OP_UNUSED_C0FF: /* 0x1c0 */
10055/* File: armv5te/OP_UNUSED_C0FF.S */
10056/* File: armv5te/unused.S */
10057    bl      common_abort
10058
10059
10060/* ------------------------------ */
10061    .balign 64
10062.L_OP_UNUSED_C1FF: /* 0x1c1 */
10063/* File: armv5te/OP_UNUSED_C1FF.S */
10064/* File: armv5te/unused.S */
10065    bl      common_abort
10066
10067
10068/* ------------------------------ */
10069    .balign 64
10070.L_OP_UNUSED_C2FF: /* 0x1c2 */
10071/* File: armv5te/OP_UNUSED_C2FF.S */
10072/* File: armv5te/unused.S */
10073    bl      common_abort
10074
10075
10076/* ------------------------------ */
10077    .balign 64
10078.L_OP_UNUSED_C3FF: /* 0x1c3 */
10079/* File: armv5te/OP_UNUSED_C3FF.S */
10080/* File: armv5te/unused.S */
10081    bl      common_abort
10082
10083
10084/* ------------------------------ */
10085    .balign 64
10086.L_OP_UNUSED_C4FF: /* 0x1c4 */
10087/* File: armv5te/OP_UNUSED_C4FF.S */
10088/* File: armv5te/unused.S */
10089    bl      common_abort
10090
10091
10092/* ------------------------------ */
10093    .balign 64
10094.L_OP_UNUSED_C5FF: /* 0x1c5 */
10095/* File: armv5te/OP_UNUSED_C5FF.S */
10096/* File: armv5te/unused.S */
10097    bl      common_abort
10098
10099
10100/* ------------------------------ */
10101    .balign 64
10102.L_OP_UNUSED_C6FF: /* 0x1c6 */
10103/* File: armv5te/OP_UNUSED_C6FF.S */
10104/* File: armv5te/unused.S */
10105    bl      common_abort
10106
10107
10108/* ------------------------------ */
10109    .balign 64
10110.L_OP_UNUSED_C7FF: /* 0x1c7 */
10111/* File: armv5te/OP_UNUSED_C7FF.S */
10112/* File: armv5te/unused.S */
10113    bl      common_abort
10114
10115
10116/* ------------------------------ */
10117    .balign 64
10118.L_OP_UNUSED_C8FF: /* 0x1c8 */
10119/* File: armv5te/OP_UNUSED_C8FF.S */
10120/* File: armv5te/unused.S */
10121    bl      common_abort
10122
10123
10124/* ------------------------------ */
10125    .balign 64
10126.L_OP_UNUSED_C9FF: /* 0x1c9 */
10127/* File: armv5te/OP_UNUSED_C9FF.S */
10128/* File: armv5te/unused.S */
10129    bl      common_abort
10130
10131
10132/* ------------------------------ */
10133    .balign 64
10134.L_OP_UNUSED_CAFF: /* 0x1ca */
10135/* File: armv5te/OP_UNUSED_CAFF.S */
10136/* File: armv5te/unused.S */
10137    bl      common_abort
10138
10139
10140/* ------------------------------ */
10141    .balign 64
10142.L_OP_UNUSED_CBFF: /* 0x1cb */
10143/* File: armv5te/OP_UNUSED_CBFF.S */
10144/* File: armv5te/unused.S */
10145    bl      common_abort
10146
10147
10148/* ------------------------------ */
10149    .balign 64
10150.L_OP_UNUSED_CCFF: /* 0x1cc */
10151/* File: armv5te/OP_UNUSED_CCFF.S */
10152/* File: armv5te/unused.S */
10153    bl      common_abort
10154
10155
10156/* ------------------------------ */
10157    .balign 64
10158.L_OP_UNUSED_CDFF: /* 0x1cd */
10159/* File: armv5te/OP_UNUSED_CDFF.S */
10160/* File: armv5te/unused.S */
10161    bl      common_abort
10162
10163
10164/* ------------------------------ */
10165    .balign 64
10166.L_OP_UNUSED_CEFF: /* 0x1ce */
10167/* File: armv5te/OP_UNUSED_CEFF.S */
10168/* File: armv5te/unused.S */
10169    bl      common_abort
10170
10171
10172/* ------------------------------ */
10173    .balign 64
10174.L_OP_UNUSED_CFFF: /* 0x1cf */
10175/* File: armv5te/OP_UNUSED_CFFF.S */
10176/* File: armv5te/unused.S */
10177    bl      common_abort
10178
10179
10180/* ------------------------------ */
10181    .balign 64
10182.L_OP_UNUSED_D0FF: /* 0x1d0 */
10183/* File: armv5te/OP_UNUSED_D0FF.S */
10184/* File: armv5te/unused.S */
10185    bl      common_abort
10186
10187
10188/* ------------------------------ */
10189    .balign 64
10190.L_OP_UNUSED_D1FF: /* 0x1d1 */
10191/* File: armv5te/OP_UNUSED_D1FF.S */
10192/* File: armv5te/unused.S */
10193    bl      common_abort
10194
10195
10196/* ------------------------------ */
10197    .balign 64
10198.L_OP_UNUSED_D2FF: /* 0x1d2 */
10199/* File: armv5te/OP_UNUSED_D2FF.S */
10200/* File: armv5te/unused.S */
10201    bl      common_abort
10202
10203
10204/* ------------------------------ */
10205    .balign 64
10206.L_OP_UNUSED_D3FF: /* 0x1d3 */
10207/* File: armv5te/OP_UNUSED_D3FF.S */
10208/* File: armv5te/unused.S */
10209    bl      common_abort
10210
10211
10212/* ------------------------------ */
10213    .balign 64
10214.L_OP_UNUSED_D4FF: /* 0x1d4 */
10215/* File: armv5te/OP_UNUSED_D4FF.S */
10216/* File: armv5te/unused.S */
10217    bl      common_abort
10218
10219
10220/* ------------------------------ */
10221    .balign 64
10222.L_OP_UNUSED_D5FF: /* 0x1d5 */
10223/* File: armv5te/OP_UNUSED_D5FF.S */
10224/* File: armv5te/unused.S */
10225    bl      common_abort
10226
10227
10228/* ------------------------------ */
10229    .balign 64
10230.L_OP_UNUSED_D6FF: /* 0x1d6 */
10231/* File: armv5te/OP_UNUSED_D6FF.S */
10232/* File: armv5te/unused.S */
10233    bl      common_abort
10234
10235
10236/* ------------------------------ */
10237    .balign 64
10238.L_OP_UNUSED_D7FF: /* 0x1d7 */
10239/* File: armv5te/OP_UNUSED_D7FF.S */
10240/* File: armv5te/unused.S */
10241    bl      common_abort
10242
10243
10244/* ------------------------------ */
10245    .balign 64
10246.L_OP_UNUSED_D8FF: /* 0x1d8 */
10247/* File: armv5te/OP_UNUSED_D8FF.S */
10248/* File: armv5te/unused.S */
10249    bl      common_abort
10250
10251
10252/* ------------------------------ */
10253    .balign 64
10254.L_OP_UNUSED_D9FF: /* 0x1d9 */
10255/* File: armv5te/OP_UNUSED_D9FF.S */
10256/* File: armv5te/unused.S */
10257    bl      common_abort
10258
10259
10260/* ------------------------------ */
10261    .balign 64
10262.L_OP_UNUSED_DAFF: /* 0x1da */
10263/* File: armv5te/OP_UNUSED_DAFF.S */
10264/* File: armv5te/unused.S */
10265    bl      common_abort
10266
10267
10268/* ------------------------------ */
10269    .balign 64
10270.L_OP_UNUSED_DBFF: /* 0x1db */
10271/* File: armv5te/OP_UNUSED_DBFF.S */
10272/* File: armv5te/unused.S */
10273    bl      common_abort
10274
10275
10276/* ------------------------------ */
10277    .balign 64
10278.L_OP_UNUSED_DCFF: /* 0x1dc */
10279/* File: armv5te/OP_UNUSED_DCFF.S */
10280/* File: armv5te/unused.S */
10281    bl      common_abort
10282
10283
10284/* ------------------------------ */
10285    .balign 64
10286.L_OP_UNUSED_DDFF: /* 0x1dd */
10287/* File: armv5te/OP_UNUSED_DDFF.S */
10288/* File: armv5te/unused.S */
10289    bl      common_abort
10290
10291
10292/* ------------------------------ */
10293    .balign 64
10294.L_OP_UNUSED_DEFF: /* 0x1de */
10295/* File: armv5te/OP_UNUSED_DEFF.S */
10296/* File: armv5te/unused.S */
10297    bl      common_abort
10298
10299
10300/* ------------------------------ */
10301    .balign 64
10302.L_OP_UNUSED_DFFF: /* 0x1df */
10303/* File: armv5te/OP_UNUSED_DFFF.S */
10304/* File: armv5te/unused.S */
10305    bl      common_abort
10306
10307
10308/* ------------------------------ */
10309    .balign 64
10310.L_OP_UNUSED_E0FF: /* 0x1e0 */
10311/* File: armv5te/OP_UNUSED_E0FF.S */
10312/* File: armv5te/unused.S */
10313    bl      common_abort
10314
10315
10316/* ------------------------------ */
10317    .balign 64
10318.L_OP_UNUSED_E1FF: /* 0x1e1 */
10319/* File: armv5te/OP_UNUSED_E1FF.S */
10320/* File: armv5te/unused.S */
10321    bl      common_abort
10322
10323
10324/* ------------------------------ */
10325    .balign 64
10326.L_OP_UNUSED_E2FF: /* 0x1e2 */
10327/* File: armv5te/OP_UNUSED_E2FF.S */
10328/* File: armv5te/unused.S */
10329    bl      common_abort
10330
10331
10332/* ------------------------------ */
10333    .balign 64
10334.L_OP_UNUSED_E3FF: /* 0x1e3 */
10335/* File: armv5te/OP_UNUSED_E3FF.S */
10336/* File: armv5te/unused.S */
10337    bl      common_abort
10338
10339
10340/* ------------------------------ */
10341    .balign 64
10342.L_OP_UNUSED_E4FF: /* 0x1e4 */
10343/* File: armv5te/OP_UNUSED_E4FF.S */
10344/* File: armv5te/unused.S */
10345    bl      common_abort
10346
10347
10348/* ------------------------------ */
10349    .balign 64
10350.L_OP_UNUSED_E5FF: /* 0x1e5 */
10351/* File: armv5te/OP_UNUSED_E5FF.S */
10352/* File: armv5te/unused.S */
10353    bl      common_abort
10354
10355
10356/* ------------------------------ */
10357    .balign 64
10358.L_OP_UNUSED_E6FF: /* 0x1e6 */
10359/* File: armv5te/OP_UNUSED_E6FF.S */
10360/* File: armv5te/unused.S */
10361    bl      common_abort
10362
10363
10364/* ------------------------------ */
10365    .balign 64
10366.L_OP_UNUSED_E7FF: /* 0x1e7 */
10367/* File: armv5te/OP_UNUSED_E7FF.S */
10368/* File: armv5te/unused.S */
10369    bl      common_abort
10370
10371
10372/* ------------------------------ */
10373    .balign 64
10374.L_OP_UNUSED_E8FF: /* 0x1e8 */
10375/* File: armv5te/OP_UNUSED_E8FF.S */
10376/* File: armv5te/unused.S */
10377    bl      common_abort
10378
10379
10380/* ------------------------------ */
10381    .balign 64
10382.L_OP_UNUSED_E9FF: /* 0x1e9 */
10383/* File: armv5te/OP_UNUSED_E9FF.S */
10384/* File: armv5te/unused.S */
10385    bl      common_abort
10386
10387
10388/* ------------------------------ */
10389    .balign 64
10390.L_OP_UNUSED_EAFF: /* 0x1ea */
10391/* File: armv5te/OP_UNUSED_EAFF.S */
10392/* File: armv5te/unused.S */
10393    bl      common_abort
10394
10395
10396/* ------------------------------ */
10397    .balign 64
10398.L_OP_UNUSED_EBFF: /* 0x1eb */
10399/* File: armv5te/OP_UNUSED_EBFF.S */
10400/* File: armv5te/unused.S */
10401    bl      common_abort
10402
10403
10404/* ------------------------------ */
10405    .balign 64
10406.L_OP_UNUSED_ECFF: /* 0x1ec */
10407/* File: armv5te/OP_UNUSED_ECFF.S */
10408/* File: armv5te/unused.S */
10409    bl      common_abort
10410
10411
10412/* ------------------------------ */
10413    .balign 64
10414.L_OP_UNUSED_EDFF: /* 0x1ed */
10415/* File: armv5te/OP_UNUSED_EDFF.S */
10416/* File: armv5te/unused.S */
10417    bl      common_abort
10418
10419
10420/* ------------------------------ */
10421    .balign 64
10422.L_OP_UNUSED_EEFF: /* 0x1ee */
10423/* File: armv5te/OP_UNUSED_EEFF.S */
10424/* File: armv5te/unused.S */
10425    bl      common_abort
10426
10427
10428/* ------------------------------ */
10429    .balign 64
10430.L_OP_UNUSED_EFFF: /* 0x1ef */
10431/* File: armv5te/OP_UNUSED_EFFF.S */
10432/* File: armv5te/unused.S */
10433    bl      common_abort
10434
10435
10436/* ------------------------------ */
10437    .balign 64
10438.L_OP_UNUSED_F0FF: /* 0x1f0 */
10439/* File: armv5te/OP_UNUSED_F0FF.S */
10440/* File: armv5te/unused.S */
10441    bl      common_abort
10442
10443
10444/* ------------------------------ */
10445    .balign 64
10446.L_OP_UNUSED_F1FF: /* 0x1f1 */
10447/* File: armv5te/OP_UNUSED_F1FF.S */
10448/* File: armv5te/unused.S */
10449    bl      common_abort
10450
10451
10452/* ------------------------------ */
10453    .balign 64
10454.L_OP_UNUSED_F2FF: /* 0x1f2 */
10455/* File: armv5te/OP_UNUSED_F2FF.S */
10456/* File: armv5te/unused.S */
10457    bl      common_abort
10458
10459
10460/* ------------------------------ */
10461    .balign 64
10462.L_OP_UNUSED_F3FF: /* 0x1f3 */
10463/* File: armv5te/OP_UNUSED_F3FF.S */
10464/* File: armv5te/unused.S */
10465    bl      common_abort
10466
10467
10468/* ------------------------------ */
10469    .balign 64
10470.L_OP_UNUSED_F4FF: /* 0x1f4 */
10471/* File: armv5te/OP_UNUSED_F4FF.S */
10472/* File: armv5te/unused.S */
10473    bl      common_abort
10474
10475
10476/* ------------------------------ */
10477    .balign 64
10478.L_OP_UNUSED_F5FF: /* 0x1f5 */
10479/* File: armv5te/OP_UNUSED_F5FF.S */
10480/* File: armv5te/unused.S */
10481    bl      common_abort
10482
10483
10484/* ------------------------------ */
10485    .balign 64
10486.L_OP_UNUSED_F6FF: /* 0x1f6 */
10487/* File: armv5te/OP_UNUSED_F6FF.S */
10488/* File: armv5te/unused.S */
10489    bl      common_abort
10490
10491
10492/* ------------------------------ */
10493    .balign 64
10494.L_OP_UNUSED_F7FF: /* 0x1f7 */
10495/* File: armv5te/OP_UNUSED_F7FF.S */
10496/* File: armv5te/unused.S */
10497    bl      common_abort
10498
10499
10500/* ------------------------------ */
10501    .balign 64
10502.L_OP_UNUSED_F8FF: /* 0x1f8 */
10503/* File: armv5te/OP_UNUSED_F8FF.S */
10504/* File: armv5te/unused.S */
10505    bl      common_abort
10506
10507
10508/* ------------------------------ */
10509    .balign 64
10510.L_OP_UNUSED_F9FF: /* 0x1f9 */
10511/* File: armv5te/OP_UNUSED_F9FF.S */
10512/* File: armv5te/unused.S */
10513    bl      common_abort
10514
10515
10516/* ------------------------------ */
10517    .balign 64
10518.L_OP_UNUSED_FAFF: /* 0x1fa */
10519/* File: armv5te/OP_UNUSED_FAFF.S */
10520/* File: armv5te/unused.S */
10521    bl      common_abort
10522
10523
10524/* ------------------------------ */
10525    .balign 64
10526.L_OP_UNUSED_FBFF: /* 0x1fb */
10527/* File: armv5te/OP_UNUSED_FBFF.S */
10528/* File: armv5te/unused.S */
10529    bl      common_abort
10530
10531
10532/* ------------------------------ */
10533    .balign 64
10534.L_OP_UNUSED_FCFF: /* 0x1fc */
10535/* File: armv5te/OP_UNUSED_FCFF.S */
10536/* File: armv5te/unused.S */
10537    bl      common_abort
10538
10539
10540/* ------------------------------ */
10541    .balign 64
10542.L_OP_UNUSED_FDFF: /* 0x1fd */
10543/* File: armv5te/OP_UNUSED_FDFF.S */
10544/* File: armv5te/unused.S */
10545    bl      common_abort
10546
10547
10548/* ------------------------------ */
10549    .balign 64
10550.L_OP_UNUSED_FEFF: /* 0x1fe */
10551/* File: armv5te/OP_UNUSED_FEFF.S */
10552/* File: armv5te/unused.S */
10553    bl      common_abort
10554
10555
10556/* ------------------------------ */
10557    .balign 64
10558.L_OP_THROW_VERIFICATION_ERROR_JUMBO: /* 0x1ff */
10559/* File: armv5te/OP_THROW_VERIFICATION_ERROR_JUMBO.S */
10560    /*
10561     * Handle a jumbo throw-verification-error instruction.  This throws an
10562     * exception for an error discovered during verification.  The
10563     * exception is indicated by BBBB, with some detail provided by AAAAAAAA.
10564     */
10565    /* exop BBBB, Class@AAAAAAAA */
10566    FETCH(r1, 1)                        @ r1<- aaaa (lo)
10567    FETCH(r2, 2)                        @ r2<- AAAA (hi)
10568    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
10569    orr     r2, r1, r2, lsl #16         @ r2<- AAAAaaaa
10570    EXPORT_PC()                         @ export the PC
10571    FETCH(r1, 3)                        @ r1<- BBBB
10572    bl      dvmThrowVerificationError   @ always throws
10573    b       common_exceptionThrown      @ handle exception
10574
10575
10576    .balign 64
10577    .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
10578    .global dvmAsmInstructionEnd
10579dvmAsmInstructionEnd:
10580
10581/*
10582 * ===========================================================================
10583 *  Sister implementations
10584 * ===========================================================================
10585 */
10586    .global dvmAsmSisterStart
10587    .type   dvmAsmSisterStart, %function
10588    .text
10589    .balign 4
10590dvmAsmSisterStart:
10591
10592/* continuation for OP_CONST_STRING */
10593
10594    /*
10595     * Continuation if the String has not yet been resolved.
10596     *  r1: BBBB (String ref)
10597     *  r9: target register
10598     */
10599.LOP_CONST_STRING_resolve:
10600    EXPORT_PC()
10601    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
10602    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
10603    bl      dvmResolveString            @ r0<- String reference
10604    cmp     r0, #0                      @ failed?
10605    beq     common_exceptionThrown      @ yup, handle the exception
10606    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
10607    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10608    SET_VREG(r0, r9)                    @ vAA<- r0
10609    GOTO_OPCODE(ip)                     @ jump to next instruction
10610
10611/* continuation for OP_CONST_STRING_JUMBO */
10612
10613    /*
10614     * Continuation if the String has not yet been resolved.
10615     *  r1: BBBBBBBB (String ref)
10616     *  r9: target register
10617     */
10618.LOP_CONST_STRING_JUMBO_resolve:
10619    EXPORT_PC()
10620    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
10621    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
10622    bl      dvmResolveString            @ r0<- String reference
10623    cmp     r0, #0                      @ failed?
10624    beq     common_exceptionThrown      @ yup, handle the exception
10625    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
10626    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10627    SET_VREG(r0, r9)                    @ vAA<- r0
10628    GOTO_OPCODE(ip)                     @ jump to next instruction
10629
10630/* continuation for OP_CONST_CLASS */
10631
10632    /*
10633     * Continuation if the Class has not yet been resolved.
10634     *  r1: BBBB (Class ref)
10635     *  r9: target register
10636     */
10637.LOP_CONST_CLASS_resolve:
10638    EXPORT_PC()
10639    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
10640    mov     r2, #1                      @ r2<- true
10641    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
10642    bl      dvmResolveClass             @ r0<- Class reference
10643    cmp     r0, #0                      @ failed?
10644    beq     common_exceptionThrown      @ yup, handle the exception
10645    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
10646    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10647    SET_VREG(r0, r9)                    @ vAA<- r0
10648    GOTO_OPCODE(ip)                     @ jump to next instruction
10649
10650/* continuation for OP_CHECK_CAST */
10651
10652    /*
10653     * Trivial test failed, need to perform full check.  This is common.
10654     *  r0 holds obj->clazz
10655     *  r1 holds desired class resolved from BBBB
10656     *  r9 holds object
10657     */
10658.LOP_CHECK_CAST_fullcheck:
10659    mov     r10, r1                     @ avoid ClassObject getting clobbered
10660    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
10661    cmp     r0, #0                      @ failed?
10662    bne     .LOP_CHECK_CAST_okay            @ no, success
10663
10664    @ A cast has failed.  We need to throw a ClassCastException.
10665    EXPORT_PC()                         @ about to throw
10666    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz (actual class)
10667    mov     r1, r10                     @ r1<- desired class
10668    bl      dvmThrowClassCastException
10669    b       common_exceptionThrown
10670
10671    /*
10672     * Resolution required.  This is the least-likely path.
10673     *
10674     *  r2 holds BBBB
10675     *  r9 holds object
10676     */
10677.LOP_CHECK_CAST_resolve:
10678    EXPORT_PC()                         @ resolve() could throw
10679    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
10680    mov     r1, r2                      @ r1<- BBBB
10681    mov     r2, #0                      @ r2<- false
10682    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
10683    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
10684    cmp     r0, #0                      @ got null?
10685    beq     common_exceptionThrown      @ yes, handle exception
10686    mov     r1, r0                      @ r1<- class resolved from BBB
10687    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
10688    b       .LOP_CHECK_CAST_resolved        @ pick up where we left off
10689
10690/* continuation for OP_INSTANCE_OF */
10691
10692    /*
10693     * Trivial test failed, need to perform full check.  This is common.
10694     *  r0 holds obj->clazz
10695     *  r1 holds class resolved from BBBB
10696     *  r9 holds A
10697     */
10698.LOP_INSTANCE_OF_fullcheck:
10699    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
10700    @ fall through to OP_INSTANCE_OF_store
10701
10702    /*
10703     * r0 holds boolean result
10704     * r9 holds A
10705     */
10706.LOP_INSTANCE_OF_store:
10707    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
10708    SET_VREG(r0, r9)                    @ vA<- r0
10709    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10710    GOTO_OPCODE(ip)                     @ jump to next instruction
10711
10712    /*
10713     * Trivial test succeeded, save and bail.
10714     *  r9 holds A
10715     */
10716.LOP_INSTANCE_OF_trivial:
10717    mov     r0, #1                      @ indicate success
10718    @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
10719    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
10720    SET_VREG(r0, r9)                    @ vA<- r0
10721    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10722    GOTO_OPCODE(ip)                     @ jump to next instruction
10723
10724    /*
10725     * Resolution required.  This is the least-likely path.
10726     *
10727     *  r3 holds BBBB
10728     *  r9 holds A
10729     */
10730.LOP_INSTANCE_OF_resolve:
10731    EXPORT_PC()                         @ resolve() could throw
10732    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
10733    mov     r1, r3                      @ r1<- BBBB
10734    mov     r2, #1                      @ r2<- true
10735    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
10736    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
10737    cmp     r0, #0                      @ got null?
10738    beq     common_exceptionThrown      @ yes, handle exception
10739    mov     r1, r0                      @ r1<- class resolved from BBB
10740    mov     r3, rINST, lsr #12          @ r3<- B
10741    GET_VREG(r0, r3)                    @ r0<- vB (object)
10742    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
10743    b       .LOP_INSTANCE_OF_resolved        @ pick up where we left off
10744
10745/* continuation for OP_NEW_INSTANCE */
10746
10747    .balign 32                          @ minimize cache lines
10748.LOP_NEW_INSTANCE_finish: @ r0=new object
10749    mov     r3, rINST, lsr #8           @ r3<- AA
10750    cmp     r0, #0                      @ failed?
10751    beq     common_exceptionThrown      @ yes, handle the exception
10752    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
10753    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10754    SET_VREG(r0, r3)                    @ vAA<- r0
10755    GOTO_OPCODE(ip)                     @ jump to next instruction
10756
10757    /*
10758     * Class initialization required.
10759     *
10760     *  r0 holds class object
10761     */
10762.LOP_NEW_INSTANCE_needinit:
10763    mov     r9, r0                      @ save r0
10764    bl      dvmInitClass                @ initialize class
10765    cmp     r0, #0                      @ check boolean result
10766    mov     r0, r9                      @ restore r0
10767    bne     .LOP_NEW_INSTANCE_initialized     @ success, continue
10768    b       common_exceptionThrown      @ failed, deal with init exception
10769
10770    /*
10771     * Resolution required.  This is the least-likely path.
10772     *
10773     *  r1 holds BBBB
10774     */
10775.LOP_NEW_INSTANCE_resolve:
10776    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
10777    mov     r2, #0                      @ r2<- false
10778    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
10779    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
10780    cmp     r0, #0                      @ got null?
10781    bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
10782    b       common_exceptionThrown      @ yes, handle exception
10783
10784.LstrInstantiationErrorPtr:
10785    .word   .LstrInstantiationError
10786
10787/* continuation for OP_NEW_ARRAY */
10788
10789
10790    /*
10791     * Resolve class.  (This is an uncommon case.)
10792     *
10793     *  r1 holds array length
10794     *  r2 holds class ref CCCC
10795     */
10796.LOP_NEW_ARRAY_resolve:
10797    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
10798    mov     r9, r1                      @ r9<- length (save)
10799    mov     r1, r2                      @ r1<- CCCC
10800    mov     r2, #0                      @ r2<- false
10801    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
10802    bl      dvmResolveClass             @ r0<- call(clazz, ref)
10803    cmp     r0, #0                      @ got null?
10804    mov     r1, r9                      @ r1<- length (restore)
10805    beq     common_exceptionThrown      @ yes, handle exception
10806    @ fall through to OP_NEW_ARRAY_finish
10807
10808    /*
10809     * Finish allocation.
10810     *
10811     *  r0 holds class
10812     *  r1 holds array length
10813     */
10814.LOP_NEW_ARRAY_finish:
10815    mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
10816    bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
10817    cmp     r0, #0                      @ failed?
10818    mov     r2, rINST, lsr #8           @ r2<- A+
10819    beq     common_exceptionThrown      @ yes, handle the exception
10820    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
10821    and     r2, r2, #15                 @ r2<- A
10822    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10823    SET_VREG(r0, r2)                    @ vA<- r0
10824    GOTO_OPCODE(ip)                     @ jump to next instruction
10825
10826/* continuation for OP_FILLED_NEW_ARRAY */
10827
10828    /*
10829     * On entry:
10830     *  r0 holds array class
10831     *  r10 holds AA or BA
10832     */
10833.LOP_FILLED_NEW_ARRAY_continue:
10834    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
10835    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
10836    ldrb    rINST, [r3, #1]             @ rINST<- descriptor[1]
10837    .if     0
10838    mov     r1, r10                     @ r1<- AA (length)
10839    .else
10840    mov     r1, r10, lsr #4             @ r1<- B (length)
10841    .endif
10842    cmp     rINST, #'I'                 @ array of ints?
10843    cmpne   rINST, #'L'                 @ array of objects?
10844    cmpne   rINST, #'['                 @ array of arrays?
10845    mov     r9, r1                      @ save length in r9
10846    bne     .LOP_FILLED_NEW_ARRAY_notimpl         @ no, not handled yet
10847    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
10848    cmp     r0, #0                      @ null return?
10849    beq     common_exceptionThrown      @ alloc failed, handle exception
10850
10851    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
10852    str     r0, [rGLUE, #offGlue_retval]      @ retval.l <- new array
10853    str     rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
10854    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
10855    subs    r9, r9, #1                  @ length--, check for neg
10856    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
10857    bmi     2f                          @ was zero, bail
10858
10859    @ copy values from registers into the array
10860    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
10861    .if     0
10862    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
108631:  ldr     r3, [r2], #4                @ r3<- *r2++
10864    subs    r9, r9, #1                  @ count--
10865    str     r3, [r0], #4                @ *contents++ = vX
10866    bpl     1b
10867    @ continue at 2
10868    .else
10869    cmp     r9, #4                      @ length was initially 5?
10870    and     r2, r10, #15                @ r2<- A
10871    bne     1f                          @ <= 4 args, branch
10872    GET_VREG(r3, r2)                    @ r3<- vA
10873    sub     r9, r9, #1                  @ count--
10874    str     r3, [r0, #16]               @ contents[4] = vA
108751:  and     r2, r1, #15                 @ r2<- F/E/D/C
10876    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
10877    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
10878    subs    r9, r9, #1                  @ count--
10879    str     r3, [r0], #4                @ *contents++ = vX
10880    bpl     1b
10881    @ continue at 2
10882    .endif
10883
108842:
10885    ldr     r0, [rGLUE, #offGlue_retval]     @ r0<- object
10886    ldr     r1, [rGLUE, #offGlue_retval+4]   @ r1<- type
10887    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
10888    GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
10889    cmp     r1, #'I'                         @ Is int array?
10890    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head
10891    GOTO_OPCODE(ip)                          @ execute it
10892
10893    /*
10894     * Throw an exception indicating that we have not implemented this
10895     * mode of filled-new-array.
10896     */
10897.LOP_FILLED_NEW_ARRAY_notimpl:
10898    ldr     r0, .L_strInternalError
10899    ldr     r1, .L_strFilledNewArrayNotImpl
10900    bl      dvmThrowException
10901    b       common_exceptionThrown
10902
10903    .if     (!0)                 @ define in one or the other, not both
10904.L_strFilledNewArrayNotImpl:
10905    .word   .LstrFilledNewArrayNotImpl
10906.L_strInternalError:
10907    .word   .LstrInternalError
10908    .endif
10909
10910/* continuation for OP_FILLED_NEW_ARRAY_RANGE */
10911
10912    /*
10913     * On entry:
10914     *  r0 holds array class
10915     *  r10 holds AA or BA
10916     */
10917.LOP_FILLED_NEW_ARRAY_RANGE_continue:
10918    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
10919    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
10920    ldrb    rINST, [r3, #1]             @ rINST<- descriptor[1]
10921    .if     1
10922    mov     r1, r10                     @ r1<- AA (length)
10923    .else
10924    mov     r1, r10, lsr #4             @ r1<- B (length)
10925    .endif
10926    cmp     rINST, #'I'                 @ array of ints?
10927    cmpne   rINST, #'L'                 @ array of objects?
10928    cmpne   rINST, #'['                 @ array of arrays?
10929    mov     r9, r1                      @ save length in r9
10930    bne     .LOP_FILLED_NEW_ARRAY_RANGE_notimpl         @ no, not handled yet
10931    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
10932    cmp     r0, #0                      @ null return?
10933    beq     common_exceptionThrown      @ alloc failed, handle exception
10934
10935    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
10936    str     r0, [rGLUE, #offGlue_retval]      @ retval.l <- new array
10937    str     rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
10938    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
10939    subs    r9, r9, #1                  @ length--, check for neg
10940    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
10941    bmi     2f                          @ was zero, bail
10942
10943    @ copy values from registers into the array
10944    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
10945    .if     1
10946    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
109471:  ldr     r3, [r2], #4                @ r3<- *r2++
10948    subs    r9, r9, #1                  @ count--
10949    str     r3, [r0], #4                @ *contents++ = vX
10950    bpl     1b
10951    @ continue at 2
10952    .else
10953    cmp     r9, #4                      @ length was initially 5?
10954    and     r2, r10, #15                @ r2<- A
10955    bne     1f                          @ <= 4 args, branch
10956    GET_VREG(r3, r2)                    @ r3<- vA
10957    sub     r9, r9, #1                  @ count--
10958    str     r3, [r0, #16]               @ contents[4] = vA
109591:  and     r2, r1, #15                 @ r2<- F/E/D/C
10960    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
10961    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
10962    subs    r9, r9, #1                  @ count--
10963    str     r3, [r0], #4                @ *contents++ = vX
10964    bpl     1b
10965    @ continue at 2
10966    .endif
10967
109682:
10969    ldr     r0, [rGLUE, #offGlue_retval]     @ r0<- object
10970    ldr     r1, [rGLUE, #offGlue_retval+4]   @ r1<- type
10971    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
10972    GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
10973    cmp     r1, #'I'                         @ Is int array?
10974    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head
10975    GOTO_OPCODE(ip)                          @ execute it
10976
10977    /*
10978     * Throw an exception indicating that we have not implemented this
10979     * mode of filled-new-array.
10980     */
10981.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
10982    ldr     r0, .L_strInternalError
10983    ldr     r1, .L_strFilledNewArrayNotImpl
10984    bl      dvmThrowException
10985    b       common_exceptionThrown
10986
10987    .if     (!1)                 @ define in one or the other, not both
10988.L_strFilledNewArrayNotImpl:
10989    .word   .LstrFilledNewArrayNotImpl
10990.L_strInternalError:
10991    .word   .LstrInternalError
10992    .endif
10993
10994/* continuation for OP_CMPL_FLOAT */
10995.LOP_CMPL_FLOAT_finish:
10996    SET_VREG(r0, r9)                    @ vAA<- r0
10997    GOTO_OPCODE(ip)                     @ jump to next instruction
10998
10999/* continuation for OP_CMPG_FLOAT */
11000.LOP_CMPG_FLOAT_finish:
11001    SET_VREG(r0, r9)                    @ vAA<- r0
11002    GOTO_OPCODE(ip)                     @ jump to next instruction
11003
11004/* continuation for OP_CMPL_DOUBLE */
11005.LOP_CMPL_DOUBLE_finish:
11006    SET_VREG(r0, r9)                    @ vAA<- r0
11007    GOTO_OPCODE(ip)                     @ jump to next instruction
11008
11009/* continuation for OP_CMPG_DOUBLE */
11010.LOP_CMPG_DOUBLE_finish:
11011    SET_VREG(r0, r9)                    @ vAA<- r0
11012    GOTO_OPCODE(ip)                     @ jump to next instruction
11013
11014/* continuation for OP_CMP_LONG */
11015
11016.LOP_CMP_LONG_less:
11017    mvn     r1, #0                      @ r1<- -1
11018    @ Want to cond code the next mov so we can avoid branch, but don't see it;
11019    @ instead, we just replicate the tail end.
11020    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11021    SET_VREG(r1, r9)                    @ vAA<- r1
11022    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11023    GOTO_OPCODE(ip)                     @ jump to next instruction
11024
11025.LOP_CMP_LONG_greater:
11026    mov     r1, #1                      @ r1<- 1
11027    @ fall through to _finish
11028
11029.LOP_CMP_LONG_finish:
11030    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11031    SET_VREG(r1, r9)                    @ vAA<- r1
11032    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11033    GOTO_OPCODE(ip)                     @ jump to next instruction
11034
11035/* continuation for OP_AGET_WIDE */
11036
11037.LOP_AGET_WIDE_finish:
11038    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11039    ldrd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
11040    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
11041    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11042    stmia   r9, {r2-r3}                 @ vAA/vAA+1<- r2/r3
11043    GOTO_OPCODE(ip)                     @ jump to next instruction
11044
11045/* continuation for OP_APUT_WIDE */
11046
11047.LOP_APUT_WIDE_finish:
11048    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11049    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
11050    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11051    strd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
11052    GOTO_OPCODE(ip)                     @ jump to next instruction
11053
11054/* continuation for OP_APUT_OBJECT */
11055    /*
11056     * On entry:
11057     *  rINST = vBB (arrayObj)
11058     *  r9 = vAA (obj)
11059     *  r10 = offset into array (vBB + vCC * width)
11060     */
11061.LOP_APUT_OBJECT_finish:
11062    cmp     r9, #0                      @ storing null reference?
11063    beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
11064    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
11065    ldr     r1, [rINST, #offObject_clazz]  @ r1<- arrayObj->clazz
11066    bl      dvmCanPutArrayElement       @ test object type vs. array type
11067    cmp     r0, #0                      @ okay?
11068    beq     .LOP_APUT_OBJECT_throw           @ no
11069    mov     r1, rINST                   @ r1<- arrayObj
11070    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11071    ldr     r2, [rGLUE, #offGlue_cardTable]     @ get biased CT base
11072    add     r10, #offArrayObject_contents   @ r0<- pointer to slot
11073    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11074    str     r9, [r10]                   @ vBB[vCC]<- vAA
11075    strb    r2, [r2, r1, lsr #GC_CARD_SHIFT] @ mark card using object head
11076    GOTO_OPCODE(ip)                     @ jump to next instruction
11077.LOP_APUT_OBJECT_skip_check:
11078    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11079    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11080    str     r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
11081    GOTO_OPCODE(ip)                     @ jump to next instruction
11082.LOP_APUT_OBJECT_throw:
11083    @ The types don't match.  We need to throw an ArrayStoreException.
11084    ldr     r0, [r9, #offObject_clazz]
11085    ldr     r1, [rINST, #offObject_clazz]
11086    EXPORT_PC()
11087    bl      dvmThrowArrayStoreException
11088    b       common_exceptionThrown
11089
11090/* continuation for OP_IGET */
11091
11092    /*
11093     * Currently:
11094     *  r0 holds resolved field
11095     *  r9 holds object
11096     */
11097.LOP_IGET_finish:
11098    @bl      common_squeak0
11099    cmp     r9, #0                      @ check object for null
11100    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
11101    beq     common_errNullObject        @ object was null
11102    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
11103    @ no-op                             @ acquiring load
11104    mov     r2, rINST, lsr #8           @ r2<- A+
11105    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11106    and     r2, r2, #15                 @ r2<- A
11107    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11108    SET_VREG(r0, r2)                    @ fp[A]<- r0
11109    GOTO_OPCODE(ip)                     @ jump to next instruction
11110
11111/* continuation for OP_IGET_WIDE */
11112
11113    /*
11114     * Currently:
11115     *  r0 holds resolved field
11116     *  r9 holds object
11117     */
11118.LOP_IGET_WIDE_finish:
11119    cmp     r9, #0                      @ check object for null
11120    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
11121    beq     common_errNullObject        @ object was null
11122    .if     0
11123    add     r0, r9, r3                  @ r0<- address of field
11124    bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
11125    .else
11126    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
11127    .endif
11128    mov     r2, rINST, lsr #8           @ r2<- A+
11129    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11130    and     r2, r2, #15                 @ r2<- A
11131    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
11132    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11133    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
11134    GOTO_OPCODE(ip)                     @ jump to next instruction
11135
11136/* continuation for OP_IGET_OBJECT */
11137
11138    /*
11139     * Currently:
11140     *  r0 holds resolved field
11141     *  r9 holds object
11142     */
11143.LOP_IGET_OBJECT_finish:
11144    @bl      common_squeak0
11145    cmp     r9, #0                      @ check object for null
11146    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
11147    beq     common_errNullObject        @ object was null
11148    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
11149    @ no-op                             @ acquiring load
11150    mov     r2, rINST, lsr #8           @ r2<- A+
11151    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11152    and     r2, r2, #15                 @ r2<- A
11153    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11154    SET_VREG(r0, r2)                    @ fp[A]<- r0
11155    GOTO_OPCODE(ip)                     @ jump to next instruction
11156
11157/* continuation for OP_IGET_BOOLEAN */
11158
11159    /*
11160     * Currently:
11161     *  r0 holds resolved field
11162     *  r9 holds object
11163     */
11164.LOP_IGET_BOOLEAN_finish:
11165    @bl      common_squeak1
11166    cmp     r9, #0                      @ check object for null
11167    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
11168    beq     common_errNullObject        @ object was null
11169    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
11170    @ no-op                             @ acquiring load
11171    mov     r2, rINST, lsr #8           @ r2<- A+
11172    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11173    and     r2, r2, #15                 @ r2<- A
11174    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11175    SET_VREG(r0, r2)                    @ fp[A]<- r0
11176    GOTO_OPCODE(ip)                     @ jump to next instruction
11177
11178/* continuation for OP_IGET_BYTE */
11179
11180    /*
11181     * Currently:
11182     *  r0 holds resolved field
11183     *  r9 holds object
11184     */
11185.LOP_IGET_BYTE_finish:
11186    @bl      common_squeak2
11187    cmp     r9, #0                      @ check object for null
11188    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
11189    beq     common_errNullObject        @ object was null
11190    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
11191    @ no-op                             @ acquiring load
11192    mov     r2, rINST, lsr #8           @ r2<- A+
11193    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11194    and     r2, r2, #15                 @ r2<- A
11195    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11196    SET_VREG(r0, r2)                    @ fp[A]<- r0
11197    GOTO_OPCODE(ip)                     @ jump to next instruction
11198
11199/* continuation for OP_IGET_CHAR */
11200
11201    /*
11202     * Currently:
11203     *  r0 holds resolved field
11204     *  r9 holds object
11205     */
11206.LOP_IGET_CHAR_finish:
11207    @bl      common_squeak3
11208    cmp     r9, #0                      @ check object for null
11209    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
11210    beq     common_errNullObject        @ object was null
11211    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
11212    @ no-op                             @ acquiring load
11213    mov     r2, rINST, lsr #8           @ r2<- A+
11214    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11215    and     r2, r2, #15                 @ r2<- A
11216    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11217    SET_VREG(r0, r2)                    @ fp[A]<- r0
11218    GOTO_OPCODE(ip)                     @ jump to next instruction
11219
11220/* continuation for OP_IGET_SHORT */
11221
11222    /*
11223     * Currently:
11224     *  r0 holds resolved field
11225     *  r9 holds object
11226     */
11227.LOP_IGET_SHORT_finish:
11228    @bl      common_squeak4
11229    cmp     r9, #0                      @ check object for null
11230    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
11231    beq     common_errNullObject        @ object was null
11232    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
11233    @ no-op                             @ acquiring load
11234    mov     r2, rINST, lsr #8           @ r2<- A+
11235    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11236    and     r2, r2, #15                 @ r2<- A
11237    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11238    SET_VREG(r0, r2)                    @ fp[A]<- r0
11239    GOTO_OPCODE(ip)                     @ jump to next instruction
11240
11241/* continuation for OP_IPUT */
11242
11243    /*
11244     * Currently:
11245     *  r0 holds resolved field
11246     *  r9 holds object
11247     */
11248.LOP_IPUT_finish:
11249    @bl      common_squeak0
11250    mov     r1, rINST, lsr #8           @ r1<- A+
11251    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
11252    and     r1, r1, #15                 @ r1<- A
11253    cmp     r9, #0                      @ check object for null
11254    GET_VREG(r0, r1)                    @ r0<- fp[A]
11255    beq     common_errNullObject        @ object was null
11256    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11257    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11258    @ no-op                             @ releasing store
11259    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
11260    GOTO_OPCODE(ip)                     @ jump to next instruction
11261
11262/* continuation for OP_IPUT_WIDE */
11263
11264    /*
11265     * Currently:
11266     *  r0 holds resolved field
11267     *  r9 holds object
11268     */
11269.LOP_IPUT_WIDE_finish:
11270    mov     r2, rINST, lsr #8           @ r2<- A+
11271    cmp     r9, #0                      @ check object for null
11272    and     r2, r2, #15                 @ r2<- A
11273    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
11274    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
11275    beq     common_errNullObject        @ object was null
11276    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11277    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
11278    GET_INST_OPCODE(r10)                @ extract opcode from rINST
11279    .if     0
11280    add     r2, r9, r3                  @ r2<- target address
11281    bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
11282    .else
11283    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0/r1
11284    .endif
11285    GOTO_OPCODE(r10)                    @ jump to next instruction
11286
11287/* continuation for OP_IPUT_OBJECT */
11288
11289    /*
11290     * Currently:
11291     *  r0 holds resolved field
11292     *  r9 holds object
11293     */
11294.LOP_IPUT_OBJECT_finish:
11295    @bl      common_squeak0
11296    mov     r1, rINST, lsr #8           @ r1<- A+
11297    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
11298    and     r1, r1, #15                 @ r1<- A
11299    cmp     r9, #0                      @ check object for null
11300    GET_VREG(r0, r1)                    @ r0<- fp[A]
11301    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
11302    beq     common_errNullObject        @ object was null
11303    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11304    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11305    @ no-op                             @ releasing store
11306    str     r0, [r9, r3]                @ obj.field (32 bits)<- r0
11307    cmp     r0, #0                      @ stored a null reference?
11308    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
11309    GOTO_OPCODE(ip)                     @ jump to next instruction
11310
11311/* continuation for OP_IPUT_BOOLEAN */
11312
11313    /*
11314     * Currently:
11315     *  r0 holds resolved field
11316     *  r9 holds object
11317     */
11318.LOP_IPUT_BOOLEAN_finish:
11319    @bl      common_squeak1
11320    mov     r1, rINST, lsr #8           @ r1<- A+
11321    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
11322    and     r1, r1, #15                 @ r1<- A
11323    cmp     r9, #0                      @ check object for null
11324    GET_VREG(r0, r1)                    @ r0<- fp[A]
11325    beq     common_errNullObject        @ object was null
11326    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11327    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11328    @ no-op                             @ releasing store
11329    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
11330    GOTO_OPCODE(ip)                     @ jump to next instruction
11331
11332/* continuation for OP_IPUT_BYTE */
11333
11334    /*
11335     * Currently:
11336     *  r0 holds resolved field
11337     *  r9 holds object
11338     */
11339.LOP_IPUT_BYTE_finish:
11340    @bl      common_squeak2
11341    mov     r1, rINST, lsr #8           @ r1<- A+
11342    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
11343    and     r1, r1, #15                 @ r1<- A
11344    cmp     r9, #0                      @ check object for null
11345    GET_VREG(r0, r1)                    @ r0<- fp[A]
11346    beq     common_errNullObject        @ object was null
11347    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11348    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11349    @ no-op                             @ releasing store
11350    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
11351    GOTO_OPCODE(ip)                     @ jump to next instruction
11352
11353/* continuation for OP_IPUT_CHAR */
11354
11355    /*
11356     * Currently:
11357     *  r0 holds resolved field
11358     *  r9 holds object
11359     */
11360.LOP_IPUT_CHAR_finish:
11361    @bl      common_squeak3
11362    mov     r1, rINST, lsr #8           @ r1<- A+
11363    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
11364    and     r1, r1, #15                 @ r1<- A
11365    cmp     r9, #0                      @ check object for null
11366    GET_VREG(r0, r1)                    @ r0<- fp[A]
11367    beq     common_errNullObject        @ object was null
11368    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11369    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11370    @ no-op                             @ releasing store
11371    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
11372    GOTO_OPCODE(ip)                     @ jump to next instruction
11373
11374/* continuation for OP_IPUT_SHORT */
11375
11376    /*
11377     * Currently:
11378     *  r0 holds resolved field
11379     *  r9 holds object
11380     */
11381.LOP_IPUT_SHORT_finish:
11382    @bl      common_squeak4
11383    mov     r1, rINST, lsr #8           @ r1<- A+
11384    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
11385    and     r1, r1, #15                 @ r1<- A
11386    cmp     r9, #0                      @ check object for null
11387    GET_VREG(r0, r1)                    @ r0<- fp[A]
11388    beq     common_errNullObject        @ object was null
11389    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11390    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11391    @ no-op                             @ releasing store
11392    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
11393    GOTO_OPCODE(ip)                     @ jump to next instruction
11394
11395/* continuation for OP_SGET */
11396
11397    /*
11398     * Continuation if the field has not yet been resolved.
11399     *  r1: BBBB field ref
11400     */
11401.LOP_SGET_resolve:
11402    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
11403    EXPORT_PC()                         @ resolve() could throw, so export now
11404    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
11405    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
11406    cmp     r0, #0                      @ success?
11407    bne     .LOP_SGET_finish          @ yes, finish
11408    b       common_exceptionThrown      @ no, handle exception
11409
11410/* continuation for OP_SGET_WIDE */
11411
11412    /*
11413     * Continuation if the field has not yet been resolved.
11414     *  r1: BBBB field ref
11415     *
11416     * Returns StaticField pointer in r0.
11417     */
11418.LOP_SGET_WIDE_resolve:
11419    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
11420    EXPORT_PC()                         @ resolve() could throw, so export now
11421    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
11422    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
11423    cmp     r0, #0                      @ success?
11424    bne     .LOP_SGET_WIDE_finish          @ yes, finish
11425    b       common_exceptionThrown      @ no, handle exception
11426
11427/* continuation for OP_SGET_OBJECT */
11428
11429    /*
11430     * Continuation if the field has not yet been resolved.
11431     *  r1: BBBB field ref
11432     */
11433.LOP_SGET_OBJECT_resolve:
11434    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
11435    EXPORT_PC()                         @ resolve() could throw, so export now
11436    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
11437    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
11438    cmp     r0, #0                      @ success?
11439    bne     .LOP_SGET_OBJECT_finish          @ yes, finish
11440    b       common_exceptionThrown      @ no, handle exception
11441
11442/* continuation for OP_SGET_BOOLEAN */
11443
11444    /*
11445     * Continuation if the field has not yet been resolved.
11446     *  r1: BBBB field ref
11447     */
11448.LOP_SGET_BOOLEAN_resolve:
11449    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
11450    EXPORT_PC()                         @ resolve() could throw, so export now
11451    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
11452    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
11453    cmp     r0, #0                      @ success?
11454    bne     .LOP_SGET_BOOLEAN_finish          @ yes, finish
11455    b       common_exceptionThrown      @ no, handle exception
11456
11457/* continuation for OP_SGET_BYTE */
11458
11459    /*
11460     * Continuation if the field has not yet been resolved.
11461     *  r1: BBBB field ref
11462     */
11463.LOP_SGET_BYTE_resolve:
11464    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
11465    EXPORT_PC()                         @ resolve() could throw, so export now
11466    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
11467    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
11468    cmp     r0, #0                      @ success?
11469    bne     .LOP_SGET_BYTE_finish          @ yes, finish
11470    b       common_exceptionThrown      @ no, handle exception
11471
11472/* continuation for OP_SGET_CHAR */
11473
11474    /*
11475     * Continuation if the field has not yet been resolved.
11476     *  r1: BBBB field ref
11477     */
11478.LOP_SGET_CHAR_resolve:
11479    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
11480    EXPORT_PC()                         @ resolve() could throw, so export now
11481    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
11482    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
11483    cmp     r0, #0                      @ success?
11484    bne     .LOP_SGET_CHAR_finish          @ yes, finish
11485    b       common_exceptionThrown      @ no, handle exception
11486
11487/* continuation for OP_SGET_SHORT */
11488
11489    /*
11490     * Continuation if the field has not yet been resolved.
11491     *  r1: BBBB field ref
11492     */
11493.LOP_SGET_SHORT_resolve:
11494    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
11495    EXPORT_PC()                         @ resolve() could throw, so export now
11496    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
11497    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
11498    cmp     r0, #0                      @ success?
11499    bne     .LOP_SGET_SHORT_finish          @ yes, finish
11500    b       common_exceptionThrown      @ no, handle exception
11501
11502/* continuation for OP_SPUT */
11503
11504    /*
11505     * Continuation if the field has not yet been resolved.
11506     *  r1: BBBB field ref
11507     */
11508.LOP_SPUT_resolve:
11509    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
11510    EXPORT_PC()                         @ resolve() could throw, so export now
11511    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
11512    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
11513    cmp     r0, #0                      @ success?
11514    bne     .LOP_SPUT_finish          @ yes, finish
11515    b       common_exceptionThrown      @ no, handle exception
11516
11517/* continuation for OP_SPUT_WIDE */
11518
11519    /*
11520     * Continuation if the field has not yet been resolved.
11521     *  r1: BBBB field ref
11522     *  r9: &fp[AA]
11523     *
11524     * Returns StaticField pointer in r2.
11525     */
11526.LOP_SPUT_WIDE_resolve:
11527    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
11528    EXPORT_PC()                         @ resolve() could throw, so export now
11529    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
11530    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
11531    cmp     r0, #0                      @ success?
11532    mov     r2, r0                      @ copy to r2
11533    bne     .LOP_SPUT_WIDE_finish          @ yes, finish
11534    b       common_exceptionThrown      @ no, handle exception
11535
11536/* continuation for OP_SPUT_OBJECT */
11537.LOP_SPUT_OBJECT_finish:   @ field ptr in r0
11538    mov     r2, rINST, lsr #8           @ r2<- AA
11539    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11540    GET_VREG(r1, r2)                    @ r1<- fp[AA]
11541    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
11542    ldr     r9, [r0, #offField_clazz]   @ r9<- field->clazz
11543    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11544    @ no-op                             @ releasing store
11545    str     r1, [r0, #offStaticField_value]  @ field<- vAA
11546    cmp     r1, #0                      @ stored a null object?
11547    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card based on obj head
11548    GOTO_OPCODE(ip)                     @ jump to next instruction
11549
11550/* continuation for OP_SPUT_BOOLEAN */
11551
11552    /*
11553     * Continuation if the field has not yet been resolved.
11554     *  r1: BBBB field ref
11555     */
11556.LOP_SPUT_BOOLEAN_resolve:
11557    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
11558    EXPORT_PC()                         @ resolve() could throw, so export now
11559    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
11560    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
11561    cmp     r0, #0                      @ success?
11562    bne     .LOP_SPUT_BOOLEAN_finish          @ yes, finish
11563    b       common_exceptionThrown      @ no, handle exception
11564
11565/* continuation for OP_SPUT_BYTE */
11566
11567    /*
11568     * Continuation if the field has not yet been resolved.
11569     *  r1: BBBB field ref
11570     */
11571.LOP_SPUT_BYTE_resolve:
11572    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
11573    EXPORT_PC()                         @ resolve() could throw, so export now
11574    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
11575    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
11576    cmp     r0, #0                      @ success?
11577    bne     .LOP_SPUT_BYTE_finish          @ yes, finish
11578    b       common_exceptionThrown      @ no, handle exception
11579
11580/* continuation for OP_SPUT_CHAR */
11581
11582    /*
11583     * Continuation if the field has not yet been resolved.
11584     *  r1: BBBB field ref
11585     */
11586.LOP_SPUT_CHAR_resolve:
11587    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
11588    EXPORT_PC()                         @ resolve() could throw, so export now
11589    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
11590    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
11591    cmp     r0, #0                      @ success?
11592    bne     .LOP_SPUT_CHAR_finish          @ yes, finish
11593    b       common_exceptionThrown      @ no, handle exception
11594
11595/* continuation for OP_SPUT_SHORT */
11596
11597    /*
11598     * Continuation if the field has not yet been resolved.
11599     *  r1: BBBB field ref
11600     */
11601.LOP_SPUT_SHORT_resolve:
11602    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
11603    EXPORT_PC()                         @ resolve() could throw, so export now
11604    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
11605    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
11606    cmp     r0, #0                      @ success?
11607    bne     .LOP_SPUT_SHORT_finish          @ yes, finish
11608    b       common_exceptionThrown      @ no, handle exception
11609
11610/* continuation for OP_INVOKE_VIRTUAL */
11611
11612    /*
11613     * At this point:
11614     *  r0 = resolved base method
11615     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
11616     */
11617.LOP_INVOKE_VIRTUAL_continue:
11618    GET_VREG(r1, r10)                   @ r1<- "this" ptr
11619    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
11620    cmp     r1, #0                      @ is "this" null?
11621    beq     common_errNullObject        @ null "this", throw exception
11622    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
11623    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
11624    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
11625    bl      common_invokeMethodNoRange @ continue on
11626
11627/* continuation for OP_INVOKE_SUPER */
11628
11629    /*
11630     * At this point:
11631     *  r0 = resolved base method
11632     *  r9 = method->clazz
11633     */
11634.LOP_INVOKE_SUPER_continue:
11635    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
11636    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
11637    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
11638    EXPORT_PC()                         @ must export for invoke
11639    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
11640    bcs     .LOP_INVOKE_SUPER_nsm             @ method not present in superclass
11641    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
11642    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
11643    bl      common_invokeMethodNoRange @ continue on
11644
11645.LOP_INVOKE_SUPER_resolve:
11646    mov     r0, r9                      @ r0<- method->clazz
11647    mov     r2, #METHOD_VIRTUAL         @ resolver method type
11648    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
11649    cmp     r0, #0                      @ got null?
11650    bne     .LOP_INVOKE_SUPER_continue        @ no, continue
11651    b       common_exceptionThrown      @ yes, handle exception
11652
11653    /*
11654     * Throw a NoSuchMethodError with the method name as the message.
11655     *  r0 = resolved base method
11656     */
11657.LOP_INVOKE_SUPER_nsm:
11658    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
11659    b       common_errNoSuchMethod
11660
11661/* continuation for OP_INVOKE_DIRECT */
11662
11663    /*
11664     * On entry:
11665     *  r1 = reference (BBBB or CCCC)
11666     *  r10 = "this" register
11667     */
11668.LOP_INVOKE_DIRECT_resolve:
11669    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
11670    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
11671    mov     r2, #METHOD_DIRECT          @ resolver method type
11672    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
11673    cmp     r0, #0                      @ got null?
11674    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
11675    bne     .LOP_INVOKE_DIRECT_finish          @ no, continue
11676    b       common_exceptionThrown      @ yes, handle exception
11677
11678/* continuation for OP_INVOKE_VIRTUAL_RANGE */
11679
11680    /*
11681     * At this point:
11682     *  r0 = resolved base method
11683     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
11684     */
11685.LOP_INVOKE_VIRTUAL_RANGE_continue:
11686    GET_VREG(r1, r10)                   @ r1<- "this" ptr
11687    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
11688    cmp     r1, #0                      @ is "this" null?
11689    beq     common_errNullObject        @ null "this", throw exception
11690    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
11691    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
11692    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
11693    bl      common_invokeMethodRange @ continue on
11694
11695/* continuation for OP_INVOKE_SUPER_RANGE */
11696
11697    /*
11698     * At this point:
11699     *  r0 = resolved base method
11700     *  r9 = method->clazz
11701     */
11702.LOP_INVOKE_SUPER_RANGE_continue:
11703    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
11704    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
11705    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
11706    EXPORT_PC()                         @ must export for invoke
11707    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
11708    bcs     .LOP_INVOKE_SUPER_RANGE_nsm             @ method not present in superclass
11709    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
11710    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
11711    bl      common_invokeMethodRange @ continue on
11712
11713.LOP_INVOKE_SUPER_RANGE_resolve:
11714    mov     r0, r9                      @ r0<- method->clazz
11715    mov     r2, #METHOD_VIRTUAL         @ resolver method type
11716    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
11717    cmp     r0, #0                      @ got null?
11718    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ no, continue
11719    b       common_exceptionThrown      @ yes, handle exception
11720
11721    /*
11722     * Throw a NoSuchMethodError with the method name as the message.
11723     *  r0 = resolved base method
11724     */
11725.LOP_INVOKE_SUPER_RANGE_nsm:
11726    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
11727    b       common_errNoSuchMethod
11728
11729/* continuation for OP_INVOKE_DIRECT_RANGE */
11730
11731    /*
11732     * On entry:
11733     *  r1 = reference (BBBB or CCCC)
11734     *  r10 = "this" register
11735     */
11736.LOP_INVOKE_DIRECT_RANGE_resolve:
11737    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
11738    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
11739    mov     r2, #METHOD_DIRECT          @ resolver method type
11740    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
11741    cmp     r0, #0                      @ got null?
11742    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
11743    bne     .LOP_INVOKE_DIRECT_RANGE_finish          @ no, continue
11744    b       common_exceptionThrown      @ yes, handle exception
11745
11746/* continuation for OP_FLOAT_TO_LONG */
11747/*
11748 * Convert the float in r0 to a long in r0/r1.
11749 *
11750 * We have to clip values to long min/max per the specification.  The
11751 * expected common case is a "reasonable" value that converts directly
11752 * to modest integer.  The EABI convert function isn't doing this for us.
11753 */
11754f2l_doconv:
11755    stmfd   sp!, {r4, lr}
11756    mov     r1, #0x5f000000             @ (float)maxlong
11757    mov     r4, r0
11758    bl      __aeabi_fcmpge              @ is arg >= maxlong?
11759    cmp     r0, #0                      @ nonzero == yes
11760    mvnne   r0, #0                      @ return maxlong (7fffffff)
11761    mvnne   r1, #0x80000000
11762    ldmnefd sp!, {r4, pc}
11763
11764    mov     r0, r4                      @ recover arg
11765    mov     r1, #0xdf000000             @ (float)minlong
11766    bl      __aeabi_fcmple              @ is arg <= minlong?
11767    cmp     r0, #0                      @ nonzero == yes
11768    movne   r0, #0                      @ return minlong (80000000)
11769    movne   r1, #0x80000000
11770    ldmnefd sp!, {r4, pc}
11771
11772    mov     r0, r4                      @ recover arg
11773    mov     r1, r4
11774    bl      __aeabi_fcmpeq              @ is arg == self?
11775    cmp     r0, #0                      @ zero == no
11776    moveq   r1, #0                      @ return zero for NaN
11777    ldmeqfd sp!, {r4, pc}
11778
11779    mov     r0, r4                      @ recover arg
11780    bl      __aeabi_f2lz                @ convert float to long
11781    ldmfd   sp!, {r4, pc}
11782
11783/* continuation for OP_DOUBLE_TO_LONG */
11784/*
11785 * Convert the double in r0/r1 to a long in r0/r1.
11786 *
11787 * We have to clip values to long min/max per the specification.  The
11788 * expected common case is a "reasonable" value that converts directly
11789 * to modest integer.  The EABI convert function isn't doing this for us.
11790 */
11791d2l_doconv:
11792    stmfd   sp!, {r4, r5, lr}           @ save regs
11793    mov     r3, #0x43000000             @ maxlong, as a double (high word)
11794    add     r3, #0x00e00000             @  0x43e00000
11795    mov     r2, #0                      @ maxlong, as a double (low word)
11796    sub     sp, sp, #4                  @ align for EABI
11797    mov     r4, r0                      @ save a copy of r0
11798    mov     r5, r1                      @  and r1
11799    bl      __aeabi_dcmpge              @ is arg >= maxlong?
11800    cmp     r0, #0                      @ nonzero == yes
11801    mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
11802    mvnne   r1, #0x80000000
11803    bne     1f
11804
11805    mov     r0, r4                      @ recover arg
11806    mov     r1, r5
11807    mov     r3, #0xc3000000             @ minlong, as a double (high word)
11808    add     r3, #0x00e00000             @  0xc3e00000
11809    mov     r2, #0                      @ minlong, as a double (low word)
11810    bl      __aeabi_dcmple              @ is arg <= minlong?
11811    cmp     r0, #0                      @ nonzero == yes
11812    movne   r0, #0                      @ return minlong (8000000000000000)
11813    movne   r1, #0x80000000
11814    bne     1f
11815
11816    mov     r0, r4                      @ recover arg
11817    mov     r1, r5
11818    mov     r2, r4                      @ compare against self
11819    mov     r3, r5
11820    bl      __aeabi_dcmpeq              @ is arg == self?
11821    cmp     r0, #0                      @ zero == no
11822    moveq   r1, #0                      @ return zero for NaN
11823    beq     1f
11824
11825    mov     r0, r4                      @ recover arg
11826    mov     r1, r5
11827    bl      __aeabi_d2lz                @ convert double to long
11828
118291:
11830    add     sp, sp, #4
11831    ldmfd   sp!, {r4, r5, pc}
11832
11833/* continuation for OP_MUL_LONG */
11834
11835.LOP_MUL_LONG_finish:
11836    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11837    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
11838    GOTO_OPCODE(ip)                     @ jump to next instruction
11839
11840/* continuation for OP_SHL_LONG */
11841
11842.LOP_SHL_LONG_finish:
11843    mov     r0, r0, asl r2              @  r0<- r0 << r2
11844    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11845    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
11846    GOTO_OPCODE(ip)                     @ jump to next instruction
11847
11848/* continuation for OP_SHR_LONG */
11849
11850.LOP_SHR_LONG_finish:
11851    mov     r1, r1, asr r2              @  r1<- r1 >> r2
11852    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11853    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
11854    GOTO_OPCODE(ip)                     @ jump to next instruction
11855
11856/* continuation for OP_USHR_LONG */
11857
11858.LOP_USHR_LONG_finish:
11859    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
11860    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11861    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
11862    GOTO_OPCODE(ip)                     @ jump to next instruction
11863
11864/* continuation for OP_SHL_LONG_2ADDR */
11865
11866.LOP_SHL_LONG_2ADDR_finish:
11867    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11868    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
11869    GOTO_OPCODE(ip)                     @ jump to next instruction
11870
11871/* continuation for OP_SHR_LONG_2ADDR */
11872
11873.LOP_SHR_LONG_2ADDR_finish:
11874    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11875    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
11876    GOTO_OPCODE(ip)                     @ jump to next instruction
11877
11878/* continuation for OP_USHR_LONG_2ADDR */
11879
11880.LOP_USHR_LONG_2ADDR_finish:
11881    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11882    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
11883    GOTO_OPCODE(ip)                     @ jump to next instruction
11884
11885/* continuation for OP_IGET_VOLATILE */
11886
11887    /*
11888     * Currently:
11889     *  r0 holds resolved field
11890     *  r9 holds object
11891     */
11892.LOP_IGET_VOLATILE_finish:
11893    @bl      common_squeak0
11894    cmp     r9, #0                      @ check object for null
11895    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
11896    beq     common_errNullObject        @ object was null
11897    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
11898    SMP_DMB                            @ acquiring load
11899    mov     r2, rINST, lsr #8           @ r2<- A+
11900    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11901    and     r2, r2, #15                 @ r2<- A
11902    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11903    SET_VREG(r0, r2)                    @ fp[A]<- r0
11904    GOTO_OPCODE(ip)                     @ jump to next instruction
11905
11906/* continuation for OP_IPUT_VOLATILE */
11907
11908    /*
11909     * Currently:
11910     *  r0 holds resolved field
11911     *  r9 holds object
11912     */
11913.LOP_IPUT_VOLATILE_finish:
11914    @bl      common_squeak0
11915    mov     r1, rINST, lsr #8           @ r1<- A+
11916    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
11917    and     r1, r1, #15                 @ r1<- A
11918    cmp     r9, #0                      @ check object for null
11919    GET_VREG(r0, r1)                    @ r0<- fp[A]
11920    beq     common_errNullObject        @ object was null
11921    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11922    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11923    SMP_DMB                            @ releasing store
11924    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
11925    GOTO_OPCODE(ip)                     @ jump to next instruction
11926
11927/* continuation for OP_SGET_VOLATILE */
11928
11929    /*
11930     * Continuation if the field has not yet been resolved.
11931     *  r1: BBBB field ref
11932     */
11933.LOP_SGET_VOLATILE_resolve:
11934    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
11935    EXPORT_PC()                         @ resolve() could throw, so export now
11936    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
11937    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
11938    cmp     r0, #0                      @ success?
11939    bne     .LOP_SGET_VOLATILE_finish          @ yes, finish
11940    b       common_exceptionThrown      @ no, handle exception
11941
11942/* continuation for OP_SPUT_VOLATILE */
11943
11944    /*
11945     * Continuation if the field has not yet been resolved.
11946     *  r1: BBBB field ref
11947     */
11948.LOP_SPUT_VOLATILE_resolve:
11949    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
11950    EXPORT_PC()                         @ resolve() could throw, so export now
11951    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
11952    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
11953    cmp     r0, #0                      @ success?
11954    bne     .LOP_SPUT_VOLATILE_finish          @ yes, finish
11955    b       common_exceptionThrown      @ no, handle exception
11956
11957/* continuation for OP_IGET_OBJECT_VOLATILE */
11958
11959    /*
11960     * Currently:
11961     *  r0 holds resolved field
11962     *  r9 holds object
11963     */
11964.LOP_IGET_OBJECT_VOLATILE_finish:
11965    @bl      common_squeak0
11966    cmp     r9, #0                      @ check object for null
11967    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
11968    beq     common_errNullObject        @ object was null
11969    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
11970    SMP_DMB                            @ acquiring load
11971    mov     r2, rINST, lsr #8           @ r2<- A+
11972    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11973    and     r2, r2, #15                 @ r2<- A
11974    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11975    SET_VREG(r0, r2)                    @ fp[A]<- r0
11976    GOTO_OPCODE(ip)                     @ jump to next instruction
11977
11978/* continuation for OP_IGET_WIDE_VOLATILE */
11979
11980    /*
11981     * Currently:
11982     *  r0 holds resolved field
11983     *  r9 holds object
11984     */
11985.LOP_IGET_WIDE_VOLATILE_finish:
11986    cmp     r9, #0                      @ check object for null
11987    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
11988    beq     common_errNullObject        @ object was null
11989    .if     1
11990    add     r0, r9, r3                  @ r0<- address of field
11991    bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
11992    .else
11993    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
11994    .endif
11995    mov     r2, rINST, lsr #8           @ r2<- A+
11996    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11997    and     r2, r2, #15                 @ r2<- A
11998    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
11999    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12000    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
12001    GOTO_OPCODE(ip)                     @ jump to next instruction
12002
12003/* continuation for OP_IPUT_WIDE_VOLATILE */
12004
12005    /*
12006     * Currently:
12007     *  r0 holds resolved field
12008     *  r9 holds object
12009     */
12010.LOP_IPUT_WIDE_VOLATILE_finish:
12011    mov     r2, rINST, lsr #8           @ r2<- A+
12012    cmp     r9, #0                      @ check object for null
12013    and     r2, r2, #15                 @ r2<- A
12014    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
12015    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
12016    beq     common_errNullObject        @ object was null
12017    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
12018    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
12019    GET_INST_OPCODE(r10)                @ extract opcode from rINST
12020    .if     1
12021    add     r2, r9, r3                  @ r2<- target address
12022    bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
12023    .else
12024    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0/r1
12025    .endif
12026    GOTO_OPCODE(r10)                    @ jump to next instruction
12027
12028/* continuation for OP_SGET_WIDE_VOLATILE */
12029
12030    /*
12031     * Continuation if the field has not yet been resolved.
12032     *  r1: BBBB field ref
12033     *
12034     * Returns StaticField pointer in r0.
12035     */
12036.LOP_SGET_WIDE_VOLATILE_resolve:
12037    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
12038    EXPORT_PC()                         @ resolve() could throw, so export now
12039    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
12040    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
12041    cmp     r0, #0                      @ success?
12042    bne     .LOP_SGET_WIDE_VOLATILE_finish          @ yes, finish
12043    b       common_exceptionThrown      @ no, handle exception
12044
12045/* continuation for OP_SPUT_WIDE_VOLATILE */
12046
12047    /*
12048     * Continuation if the field has not yet been resolved.
12049     *  r1: BBBB field ref
12050     *  r9: &fp[AA]
12051     *
12052     * Returns StaticField pointer in r2.
12053     */
12054.LOP_SPUT_WIDE_VOLATILE_resolve:
12055    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
12056    EXPORT_PC()                         @ resolve() could throw, so export now
12057    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
12058    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
12059    cmp     r0, #0                      @ success?
12060    mov     r2, r0                      @ copy to r2
12061    bne     .LOP_SPUT_WIDE_VOLATILE_finish          @ yes, finish
12062    b       common_exceptionThrown      @ no, handle exception
12063
12064/* continuation for OP_EXECUTE_INLINE */
12065
12066    /*
12067     * Extract args, call function.
12068     *  r0 = #of args (0-4)
12069     *  r10 = call index
12070     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
12071     *
12072     * Other ideas:
12073     * - Use a jump table from the main piece to jump directly into the
12074     *   AND/LDR pairs.  Costs a data load, saves a branch.
12075     * - Have five separate pieces that do the loading, so we can work the
12076     *   interleave a little better.  Increases code size.
12077     */
12078.LOP_EXECUTE_INLINE_continue:
12079    rsb     r0, r0, #4                  @ r0<- 4-r0
12080    FETCH(r9, 2)                        @ r9<- FEDC
12081    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
12082    bl      common_abort                @ (skipped due to ARM prefetch)
120834:  and     ip, r9, #0xf000             @ isolate F
12084    ldr     r3, [rFP, ip, lsr #10]      @ r3<- vF (shift right 12, left 2)
120853:  and     ip, r9, #0x0f00             @ isolate E
12086    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vE
120872:  and     ip, r9, #0x00f0             @ isolate D
12088    ldr     r1, [rFP, ip, lsr #2]       @ r1<- vD
120891:  and     ip, r9, #0x000f             @ isolate C
12090    ldr     r0, [rFP, ip, lsl #2]       @ r0<- vC
120910:
12092    ldr     r9, .LOP_EXECUTE_INLINE_table       @ table of InlineOperation
12093    ldr     pc, [r9, r10, lsl #4]       @ sizeof=16, "func" is first entry
12094    @ (not reached)
12095
12096.LOP_EXECUTE_INLINE_table:
12097    .word   gDvmInlineOpsTable
12098
12099/* continuation for OP_EXECUTE_INLINE_RANGE */
12100
12101    /*
12102     * Extract args, call function.
12103     *  r0 = #of args (0-4)
12104     *  r10 = call index
12105     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
12106     */
12107.LOP_EXECUTE_INLINE_RANGE_continue:
12108    rsb     r0, r0, #4                  @ r0<- 4-r0
12109    FETCH(r9, 2)                        @ r9<- CCCC
12110    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
12111    bl      common_abort                @ (skipped due to ARM prefetch)
121124:  add     ip, r9, #3                  @ base+3
12113    GET_VREG(r3, ip)                    @ r3<- vBase[3]
121143:  add     ip, r9, #2                  @ base+2
12115    GET_VREG(r2, ip)                    @ r2<- vBase[2]
121162:  add     ip, r9, #1                  @ base+1
12117    GET_VREG(r1, ip)                    @ r1<- vBase[1]
121181:  add     ip, r9, #0                  @ (nop)
12119    GET_VREG(r0, ip)                    @ r0<- vBase[0]
121200:
12121    ldr     r9, .LOP_EXECUTE_INLINE_RANGE_table       @ table of InlineOperation
12122    ldr     pc, [r9, r10, lsl #4]       @ sizeof=16, "func" is first entry
12123    @ (not reached)
12124
12125.LOP_EXECUTE_INLINE_RANGE_table:
12126    .word   gDvmInlineOpsTable
12127
12128/* continuation for OP_IPUT_OBJECT_VOLATILE */
12129
12130    /*
12131     * Currently:
12132     *  r0 holds resolved field
12133     *  r9 holds object
12134     */
12135.LOP_IPUT_OBJECT_VOLATILE_finish:
12136    @bl      common_squeak0
12137    mov     r1, rINST, lsr #8           @ r1<- A+
12138    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
12139    and     r1, r1, #15                 @ r1<- A
12140    cmp     r9, #0                      @ check object for null
12141    GET_VREG(r0, r1)                    @ r0<- fp[A]
12142    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
12143    beq     common_errNullObject        @ object was null
12144    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
12145    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12146    SMP_DMB                            @ releasing store
12147    str     r0, [r9, r3]                @ obj.field (32 bits)<- r0
12148    cmp     r0, #0                      @ stored a null reference?
12149    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
12150    GOTO_OPCODE(ip)                     @ jump to next instruction
12151
12152/* continuation for OP_SGET_OBJECT_VOLATILE */
12153
12154    /*
12155     * Continuation if the field has not yet been resolved.
12156     *  r1: BBBB field ref
12157     */
12158.LOP_SGET_OBJECT_VOLATILE_resolve:
12159    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
12160    EXPORT_PC()                         @ resolve() could throw, so export now
12161    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
12162    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
12163    cmp     r0, #0                      @ success?
12164    bne     .LOP_SGET_OBJECT_VOLATILE_finish          @ yes, finish
12165    b       common_exceptionThrown      @ no, handle exception
12166
12167/* continuation for OP_SPUT_OBJECT_VOLATILE */
12168.LOP_SPUT_OBJECT_VOLATILE_finish:   @ field ptr in r0
12169    mov     r2, rINST, lsr #8           @ r2<- AA
12170    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
12171    GET_VREG(r1, r2)                    @ r1<- fp[AA]
12172    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
12173    ldr     r9, [r0, #offField_clazz]   @ r9<- field->clazz
12174    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12175    SMP_DMB                            @ releasing store
12176    str     r1, [r0, #offStaticField_value]  @ field<- vAA
12177    cmp     r1, #0                      @ stored a null object?
12178    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card based on obj head
12179    GOTO_OPCODE(ip)                     @ jump to next instruction
12180
12181/* continuation for OP_CONST_CLASS_JUMBO */
12182
12183    /*
12184     * Continuation if the Class has not yet been resolved.
12185     *  r1: AAAAAAAA (Class ref)
12186     *  r9: target register
12187     */
12188.LOP_CONST_CLASS_JUMBO_resolve:
12189    EXPORT_PC()
12190    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
12191    mov     r2, #1                      @ r2<- true
12192    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
12193    bl      dvmResolveClass             @ r0<- Class reference
12194    cmp     r0, #0                      @ failed?
12195    beq     common_exceptionThrown      @ yup, handle the exception
12196    FETCH_ADVANCE_INST(4)               @ advance rPC, load rINST
12197    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12198    SET_VREG(r0, r9)                    @ vBBBB<- r0
12199    GOTO_OPCODE(ip)                     @ jump to next instruction
12200
12201/* continuation for OP_CHECK_CAST_JUMBO */
12202
12203    /*
12204     * Trivial test failed, need to perform full check.  This is common.
12205     *  r0 holds obj->clazz
12206     *  r1 holds desired class resolved from AAAAAAAA
12207     *  r9 holds object
12208     */
12209.LOP_CHECK_CAST_JUMBO_fullcheck:
12210    mov     r10, r1                     @ avoid ClassObject getting clobbered
12211    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
12212    cmp     r0, #0                      @ failed?
12213    bne     .LOP_CHECK_CAST_JUMBO_okay            @ no, success
12214
12215    @ A cast has failed.  We need to throw a ClassCastException.
12216    EXPORT_PC()                         @ about to throw
12217    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz (actual class)
12218    mov     r1, r10                     @ r1<- desired class
12219    bl      dvmThrowClassCastException
12220    b       common_exceptionThrown
12221
12222    /*
12223     * Advance PC and get the next opcode.
12224     */
12225.LOP_CHECK_CAST_JUMBO_okay:
12226    FETCH_ADVANCE_INST(4)               @ advance rPC, load rINST
12227    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12228    GOTO_OPCODE(ip)                     @ jump to next instruction
12229
12230    /*
12231     * Resolution required.  This is the least-likely path.
12232     *
12233     *  r2 holds AAAAAAAA
12234     *  r9 holds object
12235     */
12236.LOP_CHECK_CAST_JUMBO_resolve:
12237    EXPORT_PC()                         @ resolve() could throw
12238    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
12239    mov     r1, r2                      @ r1<- AAAAAAAA
12240    mov     r2, #0                      @ r2<- false
12241    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
12242    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
12243    cmp     r0, #0                      @ got null?
12244    beq     common_exceptionThrown      @ yes, handle exception
12245    mov     r1, r0                      @ r1<- class resolved from AAAAAAAA
12246    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
12247    b       .LOP_CHECK_CAST_JUMBO_resolved        @ pick up where we left off
12248
12249/* continuation for OP_INSTANCE_OF_JUMBO */
12250
12251    /*
12252     * Class resolved, determine type of check necessary.  This is common.
12253     *  r0 holds obj->clazz
12254     *  r1 holds class resolved from AAAAAAAA
12255     *  r9 holds BBBB
12256     */
12257.LOP_INSTANCE_OF_JUMBO_resolved:
12258    cmp     r0, r1                      @ same class (trivial success)?
12259    beq     .LOP_INSTANCE_OF_JUMBO_trivial         @ yes, trivial finish
12260    @ fall through to OP_INSTANCE_OF_JUMBO_fullcheck
12261
12262    /*
12263     * Trivial test failed, need to perform full check.  This is common.
12264     *  r0 holds obj->clazz
12265     *  r1 holds class resolved from AAAAAAAA
12266     *  r9 holds BBBB
12267     */
12268.LOP_INSTANCE_OF_JUMBO_fullcheck:
12269    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
12270    @ fall through to OP_INSTANCE_OF_JUMBO_store
12271
12272    /*
12273     * r0 holds boolean result
12274     * r9 holds BBBB
12275     */
12276.LOP_INSTANCE_OF_JUMBO_store:
12277    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
12278    SET_VREG(r0, r9)                    @ vBBBB<- r0
12279    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12280    GOTO_OPCODE(ip)                     @ jump to next instruction
12281
12282    /*
12283     * Trivial test succeeded, save and bail.
12284     *  r9 holds BBBB
12285     */
12286.LOP_INSTANCE_OF_JUMBO_trivial:
12287    mov     r0, #1                      @ indicate success
12288    @ could b OP_INSTANCE_OF_JUMBO_store, but copying is faster and cheaper
12289    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
12290    SET_VREG(r0, r9)                    @ vBBBB<- r0
12291    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12292    GOTO_OPCODE(ip)                     @ jump to next instruction
12293
12294    /*
12295     * Resolution required.  This is the least-likely path.
12296     *
12297     *  r3 holds AAAAAAAA
12298     *  r9 holds BBBB
12299     */
12300
12301.LOP_INSTANCE_OF_JUMBO_resolve:
12302    EXPORT_PC()                         @ resolve() could throw
12303    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
12304    mov     r1, r3                      @ r1<- AAAAAAAA
12305    mov     r2, #1                      @ r2<- true
12306    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
12307    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
12308    cmp     r0, #0                      @ got null?
12309    beq     common_exceptionThrown      @ yes, handle exception
12310    FETCH(r3, 4)                        @ r3<- vCCCC
12311    mov     r1, r0                      @ r1<- class resolved from AAAAAAAA
12312    GET_VREG(r0, r3)                    @ r0<- vCCCC (object)
12313    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
12314    b       .LOP_INSTANCE_OF_JUMBO_resolved        @ pick up where we left off
12315
12316/* continuation for OP_NEW_INSTANCE_JUMBO */
12317
12318    .balign 32                          @ minimize cache lines
12319.LOP_NEW_INSTANCE_JUMBO_finish: @ r0=new object
12320    FETCH(r3, 3)                        @ r3<- BBBB
12321    cmp     r0, #0                      @ failed?
12322    beq     common_exceptionThrown      @ yes, handle the exception
12323    FETCH_ADVANCE_INST(4)               @ advance rPC, load rINST
12324    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12325    SET_VREG(r0, r3)                    @ vBBBB<- r0
12326    GOTO_OPCODE(ip)                     @ jump to next instruction
12327
12328    /*
12329     * Class initialization required.
12330     *
12331     *  r0 holds class object
12332     */
12333.LOP_NEW_INSTANCE_JUMBO_needinit:
12334    mov     r9, r0                      @ save r0
12335    bl      dvmInitClass                @ initialize class
12336    cmp     r0, #0                      @ check boolean result
12337    mov     r0, r9                      @ restore r0
12338    bne     .LOP_NEW_INSTANCE_JUMBO_initialized     @ success, continue
12339    b       common_exceptionThrown      @ failed, deal with init exception
12340
12341    /*
12342     * Resolution required.  This is the least-likely path.
12343     *
12344     *  r1 holds AAAAAAAA
12345     */
12346.LOP_NEW_INSTANCE_JUMBO_resolve:
12347    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
12348    mov     r2, #0                      @ r2<- false
12349    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
12350    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
12351    cmp     r0, #0                      @ got null?
12352    bne     .LOP_NEW_INSTANCE_JUMBO_resolved        @ no, continue
12353    b       common_exceptionThrown      @ yes, handle exception
12354
12355/* continuation for OP_NEW_ARRAY_JUMBO */
12356
12357
12358    /*
12359     * Resolve class.  (This is an uncommon case.)
12360     *
12361     *  r1 holds array length
12362     *  r2 holds class ref AAAAAAAA
12363     */
12364.LOP_NEW_ARRAY_JUMBO_resolve:
12365    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
12366    mov     r9, r1                      @ r9<- length (save)
12367    mov     r1, r2                      @ r1<- AAAAAAAA
12368    mov     r2, #0                      @ r2<- false
12369    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
12370    bl      dvmResolveClass             @ r0<- call(clazz, ref)
12371    cmp     r0, #0                      @ got null?
12372    mov     r1, r9                      @ r1<- length (restore)
12373    beq     common_exceptionThrown      @ yes, handle exception
12374    @ fall through to OP_NEW_ARRAY_JUMBO_finish
12375
12376    /*
12377     * Finish allocation.
12378     *
12379     *  r0 holds class
12380     *  r1 holds array length
12381     */
12382.LOP_NEW_ARRAY_JUMBO_finish:
12383    mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
12384    bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
12385    cmp     r0, #0                      @ failed?
12386    FETCH(r2, 3)                        @ r2<- vBBBB
12387    beq     common_exceptionThrown      @ yes, handle the exception
12388    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
12389    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12390    SET_VREG(r0, r2)                    @ vBBBB<- r0
12391    GOTO_OPCODE(ip)                     @ jump to next instruction
12392
12393/* continuation for OP_FILLED_NEW_ARRAY_JUMBO */
12394
12395    /*
12396     * On entry:
12397     *  r0 holds array class
12398     */
12399.LOP_FILLED_NEW_ARRAY_JUMBO_continue:
12400    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
12401    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
12402    ldrb    rINST, [r3, #1]             @ rINST<- descriptor[1]
12403    FETCH(r1, 3)                        @ r1<- BBBB (length)
12404    cmp     rINST, #'I'                 @ array of ints?
12405    cmpne   rINST, #'L'                 @ array of objects?
12406    cmpne   rINST, #'['                 @ array of arrays?
12407    mov     r9, r1                      @ save length in r9
12408    bne     .LOP_FILLED_NEW_ARRAY_JUMBO_notimpl         @ no, not handled yet
12409    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
12410    cmp     r0, #0                      @ null return?
12411    beq     common_exceptionThrown      @ alloc failed, handle exception
12412
12413    FETCH(r1, 4)                        @ r1<- CCCC
12414    str     r0, [rGLUE, #offGlue_retval]      @ retval.l <- new array
12415    str     rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
12416    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
12417    subs    r9, r9, #1                  @ length--, check for neg
12418    FETCH_ADVANCE_INST(5)               @ advance to next instr, load rINST
12419    bmi     2f                          @ was zero, bail
12420
12421    @ copy values from registers into the array
12422    @ r0=array, r1=CCCC, r9=BBBB (length)
12423    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
124241:  ldr     r3, [r2], #4                @ r3<- *r2++
12425    subs    r9, r9, #1                  @ count--
12426    str     r3, [r0], #4                @ *contents++ = vX
12427    bpl     1b
12428
124292:  ldr     r0, [rGLUE, #offGlue_retval]     @ r0<- object
12430    ldr     r1, [rGLUE, #offGlue_retval+4]   @ r1<- type
12431    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
12432    GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
12433    cmp     r1, #'I'                         @ Is int array?
12434    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head
12435    GOTO_OPCODE(ip)                          @ execute it
12436
12437    /*
12438     * Throw an exception indicating that we have not implemented this
12439     * mode of filled-new-array.
12440     */
12441.LOP_FILLED_NEW_ARRAY_JUMBO_notimpl:
12442    ldr     r0, .L_strInternalError
12443    ldr     r1, .L_strFilledNewArrayNotImpl
12444    bl      dvmThrowException
12445    b       common_exceptionThrown
12446
12447/* continuation for OP_IGET_JUMBO */
12448
12449    /*
12450     * Currently:
12451     *  r0 holds resolved field
12452     *  r9 holds object
12453     */
12454.LOP_IGET_JUMBO_resolved:
12455    cmp     r0, #0                      @ resolution unsuccessful?
12456    beq     common_exceptionThrown      @ yes, throw exception
12457    @ fall through to OP_IGET_JUMBO_finish
12458
12459    /*
12460     * Currently:
12461     *  r0 holds resolved field
12462     *  r9 holds object
12463     */
12464.LOP_IGET_JUMBO_finish:
12465    @bl      common_squeak0
12466    cmp     r9, #0                      @ check object for null
12467    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
12468    beq     common_errNullObject        @ object was null
12469    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
12470    @ no-op                             @ acquiring load
12471    FETCH(r2, 3)                        @ r2<- BBBB
12472    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
12473    SET_VREG(r0, r2)                    @ fp[BBBB]<- r0
12474    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12475    GOTO_OPCODE(ip)                     @ jump to next instruction
12476
12477/* continuation for OP_IGET_WIDE_JUMBO */
12478
12479    /*
12480     * Currently:
12481     *  r0 holds resolved field
12482     *  r9 holds object
12483     */
12484.LOP_IGET_WIDE_JUMBO_resolved:
12485    cmp     r0, #0                      @ resolution unsuccessful?
12486    beq     common_exceptionThrown      @ yes, throw exception
12487    @ fall through to OP_IGET_WIDE_JUMBO_finish
12488
12489    /*
12490     * Currently:
12491     *  r0 holds resolved field
12492     *  r9 holds object
12493     */
12494.LOP_IGET_WIDE_JUMBO_finish:
12495    cmp     r9, #0                      @ check object for null
12496    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
12497    beq     common_errNullObject        @ object was null
12498    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
12499    FETCH(r2, 3)                        @ r2<- BBBB
12500    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
12501    add     r3, rFP, r2, lsl #2         @ r3<- &fp[BBBB]
12502    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12503    stmia   r3, {r0-r1}                 @ fp[BBBB]<- r0/r1
12504    GOTO_OPCODE(ip)                     @ jump to next instruction
12505
12506/* continuation for OP_IGET_OBJECT_JUMBO */
12507
12508    /*
12509     * Currently:
12510     *  r0 holds resolved field
12511     *  r9 holds object
12512     */
12513.LOP_IGET_OBJECT_JUMBO_resolved:
12514    cmp     r0, #0                      @ resolution unsuccessful?
12515    beq     common_exceptionThrown      @ yes, throw exception
12516    @ fall through to OP_IGET_OBJECT_JUMBO_finish
12517
12518    /*
12519     * Currently:
12520     *  r0 holds resolved field
12521     *  r9 holds object
12522     */
12523.LOP_IGET_OBJECT_JUMBO_finish:
12524    @bl      common_squeak0
12525    cmp     r9, #0                      @ check object for null
12526    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
12527    beq     common_errNullObject        @ object was null
12528    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
12529    @ no-op                             @ acquiring load
12530    FETCH(r2, 3)                        @ r2<- BBBB
12531    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
12532    SET_VREG(r0, r2)                    @ fp[BBBB]<- r0
12533    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12534    GOTO_OPCODE(ip)                     @ jump to next instruction
12535
12536/* continuation for OP_IGET_BOOLEAN_JUMBO */
12537
12538    /*
12539     * Currently:
12540     *  r0 holds resolved field
12541     *  r9 holds object
12542     */
12543.LOP_IGET_BOOLEAN_JUMBO_resolved:
12544    cmp     r0, #0                      @ resolution unsuccessful?
12545    beq     common_exceptionThrown      @ yes, throw exception
12546    @ fall through to OP_IGET_BOOLEAN_JUMBO_finish
12547
12548    /*
12549     * Currently:
12550     *  r0 holds resolved field
12551     *  r9 holds object
12552     */
12553.LOP_IGET_BOOLEAN_JUMBO_finish:
12554    @bl      common_squeak1
12555    cmp     r9, #0                      @ check object for null
12556    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
12557    beq     common_errNullObject        @ object was null
12558    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
12559    @ no-op                             @ acquiring load
12560    FETCH(r2, 3)                        @ r2<- BBBB
12561    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
12562    SET_VREG(r0, r2)                    @ fp[BBBB]<- r0
12563    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12564    GOTO_OPCODE(ip)                     @ jump to next instruction
12565
12566/* continuation for OP_IGET_BYTE_JUMBO */
12567
12568    /*
12569     * Currently:
12570     *  r0 holds resolved field
12571     *  r9 holds object
12572     */
12573.LOP_IGET_BYTE_JUMBO_resolved:
12574    cmp     r0, #0                      @ resolution unsuccessful?
12575    beq     common_exceptionThrown      @ yes, throw exception
12576    @ fall through to OP_IGET_BYTE_JUMBO_finish
12577
12578    /*
12579     * Currently:
12580     *  r0 holds resolved field
12581     *  r9 holds object
12582     */
12583.LOP_IGET_BYTE_JUMBO_finish:
12584    @bl      common_squeak2
12585    cmp     r9, #0                      @ check object for null
12586    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
12587    beq     common_errNullObject        @ object was null
12588    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
12589    @ no-op                             @ acquiring load
12590    FETCH(r2, 3)                        @ r2<- BBBB
12591    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
12592    SET_VREG(r0, r2)                    @ fp[BBBB]<- r0
12593    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12594    GOTO_OPCODE(ip)                     @ jump to next instruction
12595
12596/* continuation for OP_IGET_CHAR_JUMBO */
12597
12598    /*
12599     * Currently:
12600     *  r0 holds resolved field
12601     *  r9 holds object
12602     */
12603.LOP_IGET_CHAR_JUMBO_resolved:
12604    cmp     r0, #0                      @ resolution unsuccessful?
12605    beq     common_exceptionThrown      @ yes, throw exception
12606    @ fall through to OP_IGET_CHAR_JUMBO_finish
12607
12608    /*
12609     * Currently:
12610     *  r0 holds resolved field
12611     *  r9 holds object
12612     */
12613.LOP_IGET_CHAR_JUMBO_finish:
12614    @bl      common_squeak3
12615    cmp     r9, #0                      @ check object for null
12616    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
12617    beq     common_errNullObject        @ object was null
12618    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
12619    @ no-op                             @ acquiring load
12620    FETCH(r2, 3)                        @ r2<- BBBB
12621    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
12622    SET_VREG(r0, r2)                    @ fp[BBBB]<- r0
12623    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12624    GOTO_OPCODE(ip)                     @ jump to next instruction
12625
12626/* continuation for OP_IGET_SHORT_JUMBO */
12627
12628    /*
12629     * Currently:
12630     *  r0 holds resolved field
12631     *  r9 holds object
12632     */
12633.LOP_IGET_SHORT_JUMBO_resolved:
12634    cmp     r0, #0                      @ resolution unsuccessful?
12635    beq     common_exceptionThrown      @ yes, throw exception
12636    @ fall through to OP_IGET_SHORT_JUMBO_finish
12637
12638    /*
12639     * Currently:
12640     *  r0 holds resolved field
12641     *  r9 holds object
12642     */
12643.LOP_IGET_SHORT_JUMBO_finish:
12644    @bl      common_squeak4
12645    cmp     r9, #0                      @ check object for null
12646    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
12647    beq     common_errNullObject        @ object was null
12648    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
12649    @ no-op                             @ acquiring load
12650    FETCH(r2, 3)                        @ r2<- BBBB
12651    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
12652    SET_VREG(r0, r2)                    @ fp[BBBB]<- r0
12653    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12654    GOTO_OPCODE(ip)                     @ jump to next instruction
12655
12656/* continuation for OP_IPUT_JUMBO */
12657
12658    /*
12659     * Currently:
12660     *  r0 holds resolved field
12661     *  r9 holds object
12662     */
12663.LOP_IPUT_JUMBO_resolved:
12664     cmp     r0, #0                     @ resolution unsuccessful?
12665     beq     common_exceptionThrown     @ yes, throw exception
12666     @ fall through to OP_IPUT_JUMBO_finish
12667
12668    /*
12669     * Currently:
12670     *  r0 holds resolved field
12671     *  r9 holds object
12672     */
12673.LOP_IPUT_JUMBO_finish:
12674    @bl      common_squeak0
12675    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
12676    FETCH(r1, 3)                        @ r1<- BBBB
12677    cmp     r9, #0                      @ check object for null
12678    GET_VREG(r0, r1)                    @ r0<- fp[BBBB]
12679    beq     common_errNullObject        @ object was null
12680    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
12681    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12682    @ no-op                             @ releasing store
12683    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
12684    GOTO_OPCODE(ip)                     @ jump to next instruction
12685
12686/* continuation for OP_IPUT_WIDE_JUMBO */
12687
12688    /*
12689     * Currently:
12690     *  r0 holds resolved field
12691     *  r9 holds object
12692     */
12693.LOP_IPUT_WIDE_JUMBO_resolved:
12694     cmp     r0, #0                     @ resolution unsuccessful?
12695     beq     common_exceptionThrown     @ yes, throw exception
12696     @ fall through to OP_IPUT_WIDE_JUMBO_finish
12697
12698    /*
12699     * Currently:
12700     *  r0 holds resolved field
12701     *  r9 holds object
12702     */
12703.LOP_IPUT_WIDE_JUMBO_finish:
12704    cmp     r9, #0                      @ check object for null
12705    FETCH(r2, 3)                        @ r1<- BBBB
12706    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
12707    add     r2, rFP, r2, lsl #2         @ r3<- &fp[BBBB]
12708    beq     common_errNullObject        @ object was null
12709    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
12710    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[BBBB]
12711    GET_INST_OPCODE(r10)                @ extract opcode from rINST
12712    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0/r1
12713    GOTO_OPCODE(r10)                    @ jump to next instruction
12714
12715/* continuation for OP_IPUT_OBJECT_JUMBO */
12716
12717    /*
12718     * Currently:
12719     *  r0 holds resolved field
12720     *  r9 holds object
12721     */
12722.LOP_IPUT_OBJECT_JUMBO_resolved:
12723     cmp     r0, #0                     @ resolution unsuccessful?
12724     beq     common_exceptionThrown     @ yes, throw exception
12725     @ fall through to OP_IPUT_OBJECT_JUMBO_finish
12726
12727    /*
12728     * Currently:
12729     *  r0 holds resolved field
12730     *  r9 holds object
12731     */
12732.LOP_IPUT_OBJECT_JUMBO_finish:
12733    @bl      common_squeak0
12734    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
12735    FETCH(r1, 3)                        @ r1<- BBBB
12736    cmp     r9, #0                      @ check object for null
12737    GET_VREG(r0, r1)                    @ r0<- fp[BBBB]
12738    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
12739    beq     common_errNullObject        @ object was null
12740    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
12741    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12742    @ no-op                             @ releasing store
12743    str     r0, [r9, r3]                @ obj.field (32 bits)<- r0
12744    cmp     r0, #0                      @ stored a null reference?
12745    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
12746    GOTO_OPCODE(ip)                     @ jump to next instruction
12747
12748/* continuation for OP_IPUT_BOOLEAN_JUMBO */
12749
12750    /*
12751     * Currently:
12752     *  r0 holds resolved field
12753     *  r9 holds object
12754     */
12755.LOP_IPUT_BOOLEAN_JUMBO_resolved:
12756     cmp     r0, #0                     @ resolution unsuccessful?
12757     beq     common_exceptionThrown     @ yes, throw exception
12758     @ fall through to OP_IPUT_BOOLEAN_JUMBO_finish
12759
12760    /*
12761     * Currently:
12762     *  r0 holds resolved field
12763     *  r9 holds object
12764     */
12765.LOP_IPUT_BOOLEAN_JUMBO_finish:
12766    @bl      common_squeak1
12767    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
12768    FETCH(r1, 3)                        @ r1<- BBBB
12769    cmp     r9, #0                      @ check object for null
12770    GET_VREG(r0, r1)                    @ r0<- fp[BBBB]
12771    beq     common_errNullObject        @ object was null
12772    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
12773    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12774    @ no-op                             @ releasing store
12775    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
12776    GOTO_OPCODE(ip)                     @ jump to next instruction
12777
12778/* continuation for OP_IPUT_BYTE_JUMBO */
12779
12780    /*
12781     * Currently:
12782     *  r0 holds resolved field
12783     *  r9 holds object
12784     */
12785.LOP_IPUT_BYTE_JUMBO_resolved:
12786     cmp     r0, #0                     @ resolution unsuccessful?
12787     beq     common_exceptionThrown     @ yes, throw exception
12788     @ fall through to OP_IPUT_BYTE_JUMBO_finish
12789
12790    /*
12791     * Currently:
12792     *  r0 holds resolved field
12793     *  r9 holds object
12794     */
12795.LOP_IPUT_BYTE_JUMBO_finish:
12796    @bl      common_squeak2
12797    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
12798    FETCH(r1, 3)                        @ r1<- BBBB
12799    cmp     r9, #0                      @ check object for null
12800    GET_VREG(r0, r1)                    @ r0<- fp[BBBB]
12801    beq     common_errNullObject        @ object was null
12802    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
12803    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12804    @ no-op                             @ releasing store
12805    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
12806    GOTO_OPCODE(ip)                     @ jump to next instruction
12807
12808/* continuation for OP_IPUT_CHAR_JUMBO */
12809
12810    /*
12811     * Currently:
12812     *  r0 holds resolved field
12813     *  r9 holds object
12814     */
12815.LOP_IPUT_CHAR_JUMBO_resolved:
12816     cmp     r0, #0                     @ resolution unsuccessful?
12817     beq     common_exceptionThrown     @ yes, throw exception
12818     @ fall through to OP_IPUT_CHAR_JUMBO_finish
12819
12820    /*
12821     * Currently:
12822     *  r0 holds resolved field
12823     *  r9 holds object
12824     */
12825.LOP_IPUT_CHAR_JUMBO_finish:
12826    @bl      common_squeak3
12827    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
12828    FETCH(r1, 3)                        @ r1<- BBBB
12829    cmp     r9, #0                      @ check object for null
12830    GET_VREG(r0, r1)                    @ r0<- fp[BBBB]
12831    beq     common_errNullObject        @ object was null
12832    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
12833    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12834    @ no-op                             @ releasing store
12835    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
12836    GOTO_OPCODE(ip)                     @ jump to next instruction
12837
12838/* continuation for OP_IPUT_SHORT_JUMBO */
12839
12840    /*
12841     * Currently:
12842     *  r0 holds resolved field
12843     *  r9 holds object
12844     */
12845.LOP_IPUT_SHORT_JUMBO_resolved:
12846     cmp     r0, #0                     @ resolution unsuccessful?
12847     beq     common_exceptionThrown     @ yes, throw exception
12848     @ fall through to OP_IPUT_SHORT_JUMBO_finish
12849
12850    /*
12851     * Currently:
12852     *  r0 holds resolved field
12853     *  r9 holds object
12854     */
12855.LOP_IPUT_SHORT_JUMBO_finish:
12856    @bl      common_squeak4
12857    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
12858    FETCH(r1, 3)                        @ r1<- BBBB
12859    cmp     r9, #0                      @ check object for null
12860    GET_VREG(r0, r1)                    @ r0<- fp[BBBB]
12861    beq     common_errNullObject        @ object was null
12862    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
12863    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12864    @ no-op                             @ releasing store
12865    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
12866    GOTO_OPCODE(ip)                     @ jump to next instruction
12867
12868/* continuation for OP_SGET_JUMBO */
12869
12870    /*
12871     * Continuation if the field has not yet been resolved.
12872     *  r1: AAAAAAAA field ref
12873     */
12874.LOP_SGET_JUMBO_resolve:
12875    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
12876    EXPORT_PC()                         @ resolve() could throw, so export now
12877    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
12878    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
12879    cmp     r0, #0                      @ success?
12880    bne     .LOP_SGET_JUMBO_finish          @ yes, finish
12881    b       common_exceptionThrown      @ no, handle exception
12882
12883/* continuation for OP_SGET_WIDE_JUMBO */
12884
12885    /*
12886     * Continuation if the field has not yet been resolved.
12887     *  r1: BBBB field ref
12888     *
12889     * Returns StaticField pointer in r0.
12890     */
12891.LOP_SGET_WIDE_JUMBO_resolve:
12892    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
12893    EXPORT_PC()                         @ resolve() could throw, so export now
12894    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
12895    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
12896    cmp     r0, #0                      @ success?
12897    bne     .LOP_SGET_WIDE_JUMBO_finish          @ yes, finish
12898    b       common_exceptionThrown      @ no, handle exception
12899
12900/* continuation for OP_SGET_OBJECT_JUMBO */
12901
12902    /*
12903     * Continuation if the field has not yet been resolved.
12904     *  r1: AAAAAAAA field ref
12905     */
12906.LOP_SGET_OBJECT_JUMBO_resolve:
12907    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
12908    EXPORT_PC()                         @ resolve() could throw, so export now
12909    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
12910    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
12911    cmp     r0, #0                      @ success?
12912    bne     .LOP_SGET_OBJECT_JUMBO_finish          @ yes, finish
12913    b       common_exceptionThrown      @ no, handle exception
12914
12915/* continuation for OP_SGET_BOOLEAN_JUMBO */
12916
12917    /*
12918     * Continuation if the field has not yet been resolved.
12919     *  r1: AAAAAAAA field ref
12920     */
12921.LOP_SGET_BOOLEAN_JUMBO_resolve:
12922    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
12923    EXPORT_PC()                         @ resolve() could throw, so export now
12924    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
12925    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
12926    cmp     r0, #0                      @ success?
12927    bne     .LOP_SGET_BOOLEAN_JUMBO_finish          @ yes, finish
12928    b       common_exceptionThrown      @ no, handle exception
12929
12930/* continuation for OP_SGET_BYTE_JUMBO */
12931
12932    /*
12933     * Continuation if the field has not yet been resolved.
12934     *  r1: AAAAAAAA field ref
12935     */
12936.LOP_SGET_BYTE_JUMBO_resolve:
12937    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
12938    EXPORT_PC()                         @ resolve() could throw, so export now
12939    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
12940    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
12941    cmp     r0, #0                      @ success?
12942    bne     .LOP_SGET_BYTE_JUMBO_finish          @ yes, finish
12943    b       common_exceptionThrown      @ no, handle exception
12944
12945/* continuation for OP_SGET_CHAR_JUMBO */
12946
12947    /*
12948     * Continuation if the field has not yet been resolved.
12949     *  r1: AAAAAAAA field ref
12950     */
12951.LOP_SGET_CHAR_JUMBO_resolve:
12952    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
12953    EXPORT_PC()                         @ resolve() could throw, so export now
12954    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
12955    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
12956    cmp     r0, #0                      @ success?
12957    bne     .LOP_SGET_CHAR_JUMBO_finish          @ yes, finish
12958    b       common_exceptionThrown      @ no, handle exception
12959
12960/* continuation for OP_SGET_SHORT_JUMBO */
12961
12962    /*
12963     * Continuation if the field has not yet been resolved.
12964     *  r1: AAAAAAAA field ref
12965     */
12966.LOP_SGET_SHORT_JUMBO_resolve:
12967    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
12968    EXPORT_PC()                         @ resolve() could throw, so export now
12969    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
12970    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
12971    cmp     r0, #0                      @ success?
12972    bne     .LOP_SGET_SHORT_JUMBO_finish          @ yes, finish
12973    b       common_exceptionThrown      @ no, handle exception
12974
12975/* continuation for OP_SPUT_JUMBO */
12976
12977    /*
12978     * Continuation if the field has not yet been resolved.
12979     *  r1: AAAAAAAA field ref
12980     */
12981.LOP_SPUT_JUMBO_resolve:
12982    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
12983    EXPORT_PC()                         @ resolve() could throw, so export now
12984    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
12985    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
12986    cmp     r0, #0                      @ success?
12987    bne     .LOP_SPUT_JUMBO_finish          @ yes, finish
12988    b       common_exceptionThrown      @ no, handle exception
12989
12990/* continuation for OP_SPUT_WIDE_JUMBO */
12991
12992    /*
12993     * Continuation if the field has not yet been resolved.
12994     *  r1: BBBB field ref
12995     *  r9: &fp[AA]
12996     *
12997     * Returns StaticField pointer in r2.
12998     */
12999.LOP_SPUT_WIDE_JUMBO_resolve:
13000    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
13001    EXPORT_PC()                         @ resolve() could throw, so export now
13002    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
13003    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
13004    cmp     r0, #0                      @ success?
13005    mov     r2, r0                      @ copy to r2
13006    bne     .LOP_SPUT_WIDE_JUMBO_finish          @ yes, finish
13007    b       common_exceptionThrown      @ no, handle exception
13008
13009/* continuation for OP_SPUT_OBJECT_JUMBO */
13010
13011.LOP_SPUT_OBJECT_JUMBO_finish:   @ field ptr in r0
13012    FETCH(r2, 3)                        @ r2<- BBBB
13013    FETCH_ADVANCE_INST(4)               @ advance rPC, load rINST
13014    GET_VREG(r1, r2)                    @ r1<- fp[BBBB]
13015    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
13016    ldr     r9, [r0, #offField_clazz]   @ r9<- field->clazz
13017    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
13018    @ no-op                             @ releasing store
13019    str     r1, [r0, #offStaticField_value]  @ field<- vBBBB
13020    cmp     r1, #0                      @ stored a null object?
13021    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card based on obj head
13022    GOTO_OPCODE(ip)                     @ jump to next instruction
13023
13024/* continuation for OP_SPUT_BOOLEAN_JUMBO */
13025
13026    /*
13027     * Continuation if the field has not yet been resolved.
13028     *  r1: AAAAAAAA field ref
13029     */
13030.LOP_SPUT_BOOLEAN_JUMBO_resolve:
13031    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
13032    EXPORT_PC()                         @ resolve() could throw, so export now
13033    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
13034    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
13035    cmp     r0, #0                      @ success?
13036    bne     .LOP_SPUT_BOOLEAN_JUMBO_finish          @ yes, finish
13037    b       common_exceptionThrown      @ no, handle exception
13038
13039/* continuation for OP_SPUT_BYTE_JUMBO */
13040
13041    /*
13042     * Continuation if the field has not yet been resolved.
13043     *  r1: AAAAAAAA field ref
13044     */
13045.LOP_SPUT_BYTE_JUMBO_resolve:
13046    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
13047    EXPORT_PC()                         @ resolve() could throw, so export now
13048    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
13049    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
13050    cmp     r0, #0                      @ success?
13051    bne     .LOP_SPUT_BYTE_JUMBO_finish          @ yes, finish
13052    b       common_exceptionThrown      @ no, handle exception
13053
13054/* continuation for OP_SPUT_CHAR_JUMBO */
13055
13056    /*
13057     * Continuation if the field has not yet been resolved.
13058     *  r1: AAAAAAAA field ref
13059     */
13060.LOP_SPUT_CHAR_JUMBO_resolve:
13061    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
13062    EXPORT_PC()                         @ resolve() could throw, so export now
13063    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
13064    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
13065    cmp     r0, #0                      @ success?
13066    bne     .LOP_SPUT_CHAR_JUMBO_finish          @ yes, finish
13067    b       common_exceptionThrown      @ no, handle exception
13068
13069/* continuation for OP_SPUT_SHORT_JUMBO */
13070
13071    /*
13072     * Continuation if the field has not yet been resolved.
13073     *  r1: AAAAAAAA field ref
13074     */
13075.LOP_SPUT_SHORT_JUMBO_resolve:
13076    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
13077    EXPORT_PC()                         @ resolve() could throw, so export now
13078    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
13079    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
13080    cmp     r0, #0                      @ success?
13081    bne     .LOP_SPUT_SHORT_JUMBO_finish          @ yes, finish
13082    b       common_exceptionThrown      @ no, handle exception
13083
13084/* continuation for OP_INVOKE_VIRTUAL_JUMBO */
13085
13086    /*
13087     * At this point:
13088     *  r0 = resolved base method
13089     */
13090.LOP_INVOKE_VIRTUAL_JUMBO_continue:
13091    FETCH(r10, 4)                       @ r10<- CCCC
13092    GET_VREG(r1, r10)                   @ r1<- "this" ptr
13093    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
13094    cmp     r1, #0                      @ is "this" null?
13095    beq     common_errNullObject        @ null "this", throw exception
13096    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
13097    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
13098    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
13099    bl      common_invokeMethodJumbo    @ continue on
13100
13101/* continuation for OP_INVOKE_SUPER_JUMBO */
13102
13103    /*
13104     * At this point:
13105     *  r0 = resolved base method
13106     *  r9 = method->clazz
13107     */
13108.LOP_INVOKE_SUPER_JUMBO_continue:
13109    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
13110    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
13111    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
13112    EXPORT_PC()                         @ must export for invoke
13113    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
13114    bcs     .LOP_INVOKE_SUPER_JUMBO_nsm             @ method not present in superclass
13115    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
13116    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
13117    bl      common_invokeMethodJumbo    @ continue on
13118
13119.LOP_INVOKE_SUPER_JUMBO_resolve:
13120    mov     r0, r9                      @ r0<- method->clazz
13121    mov     r2, #METHOD_VIRTUAL         @ resolver method type
13122    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
13123    cmp     r0, #0                      @ got null?
13124    bne     .LOP_INVOKE_SUPER_JUMBO_continue        @ no, continue
13125    b       common_exceptionThrown      @ yes, handle exception
13126
13127    /*
13128     * Throw a NoSuchMethodError with the method name as the message.
13129     *  r0 = resolved base method
13130     */
13131.LOP_INVOKE_SUPER_JUMBO_nsm:
13132    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
13133    b       common_errNoSuchMethod
13134
13135/* continuation for OP_INVOKE_DIRECT_JUMBO */
13136
13137    /*
13138     * On entry:
13139     *  r1 = reference (CCCC)
13140     *  r10 = "this" register
13141     */
13142.LOP_INVOKE_DIRECT_JUMBO_resolve:
13143    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
13144    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
13145    mov     r2, #METHOD_DIRECT          @ resolver method type
13146    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
13147    cmp     r0, #0                      @ got null?
13148    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
13149    bne     .LOP_INVOKE_DIRECT_JUMBO_finish          @ no, continue
13150    b       common_exceptionThrown      @ yes, handle exception
13151
13152    .size   dvmAsmSisterStart, .-dvmAsmSisterStart
13153    .global dvmAsmSisterEnd
13154dvmAsmSisterEnd:
13155
13156/* File: armv5te/footer.S */
13157
13158/*
13159 * ===========================================================================
13160 *  Common subroutines and data
13161 * ===========================================================================
13162 */
13163
13164
13165
13166    .text
13167    .align  2
13168
13169#if defined(WITH_JIT)
13170#if defined(WITH_SELF_VERIFICATION)
13171    .global dvmJitToInterpPunt
13172dvmJitToInterpPunt:
13173    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
13174    mov    r2,#kSVSPunt                 @ r2<- interpreter entry point
13175    mov    r3, #0
13176    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
13177    b      jitSVShadowRunEnd            @ doesn't return
13178
13179    .global dvmJitToInterpSingleStep
13180dvmJitToInterpSingleStep:
13181    str    lr,[rGLUE,#offGlue_jitResumeNPC]
13182    str    r1,[rGLUE,#offGlue_jitResumeDPC]
13183    mov    r2,#kSVSSingleStep           @ r2<- interpreter entry point
13184    b      jitSVShadowRunEnd            @ doesn't return
13185
13186    .global dvmJitToInterpNoChainNoProfile
13187dvmJitToInterpNoChainNoProfile:
13188    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
13189    mov    r0,rPC                       @ pass our target PC
13190    mov    r2,#kSVSNoProfile            @ r2<- interpreter entry point
13191    mov    r3, #0                       @ 0 means !inJitCodeCache
13192    str    r3, [r10, #offThread_inJitCodeCache] @ back to the interp land
13193    b      jitSVShadowRunEnd            @ doesn't return
13194
13195    .global dvmJitToInterpTraceSelectNoChain
13196dvmJitToInterpTraceSelectNoChain:
13197    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
13198    mov    r0,rPC                       @ pass our target PC
13199    mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
13200    mov    r3, #0                       @ 0 means !inJitCodeCache
13201    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
13202    b      jitSVShadowRunEnd            @ doesn't return
13203
13204    .global dvmJitToInterpTraceSelect
13205dvmJitToInterpTraceSelect:
13206    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
13207    ldr    r0,[lr, #-1]                 @ pass our target PC
13208    mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
13209    mov    r3, #0                       @ 0 means !inJitCodeCache
13210    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
13211    b      jitSVShadowRunEnd            @ doesn't return
13212
13213    .global dvmJitToInterpBackwardBranch
13214dvmJitToInterpBackwardBranch:
13215    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
13216    ldr    r0,[lr, #-1]                 @ pass our target PC
13217    mov    r2,#kSVSBackwardBranch       @ r2<- interpreter entry point
13218    mov    r3, #0                       @ 0 means !inJitCodeCache
13219    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
13220    b      jitSVShadowRunEnd            @ doesn't return
13221
13222    .global dvmJitToInterpNormal
13223dvmJitToInterpNormal:
13224    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
13225    ldr    r0,[lr, #-1]                 @ pass our target PC
13226    mov    r2,#kSVSNormal               @ r2<- interpreter entry point
13227    mov    r3, #0                       @ 0 means !inJitCodeCache
13228    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
13229    b      jitSVShadowRunEnd            @ doesn't return
13230
13231    .global dvmJitToInterpNoChain
13232dvmJitToInterpNoChain:
13233    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
13234    mov    r0,rPC                       @ pass our target PC
13235    mov    r2,#kSVSNoChain              @ r2<- interpreter entry point
13236    mov    r3, #0                       @ 0 means !inJitCodeCache
13237    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
13238    b      jitSVShadowRunEnd            @ doesn't return
13239#else
13240/*
13241 * Return from the translation cache to the interpreter when the compiler is
13242 * having issues translating/executing a Dalvik instruction. We have to skip
13243 * the code cache lookup otherwise it is possible to indefinitely bouce
13244 * between the interpreter and the code cache if the instruction that fails
13245 * to be compiled happens to be at a trace start.
13246 */
13247    .global dvmJitToInterpPunt
13248dvmJitToInterpPunt:
13249    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
13250    mov    rPC, r0
13251#if defined(WITH_JIT_TUNING)
13252    mov    r0,lr
13253    bl     dvmBumpPunt;
13254#endif
13255    EXPORT_PC()
13256    mov    r0, #0
13257    str    r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land
13258    adrl   rIBASE, dvmAsmInstructionStart
13259    FETCH_INST()
13260    GET_INST_OPCODE(ip)
13261    GOTO_OPCODE(ip)
13262
13263/*
13264 * Return to the interpreter to handle a single instruction.
13265 * On entry:
13266 *    r0 <= PC
13267 *    r1 <= PC of resume instruction
13268 *    lr <= resume point in translation
13269 */
13270    .global dvmJitToInterpSingleStep
13271dvmJitToInterpSingleStep:
13272    str    lr,[rGLUE,#offGlue_jitResumeNPC]
13273    str    r1,[rGLUE,#offGlue_jitResumeDPC]
13274    mov    r1,#kInterpEntryInstr
13275    @ enum is 4 byte in aapcs-EABI
13276    str    r1, [rGLUE, #offGlue_entryPoint]
13277    mov    rPC,r0
13278    EXPORT_PC()
13279
13280    adrl   rIBASE, dvmAsmInstructionStart
13281    mov    r2,#kJitSingleStep     @ Ask for single step and then revert
13282    str    r2,[rGLUE,#offGlue_jitState]
13283    mov    r1,#1                  @ set changeInterp to bail to debug interp
13284    b      common_gotoBail
13285
13286/*
13287 * Return from the translation cache and immediately request
13288 * a translation for the exit target.  Commonly used for callees.
13289 */
13290    .global dvmJitToInterpTraceSelectNoChain
13291dvmJitToInterpTraceSelectNoChain:
13292#if defined(WITH_JIT_TUNING)
13293    bl     dvmBumpNoChain
13294#endif
13295    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
13296    mov    r0,rPC
13297    bl     dvmJitGetTraceAddr       @ Is there a translation?
13298    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
13299    mov    r1, rPC                  @ arg1 of translation may need this
13300    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
13301    cmp    r0,#0                    @ !0 means translation exists
13302    bxne   r0                       @ continue native execution if so
13303    b      2f                       @ branch over to use the interpreter
13304
13305/*
13306 * Return from the translation cache and immediately request
13307 * a translation for the exit target.  Commonly used following
13308 * invokes.
13309 */
13310    .global dvmJitToInterpTraceSelect
13311dvmJitToInterpTraceSelect:
13312    ldr    rPC,[lr, #-1]           @ get our target PC
13313    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
13314    add    rINST,lr,#-5            @ save start of chain branch
13315    add    rINST, #-4              @  .. which is 9 bytes back
13316    mov    r0,rPC
13317    bl     dvmJitGetTraceAddr      @ Is there a translation?
13318    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
13319    cmp    r0,#0
13320    beq    2f
13321    mov    r1,rINST
13322    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
13323    mov    r1, rPC                  @ arg1 of translation may need this
13324    mov    lr, #0                   @ in case target is HANDLER_INTERPRET
13325    cmp    r0,#0                    @ successful chain?
13326    bxne   r0                       @ continue native execution
13327    b      toInterpreter            @ didn't chain - resume with interpreter
13328
13329/* No translation, so request one if profiling isn't disabled*/
133302:
13331    adrl   rIBASE, dvmAsmInstructionStart
13332    GET_JIT_PROF_TABLE(r0)
13333    FETCH_INST()
13334    cmp    r0, #0
13335    movne  r2,#kJitTSelectRequestHot   @ ask for trace selection
13336    bne    common_selectTrace
13337    GET_INST_OPCODE(ip)
13338    GOTO_OPCODE(ip)
13339
13340/*
13341 * Return from the translation cache to the interpreter.
13342 * The return was done with a BLX from thumb mode, and
13343 * the following 32-bit word contains the target rPC value.
13344 * Note that lr (r14) will have its low-order bit set to denote
13345 * its thumb-mode origin.
13346 *
13347 * We'll need to stash our lr origin away, recover the new
13348 * target and then check to see if there is a translation available
13349 * for our new target.  If so, we do a translation chain and
13350 * go back to native execution.  Otherwise, it's back to the
13351 * interpreter (after treating this entry as a potential
13352 * trace start).
13353 */
13354    .global dvmJitToInterpNormal
13355dvmJitToInterpNormal:
13356    ldr    rPC,[lr, #-1]           @ get our target PC
13357    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
13358    add    rINST,lr,#-5            @ save start of chain branch
13359    add    rINST,#-4               @ .. which is 9 bytes back
13360#if defined(WITH_JIT_TUNING)
13361    bl     dvmBumpNormal
13362#endif
13363    mov    r0,rPC
13364    bl     dvmJitGetTraceAddr      @ Is there a translation?
13365    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
13366    cmp    r0,#0
13367    beq    toInterpreter            @ go if not, otherwise do chain
13368    mov    r1,rINST
13369    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
13370    mov    r1, rPC                  @ arg1 of translation may need this
13371    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
13372    cmp    r0,#0                    @ successful chain?
13373    bxne   r0                       @ continue native execution
13374    b      toInterpreter            @ didn't chain - resume with interpreter
13375
13376/*
13377 * Return from the translation cache to the interpreter to do method invocation.
13378 * Check if translation exists for the callee, but don't chain to it.
13379 */
13380    .global dvmJitToInterpNoChainNoProfile
13381dvmJitToInterpNoChainNoProfile:
13382#if defined(WITH_JIT_TUNING)
13383    bl     dvmBumpNoChain
13384#endif
13385    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
13386    mov    r0,rPC
13387    bl     dvmJitGetTraceAddr       @ Is there a translation?
13388    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
13389    mov    r1, rPC                  @ arg1 of translation may need this
13390    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
13391    cmp    r0,#0
13392    bxne   r0                       @ continue native execution if so
13393    EXPORT_PC()
13394    adrl   rIBASE, dvmAsmInstructionStart
13395    FETCH_INST()
13396    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
13397    GOTO_OPCODE(ip)                     @ jump to next instruction
13398
13399/*
13400 * Return from the translation cache to the interpreter to do method invocation.
13401 * Check if translation exists for the callee, but don't chain to it.
13402 */
13403    .global dvmJitToInterpNoChain
13404dvmJitToInterpNoChain:
13405#if defined(WITH_JIT_TUNING)
13406    bl     dvmBumpNoChain
13407#endif
13408    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
13409    mov    r0,rPC
13410    bl     dvmJitGetTraceAddr       @ Is there a translation?
13411    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
13412    mov    r1, rPC                  @ arg1 of translation may need this
13413    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
13414    cmp    r0,#0
13415    bxne   r0                       @ continue native execution if so
13416#endif
13417
13418/*
13419 * No translation, restore interpreter regs and start interpreting.
13420 * rGLUE & rFP were preserved in the translated code, and rPC has
13421 * already been restored by the time we get here.  We'll need to set
13422 * up rIBASE & rINST, and load the address of the JitTable into r0.
13423 */
13424toInterpreter:
13425    EXPORT_PC()
13426    adrl   rIBASE, dvmAsmInstructionStart
13427    FETCH_INST()
13428    GET_JIT_PROF_TABLE(r0)
13429    @ NOTE: intended fallthrough
13430
13431/*
13432 * Common code to update potential trace start counter, and initiate
13433 * a trace-build if appropriate.  On entry, rPC should point to the
13434 * next instruction to execute, and rINST should be already loaded with
13435 * the next opcode word, and r0 holds a pointer to the jit profile
13436 * table (pJitProfTable).
13437 */
13438common_testUpdateProfile:
13439    cmp     r0,#0
13440    GET_INST_OPCODE(ip)
13441    GOTO_OPCODE_IFEQ(ip)       @ if not profiling, fallthrough otherwise */
13442
13443common_updateProfile:
13444    eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
13445    lsl     r3,r3,#(32 - JIT_PROF_SIZE_LOG_2)          @ shift out excess bits
13446    ldrb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter
13447    GET_INST_OPCODE(ip)
13448    subs    r1,r1,#1           @ decrement counter
13449    strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it
13450    GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
13451
13452/*
13453 * Here, we switch to the debug interpreter to request
13454 * trace selection.  First, though, check to see if there
13455 * is already a native translation in place (and, if so,
13456 * jump to it now).
13457 */
13458    GET_JIT_THRESHOLD(r1)
13459    ldr     r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
13460    strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter
13461    EXPORT_PC()
13462    mov     r0,rPC
13463    bl      dvmJitGetTraceAddr          @ r0<- dvmJitGetTraceAddr(rPC)
13464    str     r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
13465    mov     r1, rPC                     @ arg1 of translation may need this
13466    mov     lr, #0                      @  in case target is HANDLER_INTERPRET
13467    cmp     r0,#0
13468#if !defined(WITH_SELF_VERIFICATION)
13469    bxne    r0                          @ jump to the translation
13470    mov     r2,#kJitTSelectRequest      @ ask for trace selection
13471    @ fall-through to common_selectTrace
13472#else
13473    moveq   r2,#kJitTSelectRequest      @ ask for trace selection
13474    beq     common_selectTrace
13475    /*
13476     * At this point, we have a target translation.  However, if
13477     * that translation is actually the interpret-only pseudo-translation
13478     * we want to treat it the same as no translation.
13479     */
13480    mov     r10, r0                     @ save target
13481    bl      dvmCompilerGetInterpretTemplate
13482    cmp     r0, r10                     @ special case?
13483    bne     jitSVShadowRunStart         @ set up self verification shadow space
13484    @ Need to clear the inJitCodeCache flag
13485    ldr    r10, [rGLUE, #offGlue_self]  @ r10 <- glue->self
13486    mov    r3, #0                       @ 0 means not in the JIT code cache
13487    str    r3, [r10, #offThread_inJitCodeCache] @ back to the interp land
13488    GET_INST_OPCODE(ip)
13489    GOTO_OPCODE(ip)
13490    /* no return */
13491#endif
13492
13493/*
13494 * On entry:
13495 *  r2 is jit state, e.g. kJitTSelectRequest or kJitTSelectRequestHot
13496 */
13497common_selectTrace:
13498    str     r2,[rGLUE,#offGlue_jitState]
13499    mov     r2,#kInterpEntryInstr       @ normal entry reason
13500    str     r2,[rGLUE,#offGlue_entryPoint]
13501    mov     r1,#1                       @ set changeInterp
13502    b       common_gotoBail
13503
13504#if defined(WITH_SELF_VERIFICATION)
13505/*
13506 * Save PC and registers to shadow memory for self verification mode
13507 * before jumping to native translation.
13508 * On entry:
13509 *    rPC, rFP, rGLUE: the values that they should contain
13510 *    r10: the address of the target translation.
13511 */
13512jitSVShadowRunStart:
13513    mov     r0,rPC                      @ r0<- program counter
13514    mov     r1,rFP                      @ r1<- frame pointer
13515    mov     r2,rGLUE                    @ r2<- InterpState pointer
13516    mov     r3,r10                      @ r3<- target translation
13517    bl      dvmSelfVerificationSaveState @ save registers to shadow space
13518    ldr     rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
13519    add     rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
13520    bx      r10                         @ jump to the translation
13521
13522/*
13523 * Restore PC, registers, and interpState to original values
13524 * before jumping back to the interpreter.
13525 */
13526jitSVShadowRunEnd:
13527    mov    r1,rFP                        @ pass ending fp
13528    bl     dvmSelfVerificationRestoreState @ restore pc and fp values
13529    ldr    rPC,[r0,#offShadowSpace_startPC] @ restore PC
13530    ldr    rFP,[r0,#offShadowSpace_fp]   @ restore FP
13531    ldr    rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
13532    ldr    r1,[r0,#offShadowSpace_svState] @ get self verification state
13533    cmp    r1,#0                         @ check for punt condition
13534    beq    1f
13535    mov    r2,#kJitSelfVerification      @ ask for self verification
13536    str    r2,[rGLUE,#offGlue_jitState]
13537    mov    r2,#kInterpEntryInstr         @ normal entry reason
13538    str    r2,[rGLUE,#offGlue_entryPoint]
13539    mov    r1,#1                         @ set changeInterp
13540    b      common_gotoBail
13541
135421:                                       @ exit to interpreter without check
13543    EXPORT_PC()
13544    adrl   rIBASE, dvmAsmInstructionStart
13545    FETCH_INST()
13546    GET_INST_OPCODE(ip)
13547    GOTO_OPCODE(ip)
13548#endif
13549
13550#endif
13551
13552/*
13553 * Common code when a backward branch is taken.
13554 *
13555 * TODO: we could avoid a branch by just setting r0 and falling through
13556 * into the common_periodicChecks code, and having a test on r0 at the
13557 * end determine if we should return to the caller or update & branch to
13558 * the next instr.
13559 *
13560 * On entry:
13561 *  r9 is PC adjustment *in bytes*
13562 */
13563common_backwardBranch:
13564    mov     r0, #kInterpEntryInstr
13565    bl      common_periodicChecks
13566#if defined(WITH_JIT)
13567    GET_JIT_PROF_TABLE(r0)
13568    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
13569    cmp     r0,#0
13570    bne     common_updateProfile
13571    GET_INST_OPCODE(ip)
13572    GOTO_OPCODE(ip)
13573#else
13574    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
13575    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
13576    GOTO_OPCODE(ip)                     @ jump to next instruction
13577#endif
13578
13579
13580/*
13581 * Need to see if the thread needs to be suspended or debugger/profiler
13582 * activity has begun.  If so, we suspend the thread or side-exit to
13583 * the debug interpreter as appropriate.
13584 *
13585 * The common case is no activity on any of these, so we want to figure
13586 * that out quickly.  If something is up, we can then sort out what.
13587 *
13588 * We want to be fast if the VM was built without debugger or profiler
13589 * support, but we also need to recognize that the system is usually
13590 * shipped with both of these enabled.
13591 *
13592 * TODO: reduce this so we're just checking a single location.
13593 *
13594 * On entry:
13595 *  r0 is reentry type, e.g. kInterpEntryInstr (for debugger/profiling)
13596 *  r9 is trampoline PC adjustment *in bytes*
13597 */
13598common_periodicChecks:
13599    ldr     r1, [rGLUE, #offGlue_pInterpBreak] @ r3<- &interpBreak
13600    /* speculatively load address of thread-specific suspend count */
13601    ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
13602    ldr     r1, [r1]                                @ r1<- interpBreak
13603    /* speculatively load thread-specific suspend count */
13604    ldr     ip, [r3]                    @ ip<- suspendCount (int)
13605    cmp     r1, #0                                  @ anything unusual?
13606    bxeq    lr                                      @ return if not
13607    /*
13608     * One or more interesting events have happened.  Figure out what.
13609     *
13610     * r0 still holds the reentry type.
13611     */
13612    cmp     ip, #0                      @ want suspend?
13613    beq     3f                          @ no, must be something else
13614
13615    stmfd   sp!, {r0, lr}               @ preserve r0 and lr
13616#if defined(WITH_JIT)
13617    /*
13618     * Refresh the Jit's cached copy of profile table pointer.  This pointer
13619     * doubles as the Jit's on/off switch.
13620     */
13621    ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ r3<-&gDvmJit.pJitProfTable
13622    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
13623    ldr     r3, [r3] @ r3 <- pJitProfTable
13624    EXPORT_PC()                         @ need for precise GC
13625    str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch
13626#else
13627    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
13628    EXPORT_PC()                         @ need for precise GC
13629#endif
13630    bl      dvmCheckSuspendPending      @ do full check, suspend if necessary
13631    ldmfd   sp!, {r0, lr}               @ restore r0 and lr
13632
13633    /*
13634     * Reload the interpBreak flags - they may have changed while we
13635     * were suspended.
13636     */
13637    ldr     r1, [rGLUE, #offGlue_pInterpBreak]   @ r1<- &interpBreak
13638    ldr     r1, [r1]                    @ r1<- interpBreak
136393:
13640    /*
13641     * TODO: this code is too fragile.  Need a general mechanism
13642     * to identify what actions to take by submode.  Some profiling modes
13643     * (instruction count) need to single-step, while method tracing
13644     * may not.  Debugging with breakpoints can run unfettered, but
13645     * source-level single-stepping requires Dalvik singlestepping.
13646     * GC may require a one-shot action and then full-speed resumption.
13647     */
13648    ands    r1, #(kSubModeDebuggerActive | kSubModeEmulatorTrace | kSubModeInstCounting)
13649    bxeq    lr                          @ nothing to do, return
13650
13651    @ debugger/profiler enabled, bail out; glue->entryPoint was set above
13652    str     r0, [rGLUE, #offGlue_entryPoint]    @ store r0, need for debug/prof
13653    add     rPC, rPC, r9                @ update rPC
13654    mov     r1, #1                      @ "want switch" = true
13655    b       common_gotoBail             @ side exit
13656
13657
13658/*
13659 * The equivalent of "goto bail", this calls through the "bail handler".
13660 *
13661 * State registers will be saved to the "glue" area before bailing.
13662 *
13663 * On entry:
13664 *  r1 is "bool changeInterp", indicating if we want to switch to the
13665 *     other interpreter or just bail all the way out
13666 */
13667common_gotoBail:
13668    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
13669    mov     r0, rGLUE                   @ r0<- glue ptr
13670    b       dvmMterpStdBail             @ call(glue, changeInterp)
13671
13672    @add     r1, r1, #1                  @ using (boolean+1)
13673    @add     r0, rGLUE, #offGlue_jmpBuf  @ r0<- &glue->jmpBuf
13674    @bl      _longjmp                    @ does not return
13675    @bl      common_abort
13676
13677
13678/*
13679 * Common code for jumbo method invocation.
13680 * NOTE: this adjusts rPC to account for the difference in instruction width.
13681 * As a result, the savedPc in the stack frame will not be wholly accurate. So
13682 * long as that is only used for source file line number calculations, we're
13683 * okay.
13684 *
13685 * On entry:
13686 *  r0 is "Method* methodToCall", the method we're trying to call
13687 */
13688common_invokeMethodJumbo:
13689.LinvokeNewJumbo:
13690    @ prepare to copy args to "outs" area of current frame
13691    add     rPC, rPC, #4                @ adjust pc to make return consistent
13692    FETCH(r2, 1)                        @ r2<- BBBB (arg count)
13693    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
13694    cmp     r2, #0                      @ no args?
13695    beq     .LinvokeArgsDone            @ if no args, skip the rest
13696    FETCH(r1, 2)                        @ r1<- CCCC
13697    b       .LinvokeRangeArgs           @ handle args like invoke range
13698
13699/*
13700 * Common code for method invocation with range.
13701 *
13702 * On entry:
13703 *  r0 is "Method* methodToCall", the method we're trying to call
13704 */
13705common_invokeMethodRange:
13706.LinvokeNewRange:
13707    @ prepare to copy args to "outs" area of current frame
13708    movs    r2, rINST, lsr #8           @ r2<- AA (arg count) -- test for zero
13709    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
13710    beq     .LinvokeArgsDone            @ if no args, skip the rest
13711    FETCH(r1, 2)                        @ r1<- CCCC
13712
13713.LinvokeRangeArgs:
13714    @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
13715    @ (very few methods have > 10 args; could unroll for common cases)
13716    add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
13717    sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
137181:  ldr     r1, [r3], #4                @ val = *fp++
13719    subs    r2, r2, #1                  @ count--
13720    str     r1, [r10], #4               @ *outs++ = val
13721    bne     1b                          @ ...while count != 0
13722    b       .LinvokeArgsDone
13723
13724/*
13725 * Common code for method invocation without range.
13726 *
13727 * On entry:
13728 *  r0 is "Method* methodToCall", the method we're trying to call
13729 */
13730common_invokeMethodNoRange:
13731.LinvokeNewNoRange:
13732    @ prepare to copy args to "outs" area of current frame
13733    movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
13734    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
13735    FETCH(r1, 2)                        @ r1<- GFED (load here to hide latency)
13736    beq     .LinvokeArgsDone
13737
13738    @ r0=methodToCall, r1=GFED, r2=count, r10=outs
13739.LinvokeNonRange:
13740    rsb     r2, r2, #5                  @ r2<- 5-r2
13741    add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
13742    bl      common_abort                @ (skipped due to ARM prefetch)
137435:  and     ip, rINST, #0x0f00          @ isolate A
13744    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vA (shift right 8, left 2)
13745    mov     r0, r0                      @ nop
13746    str     r2, [r10, #-4]!             @ *--outs = vA
137474:  and     ip, r1, #0xf000             @ isolate G
13748    ldr     r2, [rFP, ip, lsr #10]      @ r2<- vG (shift right 12, left 2)
13749    mov     r0, r0                      @ nop
13750    str     r2, [r10, #-4]!             @ *--outs = vG
137513:  and     ip, r1, #0x0f00             @ isolate F
13752    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vF
13753    mov     r0, r0                      @ nop
13754    str     r2, [r10, #-4]!             @ *--outs = vF
137552:  and     ip, r1, #0x00f0             @ isolate E
13756    ldr     r2, [rFP, ip, lsr #2]       @ r2<- vE
13757    mov     r0, r0                      @ nop
13758    str     r2, [r10, #-4]!             @ *--outs = vE
137591:  and     ip, r1, #0x000f             @ isolate D
13760    ldr     r2, [rFP, ip, lsl #2]       @ r2<- vD
13761    mov     r0, r0                      @ nop
13762    str     r2, [r10, #-4]!             @ *--outs = vD
137630:  @ fall through to .LinvokeArgsDone
13764
13765.LinvokeArgsDone: @ r0=methodToCall
13766    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
13767    ldrh    r3, [r0, #offMethod_outsSize]  @ r3<- methodToCall->outsSize
13768    ldr     r2, [r0, #offMethod_insns]  @ r2<- method->insns
13769    ldr     rINST, [r0, #offMethod_clazz]  @ rINST<- method->clazz
13770    @ find space for the new stack frame, check for overflow
13771    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
13772    sub     r1, r1, r9, lsl #2          @ r1<- newFp (old savearea - regsSize)
13773    SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
13774@    bl      common_dumpRegs
13775    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
13776    sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
13777    cmp     r3, r9                      @ bottom < interpStackEnd?
13778    ldr     lr, [rGLUE, #offGlue_pInterpBreak]
13779    ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
13780    blo     .LstackOverflow             @ yes, this frame will overflow stack
13781
13782    @ set up newSaveArea
13783    ldr     lr, [lr]                    @ lr<- active submodes
13784#ifdef EASY_GDB
13785    SAVEAREA_FROM_FP(ip, rFP)           @ ip<- stack save area
13786    str     ip, [r10, #offStackSaveArea_prevSave]
13787#endif
13788    str     rFP, [r10, #offStackSaveArea_prevFrame]
13789    str     rPC, [r10, #offStackSaveArea_savedPc]
13790#if defined(WITH_JIT)
13791    mov     r9, #0
13792    str     r9, [r10, #offStackSaveArea_returnAddr]
13793#endif
13794    ands    lr, #kSubModeMethodTrace    @ method tracing?
13795    beq     1f                          @ skip if not
13796    stmfd   sp!, {r0-r3}                @ preserve r0-r3
13797    mov     r1, r6
13798    @ r0=methodToCall, r1=rGlue
13799    bl      dvmFastMethodTraceEnter
13800    ldmfd   sp!, {r0-r3}                @ restore r0-r3
138011:
13802    str     r0, [r10, #offStackSaveArea_method]
13803    tst     r3, #ACC_NATIVE
13804    bne     .LinvokeNative
13805
13806    /*
13807    stmfd   sp!, {r0-r3}
13808    bl      common_printNewline
13809    mov     r0, rFP
13810    mov     r1, #0
13811    bl      dvmDumpFp
13812    ldmfd   sp!, {r0-r3}
13813    stmfd   sp!, {r0-r3}
13814    mov     r0, r1
13815    mov     r1, r10
13816    bl      dvmDumpFp
13817    bl      common_printNewline
13818    ldmfd   sp!, {r0-r3}
13819    */
13820
13821    ldrh    r9, [r2]                        @ r9 <- load INST from new PC
13822    ldr     r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
13823    mov     rPC, r2                         @ publish new rPC
13824    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
13825
13826    @ Update "glue" values for the new method
13827    @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
13828    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
13829    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
13830#if defined(WITH_JIT)
13831    GET_JIT_PROF_TABLE(r0)
13832    mov     rFP, r1                         @ fp = newFp
13833    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
13834    mov     rINST, r9                       @ publish new rINST
13835    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
13836    cmp     r0,#0
13837    bne     common_updateProfile
13838    GOTO_OPCODE(ip)                         @ jump to next instruction
13839#else
13840    mov     rFP, r1                         @ fp = newFp
13841    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
13842    mov     rINST, r9                       @ publish new rINST
13843    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
13844    GOTO_OPCODE(ip)                         @ jump to next instruction
13845#endif
13846
13847.LinvokeNative:
13848    @ Prep for the native call
13849    @ r0=methodToCall, r1=newFp, r10=newSaveArea
13850    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
13851    ldr     lr, [rGLUE, #offGlue_pInterpBreak]
13852    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
13853    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
13854    str     r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
13855    ldr     lr, [lr]                    @ lr<- active submodes
13856    mov     r9, r3                      @ r9<- glue->self (preserve)
13857
13858    mov     r2, r0                      @ r2<- methodToCall
13859    mov     r0, r1                      @ r0<- newFp (points to args)
13860    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
13861
13862#ifdef ASSIST_DEBUGGER
13863    /* insert fake function header to help gdb find the stack frame */
13864    b       .Lskip
13865    .type   dalvik_mterp, %function
13866dalvik_mterp:
13867    .fnstart
13868    MTERP_ENTRY1
13869    MTERP_ENTRY2
13870.Lskip:
13871#endif
13872
13873    ands    lr, #kSubModeMethodTrace    @ method tracing?
13874    beq     110f                        @ hop if not
13875    @ r2=JNIMethod, r6=rGLUE
13876    stmfd   sp!, {r2,r6}
13877
13878    mov     lr, pc                      @ set return addr
13879    ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
13880
13881    @ r0=JNIMethod, r1=rGLUE
13882    ldmfd   sp!, {r0-r1}
13883    bl      dvmFastNativeMethodTraceExit
13884    @ r2=JNIMethod, r6=rGLUE
13885    stmfd   sp!, {r2,r6}
13886    b       220f
13887110:
13888    mov     lr, pc                      @ set return addr
13889    ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
13890220:
13891#if defined(WITH_JIT)
13892    ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status
13893#endif
13894
13895    @ native return; r9=self, r10=newSaveArea
13896    @ equivalent to dvmPopJniLocals
13897    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
13898    ldr     r1, [r9, #offThread_exception] @ check for exception
13899#if defined(WITH_JIT)
13900    ldr     r3, [r3]                    @ r3 <- gDvmJit.pProfTable
13901#endif
13902    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
13903    cmp     r1, #0                      @ null?
13904    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
13905#if defined(WITH_JIT)
13906    str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch
13907#endif
13908    bne     common_exceptionThrown      @ no, handle exception
13909
13910    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
13911    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
13912    GOTO_OPCODE(ip)                     @ jump to next instruction
13913
13914.LstackOverflow:    @ r0=methodToCall
13915    mov     r1, r0                      @ r1<- methodToCall
13916    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
13917    bl      dvmHandleStackOverflow
13918    b       common_exceptionThrown
13919#ifdef ASSIST_DEBUGGER
13920    .fnend
13921#endif
13922
13923
13924    /*
13925     * Common code for method invocation, calling through "glue code".
13926     *
13927     * TODO: now that we have range and non-range invoke handlers, this
13928     *       needs to be split into two.  Maybe just create entry points
13929     *       that set r9 and jump here?
13930     *
13931     * On entry:
13932     *  r0 is "Method* methodToCall", the method we're trying to call
13933     *  r9 is "bool methodCallRange", indicating if this is a /range variant
13934     */
13935     .if    0
13936.LinvokeOld:
13937    sub     sp, sp, #8                  @ space for args + pad
13938    FETCH(ip, 2)                        @ ip<- FEDC or CCCC
13939    mov     r2, r0                      @ A2<- methodToCall
13940    mov     r0, rGLUE                   @ A0<- glue
13941    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
13942    mov     r1, r9                      @ A1<- methodCallRange
13943    mov     r3, rINST, lsr #8           @ A3<- AA
13944    str     ip, [sp, #0]                @ A4<- ip
13945    bl      dvmMterp_invokeMethod       @ call the C invokeMethod
13946    add     sp, sp, #8                  @ remove arg area
13947    b       common_resumeAfterGlueCall  @ continue to next instruction
13948    .endif
13949
13950
13951
13952/*
13953 * Common code for handling a return instruction.
13954 *
13955 * This does not return.
13956 */
13957common_returnFromMethod:
13958.LreturnNew:
13959    mov     r0, #kInterpEntryReturn
13960    mov     r9, #0
13961    bl      common_periodicChecks
13962
13963    ldr     lr, [rGLUE, #offGlue_pInterpBreak]
13964    SAVEAREA_FROM_FP(r0, rFP)
13965    ldr     lr, [lr]                    @ lr<- active submodes
13966    ldr     r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
13967    ands    lr, #kSubModeMethodTrace    @ method tracing?
13968    beq     333f
13969    stmfd   sp!, {r0-r3}                @ preserve r0-r3
13970    mov     r0, r6
13971    @ r0=rGlue
13972    bl      dvmFastJavaMethodTraceExit
13973    ldmfd   sp!, {r0-r3}                @ restore r0-r3
13974333:
13975    ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
13976    ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
13977    ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
13978                                        @ r2<- method we're returning to
13979    cmp     r2, #0                      @ is this a break frame?
13980#if defined(WORKAROUND_CORTEX_A9_745320)
13981    /* Don't use conditional loads if the HW defect exists */
13982    beq     101f
13983    ldr     r10, [r2, #offMethod_clazz] @ r10<- method->clazz
13984101:
13985#else
13986    ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
13987#endif
13988    mov     r1, #0                      @ "want switch" = false
13989    beq     common_gotoBail             @ break frame, bail out completely
13990
13991    PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
13992    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
13993    ldr     r1, [r10, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
13994    str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
13995#if defined(WITH_JIT)
13996    ldr     r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr
13997    mov     rPC, r9                     @ publish new rPC
13998    str     r1, [rGLUE, #offGlue_methodClassDex]
13999    str     r10, [r3, #offThread_inJitCodeCache]  @ may return to JIT'ed land
14000    cmp     r10, #0                      @ caller is compiled code
14001    blxne   r10
14002    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
14003    GOTO_OPCODE(ip)                     @ jump to next instruction
14004#else
14005    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
14006    mov     rPC, r9                     @ publish new rPC
14007    str     r1, [rGLUE, #offGlue_methodClassDex]
14008    GOTO_OPCODE(ip)                     @ jump to next instruction
14009#endif
14010
14011    /*
14012     * Return handling, calls through "glue code".
14013     */
14014     .if    0
14015.LreturnOld:
14016    SAVE_PC_FP_TO_GLUE()                @ export state
14017    mov     r0, rGLUE                   @ arg to function
14018    bl      dvmMterp_returnFromMethod
14019    b       common_resumeAfterGlueCall
14020    .endif
14021
14022
14023/*
14024 * Somebody has thrown an exception.  Handle it.
14025 *
14026 * If the exception processing code returns to us (instead of falling
14027 * out of the interpreter), continue with whatever the next instruction
14028 * now happens to be.
14029 *
14030 * This does not return.
14031 */
14032     .global dvmMterpCommonExceptionThrown
14033dvmMterpCommonExceptionThrown:
14034common_exceptionThrown:
14035.LexceptionNew:
14036    mov     r0, #kInterpEntryThrow
14037    mov     r9, #0
14038    bl      common_periodicChecks
14039
14040    ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
14041    ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
14042    mov     r1, r10                     @ r1<- self
14043    mov     r0, r9                      @ r0<- exception
14044    bl      dvmAddTrackedAlloc          @ don't let the exception be GCed
14045    mov     r3, #0                      @ r3<- NULL
14046    str     r3, [r10, #offThread_exception] @ self->exception = NULL
14047
14048    /* set up args and a local for "&fp" */
14049    /* (str sp, [sp, #-4]!  would be perfect here, but is discouraged) */
14050    str     rFP, [sp, #-4]!             @ *--sp = fp
14051    mov     ip, sp                      @ ip<- &fp
14052    mov     r3, #0                      @ r3<- false
14053    str     ip, [sp, #-4]!              @ *--sp = &fp
14054    ldr     r1, [rGLUE, #offGlue_method] @ r1<- glue->method
14055    mov     r0, r10                     @ r0<- self
14056    ldr     r1, [r1, #offMethod_insns]  @ r1<- method->insns
14057    mov     r2, r9                      @ r2<- exception
14058    sub     r1, rPC, r1                 @ r1<- pc - method->insns
14059    mov     r1, r1, asr #1              @ r1<- offset in code units
14060
14061    /* call, r0 gets catchRelPc (a code-unit offset) */
14062    bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
14063
14064    /* fix earlier stack overflow if necessary; may trash rFP */
14065    ldrb    r1, [r10, #offThread_stackOverflowed]
14066    cmp     r1, #0                      @ did we overflow earlier?
14067    beq     1f                          @ no, skip ahead
14068    mov     rFP, r0                     @ save relPc result in rFP
14069    mov     r0, r10                     @ r0<- self
14070    mov     r1, r9                      @ r1<- exception
14071    bl      dvmCleanupStackOverflow     @ call(self)
14072    mov     r0, rFP                     @ restore result
140731:
14074
14075    /* update frame pointer and check result from dvmFindCatchBlock */
14076    ldr     rFP, [sp, #4]               @ retrieve the updated rFP
14077    cmp     r0, #0                      @ is catchRelPc < 0?
14078    add     sp, sp, #8                  @ restore stack
14079    bmi     .LnotCaughtLocally
14080
14081    /* adjust locals to match self->curFrame and updated PC */
14082    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
14083    ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
14084    str     r1, [rGLUE, #offGlue_method]    @ glue->method = new method
14085    ldr     r2, [r1, #offMethod_clazz]      @ r2<- method->clazz
14086    ldr     r3, [r1, #offMethod_insns]      @ r3<- method->insns
14087    ldr     r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
14088    add     rPC, r3, r0, asl #1             @ rPC<- method->insns + catchRelPc
14089    str     r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
14090
14091    /* release the tracked alloc on the exception */
14092    mov     r0, r9                      @ r0<- exception
14093    mov     r1, r10                     @ r1<- self
14094    bl      dvmReleaseTrackedAlloc      @ release the exception
14095
14096    /* restore the exception if the handler wants it */
14097    FETCH_INST()                        @ load rINST from rPC
14098    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
14099    cmp     ip, #OP_MOVE_EXCEPTION      @ is it "move-exception"?
14100    streq   r9, [r10, #offThread_exception] @ yes, restore the exception
14101    GOTO_OPCODE(ip)                     @ jump to next instruction
14102
14103.LnotCaughtLocally: @ r9=exception, r10=self
14104    /* fix stack overflow if necessary */
14105    ldrb    r1, [r10, #offThread_stackOverflowed]
14106    cmp     r1, #0                      @ did we overflow earlier?
14107    movne   r0, r10                     @ if yes: r0<- self
14108    movne   r1, r9                      @ if yes: r1<- exception
14109    blne    dvmCleanupStackOverflow     @ if yes: call(self)
14110
14111    @ may want to show "not caught locally" debug messages here
14112#if DVM_SHOW_EXCEPTION >= 2
14113    /* call __android_log_print(prio, tag, format, ...) */
14114    /* "Exception %s from %s:%d not caught locally" */
14115    @ dvmLineNumFromPC(method, pc - method->insns)
14116    ldr     r0, [rGLUE, #offGlue_method]
14117    ldr     r1, [r0, #offMethod_insns]
14118    sub     r1, rPC, r1
14119    asr     r1, r1, #1
14120    bl      dvmLineNumFromPC
14121    str     r0, [sp, #-4]!
14122    @ dvmGetMethodSourceFile(method)
14123    ldr     r0, [rGLUE, #offGlue_method]
14124    bl      dvmGetMethodSourceFile
14125    str     r0, [sp, #-4]!
14126    @ exception->clazz->descriptor
14127    ldr     r3, [r9, #offObject_clazz]
14128    ldr     r3, [r3, #offClassObject_descriptor]
14129    @
14130    ldr     r2, strExceptionNotCaughtLocally
14131    ldr     r1, strLogTag
14132    mov     r0, #3                      @ LOG_DEBUG
14133    bl      __android_log_print
14134#endif
14135    str     r9, [r10, #offThread_exception] @ restore exception
14136    mov     r0, r9                      @ r0<- exception
14137    mov     r1, r10                     @ r1<- self
14138    bl      dvmReleaseTrackedAlloc      @ release the exception
14139    mov     r1, #0                      @ "want switch" = false
14140    b       common_gotoBail             @ bail out
14141
14142
14143    /*
14144     * Exception handling, calls through "glue code".
14145     */
14146    .if     0
14147.LexceptionOld:
14148    SAVE_PC_FP_TO_GLUE()                @ export state
14149    mov     r0, rGLUE                   @ arg to function
14150    bl      dvmMterp_exceptionThrown
14151    b       common_resumeAfterGlueCall
14152    .endif
14153
14154
14155/*
14156 * After returning from a "glued" function, pull out the updated
14157 * values and start executing at the next instruction.
14158 */
14159common_resumeAfterGlueCall:
14160    LOAD_PC_FP_FROM_GLUE()              @ pull rPC and rFP out of glue
14161    FETCH_INST()                        @ load rINST from rPC
14162    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
14163    GOTO_OPCODE(ip)                     @ jump to next instruction
14164
14165/*
14166 * Invalid array index. Note that our calling convention is strange; we use r1
14167 * and r3 because those just happen to be the registers all our callers are
14168 * using. We shuffle them here before calling the C function.
14169 * r1: index
14170 * r3: size
14171 */
14172common_errArrayIndex:
14173    EXPORT_PC()
14174    mov     r0, r1
14175    mov     r1, r3
14176    bl      dvmThrowAIOOBE
14177    b       common_exceptionThrown
14178
14179/*
14180 * Integer divide or mod by zero.
14181 */
14182common_errDivideByZero:
14183    EXPORT_PC()
14184    ldr     r0, strArithmeticException
14185    ldr     r1, strDivideByZero
14186    bl      dvmThrowException
14187    b       common_exceptionThrown
14188
14189/*
14190 * Attempt to allocate an array with a negative size.
14191 */
14192common_errNegativeArraySize:
14193    EXPORT_PC()
14194    ldr     r0, strNegativeArraySizeException
14195    mov     r1, #0
14196    bl      dvmThrowException
14197    b       common_exceptionThrown
14198
14199/*
14200 * Invocation of a non-existent method.
14201 */
14202common_errNoSuchMethod:
14203    EXPORT_PC()
14204    ldr     r0, strNoSuchMethodError
14205    mov     r1, #0
14206    bl      dvmThrowException
14207    b       common_exceptionThrown
14208
14209/*
14210 * We encountered a null object when we weren't expecting one.  We
14211 * export the PC, throw a NullPointerException, and goto the exception
14212 * processing code.
14213 */
14214common_errNullObject:
14215    EXPORT_PC()
14216    ldr     r0, strNullPointerException
14217    mov     r1, #0
14218    bl      dvmThrowException
14219    b       common_exceptionThrown
14220
14221/*
14222 * For debugging, cause an immediate fault.  The source address will
14223 * be in lr (use a bl instruction to jump here).
14224 */
14225common_abort:
14226    ldr     pc, .LdeadFood
14227.LdeadFood:
14228    .word   0xdeadf00d
14229
14230/*
14231 * Spit out a "we were here", preserving all registers.  (The attempt
14232 * to save ip won't work, but we need to save an even number of
14233 * registers for EABI 64-bit stack alignment.)
14234 */
14235    .macro  SQUEAK num
14236common_squeak\num:
14237    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
14238    ldr     r0, strSqueak
14239    mov     r1, #\num
14240    bl      printf
14241    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
14242    bx      lr
14243    .endm
14244
14245    SQUEAK  0
14246    SQUEAK  1
14247    SQUEAK  2
14248    SQUEAK  3
14249    SQUEAK  4
14250    SQUEAK  5
14251
14252/*
14253 * Spit out the number in r0, preserving registers.
14254 */
14255common_printNum:
14256    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
14257    mov     r1, r0
14258    ldr     r0, strSqueak
14259    bl      printf
14260    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
14261    bx      lr
14262
14263/*
14264 * Print a newline, preserving registers.
14265 */
14266common_printNewline:
14267    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
14268    ldr     r0, strNewline
14269    bl      printf
14270    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
14271    bx      lr
14272
14273    /*
14274     * Print the 32-bit quantity in r0 as a hex value, preserving registers.
14275     */
14276common_printHex:
14277    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
14278    mov     r1, r0
14279    ldr     r0, strPrintHex
14280    bl      printf
14281    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
14282    bx      lr
14283
14284/*
14285 * Print the 64-bit quantity in r0-r1, preserving registers.
14286 */
14287common_printLong:
14288    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
14289    mov     r3, r1
14290    mov     r2, r0
14291    ldr     r0, strPrintLong
14292    bl      printf
14293    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
14294    bx      lr
14295
14296/*
14297 * Print full method info.  Pass the Method* in r0.  Preserves regs.
14298 */
14299common_printMethod:
14300    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
14301    bl      dvmMterpPrintMethod
14302    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
14303    bx      lr
14304
14305/*
14306 * Call a C helper function that dumps regs and possibly some
14307 * additional info.  Requires the C function to be compiled in.
14308 */
14309    .if     0
14310common_dumpRegs:
14311    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
14312    bl      dvmMterpDumpArmRegs
14313    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
14314    bx      lr
14315    .endif
14316
14317#if 0
14318/*
14319 * Experiment on VFP mode.
14320 *
14321 * uint32_t setFPSCR(uint32_t val, uint32_t mask)
14322 *
14323 * Updates the bits specified by "mask", setting them to the values in "val".
14324 */
14325setFPSCR:
14326    and     r0, r0, r1                  @ make sure no stray bits are set
14327    fmrx    r2, fpscr                   @ get VFP reg
14328    mvn     r1, r1                      @ bit-invert mask
14329    and     r2, r2, r1                  @ clear masked bits
14330    orr     r2, r2, r0                  @ set specified bits
14331    fmxr    fpscr, r2                   @ set VFP reg
14332    mov     r0, r2                      @ return new value
14333    bx      lr
14334
14335    .align  2
14336    .global dvmConfigureFP
14337    .type   dvmConfigureFP, %function
14338dvmConfigureFP:
14339    stmfd   sp!, {ip, lr}
14340    /* 0x03000000 sets DN/FZ */
14341    /* 0x00009f00 clears the six exception enable flags */
14342    bl      common_squeak0
14343    mov     r0, #0x03000000             @ r0<- 0x03000000
14344    add     r1, r0, #0x9f00             @ r1<- 0x03009f00
14345    bl      setFPSCR
14346    ldmfd   sp!, {ip, pc}
14347#endif
14348
14349
14350/*
14351 * String references, must be close to the code that uses them.
14352 */
14353    .align  2
14354strArithmeticException:
14355    .word   .LstrArithmeticException
14356strDivideByZero:
14357    .word   .LstrDivideByZero
14358strNegativeArraySizeException:
14359    .word   .LstrNegativeArraySizeException
14360strNoSuchMethodError:
14361    .word   .LstrNoSuchMethodError
14362strNullPointerException:
14363    .word   .LstrNullPointerException
14364
14365strLogTag:
14366    .word   .LstrLogTag
14367strExceptionNotCaughtLocally:
14368    .word   .LstrExceptionNotCaughtLocally
14369
14370strNewline:
14371    .word   .LstrNewline
14372strSqueak:
14373    .word   .LstrSqueak
14374strPrintHex:
14375    .word   .LstrPrintHex
14376strPrintLong:
14377    .word   .LstrPrintLong
14378
14379/*
14380 * Zero-terminated ASCII string data.
14381 *
14382 * On ARM we have two choices: do like gcc does, and LDR from a .word
14383 * with the address, or use an ADR pseudo-op to get the address
14384 * directly.  ADR saves 4 bytes and an indirection, but it's using a
14385 * PC-relative addressing mode and hence has a limited range, which
14386 * makes it not work well with mergeable string sections.
14387 */
14388    .section .rodata.str1.4,"aMS",%progbits,1
14389
14390.LstrBadEntryPoint:
14391    .asciz  "Bad entry point %d\n"
14392.LstrArithmeticException:
14393    .asciz  "Ljava/lang/ArithmeticException;"
14394.LstrDivideByZero:
14395    .asciz  "divide by zero"
14396.LstrFilledNewArrayNotImpl:
14397    .asciz  "filled-new-array only implemented for objects and 'int'"
14398.LstrInternalError:
14399    .asciz  "Ljava/lang/InternalError;"
14400.LstrInstantiationError:
14401    .asciz  "Ljava/lang/InstantiationError;"
14402.LstrNegativeArraySizeException:
14403    .asciz  "Ljava/lang/NegativeArraySizeException;"
14404.LstrNoSuchMethodError:
14405    .asciz  "Ljava/lang/NoSuchMethodError;"
14406.LstrNullPointerException:
14407    .asciz  "Ljava/lang/NullPointerException;"
14408
14409.LstrLogTag:
14410    .asciz  "mterp"
14411.LstrExceptionNotCaughtLocally:
14412    .asciz  "Exception %s from %s:%d not caught locally\n"
14413
14414.LstrNewline:
14415    .asciz  "\n"
14416.LstrSqueak:
14417    .asciz  "<%d>"
14418.LstrPrintHex:
14419    .asciz  "<0x%x>"
14420.LstrPrintLong:
14421    .asciz  "<%lld>"
14422
14423