InterpAsm-armv7-a.S revision 18fba346582c08d81aa96d9508c0e935bad5f36f
1/*
2 * This file was generated automatically by gen-mterp.py for 'armv7-a'.
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: armv7-a/platform.S */
210/*
211 * ===========================================================================
212 *  CPU-version-specific defines
213 * ===========================================================================
214 */
215
216#if !defined(ANDROID_SMP)
217# error "Must define ANDROID_SMP"
218#endif
219
220/*
221 * Macro for data memory barrier.
222 */
223.macro  SMP_DMB
224#if ANDROID_SMP != 0
225    dmb
226#else
227    /* not SMP */
228#endif
229.endm
230
231/*
232 * Macro for data memory barrier (store/store variant).
233 */
234.macro  SMP_DMB_ST
235#if ANDROID_SMP != 0
236    dmb     st
237#else
238    /* not SMP */
239#endif
240.endm
241
242/* File: armv5te/entry.S */
243/*
244 * Copyright (C) 2008 The Android Open Source Project
245 *
246 * Licensed under the Apache License, Version 2.0 (the "License");
247 * you may not use this file except in compliance with the License.
248 * You may obtain a copy of the License at
249 *
250 *      http://www.apache.org/licenses/LICENSE-2.0
251 *
252 * Unless required by applicable law or agreed to in writing, software
253 * distributed under the License is distributed on an "AS IS" BASIS,
254 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
255 * See the License for the specific language governing permissions and
256 * limitations under the License.
257 */
258/*
259 * Interpreter entry point.
260 */
261
262/*
263 * We don't have formal stack frames, so gdb scans upward in the code
264 * to find the start of the function (a label with the %function type),
265 * and then looks at the next few instructions to figure out what
266 * got pushed onto the stack.  From this it figures out how to restore
267 * the registers, including PC, for the previous stack frame.  If gdb
268 * sees a non-function label, it stops scanning, so either we need to
269 * have nothing but assembler-local labels between the entry point and
270 * the break, or we need to fake it out.
271 *
272 * When this is defined, we add some stuff to make gdb less confused.
273 */
274#define ASSIST_DEBUGGER 1
275
276    .text
277    .align  2
278    .global dvmMterpStdRun
279    .type   dvmMterpStdRun, %function
280
281/*
282 * On entry:
283 *  r0  MterpGlue* glue
284 *
285 * This function returns a boolean "changeInterp" value.  The return comes
286 * via a call to dvmMterpStdBail().
287 */
288dvmMterpStdRun:
289#define MTERP_ENTRY1 \
290    .save {r4-r10,fp,lr}; \
291    stmfd   sp!, {r4-r10,fp,lr}         @ save 9 regs
292#define MTERP_ENTRY2 \
293    .pad    #4; \
294    sub     sp, sp, #4                  @ align 64
295
296    .fnstart
297    MTERP_ENTRY1
298    MTERP_ENTRY2
299
300    /* save stack pointer, add magic word for debuggerd */
301    str     sp, [r0, #offGlue_bailPtr]  @ save SP for eventual return
302
303    /* set up "named" registers, figure out entry point */
304    mov     rGLUE, r0                   @ set rGLUE
305    ldr     r1, [r0, #offGlue_entryPoint]   @ enum is 4 bytes in aapcs-EABI
306    LOAD_PC_FP_FROM_GLUE()              @ load rPC and rFP from "glue"
307    adr     rIBASE, dvmAsmInstructionStart  @ set rIBASE
308    cmp     r1, #kInterpEntryInstr      @ usual case?
309    bne     .Lnot_instr                 @ no, handle it
310
311#if defined(WITH_JIT)
312.LentryInstr:
313    ldr     r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
314    /* Entry is always a possible trace start */
315    GET_JIT_PROF_TABLE(r0)
316    FETCH_INST()
317    mov     r1, #0                      @ prepare the value for the new state
318    str     r1, [r10, #offThread_inJitCodeCache] @ back to the interp land
319    cmp     r0,#0                       @ is profiling disabled?
320#if !defined(WITH_SELF_VERIFICATION)
321    bne     common_updateProfile        @ profiling is enabled
322#else
323    ldr     r2, [r10, #offThread_shadowSpace]   @ to find out the jit exit state
324    beq     1f                          @ profiling is disabled
325    ldr     r3, [r2, #offShadowSpace_jitExitState]  @ jit exit state
326    cmp     r3, #kSVSTraceSelect        @ hot trace following?
327    moveq   r2,#kJitTSelectRequestHot   @ ask for trace selection
328    beq     common_selectTrace          @ go build the trace
329    cmp     r3, #kSVSNoProfile          @ don't profile the next instruction?
330    beq     1f                          @ intrepret the next instruction
331    b       common_updateProfile        @ collect profiles
332#endif
3331:
334    GET_INST_OPCODE(ip)
335    GOTO_OPCODE(ip)
336#else
337    /* start executing the instruction at rPC */
338    FETCH_INST()                        @ load rINST from rPC
339    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
340    GOTO_OPCODE(ip)                     @ jump to next instruction
341#endif
342
343.Lnot_instr:
344    cmp     r1, #kInterpEntryReturn     @ were we returning from a method?
345    beq     common_returnFromMethod
346
347.Lnot_return:
348    cmp     r1, #kInterpEntryThrow      @ were we throwing an exception?
349    beq     common_exceptionThrown
350
351#if defined(WITH_JIT)
352.Lnot_throw:
353    ldr     r10,[rGLUE, #offGlue_jitResumeNPC]
354    ldr     r2,[rGLUE, #offGlue_jitResumeDPC]
355    cmp     r1, #kInterpEntryResume     @ resuming after Jit single-step?
356    bne     .Lbad_arg
357    cmp     rPC,r2
358    bne     .LentryInstr                @ must have branched, don't resume
359#if defined(WITH_SELF_VERIFICATION)
360    @ glue->entryPoint will be set in dvmSelfVerificationSaveState
361    b       jitSVShadowRunStart         @ re-enter the translation after the
362                                        @ single-stepped instruction
363    @noreturn
364#endif
365    mov     r1, #kInterpEntryInstr
366    str     r1, [rGLUE, #offGlue_entryPoint]
367    bx      r10                         @ re-enter the translation
368#endif
369
370.Lbad_arg:
371    ldr     r0, strBadEntryPoint
372    @ r1 holds value of entryPoint
373    bl      printf
374    bl      dvmAbort
375    .fnend
376
377
378    .global dvmMterpStdBail
379    .type   dvmMterpStdBail, %function
380
381/*
382 * Restore the stack pointer and PC from the save point established on entry.
383 * This is essentially the same as a longjmp, but should be cheaper.  The
384 * last instruction causes us to return to whoever called dvmMterpStdRun.
385 *
386 * We pushed some registers on the stack in dvmMterpStdRun, then saved
387 * SP and LR.  Here we restore SP, restore the registers, and then restore
388 * LR to PC.
389 *
390 * On entry:
391 *  r0  MterpGlue* glue
392 *  r1  bool changeInterp
393 */
394dvmMterpStdBail:
395    ldr     sp, [r0, #offGlue_bailPtr]      @ sp<- saved SP
396    mov     r0, r1                          @ return the changeInterp value
397    add     sp, sp, #4                      @ un-align 64
398    ldmfd   sp!, {r4-r10,fp,pc}             @ restore 9 regs and return
399
400
401/*
402 * String references.
403 */
404strBadEntryPoint:
405    .word   .LstrBadEntryPoint
406
407
408    .global dvmAsmInstructionStart
409    .type   dvmAsmInstructionStart, %function
410dvmAsmInstructionStart = .L_OP_NOP
411    .text
412
413/* ------------------------------ */
414    .balign 64
415.L_OP_NOP: /* 0x00 */
416/* File: armv5te/OP_NOP.S */
417    FETCH_ADVANCE_INST(1)               @ advance to next instr, load rINST
418    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
419    GOTO_OPCODE(ip)                     @ execute it
420
421#ifdef ASSIST_DEBUGGER
422    /* insert fake function header to help gdb find the stack frame */
423    .type   dalvik_inst, %function
424dalvik_inst:
425    .fnstart
426    MTERP_ENTRY1
427    MTERP_ENTRY2
428    .fnend
429#endif
430
431/* ------------------------------ */
432    .balign 64
433.L_OP_MOVE: /* 0x01 */
434/* File: armv6t2/OP_MOVE.S */
435    /* for move, move-object, long-to-int */
436    /* op vA, vB */
437    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
438    ubfx    r0, rINST, #8, #4           @ r0<- A from 11:8
439    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
440    GET_VREG(r2, r1)                    @ r2<- fp[B]
441    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
442    SET_VREG(r2, r0)                    @ fp[A]<- r2
443    GOTO_OPCODE(ip)                     @ execute next instruction
444
445/* ------------------------------ */
446    .balign 64
447.L_OP_MOVE_FROM16: /* 0x02 */
448/* File: armv5te/OP_MOVE_FROM16.S */
449    /* for: move/from16, move-object/from16 */
450    /* op vAA, vBBBB */
451    FETCH(r1, 1)                        @ r1<- BBBB
452    mov     r0, rINST, lsr #8           @ r0<- AA
453    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
454    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
455    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
456    SET_VREG(r2, r0)                    @ fp[AA]<- r2
457    GOTO_OPCODE(ip)                     @ jump to next instruction
458
459/* ------------------------------ */
460    .balign 64
461.L_OP_MOVE_16: /* 0x03 */
462/* File: armv5te/OP_MOVE_16.S */
463    /* for: move/16, move-object/16 */
464    /* op vAAAA, vBBBB */
465    FETCH(r1, 2)                        @ r1<- BBBB
466    FETCH(r0, 1)                        @ r0<- AAAA
467    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
468    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
469    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
470    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
471    GOTO_OPCODE(ip)                     @ jump to next instruction
472
473/* ------------------------------ */
474    .balign 64
475.L_OP_MOVE_WIDE: /* 0x04 */
476/* File: armv6t2/OP_MOVE_WIDE.S */
477    /* move-wide vA, vB */
478    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
479    mov     r3, rINST, lsr #12          @ r3<- B
480    ubfx    r2, rINST, #8, #4           @ r2<- A
481    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
482    add     r2, rFP, r2, lsl #2         @ r2<- &fp[A]
483    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[B]
484    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
485    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
486    stmia   r2, {r0-r1}                 @ fp[A]<- r0/r1
487    GOTO_OPCODE(ip)                     @ jump to next instruction
488
489/* ------------------------------ */
490    .balign 64
491.L_OP_MOVE_WIDE_FROM16: /* 0x05 */
492/* File: armv5te/OP_MOVE_WIDE_FROM16.S */
493    /* move-wide/from16 vAA, vBBBB */
494    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
495    FETCH(r3, 1)                        @ r3<- BBBB
496    mov     r2, rINST, lsr #8           @ r2<- AA
497    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
498    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
499    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
500    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
501    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
502    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
503    GOTO_OPCODE(ip)                     @ jump to next instruction
504
505/* ------------------------------ */
506    .balign 64
507.L_OP_MOVE_WIDE_16: /* 0x06 */
508/* File: armv5te/OP_MOVE_WIDE_16.S */
509    /* move-wide/16 vAAAA, vBBBB */
510    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
511    FETCH(r3, 2)                        @ r3<- BBBB
512    FETCH(r2, 1)                        @ r2<- AAAA
513    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
514    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AAAA]
515    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
516    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
517    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
518    stmia   r2, {r0-r1}                 @ fp[AAAA]<- r0/r1
519    GOTO_OPCODE(ip)                     @ jump to next instruction
520
521/* ------------------------------ */
522    .balign 64
523.L_OP_MOVE_OBJECT: /* 0x07 */
524/* File: armv5te/OP_MOVE_OBJECT.S */
525/* File: armv5te/OP_MOVE.S */
526    /* for move, move-object, long-to-int */
527    /* op vA, vB */
528    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
529    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
530    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
531    GET_VREG(r2, r1)                    @ r2<- fp[B]
532    and     r0, r0, #15
533    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
534    SET_VREG(r2, r0)                    @ fp[A]<- r2
535    GOTO_OPCODE(ip)                     @ execute next instruction
536
537
538/* ------------------------------ */
539    .balign 64
540.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
541/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */
542/* File: armv5te/OP_MOVE_FROM16.S */
543    /* for: move/from16, move-object/from16 */
544    /* op vAA, vBBBB */
545    FETCH(r1, 1)                        @ r1<- BBBB
546    mov     r0, rINST, lsr #8           @ r0<- AA
547    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
548    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
549    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
550    SET_VREG(r2, r0)                    @ fp[AA]<- r2
551    GOTO_OPCODE(ip)                     @ jump to next instruction
552
553
554/* ------------------------------ */
555    .balign 64
556.L_OP_MOVE_OBJECT_16: /* 0x09 */
557/* File: armv5te/OP_MOVE_OBJECT_16.S */
558/* File: armv5te/OP_MOVE_16.S */
559    /* for: move/16, move-object/16 */
560    /* op vAAAA, vBBBB */
561    FETCH(r1, 2)                        @ r1<- BBBB
562    FETCH(r0, 1)                        @ r0<- AAAA
563    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
564    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
565    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
566    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
567    GOTO_OPCODE(ip)                     @ jump to next instruction
568
569
570/* ------------------------------ */
571    .balign 64
572.L_OP_MOVE_RESULT: /* 0x0a */
573/* File: armv5te/OP_MOVE_RESULT.S */
574    /* for: move-result, move-result-object */
575    /* op vAA */
576    mov     r2, rINST, lsr #8           @ r2<- AA
577    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
578    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
579    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
580    SET_VREG(r0, r2)                    @ fp[AA]<- r0
581    GOTO_OPCODE(ip)                     @ jump to next instruction
582
583/* ------------------------------ */
584    .balign 64
585.L_OP_MOVE_RESULT_WIDE: /* 0x0b */
586/* File: armv5te/OP_MOVE_RESULT_WIDE.S */
587    /* move-result-wide vAA */
588    mov     r2, rINST, lsr #8           @ r2<- AA
589    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
590    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
591    ldmia   r3, {r0-r1}                 @ r0/r1<- retval.j
592    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
593    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
594    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
595    GOTO_OPCODE(ip)                     @ jump to next instruction
596
597/* ------------------------------ */
598    .balign 64
599.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
600/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */
601/* File: armv5te/OP_MOVE_RESULT.S */
602    /* for: move-result, move-result-object */
603    /* op vAA */
604    mov     r2, rINST, lsr #8           @ r2<- AA
605    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
606    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
607    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
608    SET_VREG(r0, r2)                    @ fp[AA]<- r0
609    GOTO_OPCODE(ip)                     @ jump to next instruction
610
611
612/* ------------------------------ */
613    .balign 64
614.L_OP_MOVE_EXCEPTION: /* 0x0d */
615/* File: armv5te/OP_MOVE_EXCEPTION.S */
616    /* move-exception vAA */
617    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
618    mov     r2, rINST, lsr #8           @ r2<- AA
619    ldr     r3, [r0, #offThread_exception]  @ r3<- dvmGetException bypass
620    mov     r1, #0                      @ r1<- 0
621    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
622    SET_VREG(r3, r2)                    @ fp[AA]<- exception obj
623    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
624    str     r1, [r0, #offThread_exception]  @ dvmClearException bypass
625    GOTO_OPCODE(ip)                     @ jump to next instruction
626
627/* ------------------------------ */
628    .balign 64
629.L_OP_RETURN_VOID: /* 0x0e */
630/* File: armv5te/OP_RETURN_VOID.S */
631    b       common_returnFromMethod
632
633/* ------------------------------ */
634    .balign 64
635.L_OP_RETURN: /* 0x0f */
636/* File: armv5te/OP_RETURN.S */
637    /*
638     * Return a 32-bit value.  Copies the return value into the "glue"
639     * structure, then jumps to the return handler.
640     *
641     * for: return, return-object
642     */
643    /* op vAA */
644    mov     r2, rINST, lsr #8           @ r2<- AA
645    GET_VREG(r0, r2)                    @ r0<- vAA
646    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
647    b       common_returnFromMethod
648
649/* ------------------------------ */
650    .balign 64
651.L_OP_RETURN_WIDE: /* 0x10 */
652/* File: armv5te/OP_RETURN_WIDE.S */
653    /*
654     * Return a 64-bit value.  Copies the return value into the "glue"
655     * structure, then jumps to the return handler.
656     */
657    /* return-wide vAA */
658    mov     r2, rINST, lsr #8           @ r2<- AA
659    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
660    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
661    ldmia   r2, {r0-r1}                 @ r0/r1 <- vAA/vAA+1
662    stmia   r3, {r0-r1}                 @ retval<- r0/r1
663    b       common_returnFromMethod
664
665/* ------------------------------ */
666    .balign 64
667.L_OP_RETURN_OBJECT: /* 0x11 */
668/* File: armv5te/OP_RETURN_OBJECT.S */
669/* File: armv5te/OP_RETURN.S */
670    /*
671     * Return a 32-bit value.  Copies the return value into the "glue"
672     * structure, then jumps to the return handler.
673     *
674     * for: return, return-object
675     */
676    /* op vAA */
677    mov     r2, rINST, lsr #8           @ r2<- AA
678    GET_VREG(r0, r2)                    @ r0<- vAA
679    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
680    b       common_returnFromMethod
681
682
683/* ------------------------------ */
684    .balign 64
685.L_OP_CONST_4: /* 0x12 */
686/* File: armv6t2/OP_CONST_4.S */
687    /* const/4 vA, #+B */
688    mov     r1, rINST, lsl #16          @ r1<- Bxxx0000
689    ubfx    r0, rINST, #8, #4           @ r0<- A
690    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
691    mov     r1, r1, asr #28             @ r1<- sssssssB (sign-extended)
692    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
693    SET_VREG(r1, r0)                    @ fp[A]<- r1
694    GOTO_OPCODE(ip)                     @ execute next instruction
695
696/* ------------------------------ */
697    .balign 64
698.L_OP_CONST_16: /* 0x13 */
699/* File: armv5te/OP_CONST_16.S */
700    /* const/16 vAA, #+BBBB */
701    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
702    mov     r3, rINST, lsr #8           @ r3<- AA
703    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
704    SET_VREG(r0, r3)                    @ vAA<- r0
705    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
706    GOTO_OPCODE(ip)                     @ jump to next instruction
707
708/* ------------------------------ */
709    .balign 64
710.L_OP_CONST: /* 0x14 */
711/* File: armv5te/OP_CONST.S */
712    /* const vAA, #+BBBBbbbb */
713    mov     r3, rINST, lsr #8           @ r3<- AA
714    FETCH(r0, 1)                        @ r0<- bbbb (low)
715    FETCH(r1, 2)                        @ r1<- BBBB (high)
716    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
717    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
718    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
719    SET_VREG(r0, r3)                    @ vAA<- r0
720    GOTO_OPCODE(ip)                     @ jump to next instruction
721
722/* ------------------------------ */
723    .balign 64
724.L_OP_CONST_HIGH16: /* 0x15 */
725/* File: armv5te/OP_CONST_HIGH16.S */
726    /* const/high16 vAA, #+BBBB0000 */
727    FETCH(r0, 1)                        @ r0<- 0000BBBB (zero-extended)
728    mov     r3, rINST, lsr #8           @ r3<- AA
729    mov     r0, r0, lsl #16             @ r0<- BBBB0000
730    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
731    SET_VREG(r0, r3)                    @ vAA<- r0
732    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
733    GOTO_OPCODE(ip)                     @ jump to next instruction
734
735/* ------------------------------ */
736    .balign 64
737.L_OP_CONST_WIDE_16: /* 0x16 */
738/* File: armv5te/OP_CONST_WIDE_16.S */
739    /* const-wide/16 vAA, #+BBBB */
740    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
741    mov     r3, rINST, lsr #8           @ r3<- AA
742    mov     r1, r0, asr #31             @ r1<- ssssssss
743    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
744    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
745    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
746    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
747    GOTO_OPCODE(ip)                     @ jump to next instruction
748
749/* ------------------------------ */
750    .balign 64
751.L_OP_CONST_WIDE_32: /* 0x17 */
752/* File: armv5te/OP_CONST_WIDE_32.S */
753    /* const-wide/32 vAA, #+BBBBbbbb */
754    FETCH(r0, 1)                        @ r0<- 0000bbbb (low)
755    mov     r3, rINST, lsr #8           @ r3<- AA
756    FETCH_S(r2, 2)                      @ r2<- ssssBBBB (high)
757    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
758    orr     r0, r0, r2, lsl #16         @ r0<- BBBBbbbb
759    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
760    mov     r1, r0, asr #31             @ r1<- ssssssss
761    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
762    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
763    GOTO_OPCODE(ip)                     @ jump to next instruction
764
765/* ------------------------------ */
766    .balign 64
767.L_OP_CONST_WIDE: /* 0x18 */
768/* File: armv5te/OP_CONST_WIDE.S */
769    /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
770    FETCH(r0, 1)                        @ r0<- bbbb (low)
771    FETCH(r1, 2)                        @ r1<- BBBB (low middle)
772    FETCH(r2, 3)                        @ r2<- hhhh (high middle)
773    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb (low word)
774    FETCH(r3, 4)                        @ r3<- HHHH (high)
775    mov     r9, rINST, lsr #8           @ r9<- AA
776    orr     r1, r2, r3, lsl #16         @ r1<- HHHHhhhh (high word)
777    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
778    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
779    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
780    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
781    GOTO_OPCODE(ip)                     @ jump to next instruction
782
783/* ------------------------------ */
784    .balign 64
785.L_OP_CONST_WIDE_HIGH16: /* 0x19 */
786/* File: armv5te/OP_CONST_WIDE_HIGH16.S */
787    /* const-wide/high16 vAA, #+BBBB000000000000 */
788    FETCH(r1, 1)                        @ r1<- 0000BBBB (zero-extended)
789    mov     r3, rINST, lsr #8           @ r3<- AA
790    mov     r0, #0                      @ r0<- 00000000
791    mov     r1, r1, lsl #16             @ r1<- BBBB0000
792    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
793    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
794    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
795    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
796    GOTO_OPCODE(ip)                     @ jump to next instruction
797
798/* ------------------------------ */
799    .balign 64
800.L_OP_CONST_STRING: /* 0x1a */
801/* File: armv5te/OP_CONST_STRING.S */
802    /* const/string vAA, String@BBBB */
803    FETCH(r1, 1)                        @ r1<- BBBB
804    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
805    mov     r9, rINST, lsr #8           @ r9<- AA
806    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
807    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
808    cmp     r0, #0                      @ not yet resolved?
809    beq     .LOP_CONST_STRING_resolve
810    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
811    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
812    SET_VREG(r0, r9)                    @ vAA<- r0
813    GOTO_OPCODE(ip)                     @ jump to next instruction
814
815/* ------------------------------ */
816    .balign 64
817.L_OP_CONST_STRING_JUMBO: /* 0x1b */
818/* File: armv5te/OP_CONST_STRING_JUMBO.S */
819    /* const/string vAA, String@BBBBBBBB */
820    FETCH(r0, 1)                        @ r0<- bbbb (low)
821    FETCH(r1, 2)                        @ r1<- BBBB (high)
822    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
823    mov     r9, rINST, lsr #8           @ r9<- AA
824    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
825    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
826    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
827    cmp     r0, #0
828    beq     .LOP_CONST_STRING_JUMBO_resolve
829    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
830    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
831    SET_VREG(r0, r9)                    @ vAA<- r0
832    GOTO_OPCODE(ip)                     @ jump to next instruction
833
834/* ------------------------------ */
835    .balign 64
836.L_OP_CONST_CLASS: /* 0x1c */
837/* File: armv5te/OP_CONST_CLASS.S */
838    /* const/class vAA, Class@BBBB */
839    FETCH(r1, 1)                        @ r1<- BBBB
840    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
841    mov     r9, rINST, lsr #8           @ r9<- AA
842    ldr     r2, [r2, #offDvmDex_pResClasses]   @ r2<- dvmDex->pResClasses
843    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResClasses[BBBB]
844    cmp     r0, #0                      @ not yet resolved?
845    beq     .LOP_CONST_CLASS_resolve
846    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
847    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
848    SET_VREG(r0, r9)                    @ vAA<- r0
849    GOTO_OPCODE(ip)                     @ jump to next instruction
850
851/* ------------------------------ */
852    .balign 64
853.L_OP_MONITOR_ENTER: /* 0x1d */
854/* File: armv5te/OP_MONITOR_ENTER.S */
855    /*
856     * Synchronize on an object.
857     */
858    /* monitor-enter vAA */
859    mov     r2, rINST, lsr #8           @ r2<- AA
860    GET_VREG(r1, r2)                    @ r1<- vAA (object)
861    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
862    cmp     r1, #0                      @ null object?
863    EXPORT_PC()                         @ need for precise GC, MONITOR_TRACKING
864    beq     common_errNullObject        @ null object, throw an exception
865    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
866    bl      dvmLockObject               @ call(self, obj)
867#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */
868    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
869    ldr     r1, [r0, #offThread_exception] @ check for exception
870    cmp     r1, #0
871    bne     common_exceptionThrown      @ exception raised, bail out
872#endif
873    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
874    GOTO_OPCODE(ip)                     @ jump to next instruction
875
876/* ------------------------------ */
877    .balign 64
878.L_OP_MONITOR_EXIT: /* 0x1e */
879/* File: armv5te/OP_MONITOR_EXIT.S */
880    /*
881     * Unlock an object.
882     *
883     * Exceptions that occur when unlocking a monitor need to appear as
884     * if they happened at the following instruction.  See the Dalvik
885     * instruction spec.
886     */
887    /* monitor-exit vAA */
888    mov     r2, rINST, lsr #8           @ r2<- AA
889    EXPORT_PC()                         @ before fetch: export the PC
890    GET_VREG(r1, r2)                    @ r1<- vAA (object)
891    cmp     r1, #0                      @ null object?
892    beq     1f                          @ yes
893    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
894    bl      dvmUnlockObject             @ r0<- success for unlock(self, obj)
895    cmp     r0, #0                      @ failed?
896    FETCH_ADVANCE_INST(1)               @ before throw: advance rPC, load rINST
897    beq     common_exceptionThrown      @ yes, exception is pending
898    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
899    GOTO_OPCODE(ip)                     @ jump to next instruction
9001:
901    FETCH_ADVANCE_INST(1)               @ advance before throw
902    b      common_errNullObject
903
904/* ------------------------------ */
905    .balign 64
906.L_OP_CHECK_CAST: /* 0x1f */
907/* File: armv5te/OP_CHECK_CAST.S */
908    /*
909     * Check to see if a cast from one class to another is allowed.
910     */
911    /* check-cast vAA, class@BBBB */
912    mov     r3, rINST, lsr #8           @ r3<- AA
913    FETCH(r2, 1)                        @ r2<- BBBB
914    GET_VREG(r9, r3)                    @ r9<- object
915    ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- pDvmDex
916    cmp     r9, #0                      @ is object null?
917    ldr     r0, [r0, #offDvmDex_pResClasses]    @ r0<- pDvmDex->pResClasses
918    beq     .LOP_CHECK_CAST_okay            @ null obj, cast always succeeds
919    ldr     r1, [r0, r2, lsl #2]        @ r1<- resolved class
920    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
921    cmp     r1, #0                      @ have we resolved this before?
922    beq     .LOP_CHECK_CAST_resolve         @ not resolved, do it now
923.LOP_CHECK_CAST_resolved:
924    cmp     r0, r1                      @ same class (trivial success)?
925    bne     .LOP_CHECK_CAST_fullcheck       @ no, do full check
926.LOP_CHECK_CAST_okay:
927    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
928    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
929    GOTO_OPCODE(ip)                     @ jump to next instruction
930
931/* ------------------------------ */
932    .balign 64
933.L_OP_INSTANCE_OF: /* 0x20 */
934/* File: armv5te/OP_INSTANCE_OF.S */
935    /*
936     * Check to see if an object reference is an instance of a class.
937     *
938     * Most common situation is a non-null object, being compared against
939     * an already-resolved class.
940     */
941    /* instance-of vA, vB, class@CCCC */
942    mov     r3, rINST, lsr #12          @ r3<- B
943    mov     r9, rINST, lsr #8           @ r9<- A+
944    GET_VREG(r0, r3)                    @ r0<- vB (object)
945    and     r9, r9, #15                 @ r9<- A
946    cmp     r0, #0                      @ is object null?
947    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- pDvmDex
948    beq     .LOP_INSTANCE_OF_store           @ null obj, not an instance, store r0
949    FETCH(r3, 1)                        @ r3<- CCCC
950    ldr     r2, [r2, #offDvmDex_pResClasses]    @ r2<- pDvmDex->pResClasses
951    ldr     r1, [r2, r3, lsl #2]        @ r1<- resolved class
952    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
953    cmp     r1, #0                      @ have we resolved this before?
954    beq     .LOP_INSTANCE_OF_resolve         @ not resolved, do it now
955.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class
956    cmp     r0, r1                      @ same class (trivial success)?
957    beq     .LOP_INSTANCE_OF_trivial         @ yes, trivial finish
958    b       .LOP_INSTANCE_OF_fullcheck       @ no, do full check
959
960/* ------------------------------ */
961    .balign 64
962.L_OP_ARRAY_LENGTH: /* 0x21 */
963/* File: armv6t2/OP_ARRAY_LENGTH.S */
964    /*
965     * Return the length of an array.
966     */
967    mov     r1, rINST, lsr #12          @ r1<- B
968    ubfx    r2, rINST, #8, #4           @ r2<- A
969    GET_VREG(r0, r1)                    @ r0<- vB (object ref)
970    cmp     r0, #0                      @ is object null?
971    beq     common_errNullObject        @ yup, fail
972    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
973    ldr     r3, [r0, #offArrayObject_length]    @ r3<- array length
974    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
975    SET_VREG(r3, r2)                    @ vB<- length
976    GOTO_OPCODE(ip)                     @ jump to next instruction
977
978/* ------------------------------ */
979    .balign 64
980.L_OP_NEW_INSTANCE: /* 0x22 */
981/* File: armv5te/OP_NEW_INSTANCE.S */
982    /*
983     * Create a new instance of a class.
984     */
985    /* new-instance vAA, class@BBBB */
986    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
987    FETCH(r1, 1)                        @ r1<- BBBB
988    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
989    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
990    EXPORT_PC()                         @ req'd for init, resolve, alloc
991    cmp     r0, #0                      @ already resolved?
992    beq     .LOP_NEW_INSTANCE_resolve         @ no, resolve it now
993.LOP_NEW_INSTANCE_resolved:   @ r0=class
994    ldrb    r1, [r0, #offClassObject_status]    @ r1<- ClassStatus enum
995    cmp     r1, #CLASS_INITIALIZED      @ has class been initialized?
996    bne     .LOP_NEW_INSTANCE_needinit        @ no, init class now
997.LOP_NEW_INSTANCE_initialized: @ r0=class
998    mov     r1, #ALLOC_DONT_TRACK       @ flags for alloc call
999    bl      dvmAllocObject              @ r0<- new object
1000    b       .LOP_NEW_INSTANCE_finish          @ continue
1001
1002/* ------------------------------ */
1003    .balign 64
1004.L_OP_NEW_ARRAY: /* 0x23 */
1005/* File: armv5te/OP_NEW_ARRAY.S */
1006    /*
1007     * Allocate an array of objects, specified with the array class
1008     * and a count.
1009     *
1010     * The verifier guarantees that this is an array class, so we don't
1011     * check for it here.
1012     */
1013    /* new-array vA, vB, class@CCCC */
1014    mov     r0, rINST, lsr #12          @ r0<- B
1015    FETCH(r2, 1)                        @ r2<- CCCC
1016    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1017    GET_VREG(r1, r0)                    @ r1<- vB (array length)
1018    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1019    cmp     r1, #0                      @ check length
1020    ldr     r0, [r3, r2, lsl #2]        @ r0<- resolved class
1021    bmi     common_errNegativeArraySize @ negative length, bail
1022    cmp     r0, #0                      @ already resolved?
1023    EXPORT_PC()                         @ req'd for resolve, alloc
1024    bne     .LOP_NEW_ARRAY_finish          @ resolved, continue
1025    b       .LOP_NEW_ARRAY_resolve         @ do resolve now
1026
1027/* ------------------------------ */
1028    .balign 64
1029.L_OP_FILLED_NEW_ARRAY: /* 0x24 */
1030/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1031    /*
1032     * Create a new array with elements filled from registers.
1033     *
1034     * for: filled-new-array, filled-new-array/range
1035     */
1036    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1037    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1038    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1039    FETCH(r1, 1)                        @ r1<- BBBB
1040    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1041    EXPORT_PC()                         @ need for resolve and alloc
1042    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1043    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1044    cmp     r0, #0                      @ already resolved?
1045    bne     .LOP_FILLED_NEW_ARRAY_continue        @ yes, continue on
10468:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1047    mov     r2, #0                      @ r2<- false
1048    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1049    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1050    cmp     r0, #0                      @ got null?
1051    beq     common_exceptionThrown      @ yes, handle exception
1052    b       .LOP_FILLED_NEW_ARRAY_continue
1053
1054/* ------------------------------ */
1055    .balign 64
1056.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
1057/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */
1058/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1059    /*
1060     * Create a new array with elements filled from registers.
1061     *
1062     * for: filled-new-array, filled-new-array/range
1063     */
1064    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1065    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1066    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1067    FETCH(r1, 1)                        @ r1<- BBBB
1068    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1069    EXPORT_PC()                         @ need for resolve and alloc
1070    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1071    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1072    cmp     r0, #0                      @ already resolved?
1073    bne     .LOP_FILLED_NEW_ARRAY_RANGE_continue        @ yes, continue on
10748:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1075    mov     r2, #0                      @ r2<- false
1076    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1077    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1078    cmp     r0, #0                      @ got null?
1079    beq     common_exceptionThrown      @ yes, handle exception
1080    b       .LOP_FILLED_NEW_ARRAY_RANGE_continue
1081
1082
1083/* ------------------------------ */
1084    .balign 64
1085.L_OP_FILL_ARRAY_DATA: /* 0x26 */
1086/* File: armv5te/OP_FILL_ARRAY_DATA.S */
1087    /* fill-array-data vAA, +BBBBBBBB */
1088    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1089    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1090    mov     r3, rINST, lsr #8           @ r3<- AA
1091    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
1092    GET_VREG(r0, r3)                    @ r0<- vAA (array object)
1093    add     r1, rPC, r1, lsl #1         @ r1<- PC + BBBBbbbb*2 (array data off.)
1094    EXPORT_PC();
1095    bl      dvmInterpHandleFillArrayData@ fill the array with predefined data
1096    cmp     r0, #0                      @ 0 means an exception is thrown
1097    beq     common_exceptionThrown      @ has exception
1098    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
1099    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1100    GOTO_OPCODE(ip)                     @ jump to next instruction
1101
1102/* ------------------------------ */
1103    .balign 64
1104.L_OP_THROW: /* 0x27 */
1105/* File: armv5te/OP_THROW.S */
1106    /*
1107     * Throw an exception object in the current thread.
1108     */
1109    /* throw vAA */
1110    mov     r2, rINST, lsr #8           @ r2<- AA
1111    GET_VREG(r1, r2)                    @ r1<- vAA (exception object)
1112    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
1113    EXPORT_PC()                         @ exception handler can throw
1114    cmp     r1, #0                      @ null object?
1115    beq     common_errNullObject        @ yes, throw an NPE instead
1116    @ bypass dvmSetException, just store it
1117    str     r1, [r0, #offThread_exception]  @ thread->exception<- obj
1118    b       common_exceptionThrown
1119
1120/* ------------------------------ */
1121    .balign 64
1122.L_OP_GOTO: /* 0x28 */
1123/* File: armv5te/OP_GOTO.S */
1124    /*
1125     * Unconditional branch, 8-bit offset.
1126     *
1127     * The branch distance is a signed code-unit offset, which we need to
1128     * double to get a byte offset.
1129     */
1130    /* goto +AA */
1131    mov     r0, rINST, lsl #16          @ r0<- AAxx0000
1132    movs    r9, r0, asr #24             @ r9<- ssssssAA (sign-extended)
1133    mov     r9, r9, lsl #1              @ r9<- byte offset
1134    bmi     common_backwardBranch       @ backward branch, do periodic checks
1135#if defined(WITH_JIT)
1136    GET_JIT_PROF_TABLE(r0)
1137    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1138    cmp     r0,#0
1139    bne     common_updateProfile
1140    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1141    GOTO_OPCODE(ip)                     @ jump to next instruction
1142#else
1143    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1144    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1145    GOTO_OPCODE(ip)                     @ jump to next instruction
1146#endif
1147
1148/* ------------------------------ */
1149    .balign 64
1150.L_OP_GOTO_16: /* 0x29 */
1151/* File: armv5te/OP_GOTO_16.S */
1152    /*
1153     * Unconditional branch, 16-bit offset.
1154     *
1155     * The branch distance is a signed code-unit offset, which we need to
1156     * double to get a byte offset.
1157     */
1158    /* goto/16 +AAAA */
1159    FETCH_S(r0, 1)                      @ r0<- ssssAAAA (sign-extended)
1160    movs    r9, r0, asl #1              @ r9<- byte offset, check sign
1161    bmi     common_backwardBranch       @ backward branch, do periodic checks
1162#if defined(WITH_JIT)
1163    GET_JIT_PROF_TABLE(r0)
1164    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1165    cmp     r0,#0
1166    bne     common_updateProfile
1167    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1168    GOTO_OPCODE(ip)                     @ jump to next instruction
1169#else
1170    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1171    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1172    GOTO_OPCODE(ip)                     @ jump to next instruction
1173#endif
1174
1175/* ------------------------------ */
1176    .balign 64
1177.L_OP_GOTO_32: /* 0x2a */
1178/* File: armv5te/OP_GOTO_32.S */
1179    /*
1180     * Unconditional branch, 32-bit offset.
1181     *
1182     * The branch distance is a signed code-unit offset, which we need to
1183     * double to get a byte offset.
1184     *
1185     * Unlike most opcodes, this one is allowed to branch to itself, so
1186     * our "backward branch" test must be "<=0" instead of "<0".  The ORRS
1187     * instruction doesn't affect the V flag, so we need to clear it
1188     * explicitly.
1189     */
1190    /* goto/32 +AAAAAAAA */
1191    FETCH(r0, 1)                        @ r0<- aaaa (lo)
1192    FETCH(r1, 2)                        @ r1<- AAAA (hi)
1193    cmp     ip, ip                      @ (clear V flag during stall)
1194    orrs    r0, r0, r1, lsl #16         @ r0<- AAAAaaaa, check sign
1195    mov     r9, r0, asl #1              @ r9<- byte offset
1196    ble     common_backwardBranch       @ backward branch, do periodic checks
1197#if defined(WITH_JIT)
1198    GET_JIT_PROF_TABLE(r0)
1199    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1200    cmp     r0,#0
1201    bne     common_updateProfile
1202    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1203    GOTO_OPCODE(ip)                     @ jump to next instruction
1204#else
1205    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1206    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1207    GOTO_OPCODE(ip)                     @ jump to next instruction
1208#endif
1209
1210/* ------------------------------ */
1211    .balign 64
1212.L_OP_PACKED_SWITCH: /* 0x2b */
1213/* File: armv5te/OP_PACKED_SWITCH.S */
1214    /*
1215     * Handle a packed-switch or sparse-switch instruction.  In both cases
1216     * we decode it and hand it off to a helper function.
1217     *
1218     * We don't really expect backward branches in a switch statement, but
1219     * they're perfectly legal, so we check for them here.
1220     *
1221     * for: packed-switch, sparse-switch
1222     */
1223    /* op vAA, +BBBB */
1224    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1225    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1226    mov     r3, rINST, lsr #8           @ r3<- AA
1227    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1228    GET_VREG(r1, r3)                    @ r1<- vAA
1229    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1230    bl      dvmInterpHandlePackedSwitch                       @ r0<- code-unit branch offset
1231    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1232    bmi     common_backwardBranch       @ backward branch, do periodic checks
1233    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1234#if defined(WITH_JIT)
1235    GET_JIT_PROF_TABLE(r0)
1236    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1237    cmp     r0,#0
1238    bne     common_updateProfile
1239    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1240    GOTO_OPCODE(ip)                     @ jump to next instruction
1241#else
1242    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1243    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1244    GOTO_OPCODE(ip)                     @ jump to next instruction
1245#endif
1246
1247/* ------------------------------ */
1248    .balign 64
1249.L_OP_SPARSE_SWITCH: /* 0x2c */
1250/* File: armv5te/OP_SPARSE_SWITCH.S */
1251/* File: armv5te/OP_PACKED_SWITCH.S */
1252    /*
1253     * Handle a packed-switch or sparse-switch instruction.  In both cases
1254     * we decode it and hand it off to a helper function.
1255     *
1256     * We don't really expect backward branches in a switch statement, but
1257     * they're perfectly legal, so we check for them here.
1258     *
1259     * for: packed-switch, sparse-switch
1260     */
1261    /* op vAA, +BBBB */
1262    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1263    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1264    mov     r3, rINST, lsr #8           @ r3<- AA
1265    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1266    GET_VREG(r1, r3)                    @ r1<- vAA
1267    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1268    bl      dvmInterpHandleSparseSwitch                       @ r0<- code-unit branch offset
1269    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1270    bmi     common_backwardBranch       @ backward branch, do periodic checks
1271    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1272#if defined(WITH_JIT)
1273    GET_JIT_PROF_TABLE(r0)
1274    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1275    cmp     r0,#0
1276    bne     common_updateProfile
1277    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1278    GOTO_OPCODE(ip)                     @ jump to next instruction
1279#else
1280    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1281    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1282    GOTO_OPCODE(ip)                     @ jump to next instruction
1283#endif
1284
1285
1286/* ------------------------------ */
1287    .balign 64
1288.L_OP_CMPL_FLOAT: /* 0x2d */
1289/* File: arm-vfp/OP_CMPL_FLOAT.S */
1290    /*
1291     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1292     * destination register based on the results of the comparison.
1293     *
1294     * int compare(x, y) {
1295     *     if (x == y) {
1296     *         return 0;
1297     *     } else if (x > y) {
1298     *         return 1;
1299     *     } else if (x < y) {
1300     *         return -1;
1301     *     } else {
1302     *         return -1;
1303     *     }
1304     * }
1305     */
1306    /* op vAA, vBB, vCC */
1307    FETCH(r0, 1)                        @ r0<- CCBB
1308    mov     r9, rINST, lsr #8           @ r9<- AA
1309    and     r2, r0, #255                @ r2<- BB
1310    mov     r3, r0, lsr #8              @ r3<- CC
1311    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1312    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1313    flds    s0, [r2]                    @ s0<- vBB
1314    flds    s1, [r3]                    @ s1<- vCC
1315    fcmpes  s0, s1                      @ compare (vBB, vCC)
1316    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1317    mvn     r0, #0                      @ r0<- -1 (default)
1318    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1319    fmstat                              @ export status flags
1320    movgt   r0, #1                      @ (greater than) r1<- 1
1321    moveq   r0, #0                      @ (equal) r1<- 0
1322    b       .LOP_CMPL_FLOAT_finish          @ argh
1323
1324
1325/* ------------------------------ */
1326    .balign 64
1327.L_OP_CMPG_FLOAT: /* 0x2e */
1328/* File: arm-vfp/OP_CMPG_FLOAT.S */
1329    /*
1330     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1331     * destination register based on the results of the comparison.
1332     *
1333     * int compare(x, y) {
1334     *     if (x == y) {
1335     *         return 0;
1336     *     } else if (x < y) {
1337     *         return -1;
1338     *     } else if (x > y) {
1339     *         return 1;
1340     *     } else {
1341     *         return 1;
1342     *     }
1343     * }
1344     */
1345    /* op vAA, vBB, vCC */
1346    FETCH(r0, 1)                        @ r0<- CCBB
1347    mov     r9, rINST, lsr #8           @ r9<- AA
1348    and     r2, r0, #255                @ r2<- BB
1349    mov     r3, r0, lsr #8              @ r3<- CC
1350    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1351    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1352    flds    s0, [r2]                    @ s0<- vBB
1353    flds    s1, [r3]                    @ s1<- vCC
1354    fcmpes  s0, s1                      @ compare (vBB, vCC)
1355    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1356    mov     r0, #1                      @ r0<- 1 (default)
1357    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1358    fmstat                              @ export status flags
1359    mvnmi   r0, #0                      @ (less than) r1<- -1
1360    moveq   r0, #0                      @ (equal) r1<- 0
1361    b       .LOP_CMPG_FLOAT_finish          @ argh
1362
1363
1364/* ------------------------------ */
1365    .balign 64
1366.L_OP_CMPL_DOUBLE: /* 0x2f */
1367/* File: arm-vfp/OP_CMPL_DOUBLE.S */
1368    /*
1369     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1370     * destination register based on the results of the comparison.
1371     *
1372     * int compare(x, y) {
1373     *     if (x == y) {
1374     *         return 0;
1375     *     } else if (x > y) {
1376     *         return 1;
1377     *     } else if (x < y) {
1378     *         return -1;
1379     *     } else {
1380     *         return -1;
1381     *     }
1382     * }
1383     */
1384    /* op vAA, vBB, vCC */
1385    FETCH(r0, 1)                        @ r0<- CCBB
1386    mov     r9, rINST, lsr #8           @ r9<- AA
1387    and     r2, r0, #255                @ r2<- BB
1388    mov     r3, r0, lsr #8              @ r3<- CC
1389    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1390    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1391    fldd    d0, [r2]                    @ d0<- vBB
1392    fldd    d1, [r3]                    @ d1<- vCC
1393    fcmped  d0, d1                      @ compare (vBB, vCC)
1394    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1395    mvn     r0, #0                      @ r0<- -1 (default)
1396    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1397    fmstat                              @ export status flags
1398    movgt   r0, #1                      @ (greater than) r1<- 1
1399    moveq   r0, #0                      @ (equal) r1<- 0
1400    b       .LOP_CMPL_DOUBLE_finish          @ argh
1401
1402
1403/* ------------------------------ */
1404    .balign 64
1405.L_OP_CMPG_DOUBLE: /* 0x30 */
1406/* File: arm-vfp/OP_CMPG_DOUBLE.S */
1407    /*
1408     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1409     * destination register based on the results of the comparison.
1410     *
1411     * int compare(x, y) {
1412     *     if (x == y) {
1413     *         return 0;
1414     *     } else if (x < y) {
1415     *         return -1;
1416     *     } else if (x > y) {
1417     *         return 1;
1418     *     } else {
1419     *         return 1;
1420     *     }
1421     * }
1422     */
1423    /* op vAA, vBB, vCC */
1424    FETCH(r0, 1)                        @ r0<- CCBB
1425    mov     r9, rINST, lsr #8           @ r9<- AA
1426    and     r2, r0, #255                @ r2<- BB
1427    mov     r3, r0, lsr #8              @ r3<- CC
1428    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1429    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1430    fldd    d0, [r2]                    @ d0<- vBB
1431    fldd    d1, [r3]                    @ d1<- vCC
1432    fcmped  d0, d1                      @ compare (vBB, vCC)
1433    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1434    mov     r0, #1                      @ r0<- 1 (default)
1435    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1436    fmstat                              @ export status flags
1437    mvnmi   r0, #0                      @ (less than) r1<- -1
1438    moveq   r0, #0                      @ (equal) r1<- 0
1439    b       .LOP_CMPG_DOUBLE_finish          @ argh
1440
1441
1442/* ------------------------------ */
1443    .balign 64
1444.L_OP_CMP_LONG: /* 0x31 */
1445/* File: armv5te/OP_CMP_LONG.S */
1446    /*
1447     * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
1448     * register based on the results of the comparison.
1449     *
1450     * We load the full values with LDM, but in practice many values could
1451     * be resolved by only looking at the high word.  This could be made
1452     * faster or slower by splitting the LDM into a pair of LDRs.
1453     *
1454     * If we just wanted to set condition flags, we could do this:
1455     *  subs    ip, r0, r2
1456     *  sbcs    ip, r1, r3
1457     *  subeqs  ip, r0, r2
1458     * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
1459     * integer value, which we can do with 2 conditional mov/mvn instructions
1460     * (set 1, set -1; if they're equal we already have 0 in ip), giving
1461     * us a constant 5-cycle path plus a branch at the end to the
1462     * instruction epilogue code.  The multi-compare approach below needs
1463     * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
1464     * in the worst case (the 64-bit values are equal).
1465     */
1466    /* cmp-long vAA, vBB, vCC */
1467    FETCH(r0, 1)                        @ r0<- CCBB
1468    mov     r9, rINST, lsr #8           @ r9<- AA
1469    and     r2, r0, #255                @ r2<- BB
1470    mov     r3, r0, lsr #8              @ r3<- CC
1471    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
1472    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
1473    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1474    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
1475    cmp     r1, r3                      @ compare (vBB+1, vCC+1)
1476    blt     .LOP_CMP_LONG_less            @ signed compare on high part
1477    bgt     .LOP_CMP_LONG_greater
1478    subs    r1, r0, r2                  @ r1<- r0 - r2
1479    bhi     .LOP_CMP_LONG_greater         @ unsigned compare on low part
1480    bne     .LOP_CMP_LONG_less
1481    b       .LOP_CMP_LONG_finish          @ equal; r1 already holds 0
1482
1483/* ------------------------------ */
1484    .balign 64
1485.L_OP_IF_EQ: /* 0x32 */
1486/* File: armv6t2/OP_IF_EQ.S */
1487/* File: armv6t2/bincmp.S */
1488    /*
1489     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1490     * fragment that specifies the *reverse* comparison to perform, e.g.
1491     * for "if-le" you would use "gt".
1492     *
1493     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1494     */
1495    /* if-cmp vA, vB, +CCCC */
1496    mov     r1, rINST, lsr #12          @ r1<- B
1497    ubfx    r0, rINST, #8, #4           @ r0<- A
1498    GET_VREG(r3, r1)                    @ r3<- vB
1499    GET_VREG(r2, r0)                    @ r2<- vA
1500    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1501    cmp     r2, r3                      @ compare (vA, vB)
1502    bne  1f                      @ branch to 1 if comparison failed
1503    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1504    movs    r9, r9, asl #1              @ convert to bytes, check sign
1505    bmi     common_backwardBranch       @ yes, do periodic checks
15061:
1507#if defined(WITH_JIT)
1508    GET_JIT_PROF_TABLE(r0)
1509    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1510    b        common_testUpdateProfile
1511#else
1512    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1513    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1514    GOTO_OPCODE(ip)                     @ jump to next instruction
1515#endif
1516
1517
1518/* ------------------------------ */
1519    .balign 64
1520.L_OP_IF_NE: /* 0x33 */
1521/* File: armv6t2/OP_IF_NE.S */
1522/* File: armv6t2/bincmp.S */
1523    /*
1524     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1525     * fragment that specifies the *reverse* comparison to perform, e.g.
1526     * for "if-le" you would use "gt".
1527     *
1528     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1529     */
1530    /* if-cmp vA, vB, +CCCC */
1531    mov     r1, rINST, lsr #12          @ r1<- B
1532    ubfx    r0, rINST, #8, #4           @ r0<- A
1533    GET_VREG(r3, r1)                    @ r3<- vB
1534    GET_VREG(r2, r0)                    @ r2<- vA
1535    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1536    cmp     r2, r3                      @ compare (vA, vB)
1537    beq  1f                      @ branch to 1 if comparison failed
1538    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1539    movs    r9, r9, asl #1              @ convert to bytes, check sign
1540    bmi     common_backwardBranch       @ yes, do periodic checks
15411:
1542#if defined(WITH_JIT)
1543    GET_JIT_PROF_TABLE(r0)
1544    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1545    b        common_testUpdateProfile
1546#else
1547    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1548    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1549    GOTO_OPCODE(ip)                     @ jump to next instruction
1550#endif
1551
1552
1553/* ------------------------------ */
1554    .balign 64
1555.L_OP_IF_LT: /* 0x34 */
1556/* File: armv6t2/OP_IF_LT.S */
1557/* File: armv6t2/bincmp.S */
1558    /*
1559     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1560     * fragment that specifies the *reverse* comparison to perform, e.g.
1561     * for "if-le" you would use "gt".
1562     *
1563     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1564     */
1565    /* if-cmp vA, vB, +CCCC */
1566    mov     r1, rINST, lsr #12          @ r1<- B
1567    ubfx    r0, rINST, #8, #4           @ r0<- A
1568    GET_VREG(r3, r1)                    @ r3<- vB
1569    GET_VREG(r2, r0)                    @ r2<- vA
1570    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1571    cmp     r2, r3                      @ compare (vA, vB)
1572    bge  1f                      @ branch to 1 if comparison failed
1573    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1574    movs    r9, r9, asl #1              @ convert to bytes, check sign
1575    bmi     common_backwardBranch       @ yes, do periodic checks
15761:
1577#if defined(WITH_JIT)
1578    GET_JIT_PROF_TABLE(r0)
1579    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1580    b        common_testUpdateProfile
1581#else
1582    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1583    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1584    GOTO_OPCODE(ip)                     @ jump to next instruction
1585#endif
1586
1587
1588/* ------------------------------ */
1589    .balign 64
1590.L_OP_IF_GE: /* 0x35 */
1591/* File: armv6t2/OP_IF_GE.S */
1592/* File: armv6t2/bincmp.S */
1593    /*
1594     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1595     * fragment that specifies the *reverse* comparison to perform, e.g.
1596     * for "if-le" you would use "gt".
1597     *
1598     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1599     */
1600    /* if-cmp vA, vB, +CCCC */
1601    mov     r1, rINST, lsr #12          @ r1<- B
1602    ubfx    r0, rINST, #8, #4           @ r0<- A
1603    GET_VREG(r3, r1)                    @ r3<- vB
1604    GET_VREG(r2, r0)                    @ r2<- vA
1605    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1606    cmp     r2, r3                      @ compare (vA, vB)
1607    blt  1f                      @ branch to 1 if comparison failed
1608    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1609    movs    r9, r9, asl #1              @ convert to bytes, check sign
1610    bmi     common_backwardBranch       @ yes, do periodic checks
16111:
1612#if defined(WITH_JIT)
1613    GET_JIT_PROF_TABLE(r0)
1614    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1615    b        common_testUpdateProfile
1616#else
1617    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1618    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1619    GOTO_OPCODE(ip)                     @ jump to next instruction
1620#endif
1621
1622
1623/* ------------------------------ */
1624    .balign 64
1625.L_OP_IF_GT: /* 0x36 */
1626/* File: armv6t2/OP_IF_GT.S */
1627/* File: armv6t2/bincmp.S */
1628    /*
1629     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1630     * fragment that specifies the *reverse* comparison to perform, e.g.
1631     * for "if-le" you would use "gt".
1632     *
1633     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1634     */
1635    /* if-cmp vA, vB, +CCCC */
1636    mov     r1, rINST, lsr #12          @ r1<- B
1637    ubfx    r0, rINST, #8, #4           @ r0<- A
1638    GET_VREG(r3, r1)                    @ r3<- vB
1639    GET_VREG(r2, r0)                    @ r2<- vA
1640    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1641    cmp     r2, r3                      @ compare (vA, vB)
1642    ble  1f                      @ branch to 1 if comparison failed
1643    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1644    movs    r9, r9, asl #1              @ convert to bytes, check sign
1645    bmi     common_backwardBranch       @ yes, do periodic checks
16461:
1647#if defined(WITH_JIT)
1648    GET_JIT_PROF_TABLE(r0)
1649    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1650    b        common_testUpdateProfile
1651#else
1652    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1653    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1654    GOTO_OPCODE(ip)                     @ jump to next instruction
1655#endif
1656
1657
1658/* ------------------------------ */
1659    .balign 64
1660.L_OP_IF_LE: /* 0x37 */
1661/* File: armv6t2/OP_IF_LE.S */
1662/* File: armv6t2/bincmp.S */
1663    /*
1664     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1665     * fragment that specifies the *reverse* comparison to perform, e.g.
1666     * for "if-le" you would use "gt".
1667     *
1668     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1669     */
1670    /* if-cmp vA, vB, +CCCC */
1671    mov     r1, rINST, lsr #12          @ r1<- B
1672    ubfx    r0, rINST, #8, #4           @ r0<- A
1673    GET_VREG(r3, r1)                    @ r3<- vB
1674    GET_VREG(r2, r0)                    @ r2<- vA
1675    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1676    cmp     r2, r3                      @ compare (vA, vB)
1677    bgt  1f                      @ branch to 1 if comparison failed
1678    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1679    movs    r9, r9, asl #1              @ convert to bytes, check sign
1680    bmi     common_backwardBranch       @ yes, do periodic checks
16811:
1682#if defined(WITH_JIT)
1683    GET_JIT_PROF_TABLE(r0)
1684    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1685    b        common_testUpdateProfile
1686#else
1687    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1688    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1689    GOTO_OPCODE(ip)                     @ jump to next instruction
1690#endif
1691
1692
1693/* ------------------------------ */
1694    .balign 64
1695.L_OP_IF_EQZ: /* 0x38 */
1696/* File: armv5te/OP_IF_EQZ.S */
1697/* File: armv5te/zcmp.S */
1698    /*
1699     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1700     * fragment that specifies the *reverse* comparison to perform, e.g.
1701     * for "if-le" you would use "gt".
1702     *
1703     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1704     */
1705    /* if-cmp vAA, +BBBB */
1706    mov     r0, rINST, lsr #8           @ r0<- AA
1707    GET_VREG(r2, r0)                    @ r2<- vAA
1708    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1709    cmp     r2, #0                      @ compare (vA, 0)
1710    bne  1f                      @ branch to 1 if comparison failed
1711    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1712    movs    r9, r9, asl #1              @ convert to bytes, check sign
1713    bmi     common_backwardBranch       @ backward branch, do periodic checks
17141:
1715#if defined(WITH_JIT)
1716    GET_JIT_PROF_TABLE(r0)
1717    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1718    cmp     r0,#0
1719    bne     common_updateProfile
1720    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1721    GOTO_OPCODE(ip)                     @ jump to next instruction
1722#else
1723    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1724    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1725    GOTO_OPCODE(ip)                     @ jump to next instruction
1726#endif
1727
1728
1729/* ------------------------------ */
1730    .balign 64
1731.L_OP_IF_NEZ: /* 0x39 */
1732/* File: armv5te/OP_IF_NEZ.S */
1733/* File: armv5te/zcmp.S */
1734    /*
1735     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1736     * fragment that specifies the *reverse* comparison to perform, e.g.
1737     * for "if-le" you would use "gt".
1738     *
1739     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1740     */
1741    /* if-cmp vAA, +BBBB */
1742    mov     r0, rINST, lsr #8           @ r0<- AA
1743    GET_VREG(r2, r0)                    @ r2<- vAA
1744    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1745    cmp     r2, #0                      @ compare (vA, 0)
1746    beq  1f                      @ branch to 1 if comparison failed
1747    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1748    movs    r9, r9, asl #1              @ convert to bytes, check sign
1749    bmi     common_backwardBranch       @ backward branch, do periodic checks
17501:
1751#if defined(WITH_JIT)
1752    GET_JIT_PROF_TABLE(r0)
1753    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1754    cmp     r0,#0
1755    bne     common_updateProfile
1756    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1757    GOTO_OPCODE(ip)                     @ jump to next instruction
1758#else
1759    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1760    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1761    GOTO_OPCODE(ip)                     @ jump to next instruction
1762#endif
1763
1764
1765/* ------------------------------ */
1766    .balign 64
1767.L_OP_IF_LTZ: /* 0x3a */
1768/* File: armv5te/OP_IF_LTZ.S */
1769/* File: armv5te/zcmp.S */
1770    /*
1771     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1772     * fragment that specifies the *reverse* comparison to perform, e.g.
1773     * for "if-le" you would use "gt".
1774     *
1775     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1776     */
1777    /* if-cmp vAA, +BBBB */
1778    mov     r0, rINST, lsr #8           @ r0<- AA
1779    GET_VREG(r2, r0)                    @ r2<- vAA
1780    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1781    cmp     r2, #0                      @ compare (vA, 0)
1782    bge  1f                      @ branch to 1 if comparison failed
1783    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1784    movs    r9, r9, asl #1              @ convert to bytes, check sign
1785    bmi     common_backwardBranch       @ backward branch, do periodic checks
17861:
1787#if defined(WITH_JIT)
1788    GET_JIT_PROF_TABLE(r0)
1789    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1790    cmp     r0,#0
1791    bne     common_updateProfile
1792    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1793    GOTO_OPCODE(ip)                     @ jump to next instruction
1794#else
1795    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1796    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1797    GOTO_OPCODE(ip)                     @ jump to next instruction
1798#endif
1799
1800
1801/* ------------------------------ */
1802    .balign 64
1803.L_OP_IF_GEZ: /* 0x3b */
1804/* File: armv5te/OP_IF_GEZ.S */
1805/* File: armv5te/zcmp.S */
1806    /*
1807     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1808     * fragment that specifies the *reverse* comparison to perform, e.g.
1809     * for "if-le" you would use "gt".
1810     *
1811     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1812     */
1813    /* if-cmp vAA, +BBBB */
1814    mov     r0, rINST, lsr #8           @ r0<- AA
1815    GET_VREG(r2, r0)                    @ r2<- vAA
1816    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1817    cmp     r2, #0                      @ compare (vA, 0)
1818    blt  1f                      @ branch to 1 if comparison failed
1819    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1820    movs    r9, r9, asl #1              @ convert to bytes, check sign
1821    bmi     common_backwardBranch       @ backward branch, do periodic checks
18221:
1823#if defined(WITH_JIT)
1824    GET_JIT_PROF_TABLE(r0)
1825    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1826    cmp     r0,#0
1827    bne     common_updateProfile
1828    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1829    GOTO_OPCODE(ip)                     @ jump to next instruction
1830#else
1831    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1832    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1833    GOTO_OPCODE(ip)                     @ jump to next instruction
1834#endif
1835
1836
1837/* ------------------------------ */
1838    .balign 64
1839.L_OP_IF_GTZ: /* 0x3c */
1840/* File: armv5te/OP_IF_GTZ.S */
1841/* File: armv5te/zcmp.S */
1842    /*
1843     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1844     * fragment that specifies the *reverse* comparison to perform, e.g.
1845     * for "if-le" you would use "gt".
1846     *
1847     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1848     */
1849    /* if-cmp vAA, +BBBB */
1850    mov     r0, rINST, lsr #8           @ r0<- AA
1851    GET_VREG(r2, r0)                    @ r2<- vAA
1852    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1853    cmp     r2, #0                      @ compare (vA, 0)
1854    ble  1f                      @ branch to 1 if comparison failed
1855    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1856    movs    r9, r9, asl #1              @ convert to bytes, check sign
1857    bmi     common_backwardBranch       @ backward branch, do periodic checks
18581:
1859#if defined(WITH_JIT)
1860    GET_JIT_PROF_TABLE(r0)
1861    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1862    cmp     r0,#0
1863    bne     common_updateProfile
1864    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1865    GOTO_OPCODE(ip)                     @ jump to next instruction
1866#else
1867    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1868    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1869    GOTO_OPCODE(ip)                     @ jump to next instruction
1870#endif
1871
1872
1873/* ------------------------------ */
1874    .balign 64
1875.L_OP_IF_LEZ: /* 0x3d */
1876/* File: armv5te/OP_IF_LEZ.S */
1877/* File: armv5te/zcmp.S */
1878    /*
1879     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1880     * fragment that specifies the *reverse* comparison to perform, e.g.
1881     * for "if-le" you would use "gt".
1882     *
1883     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1884     */
1885    /* if-cmp vAA, +BBBB */
1886    mov     r0, rINST, lsr #8           @ r0<- AA
1887    GET_VREG(r2, r0)                    @ r2<- vAA
1888    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1889    cmp     r2, #0                      @ compare (vA, 0)
1890    bgt  1f                      @ branch to 1 if comparison failed
1891    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1892    movs    r9, r9, asl #1              @ convert to bytes, check sign
1893    bmi     common_backwardBranch       @ backward branch, do periodic checks
18941:
1895#if defined(WITH_JIT)
1896    GET_JIT_PROF_TABLE(r0)
1897    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1898    cmp     r0,#0
1899    bne     common_updateProfile
1900    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1901    GOTO_OPCODE(ip)                     @ jump to next instruction
1902#else
1903    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1904    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1905    GOTO_OPCODE(ip)                     @ jump to next instruction
1906#endif
1907
1908
1909/* ------------------------------ */
1910    .balign 64
1911.L_OP_UNUSED_3E: /* 0x3e */
1912/* File: armv5te/OP_UNUSED_3E.S */
1913/* File: armv5te/unused.S */
1914    bl      common_abort
1915
1916
1917/* ------------------------------ */
1918    .balign 64
1919.L_OP_UNUSED_3F: /* 0x3f */
1920/* File: armv5te/OP_UNUSED_3F.S */
1921/* File: armv5te/unused.S */
1922    bl      common_abort
1923
1924
1925/* ------------------------------ */
1926    .balign 64
1927.L_OP_UNUSED_40: /* 0x40 */
1928/* File: armv5te/OP_UNUSED_40.S */
1929/* File: armv5te/unused.S */
1930    bl      common_abort
1931
1932
1933/* ------------------------------ */
1934    .balign 64
1935.L_OP_UNUSED_41: /* 0x41 */
1936/* File: armv5te/OP_UNUSED_41.S */
1937/* File: armv5te/unused.S */
1938    bl      common_abort
1939
1940
1941/* ------------------------------ */
1942    .balign 64
1943.L_OP_UNUSED_42: /* 0x42 */
1944/* File: armv5te/OP_UNUSED_42.S */
1945/* File: armv5te/unused.S */
1946    bl      common_abort
1947
1948
1949/* ------------------------------ */
1950    .balign 64
1951.L_OP_UNUSED_43: /* 0x43 */
1952/* File: armv5te/OP_UNUSED_43.S */
1953/* File: armv5te/unused.S */
1954    bl      common_abort
1955
1956
1957/* ------------------------------ */
1958    .balign 64
1959.L_OP_AGET: /* 0x44 */
1960/* File: armv5te/OP_AGET.S */
1961    /*
1962     * Array get, 32 bits or less.  vAA <- vBB[vCC].
1963     *
1964     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
1965     * instructions.  We use a pair of FETCH_Bs instead.
1966     *
1967     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1968     */
1969    /* op vAA, vBB, vCC */
1970    FETCH_B(r2, 1, 0)                   @ r2<- BB
1971    mov     r9, rINST, lsr #8           @ r9<- AA
1972    FETCH_B(r3, 1, 1)                   @ r3<- CC
1973    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
1974    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
1975    cmp     r0, #0                      @ null array object?
1976    beq     common_errNullObject        @ yes, bail
1977    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
1978    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
1979    cmp     r1, r3                      @ compare unsigned index, length
1980    bcs     common_errArrayIndex        @ index >= length, bail
1981    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1982    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
1983    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1984    SET_VREG(r2, r9)                    @ vAA<- r2
1985    GOTO_OPCODE(ip)                     @ jump to next instruction
1986
1987/* ------------------------------ */
1988    .balign 64
1989.L_OP_AGET_WIDE: /* 0x45 */
1990/* File: armv5te/OP_AGET_WIDE.S */
1991    /*
1992     * Array get, 64 bits.  vAA <- vBB[vCC].
1993     *
1994     * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD.
1995     */
1996    /* aget-wide vAA, vBB, vCC */
1997    FETCH(r0, 1)                        @ r0<- CCBB
1998    mov     r9, rINST, lsr #8           @ r9<- AA
1999    and     r2, r0, #255                @ r2<- BB
2000    mov     r3, r0, lsr #8              @ r3<- CC
2001    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2002    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2003    cmp     r0, #0                      @ null array object?
2004    beq     common_errNullObject        @ yes, bail
2005    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2006    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2007    cmp     r1, r3                      @ compare unsigned index, length
2008    bcc     .LOP_AGET_WIDE_finish          @ okay, continue below
2009    b       common_errArrayIndex        @ index >= length, bail
2010    @ May want to swap the order of these two branches depending on how the
2011    @ branch prediction (if any) handles conditional forward branches vs.
2012    @ unconditional forward branches.
2013
2014/* ------------------------------ */
2015    .balign 64
2016.L_OP_AGET_OBJECT: /* 0x46 */
2017/* File: armv5te/OP_AGET_OBJECT.S */
2018/* File: armv5te/OP_AGET.S */
2019    /*
2020     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2021     *
2022     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2023     * instructions.  We use a pair of FETCH_Bs instead.
2024     *
2025     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2026     */
2027    /* op vAA, vBB, vCC */
2028    FETCH_B(r2, 1, 0)                   @ r2<- BB
2029    mov     r9, rINST, lsr #8           @ r9<- AA
2030    FETCH_B(r3, 1, 1)                   @ r3<- CC
2031    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2032    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2033    cmp     r0, #0                      @ null array object?
2034    beq     common_errNullObject        @ yes, bail
2035    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2036    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2037    cmp     r1, r3                      @ compare unsigned index, length
2038    bcs     common_errArrayIndex        @ index >= length, bail
2039    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2040    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2041    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2042    SET_VREG(r2, r9)                    @ vAA<- r2
2043    GOTO_OPCODE(ip)                     @ jump to next instruction
2044
2045
2046/* ------------------------------ */
2047    .balign 64
2048.L_OP_AGET_BOOLEAN: /* 0x47 */
2049/* File: armv5te/OP_AGET_BOOLEAN.S */
2050/* File: armv5te/OP_AGET.S */
2051    /*
2052     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2053     *
2054     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2055     * instructions.  We use a pair of FETCH_Bs instead.
2056     *
2057     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2058     */
2059    /* op vAA, vBB, vCC */
2060    FETCH_B(r2, 1, 0)                   @ r2<- BB
2061    mov     r9, rINST, lsr #8           @ r9<- AA
2062    FETCH_B(r3, 1, 1)                   @ r3<- CC
2063    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2064    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2065    cmp     r0, #0                      @ null array object?
2066    beq     common_errNullObject        @ yes, bail
2067    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2068    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2069    cmp     r1, r3                      @ compare unsigned index, length
2070    bcs     common_errArrayIndex        @ index >= length, bail
2071    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2072    ldrb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2073    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2074    SET_VREG(r2, r9)                    @ vAA<- r2
2075    GOTO_OPCODE(ip)                     @ jump to next instruction
2076
2077
2078/* ------------------------------ */
2079    .balign 64
2080.L_OP_AGET_BYTE: /* 0x48 */
2081/* File: armv5te/OP_AGET_BYTE.S */
2082/* File: armv5te/OP_AGET.S */
2083    /*
2084     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2085     *
2086     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2087     * instructions.  We use a pair of FETCH_Bs instead.
2088     *
2089     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2090     */
2091    /* op vAA, vBB, vCC */
2092    FETCH_B(r2, 1, 0)                   @ r2<- BB
2093    mov     r9, rINST, lsr #8           @ r9<- AA
2094    FETCH_B(r3, 1, 1)                   @ r3<- CC
2095    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2096    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2097    cmp     r0, #0                      @ null array object?
2098    beq     common_errNullObject        @ yes, bail
2099    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2100    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2101    cmp     r1, r3                      @ compare unsigned index, length
2102    bcs     common_errArrayIndex        @ index >= length, bail
2103    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2104    ldrsb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2105    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2106    SET_VREG(r2, r9)                    @ vAA<- r2
2107    GOTO_OPCODE(ip)                     @ jump to next instruction
2108
2109
2110/* ------------------------------ */
2111    .balign 64
2112.L_OP_AGET_CHAR: /* 0x49 */
2113/* File: armv5te/OP_AGET_CHAR.S */
2114/* File: armv5te/OP_AGET.S */
2115    /*
2116     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2117     *
2118     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2119     * instructions.  We use a pair of FETCH_Bs instead.
2120     *
2121     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2122     */
2123    /* op vAA, vBB, vCC */
2124    FETCH_B(r2, 1, 0)                   @ r2<- BB
2125    mov     r9, rINST, lsr #8           @ r9<- AA
2126    FETCH_B(r3, 1, 1)                   @ r3<- CC
2127    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2128    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2129    cmp     r0, #0                      @ null array object?
2130    beq     common_errNullObject        @ yes, bail
2131    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2132    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2133    cmp     r1, r3                      @ compare unsigned index, length
2134    bcs     common_errArrayIndex        @ index >= length, bail
2135    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2136    ldrh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2137    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2138    SET_VREG(r2, r9)                    @ vAA<- r2
2139    GOTO_OPCODE(ip)                     @ jump to next instruction
2140
2141
2142/* ------------------------------ */
2143    .balign 64
2144.L_OP_AGET_SHORT: /* 0x4a */
2145/* File: armv5te/OP_AGET_SHORT.S */
2146/* File: armv5te/OP_AGET.S */
2147    /*
2148     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2149     *
2150     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2151     * instructions.  We use a pair of FETCH_Bs instead.
2152     *
2153     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2154     */
2155    /* op vAA, vBB, vCC */
2156    FETCH_B(r2, 1, 0)                   @ r2<- BB
2157    mov     r9, rINST, lsr #8           @ r9<- AA
2158    FETCH_B(r3, 1, 1)                   @ r3<- CC
2159    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2160    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2161    cmp     r0, #0                      @ null array object?
2162    beq     common_errNullObject        @ yes, bail
2163    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2164    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2165    cmp     r1, r3                      @ compare unsigned index, length
2166    bcs     common_errArrayIndex        @ index >= length, bail
2167    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2168    ldrsh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2169    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2170    SET_VREG(r2, r9)                    @ vAA<- r2
2171    GOTO_OPCODE(ip)                     @ jump to next instruction
2172
2173
2174/* ------------------------------ */
2175    .balign 64
2176.L_OP_APUT: /* 0x4b */
2177/* File: armv5te/OP_APUT.S */
2178    /*
2179     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2180     *
2181     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2182     * instructions.  We use a pair of FETCH_Bs instead.
2183     *
2184     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2185     */
2186    /* op vAA, vBB, vCC */
2187    FETCH_B(r2, 1, 0)                   @ r2<- BB
2188    mov     r9, rINST, lsr #8           @ r9<- AA
2189    FETCH_B(r3, 1, 1)                   @ r3<- CC
2190    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2191    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2192    cmp     r0, #0                      @ null array object?
2193    beq     common_errNullObject        @ yes, bail
2194    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2195    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2196    cmp     r1, r3                      @ compare unsigned index, length
2197    bcs     common_errArrayIndex        @ index >= length, bail
2198    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2199    GET_VREG(r2, r9)                    @ r2<- vAA
2200    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2201    str  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2202    GOTO_OPCODE(ip)                     @ jump to next instruction
2203
2204/* ------------------------------ */
2205    .balign 64
2206.L_OP_APUT_WIDE: /* 0x4c */
2207/* File: armv5te/OP_APUT_WIDE.S */
2208    /*
2209     * Array put, 64 bits.  vBB[vCC] <- vAA.
2210     *
2211     * Arrays of long/double are 64-bit aligned, so it's okay to use STRD.
2212     */
2213    /* aput-wide vAA, vBB, vCC */
2214    FETCH(r0, 1)                        @ r0<- CCBB
2215    mov     r9, rINST, lsr #8           @ r9<- AA
2216    and     r2, r0, #255                @ r2<- BB
2217    mov     r3, r0, lsr #8              @ r3<- CC
2218    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2219    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2220    cmp     r0, #0                      @ null array object?
2221    beq     common_errNullObject        @ yes, bail
2222    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2223    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2224    cmp     r1, r3                      @ compare unsigned index, length
2225    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2226    bcc     .LOP_APUT_WIDE_finish          @ okay, continue below
2227    b       common_errArrayIndex        @ index >= length, bail
2228    @ May want to swap the order of these two branches depending on how the
2229    @ branch prediction (if any) handles conditional forward branches vs.
2230    @ unconditional forward branches.
2231
2232/* ------------------------------ */
2233    .balign 64
2234.L_OP_APUT_OBJECT: /* 0x4d */
2235/* File: armv5te/OP_APUT_OBJECT.S */
2236    /*
2237     * Store an object into an array.  vBB[vCC] <- vAA.
2238     */
2239    /* op vAA, vBB, vCC */
2240    FETCH(r0, 1)                        @ r0<- CCBB
2241    mov     r9, rINST, lsr #8           @ r9<- AA
2242    and     r2, r0, #255                @ r2<- BB
2243    mov     r3, r0, lsr #8              @ r3<- CC
2244    GET_VREG(rINST, r2)                 @ rINST<- vBB (array object)
2245    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2246    cmp     rINST, #0                   @ null array object?
2247    GET_VREG(r9, r9)                    @ r9<- vAA
2248    beq     common_errNullObject        @ yes, bail
2249    ldr     r3, [rINST, #offArrayObject_length]   @ r3<- arrayObj->length
2250    add     r10, rINST, r1, lsl #2      @ r10<- arrayObj + index*width
2251    cmp     r1, r3                      @ compare unsigned index, length
2252    bcc     .LOP_APUT_OBJECT_finish          @ we're okay, continue on
2253    b       common_errArrayIndex        @ index >= length, bail
2254
2255
2256/* ------------------------------ */
2257    .balign 64
2258.L_OP_APUT_BOOLEAN: /* 0x4e */
2259/* File: armv5te/OP_APUT_BOOLEAN.S */
2260/* File: armv5te/OP_APUT.S */
2261    /*
2262     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2263     *
2264     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2265     * instructions.  We use a pair of FETCH_Bs instead.
2266     *
2267     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2268     */
2269    /* op vAA, vBB, vCC */
2270    FETCH_B(r2, 1, 0)                   @ r2<- BB
2271    mov     r9, rINST, lsr #8           @ r9<- AA
2272    FETCH_B(r3, 1, 1)                   @ r3<- CC
2273    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2274    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2275    cmp     r0, #0                      @ null array object?
2276    beq     common_errNullObject        @ yes, bail
2277    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2278    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2279    cmp     r1, r3                      @ compare unsigned index, length
2280    bcs     common_errArrayIndex        @ index >= length, bail
2281    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2282    GET_VREG(r2, r9)                    @ r2<- vAA
2283    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2284    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2285    GOTO_OPCODE(ip)                     @ jump to next instruction
2286
2287
2288/* ------------------------------ */
2289    .balign 64
2290.L_OP_APUT_BYTE: /* 0x4f */
2291/* File: armv5te/OP_APUT_BYTE.S */
2292/* File: armv5te/OP_APUT.S */
2293    /*
2294     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2295     *
2296     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2297     * instructions.  We use a pair of FETCH_Bs instead.
2298     *
2299     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2300     */
2301    /* op vAA, vBB, vCC */
2302    FETCH_B(r2, 1, 0)                   @ r2<- BB
2303    mov     r9, rINST, lsr #8           @ r9<- AA
2304    FETCH_B(r3, 1, 1)                   @ r3<- CC
2305    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2306    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2307    cmp     r0, #0                      @ null array object?
2308    beq     common_errNullObject        @ yes, bail
2309    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2310    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2311    cmp     r1, r3                      @ compare unsigned index, length
2312    bcs     common_errArrayIndex        @ index >= length, bail
2313    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2314    GET_VREG(r2, r9)                    @ r2<- vAA
2315    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2316    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2317    GOTO_OPCODE(ip)                     @ jump to next instruction
2318
2319
2320/* ------------------------------ */
2321    .balign 64
2322.L_OP_APUT_CHAR: /* 0x50 */
2323/* File: armv5te/OP_APUT_CHAR.S */
2324/* File: armv5te/OP_APUT.S */
2325    /*
2326     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2327     *
2328     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2329     * instructions.  We use a pair of FETCH_Bs instead.
2330     *
2331     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2332     */
2333    /* op vAA, vBB, vCC */
2334    FETCH_B(r2, 1, 0)                   @ r2<- BB
2335    mov     r9, rINST, lsr #8           @ r9<- AA
2336    FETCH_B(r3, 1, 1)                   @ r3<- CC
2337    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2338    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2339    cmp     r0, #0                      @ null array object?
2340    beq     common_errNullObject        @ yes, bail
2341    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2342    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2343    cmp     r1, r3                      @ compare unsigned index, length
2344    bcs     common_errArrayIndex        @ index >= length, bail
2345    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2346    GET_VREG(r2, r9)                    @ r2<- vAA
2347    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2348    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2349    GOTO_OPCODE(ip)                     @ jump to next instruction
2350
2351
2352/* ------------------------------ */
2353    .balign 64
2354.L_OP_APUT_SHORT: /* 0x51 */
2355/* File: armv5te/OP_APUT_SHORT.S */
2356/* File: armv5te/OP_APUT.S */
2357    /*
2358     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2359     *
2360     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2361     * instructions.  We use a pair of FETCH_Bs instead.
2362     *
2363     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2364     */
2365    /* op vAA, vBB, vCC */
2366    FETCH_B(r2, 1, 0)                   @ r2<- BB
2367    mov     r9, rINST, lsr #8           @ r9<- AA
2368    FETCH_B(r3, 1, 1)                   @ r3<- CC
2369    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2370    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2371    cmp     r0, #0                      @ null array object?
2372    beq     common_errNullObject        @ yes, bail
2373    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2374    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2375    cmp     r1, r3                      @ compare unsigned index, length
2376    bcs     common_errArrayIndex        @ index >= length, bail
2377    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2378    GET_VREG(r2, r9)                    @ r2<- vAA
2379    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2380    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2381    GOTO_OPCODE(ip)                     @ jump to next instruction
2382
2383
2384/* ------------------------------ */
2385    .balign 64
2386.L_OP_IGET: /* 0x52 */
2387/* File: armv6t2/OP_IGET.S */
2388    /*
2389     * General 32-bit instance field get.
2390     *
2391     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2392     */
2393    /* op vA, vB, field@CCCC */
2394    mov     r0, rINST, lsr #12          @ r0<- B
2395    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2396    FETCH(r1, 1)                        @ r1<- field ref CCCC
2397    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2398    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2399    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2400    cmp     r0, #0                      @ is resolved entry null?
2401    bne     .LOP_IGET_finish          @ no, already resolved
24028:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2403    EXPORT_PC()                         @ resolve() could throw
2404    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2405    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2406    cmp     r0, #0
2407    bne     .LOP_IGET_finish
2408    b       common_exceptionThrown
2409
2410/* ------------------------------ */
2411    .balign 64
2412.L_OP_IGET_WIDE: /* 0x53 */
2413/* File: armv6t2/OP_IGET_WIDE.S */
2414    /*
2415     * Wide 32-bit instance field get.
2416     */
2417    /* iget-wide vA, vB, field@CCCC */
2418    mov     r0, rINST, lsr #12          @ r0<- B
2419    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2420    FETCH(r1, 1)                        @ r1<- field ref CCCC
2421    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2422    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2423    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2424    cmp     r0, #0                      @ is resolved entry null?
2425    bne     .LOP_IGET_WIDE_finish          @ no, already resolved
24268:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2427    EXPORT_PC()                         @ resolve() could throw
2428    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2429    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2430    cmp     r0, #0
2431    bne     .LOP_IGET_WIDE_finish
2432    b       common_exceptionThrown
2433
2434/* ------------------------------ */
2435    .balign 64
2436.L_OP_IGET_OBJECT: /* 0x54 */
2437/* File: armv5te/OP_IGET_OBJECT.S */
2438/* File: armv5te/OP_IGET.S */
2439    /*
2440     * General 32-bit instance field get.
2441     *
2442     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2443     */
2444    /* op vA, vB, field@CCCC */
2445    mov     r0, rINST, lsr #12          @ r0<- B
2446    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2447    FETCH(r1, 1)                        @ r1<- field ref CCCC
2448    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2449    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2450    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2451    cmp     r0, #0                      @ is resolved entry null?
2452    bne     .LOP_IGET_OBJECT_finish          @ no, already resolved
24538:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2454    EXPORT_PC()                         @ resolve() could throw
2455    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2456    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2457    cmp     r0, #0
2458    bne     .LOP_IGET_OBJECT_finish
2459    b       common_exceptionThrown
2460
2461
2462/* ------------------------------ */
2463    .balign 64
2464.L_OP_IGET_BOOLEAN: /* 0x55 */
2465/* File: armv5te/OP_IGET_BOOLEAN.S */
2466@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" }
2467/* File: armv5te/OP_IGET.S */
2468    /*
2469     * General 32-bit instance field get.
2470     *
2471     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2472     */
2473    /* op vA, vB, field@CCCC */
2474    mov     r0, rINST, lsr #12          @ r0<- B
2475    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2476    FETCH(r1, 1)                        @ r1<- field ref CCCC
2477    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2478    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2479    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2480    cmp     r0, #0                      @ is resolved entry null?
2481    bne     .LOP_IGET_BOOLEAN_finish          @ no, already resolved
24828:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2483    EXPORT_PC()                         @ resolve() could throw
2484    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2485    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2486    cmp     r0, #0
2487    bne     .LOP_IGET_BOOLEAN_finish
2488    b       common_exceptionThrown
2489
2490
2491/* ------------------------------ */
2492    .balign 64
2493.L_OP_IGET_BYTE: /* 0x56 */
2494/* File: armv5te/OP_IGET_BYTE.S */
2495@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" }
2496/* File: armv5te/OP_IGET.S */
2497    /*
2498     * General 32-bit instance field get.
2499     *
2500     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2501     */
2502    /* op vA, vB, field@CCCC */
2503    mov     r0, rINST, lsr #12          @ r0<- B
2504    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2505    FETCH(r1, 1)                        @ r1<- field ref CCCC
2506    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2507    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2508    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2509    cmp     r0, #0                      @ is resolved entry null?
2510    bne     .LOP_IGET_BYTE_finish          @ no, already resolved
25118:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2512    EXPORT_PC()                         @ resolve() could throw
2513    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2514    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2515    cmp     r0, #0
2516    bne     .LOP_IGET_BYTE_finish
2517    b       common_exceptionThrown
2518
2519
2520/* ------------------------------ */
2521    .balign 64
2522.L_OP_IGET_CHAR: /* 0x57 */
2523/* File: armv5te/OP_IGET_CHAR.S */
2524@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" }
2525/* File: armv5te/OP_IGET.S */
2526    /*
2527     * General 32-bit instance field get.
2528     *
2529     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2530     */
2531    /* op vA, vB, field@CCCC */
2532    mov     r0, rINST, lsr #12          @ r0<- B
2533    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2534    FETCH(r1, 1)                        @ r1<- field ref CCCC
2535    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2536    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2537    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2538    cmp     r0, #0                      @ is resolved entry null?
2539    bne     .LOP_IGET_CHAR_finish          @ no, already resolved
25408:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2541    EXPORT_PC()                         @ resolve() could throw
2542    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2543    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2544    cmp     r0, #0
2545    bne     .LOP_IGET_CHAR_finish
2546    b       common_exceptionThrown
2547
2548
2549/* ------------------------------ */
2550    .balign 64
2551.L_OP_IGET_SHORT: /* 0x58 */
2552/* File: armv5te/OP_IGET_SHORT.S */
2553@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" }
2554/* File: armv5te/OP_IGET.S */
2555    /*
2556     * General 32-bit instance field get.
2557     *
2558     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2559     */
2560    /* op vA, vB, field@CCCC */
2561    mov     r0, rINST, lsr #12          @ r0<- B
2562    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2563    FETCH(r1, 1)                        @ r1<- field ref CCCC
2564    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2565    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2566    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2567    cmp     r0, #0                      @ is resolved entry null?
2568    bne     .LOP_IGET_SHORT_finish          @ no, already resolved
25698:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2570    EXPORT_PC()                         @ resolve() could throw
2571    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2572    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2573    cmp     r0, #0
2574    bne     .LOP_IGET_SHORT_finish
2575    b       common_exceptionThrown
2576
2577
2578/* ------------------------------ */
2579    .balign 64
2580.L_OP_IPUT: /* 0x59 */
2581/* File: armv6t2/OP_IPUT.S */
2582    /*
2583     * General 32-bit instance field put.
2584     *
2585     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2586     */
2587    /* op vA, vB, field@CCCC */
2588    mov     r0, rINST, lsr #12          @ r0<- B
2589    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2590    FETCH(r1, 1)                        @ r1<- field ref CCCC
2591    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2592    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2593    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2594    cmp     r0, #0                      @ is resolved entry null?
2595    bne     .LOP_IPUT_finish          @ no, already resolved
25968:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2597    EXPORT_PC()                         @ resolve() could throw
2598    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2599    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2600    cmp     r0, #0                      @ success?
2601    bne     .LOP_IPUT_finish          @ yes, finish up
2602    b       common_exceptionThrown
2603
2604/* ------------------------------ */
2605    .balign 64
2606.L_OP_IPUT_WIDE: /* 0x5a */
2607/* File: armv6t2/OP_IPUT_WIDE.S */
2608    /* iput-wide vA, vB, field@CCCC */
2609    mov     r0, rINST, lsr #12          @ r0<- B
2610    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2611    FETCH(r1, 1)                        @ r1<- field ref CCCC
2612    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2613    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2614    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2615    cmp     r0, #0                      @ is resolved entry null?
2616    bne     .LOP_IPUT_WIDE_finish          @ no, already resolved
26178:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2618    EXPORT_PC()                         @ resolve() could throw
2619    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2620    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2621    cmp     r0, #0                      @ success?
2622    bne     .LOP_IPUT_WIDE_finish          @ yes, finish up
2623    b       common_exceptionThrown
2624
2625/* ------------------------------ */
2626    .balign 64
2627.L_OP_IPUT_OBJECT: /* 0x5b */
2628/* File: armv5te/OP_IPUT_OBJECT.S */
2629    /*
2630     * 32-bit instance field put.
2631     *
2632     * for: iput-object, iput-object-volatile
2633     */
2634    /* op vA, vB, field@CCCC */
2635    mov     r0, rINST, lsr #12          @ r0<- B
2636    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2637    FETCH(r1, 1)                        @ r1<- field ref CCCC
2638    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2639    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2640    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2641    cmp     r0, #0                      @ is resolved entry null?
2642    bne     .LOP_IPUT_OBJECT_finish          @ no, already resolved
26438:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2644    EXPORT_PC()                         @ resolve() could throw
2645    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2646    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2647    cmp     r0, #0                      @ success?
2648    bne     .LOP_IPUT_OBJECT_finish          @ yes, finish up
2649    b       common_exceptionThrown
2650
2651/* ------------------------------ */
2652    .balign 64
2653.L_OP_IPUT_BOOLEAN: /* 0x5c */
2654/* File: armv5te/OP_IPUT_BOOLEAN.S */
2655@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" }
2656/* File: armv5te/OP_IPUT.S */
2657    /*
2658     * General 32-bit instance field put.
2659     *
2660     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2661     */
2662    /* op vA, vB, field@CCCC */
2663    mov     r0, rINST, lsr #12          @ r0<- B
2664    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2665    FETCH(r1, 1)                        @ r1<- field ref CCCC
2666    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2667    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2668    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2669    cmp     r0, #0                      @ is resolved entry null?
2670    bne     .LOP_IPUT_BOOLEAN_finish          @ no, already resolved
26718:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2672    EXPORT_PC()                         @ resolve() could throw
2673    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2674    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2675    cmp     r0, #0                      @ success?
2676    bne     .LOP_IPUT_BOOLEAN_finish          @ yes, finish up
2677    b       common_exceptionThrown
2678
2679
2680/* ------------------------------ */
2681    .balign 64
2682.L_OP_IPUT_BYTE: /* 0x5d */
2683/* File: armv5te/OP_IPUT_BYTE.S */
2684@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" }
2685/* File: armv5te/OP_IPUT.S */
2686    /*
2687     * General 32-bit instance field put.
2688     *
2689     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2690     */
2691    /* op vA, vB, field@CCCC */
2692    mov     r0, rINST, lsr #12          @ r0<- B
2693    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2694    FETCH(r1, 1)                        @ r1<- field ref CCCC
2695    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2696    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2697    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2698    cmp     r0, #0                      @ is resolved entry null?
2699    bne     .LOP_IPUT_BYTE_finish          @ no, already resolved
27008:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2701    EXPORT_PC()                         @ resolve() could throw
2702    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2703    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2704    cmp     r0, #0                      @ success?
2705    bne     .LOP_IPUT_BYTE_finish          @ yes, finish up
2706    b       common_exceptionThrown
2707
2708
2709/* ------------------------------ */
2710    .balign 64
2711.L_OP_IPUT_CHAR: /* 0x5e */
2712/* File: armv5te/OP_IPUT_CHAR.S */
2713@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" }
2714/* File: armv5te/OP_IPUT.S */
2715    /*
2716     * General 32-bit instance field put.
2717     *
2718     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2719     */
2720    /* op vA, vB, field@CCCC */
2721    mov     r0, rINST, lsr #12          @ r0<- B
2722    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2723    FETCH(r1, 1)                        @ r1<- field ref CCCC
2724    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2725    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2726    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2727    cmp     r0, #0                      @ is resolved entry null?
2728    bne     .LOP_IPUT_CHAR_finish          @ no, already resolved
27298:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2730    EXPORT_PC()                         @ resolve() could throw
2731    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2732    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2733    cmp     r0, #0                      @ success?
2734    bne     .LOP_IPUT_CHAR_finish          @ yes, finish up
2735    b       common_exceptionThrown
2736
2737
2738/* ------------------------------ */
2739    .balign 64
2740.L_OP_IPUT_SHORT: /* 0x5f */
2741/* File: armv5te/OP_IPUT_SHORT.S */
2742@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" }
2743/* File: armv5te/OP_IPUT.S */
2744    /*
2745     * General 32-bit instance field put.
2746     *
2747     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2748     */
2749    /* op vA, vB, field@CCCC */
2750    mov     r0, rINST, lsr #12          @ r0<- B
2751    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2752    FETCH(r1, 1)                        @ r1<- field ref CCCC
2753    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2754    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2755    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2756    cmp     r0, #0                      @ is resolved entry null?
2757    bne     .LOP_IPUT_SHORT_finish          @ no, already resolved
27588:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2759    EXPORT_PC()                         @ resolve() could throw
2760    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2761    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2762    cmp     r0, #0                      @ success?
2763    bne     .LOP_IPUT_SHORT_finish          @ yes, finish up
2764    b       common_exceptionThrown
2765
2766
2767/* ------------------------------ */
2768    .balign 64
2769.L_OP_SGET: /* 0x60 */
2770/* File: armv5te/OP_SGET.S */
2771    /*
2772     * General 32-bit SGET handler.
2773     *
2774     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2775     */
2776    /* op vAA, field@BBBB */
2777    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2778    FETCH(r1, 1)                        @ r1<- field ref BBBB
2779    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2780    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2781    cmp     r0, #0                      @ is resolved entry null?
2782    beq     .LOP_SGET_resolve         @ yes, do resolve
2783.LOP_SGET_finish: @ field ptr in r0
2784    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2785    @ no-op                             @ acquiring load
2786    mov     r2, rINST, lsr #8           @ r2<- AA
2787    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2788    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2789    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2790    GOTO_OPCODE(ip)                     @ jump to next instruction
2791
2792/* ------------------------------ */
2793    .balign 64
2794.L_OP_SGET_WIDE: /* 0x61 */
2795/* File: armv5te/OP_SGET_WIDE.S */
2796    /*
2797     * 64-bit SGET handler.
2798     */
2799    /* sget-wide vAA, field@BBBB */
2800    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2801    FETCH(r1, 1)                        @ r1<- field ref BBBB
2802    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2803    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2804    cmp     r0, #0                      @ is resolved entry null?
2805    beq     .LOP_SGET_WIDE_resolve         @ yes, do resolve
2806.LOP_SGET_WIDE_finish:
2807    mov     r9, rINST, lsr #8           @ r9<- AA
2808    .if 0
2809    add     r0, r0, #offStaticField_value @ r0<- pointer to data
2810    bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
2811    .else
2812    ldrd    r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
2813    .endif
2814    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2815    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2816    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
2817    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2818    GOTO_OPCODE(ip)                     @ jump to next instruction
2819
2820/* ------------------------------ */
2821    .balign 64
2822.L_OP_SGET_OBJECT: /* 0x62 */
2823/* File: armv5te/OP_SGET_OBJECT.S */
2824/* File: armv5te/OP_SGET.S */
2825    /*
2826     * General 32-bit SGET handler.
2827     *
2828     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2829     */
2830    /* op vAA, field@BBBB */
2831    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2832    FETCH(r1, 1)                        @ r1<- field ref BBBB
2833    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2834    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2835    cmp     r0, #0                      @ is resolved entry null?
2836    beq     .LOP_SGET_OBJECT_resolve         @ yes, do resolve
2837.LOP_SGET_OBJECT_finish: @ field ptr in r0
2838    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2839    @ no-op                             @ acquiring load
2840    mov     r2, rINST, lsr #8           @ r2<- AA
2841    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2842    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2843    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2844    GOTO_OPCODE(ip)                     @ jump to next instruction
2845
2846
2847/* ------------------------------ */
2848    .balign 64
2849.L_OP_SGET_BOOLEAN: /* 0x63 */
2850/* File: armv5te/OP_SGET_BOOLEAN.S */
2851/* File: armv5te/OP_SGET.S */
2852    /*
2853     * General 32-bit SGET handler.
2854     *
2855     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2856     */
2857    /* op vAA, field@BBBB */
2858    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2859    FETCH(r1, 1)                        @ r1<- field ref BBBB
2860    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2861    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2862    cmp     r0, #0                      @ is resolved entry null?
2863    beq     .LOP_SGET_BOOLEAN_resolve         @ yes, do resolve
2864.LOP_SGET_BOOLEAN_finish: @ field ptr in r0
2865    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2866    @ no-op                             @ acquiring load
2867    mov     r2, rINST, lsr #8           @ r2<- AA
2868    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2869    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2870    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2871    GOTO_OPCODE(ip)                     @ jump to next instruction
2872
2873
2874/* ------------------------------ */
2875    .balign 64
2876.L_OP_SGET_BYTE: /* 0x64 */
2877/* File: armv5te/OP_SGET_BYTE.S */
2878/* File: armv5te/OP_SGET.S */
2879    /*
2880     * General 32-bit SGET handler.
2881     *
2882     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2883     */
2884    /* op vAA, field@BBBB */
2885    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2886    FETCH(r1, 1)                        @ r1<- field ref BBBB
2887    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2888    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2889    cmp     r0, #0                      @ is resolved entry null?
2890    beq     .LOP_SGET_BYTE_resolve         @ yes, do resolve
2891.LOP_SGET_BYTE_finish: @ field ptr in r0
2892    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2893    @ no-op                             @ acquiring load
2894    mov     r2, rINST, lsr #8           @ r2<- AA
2895    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2896    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2897    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2898    GOTO_OPCODE(ip)                     @ jump to next instruction
2899
2900
2901/* ------------------------------ */
2902    .balign 64
2903.L_OP_SGET_CHAR: /* 0x65 */
2904/* File: armv5te/OP_SGET_CHAR.S */
2905/* File: armv5te/OP_SGET.S */
2906    /*
2907     * General 32-bit SGET handler.
2908     *
2909     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2910     */
2911    /* op vAA, field@BBBB */
2912    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2913    FETCH(r1, 1)                        @ r1<- field ref BBBB
2914    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2915    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2916    cmp     r0, #0                      @ is resolved entry null?
2917    beq     .LOP_SGET_CHAR_resolve         @ yes, do resolve
2918.LOP_SGET_CHAR_finish: @ field ptr in r0
2919    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2920    @ no-op                             @ acquiring load
2921    mov     r2, rINST, lsr #8           @ r2<- AA
2922    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2923    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2924    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2925    GOTO_OPCODE(ip)                     @ jump to next instruction
2926
2927
2928/* ------------------------------ */
2929    .balign 64
2930.L_OP_SGET_SHORT: /* 0x66 */
2931/* File: armv5te/OP_SGET_SHORT.S */
2932/* File: armv5te/OP_SGET.S */
2933    /*
2934     * General 32-bit SGET handler.
2935     *
2936     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2937     */
2938    /* op vAA, field@BBBB */
2939    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2940    FETCH(r1, 1)                        @ r1<- field ref BBBB
2941    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2942    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2943    cmp     r0, #0                      @ is resolved entry null?
2944    beq     .LOP_SGET_SHORT_resolve         @ yes, do resolve
2945.LOP_SGET_SHORT_finish: @ field ptr in r0
2946    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2947    @ no-op                             @ acquiring load
2948    mov     r2, rINST, lsr #8           @ r2<- AA
2949    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2950    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2951    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2952    GOTO_OPCODE(ip)                     @ jump to next instruction
2953
2954
2955/* ------------------------------ */
2956    .balign 64
2957.L_OP_SPUT: /* 0x67 */
2958/* File: armv5te/OP_SPUT.S */
2959    /*
2960     * General 32-bit SPUT handler.
2961     *
2962     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
2963     */
2964    /* op vAA, field@BBBB */
2965    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2966    FETCH(r1, 1)                        @ r1<- field ref BBBB
2967    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2968    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2969    cmp     r0, #0                      @ is resolved entry null?
2970    beq     .LOP_SPUT_resolve         @ yes, do resolve
2971.LOP_SPUT_finish:   @ field ptr in r0
2972    mov     r2, rINST, lsr #8           @ r2<- AA
2973    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2974    GET_VREG(r1, r2)                    @ r1<- fp[AA]
2975    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2976    @ no-op                             @ releasing store
2977    str     r1, [r0, #offStaticField_value] @ field<- vAA
2978    GOTO_OPCODE(ip)                     @ jump to next instruction
2979
2980/* ------------------------------ */
2981    .balign 64
2982.L_OP_SPUT_WIDE: /* 0x68 */
2983/* File: armv5te/OP_SPUT_WIDE.S */
2984    /*
2985     * 64-bit SPUT handler.
2986     */
2987    /* sput-wide vAA, field@BBBB */
2988    ldr     r0, [rGLUE, #offGlue_methodClassDex]  @ r0<- DvmDex
2989    FETCH(r1, 1)                        @ r1<- field ref BBBB
2990    ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
2991    mov     r9, rINST, lsr #8           @ r9<- AA
2992    ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
2993    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2994    cmp     r2, #0                      @ is resolved entry null?
2995    beq     .LOP_SPUT_WIDE_resolve         @ yes, do resolve
2996.LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9
2997    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2998    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
2999    GET_INST_OPCODE(r10)                @ extract opcode from rINST
3000    .if 0
3001    add     r2, r2, #offStaticField_value @ r2<- pointer to data
3002    bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
3003    .else
3004    strd    r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
3005    .endif
3006    GOTO_OPCODE(r10)                    @ jump to next instruction
3007
3008/* ------------------------------ */
3009    .balign 64
3010.L_OP_SPUT_OBJECT: /* 0x69 */
3011/* File: armv5te/OP_SPUT_OBJECT.S */
3012    /*
3013     * 32-bit SPUT handler for objects
3014     *
3015     * for: sput-object, sput-object-volatile
3016     */
3017    /* op vAA, field@BBBB */
3018    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3019    FETCH(r1, 1)                        @ r1<- field ref BBBB
3020    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3021    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3022    cmp     r0, #0                      @ is resolved entry null?
3023    bne     .LOP_SPUT_OBJECT_finish          @ no, continue
3024    ldr     r9, [rGLUE, #offGlue_method]    @ r9<- current method
3025    EXPORT_PC()                         @ resolve() could throw, so export now
3026    ldr     r0, [r9, #offMethod_clazz]  @ r0<- method->clazz
3027    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
3028    cmp     r0, #0                      @ success?
3029    bne     .LOP_SPUT_OBJECT_finish          @ yes, finish
3030    b       common_exceptionThrown      @ no, handle exception
3031
3032
3033/* ------------------------------ */
3034    .balign 64
3035.L_OP_SPUT_BOOLEAN: /* 0x6a */
3036/* File: armv5te/OP_SPUT_BOOLEAN.S */
3037/* File: armv5te/OP_SPUT.S */
3038    /*
3039     * General 32-bit SPUT handler.
3040     *
3041     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3042     */
3043    /* op vAA, field@BBBB */
3044    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3045    FETCH(r1, 1)                        @ r1<- field ref BBBB
3046    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3047    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3048    cmp     r0, #0                      @ is resolved entry null?
3049    beq     .LOP_SPUT_BOOLEAN_resolve         @ yes, do resolve
3050.LOP_SPUT_BOOLEAN_finish:   @ field ptr in r0
3051    mov     r2, rINST, lsr #8           @ r2<- AA
3052    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3053    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3054    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3055    @ no-op                             @ releasing store
3056    str     r1, [r0, #offStaticField_value] @ field<- vAA
3057    GOTO_OPCODE(ip)                     @ jump to next instruction
3058
3059
3060/* ------------------------------ */
3061    .balign 64
3062.L_OP_SPUT_BYTE: /* 0x6b */
3063/* File: armv5te/OP_SPUT_BYTE.S */
3064/* File: armv5te/OP_SPUT.S */
3065    /*
3066     * General 32-bit SPUT handler.
3067     *
3068     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3069     */
3070    /* op vAA, field@BBBB */
3071    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3072    FETCH(r1, 1)                        @ r1<- field ref BBBB
3073    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3074    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3075    cmp     r0, #0                      @ is resolved entry null?
3076    beq     .LOP_SPUT_BYTE_resolve         @ yes, do resolve
3077.LOP_SPUT_BYTE_finish:   @ field ptr in r0
3078    mov     r2, rINST, lsr #8           @ r2<- AA
3079    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3080    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3081    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3082    @ no-op                             @ releasing store
3083    str     r1, [r0, #offStaticField_value] @ field<- vAA
3084    GOTO_OPCODE(ip)                     @ jump to next instruction
3085
3086
3087/* ------------------------------ */
3088    .balign 64
3089.L_OP_SPUT_CHAR: /* 0x6c */
3090/* File: armv5te/OP_SPUT_CHAR.S */
3091/* File: armv5te/OP_SPUT.S */
3092    /*
3093     * General 32-bit SPUT handler.
3094     *
3095     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3096     */
3097    /* op vAA, field@BBBB */
3098    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3099    FETCH(r1, 1)                        @ r1<- field ref BBBB
3100    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3101    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3102    cmp     r0, #0                      @ is resolved entry null?
3103    beq     .LOP_SPUT_CHAR_resolve         @ yes, do resolve
3104.LOP_SPUT_CHAR_finish:   @ field ptr in r0
3105    mov     r2, rINST, lsr #8           @ r2<- AA
3106    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3107    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3108    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3109    @ no-op                             @ releasing store
3110    str     r1, [r0, #offStaticField_value] @ field<- vAA
3111    GOTO_OPCODE(ip)                     @ jump to next instruction
3112
3113
3114/* ------------------------------ */
3115    .balign 64
3116.L_OP_SPUT_SHORT: /* 0x6d */
3117/* File: armv5te/OP_SPUT_SHORT.S */
3118/* File: armv5te/OP_SPUT.S */
3119    /*
3120     * General 32-bit SPUT handler.
3121     *
3122     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3123     */
3124    /* op vAA, field@BBBB */
3125    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3126    FETCH(r1, 1)                        @ r1<- field ref BBBB
3127    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3128    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3129    cmp     r0, #0                      @ is resolved entry null?
3130    beq     .LOP_SPUT_SHORT_resolve         @ yes, do resolve
3131.LOP_SPUT_SHORT_finish:   @ field ptr in r0
3132    mov     r2, rINST, lsr #8           @ r2<- AA
3133    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3134    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3135    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3136    @ no-op                             @ releasing store
3137    str     r1, [r0, #offStaticField_value] @ field<- vAA
3138    GOTO_OPCODE(ip)                     @ jump to next instruction
3139
3140
3141/* ------------------------------ */
3142    .balign 64
3143.L_OP_INVOKE_VIRTUAL: /* 0x6e */
3144/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3145    /*
3146     * Handle a virtual method call.
3147     *
3148     * for: invoke-virtual, invoke-virtual/range
3149     */
3150    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3151    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3152    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3153    FETCH(r1, 1)                        @ r1<- BBBB
3154    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3155    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3156    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3157    .if     (!0)
3158    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3159    .endif
3160    cmp     r0, #0                      @ already resolved?
3161    EXPORT_PC()                         @ must export for invoke
3162    bne     .LOP_INVOKE_VIRTUAL_continue        @ yes, continue on
3163    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3164    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3165    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3166    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3167    cmp     r0, #0                      @ got null?
3168    bne     .LOP_INVOKE_VIRTUAL_continue        @ no, continue
3169    b       common_exceptionThrown      @ yes, handle exception
3170
3171/* ------------------------------ */
3172    .balign 64
3173.L_OP_INVOKE_SUPER: /* 0x6f */
3174/* File: armv5te/OP_INVOKE_SUPER.S */
3175    /*
3176     * Handle a "super" method call.
3177     *
3178     * for: invoke-super, invoke-super/range
3179     */
3180    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3181    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3182    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3183    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3184    .if     (!0)
3185    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3186    .endif
3187    FETCH(r1, 1)                        @ r1<- BBBB
3188    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3189    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3190    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3191    cmp     r2, #0                      @ null "this"?
3192    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3193    beq     common_errNullObject        @ null "this", throw exception
3194    cmp     r0, #0                      @ already resolved?
3195    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3196    EXPORT_PC()                         @ must export for invoke
3197    bne     .LOP_INVOKE_SUPER_continue        @ resolved, continue on
3198    b       .LOP_INVOKE_SUPER_resolve         @ do resolve now
3199
3200/* ------------------------------ */
3201    .balign 64
3202.L_OP_INVOKE_DIRECT: /* 0x70 */
3203/* File: armv5te/OP_INVOKE_DIRECT.S */
3204    /*
3205     * Handle a direct method call.
3206     *
3207     * (We could defer the "is 'this' pointer null" test to the common
3208     * method invocation code, and use a flag to indicate that static
3209     * calls don't count.  If we do this as part of copying the arguments
3210     * out we could avoiding loading the first arg twice.)
3211     *
3212     * for: invoke-direct, invoke-direct/range
3213     */
3214    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3215    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3216    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3217    FETCH(r1, 1)                        @ r1<- BBBB
3218    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3219    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3220    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3221    .if     (!0)
3222    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3223    .endif
3224    cmp     r0, #0                      @ already resolved?
3225    EXPORT_PC()                         @ must export for invoke
3226    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3227    beq     .LOP_INVOKE_DIRECT_resolve         @ not resolved, do it now
3228.LOP_INVOKE_DIRECT_finish:
3229    cmp     r2, #0                      @ null "this" ref?
3230    bne     common_invokeMethodNoRange   @ no, continue on
3231    b       common_errNullObject        @ yes, throw exception
3232
3233/* ------------------------------ */
3234    .balign 64
3235.L_OP_INVOKE_STATIC: /* 0x71 */
3236/* File: armv5te/OP_INVOKE_STATIC.S */
3237    /*
3238     * Handle a static method call.
3239     *
3240     * for: invoke-static, invoke-static/range
3241     */
3242    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3243    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3244    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3245    FETCH(r1, 1)                        @ r1<- BBBB
3246    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3247    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3248    cmp     r0, #0                      @ already resolved?
3249    EXPORT_PC()                         @ must export for invoke
3250    bne     common_invokeMethodNoRange @ yes, continue on
32510:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3252    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3253    mov     r2, #METHOD_STATIC          @ resolver method type
3254    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3255    cmp     r0, #0                      @ got null?
3256    bne     common_invokeMethodNoRange @ no, continue
3257    b       common_exceptionThrown      @ yes, handle exception
3258
3259/* ------------------------------ */
3260    .balign 64
3261.L_OP_INVOKE_INTERFACE: /* 0x72 */
3262/* File: armv5te/OP_INVOKE_INTERFACE.S */
3263    /*
3264     * Handle an interface method call.
3265     *
3266     * for: invoke-interface, invoke-interface/range
3267     */
3268    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3269    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3270    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3271    FETCH(r1, 1)                        @ r1<- BBBB
3272    .if     (!0)
3273    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3274    .endif
3275    EXPORT_PC()                         @ must export for invoke
3276    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3277    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3278    cmp     r0, #0                      @ null obj?
3279    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3280    beq     common_errNullObject        @ yes, fail
3281    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3282    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3283    cmp     r0, #0                      @ failed?
3284    beq     common_exceptionThrown      @ yes, handle exception
3285    b       common_invokeMethodNoRange @ jump to common handler
3286
3287/* ------------------------------ */
3288    .balign 64
3289.L_OP_UNUSED_73: /* 0x73 */
3290/* File: armv5te/OP_UNUSED_73.S */
3291/* File: armv5te/unused.S */
3292    bl      common_abort
3293
3294
3295/* ------------------------------ */
3296    .balign 64
3297.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
3298/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */
3299/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3300    /*
3301     * Handle a virtual method call.
3302     *
3303     * for: invoke-virtual, invoke-virtual/range
3304     */
3305    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3306    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3307    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3308    FETCH(r1, 1)                        @ r1<- BBBB
3309    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3310    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3311    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3312    .if     (!1)
3313    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3314    .endif
3315    cmp     r0, #0                      @ already resolved?
3316    EXPORT_PC()                         @ must export for invoke
3317    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ yes, continue on
3318    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3319    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3320    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3321    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3322    cmp     r0, #0                      @ got null?
3323    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ no, continue
3324    b       common_exceptionThrown      @ yes, handle exception
3325
3326
3327/* ------------------------------ */
3328    .balign 64
3329.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
3330/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */
3331/* File: armv5te/OP_INVOKE_SUPER.S */
3332    /*
3333     * Handle a "super" method call.
3334     *
3335     * for: invoke-super, invoke-super/range
3336     */
3337    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3338    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3339    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3340    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3341    .if     (!1)
3342    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3343    .endif
3344    FETCH(r1, 1)                        @ r1<- BBBB
3345    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3346    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3347    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3348    cmp     r2, #0                      @ null "this"?
3349    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3350    beq     common_errNullObject        @ null "this", throw exception
3351    cmp     r0, #0                      @ already resolved?
3352    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3353    EXPORT_PC()                         @ must export for invoke
3354    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ resolved, continue on
3355    b       .LOP_INVOKE_SUPER_RANGE_resolve         @ do resolve now
3356
3357
3358/* ------------------------------ */
3359    .balign 64
3360.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
3361/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */
3362/* File: armv5te/OP_INVOKE_DIRECT.S */
3363    /*
3364     * Handle a direct method call.
3365     *
3366     * (We could defer the "is 'this' pointer null" test to the common
3367     * method invocation code, and use a flag to indicate that static
3368     * calls don't count.  If we do this as part of copying the arguments
3369     * out we could avoiding loading the first arg twice.)
3370     *
3371     * for: invoke-direct, invoke-direct/range
3372     */
3373    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3374    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3375    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3376    FETCH(r1, 1)                        @ r1<- BBBB
3377    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3378    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3379    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3380    .if     (!1)
3381    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3382    .endif
3383    cmp     r0, #0                      @ already resolved?
3384    EXPORT_PC()                         @ must export for invoke
3385    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3386    beq     .LOP_INVOKE_DIRECT_RANGE_resolve         @ not resolved, do it now
3387.LOP_INVOKE_DIRECT_RANGE_finish:
3388    cmp     r2, #0                      @ null "this" ref?
3389    bne     common_invokeMethodRange   @ no, continue on
3390    b       common_errNullObject        @ yes, throw exception
3391
3392
3393/* ------------------------------ */
3394    .balign 64
3395.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
3396/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */
3397/* File: armv5te/OP_INVOKE_STATIC.S */
3398    /*
3399     * Handle a static method call.
3400     *
3401     * for: invoke-static, invoke-static/range
3402     */
3403    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3404    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3405    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3406    FETCH(r1, 1)                        @ r1<- BBBB
3407    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3408    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3409    cmp     r0, #0                      @ already resolved?
3410    EXPORT_PC()                         @ must export for invoke
3411    bne     common_invokeMethodRange @ yes, continue on
34120:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3413    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3414    mov     r2, #METHOD_STATIC          @ resolver method type
3415    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3416    cmp     r0, #0                      @ got null?
3417    bne     common_invokeMethodRange @ no, continue
3418    b       common_exceptionThrown      @ yes, handle exception
3419
3420
3421/* ------------------------------ */
3422    .balign 64
3423.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
3424/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */
3425/* File: armv5te/OP_INVOKE_INTERFACE.S */
3426    /*
3427     * Handle an interface method call.
3428     *
3429     * for: invoke-interface, invoke-interface/range
3430     */
3431    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3432    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3433    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3434    FETCH(r1, 1)                        @ r1<- BBBB
3435    .if     (!1)
3436    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3437    .endif
3438    EXPORT_PC()                         @ must export for invoke
3439    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3440    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3441    cmp     r0, #0                      @ null obj?
3442    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3443    beq     common_errNullObject        @ yes, fail
3444    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3445    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3446    cmp     r0, #0                      @ failed?
3447    beq     common_exceptionThrown      @ yes, handle exception
3448    b       common_invokeMethodRange @ jump to common handler
3449
3450
3451/* ------------------------------ */
3452    .balign 64
3453.L_OP_UNUSED_79: /* 0x79 */
3454/* File: armv5te/OP_UNUSED_79.S */
3455/* File: armv5te/unused.S */
3456    bl      common_abort
3457
3458
3459/* ------------------------------ */
3460    .balign 64
3461.L_OP_UNUSED_7A: /* 0x7a */
3462/* File: armv5te/OP_UNUSED_7A.S */
3463/* File: armv5te/unused.S */
3464    bl      common_abort
3465
3466
3467/* ------------------------------ */
3468    .balign 64
3469.L_OP_NEG_INT: /* 0x7b */
3470/* File: armv6t2/OP_NEG_INT.S */
3471/* File: armv6t2/unop.S */
3472    /*
3473     * Generic 32-bit unary operation.  Provide an "instr" line that
3474     * specifies an instruction that performs "result = op r0".
3475     * This could be an ARM instruction or a function call.
3476     *
3477     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3478     *      int-to-byte, int-to-char, int-to-short
3479     */
3480    /* unop vA, vB */
3481    mov     r3, rINST, lsr #12          @ r3<- B
3482    ubfx    r9, rINST, #8, #4           @ r9<- A
3483    GET_VREG(r0, r3)                    @ r0<- vB
3484                               @ optional op; may set condition codes
3485    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3486    rsb     r0, r0, #0                              @ r0<- op, r0-r3 changed
3487    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3488    SET_VREG(r0, r9)                    @ vAA<- r0
3489    GOTO_OPCODE(ip)                     @ jump to next instruction
3490    /* 8-9 instructions */
3491
3492
3493/* ------------------------------ */
3494    .balign 64
3495.L_OP_NOT_INT: /* 0x7c */
3496/* File: armv6t2/OP_NOT_INT.S */
3497/* File: armv6t2/unop.S */
3498    /*
3499     * Generic 32-bit unary operation.  Provide an "instr" line that
3500     * specifies an instruction that performs "result = op r0".
3501     * This could be an ARM instruction or a function call.
3502     *
3503     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3504     *      int-to-byte, int-to-char, int-to-short
3505     */
3506    /* unop vA, vB */
3507    mov     r3, rINST, lsr #12          @ r3<- B
3508    ubfx    r9, rINST, #8, #4           @ r9<- A
3509    GET_VREG(r0, r3)                    @ r0<- vB
3510                               @ optional op; may set condition codes
3511    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3512    mvn     r0, r0                              @ r0<- op, r0-r3 changed
3513    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3514    SET_VREG(r0, r9)                    @ vAA<- r0
3515    GOTO_OPCODE(ip)                     @ jump to next instruction
3516    /* 8-9 instructions */
3517
3518
3519/* ------------------------------ */
3520    .balign 64
3521.L_OP_NEG_LONG: /* 0x7d */
3522/* File: armv6t2/OP_NEG_LONG.S */
3523/* File: armv6t2/unopWide.S */
3524    /*
3525     * Generic 64-bit unary operation.  Provide an "instr" line that
3526     * specifies an instruction that performs "result = op r0/r1".
3527     * This could be an ARM instruction or a function call.
3528     *
3529     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3530     */
3531    /* unop vA, vB */
3532    mov     r3, rINST, lsr #12          @ r3<- B
3533    ubfx    r9, rINST, #8, #4           @ r9<- A
3534    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3535    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3536    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3537    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3538    rsbs    r0, r0, #0                           @ optional op; may set condition codes
3539    rsc     r1, r1, #0                              @ r0/r1<- op, r2-r3 changed
3540    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3541    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3542    GOTO_OPCODE(ip)                     @ jump to next instruction
3543    /* 10-11 instructions */
3544
3545
3546/* ------------------------------ */
3547    .balign 64
3548.L_OP_NOT_LONG: /* 0x7e */
3549/* File: armv6t2/OP_NOT_LONG.S */
3550/* File: armv6t2/unopWide.S */
3551    /*
3552     * Generic 64-bit unary operation.  Provide an "instr" line that
3553     * specifies an instruction that performs "result = op r0/r1".
3554     * This could be an ARM instruction or a function call.
3555     *
3556     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3557     */
3558    /* unop vA, vB */
3559    mov     r3, rINST, lsr #12          @ r3<- B
3560    ubfx    r9, rINST, #8, #4           @ r9<- A
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    /* 10-11 instructions */
3571
3572
3573/* ------------------------------ */
3574    .balign 64
3575.L_OP_NEG_FLOAT: /* 0x7f */
3576/* File: armv6t2/OP_NEG_FLOAT.S */
3577/* File: armv6t2/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    ubfx    r9, rINST, #8, #4           @ r9<- A
3589    GET_VREG(r0, r3)                    @ r0<- vB
3590                               @ optional op; may set condition codes
3591    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3592    add     r0, r0, #0x80000000                              @ r0<- op, r0-r3 changed
3593    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3594    SET_VREG(r0, r9)                    @ vAA<- r0
3595    GOTO_OPCODE(ip)                     @ jump to next instruction
3596    /* 8-9 instructions */
3597
3598
3599/* ------------------------------ */
3600    .balign 64
3601.L_OP_NEG_DOUBLE: /* 0x80 */
3602/* File: armv6t2/OP_NEG_DOUBLE.S */
3603/* File: armv6t2/unopWide.S */
3604    /*
3605     * Generic 64-bit unary operation.  Provide an "instr" line that
3606     * specifies an instruction that performs "result = op r0/r1".
3607     * This could be an ARM instruction or a function call.
3608     *
3609     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3610     */
3611    /* unop vA, vB */
3612    mov     r3, rINST, lsr #12          @ r3<- B
3613    ubfx    r9, rINST, #8, #4           @ r9<- A
3614    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3615    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3616    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3617    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3618                               @ optional op; may set condition codes
3619    add     r1, r1, #0x80000000                              @ r0/r1<- op, r2-r3 changed
3620    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3621    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3622    GOTO_OPCODE(ip)                     @ jump to next instruction
3623    /* 10-11 instructions */
3624
3625
3626/* ------------------------------ */
3627    .balign 64
3628.L_OP_INT_TO_LONG: /* 0x81 */
3629/* File: armv6t2/OP_INT_TO_LONG.S */
3630/* File: armv6t2/unopWider.S */
3631    /*
3632     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3633     * that specifies an instruction that performs "result = op r0", where
3634     * "result" is a 64-bit quantity in r0/r1.
3635     *
3636     * For: int-to-long, int-to-double, float-to-long, float-to-double
3637     */
3638    /* unop vA, vB */
3639    mov     r3, rINST, lsr #12          @ r3<- B
3640    ubfx    r9, rINST, #8, #4           @ r9<- A
3641    GET_VREG(r0, r3)                    @ r0<- vB
3642    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3643                               @ optional op; may set condition codes
3644    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3645    mov     r1, r0, asr #31                              @ r0<- op, r0-r3 changed
3646    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3647    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3648    GOTO_OPCODE(ip)                     @ jump to next instruction
3649    /* 9-10 instructions */
3650
3651
3652/* ------------------------------ */
3653    .balign 64
3654.L_OP_INT_TO_FLOAT: /* 0x82 */
3655/* File: arm-vfp/OP_INT_TO_FLOAT.S */
3656/* File: arm-vfp/funop.S */
3657    /*
3658     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3659     * line that specifies an instruction that performs "s1 = op s0".
3660     *
3661     * for: int-to-float, float-to-int
3662     */
3663    /* unop vA, vB */
3664    mov     r3, rINST, lsr #12          @ r3<- B
3665    mov     r9, rINST, lsr #8           @ r9<- A+
3666    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3667    flds    s0, [r3]                    @ s0<- vB
3668    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3669    and     r9, r9, #15                 @ r9<- A
3670    fsitos  s1, s0                              @ s1<- op
3671    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3672    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3673    fsts    s1, [r9]                    @ vA<- s1
3674    GOTO_OPCODE(ip)                     @ jump to next instruction
3675
3676
3677/* ------------------------------ */
3678    .balign 64
3679.L_OP_INT_TO_DOUBLE: /* 0x83 */
3680/* File: arm-vfp/OP_INT_TO_DOUBLE.S */
3681/* File: arm-vfp/funopWider.S */
3682    /*
3683     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3684     * "instr" line that specifies an instruction that performs "d0 = op s0".
3685     *
3686     * For: int-to-double, float-to-double
3687     */
3688    /* unop vA, vB */
3689    mov     r3, rINST, lsr #12          @ r3<- B
3690    mov     r9, rINST, lsr #8           @ r9<- A+
3691    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3692    flds    s0, [r3]                    @ s0<- vB
3693    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3694    and     r9, r9, #15                 @ r9<- A
3695    fsitod  d0, s0                              @ d0<- op
3696    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3697    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3698    fstd    d0, [r9]                    @ vA<- d0
3699    GOTO_OPCODE(ip)                     @ jump to next instruction
3700
3701
3702/* ------------------------------ */
3703    .balign 64
3704.L_OP_LONG_TO_INT: /* 0x84 */
3705/* File: armv5te/OP_LONG_TO_INT.S */
3706/* we ignore the high word, making this equivalent to a 32-bit reg move */
3707/* File: armv5te/OP_MOVE.S */
3708    /* for move, move-object, long-to-int */
3709    /* op vA, vB */
3710    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
3711    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
3712    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3713    GET_VREG(r2, r1)                    @ r2<- fp[B]
3714    and     r0, r0, #15
3715    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
3716    SET_VREG(r2, r0)                    @ fp[A]<- r2
3717    GOTO_OPCODE(ip)                     @ execute next instruction
3718
3719
3720/* ------------------------------ */
3721    .balign 64
3722.L_OP_LONG_TO_FLOAT: /* 0x85 */
3723/* File: armv6t2/OP_LONG_TO_FLOAT.S */
3724/* File: armv6t2/unopNarrower.S */
3725    /*
3726     * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
3727     * that specifies an instruction that performs "result = op r0/r1", where
3728     * "result" is a 32-bit quantity in r0.
3729     *
3730     * For: long-to-float, double-to-int, double-to-float
3731     *
3732     * (This would work for long-to-int, but that instruction is actually
3733     * an exact match for OP_MOVE.)
3734     */
3735    /* unop vA, vB */
3736    mov     r3, rINST, lsr #12          @ r3<- B
3737    ubfx    r9, rINST, #8, #4           @ r9<- A
3738    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3739    ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
3740    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3741                               @ optional op; may set condition codes
3742    bl      __aeabi_l2f                              @ r0<- op, r0-r3 changed
3743    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3744    SET_VREG(r0, r9)                    @ vA<- r0
3745    GOTO_OPCODE(ip)                     @ jump to next instruction
3746    /* 9-10 instructions */
3747
3748
3749/* ------------------------------ */
3750    .balign 64
3751.L_OP_LONG_TO_DOUBLE: /* 0x86 */
3752/* File: armv6t2/OP_LONG_TO_DOUBLE.S */
3753/* File: armv6t2/unopWide.S */
3754    /*
3755     * Generic 64-bit unary operation.  Provide an "instr" line that
3756     * specifies an instruction that performs "result = op r0/r1".
3757     * This could be an ARM instruction or a function call.
3758     *
3759     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3760     */
3761    /* unop vA, vB */
3762    mov     r3, rINST, lsr #12          @ r3<- B
3763    ubfx    r9, rINST, #8, #4           @ r9<- A
3764    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3765    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3766    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3767    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3768                               @ optional op; may set condition codes
3769    bl      __aeabi_l2d                              @ r0/r1<- op, r2-r3 changed
3770    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3771    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3772    GOTO_OPCODE(ip)                     @ jump to next instruction
3773    /* 10-11 instructions */
3774
3775
3776/* ------------------------------ */
3777    .balign 64
3778.L_OP_FLOAT_TO_INT: /* 0x87 */
3779/* File: arm-vfp/OP_FLOAT_TO_INT.S */
3780/* File: arm-vfp/funop.S */
3781    /*
3782     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3783     * line that specifies an instruction that performs "s1 = op s0".
3784     *
3785     * for: int-to-float, float-to-int
3786     */
3787    /* unop vA, vB */
3788    mov     r3, rINST, lsr #12          @ r3<- B
3789    mov     r9, rINST, lsr #8           @ r9<- A+
3790    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3791    flds    s0, [r3]                    @ s0<- vB
3792    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3793    and     r9, r9, #15                 @ r9<- A
3794    ftosizs s1, s0                              @ s1<- op
3795    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3796    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3797    fsts    s1, [r9]                    @ vA<- s1
3798    GOTO_OPCODE(ip)                     @ jump to next instruction
3799
3800
3801/* ------------------------------ */
3802    .balign 64
3803.L_OP_FLOAT_TO_LONG: /* 0x88 */
3804/* File: armv6t2/OP_FLOAT_TO_LONG.S */
3805@include "armv6t2/unopWider.S" {"instr":"bl      __aeabi_f2lz"}
3806/* File: armv6t2/unopWider.S */
3807    /*
3808     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3809     * that specifies an instruction that performs "result = op r0", where
3810     * "result" is a 64-bit quantity in r0/r1.
3811     *
3812     * For: int-to-long, int-to-double, float-to-long, float-to-double
3813     */
3814    /* unop vA, vB */
3815    mov     r3, rINST, lsr #12          @ r3<- B
3816    ubfx    r9, rINST, #8, #4           @ r9<- A
3817    GET_VREG(r0, r3)                    @ r0<- vB
3818    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3819                               @ optional op; may set condition codes
3820    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3821    bl      f2l_doconv                              @ r0<- op, r0-r3 changed
3822    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3823    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3824    GOTO_OPCODE(ip)                     @ jump to next instruction
3825    /* 9-10 instructions */
3826
3827
3828
3829/* ------------------------------ */
3830    .balign 64
3831.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
3832/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */
3833/* File: arm-vfp/funopWider.S */
3834    /*
3835     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3836     * "instr" line that specifies an instruction that performs "d0 = op s0".
3837     *
3838     * For: int-to-double, float-to-double
3839     */
3840    /* unop vA, vB */
3841    mov     r3, rINST, lsr #12          @ r3<- B
3842    mov     r9, rINST, lsr #8           @ r9<- A+
3843    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3844    flds    s0, [r3]                    @ s0<- vB
3845    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3846    and     r9, r9, #15                 @ r9<- A
3847    fcvtds  d0, s0                              @ d0<- op
3848    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3849    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3850    fstd    d0, [r9]                    @ vA<- d0
3851    GOTO_OPCODE(ip)                     @ jump to next instruction
3852
3853
3854/* ------------------------------ */
3855    .balign 64
3856.L_OP_DOUBLE_TO_INT: /* 0x8a */
3857/* File: arm-vfp/OP_DOUBLE_TO_INT.S */
3858/* File: arm-vfp/funopNarrower.S */
3859    /*
3860     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3861     * "instr" line that specifies an instruction that performs "s0 = op d0".
3862     *
3863     * For: double-to-int, double-to-float
3864     */
3865    /* unop vA, vB */
3866    mov     r3, rINST, lsr #12          @ r3<- B
3867    mov     r9, rINST, lsr #8           @ r9<- A+
3868    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3869    fldd    d0, [r3]                    @ d0<- vB
3870    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3871    and     r9, r9, #15                 @ r9<- A
3872    ftosizd  s0, d0                              @ s0<- op
3873    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3874    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3875    fsts    s0, [r9]                    @ vA<- s0
3876    GOTO_OPCODE(ip)                     @ jump to next instruction
3877
3878
3879/* ------------------------------ */
3880    .balign 64
3881.L_OP_DOUBLE_TO_LONG: /* 0x8b */
3882/* File: armv6t2/OP_DOUBLE_TO_LONG.S */
3883@include "armv6t2/unopWide.S" {"instr":"bl      __aeabi_d2lz"}
3884/* File: armv6t2/unopWide.S */
3885    /*
3886     * Generic 64-bit unary operation.  Provide an "instr" line that
3887     * specifies an instruction that performs "result = op r0/r1".
3888     * This could be an ARM instruction or a function call.
3889     *
3890     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3891     */
3892    /* unop vA, vB */
3893    mov     r3, rINST, lsr #12          @ r3<- B
3894    ubfx    r9, rINST, #8, #4           @ r9<- A
3895    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3896    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3897    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3898    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3899                               @ optional op; may set condition codes
3900    bl      d2l_doconv                              @ r0/r1<- op, r2-r3 changed
3901    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3902    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3903    GOTO_OPCODE(ip)                     @ jump to next instruction
3904    /* 10-11 instructions */
3905
3906
3907
3908/* ------------------------------ */
3909    .balign 64
3910.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
3911/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */
3912/* File: arm-vfp/funopNarrower.S */
3913    /*
3914     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3915     * "instr" line that specifies an instruction that performs "s0 = op d0".
3916     *
3917     * For: double-to-int, double-to-float
3918     */
3919    /* unop vA, vB */
3920    mov     r3, rINST, lsr #12          @ r3<- B
3921    mov     r9, rINST, lsr #8           @ r9<- A+
3922    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3923    fldd    d0, [r3]                    @ d0<- vB
3924    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3925    and     r9, r9, #15                 @ r9<- A
3926    fcvtsd  s0, d0                              @ s0<- op
3927    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3928    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3929    fsts    s0, [r9]                    @ vA<- s0
3930    GOTO_OPCODE(ip)                     @ jump to next instruction
3931
3932
3933/* ------------------------------ */
3934    .balign 64
3935.L_OP_INT_TO_BYTE: /* 0x8d */
3936/* File: armv6t2/OP_INT_TO_BYTE.S */
3937/* File: armv6t2/unop.S */
3938    /*
3939     * Generic 32-bit unary operation.  Provide an "instr" line that
3940     * specifies an instruction that performs "result = op r0".
3941     * This could be an ARM instruction or a function call.
3942     *
3943     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3944     *      int-to-byte, int-to-char, int-to-short
3945     */
3946    /* unop vA, vB */
3947    mov     r3, rINST, lsr #12          @ r3<- B
3948    ubfx    r9, rINST, #8, #4           @ r9<- A
3949    GET_VREG(r0, r3)                    @ r0<- vB
3950                               @ optional op; may set condition codes
3951    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3952    sxtb    r0, r0                              @ r0<- op, r0-r3 changed
3953    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3954    SET_VREG(r0, r9)                    @ vAA<- r0
3955    GOTO_OPCODE(ip)                     @ jump to next instruction
3956    /* 8-9 instructions */
3957
3958
3959/* ------------------------------ */
3960    .balign 64
3961.L_OP_INT_TO_CHAR: /* 0x8e */
3962/* File: armv6t2/OP_INT_TO_CHAR.S */
3963/* File: armv6t2/unop.S */
3964    /*
3965     * Generic 32-bit unary operation.  Provide an "instr" line that
3966     * specifies an instruction that performs "result = op r0".
3967     * This could be an ARM instruction or a function call.
3968     *
3969     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3970     *      int-to-byte, int-to-char, int-to-short
3971     */
3972    /* unop vA, vB */
3973    mov     r3, rINST, lsr #12          @ r3<- B
3974    ubfx    r9, rINST, #8, #4           @ r9<- A
3975    GET_VREG(r0, r3)                    @ r0<- vB
3976                               @ optional op; may set condition codes
3977    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3978    uxth    r0, r0                              @ r0<- op, r0-r3 changed
3979    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3980    SET_VREG(r0, r9)                    @ vAA<- r0
3981    GOTO_OPCODE(ip)                     @ jump to next instruction
3982    /* 8-9 instructions */
3983
3984
3985/* ------------------------------ */
3986    .balign 64
3987.L_OP_INT_TO_SHORT: /* 0x8f */
3988/* File: armv6t2/OP_INT_TO_SHORT.S */
3989/* File: armv6t2/unop.S */
3990    /*
3991     * Generic 32-bit unary operation.  Provide an "instr" line that
3992     * specifies an instruction that performs "result = op r0".
3993     * This could be an ARM instruction or a function call.
3994     *
3995     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3996     *      int-to-byte, int-to-char, int-to-short
3997     */
3998    /* unop vA, vB */
3999    mov     r3, rINST, lsr #12          @ r3<- B
4000    ubfx    r9, rINST, #8, #4           @ r9<- A
4001    GET_VREG(r0, r3)                    @ r0<- vB
4002                               @ optional op; may set condition codes
4003    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4004    sxth    r0, r0                              @ r0<- op, r0-r3 changed
4005    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4006    SET_VREG(r0, r9)                    @ vAA<- r0
4007    GOTO_OPCODE(ip)                     @ jump to next instruction
4008    /* 8-9 instructions */
4009
4010
4011/* ------------------------------ */
4012    .balign 64
4013.L_OP_ADD_INT: /* 0x90 */
4014/* File: armv5te/OP_ADD_INT.S */
4015/* File: armv5te/binop.S */
4016    /*
4017     * Generic 32-bit binary operation.  Provide an "instr" line that
4018     * specifies an instruction that performs "result = r0 op r1".
4019     * This could be an ARM instruction or a function call.  (If the result
4020     * comes back in a register other than r0, you can override "result".)
4021     *
4022     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4023     * vCC (r1).  Useful for integer division and modulus.  Note that we
4024     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4025     * handles it correctly.
4026     *
4027     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4028     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4029     *      mul-float, div-float, rem-float
4030     */
4031    /* binop vAA, vBB, vCC */
4032    FETCH(r0, 1)                        @ r0<- CCBB
4033    mov     r9, rINST, lsr #8           @ r9<- AA
4034    mov     r3, r0, lsr #8              @ r3<- CC
4035    and     r2, r0, #255                @ r2<- BB
4036    GET_VREG(r1, r3)                    @ r1<- vCC
4037    GET_VREG(r0, r2)                    @ r0<- vBB
4038    .if 0
4039    cmp     r1, #0                      @ is second operand zero?
4040    beq     common_errDivideByZero
4041    .endif
4042
4043    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4044                               @ optional op; may set condition codes
4045    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
4046    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4047    SET_VREG(r0, r9)               @ vAA<- r0
4048    GOTO_OPCODE(ip)                     @ jump to next instruction
4049    /* 11-14 instructions */
4050
4051
4052/* ------------------------------ */
4053    .balign 64
4054.L_OP_SUB_INT: /* 0x91 */
4055/* File: armv5te/OP_SUB_INT.S */
4056/* File: armv5te/binop.S */
4057    /*
4058     * Generic 32-bit binary operation.  Provide an "instr" line that
4059     * specifies an instruction that performs "result = r0 op r1".
4060     * This could be an ARM instruction or a function call.  (If the result
4061     * comes back in a register other than r0, you can override "result".)
4062     *
4063     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4064     * vCC (r1).  Useful for integer division and modulus.  Note that we
4065     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4066     * handles it correctly.
4067     *
4068     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4069     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4070     *      mul-float, div-float, rem-float
4071     */
4072    /* binop vAA, vBB, vCC */
4073    FETCH(r0, 1)                        @ r0<- CCBB
4074    mov     r9, rINST, lsr #8           @ r9<- AA
4075    mov     r3, r0, lsr #8              @ r3<- CC
4076    and     r2, r0, #255                @ r2<- BB
4077    GET_VREG(r1, r3)                    @ r1<- vCC
4078    GET_VREG(r0, r2)                    @ r0<- vBB
4079    .if 0
4080    cmp     r1, #0                      @ is second operand zero?
4081    beq     common_errDivideByZero
4082    .endif
4083
4084    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4085                               @ optional op; may set condition codes
4086    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
4087    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4088    SET_VREG(r0, r9)               @ vAA<- r0
4089    GOTO_OPCODE(ip)                     @ jump to next instruction
4090    /* 11-14 instructions */
4091
4092
4093/* ------------------------------ */
4094    .balign 64
4095.L_OP_MUL_INT: /* 0x92 */
4096/* File: armv5te/OP_MUL_INT.S */
4097/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
4098/* File: armv5te/binop.S */
4099    /*
4100     * Generic 32-bit binary operation.  Provide an "instr" line that
4101     * specifies an instruction that performs "result = r0 op r1".
4102     * This could be an ARM instruction or a function call.  (If the result
4103     * comes back in a register other than r0, you can override "result".)
4104     *
4105     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4106     * vCC (r1).  Useful for integer division and modulus.  Note that we
4107     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4108     * handles it correctly.
4109     *
4110     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4111     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4112     *      mul-float, div-float, rem-float
4113     */
4114    /* binop vAA, vBB, vCC */
4115    FETCH(r0, 1)                        @ r0<- CCBB
4116    mov     r9, rINST, lsr #8           @ r9<- AA
4117    mov     r3, r0, lsr #8              @ r3<- CC
4118    and     r2, r0, #255                @ r2<- BB
4119    GET_VREG(r1, r3)                    @ r1<- vCC
4120    GET_VREG(r0, r2)                    @ r0<- vBB
4121    .if 0
4122    cmp     r1, #0                      @ is second operand zero?
4123    beq     common_errDivideByZero
4124    .endif
4125
4126    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4127                               @ optional op; may set condition codes
4128    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
4129    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4130    SET_VREG(r0, r9)               @ vAA<- r0
4131    GOTO_OPCODE(ip)                     @ jump to next instruction
4132    /* 11-14 instructions */
4133
4134
4135/* ------------------------------ */
4136    .balign 64
4137.L_OP_DIV_INT: /* 0x93 */
4138/* File: armv5te/OP_DIV_INT.S */
4139/* File: armv5te/binop.S */
4140    /*
4141     * Generic 32-bit binary operation.  Provide an "instr" line that
4142     * specifies an instruction that performs "result = r0 op r1".
4143     * This could be an ARM instruction or a function call.  (If the result
4144     * comes back in a register other than r0, you can override "result".)
4145     *
4146     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4147     * vCC (r1).  Useful for integer division and modulus.  Note that we
4148     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4149     * handles it correctly.
4150     *
4151     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4152     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4153     *      mul-float, div-float, rem-float
4154     */
4155    /* binop vAA, vBB, vCC */
4156    FETCH(r0, 1)                        @ r0<- CCBB
4157    mov     r9, rINST, lsr #8           @ r9<- AA
4158    mov     r3, r0, lsr #8              @ r3<- CC
4159    and     r2, r0, #255                @ r2<- BB
4160    GET_VREG(r1, r3)                    @ r1<- vCC
4161    GET_VREG(r0, r2)                    @ r0<- vBB
4162    .if 1
4163    cmp     r1, #0                      @ is second operand zero?
4164    beq     common_errDivideByZero
4165    .endif
4166
4167    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4168                               @ optional op; may set condition codes
4169    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
4170    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4171    SET_VREG(r0, r9)               @ vAA<- r0
4172    GOTO_OPCODE(ip)                     @ jump to next instruction
4173    /* 11-14 instructions */
4174
4175
4176/* ------------------------------ */
4177    .balign 64
4178.L_OP_REM_INT: /* 0x94 */
4179/* File: armv5te/OP_REM_INT.S */
4180/* idivmod returns quotient in r0 and remainder in r1 */
4181/* File: armv5te/binop.S */
4182    /*
4183     * Generic 32-bit binary operation.  Provide an "instr" line that
4184     * specifies an instruction that performs "result = r0 op r1".
4185     * This could be an ARM instruction or a function call.  (If the result
4186     * comes back in a register other than r0, you can override "result".)
4187     *
4188     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4189     * vCC (r1).  Useful for integer division and modulus.  Note that we
4190     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4191     * handles it correctly.
4192     *
4193     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4194     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4195     *      mul-float, div-float, rem-float
4196     */
4197    /* binop vAA, vBB, vCC */
4198    FETCH(r0, 1)                        @ r0<- CCBB
4199    mov     r9, rINST, lsr #8           @ r9<- AA
4200    mov     r3, r0, lsr #8              @ r3<- CC
4201    and     r2, r0, #255                @ r2<- BB
4202    GET_VREG(r1, r3)                    @ r1<- vCC
4203    GET_VREG(r0, r2)                    @ r0<- vBB
4204    .if 1
4205    cmp     r1, #0                      @ is second operand zero?
4206    beq     common_errDivideByZero
4207    .endif
4208
4209    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4210                               @ optional op; may set condition codes
4211    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
4212    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4213    SET_VREG(r1, r9)               @ vAA<- r1
4214    GOTO_OPCODE(ip)                     @ jump to next instruction
4215    /* 11-14 instructions */
4216
4217
4218/* ------------------------------ */
4219    .balign 64
4220.L_OP_AND_INT: /* 0x95 */
4221/* File: armv5te/OP_AND_INT.S */
4222/* File: armv5te/binop.S */
4223    /*
4224     * Generic 32-bit binary operation.  Provide an "instr" line that
4225     * specifies an instruction that performs "result = r0 op r1".
4226     * This could be an ARM instruction or a function call.  (If the result
4227     * comes back in a register other than r0, you can override "result".)
4228     *
4229     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4230     * vCC (r1).  Useful for integer division and modulus.  Note that we
4231     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4232     * handles it correctly.
4233     *
4234     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4235     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4236     *      mul-float, div-float, rem-float
4237     */
4238    /* binop vAA, vBB, vCC */
4239    FETCH(r0, 1)                        @ r0<- CCBB
4240    mov     r9, rINST, lsr #8           @ r9<- AA
4241    mov     r3, r0, lsr #8              @ r3<- CC
4242    and     r2, r0, #255                @ r2<- BB
4243    GET_VREG(r1, r3)                    @ r1<- vCC
4244    GET_VREG(r0, r2)                    @ r0<- vBB
4245    .if 0
4246    cmp     r1, #0                      @ is second operand zero?
4247    beq     common_errDivideByZero
4248    .endif
4249
4250    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4251                               @ optional op; may set condition codes
4252    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
4253    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4254    SET_VREG(r0, r9)               @ vAA<- r0
4255    GOTO_OPCODE(ip)                     @ jump to next instruction
4256    /* 11-14 instructions */
4257
4258
4259/* ------------------------------ */
4260    .balign 64
4261.L_OP_OR_INT: /* 0x96 */
4262/* File: armv5te/OP_OR_INT.S */
4263/* File: armv5te/binop.S */
4264    /*
4265     * Generic 32-bit binary operation.  Provide an "instr" line that
4266     * specifies an instruction that performs "result = r0 op r1".
4267     * This could be an ARM instruction or a function call.  (If the result
4268     * comes back in a register other than r0, you can override "result".)
4269     *
4270     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4271     * vCC (r1).  Useful for integer division and modulus.  Note that we
4272     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4273     * handles it correctly.
4274     *
4275     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4276     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4277     *      mul-float, div-float, rem-float
4278     */
4279    /* binop vAA, vBB, vCC */
4280    FETCH(r0, 1)                        @ r0<- CCBB
4281    mov     r9, rINST, lsr #8           @ r9<- AA
4282    mov     r3, r0, lsr #8              @ r3<- CC
4283    and     r2, r0, #255                @ r2<- BB
4284    GET_VREG(r1, r3)                    @ r1<- vCC
4285    GET_VREG(r0, r2)                    @ r0<- vBB
4286    .if 0
4287    cmp     r1, #0                      @ is second operand zero?
4288    beq     common_errDivideByZero
4289    .endif
4290
4291    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4292                               @ optional op; may set condition codes
4293    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
4294    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4295    SET_VREG(r0, r9)               @ vAA<- r0
4296    GOTO_OPCODE(ip)                     @ jump to next instruction
4297    /* 11-14 instructions */
4298
4299
4300/* ------------------------------ */
4301    .balign 64
4302.L_OP_XOR_INT: /* 0x97 */
4303/* File: armv5te/OP_XOR_INT.S */
4304/* File: armv5te/binop.S */
4305    /*
4306     * Generic 32-bit binary operation.  Provide an "instr" line that
4307     * specifies an instruction that performs "result = r0 op r1".
4308     * This could be an ARM instruction or a function call.  (If the result
4309     * comes back in a register other than r0, you can override "result".)
4310     *
4311     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4312     * vCC (r1).  Useful for integer division and modulus.  Note that we
4313     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4314     * handles it correctly.
4315     *
4316     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4317     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4318     *      mul-float, div-float, rem-float
4319     */
4320    /* binop vAA, vBB, vCC */
4321    FETCH(r0, 1)                        @ r0<- CCBB
4322    mov     r9, rINST, lsr #8           @ r9<- AA
4323    mov     r3, r0, lsr #8              @ r3<- CC
4324    and     r2, r0, #255                @ r2<- BB
4325    GET_VREG(r1, r3)                    @ r1<- vCC
4326    GET_VREG(r0, r2)                    @ r0<- vBB
4327    .if 0
4328    cmp     r1, #0                      @ is second operand zero?
4329    beq     common_errDivideByZero
4330    .endif
4331
4332    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4333                               @ optional op; may set condition codes
4334    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
4335    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4336    SET_VREG(r0, r9)               @ vAA<- r0
4337    GOTO_OPCODE(ip)                     @ jump to next instruction
4338    /* 11-14 instructions */
4339
4340
4341/* ------------------------------ */
4342    .balign 64
4343.L_OP_SHL_INT: /* 0x98 */
4344/* File: armv5te/OP_SHL_INT.S */
4345/* File: armv5te/binop.S */
4346    /*
4347     * Generic 32-bit binary operation.  Provide an "instr" line that
4348     * specifies an instruction that performs "result = r0 op r1".
4349     * This could be an ARM instruction or a function call.  (If the result
4350     * comes back in a register other than r0, you can override "result".)
4351     *
4352     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4353     * vCC (r1).  Useful for integer division and modulus.  Note that we
4354     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4355     * handles it correctly.
4356     *
4357     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4358     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4359     *      mul-float, div-float, rem-float
4360     */
4361    /* binop vAA, vBB, vCC */
4362    FETCH(r0, 1)                        @ r0<- CCBB
4363    mov     r9, rINST, lsr #8           @ r9<- AA
4364    mov     r3, r0, lsr #8              @ r3<- CC
4365    and     r2, r0, #255                @ r2<- BB
4366    GET_VREG(r1, r3)                    @ r1<- vCC
4367    GET_VREG(r0, r2)                    @ r0<- vBB
4368    .if 0
4369    cmp     r1, #0                      @ is second operand zero?
4370    beq     common_errDivideByZero
4371    .endif
4372
4373    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4374    and     r1, r1, #31                           @ optional op; may set condition codes
4375    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
4376    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4377    SET_VREG(r0, r9)               @ vAA<- r0
4378    GOTO_OPCODE(ip)                     @ jump to next instruction
4379    /* 11-14 instructions */
4380
4381
4382/* ------------------------------ */
4383    .balign 64
4384.L_OP_SHR_INT: /* 0x99 */
4385/* File: armv5te/OP_SHR_INT.S */
4386/* File: armv5te/binop.S */
4387    /*
4388     * Generic 32-bit binary operation.  Provide an "instr" line that
4389     * specifies an instruction that performs "result = r0 op r1".
4390     * This could be an ARM instruction or a function call.  (If the result
4391     * comes back in a register other than r0, you can override "result".)
4392     *
4393     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4394     * vCC (r1).  Useful for integer division and modulus.  Note that we
4395     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4396     * handles it correctly.
4397     *
4398     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4399     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4400     *      mul-float, div-float, rem-float
4401     */
4402    /* binop vAA, vBB, vCC */
4403    FETCH(r0, 1)                        @ r0<- CCBB
4404    mov     r9, rINST, lsr #8           @ r9<- AA
4405    mov     r3, r0, lsr #8              @ r3<- CC
4406    and     r2, r0, #255                @ r2<- BB
4407    GET_VREG(r1, r3)                    @ r1<- vCC
4408    GET_VREG(r0, r2)                    @ r0<- vBB
4409    .if 0
4410    cmp     r1, #0                      @ is second operand zero?
4411    beq     common_errDivideByZero
4412    .endif
4413
4414    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4415    and     r1, r1, #31                           @ optional op; may set condition codes
4416    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
4417    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4418    SET_VREG(r0, r9)               @ vAA<- r0
4419    GOTO_OPCODE(ip)                     @ jump to next instruction
4420    /* 11-14 instructions */
4421
4422
4423/* ------------------------------ */
4424    .balign 64
4425.L_OP_USHR_INT: /* 0x9a */
4426/* File: armv5te/OP_USHR_INT.S */
4427/* File: armv5te/binop.S */
4428    /*
4429     * Generic 32-bit binary operation.  Provide an "instr" line that
4430     * specifies an instruction that performs "result = r0 op r1".
4431     * This could be an ARM instruction or a function call.  (If the result
4432     * comes back in a register other than r0, you can override "result".)
4433     *
4434     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4435     * vCC (r1).  Useful for integer division and modulus.  Note that we
4436     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4437     * handles it correctly.
4438     *
4439     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4440     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4441     *      mul-float, div-float, rem-float
4442     */
4443    /* binop vAA, vBB, vCC */
4444    FETCH(r0, 1)                        @ r0<- CCBB
4445    mov     r9, rINST, lsr #8           @ r9<- AA
4446    mov     r3, r0, lsr #8              @ r3<- CC
4447    and     r2, r0, #255                @ r2<- BB
4448    GET_VREG(r1, r3)                    @ r1<- vCC
4449    GET_VREG(r0, r2)                    @ r0<- vBB
4450    .if 0
4451    cmp     r1, #0                      @ is second operand zero?
4452    beq     common_errDivideByZero
4453    .endif
4454
4455    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4456    and     r1, r1, #31                           @ optional op; may set condition codes
4457    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
4458    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4459    SET_VREG(r0, r9)               @ vAA<- r0
4460    GOTO_OPCODE(ip)                     @ jump to next instruction
4461    /* 11-14 instructions */
4462
4463
4464/* ------------------------------ */
4465    .balign 64
4466.L_OP_ADD_LONG: /* 0x9b */
4467/* File: armv5te/OP_ADD_LONG.S */
4468/* File: armv5te/binopWide.S */
4469    /*
4470     * Generic 64-bit binary operation.  Provide an "instr" line that
4471     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4472     * This could be an ARM instruction or a function call.  (If the result
4473     * comes back in a register other than r0, you can override "result".)
4474     *
4475     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4476     * vCC (r1).  Useful for integer division and modulus.
4477     *
4478     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4479     *      xor-long, add-double, sub-double, mul-double, div-double,
4480     *      rem-double
4481     *
4482     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4483     */
4484    /* binop vAA, vBB, vCC */
4485    FETCH(r0, 1)                        @ r0<- CCBB
4486    mov     r9, rINST, lsr #8           @ r9<- AA
4487    and     r2, r0, #255                @ r2<- BB
4488    mov     r3, r0, lsr #8              @ r3<- CC
4489    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4490    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4491    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4492    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4493    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4494    .if 0
4495    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4496    beq     common_errDivideByZero
4497    .endif
4498    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4499
4500    adds    r0, r0, r2                           @ optional op; may set condition codes
4501    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
4502    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4503    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4504    GOTO_OPCODE(ip)                     @ jump to next instruction
4505    /* 14-17 instructions */
4506
4507
4508/* ------------------------------ */
4509    .balign 64
4510.L_OP_SUB_LONG: /* 0x9c */
4511/* File: armv5te/OP_SUB_LONG.S */
4512/* File: armv5te/binopWide.S */
4513    /*
4514     * Generic 64-bit binary operation.  Provide an "instr" line that
4515     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4516     * This could be an ARM instruction or a function call.  (If the result
4517     * comes back in a register other than r0, you can override "result".)
4518     *
4519     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4520     * vCC (r1).  Useful for integer division and modulus.
4521     *
4522     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4523     *      xor-long, add-double, sub-double, mul-double, div-double,
4524     *      rem-double
4525     *
4526     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4527     */
4528    /* binop vAA, vBB, vCC */
4529    FETCH(r0, 1)                        @ r0<- CCBB
4530    mov     r9, rINST, lsr #8           @ r9<- AA
4531    and     r2, r0, #255                @ r2<- BB
4532    mov     r3, r0, lsr #8              @ r3<- CC
4533    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4534    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4535    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4536    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4537    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4538    .if 0
4539    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4540    beq     common_errDivideByZero
4541    .endif
4542    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4543
4544    subs    r0, r0, r2                           @ optional op; may set condition codes
4545    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
4546    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4547    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4548    GOTO_OPCODE(ip)                     @ jump to next instruction
4549    /* 14-17 instructions */
4550
4551
4552/* ------------------------------ */
4553    .balign 64
4554.L_OP_MUL_LONG: /* 0x9d */
4555/* File: armv5te/OP_MUL_LONG.S */
4556    /*
4557     * Signed 64-bit integer multiply.
4558     *
4559     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
4560     *        WX
4561     *      x YZ
4562     *  --------
4563     *     ZW ZX
4564     *  YW YX
4565     *
4566     * The low word of the result holds ZX, the high word holds
4567     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
4568     * it doesn't fit in the low 64 bits.
4569     *
4570     * Unlike most ARM math operations, multiply instructions have
4571     * restrictions on using the same register more than once (Rd and Rm
4572     * cannot be the same).
4573     */
4574    /* mul-long vAA, vBB, vCC */
4575    FETCH(r0, 1)                        @ r0<- CCBB
4576    and     r2, r0, #255                @ r2<- BB
4577    mov     r3, r0, lsr #8              @ r3<- CC
4578    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4579    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4580    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4581    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4582    mul     ip, r2, r1                  @  ip<- ZxW
4583    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
4584    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
4585    mov     r0, rINST, lsr #8           @ r0<- AA
4586    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
4587    add     r0, rFP, r0, lsl #2         @ r0<- &fp[AA]
4588    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4589    b       .LOP_MUL_LONG_finish
4590
4591/* ------------------------------ */
4592    .balign 64
4593.L_OP_DIV_LONG: /* 0x9e */
4594/* File: armv5te/OP_DIV_LONG.S */
4595/* File: armv5te/binopWide.S */
4596    /*
4597     * Generic 64-bit binary operation.  Provide an "instr" line that
4598     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4599     * This could be an ARM instruction or a function call.  (If the result
4600     * comes back in a register other than r0, you can override "result".)
4601     *
4602     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4603     * vCC (r1).  Useful for integer division and modulus.
4604     *
4605     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4606     *      xor-long, add-double, sub-double, mul-double, div-double,
4607     *      rem-double
4608     *
4609     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4610     */
4611    /* binop vAA, vBB, vCC */
4612    FETCH(r0, 1)                        @ r0<- CCBB
4613    mov     r9, rINST, lsr #8           @ r9<- AA
4614    and     r2, r0, #255                @ r2<- BB
4615    mov     r3, r0, lsr #8              @ r3<- CC
4616    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4617    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4618    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4619    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4620    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4621    .if 1
4622    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4623    beq     common_errDivideByZero
4624    .endif
4625    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4626
4627                               @ optional op; may set condition codes
4628    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4629    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4630    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4631    GOTO_OPCODE(ip)                     @ jump to next instruction
4632    /* 14-17 instructions */
4633
4634
4635/* ------------------------------ */
4636    .balign 64
4637.L_OP_REM_LONG: /* 0x9f */
4638/* File: armv5te/OP_REM_LONG.S */
4639/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
4640/* File: armv5te/binopWide.S */
4641    /*
4642     * Generic 64-bit binary operation.  Provide an "instr" line that
4643     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4644     * This could be an ARM instruction or a function call.  (If the result
4645     * comes back in a register other than r0, you can override "result".)
4646     *
4647     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4648     * vCC (r1).  Useful for integer division and modulus.
4649     *
4650     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4651     *      xor-long, add-double, sub-double, mul-double, div-double,
4652     *      rem-double
4653     *
4654     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4655     */
4656    /* binop vAA, vBB, vCC */
4657    FETCH(r0, 1)                        @ r0<- CCBB
4658    mov     r9, rINST, lsr #8           @ r9<- AA
4659    and     r2, r0, #255                @ r2<- BB
4660    mov     r3, r0, lsr #8              @ r3<- CC
4661    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4662    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4663    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4664    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4665    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4666    .if 1
4667    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4668    beq     common_errDivideByZero
4669    .endif
4670    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4671
4672                               @ optional op; may set condition codes
4673    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4674    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4675    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
4676    GOTO_OPCODE(ip)                     @ jump to next instruction
4677    /* 14-17 instructions */
4678
4679
4680/* ------------------------------ */
4681    .balign 64
4682.L_OP_AND_LONG: /* 0xa0 */
4683/* File: armv5te/OP_AND_LONG.S */
4684/* File: armv5te/binopWide.S */
4685    /*
4686     * Generic 64-bit binary operation.  Provide an "instr" line that
4687     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4688     * This could be an ARM instruction or a function call.  (If the result
4689     * comes back in a register other than r0, you can override "result".)
4690     *
4691     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4692     * vCC (r1).  Useful for integer division and modulus.
4693     *
4694     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4695     *      xor-long, add-double, sub-double, mul-double, div-double,
4696     *      rem-double
4697     *
4698     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4699     */
4700    /* binop vAA, vBB, vCC */
4701    FETCH(r0, 1)                        @ r0<- CCBB
4702    mov     r9, rINST, lsr #8           @ r9<- AA
4703    and     r2, r0, #255                @ r2<- BB
4704    mov     r3, r0, lsr #8              @ r3<- CC
4705    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4706    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4707    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4708    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4709    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4710    .if 0
4711    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4712    beq     common_errDivideByZero
4713    .endif
4714    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4715
4716    and     r0, r0, r2                           @ optional op; may set condition codes
4717    and     r1, r1, r3                              @ result<- op, r0-r3 changed
4718    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4719    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4720    GOTO_OPCODE(ip)                     @ jump to next instruction
4721    /* 14-17 instructions */
4722
4723
4724/* ------------------------------ */
4725    .balign 64
4726.L_OP_OR_LONG: /* 0xa1 */
4727/* File: armv5te/OP_OR_LONG.S */
4728/* File: armv5te/binopWide.S */
4729    /*
4730     * Generic 64-bit binary operation.  Provide an "instr" line that
4731     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4732     * This could be an ARM instruction or a function call.  (If the result
4733     * comes back in a register other than r0, you can override "result".)
4734     *
4735     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4736     * vCC (r1).  Useful for integer division and modulus.
4737     *
4738     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4739     *      xor-long, add-double, sub-double, mul-double, div-double,
4740     *      rem-double
4741     *
4742     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4743     */
4744    /* binop vAA, vBB, vCC */
4745    FETCH(r0, 1)                        @ r0<- CCBB
4746    mov     r9, rINST, lsr #8           @ r9<- AA
4747    and     r2, r0, #255                @ r2<- BB
4748    mov     r3, r0, lsr #8              @ r3<- CC
4749    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4750    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4751    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4752    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4753    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4754    .if 0
4755    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4756    beq     common_errDivideByZero
4757    .endif
4758    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4759
4760    orr     r0, r0, r2                           @ optional op; may set condition codes
4761    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
4762    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4763    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4764    GOTO_OPCODE(ip)                     @ jump to next instruction
4765    /* 14-17 instructions */
4766
4767
4768/* ------------------------------ */
4769    .balign 64
4770.L_OP_XOR_LONG: /* 0xa2 */
4771/* File: armv5te/OP_XOR_LONG.S */
4772/* File: armv5te/binopWide.S */
4773    /*
4774     * Generic 64-bit binary operation.  Provide an "instr" line that
4775     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4776     * This could be an ARM instruction or a function call.  (If the result
4777     * comes back in a register other than r0, you can override "result".)
4778     *
4779     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4780     * vCC (r1).  Useful for integer division and modulus.
4781     *
4782     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4783     *      xor-long, add-double, sub-double, mul-double, div-double,
4784     *      rem-double
4785     *
4786     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4787     */
4788    /* binop vAA, vBB, vCC */
4789    FETCH(r0, 1)                        @ r0<- CCBB
4790    mov     r9, rINST, lsr #8           @ r9<- AA
4791    and     r2, r0, #255                @ r2<- BB
4792    mov     r3, r0, lsr #8              @ r3<- CC
4793    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4794    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4795    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4796    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4797    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4798    .if 0
4799    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4800    beq     common_errDivideByZero
4801    .endif
4802    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4803
4804    eor     r0, r0, r2                           @ optional op; may set condition codes
4805    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
4806    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4807    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4808    GOTO_OPCODE(ip)                     @ jump to next instruction
4809    /* 14-17 instructions */
4810
4811
4812/* ------------------------------ */
4813    .balign 64
4814.L_OP_SHL_LONG: /* 0xa3 */
4815/* File: armv5te/OP_SHL_LONG.S */
4816    /*
4817     * Long integer shift.  This is different from the generic 32/64-bit
4818     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4819     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4820     * 6 bits of the shift distance.
4821     */
4822    /* shl-long vAA, vBB, vCC */
4823    FETCH(r0, 1)                        @ r0<- CCBB
4824    mov     r9, rINST, lsr #8           @ r9<- AA
4825    and     r3, r0, #255                @ r3<- BB
4826    mov     r0, r0, lsr #8              @ r0<- CC
4827    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4828    GET_VREG(r2, r0)                    @ r2<- vCC
4829    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4830    and     r2, r2, #63                 @ r2<- r2 & 0x3f
4831    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4832
4833    mov     r1, r1, asl r2              @  r1<- r1 << r2
4834    rsb     r3, r2, #32                 @  r3<- 32 - r2
4835    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
4836    subs    ip, r2, #32                 @  ip<- r2 - 32
4837    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
4838    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4839    b       .LOP_SHL_LONG_finish
4840
4841/* ------------------------------ */
4842    .balign 64
4843.L_OP_SHR_LONG: /* 0xa4 */
4844/* File: armv5te/OP_SHR_LONG.S */
4845    /*
4846     * Long integer shift.  This is different from the generic 32/64-bit
4847     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4848     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4849     * 6 bits of the shift distance.
4850     */
4851    /* shr-long vAA, vBB, vCC */
4852    FETCH(r0, 1)                        @ r0<- CCBB
4853    mov     r9, rINST, lsr #8           @ r9<- AA
4854    and     r3, r0, #255                @ r3<- BB
4855    mov     r0, r0, lsr #8              @ r0<- CC
4856    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4857    GET_VREG(r2, r0)                    @ r2<- vCC
4858    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4859    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4860    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4861
4862    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4863    rsb     r3, r2, #32                 @  r3<- 32 - r2
4864    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4865    subs    ip, r2, #32                 @  ip<- r2 - 32
4866    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
4867    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4868    b       .LOP_SHR_LONG_finish
4869
4870/* ------------------------------ */
4871    .balign 64
4872.L_OP_USHR_LONG: /* 0xa5 */
4873/* File: armv5te/OP_USHR_LONG.S */
4874    /*
4875     * Long integer shift.  This is different from the generic 32/64-bit
4876     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4877     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4878     * 6 bits of the shift distance.
4879     */
4880    /* ushr-long vAA, vBB, vCC */
4881    FETCH(r0, 1)                        @ r0<- CCBB
4882    mov     r9, rINST, lsr #8           @ r9<- AA
4883    and     r3, r0, #255                @ r3<- BB
4884    mov     r0, r0, lsr #8              @ r0<- CC
4885    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4886    GET_VREG(r2, r0)                    @ r2<- vCC
4887    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4888    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4889    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4890
4891    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4892    rsb     r3, r2, #32                 @  r3<- 32 - r2
4893    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4894    subs    ip, r2, #32                 @  ip<- r2 - 32
4895    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
4896    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4897    b       .LOP_USHR_LONG_finish
4898
4899/* ------------------------------ */
4900    .balign 64
4901.L_OP_ADD_FLOAT: /* 0xa6 */
4902/* File: arm-vfp/OP_ADD_FLOAT.S */
4903/* File: arm-vfp/fbinop.S */
4904    /*
4905     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4906     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4907     * use the "softfp" ABI, this must be an instruction, not a function call.
4908     *
4909     * For: add-float, sub-float, mul-float, div-float
4910     */
4911    /* floatop vAA, vBB, vCC */
4912    FETCH(r0, 1)                        @ r0<- CCBB
4913    mov     r9, rINST, lsr #8           @ r9<- AA
4914    mov     r3, r0, lsr #8              @ r3<- CC
4915    and     r2, r0, #255                @ r2<- BB
4916    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
4917    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
4918    flds    s1, [r3]                    @ s1<- vCC
4919    flds    s0, [r2]                    @ s0<- vBB
4920
4921    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4922    fadds   s2, s0, s1                              @ s2<- op
4923    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4924    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
4925    fsts    s2, [r9]                    @ vAA<- s2
4926    GOTO_OPCODE(ip)                     @ jump to next instruction
4927
4928
4929/* ------------------------------ */
4930    .balign 64
4931.L_OP_SUB_FLOAT: /* 0xa7 */
4932/* File: arm-vfp/OP_SUB_FLOAT.S */
4933/* File: arm-vfp/fbinop.S */
4934    /*
4935     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4936     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4937     * use the "softfp" ABI, this must be an instruction, not a function call.
4938     *
4939     * For: add-float, sub-float, mul-float, div-float
4940     */
4941    /* floatop vAA, vBB, vCC */
4942    FETCH(r0, 1)                        @ r0<- CCBB
4943    mov     r9, rINST, lsr #8           @ r9<- AA
4944    mov     r3, r0, lsr #8              @ r3<- CC
4945    and     r2, r0, #255                @ r2<- BB
4946    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
4947    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
4948    flds    s1, [r3]                    @ s1<- vCC
4949    flds    s0, [r2]                    @ s0<- vBB
4950
4951    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4952    fsubs   s2, s0, s1                              @ s2<- op
4953    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4954    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
4955    fsts    s2, [r9]                    @ vAA<- s2
4956    GOTO_OPCODE(ip)                     @ jump to next instruction
4957
4958
4959/* ------------------------------ */
4960    .balign 64
4961.L_OP_MUL_FLOAT: /* 0xa8 */
4962/* File: arm-vfp/OP_MUL_FLOAT.S */
4963/* File: arm-vfp/fbinop.S */
4964    /*
4965     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4966     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4967     * use the "softfp" ABI, this must be an instruction, not a function call.
4968     *
4969     * For: add-float, sub-float, mul-float, div-float
4970     */
4971    /* floatop vAA, vBB, vCC */
4972    FETCH(r0, 1)                        @ r0<- CCBB
4973    mov     r9, rINST, lsr #8           @ r9<- AA
4974    mov     r3, r0, lsr #8              @ r3<- CC
4975    and     r2, r0, #255                @ r2<- BB
4976    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
4977    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
4978    flds    s1, [r3]                    @ s1<- vCC
4979    flds    s0, [r2]                    @ s0<- vBB
4980
4981    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4982    fmuls   s2, s0, s1                              @ s2<- op
4983    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4984    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
4985    fsts    s2, [r9]                    @ vAA<- s2
4986    GOTO_OPCODE(ip)                     @ jump to next instruction
4987
4988
4989/* ------------------------------ */
4990    .balign 64
4991.L_OP_DIV_FLOAT: /* 0xa9 */
4992/* File: arm-vfp/OP_DIV_FLOAT.S */
4993/* File: arm-vfp/fbinop.S */
4994    /*
4995     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4996     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4997     * use the "softfp" ABI, this must be an instruction, not a function call.
4998     *
4999     * For: add-float, sub-float, mul-float, div-float
5000     */
5001    /* floatop vAA, vBB, vCC */
5002    FETCH(r0, 1)                        @ r0<- CCBB
5003    mov     r9, rINST, lsr #8           @ r9<- AA
5004    mov     r3, r0, lsr #8              @ r3<- CC
5005    and     r2, r0, #255                @ r2<- BB
5006    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5007    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5008    flds    s1, [r3]                    @ s1<- vCC
5009    flds    s0, [r2]                    @ s0<- vBB
5010
5011    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5012    fdivs   s2, s0, s1                              @ s2<- op
5013    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5014    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5015    fsts    s2, [r9]                    @ vAA<- s2
5016    GOTO_OPCODE(ip)                     @ jump to next instruction
5017
5018
5019/* ------------------------------ */
5020    .balign 64
5021.L_OP_REM_FLOAT: /* 0xaa */
5022/* File: armv5te/OP_REM_FLOAT.S */
5023/* EABI doesn't define a float remainder function, but libm does */
5024/* File: armv5te/binop.S */
5025    /*
5026     * Generic 32-bit binary operation.  Provide an "instr" line that
5027     * specifies an instruction that performs "result = r0 op r1".
5028     * This could be an ARM instruction or a function call.  (If the result
5029     * comes back in a register other than r0, you can override "result".)
5030     *
5031     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5032     * vCC (r1).  Useful for integer division and modulus.  Note that we
5033     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5034     * handles it correctly.
5035     *
5036     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5037     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5038     *      mul-float, div-float, rem-float
5039     */
5040    /* binop vAA, vBB, vCC */
5041    FETCH(r0, 1)                        @ r0<- CCBB
5042    mov     r9, rINST, lsr #8           @ r9<- AA
5043    mov     r3, r0, lsr #8              @ r3<- CC
5044    and     r2, r0, #255                @ r2<- BB
5045    GET_VREG(r1, r3)                    @ r1<- vCC
5046    GET_VREG(r0, r2)                    @ r0<- vBB
5047    .if 0
5048    cmp     r1, #0                      @ is second operand zero?
5049    beq     common_errDivideByZero
5050    .endif
5051
5052    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5053                               @ optional op; may set condition codes
5054    bl      fmodf                              @ r0<- op, r0-r3 changed
5055    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5056    SET_VREG(r0, r9)               @ vAA<- r0
5057    GOTO_OPCODE(ip)                     @ jump to next instruction
5058    /* 11-14 instructions */
5059
5060
5061/* ------------------------------ */
5062    .balign 64
5063.L_OP_ADD_DOUBLE: /* 0xab */
5064/* File: arm-vfp/OP_ADD_DOUBLE.S */
5065/* File: arm-vfp/fbinopWide.S */
5066    /*
5067     * Generic 64-bit double-precision floating point binary operation.
5068     * Provide an "instr" line that specifies an instruction that performs
5069     * "d2 = d0 op d1".
5070     *
5071     * for: add-double, sub-double, mul-double, div-double
5072     */
5073    /* doubleop vAA, vBB, vCC */
5074    FETCH(r0, 1)                        @ r0<- CCBB
5075    mov     r9, rINST, lsr #8           @ r9<- AA
5076    mov     r3, r0, lsr #8              @ r3<- CC
5077    and     r2, r0, #255                @ r2<- BB
5078    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5079    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5080    fldd    d1, [r3]                    @ d1<- vCC
5081    fldd    d0, [r2]                    @ d0<- vBB
5082
5083    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5084    faddd   d2, d0, d1                              @ s2<- op
5085    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5086    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5087    fstd    d2, [r9]                    @ vAA<- d2
5088    GOTO_OPCODE(ip)                     @ jump to next instruction
5089
5090
5091/* ------------------------------ */
5092    .balign 64
5093.L_OP_SUB_DOUBLE: /* 0xac */
5094/* File: arm-vfp/OP_SUB_DOUBLE.S */
5095/* File: arm-vfp/fbinopWide.S */
5096    /*
5097     * Generic 64-bit double-precision floating point binary operation.
5098     * Provide an "instr" line that specifies an instruction that performs
5099     * "d2 = d0 op d1".
5100     *
5101     * for: add-double, sub-double, mul-double, div-double
5102     */
5103    /* doubleop vAA, vBB, vCC */
5104    FETCH(r0, 1)                        @ r0<- CCBB
5105    mov     r9, rINST, lsr #8           @ r9<- AA
5106    mov     r3, r0, lsr #8              @ r3<- CC
5107    and     r2, r0, #255                @ r2<- BB
5108    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5109    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5110    fldd    d1, [r3]                    @ d1<- vCC
5111    fldd    d0, [r2]                    @ d0<- vBB
5112
5113    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5114    fsubd   d2, d0, d1                              @ s2<- op
5115    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5116    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5117    fstd    d2, [r9]                    @ vAA<- d2
5118    GOTO_OPCODE(ip)                     @ jump to next instruction
5119
5120
5121/* ------------------------------ */
5122    .balign 64
5123.L_OP_MUL_DOUBLE: /* 0xad */
5124/* File: arm-vfp/OP_MUL_DOUBLE.S */
5125/* File: arm-vfp/fbinopWide.S */
5126    /*
5127     * Generic 64-bit double-precision floating point binary operation.
5128     * Provide an "instr" line that specifies an instruction that performs
5129     * "d2 = d0 op d1".
5130     *
5131     * for: add-double, sub-double, mul-double, div-double
5132     */
5133    /* doubleop vAA, vBB, vCC */
5134    FETCH(r0, 1)                        @ r0<- CCBB
5135    mov     r9, rINST, lsr #8           @ r9<- AA
5136    mov     r3, r0, lsr #8              @ r3<- CC
5137    and     r2, r0, #255                @ r2<- BB
5138    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5139    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5140    fldd    d1, [r3]                    @ d1<- vCC
5141    fldd    d0, [r2]                    @ d0<- vBB
5142
5143    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5144    fmuld   d2, d0, d1                              @ s2<- op
5145    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5146    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5147    fstd    d2, [r9]                    @ vAA<- d2
5148    GOTO_OPCODE(ip)                     @ jump to next instruction
5149
5150
5151/* ------------------------------ */
5152    .balign 64
5153.L_OP_DIV_DOUBLE: /* 0xae */
5154/* File: arm-vfp/OP_DIV_DOUBLE.S */
5155/* File: arm-vfp/fbinopWide.S */
5156    /*
5157     * Generic 64-bit double-precision floating point binary operation.
5158     * Provide an "instr" line that specifies an instruction that performs
5159     * "d2 = d0 op d1".
5160     *
5161     * for: add-double, sub-double, mul-double, div-double
5162     */
5163    /* doubleop vAA, vBB, vCC */
5164    FETCH(r0, 1)                        @ r0<- CCBB
5165    mov     r9, rINST, lsr #8           @ r9<- AA
5166    mov     r3, r0, lsr #8              @ r3<- CC
5167    and     r2, r0, #255                @ r2<- BB
5168    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5169    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5170    fldd    d1, [r3]                    @ d1<- vCC
5171    fldd    d0, [r2]                    @ d0<- vBB
5172
5173    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5174    fdivd   d2, d0, d1                              @ s2<- op
5175    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5176    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5177    fstd    d2, [r9]                    @ vAA<- d2
5178    GOTO_OPCODE(ip)                     @ jump to next instruction
5179
5180
5181/* ------------------------------ */
5182    .balign 64
5183.L_OP_REM_DOUBLE: /* 0xaf */
5184/* File: armv5te/OP_REM_DOUBLE.S */
5185/* EABI doesn't define a double remainder function, but libm does */
5186/* File: armv5te/binopWide.S */
5187    /*
5188     * Generic 64-bit binary operation.  Provide an "instr" line that
5189     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5190     * This could be an ARM instruction or a function call.  (If the result
5191     * comes back in a register other than r0, you can override "result".)
5192     *
5193     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5194     * vCC (r1).  Useful for integer division and modulus.
5195     *
5196     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5197     *      xor-long, add-double, sub-double, mul-double, div-double,
5198     *      rem-double
5199     *
5200     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5201     */
5202    /* binop vAA, vBB, vCC */
5203    FETCH(r0, 1)                        @ r0<- CCBB
5204    mov     r9, rINST, lsr #8           @ r9<- AA
5205    and     r2, r0, #255                @ r2<- BB
5206    mov     r3, r0, lsr #8              @ r3<- CC
5207    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5208    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5209    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5210    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5211    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5212    .if 0
5213    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5214    beq     common_errDivideByZero
5215    .endif
5216    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5217
5218                               @ optional op; may set condition codes
5219    bl      fmod                              @ result<- op, r0-r3 changed
5220    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5221    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5222    GOTO_OPCODE(ip)                     @ jump to next instruction
5223    /* 14-17 instructions */
5224
5225
5226/* ------------------------------ */
5227    .balign 64
5228.L_OP_ADD_INT_2ADDR: /* 0xb0 */
5229/* File: armv6t2/OP_ADD_INT_2ADDR.S */
5230/* File: armv6t2/binop2addr.S */
5231    /*
5232     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5233     * that specifies an instruction that performs "result = r0 op r1".
5234     * This could be an ARM instruction or a function call.  (If the result
5235     * comes back in a register other than r0, you can override "result".)
5236     *
5237     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5238     * vCC (r1).  Useful for integer division and modulus.
5239     *
5240     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5241     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5242     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5243     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5244     */
5245    /* binop/2addr vA, vB */
5246    mov     r3, rINST, lsr #12          @ r3<- B
5247    ubfx    r9, rINST, #8, #4           @ r9<- A
5248    GET_VREG(r1, r3)                    @ r1<- vB
5249    GET_VREG(r0, r9)                    @ r0<- vA
5250    .if 0
5251    cmp     r1, #0                      @ is second operand zero?
5252    beq     common_errDivideByZero
5253    .endif
5254    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5255
5256                               @ optional op; may set condition codes
5257    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
5258    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5259    SET_VREG(r0, r9)               @ vAA<- r0
5260    GOTO_OPCODE(ip)                     @ jump to next instruction
5261    /* 10-13 instructions */
5262
5263
5264/* ------------------------------ */
5265    .balign 64
5266.L_OP_SUB_INT_2ADDR: /* 0xb1 */
5267/* File: armv6t2/OP_SUB_INT_2ADDR.S */
5268/* File: armv6t2/binop2addr.S */
5269    /*
5270     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5271     * that specifies an instruction that performs "result = r0 op r1".
5272     * This could be an ARM instruction or a function call.  (If the result
5273     * comes back in a register other than r0, you can override "result".)
5274     *
5275     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5276     * vCC (r1).  Useful for integer division and modulus.
5277     *
5278     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5279     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5280     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5281     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5282     */
5283    /* binop/2addr vA, vB */
5284    mov     r3, rINST, lsr #12          @ r3<- B
5285    ubfx    r9, rINST, #8, #4           @ r9<- A
5286    GET_VREG(r1, r3)                    @ r1<- vB
5287    GET_VREG(r0, r9)                    @ r0<- vA
5288    .if 0
5289    cmp     r1, #0                      @ is second operand zero?
5290    beq     common_errDivideByZero
5291    .endif
5292    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5293
5294                               @ optional op; may set condition codes
5295    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
5296    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5297    SET_VREG(r0, r9)               @ vAA<- r0
5298    GOTO_OPCODE(ip)                     @ jump to next instruction
5299    /* 10-13 instructions */
5300
5301
5302/* ------------------------------ */
5303    .balign 64
5304.L_OP_MUL_INT_2ADDR: /* 0xb2 */
5305/* File: armv6t2/OP_MUL_INT_2ADDR.S */
5306/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
5307/* File: armv6t2/binop2addr.S */
5308    /*
5309     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5310     * that specifies an instruction that performs "result = r0 op r1".
5311     * This could be an ARM instruction or a function call.  (If the result
5312     * comes back in a register other than r0, you can override "result".)
5313     *
5314     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5315     * vCC (r1).  Useful for integer division and modulus.
5316     *
5317     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5318     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5319     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5320     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5321     */
5322    /* binop/2addr vA, vB */
5323    mov     r3, rINST, lsr #12          @ r3<- B
5324    ubfx    r9, rINST, #8, #4           @ r9<- A
5325    GET_VREG(r1, r3)                    @ r1<- vB
5326    GET_VREG(r0, r9)                    @ r0<- vA
5327    .if 0
5328    cmp     r1, #0                      @ is second operand zero?
5329    beq     common_errDivideByZero
5330    .endif
5331    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5332
5333                               @ optional op; may set condition codes
5334    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
5335    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5336    SET_VREG(r0, r9)               @ vAA<- r0
5337    GOTO_OPCODE(ip)                     @ jump to next instruction
5338    /* 10-13 instructions */
5339
5340
5341/* ------------------------------ */
5342    .balign 64
5343.L_OP_DIV_INT_2ADDR: /* 0xb3 */
5344/* File: armv6t2/OP_DIV_INT_2ADDR.S */
5345/* File: armv6t2/binop2addr.S */
5346    /*
5347     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5348     * that specifies an instruction that performs "result = r0 op r1".
5349     * This could be an ARM instruction or a function call.  (If the result
5350     * comes back in a register other than r0, you can override "result".)
5351     *
5352     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5353     * vCC (r1).  Useful for integer division and modulus.
5354     *
5355     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5356     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5357     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5358     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5359     */
5360    /* binop/2addr vA, vB */
5361    mov     r3, rINST, lsr #12          @ r3<- B
5362    ubfx    r9, rINST, #8, #4           @ r9<- A
5363    GET_VREG(r1, r3)                    @ r1<- vB
5364    GET_VREG(r0, r9)                    @ r0<- vA
5365    .if 1
5366    cmp     r1, #0                      @ is second operand zero?
5367    beq     common_errDivideByZero
5368    .endif
5369    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5370
5371                               @ optional op; may set condition codes
5372    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
5373    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5374    SET_VREG(r0, r9)               @ vAA<- r0
5375    GOTO_OPCODE(ip)                     @ jump to next instruction
5376    /* 10-13 instructions */
5377
5378
5379/* ------------------------------ */
5380    .balign 64
5381.L_OP_REM_INT_2ADDR: /* 0xb4 */
5382/* File: armv6t2/OP_REM_INT_2ADDR.S */
5383/* idivmod returns quotient in r0 and remainder in r1 */
5384/* File: armv6t2/binop2addr.S */
5385    /*
5386     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5387     * that specifies an instruction that performs "result = r0 op r1".
5388     * This could be an ARM instruction or a function call.  (If the result
5389     * comes back in a register other than r0, you can override "result".)
5390     *
5391     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5392     * vCC (r1).  Useful for integer division and modulus.
5393     *
5394     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5395     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5396     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5397     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5398     */
5399    /* binop/2addr vA, vB */
5400    mov     r3, rINST, lsr #12          @ r3<- B
5401    ubfx    r9, rINST, #8, #4           @ r9<- A
5402    GET_VREG(r1, r3)                    @ r1<- vB
5403    GET_VREG(r0, r9)                    @ r0<- vA
5404    .if 1
5405    cmp     r1, #0                      @ is second operand zero?
5406    beq     common_errDivideByZero
5407    .endif
5408    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5409
5410                               @ optional op; may set condition codes
5411    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
5412    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5413    SET_VREG(r1, r9)               @ vAA<- r1
5414    GOTO_OPCODE(ip)                     @ jump to next instruction
5415    /* 10-13 instructions */
5416
5417
5418/* ------------------------------ */
5419    .balign 64
5420.L_OP_AND_INT_2ADDR: /* 0xb5 */
5421/* File: armv6t2/OP_AND_INT_2ADDR.S */
5422/* File: armv6t2/binop2addr.S */
5423    /*
5424     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5425     * that specifies an instruction that performs "result = r0 op r1".
5426     * This could be an ARM instruction or a function call.  (If the result
5427     * comes back in a register other than r0, you can override "result".)
5428     *
5429     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5430     * vCC (r1).  Useful for integer division and modulus.
5431     *
5432     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5433     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5434     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5435     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5436     */
5437    /* binop/2addr vA, vB */
5438    mov     r3, rINST, lsr #12          @ r3<- B
5439    ubfx    r9, rINST, #8, #4           @ r9<- A
5440    GET_VREG(r1, r3)                    @ r1<- vB
5441    GET_VREG(r0, r9)                    @ r0<- vA
5442    .if 0
5443    cmp     r1, #0                      @ is second operand zero?
5444    beq     common_errDivideByZero
5445    .endif
5446    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5447
5448                               @ optional op; may set condition codes
5449    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
5450    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5451    SET_VREG(r0, r9)               @ vAA<- r0
5452    GOTO_OPCODE(ip)                     @ jump to next instruction
5453    /* 10-13 instructions */
5454
5455
5456/* ------------------------------ */
5457    .balign 64
5458.L_OP_OR_INT_2ADDR: /* 0xb6 */
5459/* File: armv6t2/OP_OR_INT_2ADDR.S */
5460/* File: armv6t2/binop2addr.S */
5461    /*
5462     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5463     * that specifies an instruction that performs "result = r0 op r1".
5464     * This could be an ARM instruction or a function call.  (If the result
5465     * comes back in a register other than r0, you can override "result".)
5466     *
5467     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5468     * vCC (r1).  Useful for integer division and modulus.
5469     *
5470     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5471     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5472     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5473     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5474     */
5475    /* binop/2addr vA, vB */
5476    mov     r3, rINST, lsr #12          @ r3<- B
5477    ubfx    r9, rINST, #8, #4           @ r9<- A
5478    GET_VREG(r1, r3)                    @ r1<- vB
5479    GET_VREG(r0, r9)                    @ r0<- vA
5480    .if 0
5481    cmp     r1, #0                      @ is second operand zero?
5482    beq     common_errDivideByZero
5483    .endif
5484    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5485
5486                               @ optional op; may set condition codes
5487    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
5488    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5489    SET_VREG(r0, r9)               @ vAA<- r0
5490    GOTO_OPCODE(ip)                     @ jump to next instruction
5491    /* 10-13 instructions */
5492
5493
5494/* ------------------------------ */
5495    .balign 64
5496.L_OP_XOR_INT_2ADDR: /* 0xb7 */
5497/* File: armv6t2/OP_XOR_INT_2ADDR.S */
5498/* File: armv6t2/binop2addr.S */
5499    /*
5500     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5501     * that specifies an instruction that performs "result = r0 op r1".
5502     * This could be an ARM instruction or a function call.  (If the result
5503     * comes back in a register other than r0, you can override "result".)
5504     *
5505     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5506     * vCC (r1).  Useful for integer division and modulus.
5507     *
5508     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5509     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5510     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5511     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5512     */
5513    /* binop/2addr vA, vB */
5514    mov     r3, rINST, lsr #12          @ r3<- B
5515    ubfx    r9, rINST, #8, #4           @ r9<- A
5516    GET_VREG(r1, r3)                    @ r1<- vB
5517    GET_VREG(r0, r9)                    @ r0<- vA
5518    .if 0
5519    cmp     r1, #0                      @ is second operand zero?
5520    beq     common_errDivideByZero
5521    .endif
5522    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5523
5524                               @ optional op; may set condition codes
5525    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
5526    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5527    SET_VREG(r0, r9)               @ vAA<- r0
5528    GOTO_OPCODE(ip)                     @ jump to next instruction
5529    /* 10-13 instructions */
5530
5531
5532/* ------------------------------ */
5533    .balign 64
5534.L_OP_SHL_INT_2ADDR: /* 0xb8 */
5535/* File: armv6t2/OP_SHL_INT_2ADDR.S */
5536/* File: armv6t2/binop2addr.S */
5537    /*
5538     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5539     * that specifies an instruction that performs "result = r0 op r1".
5540     * This could be an ARM instruction or a function call.  (If the result
5541     * comes back in a register other than r0, you can override "result".)
5542     *
5543     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5544     * vCC (r1).  Useful for integer division and modulus.
5545     *
5546     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5547     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5548     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5549     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5550     */
5551    /* binop/2addr vA, vB */
5552    mov     r3, rINST, lsr #12          @ r3<- B
5553    ubfx    r9, rINST, #8, #4           @ r9<- A
5554    GET_VREG(r1, r3)                    @ r1<- vB
5555    GET_VREG(r0, r9)                    @ r0<- vA
5556    .if 0
5557    cmp     r1, #0                      @ is second operand zero?
5558    beq     common_errDivideByZero
5559    .endif
5560    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5561
5562    and     r1, r1, #31                           @ optional op; may set condition codes
5563    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
5564    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5565    SET_VREG(r0, r9)               @ vAA<- r0
5566    GOTO_OPCODE(ip)                     @ jump to next instruction
5567    /* 10-13 instructions */
5568
5569
5570/* ------------------------------ */
5571    .balign 64
5572.L_OP_SHR_INT_2ADDR: /* 0xb9 */
5573/* File: armv6t2/OP_SHR_INT_2ADDR.S */
5574/* File: armv6t2/binop2addr.S */
5575    /*
5576     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5577     * that specifies an instruction that performs "result = r0 op r1".
5578     * This could be an ARM instruction or a function call.  (If the result
5579     * comes back in a register other than r0, you can override "result".)
5580     *
5581     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5582     * vCC (r1).  Useful for integer division and modulus.
5583     *
5584     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5585     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5586     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5587     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5588     */
5589    /* binop/2addr vA, vB */
5590    mov     r3, rINST, lsr #12          @ r3<- B
5591    ubfx    r9, rINST, #8, #4           @ r9<- A
5592    GET_VREG(r1, r3)                    @ r1<- vB
5593    GET_VREG(r0, r9)                    @ r0<- vA
5594    .if 0
5595    cmp     r1, #0                      @ is second operand zero?
5596    beq     common_errDivideByZero
5597    .endif
5598    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5599
5600    and     r1, r1, #31                           @ optional op; may set condition codes
5601    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
5602    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5603    SET_VREG(r0, r9)               @ vAA<- r0
5604    GOTO_OPCODE(ip)                     @ jump to next instruction
5605    /* 10-13 instructions */
5606
5607
5608/* ------------------------------ */
5609    .balign 64
5610.L_OP_USHR_INT_2ADDR: /* 0xba */
5611/* File: armv6t2/OP_USHR_INT_2ADDR.S */
5612/* File: armv6t2/binop2addr.S */
5613    /*
5614     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5615     * that specifies an instruction that performs "result = r0 op r1".
5616     * This could be an ARM instruction or a function call.  (If the result
5617     * comes back in a register other than r0, you can override "result".)
5618     *
5619     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5620     * vCC (r1).  Useful for integer division and modulus.
5621     *
5622     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5623     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5624     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5625     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5626     */
5627    /* binop/2addr vA, vB */
5628    mov     r3, rINST, lsr #12          @ r3<- B
5629    ubfx    r9, rINST, #8, #4           @ r9<- A
5630    GET_VREG(r1, r3)                    @ r1<- vB
5631    GET_VREG(r0, r9)                    @ r0<- vA
5632    .if 0
5633    cmp     r1, #0                      @ is second operand zero?
5634    beq     common_errDivideByZero
5635    .endif
5636    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5637
5638    and     r1, r1, #31                           @ optional op; may set condition codes
5639    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
5640    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5641    SET_VREG(r0, r9)               @ vAA<- r0
5642    GOTO_OPCODE(ip)                     @ jump to next instruction
5643    /* 10-13 instructions */
5644
5645
5646/* ------------------------------ */
5647    .balign 64
5648.L_OP_ADD_LONG_2ADDR: /* 0xbb */
5649/* File: armv6t2/OP_ADD_LONG_2ADDR.S */
5650/* File: armv6t2/binopWide2addr.S */
5651    /*
5652     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5653     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5654     * This could be an ARM instruction or a function call.  (If the result
5655     * comes back in a register other than r0, you can override "result".)
5656     *
5657     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5658     * vCC (r1).  Useful for integer division and modulus.
5659     *
5660     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5661     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5662     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5663     *      rem-double/2addr
5664     */
5665    /* binop/2addr vA, vB */
5666    mov     r1, rINST, lsr #12          @ r1<- B
5667    ubfx    r9, rINST, #8, #4           @ r9<- A
5668    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5669    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5670    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5671    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5672    .if 0
5673    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5674    beq     common_errDivideByZero
5675    .endif
5676    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5677
5678    adds    r0, r0, r2                           @ optional op; may set condition codes
5679    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
5680    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5681    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5682    GOTO_OPCODE(ip)                     @ jump to next instruction
5683    /* 12-15 instructions */
5684
5685
5686/* ------------------------------ */
5687    .balign 64
5688.L_OP_SUB_LONG_2ADDR: /* 0xbc */
5689/* File: armv6t2/OP_SUB_LONG_2ADDR.S */
5690/* File: armv6t2/binopWide2addr.S */
5691    /*
5692     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5693     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5694     * This could be an ARM instruction or a function call.  (If the result
5695     * comes back in a register other than r0, you can override "result".)
5696     *
5697     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5698     * vCC (r1).  Useful for integer division and modulus.
5699     *
5700     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5701     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5702     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5703     *      rem-double/2addr
5704     */
5705    /* binop/2addr vA, vB */
5706    mov     r1, rINST, lsr #12          @ r1<- B
5707    ubfx    r9, rINST, #8, #4           @ r9<- A
5708    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5709    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5710    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5711    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5712    .if 0
5713    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5714    beq     common_errDivideByZero
5715    .endif
5716    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5717
5718    subs    r0, r0, r2                           @ optional op; may set condition codes
5719    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
5720    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5721    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5722    GOTO_OPCODE(ip)                     @ jump to next instruction
5723    /* 12-15 instructions */
5724
5725
5726/* ------------------------------ */
5727    .balign 64
5728.L_OP_MUL_LONG_2ADDR: /* 0xbd */
5729/* File: armv6t2/OP_MUL_LONG_2ADDR.S */
5730    /*
5731     * Signed 64-bit integer multiply, "/2addr" version.
5732     *
5733     * See OP_MUL_LONG for an explanation.
5734     *
5735     * We get a little tight on registers, so to avoid looking up &fp[A]
5736     * again we stuff it into rINST.
5737     */
5738    /* mul-long/2addr vA, vB */
5739    mov     r1, rINST, lsr #12          @ r1<- B
5740    ubfx    r9, rINST, #8, #4           @ r9<- A
5741    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5742    add     rINST, rFP, r9, lsl #2      @ rINST<- &fp[A]
5743    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5744    ldmia   rINST, {r0-r1}              @ r0/r1<- vAA/vAA+1
5745    mul     ip, r2, r1                  @  ip<- ZxW
5746    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
5747    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
5748    mov     r0, rINST                   @ r0<- &fp[A] (free up rINST)
5749    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5750    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
5751    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5752    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
5753    GOTO_OPCODE(ip)                     @ jump to next instruction
5754
5755/* ------------------------------ */
5756    .balign 64
5757.L_OP_DIV_LONG_2ADDR: /* 0xbe */
5758/* File: armv6t2/OP_DIV_LONG_2ADDR.S */
5759/* File: armv6t2/binopWide2addr.S */
5760    /*
5761     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5762     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5763     * This could be an ARM instruction or a function call.  (If the result
5764     * comes back in a register other than r0, you can override "result".)
5765     *
5766     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5767     * vCC (r1).  Useful for integer division and modulus.
5768     *
5769     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5770     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5771     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5772     *      rem-double/2addr
5773     */
5774    /* binop/2addr vA, vB */
5775    mov     r1, rINST, lsr #12          @ r1<- B
5776    ubfx    r9, rINST, #8, #4           @ r9<- A
5777    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5778    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5779    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5780    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5781    .if 1
5782    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5783    beq     common_errDivideByZero
5784    .endif
5785    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5786
5787                               @ optional op; may set condition codes
5788    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5789    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5790    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5791    GOTO_OPCODE(ip)                     @ jump to next instruction
5792    /* 12-15 instructions */
5793
5794
5795/* ------------------------------ */
5796    .balign 64
5797.L_OP_REM_LONG_2ADDR: /* 0xbf */
5798/* File: armv6t2/OP_REM_LONG_2ADDR.S */
5799/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
5800/* File: armv6t2/binopWide2addr.S */
5801    /*
5802     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5803     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5804     * This could be an ARM instruction or a function call.  (If the result
5805     * comes back in a register other than r0, you can override "result".)
5806     *
5807     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5808     * vCC (r1).  Useful for integer division and modulus.
5809     *
5810     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5811     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5812     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5813     *      rem-double/2addr
5814     */
5815    /* binop/2addr vA, vB */
5816    mov     r1, rINST, lsr #12          @ r1<- B
5817    ubfx    r9, rINST, #8, #4           @ r9<- A
5818    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5819    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5820    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5821    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5822    .if 1
5823    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5824    beq     common_errDivideByZero
5825    .endif
5826    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5827
5828                               @ optional op; may set condition codes
5829    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5830    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5831    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
5832    GOTO_OPCODE(ip)                     @ jump to next instruction
5833    /* 12-15 instructions */
5834
5835
5836/* ------------------------------ */
5837    .balign 64
5838.L_OP_AND_LONG_2ADDR: /* 0xc0 */
5839/* File: armv6t2/OP_AND_LONG_2ADDR.S */
5840/* File: armv6t2/binopWide2addr.S */
5841    /*
5842     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5843     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5844     * This could be an ARM instruction or a function call.  (If the result
5845     * comes back in a register other than r0, you can override "result".)
5846     *
5847     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5848     * vCC (r1).  Useful for integer division and modulus.
5849     *
5850     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5851     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5852     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5853     *      rem-double/2addr
5854     */
5855    /* binop/2addr vA, vB */
5856    mov     r1, rINST, lsr #12          @ r1<- B
5857    ubfx    r9, rINST, #8, #4           @ r9<- A
5858    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5859    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5860    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5861    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5862    .if 0
5863    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5864    beq     common_errDivideByZero
5865    .endif
5866    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5867
5868    and     r0, r0, r2                           @ optional op; may set condition codes
5869    and     r1, r1, r3                              @ result<- op, r0-r3 changed
5870    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5871    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5872    GOTO_OPCODE(ip)                     @ jump to next instruction
5873    /* 12-15 instructions */
5874
5875
5876/* ------------------------------ */
5877    .balign 64
5878.L_OP_OR_LONG_2ADDR: /* 0xc1 */
5879/* File: armv6t2/OP_OR_LONG_2ADDR.S */
5880/* File: armv6t2/binopWide2addr.S */
5881    /*
5882     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5883     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5884     * This could be an ARM instruction or a function call.  (If the result
5885     * comes back in a register other than r0, you can override "result".)
5886     *
5887     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5888     * vCC (r1).  Useful for integer division and modulus.
5889     *
5890     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5891     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5892     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5893     *      rem-double/2addr
5894     */
5895    /* binop/2addr vA, vB */
5896    mov     r1, rINST, lsr #12          @ r1<- B
5897    ubfx    r9, rINST, #8, #4           @ r9<- A
5898    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5899    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5900    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5901    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5902    .if 0
5903    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5904    beq     common_errDivideByZero
5905    .endif
5906    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5907
5908    orr     r0, r0, r2                           @ optional op; may set condition codes
5909    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
5910    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5911    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5912    GOTO_OPCODE(ip)                     @ jump to next instruction
5913    /* 12-15 instructions */
5914
5915
5916/* ------------------------------ */
5917    .balign 64
5918.L_OP_XOR_LONG_2ADDR: /* 0xc2 */
5919/* File: armv6t2/OP_XOR_LONG_2ADDR.S */
5920/* File: armv6t2/binopWide2addr.S */
5921    /*
5922     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5923     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5924     * This could be an ARM instruction or a function call.  (If the result
5925     * comes back in a register other than r0, you can override "result".)
5926     *
5927     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5928     * vCC (r1).  Useful for integer division and modulus.
5929     *
5930     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5931     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5932     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5933     *      rem-double/2addr
5934     */
5935    /* binop/2addr vA, vB */
5936    mov     r1, rINST, lsr #12          @ r1<- B
5937    ubfx    r9, rINST, #8, #4           @ r9<- A
5938    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5939    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5940    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5941    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5942    .if 0
5943    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5944    beq     common_errDivideByZero
5945    .endif
5946    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5947
5948    eor     r0, r0, r2                           @ optional op; may set condition codes
5949    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
5950    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5951    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5952    GOTO_OPCODE(ip)                     @ jump to next instruction
5953    /* 12-15 instructions */
5954
5955
5956/* ------------------------------ */
5957    .balign 64
5958.L_OP_SHL_LONG_2ADDR: /* 0xc3 */
5959/* File: armv6t2/OP_SHL_LONG_2ADDR.S */
5960    /*
5961     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
5962     * 32-bit shift distance.
5963     */
5964    /* shl-long/2addr vA, vB */
5965    mov     r3, rINST, lsr #12          @ r3<- B
5966    ubfx    r9, rINST, #8, #4           @ r9<- A
5967    GET_VREG(r2, r3)                    @ r2<- vB
5968    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5969    and     r2, r2, #63                 @ r2<- r2 & 0x3f
5970    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5971
5972    mov     r1, r1, asl r2              @  r1<- r1 << r2
5973    rsb     r3, r2, #32                 @  r3<- 32 - r2
5974    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
5975    subs    ip, r2, #32                 @  ip<- r2 - 32
5976    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5977    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
5978    mov     r0, r0, asl r2              @  r0<- r0 << r2
5979    b       .LOP_SHL_LONG_2ADDR_finish
5980
5981/* ------------------------------ */
5982    .balign 64
5983.L_OP_SHR_LONG_2ADDR: /* 0xc4 */
5984/* File: armv6t2/OP_SHR_LONG_2ADDR.S */
5985    /*
5986     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
5987     * 32-bit shift distance.
5988     */
5989    /* shr-long/2addr vA, vB */
5990    mov     r3, rINST, lsr #12          @ r3<- B
5991    ubfx    r9, rINST, #8, #4           @ r9<- A
5992    GET_VREG(r2, r3)                    @ r2<- vB
5993    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5994    and     r2, r2, #63                 @ r2<- r2 & 0x3f
5995    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5996
5997    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
5998    rsb     r3, r2, #32                 @  r3<- 32 - r2
5999    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6000    subs    ip, r2, #32                 @  ip<- r2 - 32
6001    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6002    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
6003    mov     r1, r1, asr r2              @  r1<- r1 >> r2
6004    b       .LOP_SHR_LONG_2ADDR_finish
6005
6006/* ------------------------------ */
6007    .balign 64
6008.L_OP_USHR_LONG_2ADDR: /* 0xc5 */
6009/* File: armv6t2/OP_USHR_LONG_2ADDR.S */
6010    /*
6011     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6012     * 32-bit shift distance.
6013     */
6014    /* ushr-long/2addr vA, vB */
6015    mov     r3, rINST, lsr #12          @ r3<- B
6016    ubfx    r9, rINST, #8, #4           @ r9<- A
6017    GET_VREG(r2, r3)                    @ r2<- vB
6018    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6019    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6020    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6021
6022    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6023    rsb     r3, r2, #32                 @  r3<- 32 - r2
6024    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6025    subs    ip, r2, #32                 @  ip<- r2 - 32
6026    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6027    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
6028    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
6029    b       .LOP_USHR_LONG_2ADDR_finish
6030
6031/* ------------------------------ */
6032    .balign 64
6033.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
6034/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */
6035/* File: arm-vfp/fbinop2addr.S */
6036    /*
6037     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6038     * an "instr" line that specifies an instruction that performs
6039     * "s2 = s0 op s1".
6040     *
6041     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6042     */
6043    /* binop/2addr vA, vB */
6044    mov     r3, rINST, lsr #12          @ r3<- B
6045    mov     r9, rINST, lsr #8           @ r9<- A+
6046    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6047    and     r9, r9, #15                 @ r9<- A
6048    flds    s1, [r3]                    @ s1<- vB
6049    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6050    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6051    flds    s0, [r9]                    @ s0<- vA
6052
6053    fadds   s2, s0, s1                              @ s2<- op
6054    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6055    fsts    s2, [r9]                    @ vAA<- s2
6056    GOTO_OPCODE(ip)                     @ jump to next instruction
6057
6058
6059/* ------------------------------ */
6060    .balign 64
6061.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
6062/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */
6063/* File: arm-vfp/fbinop2addr.S */
6064    /*
6065     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6066     * an "instr" line that specifies an instruction that performs
6067     * "s2 = s0 op s1".
6068     *
6069     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6070     */
6071    /* binop/2addr vA, vB */
6072    mov     r3, rINST, lsr #12          @ r3<- B
6073    mov     r9, rINST, lsr #8           @ r9<- A+
6074    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6075    and     r9, r9, #15                 @ r9<- A
6076    flds    s1, [r3]                    @ s1<- vB
6077    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6078    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6079    flds    s0, [r9]                    @ s0<- vA
6080
6081    fsubs   s2, s0, s1                              @ s2<- op
6082    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6083    fsts    s2, [r9]                    @ vAA<- s2
6084    GOTO_OPCODE(ip)                     @ jump to next instruction
6085
6086
6087/* ------------------------------ */
6088    .balign 64
6089.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
6090/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */
6091/* File: arm-vfp/fbinop2addr.S */
6092    /*
6093     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6094     * an "instr" line that specifies an instruction that performs
6095     * "s2 = s0 op s1".
6096     *
6097     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6098     */
6099    /* binop/2addr vA, vB */
6100    mov     r3, rINST, lsr #12          @ r3<- B
6101    mov     r9, rINST, lsr #8           @ r9<- A+
6102    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6103    and     r9, r9, #15                 @ r9<- A
6104    flds    s1, [r3]                    @ s1<- vB
6105    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6106    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6107    flds    s0, [r9]                    @ s0<- vA
6108
6109    fmuls   s2, s0, s1                              @ s2<- op
6110    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6111    fsts    s2, [r9]                    @ vAA<- s2
6112    GOTO_OPCODE(ip)                     @ jump to next instruction
6113
6114
6115/* ------------------------------ */
6116    .balign 64
6117.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
6118/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */
6119/* File: arm-vfp/fbinop2addr.S */
6120    /*
6121     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6122     * an "instr" line that specifies an instruction that performs
6123     * "s2 = s0 op s1".
6124     *
6125     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6126     */
6127    /* binop/2addr vA, vB */
6128    mov     r3, rINST, lsr #12          @ r3<- B
6129    mov     r9, rINST, lsr #8           @ r9<- A+
6130    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6131    and     r9, r9, #15                 @ r9<- A
6132    flds    s1, [r3]                    @ s1<- vB
6133    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6134    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6135    flds    s0, [r9]                    @ s0<- vA
6136
6137    fdivs   s2, s0, s1                              @ s2<- op
6138    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6139    fsts    s2, [r9]                    @ vAA<- s2
6140    GOTO_OPCODE(ip)                     @ jump to next instruction
6141
6142
6143/* ------------------------------ */
6144    .balign 64
6145.L_OP_REM_FLOAT_2ADDR: /* 0xca */
6146/* File: armv6t2/OP_REM_FLOAT_2ADDR.S */
6147/* EABI doesn't define a float remainder function, but libm does */
6148/* File: armv6t2/binop2addr.S */
6149    /*
6150     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6151     * that specifies an instruction that performs "result = r0 op r1".
6152     * This could be an ARM instruction or a function call.  (If the result
6153     * comes back in a register other than r0, you can override "result".)
6154     *
6155     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6156     * vCC (r1).  Useful for integer division and modulus.
6157     *
6158     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6159     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6160     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6161     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6162     */
6163    /* binop/2addr vA, vB */
6164    mov     r3, rINST, lsr #12          @ r3<- B
6165    ubfx    r9, rINST, #8, #4           @ r9<- A
6166    GET_VREG(r1, r3)                    @ r1<- vB
6167    GET_VREG(r0, r9)                    @ r0<- vA
6168    .if 0
6169    cmp     r1, #0                      @ is second operand zero?
6170    beq     common_errDivideByZero
6171    .endif
6172    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6173
6174                               @ optional op; may set condition codes
6175    bl      fmodf                              @ r0<- op, r0-r3 changed
6176    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6177    SET_VREG(r0, r9)               @ vAA<- r0
6178    GOTO_OPCODE(ip)                     @ jump to next instruction
6179    /* 10-13 instructions */
6180
6181
6182/* ------------------------------ */
6183    .balign 64
6184.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
6185/* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */
6186/* File: arm-vfp/fbinopWide2addr.S */
6187    /*
6188     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6189     * an "instr" line that specifies an instruction that performs
6190     * "d2 = d0 op d1".
6191     *
6192     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6193     *      div-double/2addr
6194     */
6195    /* binop/2addr vA, vB */
6196    mov     r3, rINST, lsr #12          @ r3<- B
6197    mov     r9, rINST, lsr #8           @ r9<- A+
6198    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6199    and     r9, r9, #15                 @ r9<- A
6200    fldd    d1, [r3]                    @ d1<- vB
6201    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6202    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6203    fldd    d0, [r9]                    @ d0<- vA
6204
6205    faddd   d2, d0, d1                              @ d2<- op
6206    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6207    fstd    d2, [r9]                    @ vAA<- d2
6208    GOTO_OPCODE(ip)                     @ jump to next instruction
6209
6210
6211/* ------------------------------ */
6212    .balign 64
6213.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
6214/* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */
6215/* File: arm-vfp/fbinopWide2addr.S */
6216    /*
6217     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6218     * an "instr" line that specifies an instruction that performs
6219     * "d2 = d0 op d1".
6220     *
6221     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6222     *      div-double/2addr
6223     */
6224    /* binop/2addr vA, vB */
6225    mov     r3, rINST, lsr #12          @ r3<- B
6226    mov     r9, rINST, lsr #8           @ r9<- A+
6227    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6228    and     r9, r9, #15                 @ r9<- A
6229    fldd    d1, [r3]                    @ d1<- vB
6230    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6231    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6232    fldd    d0, [r9]                    @ d0<- vA
6233
6234    fsubd   d2, d0, d1                              @ d2<- op
6235    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6236    fstd    d2, [r9]                    @ vAA<- d2
6237    GOTO_OPCODE(ip)                     @ jump to next instruction
6238
6239
6240/* ------------------------------ */
6241    .balign 64
6242.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
6243/* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */
6244/* File: arm-vfp/fbinopWide2addr.S */
6245    /*
6246     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6247     * an "instr" line that specifies an instruction that performs
6248     * "d2 = d0 op d1".
6249     *
6250     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6251     *      div-double/2addr
6252     */
6253    /* binop/2addr vA, vB */
6254    mov     r3, rINST, lsr #12          @ r3<- B
6255    mov     r9, rINST, lsr #8           @ r9<- A+
6256    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6257    and     r9, r9, #15                 @ r9<- A
6258    fldd    d1, [r3]                    @ d1<- vB
6259    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6260    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6261    fldd    d0, [r9]                    @ d0<- vA
6262
6263    fmuld   d2, d0, d1                              @ d2<- op
6264    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6265    fstd    d2, [r9]                    @ vAA<- d2
6266    GOTO_OPCODE(ip)                     @ jump to next instruction
6267
6268
6269/* ------------------------------ */
6270    .balign 64
6271.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
6272/* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */
6273/* File: arm-vfp/fbinopWide2addr.S */
6274    /*
6275     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6276     * an "instr" line that specifies an instruction that performs
6277     * "d2 = d0 op d1".
6278     *
6279     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6280     *      div-double/2addr
6281     */
6282    /* binop/2addr vA, vB */
6283    mov     r3, rINST, lsr #12          @ r3<- B
6284    mov     r9, rINST, lsr #8           @ r9<- A+
6285    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6286    and     r9, r9, #15                 @ r9<- A
6287    fldd    d1, [r3]                    @ d1<- vB
6288    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6289    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6290    fldd    d0, [r9]                    @ d0<- vA
6291
6292    fdivd   d2, d0, d1                              @ d2<- op
6293    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6294    fstd    d2, [r9]                    @ vAA<- d2
6295    GOTO_OPCODE(ip)                     @ jump to next instruction
6296
6297
6298/* ------------------------------ */
6299    .balign 64
6300.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
6301/* File: armv6t2/OP_REM_DOUBLE_2ADDR.S */
6302/* EABI doesn't define a double remainder function, but libm does */
6303/* File: armv6t2/binopWide2addr.S */
6304    /*
6305     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6306     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6307     * This could be an ARM instruction or a function call.  (If the result
6308     * comes back in a register other than r0, you can override "result".)
6309     *
6310     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6311     * vCC (r1).  Useful for integer division and modulus.
6312     *
6313     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6314     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6315     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6316     *      rem-double/2addr
6317     */
6318    /* binop/2addr vA, vB */
6319    mov     r1, rINST, lsr #12          @ r1<- B
6320    ubfx    r9, rINST, #8, #4           @ r9<- A
6321    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6322    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6323    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6324    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6325    .if 0
6326    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6327    beq     common_errDivideByZero
6328    .endif
6329    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6330
6331                               @ optional op; may set condition codes
6332    bl      fmod                              @ result<- op, r0-r3 changed
6333    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6334    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6335    GOTO_OPCODE(ip)                     @ jump to next instruction
6336    /* 12-15 instructions */
6337
6338
6339/* ------------------------------ */
6340    .balign 64
6341.L_OP_ADD_INT_LIT16: /* 0xd0 */
6342/* File: armv6t2/OP_ADD_INT_LIT16.S */
6343/* File: armv6t2/binopLit16.S */
6344    /*
6345     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6346     * that specifies an instruction that performs "result = r0 op r1".
6347     * This could be an ARM instruction or a function call.  (If the result
6348     * comes back in a register other than r0, you can override "result".)
6349     *
6350     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6351     * vCC (r1).  Useful for integer division and modulus.
6352     *
6353     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6354     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6355     */
6356    /* binop/lit16 vA, vB, #+CCCC */
6357    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6358    mov     r2, rINST, lsr #12          @ r2<- B
6359    ubfx    r9, rINST, #8, #4           @ r9<- A
6360    GET_VREG(r0, r2)                    @ r0<- vB
6361    .if 0
6362    cmp     r1, #0                      @ is second operand zero?
6363    beq     common_errDivideByZero
6364    .endif
6365    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6366
6367    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6368    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6369    SET_VREG(r0, r9)               @ vAA<- r0
6370    GOTO_OPCODE(ip)                     @ jump to next instruction
6371    /* 10-13 instructions */
6372
6373
6374/* ------------------------------ */
6375    .balign 64
6376.L_OP_RSUB_INT: /* 0xd1 */
6377/* File: armv6t2/OP_RSUB_INT.S */
6378/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
6379/* File: armv6t2/binopLit16.S */
6380    /*
6381     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6382     * that specifies an instruction that performs "result = r0 op r1".
6383     * This could be an ARM instruction or a function call.  (If the result
6384     * comes back in a register other than r0, you can override "result".)
6385     *
6386     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6387     * vCC (r1).  Useful for integer division and modulus.
6388     *
6389     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6390     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6391     */
6392    /* binop/lit16 vA, vB, #+CCCC */
6393    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6394    mov     r2, rINST, lsr #12          @ r2<- B
6395    ubfx    r9, rINST, #8, #4           @ r9<- A
6396    GET_VREG(r0, r2)                    @ r0<- vB
6397    .if 0
6398    cmp     r1, #0                      @ is second operand zero?
6399    beq     common_errDivideByZero
6400    .endif
6401    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6402
6403    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6404    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6405    SET_VREG(r0, r9)               @ vAA<- r0
6406    GOTO_OPCODE(ip)                     @ jump to next instruction
6407    /* 10-13 instructions */
6408
6409
6410/* ------------------------------ */
6411    .balign 64
6412.L_OP_MUL_INT_LIT16: /* 0xd2 */
6413/* File: armv6t2/OP_MUL_INT_LIT16.S */
6414/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6415/* File: armv6t2/binopLit16.S */
6416    /*
6417     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6418     * that specifies an instruction that performs "result = r0 op r1".
6419     * This could be an ARM instruction or a function call.  (If the result
6420     * comes back in a register other than r0, you can override "result".)
6421     *
6422     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6423     * vCC (r1).  Useful for integer division and modulus.
6424     *
6425     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6426     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6427     */
6428    /* binop/lit16 vA, vB, #+CCCC */
6429    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6430    mov     r2, rINST, lsr #12          @ r2<- B
6431    ubfx    r9, rINST, #8, #4           @ r9<- A
6432    GET_VREG(r0, r2)                    @ r0<- vB
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    mul     r0, r1, r0                              @ 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_DIV_INT_LIT16: /* 0xd3 */
6449/* File: armv6t2/OP_DIV_INT_LIT16.S */
6450/* File: armv6t2/binopLit16.S */
6451    /*
6452     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6453     * that specifies an instruction that performs "result = r0 op r1".
6454     * This could be an ARM instruction or a function call.  (If the result
6455     * comes back in a register other than r0, you can override "result".)
6456     *
6457     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6458     * vCC (r1).  Useful for integer division and modulus.
6459     *
6460     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6461     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6462     */
6463    /* binop/lit16 vA, vB, #+CCCC */
6464    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6465    mov     r2, rINST, lsr #12          @ r2<- B
6466    ubfx    r9, rINST, #8, #4           @ r9<- A
6467    GET_VREG(r0, r2)                    @ r0<- vB
6468    .if 1
6469    cmp     r1, #0                      @ is second operand zero?
6470    beq     common_errDivideByZero
6471    .endif
6472    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6473
6474    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6475    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6476    SET_VREG(r0, r9)               @ vAA<- r0
6477    GOTO_OPCODE(ip)                     @ jump to next instruction
6478    /* 10-13 instructions */
6479
6480
6481/* ------------------------------ */
6482    .balign 64
6483.L_OP_REM_INT_LIT16: /* 0xd4 */
6484/* File: armv6t2/OP_REM_INT_LIT16.S */
6485/* idivmod returns quotient in r0 and remainder in r1 */
6486/* File: armv6t2/binopLit16.S */
6487    /*
6488     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6489     * that specifies an instruction that performs "result = r0 op r1".
6490     * This could be an ARM instruction or a function call.  (If the result
6491     * comes back in a register other than r0, you can override "result".)
6492     *
6493     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6494     * vCC (r1).  Useful for integer division and modulus.
6495     *
6496     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6497     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6498     */
6499    /* binop/lit16 vA, vB, #+CCCC */
6500    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6501    mov     r2, rINST, lsr #12          @ r2<- B
6502    ubfx    r9, rINST, #8, #4           @ r9<- A
6503    GET_VREG(r0, r2)                    @ r0<- vB
6504    .if 1
6505    cmp     r1, #0                      @ is second operand zero?
6506    beq     common_errDivideByZero
6507    .endif
6508    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6509
6510    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6511    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6512    SET_VREG(r1, r9)               @ vAA<- r1
6513    GOTO_OPCODE(ip)                     @ jump to next instruction
6514    /* 10-13 instructions */
6515
6516
6517/* ------------------------------ */
6518    .balign 64
6519.L_OP_AND_INT_LIT16: /* 0xd5 */
6520/* File: armv6t2/OP_AND_INT_LIT16.S */
6521/* File: armv6t2/binopLit16.S */
6522    /*
6523     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6524     * that specifies an instruction that performs "result = r0 op r1".
6525     * This could be an ARM instruction or a function call.  (If the result
6526     * comes back in a register other than r0, you can override "result".)
6527     *
6528     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6529     * vCC (r1).  Useful for integer division and modulus.
6530     *
6531     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6532     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6533     */
6534    /* binop/lit16 vA, vB, #+CCCC */
6535    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6536    mov     r2, rINST, lsr #12          @ r2<- B
6537    ubfx    r9, rINST, #8, #4           @ r9<- A
6538    GET_VREG(r0, r2)                    @ r0<- vB
6539    .if 0
6540    cmp     r1, #0                      @ is second operand zero?
6541    beq     common_errDivideByZero
6542    .endif
6543    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6544
6545    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6546    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6547    SET_VREG(r0, r9)               @ vAA<- r0
6548    GOTO_OPCODE(ip)                     @ jump to next instruction
6549    /* 10-13 instructions */
6550
6551
6552/* ------------------------------ */
6553    .balign 64
6554.L_OP_OR_INT_LIT16: /* 0xd6 */
6555/* File: armv6t2/OP_OR_INT_LIT16.S */
6556/* File: armv6t2/binopLit16.S */
6557    /*
6558     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6559     * that specifies an instruction that performs "result = r0 op r1".
6560     * This could be an ARM instruction or a function call.  (If the result
6561     * comes back in a register other than r0, you can override "result".)
6562     *
6563     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6564     * vCC (r1).  Useful for integer division and modulus.
6565     *
6566     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6567     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6568     */
6569    /* binop/lit16 vA, vB, #+CCCC */
6570    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6571    mov     r2, rINST, lsr #12          @ r2<- B
6572    ubfx    r9, rINST, #8, #4           @ r9<- A
6573    GET_VREG(r0, r2)                    @ r0<- vB
6574    .if 0
6575    cmp     r1, #0                      @ is second operand zero?
6576    beq     common_errDivideByZero
6577    .endif
6578    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6579
6580    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6581    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6582    SET_VREG(r0, r9)               @ vAA<- r0
6583    GOTO_OPCODE(ip)                     @ jump to next instruction
6584    /* 10-13 instructions */
6585
6586
6587/* ------------------------------ */
6588    .balign 64
6589.L_OP_XOR_INT_LIT16: /* 0xd7 */
6590/* File: armv6t2/OP_XOR_INT_LIT16.S */
6591/* File: armv6t2/binopLit16.S */
6592    /*
6593     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6594     * that specifies an instruction that performs "result = r0 op r1".
6595     * This could be an ARM instruction or a function call.  (If the result
6596     * comes back in a register other than r0, you can override "result".)
6597     *
6598     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6599     * vCC (r1).  Useful for integer division and modulus.
6600     *
6601     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6602     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6603     */
6604    /* binop/lit16 vA, vB, #+CCCC */
6605    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6606    mov     r2, rINST, lsr #12          @ r2<- B
6607    ubfx    r9, rINST, #8, #4           @ r9<- A
6608    GET_VREG(r0, r2)                    @ r0<- vB
6609    .if 0
6610    cmp     r1, #0                      @ is second operand zero?
6611    beq     common_errDivideByZero
6612    .endif
6613    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6614
6615    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
6616    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6617    SET_VREG(r0, r9)               @ vAA<- r0
6618    GOTO_OPCODE(ip)                     @ jump to next instruction
6619    /* 10-13 instructions */
6620
6621
6622/* ------------------------------ */
6623    .balign 64
6624.L_OP_ADD_INT_LIT8: /* 0xd8 */
6625/* File: armv5te/OP_ADD_INT_LIT8.S */
6626/* File: armv5te/binopLit8.S */
6627    /*
6628     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6629     * that specifies an instruction that performs "result = r0 op r1".
6630     * This could be an ARM instruction or a function call.  (If the result
6631     * comes back in a register other than r0, you can override "result".)
6632     *
6633     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6634     * vCC (r1).  Useful for integer division and modulus.
6635     *
6636     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6637     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6638     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6639     */
6640    /* binop/lit8 vAA, vBB, #+CC */
6641    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6642    mov     r9, rINST, lsr #8           @ r9<- AA
6643    and     r2, r3, #255                @ r2<- BB
6644    GET_VREG(r0, r2)                    @ r0<- vBB
6645    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6646    .if 0
6647    @cmp     r1, #0                      @ is second operand zero?
6648    beq     common_errDivideByZero
6649    .endif
6650    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6651
6652                               @ optional op; may set condition codes
6653    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6654    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6655    SET_VREG(r0, r9)               @ vAA<- r0
6656    GOTO_OPCODE(ip)                     @ jump to next instruction
6657    /* 10-12 instructions */
6658
6659
6660/* ------------------------------ */
6661    .balign 64
6662.L_OP_RSUB_INT_LIT8: /* 0xd9 */
6663/* File: armv5te/OP_RSUB_INT_LIT8.S */
6664/* File: armv5te/binopLit8.S */
6665    /*
6666     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6667     * that specifies an instruction that performs "result = r0 op r1".
6668     * This could be an ARM instruction or a function call.  (If the result
6669     * comes back in a register other than r0, you can override "result".)
6670     *
6671     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6672     * vCC (r1).  Useful for integer division and modulus.
6673     *
6674     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6675     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6676     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6677     */
6678    /* binop/lit8 vAA, vBB, #+CC */
6679    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6680    mov     r9, rINST, lsr #8           @ r9<- AA
6681    and     r2, r3, #255                @ r2<- BB
6682    GET_VREG(r0, r2)                    @ r0<- vBB
6683    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6684    .if 0
6685    @cmp     r1, #0                      @ is second operand zero?
6686    beq     common_errDivideByZero
6687    .endif
6688    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6689
6690                               @ optional op; may set condition codes
6691    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6692    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6693    SET_VREG(r0, r9)               @ vAA<- r0
6694    GOTO_OPCODE(ip)                     @ jump to next instruction
6695    /* 10-12 instructions */
6696
6697
6698/* ------------------------------ */
6699    .balign 64
6700.L_OP_MUL_INT_LIT8: /* 0xda */
6701/* File: armv5te/OP_MUL_INT_LIT8.S */
6702/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6703/* File: armv5te/binopLit8.S */
6704    /*
6705     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6706     * that specifies an instruction that performs "result = r0 op r1".
6707     * This could be an ARM instruction or a function call.  (If the result
6708     * comes back in a register other than r0, you can override "result".)
6709     *
6710     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6711     * vCC (r1).  Useful for integer division and modulus.
6712     *
6713     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6714     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6715     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6716     */
6717    /* binop/lit8 vAA, vBB, #+CC */
6718    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6719    mov     r9, rINST, lsr #8           @ r9<- AA
6720    and     r2, r3, #255                @ r2<- BB
6721    GET_VREG(r0, r2)                    @ r0<- vBB
6722    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6723    .if 0
6724    @cmp     r1, #0                      @ is second operand zero?
6725    beq     common_errDivideByZero
6726    .endif
6727    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6728
6729                               @ optional op; may set condition codes
6730    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6731    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6732    SET_VREG(r0, r9)               @ vAA<- r0
6733    GOTO_OPCODE(ip)                     @ jump to next instruction
6734    /* 10-12 instructions */
6735
6736
6737/* ------------------------------ */
6738    .balign 64
6739.L_OP_DIV_INT_LIT8: /* 0xdb */
6740/* File: armv5te/OP_DIV_INT_LIT8.S */
6741/* File: armv5te/binopLit8.S */
6742    /*
6743     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6744     * that specifies an instruction that performs "result = r0 op r1".
6745     * This could be an ARM instruction or a function call.  (If the result
6746     * comes back in a register other than r0, you can override "result".)
6747     *
6748     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6749     * vCC (r1).  Useful for integer division and modulus.
6750     *
6751     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6752     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6753     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6754     */
6755    /* binop/lit8 vAA, vBB, #+CC */
6756    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6757    mov     r9, rINST, lsr #8           @ r9<- AA
6758    and     r2, r3, #255                @ r2<- BB
6759    GET_VREG(r0, r2)                    @ r0<- vBB
6760    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6761    .if 1
6762    @cmp     r1, #0                      @ is second operand zero?
6763    beq     common_errDivideByZero
6764    .endif
6765    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6766
6767                               @ optional op; may set condition codes
6768    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6769    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6770    SET_VREG(r0, r9)               @ vAA<- r0
6771    GOTO_OPCODE(ip)                     @ jump to next instruction
6772    /* 10-12 instructions */
6773
6774
6775/* ------------------------------ */
6776    .balign 64
6777.L_OP_REM_INT_LIT8: /* 0xdc */
6778/* File: armv5te/OP_REM_INT_LIT8.S */
6779/* idivmod returns quotient in r0 and remainder in r1 */
6780/* File: armv5te/binopLit8.S */
6781    /*
6782     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6783     * that specifies an instruction that performs "result = r0 op r1".
6784     * This could be an ARM instruction or a function call.  (If the result
6785     * comes back in a register other than r0, you can override "result".)
6786     *
6787     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6788     * vCC (r1).  Useful for integer division and modulus.
6789     *
6790     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6791     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6792     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6793     */
6794    /* binop/lit8 vAA, vBB, #+CC */
6795    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6796    mov     r9, rINST, lsr #8           @ r9<- AA
6797    and     r2, r3, #255                @ r2<- BB
6798    GET_VREG(r0, r2)                    @ r0<- vBB
6799    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6800    .if 1
6801    @cmp     r1, #0                      @ is second operand zero?
6802    beq     common_errDivideByZero
6803    .endif
6804    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6805
6806                               @ optional op; may set condition codes
6807    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6808    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6809    SET_VREG(r1, r9)               @ vAA<- r1
6810    GOTO_OPCODE(ip)                     @ jump to next instruction
6811    /* 10-12 instructions */
6812
6813
6814/* ------------------------------ */
6815    .balign 64
6816.L_OP_AND_INT_LIT8: /* 0xdd */
6817/* File: armv5te/OP_AND_INT_LIT8.S */
6818/* File: armv5te/binopLit8.S */
6819    /*
6820     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6821     * that specifies an instruction that performs "result = r0 op r1".
6822     * This could be an ARM instruction or a function call.  (If the result
6823     * comes back in a register other than r0, you can override "result".)
6824     *
6825     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6826     * vCC (r1).  Useful for integer division and modulus.
6827     *
6828     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6829     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6830     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6831     */
6832    /* binop/lit8 vAA, vBB, #+CC */
6833    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6834    mov     r9, rINST, lsr #8           @ r9<- AA
6835    and     r2, r3, #255                @ r2<- BB
6836    GET_VREG(r0, r2)                    @ r0<- vBB
6837    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6838    .if 0
6839    @cmp     r1, #0                      @ is second operand zero?
6840    beq     common_errDivideByZero
6841    .endif
6842    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6843
6844                               @ optional op; may set condition codes
6845    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6846    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6847    SET_VREG(r0, r9)               @ vAA<- r0
6848    GOTO_OPCODE(ip)                     @ jump to next instruction
6849    /* 10-12 instructions */
6850
6851
6852/* ------------------------------ */
6853    .balign 64
6854.L_OP_OR_INT_LIT8: /* 0xde */
6855/* File: armv5te/OP_OR_INT_LIT8.S */
6856/* File: armv5te/binopLit8.S */
6857    /*
6858     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6859     * that specifies an instruction that performs "result = r0 op r1".
6860     * This could be an ARM instruction or a function call.  (If the result
6861     * comes back in a register other than r0, you can override "result".)
6862     *
6863     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6864     * vCC (r1).  Useful for integer division and modulus.
6865     *
6866     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6867     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6868     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6869     */
6870    /* binop/lit8 vAA, vBB, #+CC */
6871    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6872    mov     r9, rINST, lsr #8           @ r9<- AA
6873    and     r2, r3, #255                @ r2<- BB
6874    GET_VREG(r0, r2)                    @ r0<- vBB
6875    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6876    .if 0
6877    @cmp     r1, #0                      @ is second operand zero?
6878    beq     common_errDivideByZero
6879    .endif
6880    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6881
6882                               @ optional op; may set condition codes
6883    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6884    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6885    SET_VREG(r0, r9)               @ vAA<- r0
6886    GOTO_OPCODE(ip)                     @ jump to next instruction
6887    /* 10-12 instructions */
6888
6889
6890/* ------------------------------ */
6891    .balign 64
6892.L_OP_XOR_INT_LIT8: /* 0xdf */
6893/* File: armv5te/OP_XOR_INT_LIT8.S */
6894/* File: armv5te/binopLit8.S */
6895    /*
6896     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6897     * that specifies an instruction that performs "result = r0 op r1".
6898     * This could be an ARM instruction or a function call.  (If the result
6899     * comes back in a register other than r0, you can override "result".)
6900     *
6901     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6902     * vCC (r1).  Useful for integer division and modulus.
6903     *
6904     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6905     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6906     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6907     */
6908    /* binop/lit8 vAA, vBB, #+CC */
6909    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6910    mov     r9, rINST, lsr #8           @ r9<- AA
6911    and     r2, r3, #255                @ r2<- BB
6912    GET_VREG(r0, r2)                    @ r0<- vBB
6913    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6914    .if 0
6915    @cmp     r1, #0                      @ is second operand zero?
6916    beq     common_errDivideByZero
6917    .endif
6918    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6919
6920                               @ optional op; may set condition codes
6921    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
6922    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6923    SET_VREG(r0, r9)               @ vAA<- r0
6924    GOTO_OPCODE(ip)                     @ jump to next instruction
6925    /* 10-12 instructions */
6926
6927
6928/* ------------------------------ */
6929    .balign 64
6930.L_OP_SHL_INT_LIT8: /* 0xe0 */
6931/* File: armv5te/OP_SHL_INT_LIT8.S */
6932/* File: armv5te/binopLit8.S */
6933    /*
6934     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6935     * that specifies an instruction that performs "result = r0 op r1".
6936     * This could be an ARM instruction or a function call.  (If the result
6937     * comes back in a register other than r0, you can override "result".)
6938     *
6939     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6940     * vCC (r1).  Useful for integer division and modulus.
6941     *
6942     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6943     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6944     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6945     */
6946    /* binop/lit8 vAA, vBB, #+CC */
6947    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6948    mov     r9, rINST, lsr #8           @ r9<- AA
6949    and     r2, r3, #255                @ r2<- BB
6950    GET_VREG(r0, r2)                    @ r0<- vBB
6951    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6952    .if 0
6953    @cmp     r1, #0                      @ is second operand zero?
6954    beq     common_errDivideByZero
6955    .endif
6956    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6957
6958    and     r1, r1, #31                           @ optional op; may set condition codes
6959    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
6960    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6961    SET_VREG(r0, r9)               @ vAA<- r0
6962    GOTO_OPCODE(ip)                     @ jump to next instruction
6963    /* 10-12 instructions */
6964
6965
6966/* ------------------------------ */
6967    .balign 64
6968.L_OP_SHR_INT_LIT8: /* 0xe1 */
6969/* File: armv5te/OP_SHR_INT_LIT8.S */
6970/* File: armv5te/binopLit8.S */
6971    /*
6972     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6973     * that specifies an instruction that performs "result = r0 op r1".
6974     * This could be an ARM instruction or a function call.  (If the result
6975     * comes back in a register other than r0, you can override "result".)
6976     *
6977     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6978     * vCC (r1).  Useful for integer division and modulus.
6979     *
6980     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6981     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6982     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6983     */
6984    /* binop/lit8 vAA, vBB, #+CC */
6985    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6986    mov     r9, rINST, lsr #8           @ r9<- AA
6987    and     r2, r3, #255                @ r2<- BB
6988    GET_VREG(r0, r2)                    @ r0<- vBB
6989    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6990    .if 0
6991    @cmp     r1, #0                      @ is second operand zero?
6992    beq     common_errDivideByZero
6993    .endif
6994    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6995
6996    and     r1, r1, #31                           @ optional op; may set condition codes
6997    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
6998    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6999    SET_VREG(r0, r9)               @ vAA<- r0
7000    GOTO_OPCODE(ip)                     @ jump to next instruction
7001    /* 10-12 instructions */
7002
7003
7004/* ------------------------------ */
7005    .balign 64
7006.L_OP_USHR_INT_LIT8: /* 0xe2 */
7007/* File: armv5te/OP_USHR_INT_LIT8.S */
7008/* File: armv5te/binopLit8.S */
7009    /*
7010     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7011     * that specifies an instruction that performs "result = r0 op r1".
7012     * This could be an ARM instruction or a function call.  (If the result
7013     * comes back in a register other than r0, you can override "result".)
7014     *
7015     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7016     * vCC (r1).  Useful for integer division and modulus.
7017     *
7018     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7019     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7020     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7021     */
7022    /* binop/lit8 vAA, vBB, #+CC */
7023    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7024    mov     r9, rINST, lsr #8           @ r9<- AA
7025    and     r2, r3, #255                @ r2<- BB
7026    GET_VREG(r0, r2)                    @ r0<- vBB
7027    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7028    .if 0
7029    @cmp     r1, #0                      @ is second operand zero?
7030    beq     common_errDivideByZero
7031    .endif
7032    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7033
7034    and     r1, r1, #31                           @ optional op; may set condition codes
7035    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
7036    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7037    SET_VREG(r0, r9)               @ vAA<- r0
7038    GOTO_OPCODE(ip)                     @ jump to next instruction
7039    /* 10-12 instructions */
7040
7041
7042/* ------------------------------ */
7043    .balign 64
7044.L_OP_IGET_VOLATILE: /* 0xe3 */
7045/* File: armv5te/OP_IGET_VOLATILE.S */
7046/* File: armv5te/OP_IGET.S */
7047    /*
7048     * General 32-bit instance field get.
7049     *
7050     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
7051     */
7052    /* op vA, vB, field@CCCC */
7053    mov     r0, rINST, lsr #12          @ r0<- B
7054    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7055    FETCH(r1, 1)                        @ r1<- field ref CCCC
7056    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7057    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7058    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7059    cmp     r0, #0                      @ is resolved entry null?
7060    bne     .LOP_IGET_VOLATILE_finish          @ no, already resolved
70618:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7062    EXPORT_PC()                         @ resolve() could throw
7063    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7064    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7065    cmp     r0, #0
7066    bne     .LOP_IGET_VOLATILE_finish
7067    b       common_exceptionThrown
7068
7069
7070/* ------------------------------ */
7071    .balign 64
7072.L_OP_IPUT_VOLATILE: /* 0xe4 */
7073/* File: armv5te/OP_IPUT_VOLATILE.S */
7074/* File: armv5te/OP_IPUT.S */
7075    /*
7076     * General 32-bit instance field put.
7077     *
7078     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
7079     */
7080    /* op vA, vB, field@CCCC */
7081    mov     r0, rINST, lsr #12          @ r0<- B
7082    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7083    FETCH(r1, 1)                        @ r1<- field ref CCCC
7084    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7085    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7086    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7087    cmp     r0, #0                      @ is resolved entry null?
7088    bne     .LOP_IPUT_VOLATILE_finish          @ no, already resolved
70898:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7090    EXPORT_PC()                         @ resolve() could throw
7091    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7092    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7093    cmp     r0, #0                      @ success?
7094    bne     .LOP_IPUT_VOLATILE_finish          @ yes, finish up
7095    b       common_exceptionThrown
7096
7097
7098/* ------------------------------ */
7099    .balign 64
7100.L_OP_SGET_VOLATILE: /* 0xe5 */
7101/* File: armv5te/OP_SGET_VOLATILE.S */
7102/* File: armv5te/OP_SGET.S */
7103    /*
7104     * General 32-bit SGET handler.
7105     *
7106     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
7107     */
7108    /* op vAA, field@BBBB */
7109    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7110    FETCH(r1, 1)                        @ r1<- field ref BBBB
7111    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7112    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7113    cmp     r0, #0                      @ is resolved entry null?
7114    beq     .LOP_SGET_VOLATILE_resolve         @ yes, do resolve
7115.LOP_SGET_VOLATILE_finish: @ field ptr in r0
7116    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
7117    SMP_DMB                            @ acquiring load
7118    mov     r2, rINST, lsr #8           @ r2<- AA
7119    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7120    SET_VREG(r1, r2)                    @ fp[AA]<- r1
7121    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7122    GOTO_OPCODE(ip)                     @ jump to next instruction
7123
7124
7125/* ------------------------------ */
7126    .balign 64
7127.L_OP_SPUT_VOLATILE: /* 0xe6 */
7128/* File: armv5te/OP_SPUT_VOLATILE.S */
7129/* File: armv5te/OP_SPUT.S */
7130    /*
7131     * General 32-bit SPUT handler.
7132     *
7133     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
7134     */
7135    /* op vAA, field@BBBB */
7136    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7137    FETCH(r1, 1)                        @ r1<- field ref BBBB
7138    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7139    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7140    cmp     r0, #0                      @ is resolved entry null?
7141    beq     .LOP_SPUT_VOLATILE_resolve         @ yes, do resolve
7142.LOP_SPUT_VOLATILE_finish:   @ field ptr in r0
7143    mov     r2, rINST, lsr #8           @ r2<- AA
7144    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7145    GET_VREG(r1, r2)                    @ r1<- fp[AA]
7146    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7147    SMP_DMB                            @ releasing store
7148    str     r1, [r0, #offStaticField_value] @ field<- vAA
7149    GOTO_OPCODE(ip)                     @ jump to next instruction
7150
7151
7152/* ------------------------------ */
7153    .balign 64
7154.L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */
7155/* File: armv5te/OP_IGET_OBJECT_VOLATILE.S */
7156/* File: armv5te/OP_IGET.S */
7157    /*
7158     * General 32-bit instance field get.
7159     *
7160     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
7161     */
7162    /* op vA, vB, field@CCCC */
7163    mov     r0, rINST, lsr #12          @ r0<- B
7164    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7165    FETCH(r1, 1)                        @ r1<- field ref CCCC
7166    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7167    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7168    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7169    cmp     r0, #0                      @ is resolved entry null?
7170    bne     .LOP_IGET_OBJECT_VOLATILE_finish          @ no, already resolved
71718:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7172    EXPORT_PC()                         @ resolve() could throw
7173    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7174    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7175    cmp     r0, #0
7176    bne     .LOP_IGET_OBJECT_VOLATILE_finish
7177    b       common_exceptionThrown
7178
7179
7180/* ------------------------------ */
7181    .balign 64
7182.L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */
7183/* File: armv5te/OP_IGET_WIDE_VOLATILE.S */
7184/* File: armv5te/OP_IGET_WIDE.S */
7185    /*
7186     * Wide 32-bit instance field get.
7187     */
7188    /* iget-wide vA, vB, field@CCCC */
7189    mov     r0, rINST, lsr #12          @ r0<- B
7190    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7191    FETCH(r1, 1)                        @ r1<- field ref CCCC
7192    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
7193    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7194    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7195    cmp     r0, #0                      @ is resolved entry null?
7196    bne     .LOP_IGET_WIDE_VOLATILE_finish          @ no, already resolved
71978:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
7198    EXPORT_PC()                         @ resolve() could throw
7199    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7200    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7201    cmp     r0, #0
7202    bne     .LOP_IGET_WIDE_VOLATILE_finish
7203    b       common_exceptionThrown
7204
7205
7206/* ------------------------------ */
7207    .balign 64
7208.L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */
7209/* File: armv5te/OP_IPUT_WIDE_VOLATILE.S */
7210/* File: armv5te/OP_IPUT_WIDE.S */
7211    /* iput-wide vA, vB, field@CCCC */
7212    mov     r0, rINST, lsr #12          @ r0<- B
7213    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7214    FETCH(r1, 1)                        @ r1<- field ref CCCC
7215    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
7216    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7217    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7218    cmp     r0, #0                      @ is resolved entry null?
7219    bne     .LOP_IPUT_WIDE_VOLATILE_finish          @ no, already resolved
72208:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
7221    EXPORT_PC()                         @ resolve() could throw
7222    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7223    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7224    cmp     r0, #0                      @ success?
7225    bne     .LOP_IPUT_WIDE_VOLATILE_finish          @ yes, finish up
7226    b       common_exceptionThrown
7227
7228
7229/* ------------------------------ */
7230    .balign 64
7231.L_OP_SGET_WIDE_VOLATILE: /* 0xea */
7232/* File: armv5te/OP_SGET_WIDE_VOLATILE.S */
7233/* File: armv5te/OP_SGET_WIDE.S */
7234    /*
7235     * 64-bit SGET handler.
7236     */
7237    /* sget-wide vAA, field@BBBB */
7238    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7239    FETCH(r1, 1)                        @ r1<- field ref BBBB
7240    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7241    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7242    cmp     r0, #0                      @ is resolved entry null?
7243    beq     .LOP_SGET_WIDE_VOLATILE_resolve         @ yes, do resolve
7244.LOP_SGET_WIDE_VOLATILE_finish:
7245    mov     r9, rINST, lsr #8           @ r9<- AA
7246    .if 1
7247    add     r0, r0, #offStaticField_value @ r0<- pointer to data
7248    bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
7249    .else
7250    ldrd    r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
7251    .endif
7252    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
7253    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7254    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
7255    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7256    GOTO_OPCODE(ip)                     @ jump to next instruction
7257
7258
7259/* ------------------------------ */
7260    .balign 64
7261.L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */
7262/* File: armv5te/OP_SPUT_WIDE_VOLATILE.S */
7263/* File: armv5te/OP_SPUT_WIDE.S */
7264    /*
7265     * 64-bit SPUT handler.
7266     */
7267    /* sput-wide vAA, field@BBBB */
7268    ldr     r0, [rGLUE, #offGlue_methodClassDex]  @ r0<- DvmDex
7269    FETCH(r1, 1)                        @ r1<- field ref BBBB
7270    ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
7271    mov     r9, rINST, lsr #8           @ r9<- AA
7272    ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
7273    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
7274    cmp     r2, #0                      @ is resolved entry null?
7275    beq     .LOP_SPUT_WIDE_VOLATILE_resolve         @ yes, do resolve
7276.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9
7277    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7278    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
7279    GET_INST_OPCODE(r10)                @ extract opcode from rINST
7280    .if 1
7281    add     r2, r2, #offStaticField_value @ r2<- pointer to data
7282    bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
7283    .else
7284    strd    r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
7285    .endif
7286    GOTO_OPCODE(r10)                    @ jump to next instruction
7287
7288
7289/* ------------------------------ */
7290    .balign 64
7291.L_OP_BREAKPOINT: /* 0xec */
7292/* File: armv5te/OP_BREAKPOINT.S */
7293/* File: armv5te/unused.S */
7294    bl      common_abort
7295
7296
7297/* ------------------------------ */
7298    .balign 64
7299.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
7300/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
7301    /*
7302     * Handle a throw-verification-error instruction.  This throws an
7303     * exception for an error discovered during verification.  The
7304     * exception is indicated by AA, with some detail provided by BBBB.
7305     */
7306    /* op AA, ref@BBBB */
7307    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7308    FETCH(r2, 1)                        @ r2<- BBBB
7309    EXPORT_PC()                         @ export the PC
7310    mov     r1, rINST, lsr #8           @ r1<- AA
7311    bl      dvmThrowVerificationError   @ always throws
7312    b       common_exceptionThrown      @ handle exception
7313
7314/* ------------------------------ */
7315    .balign 64
7316.L_OP_EXECUTE_INLINE: /* 0xee */
7317/* File: armv5te/OP_EXECUTE_INLINE.S */
7318    /*
7319     * Execute a "native inline" instruction.
7320     *
7321     * We need to call an InlineOp4Func:
7322     *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7323     *
7324     * The first four args are in r0-r3, pointer to return value storage
7325     * is on the stack.  The function's return value is a flag that tells
7326     * us if an exception was thrown.
7327     */
7328    /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
7329    FETCH(r10, 1)                       @ r10<- BBBB
7330    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7331    EXPORT_PC()                         @ can throw
7332    sub     sp, sp, #8                  @ make room for arg, +64 bit align
7333    mov     r0, rINST, lsr #12          @ r0<- B
7334    str     r1, [sp]                    @ push &glue->retval
7335    bl      .LOP_EXECUTE_INLINE_continue        @ make call; will return after
7336    add     sp, sp, #8                  @ pop stack
7337    cmp     r0, #0                      @ test boolean result of inline
7338    beq     common_exceptionThrown      @ returned false, handle exception
7339    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7340    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7341    GOTO_OPCODE(ip)                     @ jump to next instruction
7342
7343/* ------------------------------ */
7344    .balign 64
7345.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */
7346/* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */
7347    /*
7348     * Execute a "native inline" instruction, using "/range" semantics.
7349     * Same idea as execute-inline, but we get the args differently.
7350     *
7351     * We need to call an InlineOp4Func:
7352     *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7353     *
7354     * The first four args are in r0-r3, pointer to return value storage
7355     * is on the stack.  The function's return value is a flag that tells
7356     * us if an exception was thrown.
7357     */
7358    /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */
7359    FETCH(r10, 1)                       @ r10<- BBBB
7360    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7361    EXPORT_PC()                         @ can throw
7362    sub     sp, sp, #8                  @ make room for arg, +64 bit align
7363    mov     r0, rINST, lsr #8           @ r0<- AA
7364    str     r1, [sp]                    @ push &glue->retval
7365    bl      .LOP_EXECUTE_INLINE_RANGE_continue        @ make call; will return after
7366    add     sp, sp, #8                  @ pop stack
7367    cmp     r0, #0                      @ test boolean result of inline
7368    beq     common_exceptionThrown      @ returned false, handle exception
7369    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7370    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7371    GOTO_OPCODE(ip)                     @ jump to next instruction
7372
7373/* ------------------------------ */
7374    .balign 64
7375.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
7376/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
7377    /*
7378     * invoke-direct-empty is a no-op in a "standard" interpreter.
7379     */
7380    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7381    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7382    GOTO_OPCODE(ip)                     @ execute it
7383
7384/* ------------------------------ */
7385    .balign 64
7386.L_OP_RETURN_VOID_BARRIER: /* 0xf1 */
7387/* File: armv5te/OP_RETURN_VOID_BARRIER.S */
7388    SMP_DMB_ST
7389    b       common_returnFromMethod
7390
7391/* ------------------------------ */
7392    .balign 64
7393.L_OP_IGET_QUICK: /* 0xf2 */
7394/* File: armv6t2/OP_IGET_QUICK.S */
7395    /* For: iget-quick, iget-object-quick */
7396    /* op vA, vB, offset@CCCC */
7397    mov     r2, rINST, lsr #12          @ r2<- B
7398    FETCH(r1, 1)                        @ r1<- field byte offset
7399    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7400    ubfx    r2, rINST, #8, #4           @ r2<- A
7401    cmp     r3, #0                      @ check object for null
7402    beq     common_errNullObject        @ object was null
7403    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7404    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7405    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7406    SET_VREG(r0, r2)                    @ fp[A]<- r0
7407    GOTO_OPCODE(ip)                     @ jump to next instruction
7408
7409/* ------------------------------ */
7410    .balign 64
7411.L_OP_IGET_WIDE_QUICK: /* 0xf3 */
7412/* File: armv6t2/OP_IGET_WIDE_QUICK.S */
7413    /* iget-wide-quick vA, vB, offset@CCCC */
7414    mov     r2, rINST, lsr #12          @ r2<- B
7415    FETCH(ip, 1)                        @ ip<- field byte offset
7416    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7417    ubfx    r2, rINST, #8, #4           @ r2<- A
7418    cmp     r3, #0                      @ check object for null
7419    beq     common_errNullObject        @ object was null
7420    ldrd    r0, [r3, ip]                @ r0<- obj.field (64 bits, aligned)
7421    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7422    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
7423    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7424    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
7425    GOTO_OPCODE(ip)                     @ jump to next instruction
7426
7427/* ------------------------------ */
7428    .balign 64
7429.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
7430/* File: armv5te/OP_IGET_OBJECT_QUICK.S */
7431/* File: armv5te/OP_IGET_QUICK.S */
7432    /* For: iget-quick, iget-object-quick */
7433    /* op vA, vB, offset@CCCC */
7434    mov     r2, rINST, lsr #12          @ r2<- B
7435    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7436    FETCH(r1, 1)                        @ r1<- field byte offset
7437    cmp     r3, #0                      @ check object for null
7438    mov     r2, rINST, lsr #8           @ r2<- A(+)
7439    beq     common_errNullObject        @ object was null
7440    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7441    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7442    and     r2, r2, #15
7443    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7444    SET_VREG(r0, r2)                    @ fp[A]<- r0
7445    GOTO_OPCODE(ip)                     @ jump to next instruction
7446
7447
7448/* ------------------------------ */
7449    .balign 64
7450.L_OP_IPUT_QUICK: /* 0xf5 */
7451/* File: armv6t2/OP_IPUT_QUICK.S */
7452    /* For: iput-quick, iput-object-quick */
7453    /* op vA, vB, offset@CCCC */
7454    mov     r2, rINST, lsr #12          @ r2<- B
7455    FETCH(r1, 1)                        @ r1<- field byte offset
7456    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7457    ubfx    r2, rINST, #8, #4           @ r2<- A
7458    cmp     r3, #0                      @ check object for null
7459    beq     common_errNullObject        @ object was null
7460    GET_VREG(r0, r2)                    @ r0<- fp[A]
7461    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7462    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7463    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7464    GOTO_OPCODE(ip)                     @ jump to next instruction
7465
7466/* ------------------------------ */
7467    .balign 64
7468.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
7469/* File: armv6t2/OP_IPUT_WIDE_QUICK.S */
7470    /* iput-wide-quick vA, vB, offset@CCCC */
7471    mov     r1, rINST, lsr #12          @ r1<- B
7472    ubfx    r0, rINST, #8, #4           @ r0<- A
7473    GET_VREG(r2, r1)                    @ r2<- fp[B], the object pointer
7474    add     r3, rFP, r0, lsl #2         @ r3<- &fp[A]
7475    cmp     r2, #0                      @ check object for null
7476    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[A]
7477    beq     common_errNullObject        @ object was null
7478    FETCH(r3, 1)                        @ r3<- field byte offset
7479    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7480    strd    r0, [r2, r3]                @ obj.field (64 bits, aligned)<- r0/r1
7481    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7482    GOTO_OPCODE(ip)                     @ jump to next instruction
7483
7484/* ------------------------------ */
7485    .balign 64
7486.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
7487/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
7488    /* For: iput-object-quick */
7489    /* op vA, vB, offset@CCCC */
7490    mov     r2, rINST, lsr #12          @ r2<- B
7491    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7492    FETCH(r1, 1)                        @ r1<- field byte offset
7493    cmp     r3, #0                      @ check object for null
7494    mov     r2, rINST, lsr #8           @ r2<- A(+)
7495    beq     common_errNullObject        @ object was null
7496    and     r2, r2, #15
7497    GET_VREG(r0, r2)                    @ r0<- fp[A]
7498    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
7499    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7500    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7501    cmp     r0, #0
7502    strneb  r2, [r2, r3, lsr #GC_CARD_SHIFT] @ mark card based on obj head
7503    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7504    GOTO_OPCODE(ip)                     @ jump to next instruction
7505
7506/* ------------------------------ */
7507    .balign 64
7508.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
7509/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7510    /*
7511     * Handle an optimized virtual method call.
7512     *
7513     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7514     */
7515    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7516    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7517    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7518    FETCH(r1, 1)                        @ r1<- BBBB
7519    .if     (!0)
7520    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7521    .endif
7522    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7523    cmp     r2, #0                      @ is "this" null?
7524    beq     common_errNullObject        @ null "this", throw exception
7525    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7526    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7527    EXPORT_PC()                         @ invoke must export
7528    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7529    bl      common_invokeMethodNoRange @ continue on
7530
7531/* ------------------------------ */
7532    .balign 64
7533.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
7534/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
7535/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7536    /*
7537     * Handle an optimized virtual method call.
7538     *
7539     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7540     */
7541    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7542    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7543    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7544    FETCH(r1, 1)                        @ r1<- BBBB
7545    .if     (!1)
7546    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7547    .endif
7548    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7549    cmp     r2, #0                      @ is "this" null?
7550    beq     common_errNullObject        @ null "this", throw exception
7551    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7552    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7553    EXPORT_PC()                         @ invoke must export
7554    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7555    bl      common_invokeMethodRange @ continue on
7556
7557
7558/* ------------------------------ */
7559    .balign 64
7560.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
7561/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7562    /*
7563     * Handle an optimized "super" method call.
7564     *
7565     * for: [opt] invoke-super-quick, invoke-super-quick/range
7566     */
7567    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7568    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7569    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7570    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7571    .if     (!0)
7572    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7573    .endif
7574    FETCH(r1, 1)                        @ r1<- BBBB
7575    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7576    EXPORT_PC()                         @ must export for invoke
7577    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7578    GET_VREG(r3, r10)                   @ r3<- "this"
7579    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7580    cmp     r3, #0                      @ null "this" ref?
7581    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7582    beq     common_errNullObject        @ "this" is null, throw exception
7583    bl      common_invokeMethodNoRange @ continue on
7584
7585/* ------------------------------ */
7586    .balign 64
7587.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
7588/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
7589/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7590    /*
7591     * Handle an optimized "super" method call.
7592     *
7593     * for: [opt] invoke-super-quick, invoke-super-quick/range
7594     */
7595    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7596    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7597    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7598    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7599    .if     (!1)
7600    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7601    .endif
7602    FETCH(r1, 1)                        @ r1<- BBBB
7603    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7604    EXPORT_PC()                         @ must export for invoke
7605    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7606    GET_VREG(r3, r10)                   @ r3<- "this"
7607    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7608    cmp     r3, #0                      @ null "this" ref?
7609    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7610    beq     common_errNullObject        @ "this" is null, throw exception
7611    bl      common_invokeMethodRange @ continue on
7612
7613
7614/* ------------------------------ */
7615    .balign 64
7616.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */
7617/* File: armv5te/OP_IPUT_OBJECT_VOLATILE.S */
7618/* File: armv5te/OP_IPUT_OBJECT.S */
7619    /*
7620     * 32-bit instance field put.
7621     *
7622     * for: iput-object, iput-object-volatile
7623     */
7624    /* op vA, vB, field@CCCC */
7625    mov     r0, rINST, lsr #12          @ r0<- B
7626    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7627    FETCH(r1, 1)                        @ r1<- field ref CCCC
7628    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7629    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7630    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7631    cmp     r0, #0                      @ is resolved entry null?
7632    bne     .LOP_IPUT_OBJECT_VOLATILE_finish          @ no, already resolved
76338:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7634    EXPORT_PC()                         @ resolve() could throw
7635    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7636    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7637    cmp     r0, #0                      @ success?
7638    bne     .LOP_IPUT_OBJECT_VOLATILE_finish          @ yes, finish up
7639    b       common_exceptionThrown
7640
7641
7642/* ------------------------------ */
7643    .balign 64
7644.L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */
7645/* File: armv5te/OP_SGET_OBJECT_VOLATILE.S */
7646/* File: armv5te/OP_SGET.S */
7647    /*
7648     * General 32-bit SGET handler.
7649     *
7650     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
7651     */
7652    /* op vAA, field@BBBB */
7653    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7654    FETCH(r1, 1)                        @ r1<- field ref BBBB
7655    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7656    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7657    cmp     r0, #0                      @ is resolved entry null?
7658    beq     .LOP_SGET_OBJECT_VOLATILE_resolve         @ yes, do resolve
7659.LOP_SGET_OBJECT_VOLATILE_finish: @ field ptr in r0
7660    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
7661    SMP_DMB                            @ acquiring load
7662    mov     r2, rINST, lsr #8           @ r2<- AA
7663    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7664    SET_VREG(r1, r2)                    @ fp[AA]<- r1
7665    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7666    GOTO_OPCODE(ip)                     @ jump to next instruction
7667
7668
7669/* ------------------------------ */
7670    .balign 64
7671.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */
7672/* File: armv5te/OP_SPUT_OBJECT_VOLATILE.S */
7673/* File: armv5te/OP_SPUT_OBJECT.S */
7674    /*
7675     * 32-bit SPUT handler for objects
7676     *
7677     * for: sput-object, sput-object-volatile
7678     */
7679    /* op vAA, field@BBBB */
7680    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7681    FETCH(r1, 1)                        @ r1<- field ref BBBB
7682    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7683    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7684    cmp     r0, #0                      @ is resolved entry null?
7685    bne     .LOP_SPUT_OBJECT_VOLATILE_finish          @ no, continue
7686    ldr     r9, [rGLUE, #offGlue_method]    @ r9<- current method
7687    EXPORT_PC()                         @ resolve() could throw, so export now
7688    ldr     r0, [r9, #offMethod_clazz]  @ r0<- method->clazz
7689    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
7690    cmp     r0, #0                      @ success?
7691    bne     .LOP_SPUT_OBJECT_VOLATILE_finish          @ yes, finish
7692    b       common_exceptionThrown      @ no, handle exception
7693
7694
7695
7696/* ------------------------------ */
7697    .balign 64
7698.L_OP_DISPATCH_FF: /* 0xff */
7699/* File: armv5te/OP_DISPATCH_FF.S */
7700    mov     ip, rINST, lsr #8           @ r9<- extended opcode
7701    add     ip, ip, #256                @ add offset for extended opcodes
7702    GOTO_OPCODE(ip)                     @ go to proper extended handler
7703
7704
7705/* ------------------------------ */
7706    .balign 64
7707.L_OP_CONST_CLASS_JUMBO: /* 0x100 */
7708/* File: armv5te/OP_CONST_CLASS_JUMBO.S */
7709    /* const-class/jumbo vBBBB, Class@AAAAAAAA */
7710    FETCH(r0, 1)                        @ r0<- aaaa (lo)
7711    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
7712    FETCH(r1, 2)                        @ r1<- AAAA (hi)
7713    ldr     r2, [r2, #offDvmDex_pResClasses]   @ r2<- dvmDex->pResClasses
7714    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
7715    FETCH(r9, 3)                        @ r9<- BBBB
7716    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResClasses[AAAAaaaa]
7717    cmp     r0, #0                      @ not yet resolved?
7718    beq     .LOP_CONST_CLASS_JUMBO_resolve
7719    FETCH_ADVANCE_INST(4)               @ advance rPC, load rINST
7720    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7721    SET_VREG(r0, r9)                    @ vBBBB<- r0
7722    GOTO_OPCODE(ip)                     @ jump to next instruction
7723
7724/* ------------------------------ */
7725    .balign 64
7726.L_OP_CHECK_CAST_JUMBO: /* 0x101 */
7727/* File: armv5te/OP_CHECK_CAST_JUMBO.S */
7728    /*
7729     * Check to see if a cast from one class to another is allowed.
7730     */
7731    /* check-cast/jumbo vBBBB, class@AAAAAAAA */
7732    FETCH(r0, 1)                        @ r0<- aaaa (lo)
7733    FETCH(r2, 2)                        @ r2<- AAAA (hi)
7734    FETCH(r3, 3)                        @ r3<- BBBB
7735    orr     r2, r0, r2, lsl #16         @ r2<- AAAAaaaa
7736    GET_VREG(r9, r3)                    @ r9<- object
7737    ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- pDvmDex
7738    cmp     r9, #0                      @ is object null?
7739    ldr     r0, [r0, #offDvmDex_pResClasses]    @ r0<- pDvmDex->pResClasses
7740    beq     .LOP_CHECK_CAST_JUMBO_okay            @ null obj, cast always succeeds
7741    ldr     r1, [r0, r2, lsl #2]        @ r1<- resolved class
7742    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
7743    cmp     r1, #0                      @ have we resolved this before?
7744    beq     .LOP_CHECK_CAST_JUMBO_resolve         @ not resolved, do it now
7745.LOP_CHECK_CAST_JUMBO_resolved:
7746    cmp     r0, r1                      @ same class (trivial success)?
7747    bne     .LOP_CHECK_CAST_JUMBO_fullcheck       @ no, do full check
7748    b       .LOP_CHECK_CAST_JUMBO_okay            @ yes, finish up
7749
7750/* ------------------------------ */
7751    .balign 64
7752.L_OP_INSTANCE_OF_JUMBO: /* 0x102 */
7753/* File: armv5te/OP_INSTANCE_OF_JUMBO.S */
7754    /*
7755     * Check to see if an object reference is an instance of a class.
7756     *
7757     * Most common situation is a non-null object, being compared against
7758     * an already-resolved class.
7759     *
7760     * TODO: convert most of this into a common subroutine, shared with
7761     *       OP_INSTANCE_OF.S.
7762     */
7763    /* instance-of/jumbo vBBBB, vCCCC, class@AAAAAAAA */
7764    FETCH(r3, 4)                        @ r3<- vCCCC
7765    FETCH(r9, 3)                        @ r9<- vBBBB
7766    GET_VREG(r0, r3)                    @ r0<- vCCCC (object)
7767    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- pDvmDex
7768    cmp     r0, #0                      @ is object null?
7769    beq     .LOP_INSTANCE_OF_JUMBO_store           @ null obj, not an instance, store r0
7770    FETCH(r1, 1)                        @ r1<- aaaa (lo)
7771    FETCH(r3, 2)                        @ r3<- AAAA (hi)
7772    ldr     r2, [r2, #offDvmDex_pResClasses]    @ r2<- pDvmDex->pResClasses
7773    orr     r3, r1, r3, lsl #16         @ r3<- AAAAaaaa
7774    ldr     r1, [r2, r3, lsl #2]        @ r1<- resolved class
7775    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
7776    cmp     r1, #0                      @ have we resolved this before?
7777    beq     .LOP_INSTANCE_OF_JUMBO_resolve         @ not resolved, do it now
7778    b       .LOP_INSTANCE_OF_JUMBO_resolved        @ resolved, continue
7779
7780/* ------------------------------ */
7781    .balign 64
7782.L_OP_NEW_INSTANCE_JUMBO: /* 0x103 */
7783/* File: armv5te/OP_NEW_INSTANCE_JUMBO.S */
7784    /*
7785     * Create a new instance of a class.
7786     */
7787    /* new-instance/jumbo vBBBB, class@AAAAAAAA */
7788    FETCH(r0, 1)                        @ r0<- aaaa (lo)
7789    FETCH(r1, 2)                        @ r1<- AAAA (hi)
7790    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
7791    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
7792    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
7793    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
7794    EXPORT_PC()                         @ req'd for init, resolve, alloc
7795    cmp     r0, #0                      @ already resolved?
7796    beq     .LOP_NEW_INSTANCE_JUMBO_resolve         @ no, resolve it now
7797.LOP_NEW_INSTANCE_JUMBO_resolved:   @ r0=class
7798    ldrb    r1, [r0, #offClassObject_status]    @ r1<- ClassStatus enum
7799    cmp     r1, #CLASS_INITIALIZED      @ has class been initialized?
7800    bne     .LOP_NEW_INSTANCE_JUMBO_needinit        @ no, init class now
7801.LOP_NEW_INSTANCE_JUMBO_initialized: @ r0=class
7802    mov     r1, #ALLOC_DONT_TRACK       @ flags for alloc call
7803    bl      dvmAllocObject              @ r0<- new object
7804    b       .LOP_NEW_INSTANCE_JUMBO_finish          @ continue
7805
7806/* ------------------------------ */
7807    .balign 64
7808.L_OP_NEW_ARRAY_JUMBO: /* 0x104 */
7809/* File: armv5te/OP_NEW_ARRAY_JUMBO.S */
7810    /*
7811     * Allocate an array of objects, specified with the array class
7812     * and a count.
7813     *
7814     * The verifier guarantees that this is an array class, so we don't
7815     * check for it here.
7816     */
7817    /* new-array/jumbo vBBBB, vCCCC, class@AAAAAAAA */
7818    FETCH(r2, 1)                        @ r2<- aaaa (lo)
7819    FETCH(r3, 2)                        @ r3<- AAAA (hi)
7820    FETCH(r0, 4)                        @ r0<- vCCCC
7821    orr     r2, r2, r3, lsl #16         @ r2<- AAAAaaaa
7822    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
7823    GET_VREG(r1, r0)                    @ r1<- vCCCC (array length)
7824    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
7825    cmp     r1, #0                      @ check length
7826    ldr     r0, [r3, r2, lsl #2]        @ r0<- resolved class
7827    bmi     common_errNegativeArraySize @ negative length, bail
7828    cmp     r0, #0                      @ already resolved?
7829    EXPORT_PC()                         @ req'd for resolve, alloc
7830    bne     .LOP_NEW_ARRAY_JUMBO_finish          @ resolved, continue
7831    b       .LOP_NEW_ARRAY_JUMBO_resolve         @ do resolve now
7832
7833/* ------------------------------ */
7834    .balign 64
7835.L_OP_FILLED_NEW_ARRAY_JUMBO: /* 0x105 */
7836/* File: armv5te/OP_FILLED_NEW_ARRAY_JUMBO.S */
7837    /*
7838     * Create a new array with elements filled from registers.
7839     *
7840     * TODO: convert most of this into a common subroutine, shared with
7841     *       OP_FILLED_NEW_ARRAY.S.
7842     */
7843    /* filled-new-array/jumbo {vCCCC..v(CCCC+BBBB-1)}, type@AAAAAAAA */
7844    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
7845    FETCH(r0, 1)                        @ r0<- aaaa (lo)
7846    FETCH(r1, 2)                        @ r1<- AAAA (hi)
7847    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
7848    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
7849    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
7850    EXPORT_PC()                         @ need for resolve and alloc
7851    cmp     r0, #0                      @ already resolved?
7852    bne     .LOP_FILLED_NEW_ARRAY_JUMBO_continue        @ yes, continue on
78538:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7854    mov     r2, #0                      @ r2<- false
7855    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7856    bl      dvmResolveClass             @ r0<- call(clazz, ref)
7857    cmp     r0, #0                      @ got null?
7858    beq     common_exceptionThrown      @ yes, handle exception
7859    b       .LOP_FILLED_NEW_ARRAY_JUMBO_continue
7860
7861/* ------------------------------ */
7862    .balign 64
7863.L_OP_IGET_JUMBO: /* 0x106 */
7864/* File: armv5te/OP_IGET_JUMBO.S */
7865    /*
7866     * Jumbo 32-bit instance field get.
7867     *
7868     * for: iget/jumbo, iget-object/jumbo, iget-boolean/jumbo, iget-byte/jumbo,
7869     *      iget-char/jumbo, iget-short/jumbo
7870     */
7871    /* exop vBBBB, vCCCC, field@AAAAAAAA */
7872    FETCH(r1, 1)                        @ r1<- aaaa (lo)
7873    FETCH(r2, 2)                        @ r2<- AAAA (hi)
7874    FETCH(r0, 4)                        @ r0<- CCCC
7875    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7876    orr     r1, r1, r2, lsl #16         @ r1<- AAAAaaaa
7877    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7878    GET_VREG(r9, r0)                    @ r9<- fp[CCCC], the object pointer
7879    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7880    cmp     r0, #0                      @ is resolved entry null?
7881    bne     .LOP_IGET_JUMBO_finish          @ no, already resolved
78828:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7883    EXPORT_PC()                         @ resolve() could throw
7884    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7885    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7886    b       .LOP_IGET_JUMBO_resolved        @ resolved, continue
7887
7888/* ------------------------------ */
7889    .balign 64
7890.L_OP_IGET_WIDE_JUMBO: /* 0x107 */
7891/* File: armv5te/OP_IGET_WIDE_JUMBO.S */
7892    /*
7893     * Jumbo 64-bit instance field get.
7894     */
7895    /* iget-wide/jumbo vBBBB, vCCCC, field@AAAAAAAA */
7896    FETCH(r1, 1)                        @ r1<- aaaa (lo)
7897    FETCH(r2, 2)                        @ r2<- AAAA (hi)
7898    FETCH(r0, 4)                        @ r0<- CCCC
7899    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7900    orr     r1, r1, r2, lsl #16         @ r1<- AAAAaaaa
7901    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
7902    GET_VREG(r9, r0)                    @ r9<- fp[CCCC], the object pointer
7903    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7904    cmp     r0, #0                      @ is resolved entry null?
7905    bne     .LOP_IGET_WIDE_JUMBO_finish          @ no, already resolved
79068:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
7907    EXPORT_PC()                         @ resolve() could throw
7908    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7909    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7910    b       .LOP_IGET_WIDE_JUMBO_resolved        @ resolved, continue
7911
7912/* ------------------------------ */
7913    .balign 64
7914.L_OP_IGET_OBJECT_JUMBO: /* 0x108 */
7915/* File: armv5te/OP_IGET_OBJECT_JUMBO.S */
7916/* File: armv5te/OP_IGET_JUMBO.S */
7917    /*
7918     * Jumbo 32-bit instance field get.
7919     *
7920     * for: iget/jumbo, iget-object/jumbo, iget-boolean/jumbo, iget-byte/jumbo,
7921     *      iget-char/jumbo, iget-short/jumbo
7922     */
7923    /* exop vBBBB, vCCCC, field@AAAAAAAA */
7924    FETCH(r1, 1)                        @ r1<- aaaa (lo)
7925    FETCH(r2, 2)                        @ r2<- AAAA (hi)
7926    FETCH(r0, 4)                        @ r0<- CCCC
7927    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7928    orr     r1, r1, r2, lsl #16         @ r1<- AAAAaaaa
7929    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7930    GET_VREG(r9, r0)                    @ r9<- fp[CCCC], the object pointer
7931    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7932    cmp     r0, #0                      @ is resolved entry null?
7933    bne     .LOP_IGET_OBJECT_JUMBO_finish          @ no, already resolved
79348:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7935    EXPORT_PC()                         @ resolve() could throw
7936    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7937    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7938    b       .LOP_IGET_OBJECT_JUMBO_resolved        @ resolved, continue
7939
7940
7941/* ------------------------------ */
7942    .balign 64
7943.L_OP_IGET_BOOLEAN_JUMBO: /* 0x109 */
7944/* File: armv5te/OP_IGET_BOOLEAN_JUMBO.S */
7945@include "armv5te/OP_IGET_JUMBO.S" { "load":"ldrb", "sqnum":"1" }
7946/* File: armv5te/OP_IGET_JUMBO.S */
7947    /*
7948     * Jumbo 32-bit instance field get.
7949     *
7950     * for: iget/jumbo, iget-object/jumbo, iget-boolean/jumbo, iget-byte/jumbo,
7951     *      iget-char/jumbo, iget-short/jumbo
7952     */
7953    /* exop vBBBB, vCCCC, field@AAAAAAAA */
7954    FETCH(r1, 1)                        @ r1<- aaaa (lo)
7955    FETCH(r2, 2)                        @ r2<- AAAA (hi)
7956    FETCH(r0, 4)                        @ r0<- CCCC
7957    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7958    orr     r1, r1, r2, lsl #16         @ r1<- AAAAaaaa
7959    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7960    GET_VREG(r9, r0)                    @ r9<- fp[CCCC], the object pointer
7961    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7962    cmp     r0, #0                      @ is resolved entry null?
7963    bne     .LOP_IGET_BOOLEAN_JUMBO_finish          @ no, already resolved
79648:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7965    EXPORT_PC()                         @ resolve() could throw
7966    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7967    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7968    b       .LOP_IGET_BOOLEAN_JUMBO_resolved        @ resolved, continue
7969
7970
7971/* ------------------------------ */
7972    .balign 64
7973.L_OP_IGET_BYTE_JUMBO: /* 0x10a */
7974/* File: armv5te/OP_IGET_BYTE_JUMBO.S */
7975@include "armv5te/OP_IGET_JUMBO.S" { "load":"ldrsb", "sqnum":"2" }
7976/* File: armv5te/OP_IGET_JUMBO.S */
7977    /*
7978     * Jumbo 32-bit instance field get.
7979     *
7980     * for: iget/jumbo, iget-object/jumbo, iget-boolean/jumbo, iget-byte/jumbo,
7981     *      iget-char/jumbo, iget-short/jumbo
7982     */
7983    /* exop vBBBB, vCCCC, field@AAAAAAAA */
7984    FETCH(r1, 1)                        @ r1<- aaaa (lo)
7985    FETCH(r2, 2)                        @ r2<- AAAA (hi)
7986    FETCH(r0, 4)                        @ r0<- CCCC
7987    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7988    orr     r1, r1, r2, lsl #16         @ r1<- AAAAaaaa
7989    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7990    GET_VREG(r9, r0)                    @ r9<- fp[CCCC], the object pointer
7991    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7992    cmp     r0, #0                      @ is resolved entry null?
7993    bne     .LOP_IGET_BYTE_JUMBO_finish          @ no, already resolved
79948:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7995    EXPORT_PC()                         @ resolve() could throw
7996    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7997    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7998    b       .LOP_IGET_BYTE_JUMBO_resolved        @ resolved, continue
7999
8000
8001/* ------------------------------ */
8002    .balign 64
8003.L_OP_IGET_CHAR_JUMBO: /* 0x10b */
8004/* File: armv5te/OP_IGET_CHAR_JUMBO.S */
8005@include "armv5te/OP_IGET_JUMBO.S" { "load":"ldrh", "sqnum":"3" }
8006/* File: armv5te/OP_IGET_JUMBO.S */
8007    /*
8008     * Jumbo 32-bit instance field get.
8009     *
8010     * for: iget/jumbo, iget-object/jumbo, iget-boolean/jumbo, iget-byte/jumbo,
8011     *      iget-char/jumbo, iget-short/jumbo
8012     */
8013    /* exop vBBBB, vCCCC, field@AAAAAAAA */
8014    FETCH(r1, 1)                        @ r1<- aaaa (lo)
8015    FETCH(r2, 2)                        @ r2<- AAAA (hi)
8016    FETCH(r0, 4)                        @ r0<- CCCC
8017    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
8018    orr     r1, r1, r2, lsl #16         @ r1<- AAAAaaaa
8019    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
8020    GET_VREG(r9, r0)                    @ r9<- fp[CCCC], the object pointer
8021    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
8022    cmp     r0, #0                      @ is resolved entry null?
8023    bne     .LOP_IGET_CHAR_JUMBO_finish          @ no, already resolved
80248:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8025    EXPORT_PC()                         @ resolve() could throw
8026    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8027    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
8028    b       .LOP_IGET_CHAR_JUMBO_resolved        @ resolved, continue
8029
8030
8031/* ------------------------------ */
8032    .balign 64
8033.L_OP_IGET_SHORT_JUMBO: /* 0x10c */
8034/* File: armv5te/OP_IGET_SHORT_JUMBO.S */
8035@include "armv5te/OP_IGET_JUMBO.S" { "load":"ldrsh", "sqnum":"4" }
8036/* File: armv5te/OP_IGET_JUMBO.S */
8037    /*
8038     * Jumbo 32-bit instance field get.
8039     *
8040     * for: iget/jumbo, iget-object/jumbo, iget-boolean/jumbo, iget-byte/jumbo,
8041     *      iget-char/jumbo, iget-short/jumbo
8042     */
8043    /* exop vBBBB, vCCCC, field@AAAAAAAA */
8044    FETCH(r1, 1)                        @ r1<- aaaa (lo)
8045    FETCH(r2, 2)                        @ r2<- AAAA (hi)
8046    FETCH(r0, 4)                        @ r0<- CCCC
8047    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
8048    orr     r1, r1, r2, lsl #16         @ r1<- AAAAaaaa
8049    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
8050    GET_VREG(r9, r0)                    @ r9<- fp[CCCC], the object pointer
8051    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
8052    cmp     r0, #0                      @ is resolved entry null?
8053    bne     .LOP_IGET_SHORT_JUMBO_finish          @ no, already resolved
80548:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8055    EXPORT_PC()                         @ resolve() could throw
8056    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8057    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
8058    b       .LOP_IGET_SHORT_JUMBO_resolved        @ resolved, continue
8059
8060
8061/* ------------------------------ */
8062    .balign 64
8063.L_OP_IPUT_JUMBO: /* 0x10d */
8064/* File: armv5te/OP_IPUT_JUMBO.S */
8065    /*
8066     * Jumbo 32-bit instance field put.
8067     *
8068     * for: iput/jumbo, iput-boolean/jumbo, iput-byte/jumbo, iput-char/jumbo,
8069     *      iput-short/jumbo
8070     */
8071    /* exop vBBBB, vCCCC, field@AAAAAAAA */
8072    FETCH(r1, 1)                        @ r1<- aaaa (lo)
8073    FETCH(r2, 2)                        @ r2<- AAAA (hi)
8074    FETCH(r0, 4)                        @ r0<- CCCC
8075    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
8076    orr     r1, r1, r2, lsl #16         @ r1<- AAAAaaaa
8077    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
8078    GET_VREG(r9, r0)                    @ r9<- fp[CCCC], the object pointer
8079    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
8080    cmp     r0, #0                      @ is resolved entry null?
8081    bne     .LOP_IPUT_JUMBO_finish          @ no, already resolved
80828:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8083    EXPORT_PC()                         @ resolve() could throw
8084    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8085    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
8086    b       .LOP_IPUT_JUMBO_resolved        @ resolved, continue
8087
8088/* ------------------------------ */
8089    .balign 64
8090.L_OP_IPUT_WIDE_JUMBO: /* 0x10e */
8091/* File: armv5te/OP_IPUT_WIDE_JUMBO.S */
8092    /* iput-wide/jumbo vBBBB, vCCCC, field@AAAAAAAA */
8093    FETCH(r1, 1)                        @ r1<- aaaa (lo)
8094    FETCH(r2, 2)                        @ r2<- AAAA (hi)
8095    FETCH(r0, 4)                        @ r0<- CCCC
8096    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
8097    orr     r1, r1, r2, lsl #16         @ r1<- AAAAaaaa
8098    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
8099    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
8100    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
8101    cmp     r0, #0                      @ is resolved entry null?
8102    bne     .LOP_IPUT_WIDE_JUMBO_finish          @ no, already resolved
81038:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
8104    EXPORT_PC()                         @ resolve() could throw
8105    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8106    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
8107    b       .LOP_IPUT_WIDE_JUMBO_resolved        @ resolved, continue
8108
8109/* ------------------------------ */
8110    .balign 64
8111.L_OP_IPUT_OBJECT_JUMBO: /* 0x10f */
8112/* File: armv5te/OP_IPUT_OBJECT_JUMBO.S */
8113    /*
8114     * Jumbo 32-bit instance field put.
8115     */
8116    /* iput-object/jumbo vBBBB, vCCCC, field@AAAAAAAA */
8117    FETCH(r1, 1)                        @ r1<- aaaa (lo)
8118    FETCH(r2, 2)                        @ r2<- AAAA (hi)
8119    FETCH(r0, 4)                        @ r0<- CCCC
8120    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
8121    orr     r1, r1, r2, lsl #16         @ r1<- AAAAaaaa
8122    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
8123    GET_VREG(r9, r0)                    @ r9<- fp[CCCC], the object pointer
8124    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
8125    cmp     r0, #0                      @ is resolved entry null?
8126    bne     .LOP_IPUT_OBJECT_JUMBO_finish          @ no, already resolved
81278:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8128    EXPORT_PC()                         @ resolve() could throw
8129    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8130    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
8131    b       .LOP_IPUT_OBJECT_JUMBO_resolved        @ resolved, continue
8132
8133/* ------------------------------ */
8134    .balign 64
8135.L_OP_IPUT_BOOLEAN_JUMBO: /* 0x110 */
8136/* File: armv5te/OP_IPUT_BOOLEAN_JUMBO.S */
8137@include "armv5te/OP_IPUT_JUMBO.S" { "store":"strb", "sqnum":"1" }
8138/* File: armv5te/OP_IPUT_JUMBO.S */
8139    /*
8140     * Jumbo 32-bit instance field put.
8141     *
8142     * for: iput/jumbo, iput-boolean/jumbo, iput-byte/jumbo, iput-char/jumbo,
8143     *      iput-short/jumbo
8144     */
8145    /* exop vBBBB, vCCCC, field@AAAAAAAA */
8146    FETCH(r1, 1)                        @ r1<- aaaa (lo)
8147    FETCH(r2, 2)                        @ r2<- AAAA (hi)
8148    FETCH(r0, 4)                        @ r0<- CCCC
8149    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
8150    orr     r1, r1, r2, lsl #16         @ r1<- AAAAaaaa
8151    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
8152    GET_VREG(r9, r0)                    @ r9<- fp[CCCC], the object pointer
8153    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
8154    cmp     r0, #0                      @ is resolved entry null?
8155    bne     .LOP_IPUT_BOOLEAN_JUMBO_finish          @ no, already resolved
81568:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8157    EXPORT_PC()                         @ resolve() could throw
8158    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8159    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
8160    b       .LOP_IPUT_BOOLEAN_JUMBO_resolved        @ resolved, continue
8161
8162
8163/* ------------------------------ */
8164    .balign 64
8165.L_OP_IPUT_BYTE_JUMBO: /* 0x111 */
8166/* File: armv5te/OP_IPUT_BYTE_JUMBO.S */
8167@include "armv5te/OP_IPUT_JUMBO.S" { "store":"strb", "sqnum":"2" }
8168/* File: armv5te/OP_IPUT_JUMBO.S */
8169    /*
8170     * Jumbo 32-bit instance field put.
8171     *
8172     * for: iput/jumbo, iput-boolean/jumbo, iput-byte/jumbo, iput-char/jumbo,
8173     *      iput-short/jumbo
8174     */
8175    /* exop vBBBB, vCCCC, field@AAAAAAAA */
8176    FETCH(r1, 1)                        @ r1<- aaaa (lo)
8177    FETCH(r2, 2)                        @ r2<- AAAA (hi)
8178    FETCH(r0, 4)                        @ r0<- CCCC
8179    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
8180    orr     r1, r1, r2, lsl #16         @ r1<- AAAAaaaa
8181    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
8182    GET_VREG(r9, r0)                    @ r9<- fp[CCCC], the object pointer
8183    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
8184    cmp     r0, #0                      @ is resolved entry null?
8185    bne     .LOP_IPUT_BYTE_JUMBO_finish          @ no, already resolved
81868:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8187    EXPORT_PC()                         @ resolve() could throw
8188    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8189    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
8190    b       .LOP_IPUT_BYTE_JUMBO_resolved        @ resolved, continue
8191
8192
8193/* ------------------------------ */
8194    .balign 64
8195.L_OP_IPUT_CHAR_JUMBO: /* 0x112 */
8196/* File: armv5te/OP_IPUT_CHAR_JUMBO.S */
8197@include "armv5te/OP_IPUT_JUMBO.S" { "store":"strh", "sqnum":"3" }
8198/* File: armv5te/OP_IPUT_JUMBO.S */
8199    /*
8200     * Jumbo 32-bit instance field put.
8201     *
8202     * for: iput/jumbo, iput-boolean/jumbo, iput-byte/jumbo, iput-char/jumbo,
8203     *      iput-short/jumbo
8204     */
8205    /* exop vBBBB, vCCCC, field@AAAAAAAA */
8206    FETCH(r1, 1)                        @ r1<- aaaa (lo)
8207    FETCH(r2, 2)                        @ r2<- AAAA (hi)
8208    FETCH(r0, 4)                        @ r0<- CCCC
8209    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
8210    orr     r1, r1, r2, lsl #16         @ r1<- AAAAaaaa
8211    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
8212    GET_VREG(r9, r0)                    @ r9<- fp[CCCC], the object pointer
8213    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
8214    cmp     r0, #0                      @ is resolved entry null?
8215    bne     .LOP_IPUT_CHAR_JUMBO_finish          @ no, already resolved
82168:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8217    EXPORT_PC()                         @ resolve() could throw
8218    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8219    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
8220    b       .LOP_IPUT_CHAR_JUMBO_resolved        @ resolved, continue
8221
8222
8223/* ------------------------------ */
8224    .balign 64
8225.L_OP_IPUT_SHORT_JUMBO: /* 0x113 */
8226/* File: armv5te/OP_IPUT_SHORT_JUMBO.S */
8227@include "armv5te/OP_IPUT_JUMBO.S" { "store":"strh", "sqnum":"4" }
8228/* File: armv5te/OP_IPUT_JUMBO.S */
8229    /*
8230     * Jumbo 32-bit instance field put.
8231     *
8232     * for: iput/jumbo, iput-boolean/jumbo, iput-byte/jumbo, iput-char/jumbo,
8233     *      iput-short/jumbo
8234     */
8235    /* exop vBBBB, vCCCC, field@AAAAAAAA */
8236    FETCH(r1, 1)                        @ r1<- aaaa (lo)
8237    FETCH(r2, 2)                        @ r2<- AAAA (hi)
8238    FETCH(r0, 4)                        @ r0<- CCCC
8239    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
8240    orr     r1, r1, r2, lsl #16         @ r1<- AAAAaaaa
8241    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
8242    GET_VREG(r9, r0)                    @ r9<- fp[CCCC], the object pointer
8243    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
8244    cmp     r0, #0                      @ is resolved entry null?
8245    bne     .LOP_IPUT_SHORT_JUMBO_finish          @ no, already resolved
82468:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8247    EXPORT_PC()                         @ resolve() could throw
8248    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8249    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
8250    b       .LOP_IPUT_SHORT_JUMBO_resolved        @ resolved, continue
8251
8252
8253/* ------------------------------ */
8254    .balign 64
8255.L_OP_SGET_JUMBO: /* 0x114 */
8256/* File: armv5te/OP_SGET_JUMBO.S */
8257    /*
8258     * Jumbo 32-bit SGET handler.
8259     *
8260     * for: sget/jumbo, sget-object/jumbo, sget-boolean/jumbo, sget-byte/jumbo,
8261     *      sget-char/jumbo, sget-short/jumbo
8262     */
8263    /* exop vBBBB, field@AAAAAAAA */
8264    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
8265    FETCH(r0, 1)                        @ r0<- aaaa (lo)
8266    FETCH(r1, 2)                        @ r1<- AAAA (hi)
8267    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
8268    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
8269    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
8270    cmp     r0, #0                      @ is resolved entry null?
8271    beq     .LOP_SGET_JUMBO_resolve         @ yes, do resolve
8272.LOP_SGET_JUMBO_finish: @ field ptr in r0
8273    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
8274    @ no-op                             @ acquiring load
8275    FETCH(r2, 3)                        @ r2<- BBBB
8276    FETCH_ADVANCE_INST(4)               @ advance rPC, load rINST
8277    SET_VREG(r1, r2)                    @ fp[BBBB]<- r1
8278    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8279    GOTO_OPCODE(ip)                     @ jump to next instruction
8280
8281/* ------------------------------ */
8282    .balign 64
8283.L_OP_SGET_WIDE_JUMBO: /* 0x115 */
8284/* File: armv5te/OP_SGET_WIDE_JUMBO.S */
8285    /*
8286     * Jumbo 64-bit SGET handler.
8287     */
8288    /* sget-wide/jumbo vBBBB, field@AAAAAAAA */
8289    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
8290    FETCH(r0, 1)                        @ r0<- aaaa (lo)
8291    FETCH(r1, 2)                        @ r1<- AAAA (hi)
8292    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
8293    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
8294    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
8295    cmp     r0, #0                      @ is resolved entry null?
8296    beq     .LOP_SGET_WIDE_JUMBO_resolve         @ yes, do resolve
8297.LOP_SGET_WIDE_JUMBO_finish:
8298    FETCH(r9, 3)                        @ r9<- BBBB
8299    ldrd    r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
8300    add     r9, rFP, r9, lsl #2         @ r9<- &fp[BBBB]
8301    FETCH_ADVANCE_INST(4)               @ advance rPC, load rINST
8302    stmia   r9, {r0-r1}                 @ vBBBB/vBBBB+1<- r0/r1
8303    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8304    GOTO_OPCODE(ip)                     @ jump to next instruction
8305
8306/* ------------------------------ */
8307    .balign 64
8308.L_OP_SGET_OBJECT_JUMBO: /* 0x116 */
8309/* File: armv5te/OP_SGET_OBJECT_JUMBO.S */
8310/* File: armv5te/OP_SGET_JUMBO.S */
8311    /*
8312     * Jumbo 32-bit SGET handler.
8313     *
8314     * for: sget/jumbo, sget-object/jumbo, sget-boolean/jumbo, sget-byte/jumbo,
8315     *      sget-char/jumbo, sget-short/jumbo
8316     */
8317    /* exop vBBBB, field@AAAAAAAA */
8318    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
8319    FETCH(r0, 1)                        @ r0<- aaaa (lo)
8320    FETCH(r1, 2)                        @ r1<- AAAA (hi)
8321    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
8322    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
8323    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
8324    cmp     r0, #0                      @ is resolved entry null?
8325    beq     .LOP_SGET_OBJECT_JUMBO_resolve         @ yes, do resolve
8326.LOP_SGET_OBJECT_JUMBO_finish: @ field ptr in r0
8327    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
8328    @ no-op                             @ acquiring load
8329    FETCH(r2, 3)                        @ r2<- BBBB
8330    FETCH_ADVANCE_INST(4)               @ advance rPC, load rINST
8331    SET_VREG(r1, r2)                    @ fp[BBBB]<- r1
8332    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8333    GOTO_OPCODE(ip)                     @ jump to next instruction
8334
8335
8336/* ------------------------------ */
8337    .balign 64
8338.L_OP_SGET_BOOLEAN_JUMBO: /* 0x117 */
8339/* File: armv5te/OP_SGET_BOOLEAN_JUMBO.S */
8340/* File: armv5te/OP_SGET_JUMBO.S */
8341    /*
8342     * Jumbo 32-bit SGET handler.
8343     *
8344     * for: sget/jumbo, sget-object/jumbo, sget-boolean/jumbo, sget-byte/jumbo,
8345     *      sget-char/jumbo, sget-short/jumbo
8346     */
8347    /* exop vBBBB, field@AAAAAAAA */
8348    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
8349    FETCH(r0, 1)                        @ r0<- aaaa (lo)
8350    FETCH(r1, 2)                        @ r1<- AAAA (hi)
8351    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
8352    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
8353    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
8354    cmp     r0, #0                      @ is resolved entry null?
8355    beq     .LOP_SGET_BOOLEAN_JUMBO_resolve         @ yes, do resolve
8356.LOP_SGET_BOOLEAN_JUMBO_finish: @ field ptr in r0
8357    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
8358    @ no-op                             @ acquiring load
8359    FETCH(r2, 3)                        @ r2<- BBBB
8360    FETCH_ADVANCE_INST(4)               @ advance rPC, load rINST
8361    SET_VREG(r1, r2)                    @ fp[BBBB]<- r1
8362    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8363    GOTO_OPCODE(ip)                     @ jump to next instruction
8364
8365
8366/* ------------------------------ */
8367    .balign 64
8368.L_OP_SGET_BYTE_JUMBO: /* 0x118 */
8369/* File: armv5te/OP_SGET_BYTE_JUMBO.S */
8370/* File: armv5te/OP_SGET_JUMBO.S */
8371    /*
8372     * Jumbo 32-bit SGET handler.
8373     *
8374     * for: sget/jumbo, sget-object/jumbo, sget-boolean/jumbo, sget-byte/jumbo,
8375     *      sget-char/jumbo, sget-short/jumbo
8376     */
8377    /* exop vBBBB, field@AAAAAAAA */
8378    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
8379    FETCH(r0, 1)                        @ r0<- aaaa (lo)
8380    FETCH(r1, 2)                        @ r1<- AAAA (hi)
8381    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
8382    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
8383    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
8384    cmp     r0, #0                      @ is resolved entry null?
8385    beq     .LOP_SGET_BYTE_JUMBO_resolve         @ yes, do resolve
8386.LOP_SGET_BYTE_JUMBO_finish: @ field ptr in r0
8387    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
8388    @ no-op                             @ acquiring load
8389    FETCH(r2, 3)                        @ r2<- BBBB
8390    FETCH_ADVANCE_INST(4)               @ advance rPC, load rINST
8391    SET_VREG(r1, r2)                    @ fp[BBBB]<- r1
8392    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8393    GOTO_OPCODE(ip)                     @ jump to next instruction
8394
8395
8396/* ------------------------------ */
8397    .balign 64
8398.L_OP_SGET_CHAR_JUMBO: /* 0x119 */
8399/* File: armv5te/OP_SGET_CHAR_JUMBO.S */
8400/* File: armv5te/OP_SGET_JUMBO.S */
8401    /*
8402     * Jumbo 32-bit SGET handler.
8403     *
8404     * for: sget/jumbo, sget-object/jumbo, sget-boolean/jumbo, sget-byte/jumbo,
8405     *      sget-char/jumbo, sget-short/jumbo
8406     */
8407    /* exop vBBBB, field@AAAAAAAA */
8408    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
8409    FETCH(r0, 1)                        @ r0<- aaaa (lo)
8410    FETCH(r1, 2)                        @ r1<- AAAA (hi)
8411    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
8412    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
8413    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
8414    cmp     r0, #0                      @ is resolved entry null?
8415    beq     .LOP_SGET_CHAR_JUMBO_resolve         @ yes, do resolve
8416.LOP_SGET_CHAR_JUMBO_finish: @ field ptr in r0
8417    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
8418    @ no-op                             @ acquiring load
8419    FETCH(r2, 3)                        @ r2<- BBBB
8420    FETCH_ADVANCE_INST(4)               @ advance rPC, load rINST
8421    SET_VREG(r1, r2)                    @ fp[BBBB]<- r1
8422    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8423    GOTO_OPCODE(ip)                     @ jump to next instruction
8424
8425
8426/* ------------------------------ */
8427    .balign 64
8428.L_OP_SGET_SHORT_JUMBO: /* 0x11a */
8429/* File: armv5te/OP_SGET_SHORT_JUMBO.S */
8430/* File: armv5te/OP_SGET_JUMBO.S */
8431    /*
8432     * Jumbo 32-bit SGET handler.
8433     *
8434     * for: sget/jumbo, sget-object/jumbo, sget-boolean/jumbo, sget-byte/jumbo,
8435     *      sget-char/jumbo, sget-short/jumbo
8436     */
8437    /* exop vBBBB, field@AAAAAAAA */
8438    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
8439    FETCH(r0, 1)                        @ r0<- aaaa (lo)
8440    FETCH(r1, 2)                        @ r1<- AAAA (hi)
8441    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
8442    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
8443    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
8444    cmp     r0, #0                      @ is resolved entry null?
8445    beq     .LOP_SGET_SHORT_JUMBO_resolve         @ yes, do resolve
8446.LOP_SGET_SHORT_JUMBO_finish: @ field ptr in r0
8447    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
8448    @ no-op                             @ acquiring load
8449    FETCH(r2, 3)                        @ r2<- BBBB
8450    FETCH_ADVANCE_INST(4)               @ advance rPC, load rINST
8451    SET_VREG(r1, r2)                    @ fp[BBBB]<- r1
8452    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8453    GOTO_OPCODE(ip)                     @ jump to next instruction
8454
8455
8456/* ------------------------------ */
8457    .balign 64
8458.L_OP_SPUT_JUMBO: /* 0x11b */
8459/* File: armv5te/OP_SPUT_JUMBO.S */
8460    /*
8461     * Jumbo 32-bit SPUT handler.
8462     *
8463     * for: sput/jumbo, sput-boolean/jumbo, sput-byte/jumbo, sput-char/jumbo,
8464     *      sput-short/jumbo
8465     */
8466    /* exop vBBBB, field@AAAAAAAA */
8467    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
8468    FETCH(r0, 1)                        @ r0<- aaaa (lo)
8469    FETCH(r1, 2)                        @ r1<- AAAA (hi)
8470    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
8471    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
8472    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
8473    cmp     r0, #0                      @ is resolved entry null?
8474    beq     .LOP_SPUT_JUMBO_resolve         @ yes, do resolve
8475.LOP_SPUT_JUMBO_finish:   @ field ptr in r0
8476    FETCH(r2, 3)                        @ r2<- BBBB
8477    FETCH_ADVANCE_INST(4)               @ advance rPC, load rINST
8478    GET_VREG(r1, r2)                    @ r1<- fp[BBBB]
8479    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8480    @ no-op                             @ releasing store
8481    str     r1, [r0, #offStaticField_value] @ field<- vBBBB
8482    GOTO_OPCODE(ip)                     @ jump to next instruction
8483
8484/* ------------------------------ */
8485    .balign 64
8486.L_OP_SPUT_WIDE_JUMBO: /* 0x11c */
8487/* File: armv5te/OP_SPUT_WIDE_JUMBO.S */
8488    /*
8489     * Jumbo 64-bit SPUT handler.
8490     */
8491    /* sput-wide/jumbo vBBBB, field@AAAAAAAA */
8492    ldr     r0, [rGLUE, #offGlue_methodClassDex]  @ r0<- DvmDex
8493    FETCH(r1, 1)                        @ r1<- aaaa (lo)
8494    FETCH(r2, 2)                        @ r2<- AAAA (hi)
8495    ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
8496    orr     r1, r1, r2, lsl #16         @ r1<- AAAAaaaa
8497    FETCH(r9, 3)                        @ r9<- BBBB
8498    ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
8499    add     r9, rFP, r9, lsl #2         @ r9<- &fp[BBBB]
8500    cmp     r2, #0                      @ is resolved entry null?
8501    beq     .LOP_SPUT_WIDE_JUMBO_resolve         @ yes, do resolve
8502.LOP_SPUT_WIDE_JUMBO_finish: @ field ptr in r2, BBBB in r9
8503    FETCH_ADVANCE_INST(4)               @ advance rPC, load rINST
8504    ldmia   r9, {r0-r1}                 @ r0/r1<- vBBBB/vBBBB+1
8505    GET_INST_OPCODE(r10)                @ extract opcode from rINST
8506    strd    r0, [r2, #offStaticField_value] @ field<- vBBBB/vBBBB+1
8507    GOTO_OPCODE(r10)                    @ jump to next instruction
8508
8509/* ------------------------------ */
8510    .balign 64
8511.L_OP_SPUT_OBJECT_JUMBO: /* 0x11d */
8512/* File: armv5te/OP_SPUT_OBJECT_JUMBO.S */
8513    /*
8514     * Jumbo 32-bit SPUT handler for objects
8515     */
8516    /* sput-object/jumbo vBBBB, field@AAAAAAAA */
8517    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
8518    FETCH(r0, 1)                        @ r0<- aaaa (lo)
8519    FETCH(r1, 2)                        @ r1<- AAAA (hi)
8520    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
8521    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
8522    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
8523    cmp     r0, #0                      @ is resolved entry null?
8524    bne     .LOP_SPUT_OBJECT_JUMBO_finish          @ no, continue
8525    ldr     r9, [rGLUE, #offGlue_method]    @ r9<- current method
8526    EXPORT_PC()                         @ resolve() could throw, so export now
8527    ldr     r0, [r9, #offMethod_clazz]  @ r0<- method->clazz
8528    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8529    cmp     r0, #0                      @ success?
8530    bne     .LOP_SPUT_OBJECT_JUMBO_finish          @ yes, finish
8531    b       common_exceptionThrown      @ no, handle exception
8532
8533/* ------------------------------ */
8534    .balign 64
8535.L_OP_SPUT_BOOLEAN_JUMBO: /* 0x11e */
8536/* File: armv5te/OP_SPUT_BOOLEAN_JUMBO.S */
8537/* File: armv5te/OP_SPUT_JUMBO.S */
8538    /*
8539     * Jumbo 32-bit SPUT handler.
8540     *
8541     * for: sput/jumbo, sput-boolean/jumbo, sput-byte/jumbo, sput-char/jumbo,
8542     *      sput-short/jumbo
8543     */
8544    /* exop vBBBB, field@AAAAAAAA */
8545    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
8546    FETCH(r0, 1)                        @ r0<- aaaa (lo)
8547    FETCH(r1, 2)                        @ r1<- AAAA (hi)
8548    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
8549    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
8550    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
8551    cmp     r0, #0                      @ is resolved entry null?
8552    beq     .LOP_SPUT_BOOLEAN_JUMBO_resolve         @ yes, do resolve
8553.LOP_SPUT_BOOLEAN_JUMBO_finish:   @ field ptr in r0
8554    FETCH(r2, 3)                        @ r2<- BBBB
8555    FETCH_ADVANCE_INST(4)               @ advance rPC, load rINST
8556    GET_VREG(r1, r2)                    @ r1<- fp[BBBB]
8557    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8558    @ no-op                             @ releasing store
8559    str     r1, [r0, #offStaticField_value] @ field<- vBBBB
8560    GOTO_OPCODE(ip)                     @ jump to next instruction
8561
8562
8563/* ------------------------------ */
8564    .balign 64
8565.L_OP_SPUT_BYTE_JUMBO: /* 0x11f */
8566/* File: armv5te/OP_SPUT_BYTE_JUMBO.S */
8567/* File: armv5te/OP_SPUT_JUMBO.S */
8568    /*
8569     * Jumbo 32-bit SPUT handler.
8570     *
8571     * for: sput/jumbo, sput-boolean/jumbo, sput-byte/jumbo, sput-char/jumbo,
8572     *      sput-short/jumbo
8573     */
8574    /* exop vBBBB, field@AAAAAAAA */
8575    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
8576    FETCH(r0, 1)                        @ r0<- aaaa (lo)
8577    FETCH(r1, 2)                        @ r1<- AAAA (hi)
8578    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
8579    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
8580    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
8581    cmp     r0, #0                      @ is resolved entry null?
8582    beq     .LOP_SPUT_BYTE_JUMBO_resolve         @ yes, do resolve
8583.LOP_SPUT_BYTE_JUMBO_finish:   @ field ptr in r0
8584    FETCH(r2, 3)                        @ r2<- BBBB
8585    FETCH_ADVANCE_INST(4)               @ advance rPC, load rINST
8586    GET_VREG(r1, r2)                    @ r1<- fp[BBBB]
8587    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8588    @ no-op                             @ releasing store
8589    str     r1, [r0, #offStaticField_value] @ field<- vBBBB
8590    GOTO_OPCODE(ip)                     @ jump to next instruction
8591
8592
8593/* ------------------------------ */
8594    .balign 64
8595.L_OP_SPUT_CHAR_JUMBO: /* 0x120 */
8596/* File: armv5te/OP_SPUT_CHAR_JUMBO.S */
8597/* File: armv5te/OP_SPUT_JUMBO.S */
8598    /*
8599     * Jumbo 32-bit SPUT handler.
8600     *
8601     * for: sput/jumbo, sput-boolean/jumbo, sput-byte/jumbo, sput-char/jumbo,
8602     *      sput-short/jumbo
8603     */
8604    /* exop vBBBB, field@AAAAAAAA */
8605    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
8606    FETCH(r0, 1)                        @ r0<- aaaa (lo)
8607    FETCH(r1, 2)                        @ r1<- AAAA (hi)
8608    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
8609    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
8610    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
8611    cmp     r0, #0                      @ is resolved entry null?
8612    beq     .LOP_SPUT_CHAR_JUMBO_resolve         @ yes, do resolve
8613.LOP_SPUT_CHAR_JUMBO_finish:   @ field ptr in r0
8614    FETCH(r2, 3)                        @ r2<- BBBB
8615    FETCH_ADVANCE_INST(4)               @ advance rPC, load rINST
8616    GET_VREG(r1, r2)                    @ r1<- fp[BBBB]
8617    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8618    @ no-op                             @ releasing store
8619    str     r1, [r0, #offStaticField_value] @ field<- vBBBB
8620    GOTO_OPCODE(ip)                     @ jump to next instruction
8621
8622
8623/* ------------------------------ */
8624    .balign 64
8625.L_OP_SPUT_SHORT_JUMBO: /* 0x121 */
8626/* File: armv5te/OP_SPUT_SHORT_JUMBO.S */
8627/* File: armv5te/OP_SPUT_JUMBO.S */
8628    /*
8629     * Jumbo 32-bit SPUT handler.
8630     *
8631     * for: sput/jumbo, sput-boolean/jumbo, sput-byte/jumbo, sput-char/jumbo,
8632     *      sput-short/jumbo
8633     */
8634    /* exop vBBBB, field@AAAAAAAA */
8635    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
8636    FETCH(r0, 1)                        @ r0<- aaaa (lo)
8637    FETCH(r1, 2)                        @ r1<- AAAA (hi)
8638    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
8639    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
8640    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
8641    cmp     r0, #0                      @ is resolved entry null?
8642    beq     .LOP_SPUT_SHORT_JUMBO_resolve         @ yes, do resolve
8643.LOP_SPUT_SHORT_JUMBO_finish:   @ field ptr in r0
8644    FETCH(r2, 3)                        @ r2<- BBBB
8645    FETCH_ADVANCE_INST(4)               @ advance rPC, load rINST
8646    GET_VREG(r1, r2)                    @ r1<- fp[BBBB]
8647    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8648    @ no-op                             @ releasing store
8649    str     r1, [r0, #offStaticField_value] @ field<- vBBBB
8650    GOTO_OPCODE(ip)                     @ jump to next instruction
8651
8652
8653/* ------------------------------ */
8654    .balign 64
8655.L_OP_INVOKE_VIRTUAL_JUMBO: /* 0x122 */
8656/* File: armv5te/OP_INVOKE_VIRTUAL_JUMBO.S */
8657    /*
8658     * Handle a virtual method call.
8659     */
8660    /* invoke-virtual/jumbo {vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA */
8661    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
8662    FETCH(r0, 1)                        @ r1<- aaaa (lo)
8663    FETCH(r1, 2)                        @ r1<- AAAA (hi)
8664    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
8665    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
8666    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
8667    cmp     r0, #0                      @ already resolved?
8668    EXPORT_PC()                         @ must export for invoke
8669    bne     .LOP_INVOKE_VIRTUAL_JUMBO_continue        @ yes, continue on
8670    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8671    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8672    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8673    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8674    cmp     r0, #0                      @ got null?
8675    bne     .LOP_INVOKE_VIRTUAL_JUMBO_continue        @ no, continue
8676    b       common_exceptionThrown      @ yes, handle exception
8677
8678/* ------------------------------ */
8679    .balign 64
8680.L_OP_INVOKE_SUPER_JUMBO: /* 0x123 */
8681/* File: armv5te/OP_INVOKE_SUPER_JUMBO.S */
8682    /*
8683     * Handle a "super" method call.
8684     */
8685    /* invoke-super/jumbo {vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA */
8686    FETCH(r10, 4)                       @ r10<- CCCC
8687    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
8688    FETCH(r0, 1)                        @ r1<- aaaa (lo)
8689    FETCH(r1, 2)                        @ r1<- AAAA (hi)
8690    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
8691    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
8692    GET_VREG(r2, r10)                   @ r2<- "this" ptr
8693    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
8694    cmp     r2, #0                      @ null "this"?
8695    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
8696    beq     common_errNullObject        @ null "this", throw exception
8697    cmp     r0, #0                      @ already resolved?
8698    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
8699    EXPORT_PC()                         @ must export for invoke
8700    bne     .LOP_INVOKE_SUPER_JUMBO_continue        @ resolved, continue on
8701    b       .LOP_INVOKE_SUPER_JUMBO_resolve         @ do resolve now
8702
8703/* ------------------------------ */
8704    .balign 64
8705.L_OP_INVOKE_DIRECT_JUMBO: /* 0x124 */
8706/* File: armv5te/OP_INVOKE_DIRECT_JUMBO.S */
8707    /*
8708     * Handle a direct method call.
8709     *
8710     * (We could defer the "is 'this' pointer null" test to the common
8711     * method invocation code, and use a flag to indicate that static
8712     * calls don't count.  If we do this as part of copying the arguments
8713     * out we could avoiding loading the first arg twice.)
8714     *
8715     */
8716    /* invoke-direct/jumbo {vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA */
8717    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
8718    FETCH(r0, 1)                        @ r1<- aaaa (lo)
8719    FETCH(r1, 2)                        @ r1<- AAAA (hi)
8720    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
8721    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
8722    FETCH(r10, 4)                       @ r10<- CCCC
8723    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
8724    cmp     r0, #0                      @ already resolved?
8725    EXPORT_PC()                         @ must export for invoke
8726    GET_VREG(r2, r10)                   @ r2<- "this" ptr
8727    beq     .LOP_INVOKE_DIRECT_JUMBO_resolve         @ not resolved, do it now
8728.LOP_INVOKE_DIRECT_JUMBO_finish:
8729    cmp     r2, #0                      @ null "this" ref?
8730    bne     common_invokeMethodJumbo    @ no, continue on
8731    b       common_errNullObject        @ yes, throw exception
8732
8733/* ------------------------------ */
8734    .balign 64
8735.L_OP_INVOKE_STATIC_JUMBO: /* 0x125 */
8736/* File: armv5te/OP_INVOKE_STATIC_JUMBO.S */
8737    /*
8738     * Handle a static method call.
8739     */
8740    /* invoke-static/jumbo {vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA */
8741    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
8742    FETCH(r0, 1)                        @ r1<- aaaa (lo)
8743    FETCH(r1, 2)                        @ r1<- AAAA (hi)
8744    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
8745    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
8746    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
8747    cmp     r0, #0                      @ already resolved?
8748    EXPORT_PC()                         @ must export for invoke
8749    bne     common_invokeMethodJumbo    @ yes, continue on
87500:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8751    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8752    mov     r2, #METHOD_STATIC          @ resolver method type
8753    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8754    cmp     r0, #0                      @ got null?
8755    bne     common_invokeMethodJumbo    @ no, continue
8756    b       common_exceptionThrown      @ yes, handle exception
8757
8758/* ------------------------------ */
8759    .balign 64
8760.L_OP_INVOKE_INTERFACE_JUMBO: /* 0x126 */
8761/* File: armv5te/OP_INVOKE_INTERFACE_JUMBO.S */
8762    /*
8763     * Handle an interface method call.
8764     */
8765    /* invoke-interface/jumbo {vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA */
8766    FETCH(r2, 4)                        @ r2<- CCCC
8767    FETCH(r0, 1)                        @ r0<- aaaa (lo)
8768    FETCH(r1, 2)                        @ r1<- AAAA (hi)
8769    EXPORT_PC()                         @ must export for invoke
8770    orr     r1, r0, r1, lsl #16         @ r1<- AAAAaaaa
8771    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
8772    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
8773    cmp     r0, #0                      @ null obj?
8774    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
8775    beq     common_errNullObject        @ yes, fail
8776    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
8777    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
8778    cmp     r0, #0                      @ failed?
8779    beq     common_exceptionThrown      @ yes, handle exception
8780    b       common_invokeMethodJumbo    @ jump to common handler
8781
8782/* ------------------------------ */
8783    .balign 64
8784.L_OP_UNUSED_27FF: /* 0x127 */
8785/* File: armv5te/OP_UNUSED_27FF.S */
8786/* File: armv5te/unused.S */
8787    bl      common_abort
8788
8789
8790/* ------------------------------ */
8791    .balign 64
8792.L_OP_UNUSED_28FF: /* 0x128 */
8793/* File: armv5te/OP_UNUSED_28FF.S */
8794/* File: armv5te/unused.S */
8795    bl      common_abort
8796
8797
8798/* ------------------------------ */
8799    .balign 64
8800.L_OP_UNUSED_29FF: /* 0x129 */
8801/* File: armv5te/OP_UNUSED_29FF.S */
8802/* File: armv5te/unused.S */
8803    bl      common_abort
8804
8805
8806/* ------------------------------ */
8807    .balign 64
8808.L_OP_UNUSED_2AFF: /* 0x12a */
8809/* File: armv5te/OP_UNUSED_2AFF.S */
8810/* File: armv5te/unused.S */
8811    bl      common_abort
8812
8813
8814/* ------------------------------ */
8815    .balign 64
8816.L_OP_UNUSED_2BFF: /* 0x12b */
8817/* File: armv5te/OP_UNUSED_2BFF.S */
8818/* File: armv5te/unused.S */
8819    bl      common_abort
8820
8821
8822/* ------------------------------ */
8823    .balign 64
8824.L_OP_UNUSED_2CFF: /* 0x12c */
8825/* File: armv5te/OP_UNUSED_2CFF.S */
8826/* File: armv5te/unused.S */
8827    bl      common_abort
8828
8829
8830/* ------------------------------ */
8831    .balign 64
8832.L_OP_UNUSED_2DFF: /* 0x12d */
8833/* File: armv5te/OP_UNUSED_2DFF.S */
8834/* File: armv5te/unused.S */
8835    bl      common_abort
8836
8837
8838/* ------------------------------ */
8839    .balign 64
8840.L_OP_UNUSED_2EFF: /* 0x12e */
8841/* File: armv5te/OP_UNUSED_2EFF.S */
8842/* File: armv5te/unused.S */
8843    bl      common_abort
8844
8845
8846/* ------------------------------ */
8847    .balign 64
8848.L_OP_UNUSED_2FFF: /* 0x12f */
8849/* File: armv5te/OP_UNUSED_2FFF.S */
8850/* File: armv5te/unused.S */
8851    bl      common_abort
8852
8853
8854/* ------------------------------ */
8855    .balign 64
8856.L_OP_UNUSED_30FF: /* 0x130 */
8857/* File: armv5te/OP_UNUSED_30FF.S */
8858/* File: armv5te/unused.S */
8859    bl      common_abort
8860
8861
8862/* ------------------------------ */
8863    .balign 64
8864.L_OP_UNUSED_31FF: /* 0x131 */
8865/* File: armv5te/OP_UNUSED_31FF.S */
8866/* File: armv5te/unused.S */
8867    bl      common_abort
8868
8869
8870/* ------------------------------ */
8871    .balign 64
8872.L_OP_UNUSED_32FF: /* 0x132 */
8873/* File: armv5te/OP_UNUSED_32FF.S */
8874/* File: armv5te/unused.S */
8875    bl      common_abort
8876
8877
8878/* ------------------------------ */
8879    .balign 64
8880.L_OP_UNUSED_33FF: /* 0x133 */
8881/* File: armv5te/OP_UNUSED_33FF.S */
8882/* File: armv5te/unused.S */
8883    bl      common_abort
8884
8885
8886/* ------------------------------ */
8887    .balign 64
8888.L_OP_UNUSED_34FF: /* 0x134 */
8889/* File: armv5te/OP_UNUSED_34FF.S */
8890/* File: armv5te/unused.S */
8891    bl      common_abort
8892
8893
8894/* ------------------------------ */
8895    .balign 64
8896.L_OP_UNUSED_35FF: /* 0x135 */
8897/* File: armv5te/OP_UNUSED_35FF.S */
8898/* File: armv5te/unused.S */
8899    bl      common_abort
8900
8901
8902/* ------------------------------ */
8903    .balign 64
8904.L_OP_UNUSED_36FF: /* 0x136 */
8905/* File: armv5te/OP_UNUSED_36FF.S */
8906/* File: armv5te/unused.S */
8907    bl      common_abort
8908
8909
8910/* ------------------------------ */
8911    .balign 64
8912.L_OP_UNUSED_37FF: /* 0x137 */
8913/* File: armv5te/OP_UNUSED_37FF.S */
8914/* File: armv5te/unused.S */
8915    bl      common_abort
8916
8917
8918/* ------------------------------ */
8919    .balign 64
8920.L_OP_UNUSED_38FF: /* 0x138 */
8921/* File: armv5te/OP_UNUSED_38FF.S */
8922/* File: armv5te/unused.S */
8923    bl      common_abort
8924
8925
8926/* ------------------------------ */
8927    .balign 64
8928.L_OP_UNUSED_39FF: /* 0x139 */
8929/* File: armv5te/OP_UNUSED_39FF.S */
8930/* File: armv5te/unused.S */
8931    bl      common_abort
8932
8933
8934/* ------------------------------ */
8935    .balign 64
8936.L_OP_UNUSED_3AFF: /* 0x13a */
8937/* File: armv5te/OP_UNUSED_3AFF.S */
8938/* File: armv5te/unused.S */
8939    bl      common_abort
8940
8941
8942/* ------------------------------ */
8943    .balign 64
8944.L_OP_UNUSED_3BFF: /* 0x13b */
8945/* File: armv5te/OP_UNUSED_3BFF.S */
8946/* File: armv5te/unused.S */
8947    bl      common_abort
8948
8949
8950/* ------------------------------ */
8951    .balign 64
8952.L_OP_UNUSED_3CFF: /* 0x13c */
8953/* File: armv5te/OP_UNUSED_3CFF.S */
8954/* File: armv5te/unused.S */
8955    bl      common_abort
8956
8957
8958/* ------------------------------ */
8959    .balign 64
8960.L_OP_UNUSED_3DFF: /* 0x13d */
8961/* File: armv5te/OP_UNUSED_3DFF.S */
8962/* File: armv5te/unused.S */
8963    bl      common_abort
8964
8965
8966/* ------------------------------ */
8967    .balign 64
8968.L_OP_UNUSED_3EFF: /* 0x13e */
8969/* File: armv5te/OP_UNUSED_3EFF.S */
8970/* File: armv5te/unused.S */
8971    bl      common_abort
8972
8973
8974/* ------------------------------ */
8975    .balign 64
8976.L_OP_UNUSED_3FFF: /* 0x13f */
8977/* File: armv5te/OP_UNUSED_3FFF.S */
8978/* File: armv5te/unused.S */
8979    bl      common_abort
8980
8981
8982/* ------------------------------ */
8983    .balign 64
8984.L_OP_UNUSED_40FF: /* 0x140 */
8985/* File: armv5te/OP_UNUSED_40FF.S */
8986/* File: armv5te/unused.S */
8987    bl      common_abort
8988
8989
8990/* ------------------------------ */
8991    .balign 64
8992.L_OP_UNUSED_41FF: /* 0x141 */
8993/* File: armv5te/OP_UNUSED_41FF.S */
8994/* File: armv5te/unused.S */
8995    bl      common_abort
8996
8997
8998/* ------------------------------ */
8999    .balign 64
9000.L_OP_UNUSED_42FF: /* 0x142 */
9001/* File: armv5te/OP_UNUSED_42FF.S */
9002/* File: armv5te/unused.S */
9003    bl      common_abort
9004
9005
9006/* ------------------------------ */
9007    .balign 64
9008.L_OP_UNUSED_43FF: /* 0x143 */
9009/* File: armv5te/OP_UNUSED_43FF.S */
9010/* File: armv5te/unused.S */
9011    bl      common_abort
9012
9013
9014/* ------------------------------ */
9015    .balign 64
9016.L_OP_UNUSED_44FF: /* 0x144 */
9017/* File: armv5te/OP_UNUSED_44FF.S */
9018/* File: armv5te/unused.S */
9019    bl      common_abort
9020
9021
9022/* ------------------------------ */
9023    .balign 64
9024.L_OP_UNUSED_45FF: /* 0x145 */
9025/* File: armv5te/OP_UNUSED_45FF.S */
9026/* File: armv5te/unused.S */
9027    bl      common_abort
9028
9029
9030/* ------------------------------ */
9031    .balign 64
9032.L_OP_UNUSED_46FF: /* 0x146 */
9033/* File: armv5te/OP_UNUSED_46FF.S */
9034/* File: armv5te/unused.S */
9035    bl      common_abort
9036
9037
9038/* ------------------------------ */
9039    .balign 64
9040.L_OP_UNUSED_47FF: /* 0x147 */
9041/* File: armv5te/OP_UNUSED_47FF.S */
9042/* File: armv5te/unused.S */
9043    bl      common_abort
9044
9045
9046/* ------------------------------ */
9047    .balign 64
9048.L_OP_UNUSED_48FF: /* 0x148 */
9049/* File: armv5te/OP_UNUSED_48FF.S */
9050/* File: armv5te/unused.S */
9051    bl      common_abort
9052
9053
9054/* ------------------------------ */
9055    .balign 64
9056.L_OP_UNUSED_49FF: /* 0x149 */
9057/* File: armv5te/OP_UNUSED_49FF.S */
9058/* File: armv5te/unused.S */
9059    bl      common_abort
9060
9061
9062/* ------------------------------ */
9063    .balign 64
9064.L_OP_UNUSED_4AFF: /* 0x14a */
9065/* File: armv5te/OP_UNUSED_4AFF.S */
9066/* File: armv5te/unused.S */
9067    bl      common_abort
9068
9069
9070/* ------------------------------ */
9071    .balign 64
9072.L_OP_UNUSED_4BFF: /* 0x14b */
9073/* File: armv5te/OP_UNUSED_4BFF.S */
9074/* File: armv5te/unused.S */
9075    bl      common_abort
9076
9077
9078/* ------------------------------ */
9079    .balign 64
9080.L_OP_UNUSED_4CFF: /* 0x14c */
9081/* File: armv5te/OP_UNUSED_4CFF.S */
9082/* File: armv5te/unused.S */
9083    bl      common_abort
9084
9085
9086/* ------------------------------ */
9087    .balign 64
9088.L_OP_UNUSED_4DFF: /* 0x14d */
9089/* File: armv5te/OP_UNUSED_4DFF.S */
9090/* File: armv5te/unused.S */
9091    bl      common_abort
9092
9093
9094/* ------------------------------ */
9095    .balign 64
9096.L_OP_UNUSED_4EFF: /* 0x14e */
9097/* File: armv5te/OP_UNUSED_4EFF.S */
9098/* File: armv5te/unused.S */
9099    bl      common_abort
9100
9101
9102/* ------------------------------ */
9103    .balign 64
9104.L_OP_UNUSED_4FFF: /* 0x14f */
9105/* File: armv5te/OP_UNUSED_4FFF.S */
9106/* File: armv5te/unused.S */
9107    bl      common_abort
9108
9109
9110/* ------------------------------ */
9111    .balign 64
9112.L_OP_UNUSED_50FF: /* 0x150 */
9113/* File: armv5te/OP_UNUSED_50FF.S */
9114/* File: armv5te/unused.S */
9115    bl      common_abort
9116
9117
9118/* ------------------------------ */
9119    .balign 64
9120.L_OP_UNUSED_51FF: /* 0x151 */
9121/* File: armv5te/OP_UNUSED_51FF.S */
9122/* File: armv5te/unused.S */
9123    bl      common_abort
9124
9125
9126/* ------------------------------ */
9127    .balign 64
9128.L_OP_UNUSED_52FF: /* 0x152 */
9129/* File: armv5te/OP_UNUSED_52FF.S */
9130/* File: armv5te/unused.S */
9131    bl      common_abort
9132
9133
9134/* ------------------------------ */
9135    .balign 64
9136.L_OP_UNUSED_53FF: /* 0x153 */
9137/* File: armv5te/OP_UNUSED_53FF.S */
9138/* File: armv5te/unused.S */
9139    bl      common_abort
9140
9141
9142/* ------------------------------ */
9143    .balign 64
9144.L_OP_UNUSED_54FF: /* 0x154 */
9145/* File: armv5te/OP_UNUSED_54FF.S */
9146/* File: armv5te/unused.S */
9147    bl      common_abort
9148
9149
9150/* ------------------------------ */
9151    .balign 64
9152.L_OP_UNUSED_55FF: /* 0x155 */
9153/* File: armv5te/OP_UNUSED_55FF.S */
9154/* File: armv5te/unused.S */
9155    bl      common_abort
9156
9157
9158/* ------------------------------ */
9159    .balign 64
9160.L_OP_UNUSED_56FF: /* 0x156 */
9161/* File: armv5te/OP_UNUSED_56FF.S */
9162/* File: armv5te/unused.S */
9163    bl      common_abort
9164
9165
9166/* ------------------------------ */
9167    .balign 64
9168.L_OP_UNUSED_57FF: /* 0x157 */
9169/* File: armv5te/OP_UNUSED_57FF.S */
9170/* File: armv5te/unused.S */
9171    bl      common_abort
9172
9173
9174/* ------------------------------ */
9175    .balign 64
9176.L_OP_UNUSED_58FF: /* 0x158 */
9177/* File: armv5te/OP_UNUSED_58FF.S */
9178/* File: armv5te/unused.S */
9179    bl      common_abort
9180
9181
9182/* ------------------------------ */
9183    .balign 64
9184.L_OP_UNUSED_59FF: /* 0x159 */
9185/* File: armv5te/OP_UNUSED_59FF.S */
9186/* File: armv5te/unused.S */
9187    bl      common_abort
9188
9189
9190/* ------------------------------ */
9191    .balign 64
9192.L_OP_UNUSED_5AFF: /* 0x15a */
9193/* File: armv5te/OP_UNUSED_5AFF.S */
9194/* File: armv5te/unused.S */
9195    bl      common_abort
9196
9197
9198/* ------------------------------ */
9199    .balign 64
9200.L_OP_UNUSED_5BFF: /* 0x15b */
9201/* File: armv5te/OP_UNUSED_5BFF.S */
9202/* File: armv5te/unused.S */
9203    bl      common_abort
9204
9205
9206/* ------------------------------ */
9207    .balign 64
9208.L_OP_UNUSED_5CFF: /* 0x15c */
9209/* File: armv5te/OP_UNUSED_5CFF.S */
9210/* File: armv5te/unused.S */
9211    bl      common_abort
9212
9213
9214/* ------------------------------ */
9215    .balign 64
9216.L_OP_UNUSED_5DFF: /* 0x15d */
9217/* File: armv5te/OP_UNUSED_5DFF.S */
9218/* File: armv5te/unused.S */
9219    bl      common_abort
9220
9221
9222/* ------------------------------ */
9223    .balign 64
9224.L_OP_UNUSED_5EFF: /* 0x15e */
9225/* File: armv5te/OP_UNUSED_5EFF.S */
9226/* File: armv5te/unused.S */
9227    bl      common_abort
9228
9229
9230/* ------------------------------ */
9231    .balign 64
9232.L_OP_UNUSED_5FFF: /* 0x15f */
9233/* File: armv5te/OP_UNUSED_5FFF.S */
9234/* File: armv5te/unused.S */
9235    bl      common_abort
9236
9237
9238/* ------------------------------ */
9239    .balign 64
9240.L_OP_UNUSED_60FF: /* 0x160 */
9241/* File: armv5te/OP_UNUSED_60FF.S */
9242/* File: armv5te/unused.S */
9243    bl      common_abort
9244
9245
9246/* ------------------------------ */
9247    .balign 64
9248.L_OP_UNUSED_61FF: /* 0x161 */
9249/* File: armv5te/OP_UNUSED_61FF.S */
9250/* File: armv5te/unused.S */
9251    bl      common_abort
9252
9253
9254/* ------------------------------ */
9255    .balign 64
9256.L_OP_UNUSED_62FF: /* 0x162 */
9257/* File: armv5te/OP_UNUSED_62FF.S */
9258/* File: armv5te/unused.S */
9259    bl      common_abort
9260
9261
9262/* ------------------------------ */
9263    .balign 64
9264.L_OP_UNUSED_63FF: /* 0x163 */
9265/* File: armv5te/OP_UNUSED_63FF.S */
9266/* File: armv5te/unused.S */
9267    bl      common_abort
9268
9269
9270/* ------------------------------ */
9271    .balign 64
9272.L_OP_UNUSED_64FF: /* 0x164 */
9273/* File: armv5te/OP_UNUSED_64FF.S */
9274/* File: armv5te/unused.S */
9275    bl      common_abort
9276
9277
9278/* ------------------------------ */
9279    .balign 64
9280.L_OP_UNUSED_65FF: /* 0x165 */
9281/* File: armv5te/OP_UNUSED_65FF.S */
9282/* File: armv5te/unused.S */
9283    bl      common_abort
9284
9285
9286/* ------------------------------ */
9287    .balign 64
9288.L_OP_UNUSED_66FF: /* 0x166 */
9289/* File: armv5te/OP_UNUSED_66FF.S */
9290/* File: armv5te/unused.S */
9291    bl      common_abort
9292
9293
9294/* ------------------------------ */
9295    .balign 64
9296.L_OP_UNUSED_67FF: /* 0x167 */
9297/* File: armv5te/OP_UNUSED_67FF.S */
9298/* File: armv5te/unused.S */
9299    bl      common_abort
9300
9301
9302/* ------------------------------ */
9303    .balign 64
9304.L_OP_UNUSED_68FF: /* 0x168 */
9305/* File: armv5te/OP_UNUSED_68FF.S */
9306/* File: armv5te/unused.S */
9307    bl      common_abort
9308
9309
9310/* ------------------------------ */
9311    .balign 64
9312.L_OP_UNUSED_69FF: /* 0x169 */
9313/* File: armv5te/OP_UNUSED_69FF.S */
9314/* File: armv5te/unused.S */
9315    bl      common_abort
9316
9317
9318/* ------------------------------ */
9319    .balign 64
9320.L_OP_UNUSED_6AFF: /* 0x16a */
9321/* File: armv5te/OP_UNUSED_6AFF.S */
9322/* File: armv5te/unused.S */
9323    bl      common_abort
9324
9325
9326/* ------------------------------ */
9327    .balign 64
9328.L_OP_UNUSED_6BFF: /* 0x16b */
9329/* File: armv5te/OP_UNUSED_6BFF.S */
9330/* File: armv5te/unused.S */
9331    bl      common_abort
9332
9333
9334/* ------------------------------ */
9335    .balign 64
9336.L_OP_UNUSED_6CFF: /* 0x16c */
9337/* File: armv5te/OP_UNUSED_6CFF.S */
9338/* File: armv5te/unused.S */
9339    bl      common_abort
9340
9341
9342/* ------------------------------ */
9343    .balign 64
9344.L_OP_UNUSED_6DFF: /* 0x16d */
9345/* File: armv5te/OP_UNUSED_6DFF.S */
9346/* File: armv5te/unused.S */
9347    bl      common_abort
9348
9349
9350/* ------------------------------ */
9351    .balign 64
9352.L_OP_UNUSED_6EFF: /* 0x16e */
9353/* File: armv5te/OP_UNUSED_6EFF.S */
9354/* File: armv5te/unused.S */
9355    bl      common_abort
9356
9357
9358/* ------------------------------ */
9359    .balign 64
9360.L_OP_UNUSED_6FFF: /* 0x16f */
9361/* File: armv5te/OP_UNUSED_6FFF.S */
9362/* File: armv5te/unused.S */
9363    bl      common_abort
9364
9365
9366/* ------------------------------ */
9367    .balign 64
9368.L_OP_UNUSED_70FF: /* 0x170 */
9369/* File: armv5te/OP_UNUSED_70FF.S */
9370/* File: armv5te/unused.S */
9371    bl      common_abort
9372
9373
9374/* ------------------------------ */
9375    .balign 64
9376.L_OP_UNUSED_71FF: /* 0x171 */
9377/* File: armv5te/OP_UNUSED_71FF.S */
9378/* File: armv5te/unused.S */
9379    bl      common_abort
9380
9381
9382/* ------------------------------ */
9383    .balign 64
9384.L_OP_UNUSED_72FF: /* 0x172 */
9385/* File: armv5te/OP_UNUSED_72FF.S */
9386/* File: armv5te/unused.S */
9387    bl      common_abort
9388
9389
9390/* ------------------------------ */
9391    .balign 64
9392.L_OP_UNUSED_73FF: /* 0x173 */
9393/* File: armv5te/OP_UNUSED_73FF.S */
9394/* File: armv5te/unused.S */
9395    bl      common_abort
9396
9397
9398/* ------------------------------ */
9399    .balign 64
9400.L_OP_UNUSED_74FF: /* 0x174 */
9401/* File: armv5te/OP_UNUSED_74FF.S */
9402/* File: armv5te/unused.S */
9403    bl      common_abort
9404
9405
9406/* ------------------------------ */
9407    .balign 64
9408.L_OP_UNUSED_75FF: /* 0x175 */
9409/* File: armv5te/OP_UNUSED_75FF.S */
9410/* File: armv5te/unused.S */
9411    bl      common_abort
9412
9413
9414/* ------------------------------ */
9415    .balign 64
9416.L_OP_UNUSED_76FF: /* 0x176 */
9417/* File: armv5te/OP_UNUSED_76FF.S */
9418/* File: armv5te/unused.S */
9419    bl      common_abort
9420
9421
9422/* ------------------------------ */
9423    .balign 64
9424.L_OP_UNUSED_77FF: /* 0x177 */
9425/* File: armv5te/OP_UNUSED_77FF.S */
9426/* File: armv5te/unused.S */
9427    bl      common_abort
9428
9429
9430/* ------------------------------ */
9431    .balign 64
9432.L_OP_UNUSED_78FF: /* 0x178 */
9433/* File: armv5te/OP_UNUSED_78FF.S */
9434/* File: armv5te/unused.S */
9435    bl      common_abort
9436
9437
9438/* ------------------------------ */
9439    .balign 64
9440.L_OP_UNUSED_79FF: /* 0x179 */
9441/* File: armv5te/OP_UNUSED_79FF.S */
9442/* File: armv5te/unused.S */
9443    bl      common_abort
9444
9445
9446/* ------------------------------ */
9447    .balign 64
9448.L_OP_UNUSED_7AFF: /* 0x17a */
9449/* File: armv5te/OP_UNUSED_7AFF.S */
9450/* File: armv5te/unused.S */
9451    bl      common_abort
9452
9453
9454/* ------------------------------ */
9455    .balign 64
9456.L_OP_UNUSED_7BFF: /* 0x17b */
9457/* File: armv5te/OP_UNUSED_7BFF.S */
9458/* File: armv5te/unused.S */
9459    bl      common_abort
9460
9461
9462/* ------------------------------ */
9463    .balign 64
9464.L_OP_UNUSED_7CFF: /* 0x17c */
9465/* File: armv5te/OP_UNUSED_7CFF.S */
9466/* File: armv5te/unused.S */
9467    bl      common_abort
9468
9469
9470/* ------------------------------ */
9471    .balign 64
9472.L_OP_UNUSED_7DFF: /* 0x17d */
9473/* File: armv5te/OP_UNUSED_7DFF.S */
9474/* File: armv5te/unused.S */
9475    bl      common_abort
9476
9477
9478/* ------------------------------ */
9479    .balign 64
9480.L_OP_UNUSED_7EFF: /* 0x17e */
9481/* File: armv5te/OP_UNUSED_7EFF.S */
9482/* File: armv5te/unused.S */
9483    bl      common_abort
9484
9485
9486/* ------------------------------ */
9487    .balign 64
9488.L_OP_UNUSED_7FFF: /* 0x17f */
9489/* File: armv5te/OP_UNUSED_7FFF.S */
9490/* File: armv5te/unused.S */
9491    bl      common_abort
9492
9493
9494/* ------------------------------ */
9495    .balign 64
9496.L_OP_UNUSED_80FF: /* 0x180 */
9497/* File: armv5te/OP_UNUSED_80FF.S */
9498/* File: armv5te/unused.S */
9499    bl      common_abort
9500
9501
9502/* ------------------------------ */
9503    .balign 64
9504.L_OP_UNUSED_81FF: /* 0x181 */
9505/* File: armv5te/OP_UNUSED_81FF.S */
9506/* File: armv5te/unused.S */
9507    bl      common_abort
9508
9509
9510/* ------------------------------ */
9511    .balign 64
9512.L_OP_UNUSED_82FF: /* 0x182 */
9513/* File: armv5te/OP_UNUSED_82FF.S */
9514/* File: armv5te/unused.S */
9515    bl      common_abort
9516
9517
9518/* ------------------------------ */
9519    .balign 64
9520.L_OP_UNUSED_83FF: /* 0x183 */
9521/* File: armv5te/OP_UNUSED_83FF.S */
9522/* File: armv5te/unused.S */
9523    bl      common_abort
9524
9525
9526/* ------------------------------ */
9527    .balign 64
9528.L_OP_UNUSED_84FF: /* 0x184 */
9529/* File: armv5te/OP_UNUSED_84FF.S */
9530/* File: armv5te/unused.S */
9531    bl      common_abort
9532
9533
9534/* ------------------------------ */
9535    .balign 64
9536.L_OP_UNUSED_85FF: /* 0x185 */
9537/* File: armv5te/OP_UNUSED_85FF.S */
9538/* File: armv5te/unused.S */
9539    bl      common_abort
9540
9541
9542/* ------------------------------ */
9543    .balign 64
9544.L_OP_UNUSED_86FF: /* 0x186 */
9545/* File: armv5te/OP_UNUSED_86FF.S */
9546/* File: armv5te/unused.S */
9547    bl      common_abort
9548
9549
9550/* ------------------------------ */
9551    .balign 64
9552.L_OP_UNUSED_87FF: /* 0x187 */
9553/* File: armv5te/OP_UNUSED_87FF.S */
9554/* File: armv5te/unused.S */
9555    bl      common_abort
9556
9557
9558/* ------------------------------ */
9559    .balign 64
9560.L_OP_UNUSED_88FF: /* 0x188 */
9561/* File: armv5te/OP_UNUSED_88FF.S */
9562/* File: armv5te/unused.S */
9563    bl      common_abort
9564
9565
9566/* ------------------------------ */
9567    .balign 64
9568.L_OP_UNUSED_89FF: /* 0x189 */
9569/* File: armv5te/OP_UNUSED_89FF.S */
9570/* File: armv5te/unused.S */
9571    bl      common_abort
9572
9573
9574/* ------------------------------ */
9575    .balign 64
9576.L_OP_UNUSED_8AFF: /* 0x18a */
9577/* File: armv5te/OP_UNUSED_8AFF.S */
9578/* File: armv5te/unused.S */
9579    bl      common_abort
9580
9581
9582/* ------------------------------ */
9583    .balign 64
9584.L_OP_UNUSED_8BFF: /* 0x18b */
9585/* File: armv5te/OP_UNUSED_8BFF.S */
9586/* File: armv5te/unused.S */
9587    bl      common_abort
9588
9589
9590/* ------------------------------ */
9591    .balign 64
9592.L_OP_UNUSED_8CFF: /* 0x18c */
9593/* File: armv5te/OP_UNUSED_8CFF.S */
9594/* File: armv5te/unused.S */
9595    bl      common_abort
9596
9597
9598/* ------------------------------ */
9599    .balign 64
9600.L_OP_UNUSED_8DFF: /* 0x18d */
9601/* File: armv5te/OP_UNUSED_8DFF.S */
9602/* File: armv5te/unused.S */
9603    bl      common_abort
9604
9605
9606/* ------------------------------ */
9607    .balign 64
9608.L_OP_UNUSED_8EFF: /* 0x18e */
9609/* File: armv5te/OP_UNUSED_8EFF.S */
9610/* File: armv5te/unused.S */
9611    bl      common_abort
9612
9613
9614/* ------------------------------ */
9615    .balign 64
9616.L_OP_UNUSED_8FFF: /* 0x18f */
9617/* File: armv5te/OP_UNUSED_8FFF.S */
9618/* File: armv5te/unused.S */
9619    bl      common_abort
9620
9621
9622/* ------------------------------ */
9623    .balign 64
9624.L_OP_UNUSED_90FF: /* 0x190 */
9625/* File: armv5te/OP_UNUSED_90FF.S */
9626/* File: armv5te/unused.S */
9627    bl      common_abort
9628
9629
9630/* ------------------------------ */
9631    .balign 64
9632.L_OP_UNUSED_91FF: /* 0x191 */
9633/* File: armv5te/OP_UNUSED_91FF.S */
9634/* File: armv5te/unused.S */
9635    bl      common_abort
9636
9637
9638/* ------------------------------ */
9639    .balign 64
9640.L_OP_UNUSED_92FF: /* 0x192 */
9641/* File: armv5te/OP_UNUSED_92FF.S */
9642/* File: armv5te/unused.S */
9643    bl      common_abort
9644
9645
9646/* ------------------------------ */
9647    .balign 64
9648.L_OP_UNUSED_93FF: /* 0x193 */
9649/* File: armv5te/OP_UNUSED_93FF.S */
9650/* File: armv5te/unused.S */
9651    bl      common_abort
9652
9653
9654/* ------------------------------ */
9655    .balign 64
9656.L_OP_UNUSED_94FF: /* 0x194 */
9657/* File: armv5te/OP_UNUSED_94FF.S */
9658/* File: armv5te/unused.S */
9659    bl      common_abort
9660
9661
9662/* ------------------------------ */
9663    .balign 64
9664.L_OP_UNUSED_95FF: /* 0x195 */
9665/* File: armv5te/OP_UNUSED_95FF.S */
9666/* File: armv5te/unused.S */
9667    bl      common_abort
9668
9669
9670/* ------------------------------ */
9671    .balign 64
9672.L_OP_UNUSED_96FF: /* 0x196 */
9673/* File: armv5te/OP_UNUSED_96FF.S */
9674/* File: armv5te/unused.S */
9675    bl      common_abort
9676
9677
9678/* ------------------------------ */
9679    .balign 64
9680.L_OP_UNUSED_97FF: /* 0x197 */
9681/* File: armv5te/OP_UNUSED_97FF.S */
9682/* File: armv5te/unused.S */
9683    bl      common_abort
9684
9685
9686/* ------------------------------ */
9687    .balign 64
9688.L_OP_UNUSED_98FF: /* 0x198 */
9689/* File: armv5te/OP_UNUSED_98FF.S */
9690/* File: armv5te/unused.S */
9691    bl      common_abort
9692
9693
9694/* ------------------------------ */
9695    .balign 64
9696.L_OP_UNUSED_99FF: /* 0x199 */
9697/* File: armv5te/OP_UNUSED_99FF.S */
9698/* File: armv5te/unused.S */
9699    bl      common_abort
9700
9701
9702/* ------------------------------ */
9703    .balign 64
9704.L_OP_UNUSED_9AFF: /* 0x19a */
9705/* File: armv5te/OP_UNUSED_9AFF.S */
9706/* File: armv5te/unused.S */
9707    bl      common_abort
9708
9709
9710/* ------------------------------ */
9711    .balign 64
9712.L_OP_UNUSED_9BFF: /* 0x19b */
9713/* File: armv5te/OP_UNUSED_9BFF.S */
9714/* File: armv5te/unused.S */
9715    bl      common_abort
9716
9717
9718/* ------------------------------ */
9719    .balign 64
9720.L_OP_UNUSED_9CFF: /* 0x19c */
9721/* File: armv5te/OP_UNUSED_9CFF.S */
9722/* File: armv5te/unused.S */
9723    bl      common_abort
9724
9725
9726/* ------------------------------ */
9727    .balign 64
9728.L_OP_UNUSED_9DFF: /* 0x19d */
9729/* File: armv5te/OP_UNUSED_9DFF.S */
9730/* File: armv5te/unused.S */
9731    bl      common_abort
9732
9733
9734/* ------------------------------ */
9735    .balign 64
9736.L_OP_UNUSED_9EFF: /* 0x19e */
9737/* File: armv5te/OP_UNUSED_9EFF.S */
9738/* File: armv5te/unused.S */
9739    bl      common_abort
9740
9741
9742/* ------------------------------ */
9743    .balign 64
9744.L_OP_UNUSED_9FFF: /* 0x19f */
9745/* File: armv5te/OP_UNUSED_9FFF.S */
9746/* File: armv5te/unused.S */
9747    bl      common_abort
9748
9749
9750/* ------------------------------ */
9751    .balign 64
9752.L_OP_UNUSED_A0FF: /* 0x1a0 */
9753/* File: armv5te/OP_UNUSED_A0FF.S */
9754/* File: armv5te/unused.S */
9755    bl      common_abort
9756
9757
9758/* ------------------------------ */
9759    .balign 64
9760.L_OP_UNUSED_A1FF: /* 0x1a1 */
9761/* File: armv5te/OP_UNUSED_A1FF.S */
9762/* File: armv5te/unused.S */
9763    bl      common_abort
9764
9765
9766/* ------------------------------ */
9767    .balign 64
9768.L_OP_UNUSED_A2FF: /* 0x1a2 */
9769/* File: armv5te/OP_UNUSED_A2FF.S */
9770/* File: armv5te/unused.S */
9771    bl      common_abort
9772
9773
9774/* ------------------------------ */
9775    .balign 64
9776.L_OP_UNUSED_A3FF: /* 0x1a3 */
9777/* File: armv5te/OP_UNUSED_A3FF.S */
9778/* File: armv5te/unused.S */
9779    bl      common_abort
9780
9781
9782/* ------------------------------ */
9783    .balign 64
9784.L_OP_UNUSED_A4FF: /* 0x1a4 */
9785/* File: armv5te/OP_UNUSED_A4FF.S */
9786/* File: armv5te/unused.S */
9787    bl      common_abort
9788
9789
9790/* ------------------------------ */
9791    .balign 64
9792.L_OP_UNUSED_A5FF: /* 0x1a5 */
9793/* File: armv5te/OP_UNUSED_A5FF.S */
9794/* File: armv5te/unused.S */
9795    bl      common_abort
9796
9797
9798/* ------------------------------ */
9799    .balign 64
9800.L_OP_UNUSED_A6FF: /* 0x1a6 */
9801/* File: armv5te/OP_UNUSED_A6FF.S */
9802/* File: armv5te/unused.S */
9803    bl      common_abort
9804
9805
9806/* ------------------------------ */
9807    .balign 64
9808.L_OP_UNUSED_A7FF: /* 0x1a7 */
9809/* File: armv5te/OP_UNUSED_A7FF.S */
9810/* File: armv5te/unused.S */
9811    bl      common_abort
9812
9813
9814/* ------------------------------ */
9815    .balign 64
9816.L_OP_UNUSED_A8FF: /* 0x1a8 */
9817/* File: armv5te/OP_UNUSED_A8FF.S */
9818/* File: armv5te/unused.S */
9819    bl      common_abort
9820
9821
9822/* ------------------------------ */
9823    .balign 64
9824.L_OP_UNUSED_A9FF: /* 0x1a9 */
9825/* File: armv5te/OP_UNUSED_A9FF.S */
9826/* File: armv5te/unused.S */
9827    bl      common_abort
9828
9829
9830/* ------------------------------ */
9831    .balign 64
9832.L_OP_UNUSED_AAFF: /* 0x1aa */
9833/* File: armv5te/OP_UNUSED_AAFF.S */
9834/* File: armv5te/unused.S */
9835    bl      common_abort
9836
9837
9838/* ------------------------------ */
9839    .balign 64
9840.L_OP_UNUSED_ABFF: /* 0x1ab */
9841/* File: armv5te/OP_UNUSED_ABFF.S */
9842/* File: armv5te/unused.S */
9843    bl      common_abort
9844
9845
9846/* ------------------------------ */
9847    .balign 64
9848.L_OP_UNUSED_ACFF: /* 0x1ac */
9849/* File: armv5te/OP_UNUSED_ACFF.S */
9850/* File: armv5te/unused.S */
9851    bl      common_abort
9852
9853
9854/* ------------------------------ */
9855    .balign 64
9856.L_OP_UNUSED_ADFF: /* 0x1ad */
9857/* File: armv5te/OP_UNUSED_ADFF.S */
9858/* File: armv5te/unused.S */
9859    bl      common_abort
9860
9861
9862/* ------------------------------ */
9863    .balign 64
9864.L_OP_UNUSED_AEFF: /* 0x1ae */
9865/* File: armv5te/OP_UNUSED_AEFF.S */
9866/* File: armv5te/unused.S */
9867    bl      common_abort
9868
9869
9870/* ------------------------------ */
9871    .balign 64
9872.L_OP_UNUSED_AFFF: /* 0x1af */
9873/* File: armv5te/OP_UNUSED_AFFF.S */
9874/* File: armv5te/unused.S */
9875    bl      common_abort
9876
9877
9878/* ------------------------------ */
9879    .balign 64
9880.L_OP_UNUSED_B0FF: /* 0x1b0 */
9881/* File: armv5te/OP_UNUSED_B0FF.S */
9882/* File: armv5te/unused.S */
9883    bl      common_abort
9884
9885
9886/* ------------------------------ */
9887    .balign 64
9888.L_OP_UNUSED_B1FF: /* 0x1b1 */
9889/* File: armv5te/OP_UNUSED_B1FF.S */
9890/* File: armv5te/unused.S */
9891    bl      common_abort
9892
9893
9894/* ------------------------------ */
9895    .balign 64
9896.L_OP_UNUSED_B2FF: /* 0x1b2 */
9897/* File: armv5te/OP_UNUSED_B2FF.S */
9898/* File: armv5te/unused.S */
9899    bl      common_abort
9900
9901
9902/* ------------------------------ */
9903    .balign 64
9904.L_OP_UNUSED_B3FF: /* 0x1b3 */
9905/* File: armv5te/OP_UNUSED_B3FF.S */
9906/* File: armv5te/unused.S */
9907    bl      common_abort
9908
9909
9910/* ------------------------------ */
9911    .balign 64
9912.L_OP_UNUSED_B4FF: /* 0x1b4 */
9913/* File: armv5te/OP_UNUSED_B4FF.S */
9914/* File: armv5te/unused.S */
9915    bl      common_abort
9916
9917
9918/* ------------------------------ */
9919    .balign 64
9920.L_OP_UNUSED_B5FF: /* 0x1b5 */
9921/* File: armv5te/OP_UNUSED_B5FF.S */
9922/* File: armv5te/unused.S */
9923    bl      common_abort
9924
9925
9926/* ------------------------------ */
9927    .balign 64
9928.L_OP_UNUSED_B6FF: /* 0x1b6 */
9929/* File: armv5te/OP_UNUSED_B6FF.S */
9930/* File: armv5te/unused.S */
9931    bl      common_abort
9932
9933
9934/* ------------------------------ */
9935    .balign 64
9936.L_OP_UNUSED_B7FF: /* 0x1b7 */
9937/* File: armv5te/OP_UNUSED_B7FF.S */
9938/* File: armv5te/unused.S */
9939    bl      common_abort
9940
9941
9942/* ------------------------------ */
9943    .balign 64
9944.L_OP_UNUSED_B8FF: /* 0x1b8 */
9945/* File: armv5te/OP_UNUSED_B8FF.S */
9946/* File: armv5te/unused.S */
9947    bl      common_abort
9948
9949
9950/* ------------------------------ */
9951    .balign 64
9952.L_OP_UNUSED_B9FF: /* 0x1b9 */
9953/* File: armv5te/OP_UNUSED_B9FF.S */
9954/* File: armv5te/unused.S */
9955    bl      common_abort
9956
9957
9958/* ------------------------------ */
9959    .balign 64
9960.L_OP_UNUSED_BAFF: /* 0x1ba */
9961/* File: armv5te/OP_UNUSED_BAFF.S */
9962/* File: armv5te/unused.S */
9963    bl      common_abort
9964
9965
9966/* ------------------------------ */
9967    .balign 64
9968.L_OP_UNUSED_BBFF: /* 0x1bb */
9969/* File: armv5te/OP_UNUSED_BBFF.S */
9970/* File: armv5te/unused.S */
9971    bl      common_abort
9972
9973
9974/* ------------------------------ */
9975    .balign 64
9976.L_OP_UNUSED_BCFF: /* 0x1bc */
9977/* File: armv5te/OP_UNUSED_BCFF.S */
9978/* File: armv5te/unused.S */
9979    bl      common_abort
9980
9981
9982/* ------------------------------ */
9983    .balign 64
9984.L_OP_UNUSED_BDFF: /* 0x1bd */
9985/* File: armv5te/OP_UNUSED_BDFF.S */
9986/* File: armv5te/unused.S */
9987    bl      common_abort
9988
9989
9990/* ------------------------------ */
9991    .balign 64
9992.L_OP_UNUSED_BEFF: /* 0x1be */
9993/* File: armv5te/OP_UNUSED_BEFF.S */
9994/* File: armv5te/unused.S */
9995    bl      common_abort
9996
9997
9998/* ------------------------------ */
9999    .balign 64
10000.L_OP_UNUSED_BFFF: /* 0x1bf */
10001/* File: armv5te/OP_UNUSED_BFFF.S */
10002/* File: armv5te/unused.S */
10003    bl      common_abort
10004
10005
10006/* ------------------------------ */
10007    .balign 64
10008.L_OP_UNUSED_C0FF: /* 0x1c0 */
10009/* File: armv5te/OP_UNUSED_C0FF.S */
10010/* File: armv5te/unused.S */
10011    bl      common_abort
10012
10013
10014/* ------------------------------ */
10015    .balign 64
10016.L_OP_UNUSED_C1FF: /* 0x1c1 */
10017/* File: armv5te/OP_UNUSED_C1FF.S */
10018/* File: armv5te/unused.S */
10019    bl      common_abort
10020
10021
10022/* ------------------------------ */
10023    .balign 64
10024.L_OP_UNUSED_C2FF: /* 0x1c2 */
10025/* File: armv5te/OP_UNUSED_C2FF.S */
10026/* File: armv5te/unused.S */
10027    bl      common_abort
10028
10029
10030/* ------------------------------ */
10031    .balign 64
10032.L_OP_UNUSED_C3FF: /* 0x1c3 */
10033/* File: armv5te/OP_UNUSED_C3FF.S */
10034/* File: armv5te/unused.S */
10035    bl      common_abort
10036
10037
10038/* ------------------------------ */
10039    .balign 64
10040.L_OP_UNUSED_C4FF: /* 0x1c4 */
10041/* File: armv5te/OP_UNUSED_C4FF.S */
10042/* File: armv5te/unused.S */
10043    bl      common_abort
10044
10045
10046/* ------------------------------ */
10047    .balign 64
10048.L_OP_UNUSED_C5FF: /* 0x1c5 */
10049/* File: armv5te/OP_UNUSED_C5FF.S */
10050/* File: armv5te/unused.S */
10051    bl      common_abort
10052
10053
10054/* ------------------------------ */
10055    .balign 64
10056.L_OP_UNUSED_C6FF: /* 0x1c6 */
10057/* File: armv5te/OP_UNUSED_C6FF.S */
10058/* File: armv5te/unused.S */
10059    bl      common_abort
10060
10061
10062/* ------------------------------ */
10063    .balign 64
10064.L_OP_UNUSED_C7FF: /* 0x1c7 */
10065/* File: armv5te/OP_UNUSED_C7FF.S */
10066/* File: armv5te/unused.S */
10067    bl      common_abort
10068
10069
10070/* ------------------------------ */
10071    .balign 64
10072.L_OP_UNUSED_C8FF: /* 0x1c8 */
10073/* File: armv5te/OP_UNUSED_C8FF.S */
10074/* File: armv5te/unused.S */
10075    bl      common_abort
10076
10077
10078/* ------------------------------ */
10079    .balign 64
10080.L_OP_UNUSED_C9FF: /* 0x1c9 */
10081/* File: armv5te/OP_UNUSED_C9FF.S */
10082/* File: armv5te/unused.S */
10083    bl      common_abort
10084
10085
10086/* ------------------------------ */
10087    .balign 64
10088.L_OP_UNUSED_CAFF: /* 0x1ca */
10089/* File: armv5te/OP_UNUSED_CAFF.S */
10090/* File: armv5te/unused.S */
10091    bl      common_abort
10092
10093
10094/* ------------------------------ */
10095    .balign 64
10096.L_OP_UNUSED_CBFF: /* 0x1cb */
10097/* File: armv5te/OP_UNUSED_CBFF.S */
10098/* File: armv5te/unused.S */
10099    bl      common_abort
10100
10101
10102/* ------------------------------ */
10103    .balign 64
10104.L_OP_UNUSED_CCFF: /* 0x1cc */
10105/* File: armv5te/OP_UNUSED_CCFF.S */
10106/* File: armv5te/unused.S */
10107    bl      common_abort
10108
10109
10110/* ------------------------------ */
10111    .balign 64
10112.L_OP_UNUSED_CDFF: /* 0x1cd */
10113/* File: armv5te/OP_UNUSED_CDFF.S */
10114/* File: armv5te/unused.S */
10115    bl      common_abort
10116
10117
10118/* ------------------------------ */
10119    .balign 64
10120.L_OP_UNUSED_CEFF: /* 0x1ce */
10121/* File: armv5te/OP_UNUSED_CEFF.S */
10122/* File: armv5te/unused.S */
10123    bl      common_abort
10124
10125
10126/* ------------------------------ */
10127    .balign 64
10128.L_OP_UNUSED_CFFF: /* 0x1cf */
10129/* File: armv5te/OP_UNUSED_CFFF.S */
10130/* File: armv5te/unused.S */
10131    bl      common_abort
10132
10133
10134/* ------------------------------ */
10135    .balign 64
10136.L_OP_UNUSED_D0FF: /* 0x1d0 */
10137/* File: armv5te/OP_UNUSED_D0FF.S */
10138/* File: armv5te/unused.S */
10139    bl      common_abort
10140
10141
10142/* ------------------------------ */
10143    .balign 64
10144.L_OP_UNUSED_D1FF: /* 0x1d1 */
10145/* File: armv5te/OP_UNUSED_D1FF.S */
10146/* File: armv5te/unused.S */
10147    bl      common_abort
10148
10149
10150/* ------------------------------ */
10151    .balign 64
10152.L_OP_UNUSED_D2FF: /* 0x1d2 */
10153/* File: armv5te/OP_UNUSED_D2FF.S */
10154/* File: armv5te/unused.S */
10155    bl      common_abort
10156
10157
10158/* ------------------------------ */
10159    .balign 64
10160.L_OP_UNUSED_D3FF: /* 0x1d3 */
10161/* File: armv5te/OP_UNUSED_D3FF.S */
10162/* File: armv5te/unused.S */
10163    bl      common_abort
10164
10165
10166/* ------------------------------ */
10167    .balign 64
10168.L_OP_UNUSED_D4FF: /* 0x1d4 */
10169/* File: armv5te/OP_UNUSED_D4FF.S */
10170/* File: armv5te/unused.S */
10171    bl      common_abort
10172
10173
10174/* ------------------------------ */
10175    .balign 64
10176.L_OP_UNUSED_D5FF: /* 0x1d5 */
10177/* File: armv5te/OP_UNUSED_D5FF.S */
10178/* File: armv5te/unused.S */
10179    bl      common_abort
10180
10181
10182/* ------------------------------ */
10183    .balign 64
10184.L_OP_UNUSED_D6FF: /* 0x1d6 */
10185/* File: armv5te/OP_UNUSED_D6FF.S */
10186/* File: armv5te/unused.S */
10187    bl      common_abort
10188
10189
10190/* ------------------------------ */
10191    .balign 64
10192.L_OP_UNUSED_D7FF: /* 0x1d7 */
10193/* File: armv5te/OP_UNUSED_D7FF.S */
10194/* File: armv5te/unused.S */
10195    bl      common_abort
10196
10197
10198/* ------------------------------ */
10199    .balign 64
10200.L_OP_UNUSED_D8FF: /* 0x1d8 */
10201/* File: armv5te/OP_UNUSED_D8FF.S */
10202/* File: armv5te/unused.S */
10203    bl      common_abort
10204
10205
10206/* ------------------------------ */
10207    .balign 64
10208.L_OP_UNUSED_D9FF: /* 0x1d9 */
10209/* File: armv5te/OP_UNUSED_D9FF.S */
10210/* File: armv5te/unused.S */
10211    bl      common_abort
10212
10213
10214/* ------------------------------ */
10215    .balign 64
10216.L_OP_UNUSED_DAFF: /* 0x1da */
10217/* File: armv5te/OP_UNUSED_DAFF.S */
10218/* File: armv5te/unused.S */
10219    bl      common_abort
10220
10221
10222/* ------------------------------ */
10223    .balign 64
10224.L_OP_UNUSED_DBFF: /* 0x1db */
10225/* File: armv5te/OP_UNUSED_DBFF.S */
10226/* File: armv5te/unused.S */
10227    bl      common_abort
10228
10229
10230/* ------------------------------ */
10231    .balign 64
10232.L_OP_UNUSED_DCFF: /* 0x1dc */
10233/* File: armv5te/OP_UNUSED_DCFF.S */
10234/* File: armv5te/unused.S */
10235    bl      common_abort
10236
10237
10238/* ------------------------------ */
10239    .balign 64
10240.L_OP_UNUSED_DDFF: /* 0x1dd */
10241/* File: armv5te/OP_UNUSED_DDFF.S */
10242/* File: armv5te/unused.S */
10243    bl      common_abort
10244
10245
10246/* ------------------------------ */
10247    .balign 64
10248.L_OP_UNUSED_DEFF: /* 0x1de */
10249/* File: armv5te/OP_UNUSED_DEFF.S */
10250/* File: armv5te/unused.S */
10251    bl      common_abort
10252
10253
10254/* ------------------------------ */
10255    .balign 64
10256.L_OP_UNUSED_DFFF: /* 0x1df */
10257/* File: armv5te/OP_UNUSED_DFFF.S */
10258/* File: armv5te/unused.S */
10259    bl      common_abort
10260
10261
10262/* ------------------------------ */
10263    .balign 64
10264.L_OP_UNUSED_E0FF: /* 0x1e0 */
10265/* File: armv5te/OP_UNUSED_E0FF.S */
10266/* File: armv5te/unused.S */
10267    bl      common_abort
10268
10269
10270/* ------------------------------ */
10271    .balign 64
10272.L_OP_UNUSED_E1FF: /* 0x1e1 */
10273/* File: armv5te/OP_UNUSED_E1FF.S */
10274/* File: armv5te/unused.S */
10275    bl      common_abort
10276
10277
10278/* ------------------------------ */
10279    .balign 64
10280.L_OP_UNUSED_E2FF: /* 0x1e2 */
10281/* File: armv5te/OP_UNUSED_E2FF.S */
10282/* File: armv5te/unused.S */
10283    bl      common_abort
10284
10285
10286/* ------------------------------ */
10287    .balign 64
10288.L_OP_UNUSED_E3FF: /* 0x1e3 */
10289/* File: armv5te/OP_UNUSED_E3FF.S */
10290/* File: armv5te/unused.S */
10291    bl      common_abort
10292
10293
10294/* ------------------------------ */
10295    .balign 64
10296.L_OP_UNUSED_E4FF: /* 0x1e4 */
10297/* File: armv5te/OP_UNUSED_E4FF.S */
10298/* File: armv5te/unused.S */
10299    bl      common_abort
10300
10301
10302/* ------------------------------ */
10303    .balign 64
10304.L_OP_UNUSED_E5FF: /* 0x1e5 */
10305/* File: armv5te/OP_UNUSED_E5FF.S */
10306/* File: armv5te/unused.S */
10307    bl      common_abort
10308
10309
10310/* ------------------------------ */
10311    .balign 64
10312.L_OP_UNUSED_E6FF: /* 0x1e6 */
10313/* File: armv5te/OP_UNUSED_E6FF.S */
10314/* File: armv5te/unused.S */
10315    bl      common_abort
10316
10317
10318/* ------------------------------ */
10319    .balign 64
10320.L_OP_UNUSED_E7FF: /* 0x1e7 */
10321/* File: armv5te/OP_UNUSED_E7FF.S */
10322/* File: armv5te/unused.S */
10323    bl      common_abort
10324
10325
10326/* ------------------------------ */
10327    .balign 64
10328.L_OP_UNUSED_E8FF: /* 0x1e8 */
10329/* File: armv5te/OP_UNUSED_E8FF.S */
10330/* File: armv5te/unused.S */
10331    bl      common_abort
10332
10333
10334/* ------------------------------ */
10335    .balign 64
10336.L_OP_UNUSED_E9FF: /* 0x1e9 */
10337/* File: armv5te/OP_UNUSED_E9FF.S */
10338/* File: armv5te/unused.S */
10339    bl      common_abort
10340
10341
10342/* ------------------------------ */
10343    .balign 64
10344.L_OP_UNUSED_EAFF: /* 0x1ea */
10345/* File: armv5te/OP_UNUSED_EAFF.S */
10346/* File: armv5te/unused.S */
10347    bl      common_abort
10348
10349
10350/* ------------------------------ */
10351    .balign 64
10352.L_OP_UNUSED_EBFF: /* 0x1eb */
10353/* File: armv5te/OP_UNUSED_EBFF.S */
10354/* File: armv5te/unused.S */
10355    bl      common_abort
10356
10357
10358/* ------------------------------ */
10359    .balign 64
10360.L_OP_UNUSED_ECFF: /* 0x1ec */
10361/* File: armv5te/OP_UNUSED_ECFF.S */
10362/* File: armv5te/unused.S */
10363    bl      common_abort
10364
10365
10366/* ------------------------------ */
10367    .balign 64
10368.L_OP_UNUSED_EDFF: /* 0x1ed */
10369/* File: armv5te/OP_UNUSED_EDFF.S */
10370/* File: armv5te/unused.S */
10371    bl      common_abort
10372
10373
10374/* ------------------------------ */
10375    .balign 64
10376.L_OP_UNUSED_EEFF: /* 0x1ee */
10377/* File: armv5te/OP_UNUSED_EEFF.S */
10378/* File: armv5te/unused.S */
10379    bl      common_abort
10380
10381
10382/* ------------------------------ */
10383    .balign 64
10384.L_OP_UNUSED_EFFF: /* 0x1ef */
10385/* File: armv5te/OP_UNUSED_EFFF.S */
10386/* File: armv5te/unused.S */
10387    bl      common_abort
10388
10389
10390/* ------------------------------ */
10391    .balign 64
10392.L_OP_UNUSED_F0FF: /* 0x1f0 */
10393/* File: armv5te/OP_UNUSED_F0FF.S */
10394/* File: armv5te/unused.S */
10395    bl      common_abort
10396
10397
10398/* ------------------------------ */
10399    .balign 64
10400.L_OP_UNUSED_F1FF: /* 0x1f1 */
10401/* File: armv5te/OP_UNUSED_F1FF.S */
10402/* File: armv5te/unused.S */
10403    bl      common_abort
10404
10405
10406/* ------------------------------ */
10407    .balign 64
10408.L_OP_UNUSED_F2FF: /* 0x1f2 */
10409/* File: armv5te/OP_UNUSED_F2FF.S */
10410/* File: armv5te/unused.S */
10411    bl      common_abort
10412
10413
10414/* ------------------------------ */
10415    .balign 64
10416.L_OP_UNUSED_F3FF: /* 0x1f3 */
10417/* File: armv5te/OP_UNUSED_F3FF.S */
10418/* File: armv5te/unused.S */
10419    bl      common_abort
10420
10421
10422/* ------------------------------ */
10423    .balign 64
10424.L_OP_UNUSED_F4FF: /* 0x1f4 */
10425/* File: armv5te/OP_UNUSED_F4FF.S */
10426/* File: armv5te/unused.S */
10427    bl      common_abort
10428
10429
10430/* ------------------------------ */
10431    .balign 64
10432.L_OP_UNUSED_F5FF: /* 0x1f5 */
10433/* File: armv5te/OP_UNUSED_F5FF.S */
10434/* File: armv5te/unused.S */
10435    bl      common_abort
10436
10437
10438/* ------------------------------ */
10439    .balign 64
10440.L_OP_UNUSED_F6FF: /* 0x1f6 */
10441/* File: armv5te/OP_UNUSED_F6FF.S */
10442/* File: armv5te/unused.S */
10443    bl      common_abort
10444
10445
10446/* ------------------------------ */
10447    .balign 64
10448.L_OP_UNUSED_F7FF: /* 0x1f7 */
10449/* File: armv5te/OP_UNUSED_F7FF.S */
10450/* File: armv5te/unused.S */
10451    bl      common_abort
10452
10453
10454/* ------------------------------ */
10455    .balign 64
10456.L_OP_UNUSED_F8FF: /* 0x1f8 */
10457/* File: armv5te/OP_UNUSED_F8FF.S */
10458/* File: armv5te/unused.S */
10459    bl      common_abort
10460
10461
10462/* ------------------------------ */
10463    .balign 64
10464.L_OP_UNUSED_F9FF: /* 0x1f9 */
10465/* File: armv5te/OP_UNUSED_F9FF.S */
10466/* File: armv5te/unused.S */
10467    bl      common_abort
10468
10469
10470/* ------------------------------ */
10471    .balign 64
10472.L_OP_UNUSED_FAFF: /* 0x1fa */
10473/* File: armv5te/OP_UNUSED_FAFF.S */
10474/* File: armv5te/unused.S */
10475    bl      common_abort
10476
10477
10478/* ------------------------------ */
10479    .balign 64
10480.L_OP_UNUSED_FBFF: /* 0x1fb */
10481/* File: armv5te/OP_UNUSED_FBFF.S */
10482/* File: armv5te/unused.S */
10483    bl      common_abort
10484
10485
10486/* ------------------------------ */
10487    .balign 64
10488.L_OP_UNUSED_FCFF: /* 0x1fc */
10489/* File: armv5te/OP_UNUSED_FCFF.S */
10490/* File: armv5te/unused.S */
10491    bl      common_abort
10492
10493
10494/* ------------------------------ */
10495    .balign 64
10496.L_OP_UNUSED_FDFF: /* 0x1fd */
10497/* File: armv5te/OP_UNUSED_FDFF.S */
10498/* File: armv5te/unused.S */
10499    bl      common_abort
10500
10501
10502/* ------------------------------ */
10503    .balign 64
10504.L_OP_UNUSED_FEFF: /* 0x1fe */
10505/* File: armv5te/OP_UNUSED_FEFF.S */
10506/* File: armv5te/unused.S */
10507    bl      common_abort
10508
10509
10510/* ------------------------------ */
10511    .balign 64
10512.L_OP_THROW_VERIFICATION_ERROR_JUMBO: /* 0x1ff */
10513/* File: armv5te/OP_THROW_VERIFICATION_ERROR_JUMBO.S */
10514    /*
10515     * Handle a jumbo throw-verification-error instruction.  This throws an
10516     * exception for an error discovered during verification.  The
10517     * exception is indicated by BBBB, with some detail provided by AAAAAAAA.
10518     */
10519    /* exop BBBB, Class@AAAAAAAA */
10520    FETCH(r1, 1)                        @ r1<- aaaa (lo)
10521    FETCH(r2, 2)                        @ r2<- AAAA (hi)
10522    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
10523    orr     r2, r1, r2, lsl #16         @ r2<- AAAAaaaa
10524    EXPORT_PC()                         @ export the PC
10525    FETCH(r1, 3)                        @ r1<- BBBB
10526    bl      dvmThrowVerificationError   @ always throws
10527    b       common_exceptionThrown      @ handle exception
10528
10529
10530    .balign 64
10531    .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
10532    .global dvmAsmInstructionEnd
10533dvmAsmInstructionEnd:
10534
10535/*
10536 * ===========================================================================
10537 *  Sister implementations
10538 * ===========================================================================
10539 */
10540    .global dvmAsmSisterStart
10541    .type   dvmAsmSisterStart, %function
10542    .text
10543    .balign 4
10544dvmAsmSisterStart:
10545
10546/* continuation for OP_CONST_STRING */
10547
10548    /*
10549     * Continuation if the String has not yet been resolved.
10550     *  r1: BBBB (String ref)
10551     *  r9: target register
10552     */
10553.LOP_CONST_STRING_resolve:
10554    EXPORT_PC()
10555    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
10556    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
10557    bl      dvmResolveString            @ r0<- String reference
10558    cmp     r0, #0                      @ failed?
10559    beq     common_exceptionThrown      @ yup, handle the exception
10560    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
10561    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10562    SET_VREG(r0, r9)                    @ vAA<- r0
10563    GOTO_OPCODE(ip)                     @ jump to next instruction
10564
10565/* continuation for OP_CONST_STRING_JUMBO */
10566
10567    /*
10568     * Continuation if the String has not yet been resolved.
10569     *  r1: BBBBBBBB (String ref)
10570     *  r9: target register
10571     */
10572.LOP_CONST_STRING_JUMBO_resolve:
10573    EXPORT_PC()
10574    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
10575    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
10576    bl      dvmResolveString            @ r0<- String reference
10577    cmp     r0, #0                      @ failed?
10578    beq     common_exceptionThrown      @ yup, handle the exception
10579    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
10580    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10581    SET_VREG(r0, r9)                    @ vAA<- r0
10582    GOTO_OPCODE(ip)                     @ jump to next instruction
10583
10584/* continuation for OP_CONST_CLASS */
10585
10586    /*
10587     * Continuation if the Class has not yet been resolved.
10588     *  r1: BBBB (Class ref)
10589     *  r9: target register
10590     */
10591.LOP_CONST_CLASS_resolve:
10592    EXPORT_PC()
10593    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
10594    mov     r2, #1                      @ r2<- true
10595    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
10596    bl      dvmResolveClass             @ r0<- Class reference
10597    cmp     r0, #0                      @ failed?
10598    beq     common_exceptionThrown      @ yup, handle the exception
10599    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
10600    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10601    SET_VREG(r0, r9)                    @ vAA<- r0
10602    GOTO_OPCODE(ip)                     @ jump to next instruction
10603
10604/* continuation for OP_CHECK_CAST */
10605
10606    /*
10607     * Trivial test failed, need to perform full check.  This is common.
10608     *  r0 holds obj->clazz
10609     *  r1 holds desired class resolved from BBBB
10610     *  r9 holds object
10611     */
10612.LOP_CHECK_CAST_fullcheck:
10613    mov     r10, r1                     @ avoid ClassObject getting clobbered
10614    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
10615    cmp     r0, #0                      @ failed?
10616    bne     .LOP_CHECK_CAST_okay            @ no, success
10617
10618    @ A cast has failed.  We need to throw a ClassCastException.
10619    EXPORT_PC()                         @ about to throw
10620    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz (actual class)
10621    mov     r1, r10                     @ r1<- desired class
10622    bl      dvmThrowClassCastException
10623    b       common_exceptionThrown
10624
10625    /*
10626     * Resolution required.  This is the least-likely path.
10627     *
10628     *  r2 holds BBBB
10629     *  r9 holds object
10630     */
10631.LOP_CHECK_CAST_resolve:
10632    EXPORT_PC()                         @ resolve() could throw
10633    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
10634    mov     r1, r2                      @ r1<- BBBB
10635    mov     r2, #0                      @ r2<- false
10636    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
10637    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
10638    cmp     r0, #0                      @ got null?
10639    beq     common_exceptionThrown      @ yes, handle exception
10640    mov     r1, r0                      @ r1<- class resolved from BBB
10641    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
10642    b       .LOP_CHECK_CAST_resolved        @ pick up where we left off
10643
10644/* continuation for OP_INSTANCE_OF */
10645
10646    /*
10647     * Trivial test failed, need to perform full check.  This is common.
10648     *  r0 holds obj->clazz
10649     *  r1 holds class resolved from BBBB
10650     *  r9 holds A
10651     */
10652.LOP_INSTANCE_OF_fullcheck:
10653    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
10654    @ fall through to OP_INSTANCE_OF_store
10655
10656    /*
10657     * r0 holds boolean result
10658     * r9 holds A
10659     */
10660.LOP_INSTANCE_OF_store:
10661    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
10662    SET_VREG(r0, r9)                    @ vA<- r0
10663    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10664    GOTO_OPCODE(ip)                     @ jump to next instruction
10665
10666    /*
10667     * Trivial test succeeded, save and bail.
10668     *  r9 holds A
10669     */
10670.LOP_INSTANCE_OF_trivial:
10671    mov     r0, #1                      @ indicate success
10672    @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
10673    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
10674    SET_VREG(r0, r9)                    @ vA<- r0
10675    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10676    GOTO_OPCODE(ip)                     @ jump to next instruction
10677
10678    /*
10679     * Resolution required.  This is the least-likely path.
10680     *
10681     *  r3 holds BBBB
10682     *  r9 holds A
10683     */
10684.LOP_INSTANCE_OF_resolve:
10685    EXPORT_PC()                         @ resolve() could throw
10686    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
10687    mov     r1, r3                      @ r1<- BBBB
10688    mov     r2, #1                      @ r2<- true
10689    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
10690    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
10691    cmp     r0, #0                      @ got null?
10692    beq     common_exceptionThrown      @ yes, handle exception
10693    mov     r1, r0                      @ r1<- class resolved from BBB
10694    mov     r3, rINST, lsr #12          @ r3<- B
10695    GET_VREG(r0, r3)                    @ r0<- vB (object)
10696    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
10697    b       .LOP_INSTANCE_OF_resolved        @ pick up where we left off
10698
10699/* continuation for OP_NEW_INSTANCE */
10700
10701    .balign 32                          @ minimize cache lines
10702.LOP_NEW_INSTANCE_finish: @ r0=new object
10703    mov     r3, rINST, lsr #8           @ r3<- AA
10704    cmp     r0, #0                      @ failed?
10705    beq     common_exceptionThrown      @ yes, handle the exception
10706    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
10707    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10708    SET_VREG(r0, r3)                    @ vAA<- r0
10709    GOTO_OPCODE(ip)                     @ jump to next instruction
10710
10711    /*
10712     * Class initialization required.
10713     *
10714     *  r0 holds class object
10715     */
10716.LOP_NEW_INSTANCE_needinit:
10717    mov     r9, r0                      @ save r0
10718    bl      dvmInitClass                @ initialize class
10719    cmp     r0, #0                      @ check boolean result
10720    mov     r0, r9                      @ restore r0
10721    bne     .LOP_NEW_INSTANCE_initialized     @ success, continue
10722    b       common_exceptionThrown      @ failed, deal with init exception
10723
10724    /*
10725     * Resolution required.  This is the least-likely path.
10726     *
10727     *  r1 holds BBBB
10728     */
10729.LOP_NEW_INSTANCE_resolve:
10730    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
10731    mov     r2, #0                      @ r2<- false
10732    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
10733    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
10734    cmp     r0, #0                      @ got null?
10735    bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
10736    b       common_exceptionThrown      @ yes, handle exception
10737
10738.LstrInstantiationErrorPtr:
10739    .word   .LstrInstantiationError
10740
10741/* continuation for OP_NEW_ARRAY */
10742
10743
10744    /*
10745     * Resolve class.  (This is an uncommon case.)
10746     *
10747     *  r1 holds array length
10748     *  r2 holds class ref CCCC
10749     */
10750.LOP_NEW_ARRAY_resolve:
10751    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
10752    mov     r9, r1                      @ r9<- length (save)
10753    mov     r1, r2                      @ r1<- CCCC
10754    mov     r2, #0                      @ r2<- false
10755    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
10756    bl      dvmResolveClass             @ r0<- call(clazz, ref)
10757    cmp     r0, #0                      @ got null?
10758    mov     r1, r9                      @ r1<- length (restore)
10759    beq     common_exceptionThrown      @ yes, handle exception
10760    @ fall through to OP_NEW_ARRAY_finish
10761
10762    /*
10763     * Finish allocation.
10764     *
10765     *  r0 holds class
10766     *  r1 holds array length
10767     */
10768.LOP_NEW_ARRAY_finish:
10769    mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
10770    bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
10771    cmp     r0, #0                      @ failed?
10772    mov     r2, rINST, lsr #8           @ r2<- A+
10773    beq     common_exceptionThrown      @ yes, handle the exception
10774    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
10775    and     r2, r2, #15                 @ r2<- A
10776    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10777    SET_VREG(r0, r2)                    @ vA<- r0
10778    GOTO_OPCODE(ip)                     @ jump to next instruction
10779
10780/* continuation for OP_FILLED_NEW_ARRAY */
10781
10782    /*
10783     * On entry:
10784     *  r0 holds array class
10785     *  r10 holds AA or BA
10786     */
10787.LOP_FILLED_NEW_ARRAY_continue:
10788    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
10789    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
10790    ldrb    rINST, [r3, #1]             @ rINST<- descriptor[1]
10791    .if     0
10792    mov     r1, r10                     @ r1<- AA (length)
10793    .else
10794    mov     r1, r10, lsr #4             @ r1<- B (length)
10795    .endif
10796    cmp     rINST, #'I'                 @ array of ints?
10797    cmpne   rINST, #'L'                 @ array of objects?
10798    cmpne   rINST, #'['                 @ array of arrays?
10799    mov     r9, r1                      @ save length in r9
10800    bne     .LOP_FILLED_NEW_ARRAY_notimpl         @ no, not handled yet
10801    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
10802    cmp     r0, #0                      @ null return?
10803    beq     common_exceptionThrown      @ alloc failed, handle exception
10804
10805    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
10806    str     r0, [rGLUE, #offGlue_retval]      @ retval.l <- new array
10807    str     rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
10808    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
10809    subs    r9, r9, #1                  @ length--, check for neg
10810    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
10811    bmi     2f                          @ was zero, bail
10812
10813    @ copy values from registers into the array
10814    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
10815    .if     0
10816    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
108171:  ldr     r3, [r2], #4                @ r3<- *r2++
10818    subs    r9, r9, #1                  @ count--
10819    str     r3, [r0], #4                @ *contents++ = vX
10820    bpl     1b
10821    @ continue at 2
10822    .else
10823    cmp     r9, #4                      @ length was initially 5?
10824    and     r2, r10, #15                @ r2<- A
10825    bne     1f                          @ <= 4 args, branch
10826    GET_VREG(r3, r2)                    @ r3<- vA
10827    sub     r9, r9, #1                  @ count--
10828    str     r3, [r0, #16]               @ contents[4] = vA
108291:  and     r2, r1, #15                 @ r2<- F/E/D/C
10830    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
10831    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
10832    subs    r9, r9, #1                  @ count--
10833    str     r3, [r0], #4                @ *contents++ = vX
10834    bpl     1b
10835    @ continue at 2
10836    .endif
10837
108382:
10839    ldr     r0, [rGLUE, #offGlue_retval]     @ r0<- object
10840    ldr     r1, [rGLUE, #offGlue_retval+4]   @ r1<- type
10841    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
10842    GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
10843    cmp     r1, #'I'                         @ Is int array?
10844    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head
10845    GOTO_OPCODE(ip)                          @ execute it
10846
10847    /*
10848     * Throw an exception indicating that we have not implemented this
10849     * mode of filled-new-array.
10850     */
10851.LOP_FILLED_NEW_ARRAY_notimpl:
10852    ldr     r0, .L_strInternalError
10853    ldr     r1, .L_strFilledNewArrayNotImpl
10854    bl      dvmThrowException
10855    b       common_exceptionThrown
10856
10857    .if     (!0)                 @ define in one or the other, not both
10858.L_strFilledNewArrayNotImpl:
10859    .word   .LstrFilledNewArrayNotImpl
10860.L_strInternalError:
10861    .word   .LstrInternalError
10862    .endif
10863
10864/* continuation for OP_FILLED_NEW_ARRAY_RANGE */
10865
10866    /*
10867     * On entry:
10868     *  r0 holds array class
10869     *  r10 holds AA or BA
10870     */
10871.LOP_FILLED_NEW_ARRAY_RANGE_continue:
10872    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
10873    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
10874    ldrb    rINST, [r3, #1]             @ rINST<- descriptor[1]
10875    .if     1
10876    mov     r1, r10                     @ r1<- AA (length)
10877    .else
10878    mov     r1, r10, lsr #4             @ r1<- B (length)
10879    .endif
10880    cmp     rINST, #'I'                 @ array of ints?
10881    cmpne   rINST, #'L'                 @ array of objects?
10882    cmpne   rINST, #'['                 @ array of arrays?
10883    mov     r9, r1                      @ save length in r9
10884    bne     .LOP_FILLED_NEW_ARRAY_RANGE_notimpl         @ no, not handled yet
10885    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
10886    cmp     r0, #0                      @ null return?
10887    beq     common_exceptionThrown      @ alloc failed, handle exception
10888
10889    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
10890    str     r0, [rGLUE, #offGlue_retval]      @ retval.l <- new array
10891    str     rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
10892    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
10893    subs    r9, r9, #1                  @ length--, check for neg
10894    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
10895    bmi     2f                          @ was zero, bail
10896
10897    @ copy values from registers into the array
10898    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
10899    .if     1
10900    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
109011:  ldr     r3, [r2], #4                @ r3<- *r2++
10902    subs    r9, r9, #1                  @ count--
10903    str     r3, [r0], #4                @ *contents++ = vX
10904    bpl     1b
10905    @ continue at 2
10906    .else
10907    cmp     r9, #4                      @ length was initially 5?
10908    and     r2, r10, #15                @ r2<- A
10909    bne     1f                          @ <= 4 args, branch
10910    GET_VREG(r3, r2)                    @ r3<- vA
10911    sub     r9, r9, #1                  @ count--
10912    str     r3, [r0, #16]               @ contents[4] = vA
109131:  and     r2, r1, #15                 @ r2<- F/E/D/C
10914    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
10915    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
10916    subs    r9, r9, #1                  @ count--
10917    str     r3, [r0], #4                @ *contents++ = vX
10918    bpl     1b
10919    @ continue at 2
10920    .endif
10921
109222:
10923    ldr     r0, [rGLUE, #offGlue_retval]     @ r0<- object
10924    ldr     r1, [rGLUE, #offGlue_retval+4]   @ r1<- type
10925    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
10926    GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
10927    cmp     r1, #'I'                         @ Is int array?
10928    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head
10929    GOTO_OPCODE(ip)                          @ execute it
10930
10931    /*
10932     * Throw an exception indicating that we have not implemented this
10933     * mode of filled-new-array.
10934     */
10935.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
10936    ldr     r0, .L_strInternalError
10937    ldr     r1, .L_strFilledNewArrayNotImpl
10938    bl      dvmThrowException
10939    b       common_exceptionThrown
10940
10941    .if     (!1)                 @ define in one or the other, not both
10942.L_strFilledNewArrayNotImpl:
10943    .word   .LstrFilledNewArrayNotImpl
10944.L_strInternalError:
10945    .word   .LstrInternalError
10946    .endif
10947
10948/* continuation for OP_CMPL_FLOAT */
10949.LOP_CMPL_FLOAT_finish:
10950    SET_VREG(r0, r9)                    @ vAA<- r0
10951    GOTO_OPCODE(ip)                     @ jump to next instruction
10952
10953/* continuation for OP_CMPG_FLOAT */
10954.LOP_CMPG_FLOAT_finish:
10955    SET_VREG(r0, r9)                    @ vAA<- r0
10956    GOTO_OPCODE(ip)                     @ jump to next instruction
10957
10958/* continuation for OP_CMPL_DOUBLE */
10959.LOP_CMPL_DOUBLE_finish:
10960    SET_VREG(r0, r9)                    @ vAA<- r0
10961    GOTO_OPCODE(ip)                     @ jump to next instruction
10962
10963/* continuation for OP_CMPG_DOUBLE */
10964.LOP_CMPG_DOUBLE_finish:
10965    SET_VREG(r0, r9)                    @ vAA<- r0
10966    GOTO_OPCODE(ip)                     @ jump to next instruction
10967
10968/* continuation for OP_CMP_LONG */
10969
10970.LOP_CMP_LONG_less:
10971    mvn     r1, #0                      @ r1<- -1
10972    @ Want to cond code the next mov so we can avoid branch, but don't see it;
10973    @ instead, we just replicate the tail end.
10974    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
10975    SET_VREG(r1, r9)                    @ vAA<- r1
10976    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10977    GOTO_OPCODE(ip)                     @ jump to next instruction
10978
10979.LOP_CMP_LONG_greater:
10980    mov     r1, #1                      @ r1<- 1
10981    @ fall through to _finish
10982
10983.LOP_CMP_LONG_finish:
10984    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
10985    SET_VREG(r1, r9)                    @ vAA<- r1
10986    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10987    GOTO_OPCODE(ip)                     @ jump to next instruction
10988
10989/* continuation for OP_AGET_WIDE */
10990
10991.LOP_AGET_WIDE_finish:
10992    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
10993    ldrd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
10994    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
10995    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10996    stmia   r9, {r2-r3}                 @ vAA/vAA+1<- r2/r3
10997    GOTO_OPCODE(ip)                     @ jump to next instruction
10998
10999/* continuation for OP_APUT_WIDE */
11000
11001.LOP_APUT_WIDE_finish:
11002    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11003    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
11004    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11005    strd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
11006    GOTO_OPCODE(ip)                     @ jump to next instruction
11007
11008/* continuation for OP_APUT_OBJECT */
11009    /*
11010     * On entry:
11011     *  rINST = vBB (arrayObj)
11012     *  r9 = vAA (obj)
11013     *  r10 = offset into array (vBB + vCC * width)
11014     */
11015.LOP_APUT_OBJECT_finish:
11016    cmp     r9, #0                      @ storing null reference?
11017    beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
11018    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
11019    ldr     r1, [rINST, #offObject_clazz]  @ r1<- arrayObj->clazz
11020    bl      dvmCanPutArrayElement       @ test object type vs. array type
11021    cmp     r0, #0                      @ okay?
11022    beq     .LOP_APUT_OBJECT_throw           @ no
11023    mov     r1, rINST                   @ r1<- arrayObj
11024    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11025    ldr     r2, [rGLUE, #offGlue_cardTable]     @ get biased CT base
11026    add     r10, #offArrayObject_contents   @ r0<- pointer to slot
11027    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11028    str     r9, [r10]                   @ vBB[vCC]<- vAA
11029    strb    r2, [r2, r1, lsr #GC_CARD_SHIFT] @ mark card using object head
11030    GOTO_OPCODE(ip)                     @ jump to next instruction
11031.LOP_APUT_OBJECT_skip_check:
11032    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11033    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11034    str     r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
11035    GOTO_OPCODE(ip)                     @ jump to next instruction
11036.LOP_APUT_OBJECT_throw:
11037    @ The types don't match.  We need to throw an ArrayStoreException.
11038    ldr     r0, [r9, #offObject_clazz]
11039    ldr     r1, [rINST, #offObject_clazz]
11040    EXPORT_PC()
11041    bl      dvmThrowArrayStoreException
11042    b       common_exceptionThrown
11043
11044/* continuation for OP_IGET */
11045
11046    /*
11047     * Currently:
11048     *  r0 holds resolved field
11049     *  r9 holds object
11050     */
11051.LOP_IGET_finish:
11052    @bl      common_squeak0
11053    cmp     r9, #0                      @ check object for null
11054    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
11055    beq     common_errNullObject        @ object was null
11056    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
11057    ubfx    r2, rINST, #8, #4           @ r2<- A
11058    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11059    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11060    SET_VREG(r0, r2)                    @ fp[A]<- r0
11061    GOTO_OPCODE(ip)                     @ jump to next instruction
11062
11063/* continuation for OP_IGET_WIDE */
11064
11065    /*
11066     * Currently:
11067     *  r0 holds resolved field
11068     *  r9 holds object
11069     */
11070.LOP_IGET_WIDE_finish:
11071    cmp     r9, #0                      @ check object for null
11072    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
11073    beq     common_errNullObject        @ object was null
11074    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
11075    ubfx    r2, rINST, #8, #4           @ r2<- A
11076    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11077    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
11078    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11079    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
11080    GOTO_OPCODE(ip)                     @ jump to next instruction
11081
11082/* continuation for OP_IGET_OBJECT */
11083
11084    /*
11085     * Currently:
11086     *  r0 holds resolved field
11087     *  r9 holds object
11088     */
11089.LOP_IGET_OBJECT_finish:
11090    @bl      common_squeak0
11091    cmp     r9, #0                      @ check object for null
11092    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
11093    beq     common_errNullObject        @ object was null
11094    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
11095    @ no-op                             @ acquiring load
11096    mov     r2, rINST, lsr #8           @ r2<- A+
11097    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11098    and     r2, r2, #15                 @ r2<- A
11099    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11100    SET_VREG(r0, r2)                    @ fp[A]<- r0
11101    GOTO_OPCODE(ip)                     @ jump to next instruction
11102
11103/* continuation for OP_IGET_BOOLEAN */
11104
11105    /*
11106     * Currently:
11107     *  r0 holds resolved field
11108     *  r9 holds object
11109     */
11110.LOP_IGET_BOOLEAN_finish:
11111    @bl      common_squeak1
11112    cmp     r9, #0                      @ check object for null
11113    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
11114    beq     common_errNullObject        @ object was null
11115    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
11116    @ no-op                             @ acquiring load
11117    mov     r2, rINST, lsr #8           @ r2<- A+
11118    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11119    and     r2, r2, #15                 @ r2<- A
11120    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11121    SET_VREG(r0, r2)                    @ fp[A]<- r0
11122    GOTO_OPCODE(ip)                     @ jump to next instruction
11123
11124/* continuation for OP_IGET_BYTE */
11125
11126    /*
11127     * Currently:
11128     *  r0 holds resolved field
11129     *  r9 holds object
11130     */
11131.LOP_IGET_BYTE_finish:
11132    @bl      common_squeak2
11133    cmp     r9, #0                      @ check object for null
11134    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
11135    beq     common_errNullObject        @ object was null
11136    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
11137    @ no-op                             @ acquiring load
11138    mov     r2, rINST, lsr #8           @ r2<- A+
11139    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11140    and     r2, r2, #15                 @ r2<- A
11141    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11142    SET_VREG(r0, r2)                    @ fp[A]<- r0
11143    GOTO_OPCODE(ip)                     @ jump to next instruction
11144
11145/* continuation for OP_IGET_CHAR */
11146
11147    /*
11148     * Currently:
11149     *  r0 holds resolved field
11150     *  r9 holds object
11151     */
11152.LOP_IGET_CHAR_finish:
11153    @bl      common_squeak3
11154    cmp     r9, #0                      @ check object for null
11155    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
11156    beq     common_errNullObject        @ object was null
11157    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
11158    @ no-op                             @ acquiring load
11159    mov     r2, rINST, lsr #8           @ r2<- A+
11160    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11161    and     r2, r2, #15                 @ r2<- A
11162    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11163    SET_VREG(r0, r2)                    @ fp[A]<- r0
11164    GOTO_OPCODE(ip)                     @ jump to next instruction
11165
11166/* continuation for OP_IGET_SHORT */
11167
11168    /*
11169     * Currently:
11170     *  r0 holds resolved field
11171     *  r9 holds object
11172     */
11173.LOP_IGET_SHORT_finish:
11174    @bl      common_squeak4
11175    cmp     r9, #0                      @ check object for null
11176    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
11177    beq     common_errNullObject        @ object was null
11178    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
11179    @ no-op                             @ acquiring load
11180    mov     r2, rINST, lsr #8           @ r2<- A+
11181    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11182    and     r2, r2, #15                 @ r2<- A
11183    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11184    SET_VREG(r0, r2)                    @ fp[A]<- r0
11185    GOTO_OPCODE(ip)                     @ jump to next instruction
11186
11187/* continuation for OP_IPUT */
11188
11189    /*
11190     * Currently:
11191     *  r0 holds resolved field
11192     *  r9 holds object
11193     */
11194.LOP_IPUT_finish:
11195    @bl      common_squeak0
11196    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
11197    ubfx    r1, rINST, #8, #4           @ r1<- A
11198    cmp     r9, #0                      @ check object for null
11199    GET_VREG(r0, r1)                    @ r0<- fp[A]
11200    beq     common_errNullObject        @ object was null
11201    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11202    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11203    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
11204    GOTO_OPCODE(ip)                     @ jump to next instruction
11205
11206/* continuation for OP_IPUT_WIDE */
11207
11208    /*
11209     * Currently:
11210     *  r0 holds resolved field
11211     *  r9 holds object
11212     */
11213.LOP_IPUT_WIDE_finish:
11214    ubfx    r2, rINST, #8, #4           @ r2<- A
11215    cmp     r9, #0                      @ check object for null
11216    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
11217    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
11218    beq     common_errNullObject        @ object was null
11219    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11220    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
11221    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11222    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0
11223    GOTO_OPCODE(ip)                     @ jump to next instruction
11224
11225/* continuation for OP_IPUT_OBJECT */
11226
11227    /*
11228     * Currently:
11229     *  r0 holds resolved field
11230     *  r9 holds object
11231     */
11232.LOP_IPUT_OBJECT_finish:
11233    @bl      common_squeak0
11234    mov     r1, rINST, lsr #8           @ r1<- A+
11235    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
11236    and     r1, r1, #15                 @ r1<- A
11237    cmp     r9, #0                      @ check object for null
11238    GET_VREG(r0, r1)                    @ r0<- fp[A]
11239    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
11240    beq     common_errNullObject        @ object was null
11241    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11242    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11243    @ no-op                             @ releasing store
11244    str     r0, [r9, r3]                @ obj.field (32 bits)<- r0
11245    cmp     r0, #0                      @ stored a null reference?
11246    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
11247    GOTO_OPCODE(ip)                     @ jump to next instruction
11248
11249/* continuation for OP_IPUT_BOOLEAN */
11250
11251    /*
11252     * Currently:
11253     *  r0 holds resolved field
11254     *  r9 holds object
11255     */
11256.LOP_IPUT_BOOLEAN_finish:
11257    @bl      common_squeak1
11258    mov     r1, rINST, lsr #8           @ r1<- A+
11259    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
11260    and     r1, r1, #15                 @ r1<- A
11261    cmp     r9, #0                      @ check object for null
11262    GET_VREG(r0, r1)                    @ r0<- fp[A]
11263    beq     common_errNullObject        @ object was null
11264    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11265    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11266    @ no-op                             @ releasing store
11267    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
11268    GOTO_OPCODE(ip)                     @ jump to next instruction
11269
11270/* continuation for OP_IPUT_BYTE */
11271
11272    /*
11273     * Currently:
11274     *  r0 holds resolved field
11275     *  r9 holds object
11276     */
11277.LOP_IPUT_BYTE_finish:
11278    @bl      common_squeak2
11279    mov     r1, rINST, lsr #8           @ r1<- A+
11280    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
11281    and     r1, r1, #15                 @ r1<- A
11282    cmp     r9, #0                      @ check object for null
11283    GET_VREG(r0, r1)                    @ r0<- fp[A]
11284    beq     common_errNullObject        @ object was null
11285    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11286    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11287    @ no-op                             @ releasing store
11288    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
11289    GOTO_OPCODE(ip)                     @ jump to next instruction
11290
11291/* continuation for OP_IPUT_CHAR */
11292
11293    /*
11294     * Currently:
11295     *  r0 holds resolved field
11296     *  r9 holds object
11297     */
11298.LOP_IPUT_CHAR_finish:
11299    @bl      common_squeak3
11300    mov     r1, rINST, lsr #8           @ r1<- A+
11301    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
11302    and     r1, r1, #15                 @ r1<- A
11303    cmp     r9, #0                      @ check object for null
11304    GET_VREG(r0, r1)                    @ r0<- fp[A]
11305    beq     common_errNullObject        @ object was null
11306    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11307    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11308    @ no-op                             @ releasing store
11309    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
11310    GOTO_OPCODE(ip)                     @ jump to next instruction
11311
11312/* continuation for OP_IPUT_SHORT */
11313
11314    /*
11315     * Currently:
11316     *  r0 holds resolved field
11317     *  r9 holds object
11318     */
11319.LOP_IPUT_SHORT_finish:
11320    @bl      common_squeak4
11321    mov     r1, rINST, lsr #8           @ r1<- A+
11322    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
11323    and     r1, r1, #15                 @ r1<- A
11324    cmp     r9, #0                      @ check object for null
11325    GET_VREG(r0, r1)                    @ r0<- fp[A]
11326    beq     common_errNullObject        @ object was null
11327    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11328    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11329    @ no-op                             @ releasing store
11330    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
11331    GOTO_OPCODE(ip)                     @ jump to next instruction
11332
11333/* continuation for OP_SGET */
11334
11335    /*
11336     * Continuation if the field has not yet been resolved.
11337     *  r1: BBBB field ref
11338     */
11339.LOP_SGET_resolve:
11340    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
11341    EXPORT_PC()                         @ resolve() could throw, so export now
11342    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
11343    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
11344    cmp     r0, #0                      @ success?
11345    bne     .LOP_SGET_finish          @ yes, finish
11346    b       common_exceptionThrown      @ no, handle exception
11347
11348/* continuation for OP_SGET_WIDE */
11349
11350    /*
11351     * Continuation if the field has not yet been resolved.
11352     *  r1: BBBB field ref
11353     *
11354     * Returns StaticField pointer in r0.
11355     */
11356.LOP_SGET_WIDE_resolve:
11357    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
11358    EXPORT_PC()                         @ resolve() could throw, so export now
11359    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
11360    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
11361    cmp     r0, #0                      @ success?
11362    bne     .LOP_SGET_WIDE_finish          @ yes, finish
11363    b       common_exceptionThrown      @ no, handle exception
11364
11365/* continuation for OP_SGET_OBJECT */
11366
11367    /*
11368     * Continuation if the field has not yet been resolved.
11369     *  r1: BBBB field ref
11370     */
11371.LOP_SGET_OBJECT_resolve:
11372    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
11373    EXPORT_PC()                         @ resolve() could throw, so export now
11374    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
11375    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
11376    cmp     r0, #0                      @ success?
11377    bne     .LOP_SGET_OBJECT_finish          @ yes, finish
11378    b       common_exceptionThrown      @ no, handle exception
11379
11380/* continuation for OP_SGET_BOOLEAN */
11381
11382    /*
11383     * Continuation if the field has not yet been resolved.
11384     *  r1: BBBB field ref
11385     */
11386.LOP_SGET_BOOLEAN_resolve:
11387    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
11388    EXPORT_PC()                         @ resolve() could throw, so export now
11389    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
11390    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
11391    cmp     r0, #0                      @ success?
11392    bne     .LOP_SGET_BOOLEAN_finish          @ yes, finish
11393    b       common_exceptionThrown      @ no, handle exception
11394
11395/* continuation for OP_SGET_BYTE */
11396
11397    /*
11398     * Continuation if the field has not yet been resolved.
11399     *  r1: BBBB field ref
11400     */
11401.LOP_SGET_BYTE_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_BYTE_finish          @ yes, finish
11408    b       common_exceptionThrown      @ no, handle exception
11409
11410/* continuation for OP_SGET_CHAR */
11411
11412    /*
11413     * Continuation if the field has not yet been resolved.
11414     *  r1: BBBB field ref
11415     */
11416.LOP_SGET_CHAR_resolve:
11417    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
11418    EXPORT_PC()                         @ resolve() could throw, so export now
11419    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
11420    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
11421    cmp     r0, #0                      @ success?
11422    bne     .LOP_SGET_CHAR_finish          @ yes, finish
11423    b       common_exceptionThrown      @ no, handle exception
11424
11425/* continuation for OP_SGET_SHORT */
11426
11427    /*
11428     * Continuation if the field has not yet been resolved.
11429     *  r1: BBBB field ref
11430     */
11431.LOP_SGET_SHORT_resolve:
11432    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
11433    EXPORT_PC()                         @ resolve() could throw, so export now
11434    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
11435    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
11436    cmp     r0, #0                      @ success?
11437    bne     .LOP_SGET_SHORT_finish          @ yes, finish
11438    b       common_exceptionThrown      @ no, handle exception
11439
11440/* continuation for OP_SPUT */
11441
11442    /*
11443     * Continuation if the field has not yet been resolved.
11444     *  r1: BBBB field ref
11445     */
11446.LOP_SPUT_resolve:
11447    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
11448    EXPORT_PC()                         @ resolve() could throw, so export now
11449    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
11450    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
11451    cmp     r0, #0                      @ success?
11452    bne     .LOP_SPUT_finish          @ yes, finish
11453    b       common_exceptionThrown      @ no, handle exception
11454
11455/* continuation for OP_SPUT_WIDE */
11456
11457    /*
11458     * Continuation if the field has not yet been resolved.
11459     *  r1: BBBB field ref
11460     *  r9: &fp[AA]
11461     *
11462     * Returns StaticField pointer in r2.
11463     */
11464.LOP_SPUT_WIDE_resolve:
11465    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
11466    EXPORT_PC()                         @ resolve() could throw, so export now
11467    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
11468    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
11469    cmp     r0, #0                      @ success?
11470    mov     r2, r0                      @ copy to r2
11471    bne     .LOP_SPUT_WIDE_finish          @ yes, finish
11472    b       common_exceptionThrown      @ no, handle exception
11473
11474/* continuation for OP_SPUT_OBJECT */
11475.LOP_SPUT_OBJECT_finish:   @ field ptr in r0
11476    mov     r2, rINST, lsr #8           @ r2<- AA
11477    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11478    GET_VREG(r1, r2)                    @ r1<- fp[AA]
11479    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
11480    ldr     r9, [r0, #offField_clazz]   @ r9<- field->clazz
11481    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11482    @ no-op                             @ releasing store
11483    str     r1, [r0, #offStaticField_value]  @ field<- vAA
11484    cmp     r1, #0                      @ stored a null object?
11485    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card based on obj head
11486    GOTO_OPCODE(ip)                     @ jump to next instruction
11487
11488/* continuation for OP_SPUT_BOOLEAN */
11489
11490    /*
11491     * Continuation if the field has not yet been resolved.
11492     *  r1: BBBB field ref
11493     */
11494.LOP_SPUT_BOOLEAN_resolve:
11495    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
11496    EXPORT_PC()                         @ resolve() could throw, so export now
11497    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
11498    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
11499    cmp     r0, #0                      @ success?
11500    bne     .LOP_SPUT_BOOLEAN_finish          @ yes, finish
11501    b       common_exceptionThrown      @ no, handle exception
11502
11503/* continuation for OP_SPUT_BYTE */
11504
11505    /*
11506     * Continuation if the field has not yet been resolved.
11507     *  r1: BBBB field ref
11508     */
11509.LOP_SPUT_BYTE_resolve:
11510    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
11511    EXPORT_PC()                         @ resolve() could throw, so export now
11512    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
11513    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
11514    cmp     r0, #0                      @ success?
11515    bne     .LOP_SPUT_BYTE_finish          @ yes, finish
11516    b       common_exceptionThrown      @ no, handle exception
11517
11518/* continuation for OP_SPUT_CHAR */
11519
11520    /*
11521     * Continuation if the field has not yet been resolved.
11522     *  r1: BBBB field ref
11523     */
11524.LOP_SPUT_CHAR_resolve:
11525    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
11526    EXPORT_PC()                         @ resolve() could throw, so export now
11527    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
11528    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
11529    cmp     r0, #0                      @ success?
11530    bne     .LOP_SPUT_CHAR_finish          @ yes, finish
11531    b       common_exceptionThrown      @ no, handle exception
11532
11533/* continuation for OP_SPUT_SHORT */
11534
11535    /*
11536     * Continuation if the field has not yet been resolved.
11537     *  r1: BBBB field ref
11538     */
11539.LOP_SPUT_SHORT_resolve:
11540    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
11541    EXPORT_PC()                         @ resolve() could throw, so export now
11542    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
11543    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
11544    cmp     r0, #0                      @ success?
11545    bne     .LOP_SPUT_SHORT_finish          @ yes, finish
11546    b       common_exceptionThrown      @ no, handle exception
11547
11548/* continuation for OP_INVOKE_VIRTUAL */
11549
11550    /*
11551     * At this point:
11552     *  r0 = resolved base method
11553     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
11554     */
11555.LOP_INVOKE_VIRTUAL_continue:
11556    GET_VREG(r1, r10)                   @ r1<- "this" ptr
11557    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
11558    cmp     r1, #0                      @ is "this" null?
11559    beq     common_errNullObject        @ null "this", throw exception
11560    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
11561    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
11562    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
11563    bl      common_invokeMethodNoRange @ continue on
11564
11565/* continuation for OP_INVOKE_SUPER */
11566
11567    /*
11568     * At this point:
11569     *  r0 = resolved base method
11570     *  r9 = method->clazz
11571     */
11572.LOP_INVOKE_SUPER_continue:
11573    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
11574    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
11575    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
11576    EXPORT_PC()                         @ must export for invoke
11577    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
11578    bcs     .LOP_INVOKE_SUPER_nsm             @ method not present in superclass
11579    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
11580    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
11581    bl      common_invokeMethodNoRange @ continue on
11582
11583.LOP_INVOKE_SUPER_resolve:
11584    mov     r0, r9                      @ r0<- method->clazz
11585    mov     r2, #METHOD_VIRTUAL         @ resolver method type
11586    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
11587    cmp     r0, #0                      @ got null?
11588    bne     .LOP_INVOKE_SUPER_continue        @ no, continue
11589    b       common_exceptionThrown      @ yes, handle exception
11590
11591    /*
11592     * Throw a NoSuchMethodError with the method name as the message.
11593     *  r0 = resolved base method
11594     */
11595.LOP_INVOKE_SUPER_nsm:
11596    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
11597    b       common_errNoSuchMethod
11598
11599/* continuation for OP_INVOKE_DIRECT */
11600
11601    /*
11602     * On entry:
11603     *  r1 = reference (BBBB or CCCC)
11604     *  r10 = "this" register
11605     */
11606.LOP_INVOKE_DIRECT_resolve:
11607    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
11608    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
11609    mov     r2, #METHOD_DIRECT          @ resolver method type
11610    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
11611    cmp     r0, #0                      @ got null?
11612    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
11613    bne     .LOP_INVOKE_DIRECT_finish          @ no, continue
11614    b       common_exceptionThrown      @ yes, handle exception
11615
11616/* continuation for OP_INVOKE_VIRTUAL_RANGE */
11617
11618    /*
11619     * At this point:
11620     *  r0 = resolved base method
11621     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
11622     */
11623.LOP_INVOKE_VIRTUAL_RANGE_continue:
11624    GET_VREG(r1, r10)                   @ r1<- "this" ptr
11625    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
11626    cmp     r1, #0                      @ is "this" null?
11627    beq     common_errNullObject        @ null "this", throw exception
11628    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
11629    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
11630    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
11631    bl      common_invokeMethodRange @ continue on
11632
11633/* continuation for OP_INVOKE_SUPER_RANGE */
11634
11635    /*
11636     * At this point:
11637     *  r0 = resolved base method
11638     *  r9 = method->clazz
11639     */
11640.LOP_INVOKE_SUPER_RANGE_continue:
11641    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
11642    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
11643    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
11644    EXPORT_PC()                         @ must export for invoke
11645    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
11646    bcs     .LOP_INVOKE_SUPER_RANGE_nsm             @ method not present in superclass
11647    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
11648    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
11649    bl      common_invokeMethodRange @ continue on
11650
11651.LOP_INVOKE_SUPER_RANGE_resolve:
11652    mov     r0, r9                      @ r0<- method->clazz
11653    mov     r2, #METHOD_VIRTUAL         @ resolver method type
11654    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
11655    cmp     r0, #0                      @ got null?
11656    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ no, continue
11657    b       common_exceptionThrown      @ yes, handle exception
11658
11659    /*
11660     * Throw a NoSuchMethodError with the method name as the message.
11661     *  r0 = resolved base method
11662     */
11663.LOP_INVOKE_SUPER_RANGE_nsm:
11664    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
11665    b       common_errNoSuchMethod
11666
11667/* continuation for OP_INVOKE_DIRECT_RANGE */
11668
11669    /*
11670     * On entry:
11671     *  r1 = reference (BBBB or CCCC)
11672     *  r10 = "this" register
11673     */
11674.LOP_INVOKE_DIRECT_RANGE_resolve:
11675    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
11676    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
11677    mov     r2, #METHOD_DIRECT          @ resolver method type
11678    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
11679    cmp     r0, #0                      @ got null?
11680    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
11681    bne     .LOP_INVOKE_DIRECT_RANGE_finish          @ no, continue
11682    b       common_exceptionThrown      @ yes, handle exception
11683
11684/* continuation for OP_FLOAT_TO_LONG */
11685/*
11686 * Convert the float in r0 to a long in r0/r1.
11687 *
11688 * We have to clip values to long min/max per the specification.  The
11689 * expected common case is a "reasonable" value that converts directly
11690 * to modest integer.  The EABI convert function isn't doing this for us.
11691 */
11692f2l_doconv:
11693    stmfd   sp!, {r4, lr}
11694    mov     r1, #0x5f000000             @ (float)maxlong
11695    mov     r4, r0
11696    bl      __aeabi_fcmpge              @ is arg >= maxlong?
11697    cmp     r0, #0                      @ nonzero == yes
11698    mvnne   r0, #0                      @ return maxlong (7fffffff)
11699    mvnne   r1, #0x80000000
11700    ldmnefd sp!, {r4, pc}
11701
11702    mov     r0, r4                      @ recover arg
11703    mov     r1, #0xdf000000             @ (float)minlong
11704    bl      __aeabi_fcmple              @ is arg <= minlong?
11705    cmp     r0, #0                      @ nonzero == yes
11706    movne   r0, #0                      @ return minlong (80000000)
11707    movne   r1, #0x80000000
11708    ldmnefd sp!, {r4, pc}
11709
11710    mov     r0, r4                      @ recover arg
11711    mov     r1, r4
11712    bl      __aeabi_fcmpeq              @ is arg == self?
11713    cmp     r0, #0                      @ zero == no
11714    moveq   r1, #0                      @ return zero for NaN
11715    ldmeqfd sp!, {r4, pc}
11716
11717    mov     r0, r4                      @ recover arg
11718    bl      __aeabi_f2lz                @ convert float to long
11719    ldmfd   sp!, {r4, pc}
11720
11721/* continuation for OP_DOUBLE_TO_LONG */
11722/*
11723 * Convert the double in r0/r1 to a long in r0/r1.
11724 *
11725 * We have to clip values to long min/max per the specification.  The
11726 * expected common case is a "reasonable" value that converts directly
11727 * to modest integer.  The EABI convert function isn't doing this for us.
11728 */
11729d2l_doconv:
11730    stmfd   sp!, {r4, r5, lr}           @ save regs
11731    mov     r3, #0x43000000             @ maxlong, as a double (high word)
11732    add     r3, #0x00e00000             @  0x43e00000
11733    mov     r2, #0                      @ maxlong, as a double (low word)
11734    sub     sp, sp, #4                  @ align for EABI
11735    mov     r4, r0                      @ save a copy of r0
11736    mov     r5, r1                      @  and r1
11737    bl      __aeabi_dcmpge              @ is arg >= maxlong?
11738    cmp     r0, #0                      @ nonzero == yes
11739    mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
11740    mvnne   r1, #0x80000000
11741    bne     1f
11742
11743    mov     r0, r4                      @ recover arg
11744    mov     r1, r5
11745    mov     r3, #0xc3000000             @ minlong, as a double (high word)
11746    add     r3, #0x00e00000             @  0xc3e00000
11747    mov     r2, #0                      @ minlong, as a double (low word)
11748    bl      __aeabi_dcmple              @ is arg <= minlong?
11749    cmp     r0, #0                      @ nonzero == yes
11750    movne   r0, #0                      @ return minlong (8000000000000000)
11751    movne   r1, #0x80000000
11752    bne     1f
11753
11754    mov     r0, r4                      @ recover arg
11755    mov     r1, r5
11756    mov     r2, r4                      @ compare against self
11757    mov     r3, r5
11758    bl      __aeabi_dcmpeq              @ is arg == self?
11759    cmp     r0, #0                      @ zero == no
11760    moveq   r1, #0                      @ return zero for NaN
11761    beq     1f
11762
11763    mov     r0, r4                      @ recover arg
11764    mov     r1, r5
11765    bl      __aeabi_d2lz                @ convert double to long
11766
117671:
11768    add     sp, sp, #4
11769    ldmfd   sp!, {r4, r5, pc}
11770
11771/* continuation for OP_MUL_LONG */
11772
11773.LOP_MUL_LONG_finish:
11774    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11775    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
11776    GOTO_OPCODE(ip)                     @ jump to next instruction
11777
11778/* continuation for OP_SHL_LONG */
11779
11780.LOP_SHL_LONG_finish:
11781    mov     r0, r0, asl r2              @  r0<- r0 << r2
11782    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11783    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
11784    GOTO_OPCODE(ip)                     @ jump to next instruction
11785
11786/* continuation for OP_SHR_LONG */
11787
11788.LOP_SHR_LONG_finish:
11789    mov     r1, r1, asr r2              @  r1<- r1 >> r2
11790    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11791    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
11792    GOTO_OPCODE(ip)                     @ jump to next instruction
11793
11794/* continuation for OP_USHR_LONG */
11795
11796.LOP_USHR_LONG_finish:
11797    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
11798    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11799    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
11800    GOTO_OPCODE(ip)                     @ jump to next instruction
11801
11802/* continuation for OP_SHL_LONG_2ADDR */
11803
11804.LOP_SHL_LONG_2ADDR_finish:
11805    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11806    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
11807    GOTO_OPCODE(ip)                     @ jump to next instruction
11808
11809/* continuation for OP_SHR_LONG_2ADDR */
11810
11811.LOP_SHR_LONG_2ADDR_finish:
11812    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11813    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
11814    GOTO_OPCODE(ip)                     @ jump to next instruction
11815
11816/* continuation for OP_USHR_LONG_2ADDR */
11817
11818.LOP_USHR_LONG_2ADDR_finish:
11819    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11820    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
11821    GOTO_OPCODE(ip)                     @ jump to next instruction
11822
11823/* continuation for OP_IGET_VOLATILE */
11824
11825    /*
11826     * Currently:
11827     *  r0 holds resolved field
11828     *  r9 holds object
11829     */
11830.LOP_IGET_VOLATILE_finish:
11831    @bl      common_squeak0
11832    cmp     r9, #0                      @ check object for null
11833    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
11834    beq     common_errNullObject        @ object was null
11835    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
11836    SMP_DMB                            @ acquiring load
11837    mov     r2, rINST, lsr #8           @ r2<- A+
11838    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11839    and     r2, r2, #15                 @ r2<- A
11840    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11841    SET_VREG(r0, r2)                    @ fp[A]<- r0
11842    GOTO_OPCODE(ip)                     @ jump to next instruction
11843
11844/* continuation for OP_IPUT_VOLATILE */
11845
11846    /*
11847     * Currently:
11848     *  r0 holds resolved field
11849     *  r9 holds object
11850     */
11851.LOP_IPUT_VOLATILE_finish:
11852    @bl      common_squeak0
11853    mov     r1, rINST, lsr #8           @ r1<- A+
11854    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
11855    and     r1, r1, #15                 @ r1<- A
11856    cmp     r9, #0                      @ check object for null
11857    GET_VREG(r0, r1)                    @ r0<- fp[A]
11858    beq     common_errNullObject        @ object was null
11859    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11860    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11861    SMP_DMB                            @ releasing store
11862    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
11863    GOTO_OPCODE(ip)                     @ jump to next instruction
11864
11865/* continuation for OP_SGET_VOLATILE */
11866
11867    /*
11868     * Continuation if the field has not yet been resolved.
11869     *  r1: BBBB field ref
11870     */
11871.LOP_SGET_VOLATILE_resolve:
11872    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
11873    EXPORT_PC()                         @ resolve() could throw, so export now
11874    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
11875    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
11876    cmp     r0, #0                      @ success?
11877    bne     .LOP_SGET_VOLATILE_finish          @ yes, finish
11878    b       common_exceptionThrown      @ no, handle exception
11879
11880/* continuation for OP_SPUT_VOLATILE */
11881
11882    /*
11883     * Continuation if the field has not yet been resolved.
11884     *  r1: BBBB field ref
11885     */
11886.LOP_SPUT_VOLATILE_resolve:
11887    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
11888    EXPORT_PC()                         @ resolve() could throw, so export now
11889    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
11890    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
11891    cmp     r0, #0                      @ success?
11892    bne     .LOP_SPUT_VOLATILE_finish          @ yes, finish
11893    b       common_exceptionThrown      @ no, handle exception
11894
11895/* continuation for OP_IGET_OBJECT_VOLATILE */
11896
11897    /*
11898     * Currently:
11899     *  r0 holds resolved field
11900     *  r9 holds object
11901     */
11902.LOP_IGET_OBJECT_VOLATILE_finish:
11903    @bl      common_squeak0
11904    cmp     r9, #0                      @ check object for null
11905    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
11906    beq     common_errNullObject        @ object was null
11907    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
11908    SMP_DMB                            @ acquiring load
11909    mov     r2, rINST, lsr #8           @ r2<- A+
11910    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11911    and     r2, r2, #15                 @ r2<- A
11912    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11913    SET_VREG(r0, r2)                    @ fp[A]<- r0
11914    GOTO_OPCODE(ip)                     @ jump to next instruction
11915
11916/* continuation for OP_IGET_WIDE_VOLATILE */
11917
11918    /*
11919     * Currently:
11920     *  r0 holds resolved field
11921     *  r9 holds object
11922     */
11923.LOP_IGET_WIDE_VOLATILE_finish:
11924    cmp     r9, #0                      @ check object for null
11925    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
11926    beq     common_errNullObject        @ object was null
11927    .if     1
11928    add     r0, r9, r3                  @ r0<- address of field
11929    bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
11930    .else
11931    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
11932    .endif
11933    mov     r2, rINST, lsr #8           @ r2<- A+
11934    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11935    and     r2, r2, #15                 @ r2<- A
11936    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
11937    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
11938    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
11939    GOTO_OPCODE(ip)                     @ jump to next instruction
11940
11941/* continuation for OP_IPUT_WIDE_VOLATILE */
11942
11943    /*
11944     * Currently:
11945     *  r0 holds resolved field
11946     *  r9 holds object
11947     */
11948.LOP_IPUT_WIDE_VOLATILE_finish:
11949    mov     r2, rINST, lsr #8           @ r2<- A+
11950    cmp     r9, #0                      @ check object for null
11951    and     r2, r2, #15                 @ r2<- A
11952    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
11953    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
11954    beq     common_errNullObject        @ object was null
11955    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
11956    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
11957    GET_INST_OPCODE(r10)                @ extract opcode from rINST
11958    .if     1
11959    add     r2, r9, r3                  @ r2<- target address
11960    bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
11961    .else
11962    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0/r1
11963    .endif
11964    GOTO_OPCODE(r10)                    @ jump to next instruction
11965
11966/* continuation for OP_SGET_WIDE_VOLATILE */
11967
11968    /*
11969     * Continuation if the field has not yet been resolved.
11970     *  r1: BBBB field ref
11971     *
11972     * Returns StaticField pointer in r0.
11973     */
11974.LOP_SGET_WIDE_VOLATILE_resolve:
11975    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
11976    EXPORT_PC()                         @ resolve() could throw, so export now
11977    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
11978    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
11979    cmp     r0, #0                      @ success?
11980    bne     .LOP_SGET_WIDE_VOLATILE_finish          @ yes, finish
11981    b       common_exceptionThrown      @ no, handle exception
11982
11983/* continuation for OP_SPUT_WIDE_VOLATILE */
11984
11985    /*
11986     * Continuation if the field has not yet been resolved.
11987     *  r1: BBBB field ref
11988     *  r9: &fp[AA]
11989     *
11990     * Returns StaticField pointer in r2.
11991     */
11992.LOP_SPUT_WIDE_VOLATILE_resolve:
11993    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
11994    EXPORT_PC()                         @ resolve() could throw, so export now
11995    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
11996    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
11997    cmp     r0, #0                      @ success?
11998    mov     r2, r0                      @ copy to r2
11999    bne     .LOP_SPUT_WIDE_VOLATILE_finish          @ yes, finish
12000    b       common_exceptionThrown      @ no, handle exception
12001
12002/* continuation for OP_EXECUTE_INLINE */
12003
12004    /*
12005     * Extract args, call function.
12006     *  r0 = #of args (0-4)
12007     *  r10 = call index
12008     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
12009     *
12010     * Other ideas:
12011     * - Use a jump table from the main piece to jump directly into the
12012     *   AND/LDR pairs.  Costs a data load, saves a branch.
12013     * - Have five separate pieces that do the loading, so we can work the
12014     *   interleave a little better.  Increases code size.
12015     */
12016.LOP_EXECUTE_INLINE_continue:
12017    rsb     r0, r0, #4                  @ r0<- 4-r0
12018    FETCH(r9, 2)                        @ r9<- FEDC
12019    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
12020    bl      common_abort                @ (skipped due to ARM prefetch)
120214:  and     ip, r9, #0xf000             @ isolate F
12022    ldr     r3, [rFP, ip, lsr #10]      @ r3<- vF (shift right 12, left 2)
120233:  and     ip, r9, #0x0f00             @ isolate E
12024    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vE
120252:  and     ip, r9, #0x00f0             @ isolate D
12026    ldr     r1, [rFP, ip, lsr #2]       @ r1<- vD
120271:  and     ip, r9, #0x000f             @ isolate C
12028    ldr     r0, [rFP, ip, lsl #2]       @ r0<- vC
120290:
12030    ldr     r9, .LOP_EXECUTE_INLINE_table       @ table of InlineOperation
12031    ldr     pc, [r9, r10, lsl #4]       @ sizeof=16, "func" is first entry
12032    @ (not reached)
12033
12034.LOP_EXECUTE_INLINE_table:
12035    .word   gDvmInlineOpsTable
12036
12037/* continuation for OP_EXECUTE_INLINE_RANGE */
12038
12039    /*
12040     * Extract args, call function.
12041     *  r0 = #of args (0-4)
12042     *  r10 = call index
12043     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
12044     */
12045.LOP_EXECUTE_INLINE_RANGE_continue:
12046    rsb     r0, r0, #4                  @ r0<- 4-r0
12047    FETCH(r9, 2)                        @ r9<- CCCC
12048    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
12049    bl      common_abort                @ (skipped due to ARM prefetch)
120504:  add     ip, r9, #3                  @ base+3
12051    GET_VREG(r3, ip)                    @ r3<- vBase[3]
120523:  add     ip, r9, #2                  @ base+2
12053    GET_VREG(r2, ip)                    @ r2<- vBase[2]
120542:  add     ip, r9, #1                  @ base+1
12055    GET_VREG(r1, ip)                    @ r1<- vBase[1]
120561:  add     ip, r9, #0                  @ (nop)
12057    GET_VREG(r0, ip)                    @ r0<- vBase[0]
120580:
12059    ldr     r9, .LOP_EXECUTE_INLINE_RANGE_table       @ table of InlineOperation
12060    ldr     pc, [r9, r10, lsl #4]       @ sizeof=16, "func" is first entry
12061    @ (not reached)
12062
12063.LOP_EXECUTE_INLINE_RANGE_table:
12064    .word   gDvmInlineOpsTable
12065
12066/* continuation for OP_IPUT_OBJECT_VOLATILE */
12067
12068    /*
12069     * Currently:
12070     *  r0 holds resolved field
12071     *  r9 holds object
12072     */
12073.LOP_IPUT_OBJECT_VOLATILE_finish:
12074    @bl      common_squeak0
12075    mov     r1, rINST, lsr #8           @ r1<- A+
12076    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
12077    and     r1, r1, #15                 @ r1<- A
12078    cmp     r9, #0                      @ check object for null
12079    GET_VREG(r0, r1)                    @ r0<- fp[A]
12080    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
12081    beq     common_errNullObject        @ object was null
12082    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
12083    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12084    SMP_DMB                            @ releasing store
12085    str     r0, [r9, r3]                @ obj.field (32 bits)<- r0
12086    cmp     r0, #0                      @ stored a null reference?
12087    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
12088    GOTO_OPCODE(ip)                     @ jump to next instruction
12089
12090/* continuation for OP_SGET_OBJECT_VOLATILE */
12091
12092    /*
12093     * Continuation if the field has not yet been resolved.
12094     *  r1: BBBB field ref
12095     */
12096.LOP_SGET_OBJECT_VOLATILE_resolve:
12097    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
12098    EXPORT_PC()                         @ resolve() could throw, so export now
12099    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
12100    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
12101    cmp     r0, #0                      @ success?
12102    bne     .LOP_SGET_OBJECT_VOLATILE_finish          @ yes, finish
12103    b       common_exceptionThrown      @ no, handle exception
12104
12105/* continuation for OP_SPUT_OBJECT_VOLATILE */
12106.LOP_SPUT_OBJECT_VOLATILE_finish:   @ field ptr in r0
12107    mov     r2, rINST, lsr #8           @ r2<- AA
12108    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
12109    GET_VREG(r1, r2)                    @ r1<- fp[AA]
12110    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
12111    ldr     r9, [r0, #offField_clazz]   @ r9<- field->clazz
12112    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12113    SMP_DMB                            @ releasing store
12114    str     r1, [r0, #offStaticField_value]  @ field<- vAA
12115    cmp     r1, #0                      @ stored a null object?
12116    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card based on obj head
12117    GOTO_OPCODE(ip)                     @ jump to next instruction
12118
12119/* continuation for OP_CONST_CLASS_JUMBO */
12120
12121    /*
12122     * Continuation if the Class has not yet been resolved.
12123     *  r1: AAAAAAAA (Class ref)
12124     *  r9: target register
12125     */
12126.LOP_CONST_CLASS_JUMBO_resolve:
12127    EXPORT_PC()
12128    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
12129    mov     r2, #1                      @ r2<- true
12130    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
12131    bl      dvmResolveClass             @ r0<- Class reference
12132    cmp     r0, #0                      @ failed?
12133    beq     common_exceptionThrown      @ yup, handle the exception
12134    FETCH_ADVANCE_INST(4)               @ advance rPC, load rINST
12135    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12136    SET_VREG(r0, r9)                    @ vBBBB<- r0
12137    GOTO_OPCODE(ip)                     @ jump to next instruction
12138
12139/* continuation for OP_CHECK_CAST_JUMBO */
12140
12141    /*
12142     * Trivial test failed, need to perform full check.  This is common.
12143     *  r0 holds obj->clazz
12144     *  r1 holds desired class resolved from AAAAAAAA
12145     *  r9 holds object
12146     */
12147.LOP_CHECK_CAST_JUMBO_fullcheck:
12148    mov     r10, r1                     @ avoid ClassObject getting clobbered
12149    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
12150    cmp     r0, #0                      @ failed?
12151    bne     .LOP_CHECK_CAST_JUMBO_okay            @ no, success
12152
12153    @ A cast has failed.  We need to throw a ClassCastException.
12154    EXPORT_PC()                         @ about to throw
12155    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz (actual class)
12156    mov     r1, r10                     @ r1<- desired class
12157    bl      dvmThrowClassCastException
12158    b       common_exceptionThrown
12159
12160    /*
12161     * Advance PC and get the next opcode.
12162     */
12163.LOP_CHECK_CAST_JUMBO_okay:
12164    FETCH_ADVANCE_INST(4)               @ advance rPC, load rINST
12165    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12166    GOTO_OPCODE(ip)                     @ jump to next instruction
12167
12168    /*
12169     * Resolution required.  This is the least-likely path.
12170     *
12171     *  r2 holds AAAAAAAA
12172     *  r9 holds object
12173     */
12174.LOP_CHECK_CAST_JUMBO_resolve:
12175    EXPORT_PC()                         @ resolve() could throw
12176    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
12177    mov     r1, r2                      @ r1<- AAAAAAAA
12178    mov     r2, #0                      @ r2<- false
12179    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
12180    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
12181    cmp     r0, #0                      @ got null?
12182    beq     common_exceptionThrown      @ yes, handle exception
12183    mov     r1, r0                      @ r1<- class resolved from AAAAAAAA
12184    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
12185    b       .LOP_CHECK_CAST_JUMBO_resolved        @ pick up where we left off
12186
12187/* continuation for OP_INSTANCE_OF_JUMBO */
12188
12189    /*
12190     * Class resolved, determine type of check necessary.  This is common.
12191     *  r0 holds obj->clazz
12192     *  r1 holds class resolved from AAAAAAAA
12193     *  r9 holds BBBB
12194     */
12195.LOP_INSTANCE_OF_JUMBO_resolved:
12196    cmp     r0, r1                      @ same class (trivial success)?
12197    beq     .LOP_INSTANCE_OF_JUMBO_trivial         @ yes, trivial finish
12198    @ fall through to OP_INSTANCE_OF_JUMBO_fullcheck
12199
12200    /*
12201     * Trivial test failed, need to perform full check.  This is common.
12202     *  r0 holds obj->clazz
12203     *  r1 holds class resolved from AAAAAAAA
12204     *  r9 holds BBBB
12205     */
12206.LOP_INSTANCE_OF_JUMBO_fullcheck:
12207    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
12208    @ fall through to OP_INSTANCE_OF_JUMBO_store
12209
12210    /*
12211     * r0 holds boolean result
12212     * r9 holds BBBB
12213     */
12214.LOP_INSTANCE_OF_JUMBO_store:
12215    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
12216    SET_VREG(r0, r9)                    @ vBBBB<- r0
12217    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12218    GOTO_OPCODE(ip)                     @ jump to next instruction
12219
12220    /*
12221     * Trivial test succeeded, save and bail.
12222     *  r9 holds BBBB
12223     */
12224.LOP_INSTANCE_OF_JUMBO_trivial:
12225    mov     r0, #1                      @ indicate success
12226    @ could b OP_INSTANCE_OF_JUMBO_store, but copying is faster and cheaper
12227    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
12228    SET_VREG(r0, r9)                    @ vBBBB<- r0
12229    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12230    GOTO_OPCODE(ip)                     @ jump to next instruction
12231
12232    /*
12233     * Resolution required.  This is the least-likely path.
12234     *
12235     *  r3 holds AAAAAAAA
12236     *  r9 holds BBBB
12237     */
12238
12239.LOP_INSTANCE_OF_JUMBO_resolve:
12240    EXPORT_PC()                         @ resolve() could throw
12241    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
12242    mov     r1, r3                      @ r1<- AAAAAAAA
12243    mov     r2, #1                      @ r2<- true
12244    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
12245    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
12246    cmp     r0, #0                      @ got null?
12247    beq     common_exceptionThrown      @ yes, handle exception
12248    FETCH(r3, 4)                        @ r3<- vCCCC
12249    mov     r1, r0                      @ r1<- class resolved from AAAAAAAA
12250    GET_VREG(r0, r3)                    @ r0<- vCCCC (object)
12251    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
12252    b       .LOP_INSTANCE_OF_JUMBO_resolved        @ pick up where we left off
12253
12254/* continuation for OP_NEW_INSTANCE_JUMBO */
12255
12256    .balign 32                          @ minimize cache lines
12257.LOP_NEW_INSTANCE_JUMBO_finish: @ r0=new object
12258    FETCH(r3, 3)                        @ r3<- BBBB
12259    cmp     r0, #0                      @ failed?
12260    beq     common_exceptionThrown      @ yes, handle the exception
12261    FETCH_ADVANCE_INST(4)               @ advance rPC, load rINST
12262    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12263    SET_VREG(r0, r3)                    @ vBBBB<- r0
12264    GOTO_OPCODE(ip)                     @ jump to next instruction
12265
12266    /*
12267     * Class initialization required.
12268     *
12269     *  r0 holds class object
12270     */
12271.LOP_NEW_INSTANCE_JUMBO_needinit:
12272    mov     r9, r0                      @ save r0
12273    bl      dvmInitClass                @ initialize class
12274    cmp     r0, #0                      @ check boolean result
12275    mov     r0, r9                      @ restore r0
12276    bne     .LOP_NEW_INSTANCE_JUMBO_initialized     @ success, continue
12277    b       common_exceptionThrown      @ failed, deal with init exception
12278
12279    /*
12280     * Resolution required.  This is the least-likely path.
12281     *
12282     *  r1 holds AAAAAAAA
12283     */
12284.LOP_NEW_INSTANCE_JUMBO_resolve:
12285    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
12286    mov     r2, #0                      @ r2<- false
12287    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
12288    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
12289    cmp     r0, #0                      @ got null?
12290    bne     .LOP_NEW_INSTANCE_JUMBO_resolved        @ no, continue
12291    b       common_exceptionThrown      @ yes, handle exception
12292
12293/* continuation for OP_NEW_ARRAY_JUMBO */
12294
12295
12296    /*
12297     * Resolve class.  (This is an uncommon case.)
12298     *
12299     *  r1 holds array length
12300     *  r2 holds class ref AAAAAAAA
12301     */
12302.LOP_NEW_ARRAY_JUMBO_resolve:
12303    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
12304    mov     r9, r1                      @ r9<- length (save)
12305    mov     r1, r2                      @ r1<- AAAAAAAA
12306    mov     r2, #0                      @ r2<- false
12307    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
12308    bl      dvmResolveClass             @ r0<- call(clazz, ref)
12309    cmp     r0, #0                      @ got null?
12310    mov     r1, r9                      @ r1<- length (restore)
12311    beq     common_exceptionThrown      @ yes, handle exception
12312    @ fall through to OP_NEW_ARRAY_JUMBO_finish
12313
12314    /*
12315     * Finish allocation.
12316     *
12317     *  r0 holds class
12318     *  r1 holds array length
12319     */
12320.LOP_NEW_ARRAY_JUMBO_finish:
12321    mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
12322    bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
12323    cmp     r0, #0                      @ failed?
12324    FETCH(r2, 3)                        @ r2<- vBBBB
12325    beq     common_exceptionThrown      @ yes, handle the exception
12326    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
12327    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12328    SET_VREG(r0, r2)                    @ vBBBB<- r0
12329    GOTO_OPCODE(ip)                     @ jump to next instruction
12330
12331/* continuation for OP_FILLED_NEW_ARRAY_JUMBO */
12332
12333    /*
12334     * On entry:
12335     *  r0 holds array class
12336     */
12337.LOP_FILLED_NEW_ARRAY_JUMBO_continue:
12338    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
12339    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
12340    ldrb    rINST, [r3, #1]             @ rINST<- descriptor[1]
12341    FETCH(r1, 3)                        @ r1<- BBBB (length)
12342    cmp     rINST, #'I'                 @ array of ints?
12343    cmpne   rINST, #'L'                 @ array of objects?
12344    cmpne   rINST, #'['                 @ array of arrays?
12345    mov     r9, r1                      @ save length in r9
12346    bne     .LOP_FILLED_NEW_ARRAY_JUMBO_notimpl         @ no, not handled yet
12347    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
12348    cmp     r0, #0                      @ null return?
12349    beq     common_exceptionThrown      @ alloc failed, handle exception
12350
12351    FETCH(r1, 4)                        @ r1<- CCCC
12352    str     r0, [rGLUE, #offGlue_retval]      @ retval.l <- new array
12353    str     rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
12354    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
12355    subs    r9, r9, #1                  @ length--, check for neg
12356    FETCH_ADVANCE_INST(5)               @ advance to next instr, load rINST
12357    bmi     2f                          @ was zero, bail
12358
12359    @ copy values from registers into the array
12360    @ r0=array, r1=CCCC, r9=BBBB (length)
12361    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
123621:  ldr     r3, [r2], #4                @ r3<- *r2++
12363    subs    r9, r9, #1                  @ count--
12364    str     r3, [r0], #4                @ *contents++ = vX
12365    bpl     1b
12366
123672:  ldr     r0, [rGLUE, #offGlue_retval]     @ r0<- object
12368    ldr     r1, [rGLUE, #offGlue_retval+4]   @ r1<- type
12369    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
12370    GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
12371    cmp     r1, #'I'                         @ Is int array?
12372    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head
12373    GOTO_OPCODE(ip)                          @ execute it
12374
12375    /*
12376     * Throw an exception indicating that we have not implemented this
12377     * mode of filled-new-array.
12378     */
12379.LOP_FILLED_NEW_ARRAY_JUMBO_notimpl:
12380    ldr     r0, .L_strInternalError
12381    ldr     r1, .L_strFilledNewArrayNotImpl
12382    bl      dvmThrowException
12383    b       common_exceptionThrown
12384
12385/* continuation for OP_IGET_JUMBO */
12386
12387    /*
12388     * Currently:
12389     *  r0 holds resolved field
12390     *  r9 holds object
12391     */
12392.LOP_IGET_JUMBO_resolved:
12393    cmp     r0, #0                      @ resolution unsuccessful?
12394    beq     common_exceptionThrown      @ yes, throw exception
12395    @ fall through to OP_IGET_JUMBO_finish
12396
12397    /*
12398     * Currently:
12399     *  r0 holds resolved field
12400     *  r9 holds object
12401     */
12402.LOP_IGET_JUMBO_finish:
12403    @bl      common_squeak0
12404    cmp     r9, #0                      @ check object for null
12405    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
12406    beq     common_errNullObject        @ object was null
12407    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
12408    @ no-op                             @ acquiring load
12409    FETCH(r2, 3)                        @ r2<- BBBB
12410    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
12411    SET_VREG(r0, r2)                    @ fp[BBBB]<- r0
12412    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12413    GOTO_OPCODE(ip)                     @ jump to next instruction
12414
12415/* continuation for OP_IGET_WIDE_JUMBO */
12416
12417    /*
12418     * Currently:
12419     *  r0 holds resolved field
12420     *  r9 holds object
12421     */
12422.LOP_IGET_WIDE_JUMBO_resolved:
12423    cmp     r0, #0                      @ resolution unsuccessful?
12424    beq     common_exceptionThrown      @ yes, throw exception
12425    @ fall through to OP_IGET_WIDE_JUMBO_finish
12426
12427    /*
12428     * Currently:
12429     *  r0 holds resolved field
12430     *  r9 holds object
12431     */
12432.LOP_IGET_WIDE_JUMBO_finish:
12433    cmp     r9, #0                      @ check object for null
12434    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
12435    beq     common_errNullObject        @ object was null
12436    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
12437    FETCH(r2, 3)                        @ r2<- BBBB
12438    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
12439    add     r3, rFP, r2, lsl #2         @ r3<- &fp[BBBB]
12440    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12441    stmia   r3, {r0-r1}                 @ fp[BBBB]<- r0/r1
12442    GOTO_OPCODE(ip)                     @ jump to next instruction
12443
12444/* continuation for OP_IGET_OBJECT_JUMBO */
12445
12446    /*
12447     * Currently:
12448     *  r0 holds resolved field
12449     *  r9 holds object
12450     */
12451.LOP_IGET_OBJECT_JUMBO_resolved:
12452    cmp     r0, #0                      @ resolution unsuccessful?
12453    beq     common_exceptionThrown      @ yes, throw exception
12454    @ fall through to OP_IGET_OBJECT_JUMBO_finish
12455
12456    /*
12457     * Currently:
12458     *  r0 holds resolved field
12459     *  r9 holds object
12460     */
12461.LOP_IGET_OBJECT_JUMBO_finish:
12462    @bl      common_squeak0
12463    cmp     r9, #0                      @ check object for null
12464    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
12465    beq     common_errNullObject        @ object was null
12466    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
12467    @ no-op                             @ acquiring load
12468    FETCH(r2, 3)                        @ r2<- BBBB
12469    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
12470    SET_VREG(r0, r2)                    @ fp[BBBB]<- r0
12471    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12472    GOTO_OPCODE(ip)                     @ jump to next instruction
12473
12474/* continuation for OP_IGET_BOOLEAN_JUMBO */
12475
12476    /*
12477     * Currently:
12478     *  r0 holds resolved field
12479     *  r9 holds object
12480     */
12481.LOP_IGET_BOOLEAN_JUMBO_resolved:
12482    cmp     r0, #0                      @ resolution unsuccessful?
12483    beq     common_exceptionThrown      @ yes, throw exception
12484    @ fall through to OP_IGET_BOOLEAN_JUMBO_finish
12485
12486    /*
12487     * Currently:
12488     *  r0 holds resolved field
12489     *  r9 holds object
12490     */
12491.LOP_IGET_BOOLEAN_JUMBO_finish:
12492    @bl      common_squeak1
12493    cmp     r9, #0                      @ check object for null
12494    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
12495    beq     common_errNullObject        @ object was null
12496    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
12497    @ no-op                             @ acquiring load
12498    FETCH(r2, 3)                        @ r2<- BBBB
12499    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
12500    SET_VREG(r0, r2)                    @ fp[BBBB]<- r0
12501    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12502    GOTO_OPCODE(ip)                     @ jump to next instruction
12503
12504/* continuation for OP_IGET_BYTE_JUMBO */
12505
12506    /*
12507     * Currently:
12508     *  r0 holds resolved field
12509     *  r9 holds object
12510     */
12511.LOP_IGET_BYTE_JUMBO_resolved:
12512    cmp     r0, #0                      @ resolution unsuccessful?
12513    beq     common_exceptionThrown      @ yes, throw exception
12514    @ fall through to OP_IGET_BYTE_JUMBO_finish
12515
12516    /*
12517     * Currently:
12518     *  r0 holds resolved field
12519     *  r9 holds object
12520     */
12521.LOP_IGET_BYTE_JUMBO_finish:
12522    @bl      common_squeak2
12523    cmp     r9, #0                      @ check object for null
12524    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
12525    beq     common_errNullObject        @ object was null
12526    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
12527    @ no-op                             @ acquiring load
12528    FETCH(r2, 3)                        @ r2<- BBBB
12529    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
12530    SET_VREG(r0, r2)                    @ fp[BBBB]<- r0
12531    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12532    GOTO_OPCODE(ip)                     @ jump to next instruction
12533
12534/* continuation for OP_IGET_CHAR_JUMBO */
12535
12536    /*
12537     * Currently:
12538     *  r0 holds resolved field
12539     *  r9 holds object
12540     */
12541.LOP_IGET_CHAR_JUMBO_resolved:
12542    cmp     r0, #0                      @ resolution unsuccessful?
12543    beq     common_exceptionThrown      @ yes, throw exception
12544    @ fall through to OP_IGET_CHAR_JUMBO_finish
12545
12546    /*
12547     * Currently:
12548     *  r0 holds resolved field
12549     *  r9 holds object
12550     */
12551.LOP_IGET_CHAR_JUMBO_finish:
12552    @bl      common_squeak3
12553    cmp     r9, #0                      @ check object for null
12554    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
12555    beq     common_errNullObject        @ object was null
12556    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
12557    @ no-op                             @ acquiring load
12558    FETCH(r2, 3)                        @ r2<- BBBB
12559    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
12560    SET_VREG(r0, r2)                    @ fp[BBBB]<- r0
12561    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12562    GOTO_OPCODE(ip)                     @ jump to next instruction
12563
12564/* continuation for OP_IGET_SHORT_JUMBO */
12565
12566    /*
12567     * Currently:
12568     *  r0 holds resolved field
12569     *  r9 holds object
12570     */
12571.LOP_IGET_SHORT_JUMBO_resolved:
12572    cmp     r0, #0                      @ resolution unsuccessful?
12573    beq     common_exceptionThrown      @ yes, throw exception
12574    @ fall through to OP_IGET_SHORT_JUMBO_finish
12575
12576    /*
12577     * Currently:
12578     *  r0 holds resolved field
12579     *  r9 holds object
12580     */
12581.LOP_IGET_SHORT_JUMBO_finish:
12582    @bl      common_squeak4
12583    cmp     r9, #0                      @ check object for null
12584    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
12585    beq     common_errNullObject        @ object was null
12586    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
12587    @ no-op                             @ acquiring load
12588    FETCH(r2, 3)                        @ r2<- BBBB
12589    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
12590    SET_VREG(r0, r2)                    @ fp[BBBB]<- r0
12591    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12592    GOTO_OPCODE(ip)                     @ jump to next instruction
12593
12594/* continuation for OP_IPUT_JUMBO */
12595
12596    /*
12597     * Currently:
12598     *  r0 holds resolved field
12599     *  r9 holds object
12600     */
12601.LOP_IPUT_JUMBO_resolved:
12602     cmp     r0, #0                     @ resolution unsuccessful?
12603     beq     common_exceptionThrown     @ yes, throw exception
12604     @ fall through to OP_IPUT_JUMBO_finish
12605
12606    /*
12607     * Currently:
12608     *  r0 holds resolved field
12609     *  r9 holds object
12610     */
12611.LOP_IPUT_JUMBO_finish:
12612    @bl      common_squeak0
12613    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
12614    FETCH(r1, 3)                        @ r1<- BBBB
12615    cmp     r9, #0                      @ check object for null
12616    GET_VREG(r0, r1)                    @ r0<- fp[BBBB]
12617    beq     common_errNullObject        @ object was null
12618    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
12619    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12620    @ no-op                             @ releasing store
12621    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
12622    GOTO_OPCODE(ip)                     @ jump to next instruction
12623
12624/* continuation for OP_IPUT_WIDE_JUMBO */
12625
12626    /*
12627     * Currently:
12628     *  r0 holds resolved field
12629     *  r9 holds object
12630     */
12631.LOP_IPUT_WIDE_JUMBO_resolved:
12632     cmp     r0, #0                     @ resolution unsuccessful?
12633     beq     common_exceptionThrown     @ yes, throw exception
12634     @ fall through to OP_IPUT_WIDE_JUMBO_finish
12635
12636    /*
12637     * Currently:
12638     *  r0 holds resolved field
12639     *  r9 holds object
12640     */
12641.LOP_IPUT_WIDE_JUMBO_finish:
12642    cmp     r9, #0                      @ check object for null
12643    FETCH(r2, 3)                        @ r1<- BBBB
12644    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
12645    add     r2, rFP, r2, lsl #2         @ r3<- &fp[BBBB]
12646    beq     common_errNullObject        @ object was null
12647    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
12648    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[BBBB]
12649    GET_INST_OPCODE(r10)                @ extract opcode from rINST
12650    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0/r1
12651    GOTO_OPCODE(r10)                    @ jump to next instruction
12652
12653/* continuation for OP_IPUT_OBJECT_JUMBO */
12654
12655    /*
12656     * Currently:
12657     *  r0 holds resolved field
12658     *  r9 holds object
12659     */
12660.LOP_IPUT_OBJECT_JUMBO_resolved:
12661     cmp     r0, #0                     @ resolution unsuccessful?
12662     beq     common_exceptionThrown     @ yes, throw exception
12663     @ fall through to OP_IPUT_OBJECT_JUMBO_finish
12664
12665    /*
12666     * Currently:
12667     *  r0 holds resolved field
12668     *  r9 holds object
12669     */
12670.LOP_IPUT_OBJECT_JUMBO_finish:
12671    @bl      common_squeak0
12672    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
12673    FETCH(r1, 3)                        @ r1<- BBBB
12674    cmp     r9, #0                      @ check object for null
12675    GET_VREG(r0, r1)                    @ r0<- fp[BBBB]
12676    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
12677    beq     common_errNullObject        @ object was null
12678    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
12679    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12680    @ no-op                             @ releasing store
12681    str     r0, [r9, r3]                @ obj.field (32 bits)<- r0
12682    cmp     r0, #0                      @ stored a null reference?
12683    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
12684    GOTO_OPCODE(ip)                     @ jump to next instruction
12685
12686/* continuation for OP_IPUT_BOOLEAN_JUMBO */
12687
12688    /*
12689     * Currently:
12690     *  r0 holds resolved field
12691     *  r9 holds object
12692     */
12693.LOP_IPUT_BOOLEAN_JUMBO_resolved:
12694     cmp     r0, #0                     @ resolution unsuccessful?
12695     beq     common_exceptionThrown     @ yes, throw exception
12696     @ fall through to OP_IPUT_BOOLEAN_JUMBO_finish
12697
12698    /*
12699     * Currently:
12700     *  r0 holds resolved field
12701     *  r9 holds object
12702     */
12703.LOP_IPUT_BOOLEAN_JUMBO_finish:
12704    @bl      common_squeak1
12705    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
12706    FETCH(r1, 3)                        @ r1<- BBBB
12707    cmp     r9, #0                      @ check object for null
12708    GET_VREG(r0, r1)                    @ r0<- fp[BBBB]
12709    beq     common_errNullObject        @ object was null
12710    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
12711    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12712    @ no-op                             @ releasing store
12713    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
12714    GOTO_OPCODE(ip)                     @ jump to next instruction
12715
12716/* continuation for OP_IPUT_BYTE_JUMBO */
12717
12718    /*
12719     * Currently:
12720     *  r0 holds resolved field
12721     *  r9 holds object
12722     */
12723.LOP_IPUT_BYTE_JUMBO_resolved:
12724     cmp     r0, #0                     @ resolution unsuccessful?
12725     beq     common_exceptionThrown     @ yes, throw exception
12726     @ fall through to OP_IPUT_BYTE_JUMBO_finish
12727
12728    /*
12729     * Currently:
12730     *  r0 holds resolved field
12731     *  r9 holds object
12732     */
12733.LOP_IPUT_BYTE_JUMBO_finish:
12734    @bl      common_squeak2
12735    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
12736    FETCH(r1, 3)                        @ r1<- BBBB
12737    cmp     r9, #0                      @ check object for null
12738    GET_VREG(r0, r1)                    @ r0<- fp[BBBB]
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 (8/16/32 bits)<- r0
12744    GOTO_OPCODE(ip)                     @ jump to next instruction
12745
12746/* continuation for OP_IPUT_CHAR_JUMBO */
12747
12748    /*
12749     * Currently:
12750     *  r0 holds resolved field
12751     *  r9 holds object
12752     */
12753.LOP_IPUT_CHAR_JUMBO_resolved:
12754     cmp     r0, #0                     @ resolution unsuccessful?
12755     beq     common_exceptionThrown     @ yes, throw exception
12756     @ fall through to OP_IPUT_CHAR_JUMBO_finish
12757
12758    /*
12759     * Currently:
12760     *  r0 holds resolved field
12761     *  r9 holds object
12762     */
12763.LOP_IPUT_CHAR_JUMBO_finish:
12764    @bl      common_squeak3
12765    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
12766    FETCH(r1, 3)                        @ r1<- BBBB
12767    cmp     r9, #0                      @ check object for null
12768    GET_VREG(r0, r1)                    @ r0<- fp[BBBB]
12769    beq     common_errNullObject        @ object was null
12770    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
12771    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12772    @ no-op                             @ releasing store
12773    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
12774    GOTO_OPCODE(ip)                     @ jump to next instruction
12775
12776/* continuation for OP_IPUT_SHORT_JUMBO */
12777
12778    /*
12779     * Currently:
12780     *  r0 holds resolved field
12781     *  r9 holds object
12782     */
12783.LOP_IPUT_SHORT_JUMBO_resolved:
12784     cmp     r0, #0                     @ resolution unsuccessful?
12785     beq     common_exceptionThrown     @ yes, throw exception
12786     @ fall through to OP_IPUT_SHORT_JUMBO_finish
12787
12788    /*
12789     * Currently:
12790     *  r0 holds resolved field
12791     *  r9 holds object
12792     */
12793.LOP_IPUT_SHORT_JUMBO_finish:
12794    @bl      common_squeak4
12795    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
12796    FETCH(r1, 3)                        @ r1<- BBBB
12797    cmp     r9, #0                      @ check object for null
12798    GET_VREG(r0, r1)                    @ r0<- fp[BBBB]
12799    beq     common_errNullObject        @ object was null
12800    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
12801    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12802    @ no-op                             @ releasing store
12803    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
12804    GOTO_OPCODE(ip)                     @ jump to next instruction
12805
12806/* continuation for OP_SGET_JUMBO */
12807
12808    /*
12809     * Continuation if the field has not yet been resolved.
12810     *  r1: AAAAAAAA field ref
12811     */
12812.LOP_SGET_JUMBO_resolve:
12813    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
12814    EXPORT_PC()                         @ resolve() could throw, so export now
12815    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
12816    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
12817    cmp     r0, #0                      @ success?
12818    bne     .LOP_SGET_JUMBO_finish          @ yes, finish
12819    b       common_exceptionThrown      @ no, handle exception
12820
12821/* continuation for OP_SGET_WIDE_JUMBO */
12822
12823    /*
12824     * Continuation if the field has not yet been resolved.
12825     *  r1: BBBB field ref
12826     *
12827     * Returns StaticField pointer in r0.
12828     */
12829.LOP_SGET_WIDE_JUMBO_resolve:
12830    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
12831    EXPORT_PC()                         @ resolve() could throw, so export now
12832    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
12833    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
12834    cmp     r0, #0                      @ success?
12835    bne     .LOP_SGET_WIDE_JUMBO_finish          @ yes, finish
12836    b       common_exceptionThrown      @ no, handle exception
12837
12838/* continuation for OP_SGET_OBJECT_JUMBO */
12839
12840    /*
12841     * Continuation if the field has not yet been resolved.
12842     *  r1: AAAAAAAA field ref
12843     */
12844.LOP_SGET_OBJECT_JUMBO_resolve:
12845    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
12846    EXPORT_PC()                         @ resolve() could throw, so export now
12847    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
12848    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
12849    cmp     r0, #0                      @ success?
12850    bne     .LOP_SGET_OBJECT_JUMBO_finish          @ yes, finish
12851    b       common_exceptionThrown      @ no, handle exception
12852
12853/* continuation for OP_SGET_BOOLEAN_JUMBO */
12854
12855    /*
12856     * Continuation if the field has not yet been resolved.
12857     *  r1: AAAAAAAA field ref
12858     */
12859.LOP_SGET_BOOLEAN_JUMBO_resolve:
12860    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
12861    EXPORT_PC()                         @ resolve() could throw, so export now
12862    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
12863    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
12864    cmp     r0, #0                      @ success?
12865    bne     .LOP_SGET_BOOLEAN_JUMBO_finish          @ yes, finish
12866    b       common_exceptionThrown      @ no, handle exception
12867
12868/* continuation for OP_SGET_BYTE_JUMBO */
12869
12870    /*
12871     * Continuation if the field has not yet been resolved.
12872     *  r1: AAAAAAAA field ref
12873     */
12874.LOP_SGET_BYTE_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_BYTE_JUMBO_finish          @ yes, finish
12881    b       common_exceptionThrown      @ no, handle exception
12882
12883/* continuation for OP_SGET_CHAR_JUMBO */
12884
12885    /*
12886     * Continuation if the field has not yet been resolved.
12887     *  r1: AAAAAAAA field ref
12888     */
12889.LOP_SGET_CHAR_JUMBO_resolve:
12890    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
12891    EXPORT_PC()                         @ resolve() could throw, so export now
12892    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
12893    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
12894    cmp     r0, #0                      @ success?
12895    bne     .LOP_SGET_CHAR_JUMBO_finish          @ yes, finish
12896    b       common_exceptionThrown      @ no, handle exception
12897
12898/* continuation for OP_SGET_SHORT_JUMBO */
12899
12900    /*
12901     * Continuation if the field has not yet been resolved.
12902     *  r1: AAAAAAAA field ref
12903     */
12904.LOP_SGET_SHORT_JUMBO_resolve:
12905    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
12906    EXPORT_PC()                         @ resolve() could throw, so export now
12907    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
12908    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
12909    cmp     r0, #0                      @ success?
12910    bne     .LOP_SGET_SHORT_JUMBO_finish          @ yes, finish
12911    b       common_exceptionThrown      @ no, handle exception
12912
12913/* continuation for OP_SPUT_JUMBO */
12914
12915    /*
12916     * Continuation if the field has not yet been resolved.
12917     *  r1: AAAAAAAA field ref
12918     */
12919.LOP_SPUT_JUMBO_resolve:
12920    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
12921    EXPORT_PC()                         @ resolve() could throw, so export now
12922    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
12923    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
12924    cmp     r0, #0                      @ success?
12925    bne     .LOP_SPUT_JUMBO_finish          @ yes, finish
12926    b       common_exceptionThrown      @ no, handle exception
12927
12928/* continuation for OP_SPUT_WIDE_JUMBO */
12929
12930    /*
12931     * Continuation if the field has not yet been resolved.
12932     *  r1: BBBB field ref
12933     *  r9: &fp[AA]
12934     *
12935     * Returns StaticField pointer in r2.
12936     */
12937.LOP_SPUT_WIDE_JUMBO_resolve:
12938    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
12939    EXPORT_PC()                         @ resolve() could throw, so export now
12940    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
12941    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
12942    cmp     r0, #0                      @ success?
12943    mov     r2, r0                      @ copy to r2
12944    bne     .LOP_SPUT_WIDE_JUMBO_finish          @ yes, finish
12945    b       common_exceptionThrown      @ no, handle exception
12946
12947/* continuation for OP_SPUT_OBJECT_JUMBO */
12948
12949.LOP_SPUT_OBJECT_JUMBO_finish:   @ field ptr in r0
12950    FETCH(r2, 3)                        @ r2<- BBBB
12951    FETCH_ADVANCE_INST(4)               @ advance rPC, load rINST
12952    GET_VREG(r1, r2)                    @ r1<- fp[BBBB]
12953    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
12954    ldr     r9, [r0, #offField_clazz]   @ r9<- field->clazz
12955    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
12956    @ no-op                             @ releasing store
12957    str     r1, [r0, #offStaticField_value]  @ field<- vBBBB
12958    cmp     r1, #0                      @ stored a null object?
12959    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card based on obj head
12960    GOTO_OPCODE(ip)                     @ jump to next instruction
12961
12962/* continuation for OP_SPUT_BOOLEAN_JUMBO */
12963
12964    /*
12965     * Continuation if the field has not yet been resolved.
12966     *  r1: AAAAAAAA field ref
12967     */
12968.LOP_SPUT_BOOLEAN_JUMBO_resolve:
12969    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
12970    EXPORT_PC()                         @ resolve() could throw, so export now
12971    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
12972    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
12973    cmp     r0, #0                      @ success?
12974    bne     .LOP_SPUT_BOOLEAN_JUMBO_finish          @ yes, finish
12975    b       common_exceptionThrown      @ no, handle exception
12976
12977/* continuation for OP_SPUT_BYTE_JUMBO */
12978
12979    /*
12980     * Continuation if the field has not yet been resolved.
12981     *  r1: AAAAAAAA field ref
12982     */
12983.LOP_SPUT_BYTE_JUMBO_resolve:
12984    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
12985    EXPORT_PC()                         @ resolve() could throw, so export now
12986    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
12987    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
12988    cmp     r0, #0                      @ success?
12989    bne     .LOP_SPUT_BYTE_JUMBO_finish          @ yes, finish
12990    b       common_exceptionThrown      @ no, handle exception
12991
12992/* continuation for OP_SPUT_CHAR_JUMBO */
12993
12994    /*
12995     * Continuation if the field has not yet been resolved.
12996     *  r1: AAAAAAAA field ref
12997     */
12998.LOP_SPUT_CHAR_JUMBO_resolve:
12999    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
13000    EXPORT_PC()                         @ resolve() could throw, so export now
13001    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
13002    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
13003    cmp     r0, #0                      @ success?
13004    bne     .LOP_SPUT_CHAR_JUMBO_finish          @ yes, finish
13005    b       common_exceptionThrown      @ no, handle exception
13006
13007/* continuation for OP_SPUT_SHORT_JUMBO */
13008
13009    /*
13010     * Continuation if the field has not yet been resolved.
13011     *  r1: AAAAAAAA field ref
13012     */
13013.LOP_SPUT_SHORT_JUMBO_resolve:
13014    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
13015    EXPORT_PC()                         @ resolve() could throw, so export now
13016    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
13017    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
13018    cmp     r0, #0                      @ success?
13019    bne     .LOP_SPUT_SHORT_JUMBO_finish          @ yes, finish
13020    b       common_exceptionThrown      @ no, handle exception
13021
13022/* continuation for OP_INVOKE_VIRTUAL_JUMBO */
13023
13024    /*
13025     * At this point:
13026     *  r0 = resolved base method
13027     */
13028.LOP_INVOKE_VIRTUAL_JUMBO_continue:
13029    FETCH(r10, 4)                       @ r10<- CCCC
13030    GET_VREG(r1, r10)                   @ r1<- "this" ptr
13031    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
13032    cmp     r1, #0                      @ is "this" null?
13033    beq     common_errNullObject        @ null "this", throw exception
13034    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
13035    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
13036    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
13037    bl      common_invokeMethodJumbo    @ continue on
13038
13039/* continuation for OP_INVOKE_SUPER_JUMBO */
13040
13041    /*
13042     * At this point:
13043     *  r0 = resolved base method
13044     *  r9 = method->clazz
13045     */
13046.LOP_INVOKE_SUPER_JUMBO_continue:
13047    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
13048    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
13049    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
13050    EXPORT_PC()                         @ must export for invoke
13051    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
13052    bcs     .LOP_INVOKE_SUPER_JUMBO_nsm             @ method not present in superclass
13053    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
13054    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
13055    bl      common_invokeMethodJumbo    @ continue on
13056
13057.LOP_INVOKE_SUPER_JUMBO_resolve:
13058    mov     r0, r9                      @ r0<- method->clazz
13059    mov     r2, #METHOD_VIRTUAL         @ resolver method type
13060    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
13061    cmp     r0, #0                      @ got null?
13062    bne     .LOP_INVOKE_SUPER_JUMBO_continue        @ no, continue
13063    b       common_exceptionThrown      @ yes, handle exception
13064
13065    /*
13066     * Throw a NoSuchMethodError with the method name as the message.
13067     *  r0 = resolved base method
13068     */
13069.LOP_INVOKE_SUPER_JUMBO_nsm:
13070    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
13071    b       common_errNoSuchMethod
13072
13073/* continuation for OP_INVOKE_DIRECT_JUMBO */
13074
13075    /*
13076     * On entry:
13077     *  r1 = reference (CCCC)
13078     *  r10 = "this" register
13079     */
13080.LOP_INVOKE_DIRECT_JUMBO_resolve:
13081    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
13082    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
13083    mov     r2, #METHOD_DIRECT          @ resolver method type
13084    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
13085    cmp     r0, #0                      @ got null?
13086    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
13087    bne     .LOP_INVOKE_DIRECT_JUMBO_finish          @ no, continue
13088    b       common_exceptionThrown      @ yes, handle exception
13089
13090    .size   dvmAsmSisterStart, .-dvmAsmSisterStart
13091    .global dvmAsmSisterEnd
13092dvmAsmSisterEnd:
13093
13094/* File: armv5te/footer.S */
13095
13096/*
13097 * ===========================================================================
13098 *  Common subroutines and data
13099 * ===========================================================================
13100 */
13101
13102
13103
13104    .text
13105    .align  2
13106
13107#if defined(WITH_JIT)
13108#if defined(WITH_SELF_VERIFICATION)
13109    .global dvmJitToInterpPunt
13110dvmJitToInterpPunt:
13111    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
13112    mov    r2,#kSVSPunt                 @ r2<- interpreter entry point
13113    mov    r3, #0
13114    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
13115    b      jitSVShadowRunEnd            @ doesn't return
13116
13117    .global dvmJitToInterpSingleStep
13118dvmJitToInterpSingleStep:
13119    str    lr,[rGLUE,#offGlue_jitResumeNPC]
13120    str    r1,[rGLUE,#offGlue_jitResumeDPC]
13121    mov    r2,#kSVSSingleStep           @ r2<- interpreter entry point
13122    b      jitSVShadowRunEnd            @ doesn't return
13123
13124    .global dvmJitToInterpNoChainNoProfile
13125dvmJitToInterpNoChainNoProfile:
13126    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
13127    mov    r0,rPC                       @ pass our target PC
13128    mov    r2,#kSVSNoProfile            @ r2<- interpreter entry point
13129    mov    r3, #0                       @ 0 means !inJitCodeCache
13130    str    r3, [r10, #offThread_inJitCodeCache] @ back to the interp land
13131    b      jitSVShadowRunEnd            @ doesn't return
13132
13133    .global dvmJitToInterpTraceSelectNoChain
13134dvmJitToInterpTraceSelectNoChain:
13135    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
13136    mov    r0,rPC                       @ pass our target PC
13137    mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
13138    mov    r3, #0                       @ 0 means !inJitCodeCache
13139    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
13140    b      jitSVShadowRunEnd            @ doesn't return
13141
13142    .global dvmJitToInterpTraceSelect
13143dvmJitToInterpTraceSelect:
13144    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
13145    ldr    r0,[lr, #-1]                 @ pass our target PC
13146    mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
13147    mov    r3, #0                       @ 0 means !inJitCodeCache
13148    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
13149    b      jitSVShadowRunEnd            @ doesn't return
13150
13151    .global dvmJitToInterpBackwardBranch
13152dvmJitToInterpBackwardBranch:
13153    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
13154    ldr    r0,[lr, #-1]                 @ pass our target PC
13155    mov    r2,#kSVSBackwardBranch       @ r2<- interpreter entry point
13156    mov    r3, #0                       @ 0 means !inJitCodeCache
13157    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
13158    b      jitSVShadowRunEnd            @ doesn't return
13159
13160    .global dvmJitToInterpNormal
13161dvmJitToInterpNormal:
13162    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
13163    ldr    r0,[lr, #-1]                 @ pass our target PC
13164    mov    r2,#kSVSNormal               @ r2<- interpreter entry point
13165    mov    r3, #0                       @ 0 means !inJitCodeCache
13166    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
13167    b      jitSVShadowRunEnd            @ doesn't return
13168
13169    .global dvmJitToInterpNoChain
13170dvmJitToInterpNoChain:
13171    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
13172    mov    r0,rPC                       @ pass our target PC
13173    mov    r2,#kSVSNoChain              @ r2<- interpreter entry point
13174    mov    r3, #0                       @ 0 means !inJitCodeCache
13175    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
13176    b      jitSVShadowRunEnd            @ doesn't return
13177#else
13178/*
13179 * Return from the translation cache to the interpreter when the compiler is
13180 * having issues translating/executing a Dalvik instruction. We have to skip
13181 * the code cache lookup otherwise it is possible to indefinitely bouce
13182 * between the interpreter and the code cache if the instruction that fails
13183 * to be compiled happens to be at a trace start.
13184 */
13185    .global dvmJitToInterpPunt
13186dvmJitToInterpPunt:
13187    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
13188    mov    rPC, r0
13189#if defined(WITH_JIT_TUNING)
13190    mov    r0,lr
13191    bl     dvmBumpPunt;
13192#endif
13193    EXPORT_PC()
13194    mov    r0, #0
13195    str    r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land
13196    adrl   rIBASE, dvmAsmInstructionStart
13197    FETCH_INST()
13198    GET_INST_OPCODE(ip)
13199    GOTO_OPCODE(ip)
13200
13201/*
13202 * Return to the interpreter to handle a single instruction.
13203 * On entry:
13204 *    r0 <= PC
13205 *    r1 <= PC of resume instruction
13206 *    lr <= resume point in translation
13207 */
13208    .global dvmJitToInterpSingleStep
13209dvmJitToInterpSingleStep:
13210    str    lr,[rGLUE,#offGlue_jitResumeNPC]
13211    str    r1,[rGLUE,#offGlue_jitResumeDPC]
13212    mov    r1,#kInterpEntryInstr
13213    @ enum is 4 byte in aapcs-EABI
13214    str    r1, [rGLUE, #offGlue_entryPoint]
13215    mov    rPC,r0
13216    EXPORT_PC()
13217
13218    adrl   rIBASE, dvmAsmInstructionStart
13219    mov    r2,#kJitSingleStep     @ Ask for single step and then revert
13220    str    r2,[rGLUE,#offGlue_jitState]
13221    mov    r1,#1                  @ set changeInterp to bail to debug interp
13222    b      common_gotoBail
13223
13224/*
13225 * Return from the translation cache and immediately request
13226 * a translation for the exit target.  Commonly used for callees.
13227 */
13228    .global dvmJitToInterpTraceSelectNoChain
13229dvmJitToInterpTraceSelectNoChain:
13230#if defined(WITH_JIT_TUNING)
13231    bl     dvmBumpNoChain
13232#endif
13233    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
13234    mov    r0,rPC
13235    bl     dvmJitGetCodeAddr        @ Is there a translation?
13236    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
13237    mov    r1, rPC                  @ arg1 of translation may need this
13238    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
13239    cmp    r0,#0                    @ !0 means translation exists
13240    bxne   r0                       @ continue native execution if so
13241    b      2f                       @ branch over to use the interpreter
13242
13243/*
13244 * Return from the translation cache and immediately request
13245 * a translation for the exit target.  Commonly used following
13246 * invokes.
13247 */
13248    .global dvmJitToInterpTraceSelect
13249dvmJitToInterpTraceSelect:
13250    ldr    rPC,[lr, #-1]           @ get our target PC
13251    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
13252    add    rINST,lr,#-5            @ save start of chain branch
13253    add    rINST, #-4              @  .. which is 9 bytes back
13254    mov    r0,rPC
13255    bl     dvmJitGetCodeAddr       @ Is there a translation?
13256    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
13257    cmp    r0,#0
13258    beq    2f
13259    mov    r1,rINST
13260    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
13261    mov    r1, rPC                  @ arg1 of translation may need this
13262    mov    lr, #0                   @ in case target is HANDLER_INTERPRET
13263    cmp    r0,#0                    @ successful chain?
13264    bxne   r0                       @ continue native execution
13265    b      toInterpreter            @ didn't chain - resume with interpreter
13266
13267/* No translation, so request one if profiling isn't disabled*/
132682:
13269    adrl   rIBASE, dvmAsmInstructionStart
13270    GET_JIT_PROF_TABLE(r0)
13271    FETCH_INST()
13272    cmp    r0, #0
13273    movne  r2,#kJitTSelectRequestHot   @ ask for trace selection
13274    bne    common_selectTrace
13275    GET_INST_OPCODE(ip)
13276    GOTO_OPCODE(ip)
13277
13278/*
13279 * Return from the translation cache to the interpreter.
13280 * The return was done with a BLX from thumb mode, and
13281 * the following 32-bit word contains the target rPC value.
13282 * Note that lr (r14) will have its low-order bit set to denote
13283 * its thumb-mode origin.
13284 *
13285 * We'll need to stash our lr origin away, recover the new
13286 * target and then check to see if there is a translation available
13287 * for our new target.  If so, we do a translation chain and
13288 * go back to native execution.  Otherwise, it's back to the
13289 * interpreter (after treating this entry as a potential
13290 * trace start).
13291 */
13292    .global dvmJitToInterpNormal
13293dvmJitToInterpNormal:
13294    ldr    rPC,[lr, #-1]           @ get our target PC
13295    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
13296    add    rINST,lr,#-5            @ save start of chain branch
13297    add    rINST,#-4               @ .. which is 9 bytes back
13298#if defined(WITH_JIT_TUNING)
13299    bl     dvmBumpNormal
13300#endif
13301    mov    r0,rPC
13302    bl     dvmJitGetCodeAddr        @ Is there a translation?
13303    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
13304    cmp    r0,#0
13305    beq    toInterpreter            @ go if not, otherwise do chain
13306    mov    r1,rINST
13307    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
13308    mov    r1, rPC                  @ arg1 of translation may need this
13309    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
13310    cmp    r0,#0                    @ successful chain?
13311    bxne   r0                       @ continue native execution
13312    b      toInterpreter            @ didn't chain - resume with interpreter
13313
13314/*
13315 * Return from the translation cache to the interpreter to do method invocation.
13316 * Check if translation exists for the callee, but don't chain to it.
13317 */
13318    .global dvmJitToInterpNoChainNoProfile
13319dvmJitToInterpNoChainNoProfile:
13320#if defined(WITH_JIT_TUNING)
13321    bl     dvmBumpNoChain
13322#endif
13323    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
13324    mov    r0,rPC
13325    bl     dvmJitGetCodeAddr        @ Is there a translation?
13326    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
13327    mov    r1, rPC                  @ arg1 of translation may need this
13328    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
13329    cmp    r0,#0
13330    bxne   r0                       @ continue native execution if so
13331    EXPORT_PC()
13332    adrl   rIBASE, dvmAsmInstructionStart
13333    FETCH_INST()
13334    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
13335    GOTO_OPCODE(ip)                     @ jump to next instruction
13336
13337/*
13338 * Return from the translation cache to the interpreter to do method invocation.
13339 * Check if translation exists for the callee, but don't chain to it.
13340 */
13341    .global dvmJitToInterpNoChain
13342dvmJitToInterpNoChain:
13343#if defined(WITH_JIT_TUNING)
13344    bl     dvmBumpNoChain
13345#endif
13346    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
13347    mov    r0,rPC
13348    bl     dvmJitGetCodeAddr        @ Is there a translation?
13349    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
13350    mov    r1, rPC                  @ arg1 of translation may need this
13351    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
13352    cmp    r0,#0
13353    bxne   r0                       @ continue native execution if so
13354#endif
13355
13356/*
13357 * No translation, restore interpreter regs and start interpreting.
13358 * rGLUE & rFP were preserved in the translated code, and rPC has
13359 * already been restored by the time we get here.  We'll need to set
13360 * up rIBASE & rINST, and load the address of the JitTable into r0.
13361 */
13362toInterpreter:
13363    EXPORT_PC()
13364    adrl   rIBASE, dvmAsmInstructionStart
13365    FETCH_INST()
13366    GET_JIT_PROF_TABLE(r0)
13367    @ NOTE: intended fallthrough
13368
13369/*
13370 * Common code to update potential trace start counter, and initiate
13371 * a trace-build if appropriate.  On entry, rPC should point to the
13372 * next instruction to execute, and rINST should be already loaded with
13373 * the next opcode word, and r0 holds a pointer to the jit profile
13374 * table (pJitProfTable).
13375 */
13376common_testUpdateProfile:
13377    cmp     r0,#0
13378    GET_INST_OPCODE(ip)
13379    GOTO_OPCODE_IFEQ(ip)       @ if not profiling, fallthrough otherwise */
13380
13381common_updateProfile:
13382    eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
13383    lsl     r3,r3,#(32 - JIT_PROF_SIZE_LOG_2)          @ shift out excess bits
13384    ldrb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter
13385    GET_INST_OPCODE(ip)
13386    subs    r1,r1,#1           @ decrement counter
13387    strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it
13388    GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
13389
13390/*
13391 * Here, we switch to the debug interpreter to request
13392 * trace selection.  First, though, check to see if there
13393 * is already a native translation in place (and, if so,
13394 * jump to it now).
13395 */
13396    GET_JIT_THRESHOLD(r1)
13397    ldr     r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
13398    strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter
13399    EXPORT_PC()
13400    mov     r0,rPC
13401    bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
13402    str     r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
13403    mov     r1, rPC                     @ arg1 of translation may need this
13404    mov     lr, #0                      @  in case target is HANDLER_INTERPRET
13405    cmp     r0,#0
13406#if !defined(WITH_SELF_VERIFICATION)
13407    bxne    r0                          @ jump to the translation
13408    mov     r2,#kJitTSelectRequest      @ ask for trace selection
13409    @ fall-through to common_selectTrace
13410#else
13411    moveq   r2,#kJitTSelectRequest      @ ask for trace selection
13412    beq     common_selectTrace
13413    /*
13414     * At this point, we have a target translation.  However, if
13415     * that translation is actually the interpret-only pseudo-translation
13416     * we want to treat it the same as no translation.
13417     */
13418    mov     r10, r0                     @ save target
13419    bl      dvmCompilerGetInterpretTemplate
13420    cmp     r0, r10                     @ special case?
13421    bne     jitSVShadowRunStart         @ set up self verification shadow space
13422    @ Need to clear the inJitCodeCache flag
13423    ldr    r10, [rGLUE, #offGlue_self]  @ r10 <- glue->self
13424    mov    r3, #0                       @ 0 means not in the JIT code cache
13425    str    r3, [r10, #offThread_inJitCodeCache] @ back to the interp land
13426    GET_INST_OPCODE(ip)
13427    GOTO_OPCODE(ip)
13428    /* no return */
13429#endif
13430
13431/*
13432 * On entry:
13433 *  r2 is jit state, e.g. kJitTSelectRequest or kJitTSelectRequestHot
13434 */
13435common_selectTrace:
13436    str     r2,[rGLUE,#offGlue_jitState]
13437    mov     r2,#kInterpEntryInstr       @ normal entry reason
13438    str     r2,[rGLUE,#offGlue_entryPoint]
13439    mov     r1,#1                       @ set changeInterp
13440    b       common_gotoBail
13441
13442#if defined(WITH_SELF_VERIFICATION)
13443/*
13444 * Save PC and registers to shadow memory for self verification mode
13445 * before jumping to native translation.
13446 * On entry:
13447 *    rPC, rFP, rGLUE: the values that they should contain
13448 *    r10: the address of the target translation.
13449 */
13450jitSVShadowRunStart:
13451    mov     r0,rPC                      @ r0<- program counter
13452    mov     r1,rFP                      @ r1<- frame pointer
13453    mov     r2,rGLUE                    @ r2<- InterpState pointer
13454    mov     r3,r10                      @ r3<- target translation
13455    bl      dvmSelfVerificationSaveState @ save registers to shadow space
13456    ldr     rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
13457    add     rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
13458    bx      r10                         @ jump to the translation
13459
13460/*
13461 * Restore PC, registers, and interpState to original values
13462 * before jumping back to the interpreter.
13463 */
13464jitSVShadowRunEnd:
13465    mov    r1,rFP                        @ pass ending fp
13466    bl     dvmSelfVerificationRestoreState @ restore pc and fp values
13467    ldr    rPC,[r0,#offShadowSpace_startPC] @ restore PC
13468    ldr    rFP,[r0,#offShadowSpace_fp]   @ restore FP
13469    ldr    rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
13470    ldr    r1,[r0,#offShadowSpace_svState] @ get self verification state
13471    cmp    r1,#0                         @ check for punt condition
13472    beq    1f
13473    mov    r2,#kJitSelfVerification      @ ask for self verification
13474    str    r2,[rGLUE,#offGlue_jitState]
13475    mov    r2,#kInterpEntryInstr         @ normal entry reason
13476    str    r2,[rGLUE,#offGlue_entryPoint]
13477    mov    r1,#1                         @ set changeInterp
13478    b      common_gotoBail
13479
134801:                                       @ exit to interpreter without check
13481    EXPORT_PC()
13482    adrl   rIBASE, dvmAsmInstructionStart
13483    FETCH_INST()
13484    GET_INST_OPCODE(ip)
13485    GOTO_OPCODE(ip)
13486#endif
13487
13488#endif
13489
13490/*
13491 * Common code when a backward branch is taken.
13492 *
13493 * TODO: we could avoid a branch by just setting r0 and falling through
13494 * into the common_periodicChecks code, and having a test on r0 at the
13495 * end determine if we should return to the caller or update & branch to
13496 * the next instr.
13497 *
13498 * On entry:
13499 *  r9 is PC adjustment *in bytes*
13500 */
13501common_backwardBranch:
13502    mov     r0, #kInterpEntryInstr
13503    bl      common_periodicChecks
13504#if defined(WITH_JIT)
13505    GET_JIT_PROF_TABLE(r0)
13506    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
13507    cmp     r0,#0
13508    bne     common_updateProfile
13509    GET_INST_OPCODE(ip)
13510    GOTO_OPCODE(ip)
13511#else
13512    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
13513    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
13514    GOTO_OPCODE(ip)                     @ jump to next instruction
13515#endif
13516
13517
13518/*
13519 * Need to see if the thread needs to be suspended or debugger/profiler
13520 * activity has begun.  If so, we suspend the thread or side-exit to
13521 * the debug interpreter as appropriate.
13522 *
13523 * The common case is no activity on any of these, so we want to figure
13524 * that out quickly.  If something is up, we can then sort out what.
13525 *
13526 * We want to be fast if the VM was built without debugger or profiler
13527 * support, but we also need to recognize that the system is usually
13528 * shipped with both of these enabled.
13529 *
13530 * TODO: reduce this so we're just checking a single location.
13531 *
13532 * On entry:
13533 *  r0 is reentry type, e.g. kInterpEntryInstr (for debugger/profiling)
13534 *  r9 is trampoline PC adjustment *in bytes*
13535 */
13536common_periodicChecks:
13537    ldr     r1, [rGLUE, #offGlue_pInterpBreak] @ r3<- &interpBreak
13538    /* speculatively load address of thread-specific suspend count */
13539    ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
13540    ldr     r1, [r1]                                @ r1<- interpBreak
13541    /* speculatively load thread-specific suspend count */
13542    ldr     ip, [r3]                    @ ip<- suspendCount (int)
13543    cmp     r1, #0                                  @ anything unusual?
13544    bxeq    lr                                      @ return if not
13545    /*
13546     * One or more interesting events have happened.  Figure out what.
13547     *
13548     * r0 still holds the reentry type.
13549     */
13550    cmp     ip, #0                      @ want suspend?
13551    beq     3f                          @ no, must be something else
13552
13553    stmfd   sp!, {r0, lr}               @ preserve r0 and lr
13554#if defined(WITH_JIT)
13555    /*
13556     * Refresh the Jit's cached copy of profile table pointer.  This pointer
13557     * doubles as the Jit's on/off switch.
13558     */
13559    ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ r3<-&gDvmJit.pJitProfTable
13560    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
13561    ldr     r3, [r3] @ r3 <- pJitProfTable
13562    EXPORT_PC()                         @ need for precise GC
13563    str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch
13564#else
13565    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
13566    EXPORT_PC()                         @ need for precise GC
13567#endif
13568    bl      dvmCheckSuspendPending      @ do full check, suspend if necessary
13569    ldmfd   sp!, {r0, lr}               @ restore r0 and lr
13570
13571    /*
13572     * Reload the interpBreak flags - they may have changed while we
13573     * were suspended.
13574     */
13575    ldr     r1, [rGLUE, #offGlue_pInterpBreak]   @ r1<- &interpBreak
13576    ldr     r1, [r1]                    @ r1<- interpBreak
135773:
13578    /*
13579     * TODO: this code is too fragile.  Need a general mechanism
13580     * to identify what actions to take by submode.  Some profiling modes
13581     * (instruction count) need to single-step, while method tracing
13582     * may not.  Debugging with breakpoints can run unfettered, but
13583     * source-level single-stepping requires Dalvik singlestepping.
13584     * GC may require a one-shot action and then full-speed resumption.
13585     */
13586    ands    r1, #(kSubModeDebuggerActive | kSubModeEmulatorTrace | kSubModeInstCounting)
13587    bxeq    lr                          @ nothing to do, return
13588
13589    @ debugger/profiler enabled, bail out; glue->entryPoint was set above
13590    str     r0, [rGLUE, #offGlue_entryPoint]    @ store r0, need for debug/prof
13591    add     rPC, rPC, r9                @ update rPC
13592    mov     r1, #1                      @ "want switch" = true
13593    b       common_gotoBail             @ side exit
13594
13595
13596/*
13597 * The equivalent of "goto bail", this calls through the "bail handler".
13598 *
13599 * State registers will be saved to the "glue" area before bailing.
13600 *
13601 * On entry:
13602 *  r1 is "bool changeInterp", indicating if we want to switch to the
13603 *     other interpreter or just bail all the way out
13604 */
13605common_gotoBail:
13606    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
13607    mov     r0, rGLUE                   @ r0<- glue ptr
13608    b       dvmMterpStdBail             @ call(glue, changeInterp)
13609
13610    @add     r1, r1, #1                  @ using (boolean+1)
13611    @add     r0, rGLUE, #offGlue_jmpBuf  @ r0<- &glue->jmpBuf
13612    @bl      _longjmp                    @ does not return
13613    @bl      common_abort
13614
13615
13616/*
13617 * Common code for jumbo method invocation.
13618 * NOTE: this adjusts rPC to account for the difference in instruction width.
13619 * As a result, the savedPc in the stack frame will not be wholly accurate. So
13620 * long as that is only used for source file line number calculations, we're
13621 * okay.
13622 *
13623 * On entry:
13624 *  r0 is "Method* methodToCall", the method we're trying to call
13625 */
13626common_invokeMethodJumbo:
13627.LinvokeNewJumbo:
13628    @ prepare to copy args to "outs" area of current frame
13629    add     rPC, rPC, #4                @ adjust pc to make return consistent
13630    FETCH(r2, 1)                        @ r2<- BBBB (arg count)
13631    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
13632    cmp     r2, #0                      @ no args?
13633    beq     .LinvokeArgsDone            @ if no args, skip the rest
13634    FETCH(r1, 2)                        @ r1<- CCCC
13635    b       .LinvokeRangeArgs           @ handle args like invoke range
13636
13637/*
13638 * Common code for method invocation with range.
13639 *
13640 * On entry:
13641 *  r0 is "Method* methodToCall", the method we're trying to call
13642 */
13643common_invokeMethodRange:
13644.LinvokeNewRange:
13645    @ prepare to copy args to "outs" area of current frame
13646    movs    r2, rINST, lsr #8           @ r2<- AA (arg count) -- test for zero
13647    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
13648    beq     .LinvokeArgsDone            @ if no args, skip the rest
13649    FETCH(r1, 2)                        @ r1<- CCCC
13650
13651.LinvokeRangeArgs:
13652    @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
13653    @ (very few methods have > 10 args; could unroll for common cases)
13654    add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
13655    sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
136561:  ldr     r1, [r3], #4                @ val = *fp++
13657    subs    r2, r2, #1                  @ count--
13658    str     r1, [r10], #4               @ *outs++ = val
13659    bne     1b                          @ ...while count != 0
13660    b       .LinvokeArgsDone
13661
13662/*
13663 * Common code for method invocation without range.
13664 *
13665 * On entry:
13666 *  r0 is "Method* methodToCall", the method we're trying to call
13667 */
13668common_invokeMethodNoRange:
13669.LinvokeNewNoRange:
13670    @ prepare to copy args to "outs" area of current frame
13671    movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
13672    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
13673    FETCH(r1, 2)                        @ r1<- GFED (load here to hide latency)
13674    beq     .LinvokeArgsDone
13675
13676    @ r0=methodToCall, r1=GFED, r2=count, r10=outs
13677.LinvokeNonRange:
13678    rsb     r2, r2, #5                  @ r2<- 5-r2
13679    add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
13680    bl      common_abort                @ (skipped due to ARM prefetch)
136815:  and     ip, rINST, #0x0f00          @ isolate A
13682    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vA (shift right 8, left 2)
13683    mov     r0, r0                      @ nop
13684    str     r2, [r10, #-4]!             @ *--outs = vA
136854:  and     ip, r1, #0xf000             @ isolate G
13686    ldr     r2, [rFP, ip, lsr #10]      @ r2<- vG (shift right 12, left 2)
13687    mov     r0, r0                      @ nop
13688    str     r2, [r10, #-4]!             @ *--outs = vG
136893:  and     ip, r1, #0x0f00             @ isolate F
13690    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vF
13691    mov     r0, r0                      @ nop
13692    str     r2, [r10, #-4]!             @ *--outs = vF
136932:  and     ip, r1, #0x00f0             @ isolate E
13694    ldr     r2, [rFP, ip, lsr #2]       @ r2<- vE
13695    mov     r0, r0                      @ nop
13696    str     r2, [r10, #-4]!             @ *--outs = vE
136971:  and     ip, r1, #0x000f             @ isolate D
13698    ldr     r2, [rFP, ip, lsl #2]       @ r2<- vD
13699    mov     r0, r0                      @ nop
13700    str     r2, [r10, #-4]!             @ *--outs = vD
137010:  @ fall through to .LinvokeArgsDone
13702
13703.LinvokeArgsDone: @ r0=methodToCall
13704    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
13705    ldrh    r3, [r0, #offMethod_outsSize]  @ r3<- methodToCall->outsSize
13706    ldr     r2, [r0, #offMethod_insns]  @ r2<- method->insns
13707    ldr     rINST, [r0, #offMethod_clazz]  @ rINST<- method->clazz
13708    @ find space for the new stack frame, check for overflow
13709    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
13710    sub     r1, r1, r9, lsl #2          @ r1<- newFp (old savearea - regsSize)
13711    SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
13712@    bl      common_dumpRegs
13713    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
13714    sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
13715    cmp     r3, r9                      @ bottom < interpStackEnd?
13716    ldr     lr, [rGLUE, #offGlue_pInterpBreak]
13717    ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
13718    blo     .LstackOverflow             @ yes, this frame will overflow stack
13719
13720    @ set up newSaveArea
13721    ldr     lr, [lr]                    @ lr<- active submodes
13722#ifdef EASY_GDB
13723    SAVEAREA_FROM_FP(ip, rFP)           @ ip<- stack save area
13724    str     ip, [r10, #offStackSaveArea_prevSave]
13725#endif
13726    str     rFP, [r10, #offStackSaveArea_prevFrame]
13727    str     rPC, [r10, #offStackSaveArea_savedPc]
13728#if defined(WITH_JIT)
13729    mov     r9, #0
13730    str     r9, [r10, #offStackSaveArea_returnAddr]
13731#endif
13732    ands    lr, #kSubModeMethodTrace    @ method tracing?
13733    beq     1f                          @ skip if not
13734    stmfd   sp!, {r0-r3}                @ preserve r0-r3
13735    mov     r1, r6
13736    @ r0=methodToCall, r1=rGlue
13737    bl      dvmFastMethodTraceEnter
13738    ldmfd   sp!, {r0-r3}                @ restore r0-r3
137391:
13740    str     r0, [r10, #offStackSaveArea_method]
13741    tst     r3, #ACC_NATIVE
13742    bne     .LinvokeNative
13743
13744    /*
13745    stmfd   sp!, {r0-r3}
13746    bl      common_printNewline
13747    mov     r0, rFP
13748    mov     r1, #0
13749    bl      dvmDumpFp
13750    ldmfd   sp!, {r0-r3}
13751    stmfd   sp!, {r0-r3}
13752    mov     r0, r1
13753    mov     r1, r10
13754    bl      dvmDumpFp
13755    bl      common_printNewline
13756    ldmfd   sp!, {r0-r3}
13757    */
13758
13759    ldrh    r9, [r2]                        @ r9 <- load INST from new PC
13760    ldr     r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
13761    mov     rPC, r2                         @ publish new rPC
13762    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
13763
13764    @ Update "glue" values for the new method
13765    @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
13766    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
13767    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
13768#if defined(WITH_JIT)
13769    GET_JIT_PROF_TABLE(r0)
13770    mov     rFP, r1                         @ fp = newFp
13771    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
13772    mov     rINST, r9                       @ publish new rINST
13773    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
13774    cmp     r0,#0
13775    bne     common_updateProfile
13776    GOTO_OPCODE(ip)                         @ jump to next instruction
13777#else
13778    mov     rFP, r1                         @ fp = newFp
13779    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
13780    mov     rINST, r9                       @ publish new rINST
13781    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
13782    GOTO_OPCODE(ip)                         @ jump to next instruction
13783#endif
13784
13785.LinvokeNative:
13786    @ Prep for the native call
13787    @ r0=methodToCall, r1=newFp, r10=newSaveArea
13788    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
13789    ldr     lr, [rGLUE, #offGlue_pInterpBreak]
13790    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
13791    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
13792    str     r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
13793    ldr     lr, [lr]                    @ lr<- active submodes
13794    mov     r9, r3                      @ r9<- glue->self (preserve)
13795
13796    mov     r2, r0                      @ r2<- methodToCall
13797    mov     r0, r1                      @ r0<- newFp (points to args)
13798    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
13799
13800#ifdef ASSIST_DEBUGGER
13801    /* insert fake function header to help gdb find the stack frame */
13802    b       .Lskip
13803    .type   dalvik_mterp, %function
13804dalvik_mterp:
13805    .fnstart
13806    MTERP_ENTRY1
13807    MTERP_ENTRY2
13808.Lskip:
13809#endif
13810
13811    ands    lr, #kSubModeMethodTrace    @ method tracing?
13812    beq     110f                        @ hop if not
13813    @ r2=JNIMethod, r6=rGLUE
13814    stmfd   sp!, {r2,r6}
13815
13816    mov     lr, pc                      @ set return addr
13817    ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
13818
13819    @ r0=JNIMethod, r1=rGLUE
13820    ldmfd   sp!, {r0-r1}
13821    bl      dvmFastNativeMethodTraceExit
13822    @ r2=JNIMethod, r6=rGLUE
13823    stmfd   sp!, {r2,r6}
13824    b       220f
13825110:
13826    mov     lr, pc                      @ set return addr
13827    ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
13828220:
13829#if defined(WITH_JIT)
13830    ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status
13831#endif
13832
13833    @ native return; r9=self, r10=newSaveArea
13834    @ equivalent to dvmPopJniLocals
13835    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
13836    ldr     r1, [r9, #offThread_exception] @ check for exception
13837#if defined(WITH_JIT)
13838    ldr     r3, [r3]                    @ r3 <- gDvmJit.pProfTable
13839#endif
13840    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
13841    cmp     r1, #0                      @ null?
13842    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
13843#if defined(WITH_JIT)
13844    str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch
13845#endif
13846    bne     common_exceptionThrown      @ no, handle exception
13847
13848    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
13849    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
13850    GOTO_OPCODE(ip)                     @ jump to next instruction
13851
13852.LstackOverflow:    @ r0=methodToCall
13853    mov     r1, r0                      @ r1<- methodToCall
13854    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
13855    bl      dvmHandleStackOverflow
13856    b       common_exceptionThrown
13857#ifdef ASSIST_DEBUGGER
13858    .fnend
13859#endif
13860
13861
13862    /*
13863     * Common code for method invocation, calling through "glue code".
13864     *
13865     * TODO: now that we have range and non-range invoke handlers, this
13866     *       needs to be split into two.  Maybe just create entry points
13867     *       that set r9 and jump here?
13868     *
13869     * On entry:
13870     *  r0 is "Method* methodToCall", the method we're trying to call
13871     *  r9 is "bool methodCallRange", indicating if this is a /range variant
13872     */
13873     .if    0
13874.LinvokeOld:
13875    sub     sp, sp, #8                  @ space for args + pad
13876    FETCH(ip, 2)                        @ ip<- FEDC or CCCC
13877    mov     r2, r0                      @ A2<- methodToCall
13878    mov     r0, rGLUE                   @ A0<- glue
13879    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
13880    mov     r1, r9                      @ A1<- methodCallRange
13881    mov     r3, rINST, lsr #8           @ A3<- AA
13882    str     ip, [sp, #0]                @ A4<- ip
13883    bl      dvmMterp_invokeMethod       @ call the C invokeMethod
13884    add     sp, sp, #8                  @ remove arg area
13885    b       common_resumeAfterGlueCall  @ continue to next instruction
13886    .endif
13887
13888
13889
13890/*
13891 * Common code for handling a return instruction.
13892 *
13893 * This does not return.
13894 */
13895common_returnFromMethod:
13896.LreturnNew:
13897    mov     r0, #kInterpEntryReturn
13898    mov     r9, #0
13899    bl      common_periodicChecks
13900
13901    ldr     lr, [rGLUE, #offGlue_pInterpBreak]
13902    SAVEAREA_FROM_FP(r0, rFP)
13903    ldr     lr, [lr]                    @ lr<- active submodes
13904    ldr     r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
13905    ands    lr, #kSubModeMethodTrace    @ method tracing?
13906    beq     333f
13907    stmfd   sp!, {r0-r3}                @ preserve r0-r3
13908    mov     r0, r6
13909    @ r0=rGlue
13910    bl      dvmFastJavaMethodTraceExit
13911    ldmfd   sp!, {r0-r3}                @ restore r0-r3
13912333:
13913    ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
13914    ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
13915    ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
13916                                        @ r2<- method we're returning to
13917    cmp     r2, #0                      @ is this a break frame?
13918#if defined(WORKAROUND_CORTEX_A9_745320)
13919    /* Don't use conditional loads if the HW defect exists */
13920    beq     101f
13921    ldr     r10, [r2, #offMethod_clazz] @ r10<- method->clazz
13922101:
13923#else
13924    ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
13925#endif
13926    mov     r1, #0                      @ "want switch" = false
13927    beq     common_gotoBail             @ break frame, bail out completely
13928
13929    PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
13930    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
13931    ldr     r1, [r10, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
13932    str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
13933#if defined(WITH_JIT)
13934    ldr     r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr
13935    mov     rPC, r9                     @ publish new rPC
13936    str     r1, [rGLUE, #offGlue_methodClassDex]
13937    str     r10, [r3, #offThread_inJitCodeCache]  @ may return to JIT'ed land
13938    cmp     r10, #0                      @ caller is compiled code
13939    blxne   r10
13940    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
13941    GOTO_OPCODE(ip)                     @ jump to next instruction
13942#else
13943    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
13944    mov     rPC, r9                     @ publish new rPC
13945    str     r1, [rGLUE, #offGlue_methodClassDex]
13946    GOTO_OPCODE(ip)                     @ jump to next instruction
13947#endif
13948
13949    /*
13950     * Return handling, calls through "glue code".
13951     */
13952     .if    0
13953.LreturnOld:
13954    SAVE_PC_FP_TO_GLUE()                @ export state
13955    mov     r0, rGLUE                   @ arg to function
13956    bl      dvmMterp_returnFromMethod
13957    b       common_resumeAfterGlueCall
13958    .endif
13959
13960
13961/*
13962 * Somebody has thrown an exception.  Handle it.
13963 *
13964 * If the exception processing code returns to us (instead of falling
13965 * out of the interpreter), continue with whatever the next instruction
13966 * now happens to be.
13967 *
13968 * This does not return.
13969 */
13970     .global dvmMterpCommonExceptionThrown
13971dvmMterpCommonExceptionThrown:
13972common_exceptionThrown:
13973.LexceptionNew:
13974    mov     r0, #kInterpEntryThrow
13975    mov     r9, #0
13976    bl      common_periodicChecks
13977
13978    ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
13979    ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
13980    mov     r1, r10                     @ r1<- self
13981    mov     r0, r9                      @ r0<- exception
13982    bl      dvmAddTrackedAlloc          @ don't let the exception be GCed
13983    mov     r3, #0                      @ r3<- NULL
13984    str     r3, [r10, #offThread_exception] @ self->exception = NULL
13985
13986    /* set up args and a local for "&fp" */
13987    /* (str sp, [sp, #-4]!  would be perfect here, but is discouraged) */
13988    str     rFP, [sp, #-4]!             @ *--sp = fp
13989    mov     ip, sp                      @ ip<- &fp
13990    mov     r3, #0                      @ r3<- false
13991    str     ip, [sp, #-4]!              @ *--sp = &fp
13992    ldr     r1, [rGLUE, #offGlue_method] @ r1<- glue->method
13993    mov     r0, r10                     @ r0<- self
13994    ldr     r1, [r1, #offMethod_insns]  @ r1<- method->insns
13995    mov     r2, r9                      @ r2<- exception
13996    sub     r1, rPC, r1                 @ r1<- pc - method->insns
13997    mov     r1, r1, asr #1              @ r1<- offset in code units
13998
13999    /* call, r0 gets catchRelPc (a code-unit offset) */
14000    bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
14001
14002    /* fix earlier stack overflow if necessary; may trash rFP */
14003    ldrb    r1, [r10, #offThread_stackOverflowed]
14004    cmp     r1, #0                      @ did we overflow earlier?
14005    beq     1f                          @ no, skip ahead
14006    mov     rFP, r0                     @ save relPc result in rFP
14007    mov     r0, r10                     @ r0<- self
14008    mov     r1, r9                      @ r1<- exception
14009    bl      dvmCleanupStackOverflow     @ call(self)
14010    mov     r0, rFP                     @ restore result
140111:
14012
14013    /* update frame pointer and check result from dvmFindCatchBlock */
14014    ldr     rFP, [sp, #4]               @ retrieve the updated rFP
14015    cmp     r0, #0                      @ is catchRelPc < 0?
14016    add     sp, sp, #8                  @ restore stack
14017    bmi     .LnotCaughtLocally
14018
14019    /* adjust locals to match self->curFrame and updated PC */
14020    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
14021    ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
14022    str     r1, [rGLUE, #offGlue_method]    @ glue->method = new method
14023    ldr     r2, [r1, #offMethod_clazz]      @ r2<- method->clazz
14024    ldr     r3, [r1, #offMethod_insns]      @ r3<- method->insns
14025    ldr     r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
14026    add     rPC, r3, r0, asl #1             @ rPC<- method->insns + catchRelPc
14027    str     r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
14028
14029    /* release the tracked alloc on the exception */
14030    mov     r0, r9                      @ r0<- exception
14031    mov     r1, r10                     @ r1<- self
14032    bl      dvmReleaseTrackedAlloc      @ release the exception
14033
14034    /* restore the exception if the handler wants it */
14035    FETCH_INST()                        @ load rINST from rPC
14036    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
14037    cmp     ip, #OP_MOVE_EXCEPTION      @ is it "move-exception"?
14038    streq   r9, [r10, #offThread_exception] @ yes, restore the exception
14039    GOTO_OPCODE(ip)                     @ jump to next instruction
14040
14041.LnotCaughtLocally: @ r9=exception, r10=self
14042    /* fix stack overflow if necessary */
14043    ldrb    r1, [r10, #offThread_stackOverflowed]
14044    cmp     r1, #0                      @ did we overflow earlier?
14045    movne   r0, r10                     @ if yes: r0<- self
14046    movne   r1, r9                      @ if yes: r1<- exception
14047    blne    dvmCleanupStackOverflow     @ if yes: call(self)
14048
14049    @ may want to show "not caught locally" debug messages here
14050#if DVM_SHOW_EXCEPTION >= 2
14051    /* call __android_log_print(prio, tag, format, ...) */
14052    /* "Exception %s from %s:%d not caught locally" */
14053    @ dvmLineNumFromPC(method, pc - method->insns)
14054    ldr     r0, [rGLUE, #offGlue_method]
14055    ldr     r1, [r0, #offMethod_insns]
14056    sub     r1, rPC, r1
14057    asr     r1, r1, #1
14058    bl      dvmLineNumFromPC
14059    str     r0, [sp, #-4]!
14060    @ dvmGetMethodSourceFile(method)
14061    ldr     r0, [rGLUE, #offGlue_method]
14062    bl      dvmGetMethodSourceFile
14063    str     r0, [sp, #-4]!
14064    @ exception->clazz->descriptor
14065    ldr     r3, [r9, #offObject_clazz]
14066    ldr     r3, [r3, #offClassObject_descriptor]
14067    @
14068    ldr     r2, strExceptionNotCaughtLocally
14069    ldr     r1, strLogTag
14070    mov     r0, #3                      @ LOG_DEBUG
14071    bl      __android_log_print
14072#endif
14073    str     r9, [r10, #offThread_exception] @ restore exception
14074    mov     r0, r9                      @ r0<- exception
14075    mov     r1, r10                     @ r1<- self
14076    bl      dvmReleaseTrackedAlloc      @ release the exception
14077    mov     r1, #0                      @ "want switch" = false
14078    b       common_gotoBail             @ bail out
14079
14080
14081    /*
14082     * Exception handling, calls through "glue code".
14083     */
14084    .if     0
14085.LexceptionOld:
14086    SAVE_PC_FP_TO_GLUE()                @ export state
14087    mov     r0, rGLUE                   @ arg to function
14088    bl      dvmMterp_exceptionThrown
14089    b       common_resumeAfterGlueCall
14090    .endif
14091
14092
14093/*
14094 * After returning from a "glued" function, pull out the updated
14095 * values and start executing at the next instruction.
14096 */
14097common_resumeAfterGlueCall:
14098    LOAD_PC_FP_FROM_GLUE()              @ pull rPC and rFP out of glue
14099    FETCH_INST()                        @ load rINST from rPC
14100    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
14101    GOTO_OPCODE(ip)                     @ jump to next instruction
14102
14103/*
14104 * Invalid array index. Note that our calling convention is strange; we use r1
14105 * and r3 because those just happen to be the registers all our callers are
14106 * using. We shuffle them here before calling the C function.
14107 * r1: index
14108 * r3: size
14109 */
14110common_errArrayIndex:
14111    EXPORT_PC()
14112    mov     r0, r1
14113    mov     r1, r3
14114    bl      dvmThrowAIOOBE
14115    b       common_exceptionThrown
14116
14117/*
14118 * Integer divide or mod by zero.
14119 */
14120common_errDivideByZero:
14121    EXPORT_PC()
14122    ldr     r0, strArithmeticException
14123    ldr     r1, strDivideByZero
14124    bl      dvmThrowException
14125    b       common_exceptionThrown
14126
14127/*
14128 * Attempt to allocate an array with a negative size.
14129 */
14130common_errNegativeArraySize:
14131    EXPORT_PC()
14132    ldr     r0, strNegativeArraySizeException
14133    mov     r1, #0
14134    bl      dvmThrowException
14135    b       common_exceptionThrown
14136
14137/*
14138 * Invocation of a non-existent method.
14139 */
14140common_errNoSuchMethod:
14141    EXPORT_PC()
14142    ldr     r0, strNoSuchMethodError
14143    mov     r1, #0
14144    bl      dvmThrowException
14145    b       common_exceptionThrown
14146
14147/*
14148 * We encountered a null object when we weren't expecting one.  We
14149 * export the PC, throw a NullPointerException, and goto the exception
14150 * processing code.
14151 */
14152common_errNullObject:
14153    EXPORT_PC()
14154    ldr     r0, strNullPointerException
14155    mov     r1, #0
14156    bl      dvmThrowException
14157    b       common_exceptionThrown
14158
14159/*
14160 * For debugging, cause an immediate fault.  The source address will
14161 * be in lr (use a bl instruction to jump here).
14162 */
14163common_abort:
14164    ldr     pc, .LdeadFood
14165.LdeadFood:
14166    .word   0xdeadf00d
14167
14168/*
14169 * Spit out a "we were here", preserving all registers.  (The attempt
14170 * to save ip won't work, but we need to save an even number of
14171 * registers for EABI 64-bit stack alignment.)
14172 */
14173    .macro  SQUEAK num
14174common_squeak\num:
14175    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
14176    ldr     r0, strSqueak
14177    mov     r1, #\num
14178    bl      printf
14179    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
14180    bx      lr
14181    .endm
14182
14183    SQUEAK  0
14184    SQUEAK  1
14185    SQUEAK  2
14186    SQUEAK  3
14187    SQUEAK  4
14188    SQUEAK  5
14189
14190/*
14191 * Spit out the number in r0, preserving registers.
14192 */
14193common_printNum:
14194    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
14195    mov     r1, r0
14196    ldr     r0, strSqueak
14197    bl      printf
14198    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
14199    bx      lr
14200
14201/*
14202 * Print a newline, preserving registers.
14203 */
14204common_printNewline:
14205    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
14206    ldr     r0, strNewline
14207    bl      printf
14208    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
14209    bx      lr
14210
14211    /*
14212     * Print the 32-bit quantity in r0 as a hex value, preserving registers.
14213     */
14214common_printHex:
14215    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
14216    mov     r1, r0
14217    ldr     r0, strPrintHex
14218    bl      printf
14219    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
14220    bx      lr
14221
14222/*
14223 * Print the 64-bit quantity in r0-r1, preserving registers.
14224 */
14225common_printLong:
14226    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
14227    mov     r3, r1
14228    mov     r2, r0
14229    ldr     r0, strPrintLong
14230    bl      printf
14231    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
14232    bx      lr
14233
14234/*
14235 * Print full method info.  Pass the Method* in r0.  Preserves regs.
14236 */
14237common_printMethod:
14238    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
14239    bl      dvmMterpPrintMethod
14240    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
14241    bx      lr
14242
14243/*
14244 * Call a C helper function that dumps regs and possibly some
14245 * additional info.  Requires the C function to be compiled in.
14246 */
14247    .if     0
14248common_dumpRegs:
14249    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
14250    bl      dvmMterpDumpArmRegs
14251    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
14252    bx      lr
14253    .endif
14254
14255#if 0
14256/*
14257 * Experiment on VFP mode.
14258 *
14259 * uint32_t setFPSCR(uint32_t val, uint32_t mask)
14260 *
14261 * Updates the bits specified by "mask", setting them to the values in "val".
14262 */
14263setFPSCR:
14264    and     r0, r0, r1                  @ make sure no stray bits are set
14265    fmrx    r2, fpscr                   @ get VFP reg
14266    mvn     r1, r1                      @ bit-invert mask
14267    and     r2, r2, r1                  @ clear masked bits
14268    orr     r2, r2, r0                  @ set specified bits
14269    fmxr    fpscr, r2                   @ set VFP reg
14270    mov     r0, r2                      @ return new value
14271    bx      lr
14272
14273    .align  2
14274    .global dvmConfigureFP
14275    .type   dvmConfigureFP, %function
14276dvmConfigureFP:
14277    stmfd   sp!, {ip, lr}
14278    /* 0x03000000 sets DN/FZ */
14279    /* 0x00009f00 clears the six exception enable flags */
14280    bl      common_squeak0
14281    mov     r0, #0x03000000             @ r0<- 0x03000000
14282    add     r1, r0, #0x9f00             @ r1<- 0x03009f00
14283    bl      setFPSCR
14284    ldmfd   sp!, {ip, pc}
14285#endif
14286
14287
14288/*
14289 * String references, must be close to the code that uses them.
14290 */
14291    .align  2
14292strArithmeticException:
14293    .word   .LstrArithmeticException
14294strDivideByZero:
14295    .word   .LstrDivideByZero
14296strNegativeArraySizeException:
14297    .word   .LstrNegativeArraySizeException
14298strNoSuchMethodError:
14299    .word   .LstrNoSuchMethodError
14300strNullPointerException:
14301    .word   .LstrNullPointerException
14302
14303strLogTag:
14304    .word   .LstrLogTag
14305strExceptionNotCaughtLocally:
14306    .word   .LstrExceptionNotCaughtLocally
14307
14308strNewline:
14309    .word   .LstrNewline
14310strSqueak:
14311    .word   .LstrSqueak
14312strPrintHex:
14313    .word   .LstrPrintHex
14314strPrintLong:
14315    .word   .LstrPrintLong
14316
14317/*
14318 * Zero-terminated ASCII string data.
14319 *
14320 * On ARM we have two choices: do like gcc does, and LDR from a .word
14321 * with the address, or use an ADR pseudo-op to get the address
14322 * directly.  ADR saves 4 bytes and an indirection, but it's using a
14323 * PC-relative addressing mode and hence has a limited range, which
14324 * makes it not work well with mergeable string sections.
14325 */
14326    .section .rodata.str1.4,"aMS",%progbits,1
14327
14328.LstrBadEntryPoint:
14329    .asciz  "Bad entry point %d\n"
14330.LstrArithmeticException:
14331    .asciz  "Ljava/lang/ArithmeticException;"
14332.LstrDivideByZero:
14333    .asciz  "divide by zero"
14334.LstrFilledNewArrayNotImpl:
14335    .asciz  "filled-new-array only implemented for objects and 'int'"
14336.LstrInternalError:
14337    .asciz  "Ljava/lang/InternalError;"
14338.LstrInstantiationError:
14339    .asciz  "Ljava/lang/InstantiationError;"
14340.LstrNegativeArraySizeException:
14341    .asciz  "Ljava/lang/NegativeArraySizeException;"
14342.LstrNoSuchMethodError:
14343    .asciz  "Ljava/lang/NoSuchMethodError;"
14344.LstrNullPointerException:
14345    .asciz  "Ljava/lang/NullPointerException;"
14346
14347.LstrLogTag:
14348    .asciz  "mterp"
14349.LstrExceptionNotCaughtLocally:
14350    .asciz  "Exception %s from %s:%d not caught locally\n"
14351
14352.LstrNewline:
14353    .asciz  "\n"
14354.LstrSqueak:
14355    .asciz  "<%d>"
14356.LstrPrintHex:
14357    .asciz  "<0x%x>"
14358.LstrPrintLong:
14359    .asciz  "<%lld>"
14360
14361