InterpAsm-armv5te.S revision 99409883d9c4c0ffb49b070ce307bb33a9dfe9f1
1/*
2 * This file was generated automatically by gen-mterp.py for 'armv5te'.
3 *
4 * --> DO NOT EDIT <--
5 */
6
7/* File: armv5te/header.S */
8/*
9 * Copyright (C) 2008 The Android Open Source Project
10 *
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 *      http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
22 */
23/*
24 * ARMv5 definitions and declarations.
25 */
26
27/*
28ARM EABI general notes:
29
30r0-r3 hold first 4 args to a method; they are not preserved across method calls
31r4-r8 are available for general use
32r9 is given special treatment in some situations, but not for us
33r10 (sl) seems to be generally available
34r11 (fp) is used by gcc (unless -fomit-frame-pointer is set)
35r12 (ip) is scratch -- not preserved across method calls
36r13 (sp) should be managed carefully in case a signal arrives
37r14 (lr) must be preserved
38r15 (pc) can be tinkered with directly
39
40r0 holds returns of <= 4 bytes
41r0-r1 hold returns of 8 bytes, low word in r0
42
43Callee must save/restore r4+ (except r12) if it modifies them.
44
45Stack is "full descending".  Only the arguments that don't fit in the first 4
46registers are placed on the stack.  "sp" points at the first stacked argument
47(i.e. the 5th arg).
48
49VFP: single-precision results in s0, double-precision results in d0.
50
51In the EABI, "sp" must be 64-bit aligned on entry to a function, and any
5264-bit quantities (long long, double) must be 64-bit aligned.
53*/
54
55/*
56Mterp and ARM notes:
57
58The following registers have fixed assignments:
59
60  reg nick      purpose
61  r4  rPC       interpreted program counter, used for fetching instructions
62  r5  rFP       interpreted frame pointer, used for accessing locals and args
63  r6  rGLUE     MterpGlue pointer
64  r7  rIBASE    interpreted instruction base pointer, used for computed goto
65  r8  rINST     first 16-bit code unit of current instruction
66
67Macros are provided for common operations.  Each macro MUST emit only
68one instruction to make instruction-counting easier.  They MUST NOT alter
69unspecified registers or condition codes.
70*/
71
72/* single-purpose registers, given names for clarity */
73#define rPC     r4
74#define rFP     r5
75#define rGLUE   r6
76#define rIBASE  r7
77#define rINST   r8
78
79/* save/restore the PC and/or FP from the glue struct */
80#define LOAD_PC_FROM_GLUE()     ldr     rPC, [rGLUE, #offGlue_pc]
81#define SAVE_PC_TO_GLUE()       str     rPC, [rGLUE, #offGlue_pc]
82#define LOAD_FP_FROM_GLUE()     ldr     rFP, [rGLUE, #offGlue_fp]
83#define SAVE_FP_TO_GLUE()       str     rFP, [rGLUE, #offGlue_fp]
84#define LOAD_PC_FP_FROM_GLUE()  ldmia   rGLUE, {rPC, rFP}
85#define SAVE_PC_FP_TO_GLUE()    stmia   rGLUE, {rPC, rFP}
86
87/*
88 * "export" the PC to the stack frame, f/b/o future exception objects.  Must
89 * be done *before* something calls dvmThrowException.
90 *
91 * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e.
92 * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc)
93 *
94 * It's okay to do this more than once.
95 */
96#define EXPORT_PC() \
97    str     rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)]
98
99/*
100 * Given a frame pointer, find the stack save area.
101 *
102 * In C this is "((StackSaveArea*)(_fp) -1)".
103 */
104#define SAVEAREA_FROM_FP(_reg, _fpreg) \
105    sub     _reg, _fpreg, #sizeofStackSaveArea
106
107/*
108 * Fetch the next instruction from rPC into rINST.  Does not advance rPC.
109 */
110#define FETCH_INST()            ldrh    rINST, [rPC]
111
112/*
113 * Fetch the next instruction from the specified offset.  Advances rPC
114 * to point to the next instruction.  "_count" is in 16-bit code units.
115 *
116 * Because of the limited size of immediate constants on ARM, this is only
117 * suitable for small forward movements (i.e. don't try to implement "goto"
118 * with this).
119 *
120 * This must come AFTER anything that can throw an exception, or the
121 * exception catch may miss.  (This also implies that it must come after
122 * EXPORT_PC().)
123 */
124#define FETCH_ADVANCE_INST(_count) ldrh    rINST, [rPC, #(_count*2)]!
125
126/*
127 * Fetch the next instruction from an offset specified by _reg.  Updates
128 * rPC to point to the next instruction.  "_reg" must specify the distance
129 * in bytes, *not* 16-bit code units, and may be a signed value.
130 *
131 * We want to write "ldrh rINST, [rPC, _reg, lsl #2]!", but some of the
132 * bits that hold the shift distance are used for the half/byte/sign flags.
133 * In some cases we can pre-double _reg for free, so we require a byte offset
134 * here.
135 */
136#define FETCH_ADVANCE_INST_RB(_reg) ldrh    rINST, [rPC, _reg]!
137
138/*
139 * Fetch a half-word code unit from an offset past the current PC.  The
140 * "_count" value is in 16-bit code units.  Does not advance rPC.
141 *
142 * The "_S" variant works the same but treats the value as signed.
143 */
144#define FETCH(_reg, _count)     ldrh    _reg, [rPC, #(_count*2)]
145#define FETCH_S(_reg, _count)   ldrsh   _reg, [rPC, #(_count*2)]
146
147/*
148 * Fetch one byte from an offset past the current PC.  Pass in the same
149 * "_count" as you would for FETCH, and an additional 0/1 indicating which
150 * byte of the halfword you want (lo/hi).
151 */
152#define FETCH_B(_reg, _count, _byte) ldrb     _reg, [rPC, #(_count*2+_byte)]
153
154/*
155 * Put the instruction's opcode field into the specified register.
156 */
157#define GET_INST_OPCODE(_reg)   and     _reg, rINST, #255
158
159/*
160 * Begin executing the opcode in _reg.  Because this only jumps within the
161 * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork.
162 */
163#define GOTO_OPCODE(_reg)       add     pc, rIBASE, _reg, lsl #6
164
165/*
166 * Get/set the 32-bit value from a Dalvik register.
167 */
168#define GET_VREG(_reg, _vreg)   ldr     _reg, [rFP, _vreg, lsl #2]
169#define SET_VREG(_reg, _vreg)   str     _reg, [rFP, _vreg, lsl #2]
170
171/*
172 * This is a #include, not a %include, because we want the C pre-processor
173 * to expand the macros into assembler assignment statements.
174 */
175#include "../common/asm-constants.h"
176
177
178/* File: armv5te/platform.S */
179/*
180 * ===========================================================================
181 *  CPU-version-specific defines
182 * ===========================================================================
183 */
184
185/*
186 * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5.  Essentially a
187 * one-way branch.
188 *
189 * May modify IP.  Does not modify LR.
190 */
191.macro  LDR_PC source
192    ldr     pc, \source
193.endm
194
195/*
196 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5.
197 * Jump to subroutine.
198 *
199 * May modify IP and LR.
200 */
201.macro  LDR_PC_LR source
202    mov     lr, pc
203    ldr     pc, \source
204.endm
205
206/*
207 * Macro for "LDMFD SP!, {...regs...,PC}".
208 *
209 * May modify IP and LR.
210 */
211.macro  LDMFD_PC regs
212    ldmfd   sp!, {\regs,pc}
213.endm
214
215
216/* File: armv5te/entry.S */
217/*
218 * Copyright (C) 2008 The Android Open Source Project
219 *
220 * Licensed under the Apache License, Version 2.0 (the "License");
221 * you may not use this file except in compliance with the License.
222 * You may obtain a copy of the License at
223 *
224 *      http://www.apache.org/licenses/LICENSE-2.0
225 *
226 * Unless required by applicable law or agreed to in writing, software
227 * distributed under the License is distributed on an "AS IS" BASIS,
228 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
229 * See the License for the specific language governing permissions and
230 * limitations under the License.
231 */
232/*
233 * Interpreter entry point.
234 */
235
236/*
237 * We don't have formal stack frames, so gdb scans upward in the code
238 * to find the start of the function (a label with the %function type),
239 * and then looks at the next few instructions to figure out what
240 * got pushed onto the stack.  From this it figures out how to restore
241 * the registers, including PC, for the previous stack frame.  If gdb
242 * sees a non-function label, it stops scanning, so either we need to
243 * have nothing but assembler-local labels between the entry point and
244 * the break, or we need to fake it out.
245 *
246 * When this is defined, we add some stuff to make gdb less confused.
247 */
248#define ASSIST_DEBUGGER 1
249
250    .text
251    .align  2
252    .global dvmMterpStdRun
253    .type   dvmMterpStdRun, %function
254
255/*
256 * On entry:
257 *  r0  MterpGlue* glue
258 *
259 * This function returns a boolean "changeInterp" value.  The return comes
260 * via a call to dvmMterpStdBail().
261 */
262dvmMterpStdRun:
263#define MTERP_ENTRY1 \
264    .save {r4-r10,fp,lr}; \
265    stmfd   sp!, {r4-r10,fp,lr}         @ save 9 regs
266#define MTERP_ENTRY2 \
267    .pad    #4; \
268    sub     sp, sp, #4                  @ align 64
269
270    .fnstart
271    MTERP_ENTRY1
272    MTERP_ENTRY2
273
274    /* save stack pointer, add magic word for debuggerd */
275    str     sp, [r0, #offGlue_bailPtr]  @ save SP for eventual return
276
277    /* set up "named" registers, figure out entry point */
278    mov     rGLUE, r0                   @ set rGLUE
279    ldrb    r1, [r0, #offGlue_entryPoint]   @ InterpEntry enum is char
280    LOAD_PC_FP_FROM_GLUE()              @ load rPC and rFP from "glue"
281    adr     rIBASE, dvmAsmInstructionStart  @ set rIBASE
282    cmp     r1, #kInterpEntryInstr      @ usual case?
283    bne     .Lnot_instr                 @ no, handle it
284
285    /* start executing the instruction at rPC */
286    FETCH_INST()                        @ load rINST from rPC
287    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
288    GOTO_OPCODE(ip)                     @ jump to next instruction
289
290.Lnot_instr:
291    cmp     r1, #kInterpEntryReturn     @ were we returning from a method?
292    beq     common_returnFromMethod
293
294.Lnot_return:
295    cmp     r1, #kInterpEntryThrow      @ were we throwing an exception?
296    beq     common_exceptionThrown
297
298.Lbad_arg:
299    ldr     r0, strBadEntryPoint
300    @ r1 holds value of entryPoint
301    bl      printf
302    bl      dvmAbort
303    .fnend
304
305
306    .global dvmMterpStdBail
307    .type   dvmMterpStdBail, %function
308
309/*
310 * Restore the stack pointer and PC from the save point established on entry.
311 * This is essentially the same as a longjmp, but should be cheaper.  The
312 * last instruction causes us to return to whoever called dvmMterpStdRun.
313 *
314 * We pushed some registers on the stack in dvmMterpStdRun, then saved
315 * SP and LR.  Here we restore SP, restore the registers, and then restore
316 * LR to PC.
317 *
318 * On entry:
319 *  r0  MterpGlue* glue
320 *  r1  bool changeInterp
321 */
322dvmMterpStdBail:
323    ldr     sp, [r0, #offGlue_bailPtr]      @ sp<- saved SP
324    mov     r0, r1                          @ return the changeInterp value
325    add     sp, sp, #4                      @ un-align 64
326    LDMFD_PC "r4-r10,fp"                    @ restore 9 regs and return
327
328
329/*
330 * String references.
331 */
332strBadEntryPoint:
333    .word   .LstrBadEntryPoint
334
335
336
337    .global dvmAsmInstructionStart
338    .type   dvmAsmInstructionStart, %function
339dvmAsmInstructionStart = .L_OP_NOP
340    .text
341
342/* ------------------------------ */
343    .balign 64
344.L_OP_NOP: /* 0x00 */
345/* File: armv5te/OP_NOP.S */
346    FETCH_ADVANCE_INST(1)               @ advance to next instr, load rINST
347    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
348    GOTO_OPCODE(ip)                     @ execute it
349
350#ifdef ASSIST_DEBUGGER
351    /* insert fake function header to help gdb find the stack frame */
352    .type   dalvik_inst, %function
353dalvik_inst:
354    .fnstart
355    MTERP_ENTRY1
356    MTERP_ENTRY2
357    .fnend
358#endif
359
360
361/* ------------------------------ */
362    .balign 64
363.L_OP_MOVE: /* 0x01 */
364/* File: armv5te/OP_MOVE.S */
365    /* for move, move-object, long-to-int */
366    /* op vA, vB */
367    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
368    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
369    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
370    GET_VREG(r2, r1)                    @ r2<- fp[B]
371    and     r0, r0, #15
372    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
373    SET_VREG(r2, r0)                    @ fp[A]<- r2
374    GOTO_OPCODE(ip)                     @ execute next instruction
375
376
377/* ------------------------------ */
378    .balign 64
379.L_OP_MOVE_FROM16: /* 0x02 */
380/* File: armv5te/OP_MOVE_FROM16.S */
381    /* for: move/from16, move-object/from16 */
382    /* op vAA, vBBBB */
383    FETCH(r1, 1)                        @ r1<- BBBB
384    mov     r0, rINST, lsr #8           @ r0<- AA
385    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
386    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
387    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
388    SET_VREG(r2, r0)                    @ fp[AA]<- r2
389    GOTO_OPCODE(ip)                     @ jump to next instruction
390
391
392/* ------------------------------ */
393    .balign 64
394.L_OP_MOVE_16: /* 0x03 */
395/* File: armv5te/OP_MOVE_16.S */
396    /* for: move/16, move-object/16 */
397    /* op vAAAA, vBBBB */
398    FETCH(r1, 2)                        @ r1<- BBBB
399    FETCH(r0, 1)                        @ r0<- AAAA
400    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
401    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
402    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
403    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
404    GOTO_OPCODE(ip)                     @ jump to next instruction
405
406
407/* ------------------------------ */
408    .balign 64
409.L_OP_MOVE_WIDE: /* 0x04 */
410/* File: armv5te/OP_MOVE_WIDE.S */
411    /* move-wide vA, vB */
412    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
413    mov     r2, rINST, lsr #8           @ r2<- A(+)
414    mov     r3, rINST, lsr #12          @ r3<- B
415    and     r2, r2, #15
416    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
417    add     r2, rFP, r2, lsl #2         @ r2<- &fp[A]
418    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[B]
419    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
420    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
421    stmia   r2, {r0-r1}                 @ fp[A]<- r0/r1
422    GOTO_OPCODE(ip)                     @ jump to next instruction
423
424
425/* ------------------------------ */
426    .balign 64
427.L_OP_MOVE_WIDE_FROM16: /* 0x05 */
428/* File: armv5te/OP_MOVE_WIDE_FROM16.S */
429    /* move-wide/from16 vAA, vBBBB */
430    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
431    FETCH(r3, 1)                        @ r3<- BBBB
432    mov     r2, rINST, lsr #8           @ r2<- AA
433    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
434    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
435    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
436    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
437    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
438    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
439    GOTO_OPCODE(ip)                     @ jump to next instruction
440
441
442/* ------------------------------ */
443    .balign 64
444.L_OP_MOVE_WIDE_16: /* 0x06 */
445/* File: armv5te/OP_MOVE_WIDE_16.S */
446    /* move-wide/16 vAAAA, vBBBB */
447    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
448    FETCH(r3, 2)                        @ r3<- BBBB
449    FETCH(r2, 1)                        @ r2<- AAAA
450    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
451    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AAAA]
452    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
453    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
454    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
455    stmia   r2, {r0-r1}                 @ fp[AAAA]<- r0/r1
456    GOTO_OPCODE(ip)                     @ jump to next instruction
457
458
459/* ------------------------------ */
460    .balign 64
461.L_OP_MOVE_OBJECT: /* 0x07 */
462/* File: armv5te/OP_MOVE_OBJECT.S */
463/* File: armv5te/OP_MOVE.S */
464    /* for move, move-object, long-to-int */
465    /* op vA, vB */
466    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
467    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
468    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
469    GET_VREG(r2, r1)                    @ r2<- fp[B]
470    and     r0, r0, #15
471    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
472    SET_VREG(r2, r0)                    @ fp[A]<- r2
473    GOTO_OPCODE(ip)                     @ execute next instruction
474
475
476
477/* ------------------------------ */
478    .balign 64
479.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
480/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */
481/* File: armv5te/OP_MOVE_FROM16.S */
482    /* for: move/from16, move-object/from16 */
483    /* op vAA, vBBBB */
484    FETCH(r1, 1)                        @ r1<- BBBB
485    mov     r0, rINST, lsr #8           @ r0<- AA
486    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
487    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
488    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
489    SET_VREG(r2, r0)                    @ fp[AA]<- r2
490    GOTO_OPCODE(ip)                     @ jump to next instruction
491
492
493
494/* ------------------------------ */
495    .balign 64
496.L_OP_MOVE_OBJECT_16: /* 0x09 */
497/* File: armv5te/OP_MOVE_OBJECT_16.S */
498/* File: armv5te/OP_MOVE_16.S */
499    /* for: move/16, move-object/16 */
500    /* op vAAAA, vBBBB */
501    FETCH(r1, 2)                        @ r1<- BBBB
502    FETCH(r0, 1)                        @ r0<- AAAA
503    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
504    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
505    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
506    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
507    GOTO_OPCODE(ip)                     @ jump to next instruction
508
509
510
511/* ------------------------------ */
512    .balign 64
513.L_OP_MOVE_RESULT: /* 0x0a */
514/* File: armv5te/OP_MOVE_RESULT.S */
515    /* for: move-result, move-result-object */
516    /* op vAA */
517    mov     r2, rINST, lsr #8           @ r2<- AA
518    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
519    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
520    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
521    SET_VREG(r0, r2)                    @ fp[AA]<- r0
522    GOTO_OPCODE(ip)                     @ jump to next instruction
523
524
525/* ------------------------------ */
526    .balign 64
527.L_OP_MOVE_RESULT_WIDE: /* 0x0b */
528/* File: armv5te/OP_MOVE_RESULT_WIDE.S */
529    /* move-result-wide vAA */
530    mov     r2, rINST, lsr #8           @ r2<- AA
531    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
532    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
533    ldmia   r3, {r0-r1}                 @ r0/r1<- retval.j
534    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
535    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
536    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
537    GOTO_OPCODE(ip)                     @ jump to next instruction
538
539
540/* ------------------------------ */
541    .balign 64
542.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
543/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */
544/* File: armv5te/OP_MOVE_RESULT.S */
545    /* for: move-result, move-result-object */
546    /* op vAA */
547    mov     r2, rINST, lsr #8           @ r2<- AA
548    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
549    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
550    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
551    SET_VREG(r0, r2)                    @ fp[AA]<- r0
552    GOTO_OPCODE(ip)                     @ jump to next instruction
553
554
555
556/* ------------------------------ */
557    .balign 64
558.L_OP_MOVE_EXCEPTION: /* 0x0d */
559/* File: armv5te/OP_MOVE_EXCEPTION.S */
560    /* move-exception vAA */
561    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
562    mov     r2, rINST, lsr #8           @ r2<- AA
563    ldr     r3, [r0, #offThread_exception]  @ r3<- dvmGetException bypass
564    mov     r1, #0                      @ r1<- 0
565    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
566    SET_VREG(r3, r2)                    @ fp[AA]<- exception obj
567    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
568    str     r1, [r0, #offThread_exception]  @ dvmClearException bypass
569    GOTO_OPCODE(ip)                     @ jump to next instruction
570
571
572/* ------------------------------ */
573    .balign 64
574.L_OP_RETURN_VOID: /* 0x0e */
575/* File: armv5te/OP_RETURN_VOID.S */
576    b       common_returnFromMethod
577
578
579/* ------------------------------ */
580    .balign 64
581.L_OP_RETURN: /* 0x0f */
582/* File: armv5te/OP_RETURN.S */
583    /*
584     * Return a 32-bit value.  Copies the return value into the "glue"
585     * structure, then jumps to the return handler.
586     *
587     * for: return, return-object
588     */
589    /* op vAA */
590    mov     r2, rINST, lsr #8           @ r2<- AA
591    GET_VREG(r0, r2)                    @ r0<- vAA
592    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
593    b       common_returnFromMethod
594
595
596/* ------------------------------ */
597    .balign 64
598.L_OP_RETURN_WIDE: /* 0x10 */
599/* File: armv5te/OP_RETURN_WIDE.S */
600    /*
601     * Return a 64-bit value.  Copies the return value into the "glue"
602     * structure, then jumps to the return handler.
603     */
604    /* return-wide vAA */
605    mov     r2, rINST, lsr #8           @ r2<- AA
606    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
607    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
608    ldmia   r2, {r0-r1}                 @ r0/r1 <- vAA/vAA+1
609    stmia   r3, {r0-r1}                 @ retval<- r0/r1
610    b       common_returnFromMethod
611
612
613/* ------------------------------ */
614    .balign 64
615.L_OP_RETURN_OBJECT: /* 0x11 */
616/* File: armv5te/OP_RETURN_OBJECT.S */
617/* File: armv5te/OP_RETURN.S */
618    /*
619     * Return a 32-bit value.  Copies the return value into the "glue"
620     * structure, then jumps to the return handler.
621     *
622     * for: return, return-object
623     */
624    /* op vAA */
625    mov     r2, rINST, lsr #8           @ r2<- AA
626    GET_VREG(r0, r2)                    @ r0<- vAA
627    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
628    b       common_returnFromMethod
629
630
631
632/* ------------------------------ */
633    .balign 64
634.L_OP_CONST_4: /* 0x12 */
635/* File: armv5te/OP_CONST_4.S */
636    /* const/4 vA, #+B */
637    mov     r1, rINST, lsl #16          @ r1<- Bxxx0000
638    mov     r0, rINST, lsr #8           @ r0<- A+
639    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
640    mov     r1, r1, asr #28             @ r1<- sssssssB (sign-extended)
641    and     r0, r0, #15
642    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
643    SET_VREG(r1, r0)                    @ fp[A]<- r1
644    GOTO_OPCODE(ip)                     @ execute next instruction
645
646
647/* ------------------------------ */
648    .balign 64
649.L_OP_CONST_16: /* 0x13 */
650/* File: armv5te/OP_CONST_16.S */
651    /* const/16 vAA, #+BBBB */
652    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
653    mov     r3, rINST, lsr #8           @ r3<- AA
654    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
655    SET_VREG(r0, r3)                    @ vAA<- r0
656    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
657    GOTO_OPCODE(ip)                     @ jump to next instruction
658
659
660/* ------------------------------ */
661    .balign 64
662.L_OP_CONST: /* 0x14 */
663/* File: armv5te/OP_CONST.S */
664    /* const vAA, #+BBBBbbbb */
665    mov     r3, rINST, lsr #8           @ r3<- AA
666    FETCH(r0, 1)                        @ r0<- bbbb (low)
667    FETCH(r1, 2)                        @ r1<- BBBB (high)
668    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
669    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
670    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
671    SET_VREG(r0, r3)                    @ vAA<- r0
672    GOTO_OPCODE(ip)                     @ jump to next instruction
673
674
675/* ------------------------------ */
676    .balign 64
677.L_OP_CONST_HIGH16: /* 0x15 */
678/* File: armv5te/OP_CONST_HIGH16.S */
679    /* const/high16 vAA, #+BBBB0000 */
680    FETCH(r0, 1)                        @ r0<- 0000BBBB (zero-extended)
681    mov     r3, rINST, lsr #8           @ r3<- AA
682    mov     r0, r0, lsl #16             @ r0<- BBBB0000
683    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
684    SET_VREG(r0, r3)                    @ vAA<- r0
685    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
686    GOTO_OPCODE(ip)                     @ jump to next instruction
687
688
689/* ------------------------------ */
690    .balign 64
691.L_OP_CONST_WIDE_16: /* 0x16 */
692/* File: armv5te/OP_CONST_WIDE_16.S */
693    /* const-wide/16 vAA, #+BBBB */
694    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
695    mov     r3, rINST, lsr #8           @ r3<- AA
696    mov     r1, r0, asr #31             @ r1<- ssssssss
697    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
698    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
699    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
700    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
701    GOTO_OPCODE(ip)                     @ jump to next instruction
702
703
704/* ------------------------------ */
705    .balign 64
706.L_OP_CONST_WIDE_32: /* 0x17 */
707/* File: armv5te/OP_CONST_WIDE_32.S */
708    /* const-wide/32 vAA, #+BBBBbbbb */
709    FETCH(r0, 1)                        @ r0<- 0000bbbb (low)
710    mov     r3, rINST, lsr #8           @ r3<- AA
711    FETCH_S(r2, 2)                      @ r2<- ssssBBBB (high)
712    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
713    orr     r0, r0, r2, lsl #16         @ r0<- BBBBbbbb
714    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
715    mov     r1, r0, asr #31             @ r1<- ssssssss
716    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
717    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
718    GOTO_OPCODE(ip)                     @ jump to next instruction
719
720
721/* ------------------------------ */
722    .balign 64
723.L_OP_CONST_WIDE: /* 0x18 */
724/* File: armv5te/OP_CONST_WIDE.S */
725    /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
726    FETCH(r0, 1)                        @ r0<- bbbb (low)
727    FETCH(r1, 2)                        @ r1<- BBBB (low middle)
728    FETCH(r2, 3)                        @ r2<- hhhh (high middle)
729    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb (low word)
730    FETCH(r3, 4)                        @ r3<- HHHH (high)
731    mov     r9, rINST, lsr #8           @ r9<- AA
732    orr     r1, r2, r3, lsl #16         @ r1<- HHHHhhhh (high word)
733    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
734    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
735    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
736    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
737    GOTO_OPCODE(ip)                     @ jump to next instruction
738
739
740/* ------------------------------ */
741    .balign 64
742.L_OP_CONST_WIDE_HIGH16: /* 0x19 */
743/* File: armv5te/OP_CONST_WIDE_HIGH16.S */
744    /* const-wide/high16 vAA, #+BBBB000000000000 */
745    FETCH(r1, 1)                        @ r1<- 0000BBBB (zero-extended)
746    mov     r3, rINST, lsr #8           @ r3<- AA
747    mov     r0, #0                      @ r0<- 00000000
748    mov     r1, r1, lsl #16             @ r1<- BBBB0000
749    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
750    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
751    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
752    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
753    GOTO_OPCODE(ip)                     @ jump to next instruction
754
755
756/* ------------------------------ */
757    .balign 64
758.L_OP_CONST_STRING: /* 0x1a */
759/* File: armv5te/OP_CONST_STRING.S */
760    /* const/string vAA, String@BBBB */
761    FETCH(r1, 1)                        @ r1<- BBBB
762    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
763    mov     r9, rINST, lsr #8           @ r9<- AA
764    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
765    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
766    cmp     r0, #0                      @ not yet resolved?
767    beq     .LOP_CONST_STRING_resolve
768    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
769    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
770    SET_VREG(r0, r9)                    @ vAA<- r0
771    GOTO_OPCODE(ip)                     @ jump to next instruction
772
773/* ------------------------------ */
774    .balign 64
775.L_OP_CONST_STRING_JUMBO: /* 0x1b */
776/* File: armv5te/OP_CONST_STRING_JUMBO.S */
777    /* const/string vAA, String@BBBBBBBB */
778    FETCH(r0, 1)                        @ r0<- bbbb (low)
779    FETCH(r1, 2)                        @ r1<- BBBB (high)
780    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
781    mov     r9, rINST, lsr #8           @ r9<- AA
782    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
783    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
784    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
785    cmp     r0, #0
786    beq     .LOP_CONST_STRING_JUMBO_resolve
787    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
788    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
789    SET_VREG(r0, r9)                    @ vAA<- r0
790    GOTO_OPCODE(ip)                     @ jump to next instruction
791
792/* ------------------------------ */
793    .balign 64
794.L_OP_CONST_CLASS: /* 0x1c */
795/* File: armv5te/OP_CONST_CLASS.S */
796    /* const/class vAA, Class@BBBB */
797    FETCH(r1, 1)                        @ r1<- BBBB
798    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
799    mov     r9, rINST, lsr #8           @ r9<- AA
800    ldr     r2, [r2, #offDvmDex_pResClasses]   @ r2<- dvmDex->pResClasses
801    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResClasses[BBBB]
802    cmp     r0, #0                      @ not yet resolved?
803    beq     .LOP_CONST_CLASS_resolve
804    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
805    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
806    SET_VREG(r0, r9)                    @ vAA<- r0
807    GOTO_OPCODE(ip)                     @ jump to next instruction
808
809/* ------------------------------ */
810    .balign 64
811.L_OP_MONITOR_ENTER: /* 0x1d */
812/* File: armv5te/OP_MONITOR_ENTER.S */
813    /*
814     * Synchronize on an object.
815     */
816    /* monitor-enter vAA */
817    mov     r2, rINST, lsr #8           @ r2<- AA
818    GET_VREG(r1, r2)                    @ r1<- vAA (object)
819    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
820    cmp     r1, #0                      @ null object?
821    EXPORT_PC()                         @ need for precise GC, MONITOR_TRACKING
822    beq     common_errNullObject        @ null object, throw an exception
823    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
824    bl      dvmLockObject               @ call(self, obj)
825#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */
826    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
827    ldr     r1, [r0, #offThread_exception] @ check for exception
828    cmp     r1, #0
829    bne     common_exceptionThrown      @ exception raised, bail out
830#endif
831    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
832    GOTO_OPCODE(ip)                     @ jump to next instruction
833
834
835/* ------------------------------ */
836    .balign 64
837.L_OP_MONITOR_EXIT: /* 0x1e */
838/* File: armv5te/OP_MONITOR_EXIT.S */
839    /*
840     * Unlock an object.
841     *
842     * Exceptions that occur when unlocking a monitor need to appear as
843     * if they happened at the following instruction.  See the Dalvik
844     * instruction spec.
845     */
846    /* monitor-exit vAA */
847    mov     r2, rINST, lsr #8           @ r2<- AA
848    EXPORT_PC()                         @ before fetch: export the PC
849    GET_VREG(r1, r2)                    @ r1<- vAA (object)
850    cmp     r1, #0                      @ null object?
851    beq     common_errNullObject        @ yes
852    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
853    bl      dvmUnlockObject             @ r0<- success for unlock(self, obj)
854    cmp     r0, #0                      @ failed?
855    beq     common_exceptionThrown      @ yes, exception is pending
856    FETCH_ADVANCE_INST(1)               @ before throw: advance rPC, load rINST
857    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
858    GOTO_OPCODE(ip)                     @ jump to next instruction
859
860
861/* ------------------------------ */
862    .balign 64
863.L_OP_CHECK_CAST: /* 0x1f */
864/* File: armv5te/OP_CHECK_CAST.S */
865    /*
866     * Check to see if a cast from one class to another is allowed.
867     */
868    /* check-cast vAA, class@BBBB */
869    mov     r3, rINST, lsr #8           @ r3<- AA
870    FETCH(r2, 1)                        @ r2<- BBBB
871    GET_VREG(r9, r3)                    @ r9<- object
872    ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- pDvmDex
873    cmp     r9, #0                      @ is object null?
874    ldr     r0, [r0, #offDvmDex_pResClasses]    @ r0<- pDvmDex->pResClasses
875    beq     .LOP_CHECK_CAST_okay            @ null obj, cast always succeeds
876    ldr     r1, [r0, r2, lsl #2]        @ r1<- resolved class
877    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
878    cmp     r1, #0                      @ have we resolved this before?
879    beq     .LOP_CHECK_CAST_resolve         @ not resolved, do it now
880.LOP_CHECK_CAST_resolved:
881    cmp     r0, r1                      @ same class (trivial success)?
882    bne     .LOP_CHECK_CAST_fullcheck       @ no, do full check
883.LOP_CHECK_CAST_okay:
884    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
885    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
886    GOTO_OPCODE(ip)                     @ jump to next instruction
887
888/* ------------------------------ */
889    .balign 64
890.L_OP_INSTANCE_OF: /* 0x20 */
891/* File: armv5te/OP_INSTANCE_OF.S */
892    /*
893     * Check to see if an object reference is an instance of a class.
894     *
895     * Most common situation is a non-null object, being compared against
896     * an already-resolved class.
897     */
898    /* instance-of vA, vB, class@CCCC */
899    mov     r3, rINST, lsr #12          @ r3<- B
900    mov     r9, rINST, lsr #8           @ r9<- A+
901    GET_VREG(r0, r3)                    @ r0<- vB (object)
902    and     r9, r9, #15                 @ r9<- A
903    cmp     r0, #0                      @ is object null?
904    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- pDvmDex
905    beq     .LOP_INSTANCE_OF_store           @ null obj, not an instance, store r0
906    FETCH(r3, 1)                        @ r3<- CCCC
907    ldr     r2, [r2, #offDvmDex_pResClasses]    @ r2<- pDvmDex->pResClasses
908    ldr     r1, [r2, r3, lsl #2]        @ r1<- resolved class
909    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
910    cmp     r1, #0                      @ have we resolved this before?
911    beq     .LOP_INSTANCE_OF_resolve         @ not resolved, do it now
912.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class
913    cmp     r0, r1                      @ same class (trivial success)?
914    beq     .LOP_INSTANCE_OF_trivial         @ yes, trivial finish
915    b       .LOP_INSTANCE_OF_fullcheck       @ no, do full check
916
917/* ------------------------------ */
918    .balign 64
919.L_OP_ARRAY_LENGTH: /* 0x21 */
920/* File: armv5te/OP_ARRAY_LENGTH.S */
921    /*
922     * Return the length of an array.
923     */
924    mov     r1, rINST, lsr #12          @ r1<- B
925    mov     r2, rINST, lsr #8           @ r2<- A+
926    GET_VREG(r0, r1)                    @ r0<- vB (object ref)
927    and     r2, r2, #15                 @ r2<- A
928    cmp     r0, #0                      @ is object null?
929    beq     common_errNullObject        @ yup, fail
930    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
931    ldr     r3, [r0, #offArrayObject_length]    @ r3<- array length
932    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
933    SET_VREG(r3, r2)                    @ vB<- length
934    GOTO_OPCODE(ip)                     @ jump to next instruction
935
936
937/* ------------------------------ */
938    .balign 64
939.L_OP_NEW_INSTANCE: /* 0x22 */
940/* File: armv5te/OP_NEW_INSTANCE.S */
941    /*
942     * Create a new instance of a class.
943     */
944    /* new-instance vAA, class@BBBB */
945    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
946    FETCH(r1, 1)                        @ r1<- BBBB
947    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
948    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
949    EXPORT_PC()                         @ req'd for init, resolve, alloc
950    cmp     r0, #0                      @ already resolved?
951    beq     .LOP_NEW_INSTANCE_resolve         @ no, resolve it now
952.LOP_NEW_INSTANCE_resolved:   @ r0=class
953    ldrb    r1, [r0, #offClassObject_status]    @ r1<- ClassStatus enum
954    cmp     r1, #CLASS_INITIALIZED      @ has class been initialized?
955    bne     .LOP_NEW_INSTANCE_needinit        @ no, init class now
956.LOP_NEW_INSTANCE_initialized: @ r0=class
957    ldr     r3, [r0, #offClassObject_accessFlags]   @ r3<- clazz->accessFlags
958    tst     r3, #(ACC_INTERFACE|ACC_ABSTRACT)   @ abstract or interface?
959    mov     r1, #ALLOC_DONT_TRACK       @ flags for alloc call
960    beq     .LOP_NEW_INSTANCE_finish          @ concrete class, continue
961    b       .LOP_NEW_INSTANCE_abstract        @ fail
962
963/* ------------------------------ */
964    .balign 64
965.L_OP_NEW_ARRAY: /* 0x23 */
966/* File: armv5te/OP_NEW_ARRAY.S */
967    /*
968     * Allocate an array of objects, specified with the array class
969     * and a count.
970     *
971     * The verifier guarantees that this is an array class, so we don't
972     * check for it here.
973     */
974    /* new-array vA, vB, class@CCCC */
975    mov     r0, rINST, lsr #12          @ r0<- B
976    FETCH(r2, 1)                        @ r2<- CCCC
977    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
978    GET_VREG(r1, r0)                    @ r1<- vB (array length)
979    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
980    cmp     r1, #0                      @ check length
981    ldr     r0, [r3, r2, lsl #2]        @ r0<- resolved class
982    bmi     common_errNegativeArraySize @ negative length, bail
983    cmp     r0, #0                      @ already resolved?
984    EXPORT_PC()                         @ req'd for resolve, alloc
985    bne     .LOP_NEW_ARRAY_finish          @ resolved, continue
986    b       .LOP_NEW_ARRAY_resolve         @ do resolve now
987
988/* ------------------------------ */
989    .balign 64
990.L_OP_FILLED_NEW_ARRAY: /* 0x24 */
991/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
992    /*
993     * Create a new array with elements filled from registers.
994     *
995     * for: filled-new-array, filled-new-array/range
996     */
997    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
998    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
999    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1000    FETCH(r1, 1)                        @ r1<- BBBB
1001    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1002    EXPORT_PC()                         @ need for resolve and alloc
1003    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1004    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1005    cmp     r0, #0                      @ already resolved?
1006    bne     .LOP_FILLED_NEW_ARRAY_continue        @ yes, continue on
10078:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1008    mov     r2, #0                      @ r2<- false
1009    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1010    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1011    cmp     r0, #0                      @ got null?
1012    beq     common_exceptionThrown      @ yes, handle exception
1013    b       .LOP_FILLED_NEW_ARRAY_continue
1014
1015/* ------------------------------ */
1016    .balign 64
1017.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
1018/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */
1019/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1020    /*
1021     * Create a new array with elements filled from registers.
1022     *
1023     * for: filled-new-array, filled-new-array/range
1024     */
1025    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1026    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1027    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1028    FETCH(r1, 1)                        @ r1<- BBBB
1029    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1030    EXPORT_PC()                         @ need for resolve and alloc
1031    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1032    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1033    cmp     r0, #0                      @ already resolved?
1034    bne     .LOP_FILLED_NEW_ARRAY_RANGE_continue        @ yes, continue on
10358:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1036    mov     r2, #0                      @ r2<- false
1037    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1038    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1039    cmp     r0, #0                      @ got null?
1040    beq     common_exceptionThrown      @ yes, handle exception
1041    b       .LOP_FILLED_NEW_ARRAY_RANGE_continue
1042
1043
1044/* ------------------------------ */
1045    .balign 64
1046.L_OP_FILL_ARRAY_DATA: /* 0x26 */
1047/* File: armv5te/OP_FILL_ARRAY_DATA.S */
1048    /* fill-array-data vAA, +BBBBBBBB */
1049    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1050    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1051    mov     r3, rINST, lsr #8           @ r3<- AA
1052    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
1053    GET_VREG(r0, r3)                    @ r0<- vAA (array object)
1054    add     r1, rPC, r1, lsl #1         @ r1<- PC + BBBBbbbb*2 (array data off.)
1055    EXPORT_PC();
1056    bl      dvmInterpHandleFillArrayData@ fill the array with predefined data
1057    cmp     r0, #0                      @ 0 means an exception is thrown
1058    beq     common_exceptionThrown      @ has exception
1059    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
1060    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1061    GOTO_OPCODE(ip)                     @ jump to next instruction
1062
1063/* ------------------------------ */
1064    .balign 64
1065.L_OP_THROW: /* 0x27 */
1066/* File: armv5te/OP_THROW.S */
1067    /*
1068     * Throw an exception object in the current thread.
1069     */
1070    /* throw vAA */
1071    mov     r2, rINST, lsr #8           @ r2<- AA
1072    GET_VREG(r1, r2)                    @ r1<- vAA (exception object)
1073    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
1074    cmp     r1, #0                      @ null object?
1075    beq     common_errNullObject        @ yes, throw an NPE instead
1076    @ bypass dvmSetException, just store it
1077    str     r1, [r0, #offThread_exception]  @ thread->exception<- obj
1078    b       common_exceptionThrown
1079
1080
1081/* ------------------------------ */
1082    .balign 64
1083.L_OP_GOTO: /* 0x28 */
1084/* File: armv5te/OP_GOTO.S */
1085    /*
1086     * Unconditional branch, 8-bit offset.
1087     *
1088     * The branch distance is a signed code-unit offset, which we need to
1089     * double to get a byte offset.
1090     */
1091    /* goto +AA */
1092    mov     r0, rINST, lsl #16          @ r0<- AAxx0000
1093    movs    r9, r0, asr #24             @ r9<- ssssssAA (sign-extended)
1094    mov     r9, r9, lsl #1              @ r9<- byte offset
1095    bmi     common_backwardBranch       @ backward branch, do periodic checks
1096    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1097    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1098    GOTO_OPCODE(ip)                     @ jump to next instruction
1099
1100
1101/* ------------------------------ */
1102    .balign 64
1103.L_OP_GOTO_16: /* 0x29 */
1104/* File: armv5te/OP_GOTO_16.S */
1105    /*
1106     * Unconditional branch, 16-bit offset.
1107     *
1108     * The branch distance is a signed code-unit offset, which we need to
1109     * double to get a byte offset.
1110     */
1111    /* goto/16 +AAAA */
1112    FETCH_S(r0, 1)                      @ r0<- ssssAAAA (sign-extended)
1113    movs    r9, r0, asl #1              @ r9<- byte offset, check sign
1114    bmi     common_backwardBranch       @ backward branch, do periodic checks
1115    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1116    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1117    GOTO_OPCODE(ip)                     @ jump to next instruction
1118
1119
1120/* ------------------------------ */
1121    .balign 64
1122.L_OP_GOTO_32: /* 0x2a */
1123/* File: armv5te/OP_GOTO_32.S */
1124    /*
1125     * Unconditional branch, 32-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     * Unlike most opcodes, this one is allowed to branch to itself, so
1131     * our "backward branch" test must be "<=0" instead of "<0".  The ORRS
1132     * instruction doesn't affect the V flag, so we need to clear it
1133     * explicitly.
1134     */
1135    /* goto/32 +AAAAAAAA */
1136    FETCH(r0, 1)                        @ r0<- aaaa (lo)
1137    FETCH(r1, 2)                        @ r1<- AAAA (hi)
1138    cmp     ip, ip                      @ (clear V flag during stall)
1139    orrs    r0, r0, r1, lsl #16         @ r0<- AAAAaaaa, check sign
1140    mov     r9, r0, asl #1              @ r9<- byte offset
1141    ble     common_backwardBranch       @ backward branch, do periodic checks
1142    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1143    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1144    GOTO_OPCODE(ip)                     @ jump to next instruction
1145
1146
1147/* ------------------------------ */
1148    .balign 64
1149.L_OP_PACKED_SWITCH: /* 0x2b */
1150/* File: armv5te/OP_PACKED_SWITCH.S */
1151    /*
1152     * Handle a packed-switch or sparse-switch instruction.  In both cases
1153     * we decode it and hand it off to a helper function.
1154     *
1155     * We don't really expect backward branches in a switch statement, but
1156     * they're perfectly legal, so we check for them here.
1157     *
1158     * for: packed-switch, sparse-switch
1159     */
1160    /* op vAA, +BBBB */
1161    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1162    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1163    mov     r3, rINST, lsr #8           @ r3<- AA
1164    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1165    GET_VREG(r1, r3)                    @ r1<- vAA
1166    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1167    bl      dvmInterpHandlePackedSwitch                       @ r0<- code-unit branch offset
1168    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1169    bmi     common_backwardBranch       @ backward branch, do periodic checks
1170    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1171    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1172    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1173    GOTO_OPCODE(ip)                     @ jump to next instruction
1174
1175
1176/* ------------------------------ */
1177    .balign 64
1178.L_OP_SPARSE_SWITCH: /* 0x2c */
1179/* File: armv5te/OP_SPARSE_SWITCH.S */
1180/* File: armv5te/OP_PACKED_SWITCH.S */
1181    /*
1182     * Handle a packed-switch or sparse-switch instruction.  In both cases
1183     * we decode it and hand it off to a helper function.
1184     *
1185     * We don't really expect backward branches in a switch statement, but
1186     * they're perfectly legal, so we check for them here.
1187     *
1188     * for: packed-switch, sparse-switch
1189     */
1190    /* op vAA, +BBBB */
1191    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1192    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1193    mov     r3, rINST, lsr #8           @ r3<- AA
1194    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1195    GET_VREG(r1, r3)                    @ r1<- vAA
1196    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1197    bl      dvmInterpHandleSparseSwitch                       @ r0<- code-unit branch offset
1198    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1199    bmi     common_backwardBranch       @ backward branch, do periodic checks
1200    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1201    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1202    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1203    GOTO_OPCODE(ip)                     @ jump to next instruction
1204
1205
1206
1207/* ------------------------------ */
1208    .balign 64
1209.L_OP_CMPL_FLOAT: /* 0x2d */
1210/* File: armv5te/OP_CMPL_FLOAT.S */
1211    /*
1212     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1213     * destination register based on the results of the comparison.
1214     *
1215     * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1216     * on what value we'd like to return when one of the operands is NaN.
1217     *
1218     * The operation we're implementing is:
1219     *   if (x == y)
1220     *     return 0;
1221     *   else if (x < y)
1222     *     return -1;
1223     *   else if (x > y)
1224     *     return 1;
1225     *   else
1226     *     return {-1,1};  // one or both operands was NaN
1227     *
1228     * The straightforward implementation requires 3 calls to functions
1229     * that return a result in r0.  We can do it with two calls if our
1230     * EABI library supports __aeabi_cfcmple (only one if we want to check
1231     * for NaN directly):
1232     *   check x <= y
1233     *     if <, return -1
1234     *     if ==, return 0
1235     *   check y <= x
1236     *     if <, return 1
1237     *   return {-1,1}
1238     *
1239     * for: cmpl-float, cmpg-float
1240     */
1241    /* op vAA, vBB, vCC */
1242    FETCH(r0, 1)                        @ r0<- CCBB
1243    and     r2, r0, #255                @ r2<- BB
1244    mov     r3, r0, lsr #8              @ r3<- CC
1245    GET_VREG(r9, r2)                    @ r9<- vBB
1246    GET_VREG(r10, r3)                   @ r10<- vCC
1247    mov     r0, r9                      @ copy to arg registers
1248    mov     r1, r10
1249    bl      __aeabi_cfcmple             @ cmp <=: C clear if <, Z set if eq
1250    bhi     .LOP_CMPL_FLOAT_gt_or_nan       @ C set and Z clear, disambiguate
1251    mvncc   r1, #0                      @ (less than) r1<- -1
1252    moveq   r1, #0                      @ (equal) r1<- 0, trumps less than
1253.LOP_CMPL_FLOAT_finish:
1254    mov     r3, rINST, lsr #8           @ r3<- AA
1255    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1256    SET_VREG(r1, r3)                    @ vAA<- r1
1257    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1258    GOTO_OPCODE(ip)                     @ jump to next instruction
1259
1260/* ------------------------------ */
1261    .balign 64
1262.L_OP_CMPG_FLOAT: /* 0x2e */
1263/* File: armv5te/OP_CMPG_FLOAT.S */
1264/* File: armv5te/OP_CMPL_FLOAT.S */
1265    /*
1266     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1267     * destination register based on the results of the comparison.
1268     *
1269     * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1270     * on what value we'd like to return when one of the operands is NaN.
1271     *
1272     * The operation we're implementing is:
1273     *   if (x == y)
1274     *     return 0;
1275     *   else if (x < y)
1276     *     return -1;
1277     *   else if (x > y)
1278     *     return 1;
1279     *   else
1280     *     return {-1,1};  // one or both operands was NaN
1281     *
1282     * The straightforward implementation requires 3 calls to functions
1283     * that return a result in r0.  We can do it with two calls if our
1284     * EABI library supports __aeabi_cfcmple (only one if we want to check
1285     * for NaN directly):
1286     *   check x <= y
1287     *     if <, return -1
1288     *     if ==, return 0
1289     *   check y <= x
1290     *     if <, return 1
1291     *   return {-1,1}
1292     *
1293     * for: cmpl-float, cmpg-float
1294     */
1295    /* op vAA, vBB, vCC */
1296    FETCH(r0, 1)                        @ r0<- CCBB
1297    and     r2, r0, #255                @ r2<- BB
1298    mov     r3, r0, lsr #8              @ r3<- CC
1299    GET_VREG(r9, r2)                    @ r9<- vBB
1300    GET_VREG(r10, r3)                   @ r10<- vCC
1301    mov     r0, r9                      @ copy to arg registers
1302    mov     r1, r10
1303    bl      __aeabi_cfcmple             @ cmp <=: C clear if <, Z set if eq
1304    bhi     .LOP_CMPG_FLOAT_gt_or_nan       @ C set and Z clear, disambiguate
1305    mvncc   r1, #0                      @ (less than) r1<- -1
1306    moveq   r1, #0                      @ (equal) r1<- 0, trumps less than
1307.LOP_CMPG_FLOAT_finish:
1308    mov     r3, rINST, lsr #8           @ r3<- AA
1309    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1310    SET_VREG(r1, r3)                    @ vAA<- r1
1311    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1312    GOTO_OPCODE(ip)                     @ jump to next instruction
1313
1314
1315/* ------------------------------ */
1316    .balign 64
1317.L_OP_CMPL_DOUBLE: /* 0x2f */
1318/* File: armv5te/OP_CMPL_DOUBLE.S */
1319    /*
1320     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1321     * destination register based on the results of the comparison.
1322     *
1323     * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1324     * on what value we'd like to return when one of the operands is NaN.
1325     *
1326     * See OP_CMPL_FLOAT for an explanation.
1327     *
1328     * For: cmpl-double, cmpg-double
1329     */
1330    /* op vAA, vBB, vCC */
1331    FETCH(r0, 1)                        @ r0<- CCBB
1332    and     r9, r0, #255                @ r9<- BB
1333    mov     r10, r0, lsr #8             @ r10<- CC
1334    add     r9, rFP, r9, lsl #2         @ r9<- &fp[BB]
1335    add     r10, rFP, r10, lsl #2       @ r10<- &fp[CC]
1336    ldmia   r9, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1337    ldmia   r10, {r2-r3}                @ r2/r3<- vCC/vCC+1
1338    bl      __aeabi_cdcmple             @ cmp <=: C clear if <, Z set if eq
1339    bhi     .LOP_CMPL_DOUBLE_gt_or_nan       @ C set and Z clear, disambiguate
1340    mvncc   r1, #0                      @ (less than) r1<- -1
1341    moveq   r1, #0                      @ (equal) r1<- 0, trumps less than
1342.LOP_CMPL_DOUBLE_finish:
1343    mov     r3, rINST, lsr #8           @ r3<- AA
1344    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1345    SET_VREG(r1, r3)                    @ vAA<- r1
1346    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1347    GOTO_OPCODE(ip)                     @ jump to next instruction
1348
1349/* ------------------------------ */
1350    .balign 64
1351.L_OP_CMPG_DOUBLE: /* 0x30 */
1352/* File: armv5te/OP_CMPG_DOUBLE.S */
1353/* File: armv5te/OP_CMPL_DOUBLE.S */
1354    /*
1355     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1356     * destination register based on the results of the comparison.
1357     *
1358     * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1359     * on what value we'd like to return when one of the operands is NaN.
1360     *
1361     * See OP_CMPL_FLOAT for an explanation.
1362     *
1363     * For: cmpl-double, cmpg-double
1364     */
1365    /* op vAA, vBB, vCC */
1366    FETCH(r0, 1)                        @ r0<- CCBB
1367    and     r9, r0, #255                @ r9<- BB
1368    mov     r10, r0, lsr #8             @ r10<- CC
1369    add     r9, rFP, r9, lsl #2         @ r9<- &fp[BB]
1370    add     r10, rFP, r10, lsl #2       @ r10<- &fp[CC]
1371    ldmia   r9, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1372    ldmia   r10, {r2-r3}                @ r2/r3<- vCC/vCC+1
1373    bl      __aeabi_cdcmple             @ cmp <=: C clear if <, Z set if eq
1374    bhi     .LOP_CMPG_DOUBLE_gt_or_nan       @ C set and Z clear, disambiguate
1375    mvncc   r1, #0                      @ (less than) r1<- -1
1376    moveq   r1, #0                      @ (equal) r1<- 0, trumps less than
1377.LOP_CMPG_DOUBLE_finish:
1378    mov     r3, rINST, lsr #8           @ r3<- AA
1379    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1380    SET_VREG(r1, r3)                    @ vAA<- r1
1381    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1382    GOTO_OPCODE(ip)                     @ jump to next instruction
1383
1384
1385/* ------------------------------ */
1386    .balign 64
1387.L_OP_CMP_LONG: /* 0x31 */
1388/* File: armv5te/OP_CMP_LONG.S */
1389    /*
1390     * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
1391     * register based on the results of the comparison.
1392     *
1393     * We load the full values with LDM, but in practice many values could
1394     * be resolved by only looking at the high word.  This could be made
1395     * faster or slower by splitting the LDM into a pair of LDRs.
1396     *
1397     * If we just wanted to set condition flags, we could do this:
1398     *  subs    ip, r0, r2
1399     *  sbcs    ip, r1, r3
1400     *  subeqs  ip, r0, r2
1401     * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
1402     * integer value, which we can do with 2 conditional mov/mvn instructions
1403     * (set 1, set -1; if they're equal we already have 0 in ip), giving
1404     * us a constant 5-cycle path plus a branch at the end to the
1405     * instruction epilogue code.  The multi-compare approach below needs
1406     * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
1407     * in the worst case (the 64-bit values are equal).
1408     */
1409    /* cmp-long vAA, vBB, vCC */
1410    FETCH(r0, 1)                        @ r0<- CCBB
1411    mov     r9, rINST, lsr #8           @ r9<- AA
1412    and     r2, r0, #255                @ r2<- BB
1413    mov     r3, r0, lsr #8              @ r3<- CC
1414    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
1415    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
1416    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1417    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
1418    cmp     r1, r3                      @ compare (vBB+1, vCC+1)
1419    blt     .LOP_CMP_LONG_less            @ signed compare on high part
1420    bgt     .LOP_CMP_LONG_greater
1421    subs    r1, r0, r2                  @ r1<- r0 - r2
1422    bhi     .LOP_CMP_LONG_greater         @ unsigned compare on low part
1423    bne     .LOP_CMP_LONG_less
1424    b       .LOP_CMP_LONG_finish          @ equal; r1 already holds 0
1425
1426/* ------------------------------ */
1427    .balign 64
1428.L_OP_IF_EQ: /* 0x32 */
1429/* File: armv5te/OP_IF_EQ.S */
1430/* File: armv5te/bincmp.S */
1431    /*
1432     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1433     * fragment that specifies the *reverse* comparison to perform, e.g.
1434     * for "if-le" you would use "gt".
1435     *
1436     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1437     */
1438    /* if-cmp vA, vB, +CCCC */
1439    mov     r0, rINST, lsr #8           @ r0<- A+
1440    mov     r1, rINST, lsr #12          @ r1<- B
1441    and     r0, r0, #15
1442    GET_VREG(r3, r1)                    @ r3<- vB
1443    GET_VREG(r2, r0)                    @ r2<- vA
1444    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1445    cmp     r2, r3                      @ compare (vA, vB)
1446    bne  1f                      @ branch to 1 if comparison failed
1447    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1448    movs    r9, r9, asl #1              @ convert to bytes, check sign
1449    bmi     common_backwardBranch       @ yes, do periodic checks
14501:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1451    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1452    GOTO_OPCODE(ip)                     @ jump to next instruction
1453
1454
1455
1456/* ------------------------------ */
1457    .balign 64
1458.L_OP_IF_NE: /* 0x33 */
1459/* File: armv5te/OP_IF_NE.S */
1460/* File: armv5te/bincmp.S */
1461    /*
1462     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1463     * fragment that specifies the *reverse* comparison to perform, e.g.
1464     * for "if-le" you would use "gt".
1465     *
1466     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1467     */
1468    /* if-cmp vA, vB, +CCCC */
1469    mov     r0, rINST, lsr #8           @ r0<- A+
1470    mov     r1, rINST, lsr #12          @ r1<- B
1471    and     r0, r0, #15
1472    GET_VREG(r3, r1)                    @ r3<- vB
1473    GET_VREG(r2, r0)                    @ r2<- vA
1474    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1475    cmp     r2, r3                      @ compare (vA, vB)
1476    beq  1f                      @ branch to 1 if comparison failed
1477    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1478    movs    r9, r9, asl #1              @ convert to bytes, check sign
1479    bmi     common_backwardBranch       @ yes, do periodic checks
14801:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1481    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1482    GOTO_OPCODE(ip)                     @ jump to next instruction
1483
1484
1485
1486/* ------------------------------ */
1487    .balign 64
1488.L_OP_IF_LT: /* 0x34 */
1489/* File: armv5te/OP_IF_LT.S */
1490/* File: armv5te/bincmp.S */
1491    /*
1492     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1493     * fragment that specifies the *reverse* comparison to perform, e.g.
1494     * for "if-le" you would use "gt".
1495     *
1496     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1497     */
1498    /* if-cmp vA, vB, +CCCC */
1499    mov     r0, rINST, lsr #8           @ r0<- A+
1500    mov     r1, rINST, lsr #12          @ r1<- B
1501    and     r0, r0, #15
1502    GET_VREG(r3, r1)                    @ r3<- vB
1503    GET_VREG(r2, r0)                    @ r2<- vA
1504    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1505    cmp     r2, r3                      @ compare (vA, vB)
1506    bge  1f                      @ branch to 1 if comparison failed
1507    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1508    movs    r9, r9, asl #1              @ convert to bytes, check sign
1509    bmi     common_backwardBranch       @ yes, do periodic checks
15101:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1511    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1512    GOTO_OPCODE(ip)                     @ jump to next instruction
1513
1514
1515
1516/* ------------------------------ */
1517    .balign 64
1518.L_OP_IF_GE: /* 0x35 */
1519/* File: armv5te/OP_IF_GE.S */
1520/* File: armv5te/bincmp.S */
1521    /*
1522     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1523     * fragment that specifies the *reverse* comparison to perform, e.g.
1524     * for "if-le" you would use "gt".
1525     *
1526     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1527     */
1528    /* if-cmp vA, vB, +CCCC */
1529    mov     r0, rINST, lsr #8           @ r0<- A+
1530    mov     r1, rINST, lsr #12          @ r1<- B
1531    and     r0, r0, #15
1532    GET_VREG(r3, r1)                    @ r3<- vB
1533    GET_VREG(r2, r0)                    @ r2<- vA
1534    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1535    cmp     r2, r3                      @ compare (vA, vB)
1536    blt  1f                      @ branch to 1 if comparison failed
1537    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1538    movs    r9, r9, asl #1              @ convert to bytes, check sign
1539    bmi     common_backwardBranch       @ yes, do periodic checks
15401:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1541    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1542    GOTO_OPCODE(ip)                     @ jump to next instruction
1543
1544
1545
1546/* ------------------------------ */
1547    .balign 64
1548.L_OP_IF_GT: /* 0x36 */
1549/* File: armv5te/OP_IF_GT.S */
1550/* File: armv5te/bincmp.S */
1551    /*
1552     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1553     * fragment that specifies the *reverse* comparison to perform, e.g.
1554     * for "if-le" you would use "gt".
1555     *
1556     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1557     */
1558    /* if-cmp vA, vB, +CCCC */
1559    mov     r0, rINST, lsr #8           @ r0<- A+
1560    mov     r1, rINST, lsr #12          @ r1<- B
1561    and     r0, r0, #15
1562    GET_VREG(r3, r1)                    @ r3<- vB
1563    GET_VREG(r2, r0)                    @ r2<- vA
1564    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1565    cmp     r2, r3                      @ compare (vA, vB)
1566    ble  1f                      @ branch to 1 if comparison failed
1567    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1568    movs    r9, r9, asl #1              @ convert to bytes, check sign
1569    bmi     common_backwardBranch       @ yes, do periodic checks
15701:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1571    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1572    GOTO_OPCODE(ip)                     @ jump to next instruction
1573
1574
1575
1576/* ------------------------------ */
1577    .balign 64
1578.L_OP_IF_LE: /* 0x37 */
1579/* File: armv5te/OP_IF_LE.S */
1580/* File: armv5te/bincmp.S */
1581    /*
1582     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1583     * fragment that specifies the *reverse* comparison to perform, e.g.
1584     * for "if-le" you would use "gt".
1585     *
1586     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1587     */
1588    /* if-cmp vA, vB, +CCCC */
1589    mov     r0, rINST, lsr #8           @ r0<- A+
1590    mov     r1, rINST, lsr #12          @ r1<- B
1591    and     r0, r0, #15
1592    GET_VREG(r3, r1)                    @ r3<- vB
1593    GET_VREG(r2, r0)                    @ r2<- vA
1594    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1595    cmp     r2, r3                      @ compare (vA, vB)
1596    bgt  1f                      @ branch to 1 if comparison failed
1597    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1598    movs    r9, r9, asl #1              @ convert to bytes, check sign
1599    bmi     common_backwardBranch       @ yes, do periodic checks
16001:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1601    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1602    GOTO_OPCODE(ip)                     @ jump to next instruction
1603
1604
1605
1606/* ------------------------------ */
1607    .balign 64
1608.L_OP_IF_EQZ: /* 0x38 */
1609/* File: armv5te/OP_IF_EQZ.S */
1610/* File: armv5te/zcmp.S */
1611    /*
1612     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1613     * fragment that specifies the *reverse* comparison to perform, e.g.
1614     * for "if-le" you would use "gt".
1615     *
1616     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1617     */
1618    /* if-cmp vAA, +BBBB */
1619    mov     r0, rINST, lsr #8           @ r0<- AA
1620    GET_VREG(r2, r0)                    @ r2<- vAA
1621    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1622    cmp     r2, #0                      @ compare (vA, 0)
1623    bne  1f                      @ branch to 1 if comparison failed
1624    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1625    movs    r9, r9, asl #1              @ convert to bytes, check sign
1626    bmi     common_backwardBranch       @ backward branch, do periodic checks
16271:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1628    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1629    GOTO_OPCODE(ip)                     @ jump to next instruction
1630
1631
1632
1633/* ------------------------------ */
1634    .balign 64
1635.L_OP_IF_NEZ: /* 0x39 */
1636/* File: armv5te/OP_IF_NEZ.S */
1637/* File: armv5te/zcmp.S */
1638    /*
1639     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1640     * fragment that specifies the *reverse* comparison to perform, e.g.
1641     * for "if-le" you would use "gt".
1642     *
1643     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1644     */
1645    /* if-cmp vAA, +BBBB */
1646    mov     r0, rINST, lsr #8           @ r0<- AA
1647    GET_VREG(r2, r0)                    @ r2<- vAA
1648    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1649    cmp     r2, #0                      @ compare (vA, 0)
1650    beq  1f                      @ branch to 1 if comparison failed
1651    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1652    movs    r9, r9, asl #1              @ convert to bytes, check sign
1653    bmi     common_backwardBranch       @ backward branch, do periodic checks
16541:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1655    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1656    GOTO_OPCODE(ip)                     @ jump to next instruction
1657
1658
1659
1660/* ------------------------------ */
1661    .balign 64
1662.L_OP_IF_LTZ: /* 0x3a */
1663/* File: armv5te/OP_IF_LTZ.S */
1664/* File: armv5te/zcmp.S */
1665    /*
1666     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1667     * fragment that specifies the *reverse* comparison to perform, e.g.
1668     * for "if-le" you would use "gt".
1669     *
1670     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1671     */
1672    /* if-cmp vAA, +BBBB */
1673    mov     r0, rINST, lsr #8           @ r0<- AA
1674    GET_VREG(r2, r0)                    @ r2<- vAA
1675    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1676    cmp     r2, #0                      @ compare (vA, 0)
1677    bge  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       @ backward branch, do periodic checks
16811:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1682    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1683    GOTO_OPCODE(ip)                     @ jump to next instruction
1684
1685
1686
1687/* ------------------------------ */
1688    .balign 64
1689.L_OP_IF_GEZ: /* 0x3b */
1690/* File: armv5te/OP_IF_GEZ.S */
1691/* File: armv5te/zcmp.S */
1692    /*
1693     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1694     * fragment that specifies the *reverse* comparison to perform, e.g.
1695     * for "if-le" you would use "gt".
1696     *
1697     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1698     */
1699    /* if-cmp vAA, +BBBB */
1700    mov     r0, rINST, lsr #8           @ r0<- AA
1701    GET_VREG(r2, r0)                    @ r2<- vAA
1702    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1703    cmp     r2, #0                      @ compare (vA, 0)
1704    blt  1f                      @ branch to 1 if comparison failed
1705    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1706    movs    r9, r9, asl #1              @ convert to bytes, check sign
1707    bmi     common_backwardBranch       @ backward branch, do periodic checks
17081:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1709    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1710    GOTO_OPCODE(ip)                     @ jump to next instruction
1711
1712
1713
1714/* ------------------------------ */
1715    .balign 64
1716.L_OP_IF_GTZ: /* 0x3c */
1717/* File: armv5te/OP_IF_GTZ.S */
1718/* File: armv5te/zcmp.S */
1719    /*
1720     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1721     * fragment that specifies the *reverse* comparison to perform, e.g.
1722     * for "if-le" you would use "gt".
1723     *
1724     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1725     */
1726    /* if-cmp vAA, +BBBB */
1727    mov     r0, rINST, lsr #8           @ r0<- AA
1728    GET_VREG(r2, r0)                    @ r2<- vAA
1729    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1730    cmp     r2, #0                      @ compare (vA, 0)
1731    ble  1f                      @ branch to 1 if comparison failed
1732    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1733    movs    r9, r9, asl #1              @ convert to bytes, check sign
1734    bmi     common_backwardBranch       @ backward branch, do periodic checks
17351:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1736    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1737    GOTO_OPCODE(ip)                     @ jump to next instruction
1738
1739
1740
1741/* ------------------------------ */
1742    .balign 64
1743.L_OP_IF_LEZ: /* 0x3d */
1744/* File: armv5te/OP_IF_LEZ.S */
1745/* File: armv5te/zcmp.S */
1746    /*
1747     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1748     * fragment that specifies the *reverse* comparison to perform, e.g.
1749     * for "if-le" you would use "gt".
1750     *
1751     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1752     */
1753    /* if-cmp vAA, +BBBB */
1754    mov     r0, rINST, lsr #8           @ r0<- AA
1755    GET_VREG(r2, r0)                    @ r2<- vAA
1756    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1757    cmp     r2, #0                      @ compare (vA, 0)
1758    bgt  1f                      @ branch to 1 if comparison failed
1759    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1760    movs    r9, r9, asl #1              @ convert to bytes, check sign
1761    bmi     common_backwardBranch       @ backward branch, do periodic checks
17621:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1763    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1764    GOTO_OPCODE(ip)                     @ jump to next instruction
1765
1766
1767
1768/* ------------------------------ */
1769    .balign 64
1770.L_OP_UNUSED_3E: /* 0x3e */
1771/* File: armv5te/OP_UNUSED_3E.S */
1772/* File: armv5te/unused.S */
1773    bl      common_abort
1774
1775
1776
1777/* ------------------------------ */
1778    .balign 64
1779.L_OP_UNUSED_3F: /* 0x3f */
1780/* File: armv5te/OP_UNUSED_3F.S */
1781/* File: armv5te/unused.S */
1782    bl      common_abort
1783
1784
1785
1786/* ------------------------------ */
1787    .balign 64
1788.L_OP_UNUSED_40: /* 0x40 */
1789/* File: armv5te/OP_UNUSED_40.S */
1790/* File: armv5te/unused.S */
1791    bl      common_abort
1792
1793
1794
1795/* ------------------------------ */
1796    .balign 64
1797.L_OP_UNUSED_41: /* 0x41 */
1798/* File: armv5te/OP_UNUSED_41.S */
1799/* File: armv5te/unused.S */
1800    bl      common_abort
1801
1802
1803
1804/* ------------------------------ */
1805    .balign 64
1806.L_OP_UNUSED_42: /* 0x42 */
1807/* File: armv5te/OP_UNUSED_42.S */
1808/* File: armv5te/unused.S */
1809    bl      common_abort
1810
1811
1812
1813/* ------------------------------ */
1814    .balign 64
1815.L_OP_UNUSED_43: /* 0x43 */
1816/* File: armv5te/OP_UNUSED_43.S */
1817/* File: armv5te/unused.S */
1818    bl      common_abort
1819
1820
1821
1822/* ------------------------------ */
1823    .balign 64
1824.L_OP_AGET: /* 0x44 */
1825/* File: armv5te/OP_AGET.S */
1826    /*
1827     * Array get, 32 bits or less.  vAA <- vBB[vCC].
1828     *
1829     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
1830     * instructions.  We use a pair of FETCH_Bs instead.
1831     *
1832     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1833     */
1834    /* op vAA, vBB, vCC */
1835    FETCH_B(r2, 1, 0)                   @ r2<- BB
1836    mov     r9, rINST, lsr #8           @ r9<- AA
1837    FETCH_B(r3, 1, 1)                   @ r3<- CC
1838    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
1839    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
1840    cmp     r0, #0                      @ null array object?
1841    beq     common_errNullObject        @ yes, bail
1842    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
1843    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
1844    cmp     r1, r3                      @ compare unsigned index, length
1845    bcs     common_errArrayIndex        @ index >= length, bail
1846    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1847    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
1848    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1849    SET_VREG(r2, r9)                    @ vAA<- r2
1850    GOTO_OPCODE(ip)                     @ jump to next instruction
1851
1852
1853/* ------------------------------ */
1854    .balign 64
1855.L_OP_AGET_WIDE: /* 0x45 */
1856/* File: armv5te/OP_AGET_WIDE.S */
1857    /*
1858     * Array get, 64 bits.  vAA <- vBB[vCC].
1859     *
1860     * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD.
1861     */
1862    /* aget-wide vAA, vBB, vCC */
1863    FETCH(r0, 1)                        @ r0<- CCBB
1864    mov     r9, rINST, lsr #8           @ r9<- AA
1865    and     r2, r0, #255                @ r2<- BB
1866    mov     r3, r0, lsr #8              @ r3<- CC
1867    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
1868    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
1869    cmp     r0, #0                      @ null array object?
1870    beq     common_errNullObject        @ yes, bail
1871    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
1872    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
1873    cmp     r1, r3                      @ compare unsigned index, length
1874    bcc     .LOP_AGET_WIDE_finish          @ okay, continue below
1875    b       common_errArrayIndex        @ index >= length, bail
1876    @ May want to swap the order of these two branches depending on how the
1877    @ branch prediction (if any) handles conditional forward branches vs.
1878    @ unconditional forward branches.
1879
1880/* ------------------------------ */
1881    .balign 64
1882.L_OP_AGET_OBJECT: /* 0x46 */
1883/* File: armv5te/OP_AGET_OBJECT.S */
1884/* File: armv5te/OP_AGET.S */
1885    /*
1886     * Array get, 32 bits or less.  vAA <- vBB[vCC].
1887     *
1888     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
1889     * instructions.  We use a pair of FETCH_Bs instead.
1890     *
1891     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1892     */
1893    /* op vAA, vBB, vCC */
1894    FETCH_B(r2, 1, 0)                   @ r2<- BB
1895    mov     r9, rINST, lsr #8           @ r9<- AA
1896    FETCH_B(r3, 1, 1)                   @ r3<- CC
1897    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
1898    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
1899    cmp     r0, #0                      @ null array object?
1900    beq     common_errNullObject        @ yes, bail
1901    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
1902    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
1903    cmp     r1, r3                      @ compare unsigned index, length
1904    bcs     common_errArrayIndex        @ index >= length, bail
1905    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1906    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
1907    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1908    SET_VREG(r2, r9)                    @ vAA<- r2
1909    GOTO_OPCODE(ip)                     @ jump to next instruction
1910
1911
1912
1913/* ------------------------------ */
1914    .balign 64
1915.L_OP_AGET_BOOLEAN: /* 0x47 */
1916/* File: armv5te/OP_AGET_BOOLEAN.S */
1917/* File: armv5te/OP_AGET.S */
1918    /*
1919     * Array get, 32 bits or less.  vAA <- vBB[vCC].
1920     *
1921     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
1922     * instructions.  We use a pair of FETCH_Bs instead.
1923     *
1924     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1925     */
1926    /* op vAA, vBB, vCC */
1927    FETCH_B(r2, 1, 0)                   @ r2<- BB
1928    mov     r9, rINST, lsr #8           @ r9<- AA
1929    FETCH_B(r3, 1, 1)                   @ r3<- CC
1930    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
1931    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
1932    cmp     r0, #0                      @ null array object?
1933    beq     common_errNullObject        @ yes, bail
1934    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
1935    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
1936    cmp     r1, r3                      @ compare unsigned index, length
1937    bcs     common_errArrayIndex        @ index >= length, bail
1938    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1939    ldrb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
1940    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1941    SET_VREG(r2, r9)                    @ vAA<- r2
1942    GOTO_OPCODE(ip)                     @ jump to next instruction
1943
1944
1945
1946/* ------------------------------ */
1947    .balign 64
1948.L_OP_AGET_BYTE: /* 0x48 */
1949/* File: armv5te/OP_AGET_BYTE.S */
1950/* File: armv5te/OP_AGET.S */
1951    /*
1952     * Array get, 32 bits or less.  vAA <- vBB[vCC].
1953     *
1954     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
1955     * instructions.  We use a pair of FETCH_Bs instead.
1956     *
1957     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1958     */
1959    /* op vAA, vBB, vCC */
1960    FETCH_B(r2, 1, 0)                   @ r2<- BB
1961    mov     r9, rINST, lsr #8           @ r9<- AA
1962    FETCH_B(r3, 1, 1)                   @ r3<- CC
1963    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
1964    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
1965    cmp     r0, #0                      @ null array object?
1966    beq     common_errNullObject        @ yes, bail
1967    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
1968    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
1969    cmp     r1, r3                      @ compare unsigned index, length
1970    bcs     common_errArrayIndex        @ index >= length, bail
1971    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1972    ldrsb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
1973    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1974    SET_VREG(r2, r9)                    @ vAA<- r2
1975    GOTO_OPCODE(ip)                     @ jump to next instruction
1976
1977
1978
1979/* ------------------------------ */
1980    .balign 64
1981.L_OP_AGET_CHAR: /* 0x49 */
1982/* File: armv5te/OP_AGET_CHAR.S */
1983/* File: armv5te/OP_AGET.S */
1984    /*
1985     * Array get, 32 bits or less.  vAA <- vBB[vCC].
1986     *
1987     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
1988     * instructions.  We use a pair of FETCH_Bs instead.
1989     *
1990     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1991     */
1992    /* op vAA, vBB, vCC */
1993    FETCH_B(r2, 1, 0)                   @ r2<- BB
1994    mov     r9, rINST, lsr #8           @ r9<- AA
1995    FETCH_B(r3, 1, 1)                   @ r3<- CC
1996    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
1997    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
1998    cmp     r0, #0                      @ null array object?
1999    beq     common_errNullObject        @ yes, bail
2000    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2001    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2002    cmp     r1, r3                      @ compare unsigned index, length
2003    bcs     common_errArrayIndex        @ index >= length, bail
2004    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2005    ldrh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2006    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2007    SET_VREG(r2, r9)                    @ vAA<- r2
2008    GOTO_OPCODE(ip)                     @ jump to next instruction
2009
2010
2011
2012/* ------------------------------ */
2013    .balign 64
2014.L_OP_AGET_SHORT: /* 0x4a */
2015/* File: armv5te/OP_AGET_SHORT.S */
2016/* File: armv5te/OP_AGET.S */
2017    /*
2018     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2019     *
2020     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2021     * instructions.  We use a pair of FETCH_Bs instead.
2022     *
2023     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2024     */
2025    /* op vAA, vBB, vCC */
2026    FETCH_B(r2, 1, 0)                   @ r2<- BB
2027    mov     r9, rINST, lsr #8           @ r9<- AA
2028    FETCH_B(r3, 1, 1)                   @ r3<- CC
2029    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2030    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2031    cmp     r0, #0                      @ null array object?
2032    beq     common_errNullObject        @ yes, bail
2033    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2034    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2035    cmp     r1, r3                      @ compare unsigned index, length
2036    bcs     common_errArrayIndex        @ index >= length, bail
2037    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2038    ldrsh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2039    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2040    SET_VREG(r2, r9)                    @ vAA<- r2
2041    GOTO_OPCODE(ip)                     @ jump to next instruction
2042
2043
2044
2045/* ------------------------------ */
2046    .balign 64
2047.L_OP_APUT: /* 0x4b */
2048/* File: armv5te/OP_APUT.S */
2049    /*
2050     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2051     *
2052     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2053     * instructions.  We use a pair of FETCH_Bs instead.
2054     *
2055     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2056     */
2057    /* op vAA, vBB, vCC */
2058    FETCH_B(r2, 1, 0)                   @ r2<- BB
2059    mov     r9, rINST, lsr #8           @ r9<- AA
2060    FETCH_B(r3, 1, 1)                   @ r3<- CC
2061    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2062    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2063    cmp     r0, #0                      @ null array object?
2064    beq     common_errNullObject        @ yes, bail
2065    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2066    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2067    cmp     r1, r3                      @ compare unsigned index, length
2068    bcs     common_errArrayIndex        @ index >= length, bail
2069    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2070    GET_VREG(r2, r9)                    @ r2<- vAA
2071    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2072    str  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2073    GOTO_OPCODE(ip)                     @ jump to next instruction
2074
2075
2076/* ------------------------------ */
2077    .balign 64
2078.L_OP_APUT_WIDE: /* 0x4c */
2079/* File: armv5te/OP_APUT_WIDE.S */
2080    /*
2081     * Array put, 64 bits.  vBB[vCC] <- vAA.
2082     *
2083     * Arrays of long/double are 64-bit aligned, so it's okay to use STRD.
2084     */
2085    /* aput-wide vAA, vBB, vCC */
2086    FETCH(r0, 1)                        @ r0<- CCBB
2087    mov     r9, rINST, lsr #8           @ r9<- AA
2088    and     r2, r0, #255                @ r2<- BB
2089    mov     r3, r0, lsr #8              @ r3<- CC
2090    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2091    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2092    cmp     r0, #0                      @ null array object?
2093    beq     common_errNullObject        @ yes, bail
2094    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2095    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2096    cmp     r1, r3                      @ compare unsigned index, length
2097    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2098    bcc     .LOP_APUT_WIDE_finish          @ okay, continue below
2099    b       common_errArrayIndex        @ index >= length, bail
2100    @ May want to swap the order of these two branches depending on how the
2101    @ branch prediction (if any) handles conditional forward branches vs.
2102    @ unconditional forward branches.
2103
2104/* ------------------------------ */
2105    .balign 64
2106.L_OP_APUT_OBJECT: /* 0x4d */
2107/* File: armv5te/OP_APUT_OBJECT.S */
2108    /*
2109     * Store an object into an array.  vBB[vCC] <- vAA.
2110     *
2111     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2112     * instructions.  We use a pair of FETCH_Bs instead.
2113     */
2114    /* op vAA, vBB, vCC */
2115    FETCH(r0, 1)                        @ r0<- CCBB
2116    mov     r9, rINST, lsr #8           @ r9<- AA
2117    and     r2, r0, #255                @ r2<- BB
2118    mov     r3, r0, lsr #8              @ r3<- CC
2119    GET_VREG(r1, r2)                    @ r1<- vBB (array object)
2120    GET_VREG(r0, r3)                    @ r0<- vCC (requested index)
2121    cmp     r1, #0                      @ null array object?
2122    GET_VREG(r9, r9)                    @ r9<- vAA
2123    beq     common_errNullObject        @ yes, bail
2124    ldr     r3, [r1, #offArrayObject_length]    @ r3<- arrayObj->length
2125    add     r10, r1, r0, lsl #2         @ r10<- arrayObj + index*width
2126    cmp     r0, r3                      @ compare unsigned index, length
2127    bcc     .LOP_APUT_OBJECT_finish          @ we're okay, continue on
2128    b       common_errArrayIndex        @ index >= length, bail
2129
2130
2131/* ------------------------------ */
2132    .balign 64
2133.L_OP_APUT_BOOLEAN: /* 0x4e */
2134/* File: armv5te/OP_APUT_BOOLEAN.S */
2135/* File: armv5te/OP_APUT.S */
2136    /*
2137     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2138     *
2139     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2140     * instructions.  We use a pair of FETCH_Bs instead.
2141     *
2142     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2143     */
2144    /* op vAA, vBB, vCC */
2145    FETCH_B(r2, 1, 0)                   @ r2<- BB
2146    mov     r9, rINST, lsr #8           @ r9<- AA
2147    FETCH_B(r3, 1, 1)                   @ r3<- CC
2148    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2149    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2150    cmp     r0, #0                      @ null array object?
2151    beq     common_errNullObject        @ yes, bail
2152    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2153    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2154    cmp     r1, r3                      @ compare unsigned index, length
2155    bcs     common_errArrayIndex        @ index >= length, bail
2156    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2157    GET_VREG(r2, r9)                    @ r2<- vAA
2158    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2159    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2160    GOTO_OPCODE(ip)                     @ jump to next instruction
2161
2162
2163
2164/* ------------------------------ */
2165    .balign 64
2166.L_OP_APUT_BYTE: /* 0x4f */
2167/* File: armv5te/OP_APUT_BYTE.S */
2168/* File: armv5te/OP_APUT.S */
2169    /*
2170     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2171     *
2172     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2173     * instructions.  We use a pair of FETCH_Bs instead.
2174     *
2175     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2176     */
2177    /* op vAA, vBB, vCC */
2178    FETCH_B(r2, 1, 0)                   @ r2<- BB
2179    mov     r9, rINST, lsr #8           @ r9<- AA
2180    FETCH_B(r3, 1, 1)                   @ r3<- CC
2181    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2182    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2183    cmp     r0, #0                      @ null array object?
2184    beq     common_errNullObject        @ yes, bail
2185    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2186    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2187    cmp     r1, r3                      @ compare unsigned index, length
2188    bcs     common_errArrayIndex        @ index >= length, bail
2189    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2190    GET_VREG(r2, r9)                    @ r2<- vAA
2191    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2192    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2193    GOTO_OPCODE(ip)                     @ jump to next instruction
2194
2195
2196
2197/* ------------------------------ */
2198    .balign 64
2199.L_OP_APUT_CHAR: /* 0x50 */
2200/* File: armv5te/OP_APUT_CHAR.S */
2201/* File: armv5te/OP_APUT.S */
2202    /*
2203     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2204     *
2205     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2206     * instructions.  We use a pair of FETCH_Bs instead.
2207     *
2208     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2209     */
2210    /* op vAA, vBB, vCC */
2211    FETCH_B(r2, 1, 0)                   @ r2<- BB
2212    mov     r9, rINST, lsr #8           @ r9<- AA
2213    FETCH_B(r3, 1, 1)                   @ r3<- CC
2214    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2215    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2216    cmp     r0, #0                      @ null array object?
2217    beq     common_errNullObject        @ yes, bail
2218    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2219    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2220    cmp     r1, r3                      @ compare unsigned index, length
2221    bcs     common_errArrayIndex        @ index >= length, bail
2222    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2223    GET_VREG(r2, r9)                    @ r2<- vAA
2224    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2225    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2226    GOTO_OPCODE(ip)                     @ jump to next instruction
2227
2228
2229
2230/* ------------------------------ */
2231    .balign 64
2232.L_OP_APUT_SHORT: /* 0x51 */
2233/* File: armv5te/OP_APUT_SHORT.S */
2234/* File: armv5te/OP_APUT.S */
2235    /*
2236     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2237     *
2238     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2239     * instructions.  We use a pair of FETCH_Bs instead.
2240     *
2241     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2242     */
2243    /* op vAA, vBB, vCC */
2244    FETCH_B(r2, 1, 0)                   @ r2<- BB
2245    mov     r9, rINST, lsr #8           @ r9<- AA
2246    FETCH_B(r3, 1, 1)                   @ r3<- CC
2247    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2248    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2249    cmp     r0, #0                      @ null array object?
2250    beq     common_errNullObject        @ yes, bail
2251    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2252    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2253    cmp     r1, r3                      @ compare unsigned index, length
2254    bcs     common_errArrayIndex        @ index >= length, bail
2255    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2256    GET_VREG(r2, r9)                    @ r2<- vAA
2257    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2258    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2259    GOTO_OPCODE(ip)                     @ jump to next instruction
2260
2261
2262
2263/* ------------------------------ */
2264    .balign 64
2265.L_OP_IGET: /* 0x52 */
2266/* File: armv5te/OP_IGET.S */
2267    /*
2268     * General 32-bit instance field get.
2269     *
2270     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2271     */
2272    /* op vA, vB, field@CCCC */
2273    mov     r0, rINST, lsr #12          @ r0<- B
2274    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2275    FETCH(r1, 1)                        @ r1<- field ref CCCC
2276    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2277    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2278    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2279    cmp     r0, #0                      @ is resolved entry null?
2280    bne     .LOP_IGET_finish          @ no, already resolved
22818:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2282    EXPORT_PC()                         @ resolve() could throw
2283    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2284    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2285    cmp     r0, #0
2286    bne     .LOP_IGET_finish
2287    b       common_exceptionThrown
2288
2289/* ------------------------------ */
2290    .balign 64
2291.L_OP_IGET_WIDE: /* 0x53 */
2292/* File: armv5te/OP_IGET_WIDE.S */
2293    /*
2294     * Wide 32-bit instance field get.
2295     */
2296    /* iget-wide vA, vB, field@CCCC */
2297    mov     r0, rINST, lsr #12          @ r0<- B
2298    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2299    FETCH(r1, 1)                        @ r1<- field ref CCCC
2300    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2301    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2302    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2303    cmp     r0, #0                      @ is resolved entry null?
2304    bne     .LOP_IGET_WIDE_finish          @ no, already resolved
23058:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2306    EXPORT_PC()                         @ resolve() could throw
2307    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2308    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2309    cmp     r0, #0
2310    bne     .LOP_IGET_WIDE_finish
2311    b       common_exceptionThrown
2312
2313/* ------------------------------ */
2314    .balign 64
2315.L_OP_IGET_OBJECT: /* 0x54 */
2316/* File: armv5te/OP_IGET_OBJECT.S */
2317/* File: armv5te/OP_IGET.S */
2318    /*
2319     * General 32-bit instance field get.
2320     *
2321     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2322     */
2323    /* op vA, vB, field@CCCC */
2324    mov     r0, rINST, lsr #12          @ r0<- B
2325    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2326    FETCH(r1, 1)                        @ r1<- field ref CCCC
2327    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2328    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2329    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2330    cmp     r0, #0                      @ is resolved entry null?
2331    bne     .LOP_IGET_OBJECT_finish          @ no, already resolved
23328:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2333    EXPORT_PC()                         @ resolve() could throw
2334    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2335    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2336    cmp     r0, #0
2337    bne     .LOP_IGET_OBJECT_finish
2338    b       common_exceptionThrown
2339
2340
2341/* ------------------------------ */
2342    .balign 64
2343.L_OP_IGET_BOOLEAN: /* 0x55 */
2344/* File: armv5te/OP_IGET_BOOLEAN.S */
2345@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" }
2346/* File: armv5te/OP_IGET.S */
2347    /*
2348     * General 32-bit instance field get.
2349     *
2350     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2351     */
2352    /* op vA, vB, field@CCCC */
2353    mov     r0, rINST, lsr #12          @ r0<- B
2354    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2355    FETCH(r1, 1)                        @ r1<- field ref CCCC
2356    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2357    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2358    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2359    cmp     r0, #0                      @ is resolved entry null?
2360    bne     .LOP_IGET_BOOLEAN_finish          @ no, already resolved
23618:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2362    EXPORT_PC()                         @ resolve() could throw
2363    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2364    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2365    cmp     r0, #0
2366    bne     .LOP_IGET_BOOLEAN_finish
2367    b       common_exceptionThrown
2368
2369
2370/* ------------------------------ */
2371    .balign 64
2372.L_OP_IGET_BYTE: /* 0x56 */
2373/* File: armv5te/OP_IGET_BYTE.S */
2374@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" }
2375/* File: armv5te/OP_IGET.S */
2376    /*
2377     * General 32-bit instance field get.
2378     *
2379     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2380     */
2381    /* op vA, vB, field@CCCC */
2382    mov     r0, rINST, lsr #12          @ r0<- B
2383    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2384    FETCH(r1, 1)                        @ r1<- field ref CCCC
2385    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2386    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2387    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2388    cmp     r0, #0                      @ is resolved entry null?
2389    bne     .LOP_IGET_BYTE_finish          @ no, already resolved
23908:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2391    EXPORT_PC()                         @ resolve() could throw
2392    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2393    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2394    cmp     r0, #0
2395    bne     .LOP_IGET_BYTE_finish
2396    b       common_exceptionThrown
2397
2398
2399/* ------------------------------ */
2400    .balign 64
2401.L_OP_IGET_CHAR: /* 0x57 */
2402/* File: armv5te/OP_IGET_CHAR.S */
2403@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" }
2404/* File: armv5te/OP_IGET.S */
2405    /*
2406     * General 32-bit instance field get.
2407     *
2408     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2409     */
2410    /* op vA, vB, field@CCCC */
2411    mov     r0, rINST, lsr #12          @ r0<- B
2412    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2413    FETCH(r1, 1)                        @ r1<- field ref CCCC
2414    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2415    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2416    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2417    cmp     r0, #0                      @ is resolved entry null?
2418    bne     .LOP_IGET_CHAR_finish          @ no, already resolved
24198:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2420    EXPORT_PC()                         @ resolve() could throw
2421    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2422    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2423    cmp     r0, #0
2424    bne     .LOP_IGET_CHAR_finish
2425    b       common_exceptionThrown
2426
2427
2428/* ------------------------------ */
2429    .balign 64
2430.L_OP_IGET_SHORT: /* 0x58 */
2431/* File: armv5te/OP_IGET_SHORT.S */
2432@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" }
2433/* File: armv5te/OP_IGET.S */
2434    /*
2435     * General 32-bit instance field get.
2436     *
2437     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2438     */
2439    /* op vA, vB, field@CCCC */
2440    mov     r0, rINST, lsr #12          @ r0<- B
2441    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2442    FETCH(r1, 1)                        @ r1<- field ref CCCC
2443    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2444    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2445    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2446    cmp     r0, #0                      @ is resolved entry null?
2447    bne     .LOP_IGET_SHORT_finish          @ no, already resolved
24488:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2449    EXPORT_PC()                         @ resolve() could throw
2450    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2451    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2452    cmp     r0, #0
2453    bne     .LOP_IGET_SHORT_finish
2454    b       common_exceptionThrown
2455
2456
2457/* ------------------------------ */
2458    .balign 64
2459.L_OP_IPUT: /* 0x59 */
2460/* File: armv5te/OP_IPUT.S */
2461    /*
2462     * General 32-bit instance field put.
2463     *
2464     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2465     */
2466    /* op vA, vB, field@CCCC */
2467    mov     r0, rINST, lsr #12          @ r0<- B
2468    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2469    FETCH(r1, 1)                        @ r1<- field ref CCCC
2470    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2471    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2472    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2473    cmp     r0, #0                      @ is resolved entry null?
2474    bne     .LOP_IPUT_finish          @ no, already resolved
24758:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2476    EXPORT_PC()                         @ resolve() could throw
2477    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2478    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2479    cmp     r0, #0                      @ success?
2480    bne     .LOP_IPUT_finish          @ yes, finish up
2481    b       common_exceptionThrown
2482
2483/* ------------------------------ */
2484    .balign 64
2485.L_OP_IPUT_WIDE: /* 0x5a */
2486/* File: armv5te/OP_IPUT_WIDE.S */
2487    /* iput-wide vA, vB, field@CCCC */
2488    mov     r0, rINST, lsr #12          @ r0<- B
2489    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2490    FETCH(r1, 1)                        @ r1<- field ref CCCC
2491    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2492    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2493    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2494    cmp     r0, #0                      @ is resolved entry null?
2495    bne     .LOP_IPUT_WIDE_finish          @ no, already resolved
24968:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2497    EXPORT_PC()                         @ resolve() could throw
2498    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2499    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2500    cmp     r0, #0                      @ success?
2501    bne     .LOP_IPUT_WIDE_finish          @ yes, finish up
2502    b       common_exceptionThrown
2503
2504/* ------------------------------ */
2505    .balign 64
2506.L_OP_IPUT_OBJECT: /* 0x5b */
2507/* File: armv5te/OP_IPUT_OBJECT.S */
2508/* File: armv5te/OP_IPUT.S */
2509    /*
2510     * General 32-bit instance field put.
2511     *
2512     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2513     */
2514    /* op vA, vB, field@CCCC */
2515    mov     r0, rINST, lsr #12          @ r0<- B
2516    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2517    FETCH(r1, 1)                        @ r1<- field ref CCCC
2518    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2519    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2520    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2521    cmp     r0, #0                      @ is resolved entry null?
2522    bne     .LOP_IPUT_OBJECT_finish          @ no, already resolved
25238:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2524    EXPORT_PC()                         @ resolve() could throw
2525    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2526    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2527    cmp     r0, #0                      @ success?
2528    bne     .LOP_IPUT_OBJECT_finish          @ yes, finish up
2529    b       common_exceptionThrown
2530
2531
2532/* ------------------------------ */
2533    .balign 64
2534.L_OP_IPUT_BOOLEAN: /* 0x5c */
2535/* File: armv5te/OP_IPUT_BOOLEAN.S */
2536@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" }
2537/* File: armv5te/OP_IPUT.S */
2538    /*
2539     * General 32-bit instance field put.
2540     *
2541     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2542     */
2543    /* op vA, vB, field@CCCC */
2544    mov     r0, rINST, lsr #12          @ r0<- B
2545    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2546    FETCH(r1, 1)                        @ r1<- field ref CCCC
2547    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2548    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2549    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2550    cmp     r0, #0                      @ is resolved entry null?
2551    bne     .LOP_IPUT_BOOLEAN_finish          @ no, already resolved
25528:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2553    EXPORT_PC()                         @ resolve() could throw
2554    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2555    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2556    cmp     r0, #0                      @ success?
2557    bne     .LOP_IPUT_BOOLEAN_finish          @ yes, finish up
2558    b       common_exceptionThrown
2559
2560
2561/* ------------------------------ */
2562    .balign 64
2563.L_OP_IPUT_BYTE: /* 0x5d */
2564/* File: armv5te/OP_IPUT_BYTE.S */
2565@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" }
2566/* File: armv5te/OP_IPUT.S */
2567    /*
2568     * General 32-bit instance field put.
2569     *
2570     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2571     */
2572    /* op vA, vB, field@CCCC */
2573    mov     r0, rINST, lsr #12          @ r0<- B
2574    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2575    FETCH(r1, 1)                        @ r1<- field ref CCCC
2576    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2577    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2578    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2579    cmp     r0, #0                      @ is resolved entry null?
2580    bne     .LOP_IPUT_BYTE_finish          @ no, already resolved
25818:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2582    EXPORT_PC()                         @ resolve() could throw
2583    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2584    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2585    cmp     r0, #0                      @ success?
2586    bne     .LOP_IPUT_BYTE_finish          @ yes, finish up
2587    b       common_exceptionThrown
2588
2589
2590/* ------------------------------ */
2591    .balign 64
2592.L_OP_IPUT_CHAR: /* 0x5e */
2593/* File: armv5te/OP_IPUT_CHAR.S */
2594@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" }
2595/* File: armv5te/OP_IPUT.S */
2596    /*
2597     * General 32-bit instance field put.
2598     *
2599     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2600     */
2601    /* op vA, vB, field@CCCC */
2602    mov     r0, rINST, lsr #12          @ r0<- B
2603    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2604    FETCH(r1, 1)                        @ r1<- field ref CCCC
2605    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2606    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2607    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2608    cmp     r0, #0                      @ is resolved entry null?
2609    bne     .LOP_IPUT_CHAR_finish          @ no, already resolved
26108:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2611    EXPORT_PC()                         @ resolve() could throw
2612    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2613    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2614    cmp     r0, #0                      @ success?
2615    bne     .LOP_IPUT_CHAR_finish          @ yes, finish up
2616    b       common_exceptionThrown
2617
2618
2619/* ------------------------------ */
2620    .balign 64
2621.L_OP_IPUT_SHORT: /* 0x5f */
2622/* File: armv5te/OP_IPUT_SHORT.S */
2623@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" }
2624/* File: armv5te/OP_IPUT.S */
2625    /*
2626     * General 32-bit instance field put.
2627     *
2628     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2629     */
2630    /* op vA, vB, field@CCCC */
2631    mov     r0, rINST, lsr #12          @ r0<- B
2632    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2633    FETCH(r1, 1)                        @ r1<- field ref CCCC
2634    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2635    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2636    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2637    cmp     r0, #0                      @ is resolved entry null?
2638    bne     .LOP_IPUT_SHORT_finish          @ no, already resolved
26398:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2640    EXPORT_PC()                         @ resolve() could throw
2641    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2642    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2643    cmp     r0, #0                      @ success?
2644    bne     .LOP_IPUT_SHORT_finish          @ yes, finish up
2645    b       common_exceptionThrown
2646
2647
2648/* ------------------------------ */
2649    .balign 64
2650.L_OP_SGET: /* 0x60 */
2651/* File: armv5te/OP_SGET.S */
2652    /*
2653     * General 32-bit SGET handler.
2654     *
2655     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2656     */
2657    /* op vAA, field@BBBB */
2658    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2659    FETCH(r1, 1)                        @ r1<- field ref BBBB
2660    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2661    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2662    cmp     r0, #0                      @ is resolved entry null?
2663    beq     .LOP_SGET_resolve         @ yes, do resolve
2664.LOP_SGET_finish: @ field ptr in r0
2665    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2666    mov     r2, rINST, lsr #8           @ r2<- AA
2667    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2668    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2669    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2670    GOTO_OPCODE(ip)                     @ jump to next instruction
2671
2672/* ------------------------------ */
2673    .balign 64
2674.L_OP_SGET_WIDE: /* 0x61 */
2675/* File: armv5te/OP_SGET_WIDE.S */
2676    /*
2677     * 64-bit SGET handler.
2678     */
2679    /* sget-wide vAA, field@BBBB */
2680    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2681    FETCH(r1, 1)                        @ r1<- field ref BBBB
2682    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2683    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2684    cmp     r0, #0                      @ is resolved entry null?
2685    beq     .LOP_SGET_WIDE_resolve         @ yes, do resolve
2686.LOP_SGET_WIDE_finish:
2687    mov     r1, rINST, lsr #8           @ r1<- AA
2688    ldrd    r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned)
2689    add     r1, rFP, r1, lsl #2         @ r1<- &fp[AA]
2690    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2691    stmia   r1, {r2-r3}                 @ vAA/vAA+1<- r2/r3
2692    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2693    GOTO_OPCODE(ip)                     @ jump to next instruction
2694
2695/* ------------------------------ */
2696    .balign 64
2697.L_OP_SGET_OBJECT: /* 0x62 */
2698/* File: armv5te/OP_SGET_OBJECT.S */
2699/* File: armv5te/OP_SGET.S */
2700    /*
2701     * General 32-bit SGET handler.
2702     *
2703     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2704     */
2705    /* op vAA, field@BBBB */
2706    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2707    FETCH(r1, 1)                        @ r1<- field ref BBBB
2708    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2709    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2710    cmp     r0, #0                      @ is resolved entry null?
2711    beq     .LOP_SGET_OBJECT_resolve         @ yes, do resolve
2712.LOP_SGET_OBJECT_finish: @ field ptr in r0
2713    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2714    mov     r2, rINST, lsr #8           @ r2<- AA
2715    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2716    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2717    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2718    GOTO_OPCODE(ip)                     @ jump to next instruction
2719
2720
2721/* ------------------------------ */
2722    .balign 64
2723.L_OP_SGET_BOOLEAN: /* 0x63 */
2724/* File: armv5te/OP_SGET_BOOLEAN.S */
2725/* File: armv5te/OP_SGET.S */
2726    /*
2727     * General 32-bit SGET handler.
2728     *
2729     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2730     */
2731    /* op vAA, field@BBBB */
2732    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2733    FETCH(r1, 1)                        @ r1<- field ref BBBB
2734    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2735    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2736    cmp     r0, #0                      @ is resolved entry null?
2737    beq     .LOP_SGET_BOOLEAN_resolve         @ yes, do resolve
2738.LOP_SGET_BOOLEAN_finish: @ field ptr in r0
2739    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2740    mov     r2, rINST, lsr #8           @ r2<- AA
2741    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2742    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2743    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2744    GOTO_OPCODE(ip)                     @ jump to next instruction
2745
2746
2747/* ------------------------------ */
2748    .balign 64
2749.L_OP_SGET_BYTE: /* 0x64 */
2750/* File: armv5te/OP_SGET_BYTE.S */
2751/* File: armv5te/OP_SGET.S */
2752    /*
2753     * General 32-bit SGET handler.
2754     *
2755     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2756     */
2757    /* op vAA, field@BBBB */
2758    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2759    FETCH(r1, 1)                        @ r1<- field ref BBBB
2760    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2761    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2762    cmp     r0, #0                      @ is resolved entry null?
2763    beq     .LOP_SGET_BYTE_resolve         @ yes, do resolve
2764.LOP_SGET_BYTE_finish: @ field ptr in r0
2765    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2766    mov     r2, rINST, lsr #8           @ r2<- AA
2767    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2768    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2769    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2770    GOTO_OPCODE(ip)                     @ jump to next instruction
2771
2772
2773/* ------------------------------ */
2774    .balign 64
2775.L_OP_SGET_CHAR: /* 0x65 */
2776/* File: armv5te/OP_SGET_CHAR.S */
2777/* File: armv5te/OP_SGET.S */
2778    /*
2779     * General 32-bit SGET handler.
2780     *
2781     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2782     */
2783    /* op vAA, field@BBBB */
2784    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2785    FETCH(r1, 1)                        @ r1<- field ref BBBB
2786    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2787    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2788    cmp     r0, #0                      @ is resolved entry null?
2789    beq     .LOP_SGET_CHAR_resolve         @ yes, do resolve
2790.LOP_SGET_CHAR_finish: @ field ptr in r0
2791    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2792    mov     r2, rINST, lsr #8           @ r2<- AA
2793    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2794    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2795    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2796    GOTO_OPCODE(ip)                     @ jump to next instruction
2797
2798
2799/* ------------------------------ */
2800    .balign 64
2801.L_OP_SGET_SHORT: /* 0x66 */
2802/* File: armv5te/OP_SGET_SHORT.S */
2803/* File: armv5te/OP_SGET.S */
2804    /*
2805     * General 32-bit SGET handler.
2806     *
2807     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2808     */
2809    /* op vAA, field@BBBB */
2810    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2811    FETCH(r1, 1)                        @ r1<- field ref BBBB
2812    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2813    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2814    cmp     r0, #0                      @ is resolved entry null?
2815    beq     .LOP_SGET_SHORT_resolve         @ yes, do resolve
2816.LOP_SGET_SHORT_finish: @ field ptr in r0
2817    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2818    mov     r2, rINST, lsr #8           @ r2<- AA
2819    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2820    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2821    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2822    GOTO_OPCODE(ip)                     @ jump to next instruction
2823
2824
2825/* ------------------------------ */
2826    .balign 64
2827.L_OP_SPUT: /* 0x67 */
2828/* File: armv5te/OP_SPUT.S */
2829    /*
2830     * General 32-bit SPUT handler.
2831     *
2832     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2833     */
2834    /* op vAA, field@BBBB */
2835    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2836    FETCH(r1, 1)                        @ r1<- field ref BBBB
2837    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2838    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2839    cmp     r0, #0                      @ is resolved entry null?
2840    beq     .LOP_SPUT_resolve         @ yes, do resolve
2841.LOP_SPUT_finish:   @ field ptr in r0
2842    mov     r2, rINST, lsr #8           @ r2<- AA
2843    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2844    GET_VREG(r1, r2)                    @ r1<- fp[AA]
2845    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2846    str     r1, [r0, #offStaticField_value] @ field<- vAA
2847    GOTO_OPCODE(ip)                     @ jump to next instruction
2848
2849/* ------------------------------ */
2850    .balign 64
2851.L_OP_SPUT_WIDE: /* 0x68 */
2852/* File: armv5te/OP_SPUT_WIDE.S */
2853    /*
2854     * 64-bit SPUT handler.
2855     */
2856    /* sput-wide vAA, field@BBBB */
2857    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2858    FETCH(r1, 1)                        @ r1<- field ref BBBB
2859    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2860    mov     r9, rINST, lsr #8           @ r9<- AA
2861    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2862    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2863    cmp     r0, #0                      @ is resolved entry null?
2864    beq     .LOP_SPUT_WIDE_resolve         @ yes, do resolve
2865.LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9
2866    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2867    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
2868    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2869    strd    r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1
2870    GOTO_OPCODE(ip)                     @ jump to next instruction
2871
2872/* ------------------------------ */
2873    .balign 64
2874.L_OP_SPUT_OBJECT: /* 0x69 */
2875/* File: armv5te/OP_SPUT_OBJECT.S */
2876/* File: armv5te/OP_SPUT.S */
2877    /*
2878     * General 32-bit SPUT handler.
2879     *
2880     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2881     */
2882    /* op vAA, field@BBBB */
2883    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2884    FETCH(r1, 1)                        @ r1<- field ref BBBB
2885    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2886    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2887    cmp     r0, #0                      @ is resolved entry null?
2888    beq     .LOP_SPUT_OBJECT_resolve         @ yes, do resolve
2889.LOP_SPUT_OBJECT_finish:   @ field ptr in r0
2890    mov     r2, rINST, lsr #8           @ r2<- AA
2891    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2892    GET_VREG(r1, r2)                    @ r1<- fp[AA]
2893    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2894    str     r1, [r0, #offStaticField_value] @ field<- vAA
2895    GOTO_OPCODE(ip)                     @ jump to next instruction
2896
2897
2898/* ------------------------------ */
2899    .balign 64
2900.L_OP_SPUT_BOOLEAN: /* 0x6a */
2901/* File: armv5te/OP_SPUT_BOOLEAN.S */
2902/* File: armv5te/OP_SPUT.S */
2903    /*
2904     * General 32-bit SPUT handler.
2905     *
2906     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2907     */
2908    /* op vAA, field@BBBB */
2909    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2910    FETCH(r1, 1)                        @ r1<- field ref BBBB
2911    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2912    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2913    cmp     r0, #0                      @ is resolved entry null?
2914    beq     .LOP_SPUT_BOOLEAN_resolve         @ yes, do resolve
2915.LOP_SPUT_BOOLEAN_finish:   @ field ptr in r0
2916    mov     r2, rINST, lsr #8           @ r2<- AA
2917    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2918    GET_VREG(r1, r2)                    @ r1<- fp[AA]
2919    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2920    str     r1, [r0, #offStaticField_value] @ field<- vAA
2921    GOTO_OPCODE(ip)                     @ jump to next instruction
2922
2923
2924/* ------------------------------ */
2925    .balign 64
2926.L_OP_SPUT_BYTE: /* 0x6b */
2927/* File: armv5te/OP_SPUT_BYTE.S */
2928/* File: armv5te/OP_SPUT.S */
2929    /*
2930     * General 32-bit SPUT handler.
2931     *
2932     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2933     */
2934    /* op vAA, field@BBBB */
2935    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2936    FETCH(r1, 1)                        @ r1<- field ref BBBB
2937    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2938    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2939    cmp     r0, #0                      @ is resolved entry null?
2940    beq     .LOP_SPUT_BYTE_resolve         @ yes, do resolve
2941.LOP_SPUT_BYTE_finish:   @ field ptr in r0
2942    mov     r2, rINST, lsr #8           @ r2<- AA
2943    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2944    GET_VREG(r1, r2)                    @ r1<- fp[AA]
2945    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2946    str     r1, [r0, #offStaticField_value] @ field<- vAA
2947    GOTO_OPCODE(ip)                     @ jump to next instruction
2948
2949
2950/* ------------------------------ */
2951    .balign 64
2952.L_OP_SPUT_CHAR: /* 0x6c */
2953/* File: armv5te/OP_SPUT_CHAR.S */
2954/* File: armv5te/OP_SPUT.S */
2955    /*
2956     * General 32-bit SPUT handler.
2957     *
2958     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2959     */
2960    /* op vAA, field@BBBB */
2961    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2962    FETCH(r1, 1)                        @ r1<- field ref BBBB
2963    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2964    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2965    cmp     r0, #0                      @ is resolved entry null?
2966    beq     .LOP_SPUT_CHAR_resolve         @ yes, do resolve
2967.LOP_SPUT_CHAR_finish:   @ field ptr in r0
2968    mov     r2, rINST, lsr #8           @ r2<- AA
2969    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2970    GET_VREG(r1, r2)                    @ r1<- fp[AA]
2971    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2972    str     r1, [r0, #offStaticField_value] @ field<- vAA
2973    GOTO_OPCODE(ip)                     @ jump to next instruction
2974
2975
2976/* ------------------------------ */
2977    .balign 64
2978.L_OP_SPUT_SHORT: /* 0x6d */
2979/* File: armv5te/OP_SPUT_SHORT.S */
2980/* File: armv5te/OP_SPUT.S */
2981    /*
2982     * General 32-bit SPUT handler.
2983     *
2984     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2985     */
2986    /* op vAA, field@BBBB */
2987    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2988    FETCH(r1, 1)                        @ r1<- field ref BBBB
2989    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2990    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2991    cmp     r0, #0                      @ is resolved entry null?
2992    beq     .LOP_SPUT_SHORT_resolve         @ yes, do resolve
2993.LOP_SPUT_SHORT_finish:   @ field ptr in r0
2994    mov     r2, rINST, lsr #8           @ r2<- AA
2995    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2996    GET_VREG(r1, r2)                    @ r1<- fp[AA]
2997    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2998    str     r1, [r0, #offStaticField_value] @ field<- vAA
2999    GOTO_OPCODE(ip)                     @ jump to next instruction
3000
3001
3002/* ------------------------------ */
3003    .balign 64
3004.L_OP_INVOKE_VIRTUAL: /* 0x6e */
3005/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3006    /*
3007     * Handle a virtual method call.
3008     *
3009     * for: invoke-virtual, invoke-virtual/range
3010     */
3011    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3012    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3013    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3014    FETCH(r1, 1)                        @ r1<- BBBB
3015    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3016    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3017    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3018    .if     (!0)
3019    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3020    .endif
3021    cmp     r0, #0                      @ already resolved?
3022    EXPORT_PC()                         @ must export for invoke
3023    bne     .LOP_INVOKE_VIRTUAL_continue        @ yes, continue on
3024    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3025    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3026    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3027    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3028    cmp     r0, #0                      @ got null?
3029    bne     .LOP_INVOKE_VIRTUAL_continue        @ no, continue
3030    b       common_exceptionThrown      @ yes, handle exception
3031
3032/* ------------------------------ */
3033    .balign 64
3034.L_OP_INVOKE_SUPER: /* 0x6f */
3035/* File: armv5te/OP_INVOKE_SUPER.S */
3036    /*
3037     * Handle a "super" method call.
3038     *
3039     * for: invoke-super, invoke-super/range
3040     */
3041    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3042    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3043    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3044    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3045    .if     (!0)
3046    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3047    .endif
3048    FETCH(r1, 1)                        @ r1<- BBBB
3049    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3050    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3051    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3052    cmp     r2, #0                      @ null "this"?
3053    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3054    beq     common_errNullObject        @ null "this", throw exception
3055    cmp     r0, #0                      @ already resolved?
3056    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3057    EXPORT_PC()                         @ must export for invoke
3058    bne     .LOP_INVOKE_SUPER_continue        @ resolved, continue on
3059    b       .LOP_INVOKE_SUPER_resolve         @ do resolve now
3060
3061/* ------------------------------ */
3062    .balign 64
3063.L_OP_INVOKE_DIRECT: /* 0x70 */
3064/* File: armv5te/OP_INVOKE_DIRECT.S */
3065    /*
3066     * Handle a direct method call.
3067     *
3068     * (We could defer the "is 'this' pointer null" test to the common
3069     * method invocation code, and use a flag to indicate that static
3070     * calls don't count.  If we do this as part of copying the arguments
3071     * out we could avoiding loading the first arg twice.)
3072     *
3073     * for: invoke-direct, invoke-direct/range
3074     */
3075    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3076    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3077    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3078    FETCH(r1, 1)                        @ r1<- BBBB
3079    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3080    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3081    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3082    .if     (!0)
3083    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3084    .endif
3085    cmp     r0, #0                      @ already resolved?
3086    EXPORT_PC()                         @ must export for invoke
3087    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3088    beq     .LOP_INVOKE_DIRECT_resolve         @ not resolved, do it now
3089.LOP_INVOKE_DIRECT_finish:
3090    cmp     r2, #0                      @ null "this" ref?
3091    bne     common_invokeMethodNoRange   @ no, continue on
3092    b       common_errNullObject        @ yes, throw exception
3093
3094/* ------------------------------ */
3095    .balign 64
3096.L_OP_INVOKE_STATIC: /* 0x71 */
3097/* File: armv5te/OP_INVOKE_STATIC.S */
3098    /*
3099     * Handle a static method call.
3100     *
3101     * for: invoke-static, invoke-static/range
3102     */
3103    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3104    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3105    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3106    FETCH(r1, 1)                        @ r1<- BBBB
3107    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3108    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3109    cmp     r0, #0                      @ already resolved?
3110    EXPORT_PC()                         @ must export for invoke
3111    bne     common_invokeMethodNoRange @ yes, continue on
31120:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3113    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3114    mov     r2, #METHOD_STATIC          @ resolver method type
3115    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3116    cmp     r0, #0                      @ got null?
3117    bne     common_invokeMethodNoRange @ no, continue
3118    b       common_exceptionThrown      @ yes, handle exception
3119
3120
3121/* ------------------------------ */
3122    .balign 64
3123.L_OP_INVOKE_INTERFACE: /* 0x72 */
3124/* File: armv5te/OP_INVOKE_INTERFACE.S */
3125    /*
3126     * Handle an interface method call.
3127     *
3128     * for: invoke-interface, invoke-interface/range
3129     */
3130    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3131    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3132    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3133    FETCH(r1, 1)                        @ r1<- BBBB
3134    .if     (!0)
3135    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3136    .endif
3137    EXPORT_PC()                         @ must export for invoke
3138    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3139    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3140    cmp     r0, #0                      @ null obj?
3141    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3142    beq     common_errNullObject        @ yes, fail
3143    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3144    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3145    cmp     r0, #0                      @ failed?
3146    beq     common_exceptionThrown      @ yes, handle exception
3147    b       common_invokeMethodNoRange @ jump to common handler
3148
3149
3150/* ------------------------------ */
3151    .balign 64
3152.L_OP_UNUSED_73: /* 0x73 */
3153/* File: armv5te/OP_UNUSED_73.S */
3154/* File: armv5te/unused.S */
3155    bl      common_abort
3156
3157
3158
3159/* ------------------------------ */
3160    .balign 64
3161.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
3162/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */
3163/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3164    /*
3165     * Handle a virtual method call.
3166     *
3167     * for: invoke-virtual, invoke-virtual/range
3168     */
3169    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3170    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3171    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3172    FETCH(r1, 1)                        @ r1<- BBBB
3173    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3174    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3175    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3176    .if     (!1)
3177    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3178    .endif
3179    cmp     r0, #0                      @ already resolved?
3180    EXPORT_PC()                         @ must export for invoke
3181    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ yes, continue on
3182    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3183    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3184    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3185    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3186    cmp     r0, #0                      @ got null?
3187    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ no, continue
3188    b       common_exceptionThrown      @ yes, handle exception
3189
3190
3191/* ------------------------------ */
3192    .balign 64
3193.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
3194/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */
3195/* File: armv5te/OP_INVOKE_SUPER.S */
3196    /*
3197     * Handle a "super" method call.
3198     *
3199     * for: invoke-super, invoke-super/range
3200     */
3201    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3202    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3203    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3204    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3205    .if     (!1)
3206    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3207    .endif
3208    FETCH(r1, 1)                        @ r1<- BBBB
3209    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3210    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3211    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3212    cmp     r2, #0                      @ null "this"?
3213    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3214    beq     common_errNullObject        @ null "this", throw exception
3215    cmp     r0, #0                      @ already resolved?
3216    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3217    EXPORT_PC()                         @ must export for invoke
3218    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ resolved, continue on
3219    b       .LOP_INVOKE_SUPER_RANGE_resolve         @ do resolve now
3220
3221
3222/* ------------------------------ */
3223    .balign 64
3224.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
3225/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */
3226/* File: armv5te/OP_INVOKE_DIRECT.S */
3227    /*
3228     * Handle a direct method call.
3229     *
3230     * (We could defer the "is 'this' pointer null" test to the common
3231     * method invocation code, and use a flag to indicate that static
3232     * calls don't count.  If we do this as part of copying the arguments
3233     * out we could avoiding loading the first arg twice.)
3234     *
3235     * for: invoke-direct, invoke-direct/range
3236     */
3237    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3238    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3239    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3240    FETCH(r1, 1)                        @ r1<- BBBB
3241    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3242    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3243    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3244    .if     (!1)
3245    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3246    .endif
3247    cmp     r0, #0                      @ already resolved?
3248    EXPORT_PC()                         @ must export for invoke
3249    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3250    beq     .LOP_INVOKE_DIRECT_RANGE_resolve         @ not resolved, do it now
3251.LOP_INVOKE_DIRECT_RANGE_finish:
3252    cmp     r2, #0                      @ null "this" ref?
3253    bne     common_invokeMethodRange   @ no, continue on
3254    b       common_errNullObject        @ yes, throw exception
3255
3256
3257/* ------------------------------ */
3258    .balign 64
3259.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
3260/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */
3261/* File: armv5te/OP_INVOKE_STATIC.S */
3262    /*
3263     * Handle a static method call.
3264     *
3265     * for: invoke-static, invoke-static/range
3266     */
3267    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3268    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3269    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3270    FETCH(r1, 1)                        @ r1<- BBBB
3271    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3272    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3273    cmp     r0, #0                      @ already resolved?
3274    EXPORT_PC()                         @ must export for invoke
3275    bne     common_invokeMethodRange @ yes, continue on
32760:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3277    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3278    mov     r2, #METHOD_STATIC          @ resolver method type
3279    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3280    cmp     r0, #0                      @ got null?
3281    bne     common_invokeMethodRange @ no, continue
3282    b       common_exceptionThrown      @ yes, handle exception
3283
3284
3285
3286/* ------------------------------ */
3287    .balign 64
3288.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
3289/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */
3290/* File: armv5te/OP_INVOKE_INTERFACE.S */
3291    /*
3292     * Handle an interface method call.
3293     *
3294     * for: invoke-interface, invoke-interface/range
3295     */
3296    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3297    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3298    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3299    FETCH(r1, 1)                        @ r1<- BBBB
3300    .if     (!1)
3301    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3302    .endif
3303    EXPORT_PC()                         @ must export for invoke
3304    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3305    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3306    cmp     r0, #0                      @ null obj?
3307    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3308    beq     common_errNullObject        @ yes, fail
3309    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3310    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3311    cmp     r0, #0                      @ failed?
3312    beq     common_exceptionThrown      @ yes, handle exception
3313    b       common_invokeMethodRange @ jump to common handler
3314
3315
3316
3317/* ------------------------------ */
3318    .balign 64
3319.L_OP_UNUSED_79: /* 0x79 */
3320/* File: armv5te/OP_UNUSED_79.S */
3321/* File: armv5te/unused.S */
3322    bl      common_abort
3323
3324
3325
3326/* ------------------------------ */
3327    .balign 64
3328.L_OP_UNUSED_7A: /* 0x7a */
3329/* File: armv5te/OP_UNUSED_7A.S */
3330/* File: armv5te/unused.S */
3331    bl      common_abort
3332
3333
3334
3335/* ------------------------------ */
3336    .balign 64
3337.L_OP_NEG_INT: /* 0x7b */
3338/* File: armv5te/OP_NEG_INT.S */
3339/* File: armv5te/unop.S */
3340    /*
3341     * Generic 32-bit unary operation.  Provide an "instr" line that
3342     * specifies an instruction that performs "result = op r0".
3343     * This could be an ARM instruction or a function call.
3344     *
3345     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3346     *      int-to-byte, int-to-char, int-to-short
3347     */
3348    /* unop vA, vB */
3349    mov     r3, rINST, lsr #12          @ r3<- B
3350    mov     r9, rINST, lsr #8           @ r9<- A+
3351    GET_VREG(r0, r3)                    @ r0<- vB
3352    and     r9, r9, #15
3353                               @ optional op; may set condition codes
3354    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3355    rsb     r0, r0, #0                              @ r0<- op, r0-r3 changed
3356    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3357    SET_VREG(r0, r9)                    @ vAA<- r0
3358    GOTO_OPCODE(ip)                     @ jump to next instruction
3359    /* 9-10 instructions */
3360
3361
3362/* ------------------------------ */
3363    .balign 64
3364.L_OP_NOT_INT: /* 0x7c */
3365/* File: armv5te/OP_NOT_INT.S */
3366/* File: armv5te/unop.S */
3367    /*
3368     * Generic 32-bit unary operation.  Provide an "instr" line that
3369     * specifies an instruction that performs "result = op r0".
3370     * This could be an ARM instruction or a function call.
3371     *
3372     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3373     *      int-to-byte, int-to-char, int-to-short
3374     */
3375    /* unop vA, vB */
3376    mov     r3, rINST, lsr #12          @ r3<- B
3377    mov     r9, rINST, lsr #8           @ r9<- A+
3378    GET_VREG(r0, r3)                    @ r0<- vB
3379    and     r9, r9, #15
3380                               @ optional op; may set condition codes
3381    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3382    mvn     r0, r0                              @ r0<- op, r0-r3 changed
3383    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3384    SET_VREG(r0, r9)                    @ vAA<- r0
3385    GOTO_OPCODE(ip)                     @ jump to next instruction
3386    /* 9-10 instructions */
3387
3388
3389/* ------------------------------ */
3390    .balign 64
3391.L_OP_NEG_LONG: /* 0x7d */
3392/* File: armv5te/OP_NEG_LONG.S */
3393/* File: armv5te/unopWide.S */
3394    /*
3395     * Generic 64-bit unary operation.  Provide an "instr" line that
3396     * specifies an instruction that performs "result = op r0/r1".
3397     * This could be an ARM instruction or a function call.
3398     *
3399     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3400     */
3401    /* unop vA, vB */
3402    mov     r9, rINST, lsr #8           @ r9<- A+
3403    mov     r3, rINST, lsr #12          @ r3<- B
3404    and     r9, r9, #15
3405    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3406    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3407    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3408    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3409    rsbs    r0, r0, #0                           @ optional op; may set condition codes
3410    rsc     r1, r1, #0                              @ r0/r1<- op, r2-r3 changed
3411    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3412    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3413    GOTO_OPCODE(ip)                     @ jump to next instruction
3414    /* 12-13 instructions */
3415
3416
3417
3418/* ------------------------------ */
3419    .balign 64
3420.L_OP_NOT_LONG: /* 0x7e */
3421/* File: armv5te/OP_NOT_LONG.S */
3422/* File: armv5te/unopWide.S */
3423    /*
3424     * Generic 64-bit unary operation.  Provide an "instr" line that
3425     * specifies an instruction that performs "result = op r0/r1".
3426     * This could be an ARM instruction or a function call.
3427     *
3428     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3429     */
3430    /* unop vA, vB */
3431    mov     r9, rINST, lsr #8           @ r9<- A+
3432    mov     r3, rINST, lsr #12          @ r3<- B
3433    and     r9, r9, #15
3434    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3435    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3436    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3437    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3438    mvn     r0, r0                           @ optional op; may set condition codes
3439    mvn     r1, r1                              @ r0/r1<- op, r2-r3 changed
3440    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3441    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3442    GOTO_OPCODE(ip)                     @ jump to next instruction
3443    /* 12-13 instructions */
3444
3445
3446
3447/* ------------------------------ */
3448    .balign 64
3449.L_OP_NEG_FLOAT: /* 0x7f */
3450/* File: armv5te/OP_NEG_FLOAT.S */
3451/* File: armv5te/unop.S */
3452    /*
3453     * Generic 32-bit unary operation.  Provide an "instr" line that
3454     * specifies an instruction that performs "result = op r0".
3455     * This could be an ARM instruction or a function call.
3456     *
3457     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3458     *      int-to-byte, int-to-char, int-to-short
3459     */
3460    /* unop vA, vB */
3461    mov     r3, rINST, lsr #12          @ r3<- B
3462    mov     r9, rINST, lsr #8           @ r9<- A+
3463    GET_VREG(r0, r3)                    @ r0<- vB
3464    and     r9, r9, #15
3465                               @ optional op; may set condition codes
3466    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3467    add     r0, r0, #0x80000000                              @ r0<- op, r0-r3 changed
3468    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3469    SET_VREG(r0, r9)                    @ vAA<- r0
3470    GOTO_OPCODE(ip)                     @ jump to next instruction
3471    /* 9-10 instructions */
3472
3473
3474/* ------------------------------ */
3475    .balign 64
3476.L_OP_NEG_DOUBLE: /* 0x80 */
3477/* File: armv5te/OP_NEG_DOUBLE.S */
3478/* File: armv5te/unopWide.S */
3479    /*
3480     * Generic 64-bit unary operation.  Provide an "instr" line that
3481     * specifies an instruction that performs "result = op r0/r1".
3482     * This could be an ARM instruction or a function call.
3483     *
3484     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3485     */
3486    /* unop vA, vB */
3487    mov     r9, rINST, lsr #8           @ r9<- A+
3488    mov     r3, rINST, lsr #12          @ r3<- B
3489    and     r9, r9, #15
3490    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3491    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3492    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3493    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3494                               @ optional op; may set condition codes
3495    add     r1, r1, #0x80000000                              @ r0/r1<- op, r2-r3 changed
3496    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3497    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3498    GOTO_OPCODE(ip)                     @ jump to next instruction
3499    /* 12-13 instructions */
3500
3501
3502
3503/* ------------------------------ */
3504    .balign 64
3505.L_OP_INT_TO_LONG: /* 0x81 */
3506/* File: armv5te/OP_INT_TO_LONG.S */
3507/* File: armv5te/unopWider.S */
3508    /*
3509     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3510     * that specifies an instruction that performs "result = op r0", where
3511     * "result" is a 64-bit quantity in r0/r1.
3512     *
3513     * For: int-to-long, int-to-double, float-to-long, float-to-double
3514     */
3515    /* unop vA, vB */
3516    mov     r9, rINST, lsr #8           @ r9<- A+
3517    mov     r3, rINST, lsr #12          @ r3<- B
3518    and     r9, r9, #15
3519    GET_VREG(r0, r3)                    @ r0<- vB
3520    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3521                               @ optional op; may set condition codes
3522    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3523    mov     r1, r0, asr #31                              @ r0<- op, r0-r3 changed
3524    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3525    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3526    GOTO_OPCODE(ip)                     @ jump to next instruction
3527    /* 10-11 instructions */
3528
3529
3530/* ------------------------------ */
3531    .balign 64
3532.L_OP_INT_TO_FLOAT: /* 0x82 */
3533/* File: armv5te/OP_INT_TO_FLOAT.S */
3534/* File: armv5te/unop.S */
3535    /*
3536     * Generic 32-bit unary operation.  Provide an "instr" line that
3537     * specifies an instruction that performs "result = op r0".
3538     * This could be an ARM instruction or a function call.
3539     *
3540     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3541     *      int-to-byte, int-to-char, int-to-short
3542     */
3543    /* unop vA, vB */
3544    mov     r3, rINST, lsr #12          @ r3<- B
3545    mov     r9, rINST, lsr #8           @ r9<- A+
3546    GET_VREG(r0, r3)                    @ r0<- vB
3547    and     r9, r9, #15
3548                               @ optional op; may set condition codes
3549    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3550    bl      __aeabi_i2f                              @ r0<- op, r0-r3 changed
3551    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3552    SET_VREG(r0, r9)                    @ vAA<- r0
3553    GOTO_OPCODE(ip)                     @ jump to next instruction
3554    /* 9-10 instructions */
3555
3556
3557/* ------------------------------ */
3558    .balign 64
3559.L_OP_INT_TO_DOUBLE: /* 0x83 */
3560/* File: armv5te/OP_INT_TO_DOUBLE.S */
3561/* File: armv5te/unopWider.S */
3562    /*
3563     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3564     * that specifies an instruction that performs "result = op r0", where
3565     * "result" is a 64-bit quantity in r0/r1.
3566     *
3567     * For: int-to-long, int-to-double, float-to-long, float-to-double
3568     */
3569    /* unop vA, vB */
3570    mov     r9, rINST, lsr #8           @ r9<- A+
3571    mov     r3, rINST, lsr #12          @ r3<- B
3572    and     r9, r9, #15
3573    GET_VREG(r0, r3)                    @ r0<- vB
3574    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3575                               @ optional op; may set condition codes
3576    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3577    bl      __aeabi_i2d                              @ r0<- op, r0-r3 changed
3578    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3579    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3580    GOTO_OPCODE(ip)                     @ jump to next instruction
3581    /* 10-11 instructions */
3582
3583
3584/* ------------------------------ */
3585    .balign 64
3586.L_OP_LONG_TO_INT: /* 0x84 */
3587/* File: armv5te/OP_LONG_TO_INT.S */
3588/* we ignore the high word, making this equivalent to a 32-bit reg move */
3589/* File: armv5te/OP_MOVE.S */
3590    /* for move, move-object, long-to-int */
3591    /* op vA, vB */
3592    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
3593    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
3594    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3595    GET_VREG(r2, r1)                    @ r2<- fp[B]
3596    and     r0, r0, #15
3597    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
3598    SET_VREG(r2, r0)                    @ fp[A]<- r2
3599    GOTO_OPCODE(ip)                     @ execute next instruction
3600
3601
3602
3603/* ------------------------------ */
3604    .balign 64
3605.L_OP_LONG_TO_FLOAT: /* 0x85 */
3606/* File: armv5te/OP_LONG_TO_FLOAT.S */
3607/* File: armv5te/unopNarrower.S */
3608    /*
3609     * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
3610     * that specifies an instruction that performs "result = op r0/r1", where
3611     * "result" is a 32-bit quantity in r0.
3612     *
3613     * For: long-to-float, double-to-int, double-to-float
3614     *
3615     * (This would work for long-to-int, but that instruction is actually
3616     * an exact match for OP_MOVE.)
3617     */
3618    /* unop vA, vB */
3619    mov     r3, rINST, lsr #12          @ r3<- B
3620    mov     r9, rINST, lsr #8           @ r9<- A+
3621    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3622    and     r9, r9, #15
3623    ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
3624    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3625                               @ optional op; may set condition codes
3626    bl      __aeabi_l2f                              @ r0<- op, r0-r3 changed
3627    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3628    SET_VREG(r0, r9)                    @ vA<- r0
3629    GOTO_OPCODE(ip)                     @ jump to next instruction
3630    /* 10-11 instructions */
3631
3632
3633/* ------------------------------ */
3634    .balign 64
3635.L_OP_LONG_TO_DOUBLE: /* 0x86 */
3636/* File: armv5te/OP_LONG_TO_DOUBLE.S */
3637/* File: armv5te/unopWide.S */
3638    /*
3639     * Generic 64-bit unary operation.  Provide an "instr" line that
3640     * specifies an instruction that performs "result = op r0/r1".
3641     * This could be an ARM instruction or a function call.
3642     *
3643     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3644     */
3645    /* unop vA, vB */
3646    mov     r9, rINST, lsr #8           @ r9<- A+
3647    mov     r3, rINST, lsr #12          @ r3<- B
3648    and     r9, r9, #15
3649    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3650    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3651    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3652    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3653                               @ optional op; may set condition codes
3654    bl      __aeabi_l2d                              @ r0/r1<- op, r2-r3 changed
3655    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3656    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3657    GOTO_OPCODE(ip)                     @ jump to next instruction
3658    /* 12-13 instructions */
3659
3660
3661
3662/* ------------------------------ */
3663    .balign 64
3664.L_OP_FLOAT_TO_INT: /* 0x87 */
3665/* File: armv5te/OP_FLOAT_TO_INT.S */
3666/* EABI appears to have Java-style conversions of +inf/-inf/NaN */
3667/* File: armv5te/unop.S */
3668    /*
3669     * Generic 32-bit unary operation.  Provide an "instr" line that
3670     * specifies an instruction that performs "result = op r0".
3671     * This could be an ARM instruction or a function call.
3672     *
3673     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3674     *      int-to-byte, int-to-char, int-to-short
3675     */
3676    /* unop vA, vB */
3677    mov     r3, rINST, lsr #12          @ r3<- B
3678    mov     r9, rINST, lsr #8           @ r9<- A+
3679    GET_VREG(r0, r3)                    @ r0<- vB
3680    and     r9, r9, #15
3681                               @ optional op; may set condition codes
3682    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3683    bl      __aeabi_f2iz                              @ r0<- op, r0-r3 changed
3684    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3685    SET_VREG(r0, r9)                    @ vAA<- r0
3686    GOTO_OPCODE(ip)                     @ jump to next instruction
3687    /* 9-10 instructions */
3688
3689
3690#if 0
3691@include "armv5te/unop.S" {"instr":"bl      f2i_doconv"}
3692@break
3693/*
3694 * Convert the float in r0 to an int in r0.
3695 *
3696 * We have to clip values to int min/max per the specification.  The
3697 * expected common case is a "reasonable" value that converts directly
3698 * to modest integer.  The EABI convert function isn't doing this for us.
3699 */
3700f2i_doconv:
3701    stmfd   sp!, {r4, lr}
3702    mov     r1, #0x4f000000             @ (float)maxint
3703    mov     r4, r0
3704    bl      __aeabi_fcmpge              @ is arg >= maxint?
3705    cmp     r0, #0                      @ nonzero == yes
3706    mvnne   r0, #0x80000000             @ return maxint (7fffffff)
3707    ldmnefd sp!, {r4, pc}
3708
3709    mov     r0, r4                      @ recover arg
3710    mov     r1, #0xcf000000             @ (float)minint
3711    bl      __aeabi_fcmple              @ is arg <= minint?
3712    cmp     r0, #0                      @ nonzero == yes
3713    movne   r0, #0x80000000             @ return minint (80000000)
3714    ldmnefd sp!, {r4, pc}
3715
3716    mov     r0, r4                      @ recover arg
3717    mov     r1, r4
3718    bl      __aeabi_fcmpeq              @ is arg == self?
3719    cmp     r0, #0                      @ zero == no
3720    ldmeqfd sp!, {r4, pc}               @ return zero for NaN
3721
3722    mov     r0, r4                      @ recover arg
3723    bl      __aeabi_f2iz                @ convert float to int
3724    ldmfd   sp!, {r4, pc}
3725#endif
3726
3727
3728/* ------------------------------ */
3729    .balign 64
3730.L_OP_FLOAT_TO_LONG: /* 0x88 */
3731/* File: armv5te/OP_FLOAT_TO_LONG.S */
3732@include "armv5te/unopWider.S" {"instr":"bl      __aeabi_f2lz"}
3733/* File: armv5te/unopWider.S */
3734    /*
3735     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3736     * that specifies an instruction that performs "result = op r0", where
3737     * "result" is a 64-bit quantity in r0/r1.
3738     *
3739     * For: int-to-long, int-to-double, float-to-long, float-to-double
3740     */
3741    /* unop vA, vB */
3742    mov     r9, rINST, lsr #8           @ r9<- A+
3743    mov     r3, rINST, lsr #12          @ r3<- B
3744    and     r9, r9, #15
3745    GET_VREG(r0, r3)                    @ r0<- vB
3746    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3747                               @ optional op; may set condition codes
3748    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3749    bl      f2l_doconv                              @ r0<- op, r0-r3 changed
3750    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3751    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3752    GOTO_OPCODE(ip)                     @ jump to next instruction
3753    /* 10-11 instructions */
3754
3755
3756
3757/* ------------------------------ */
3758    .balign 64
3759.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
3760/* File: armv5te/OP_FLOAT_TO_DOUBLE.S */
3761/* File: armv5te/unopWider.S */
3762    /*
3763     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3764     * that specifies an instruction that performs "result = op r0", where
3765     * "result" is a 64-bit quantity in r0/r1.
3766     *
3767     * For: int-to-long, int-to-double, float-to-long, float-to-double
3768     */
3769    /* unop vA, vB */
3770    mov     r9, rINST, lsr #8           @ r9<- A+
3771    mov     r3, rINST, lsr #12          @ r3<- B
3772    and     r9, r9, #15
3773    GET_VREG(r0, r3)                    @ r0<- vB
3774    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3775                               @ optional op; may set condition codes
3776    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3777    bl      __aeabi_f2d                              @ r0<- op, r0-r3 changed
3778    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3779    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3780    GOTO_OPCODE(ip)                     @ jump to next instruction
3781    /* 10-11 instructions */
3782
3783
3784/* ------------------------------ */
3785    .balign 64
3786.L_OP_DOUBLE_TO_INT: /* 0x8a */
3787/* File: armv5te/OP_DOUBLE_TO_INT.S */
3788/* EABI appears to have Java-style conversions of +inf/-inf/NaN */
3789/* File: armv5te/unopNarrower.S */
3790    /*
3791     * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
3792     * that specifies an instruction that performs "result = op r0/r1", where
3793     * "result" is a 32-bit quantity in r0.
3794     *
3795     * For: long-to-float, double-to-int, double-to-float
3796     *
3797     * (This would work for long-to-int, but that instruction is actually
3798     * an exact match for OP_MOVE.)
3799     */
3800    /* unop vA, vB */
3801    mov     r3, rINST, lsr #12          @ r3<- B
3802    mov     r9, rINST, lsr #8           @ r9<- A+
3803    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3804    and     r9, r9, #15
3805    ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
3806    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3807                               @ optional op; may set condition codes
3808    bl      __aeabi_d2iz                              @ r0<- op, r0-r3 changed
3809    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3810    SET_VREG(r0, r9)                    @ vA<- r0
3811    GOTO_OPCODE(ip)                     @ jump to next instruction
3812    /* 10-11 instructions */
3813
3814
3815#if 0
3816@include "armv5te/unopNarrower.S" {"instr":"bl      d2i_doconv"}
3817@break
3818/*
3819 * Convert the double in r0/r1 to an int in r0.
3820 *
3821 * We have to clip values to int min/max per the specification.  The
3822 * expected common case is a "reasonable" value that converts directly
3823 * to modest integer.  The EABI convert function isn't doing this for us.
3824 */
3825d2i_doconv:
3826    stmfd   sp!, {r4, r5, lr}           @ save regs
3827    ldr     r2, .LOP_DOUBLE_TO_INT_maxlo       @ (double)maxint, lo
3828    ldr     r3, .LOP_DOUBLE_TO_INT_maxhi       @ (double)maxint, hi
3829    sub     sp, sp, #4                  @ align for EABI
3830    mov     r4, r0                      @ save r0
3831    mov     r5, r1                      @  and r1
3832    bl      __aeabi_dcmpge              @ is arg >= maxint?
3833    cmp     r0, #0                      @ nonzero == yes
3834    mvnne   r0, #0x80000000             @ return maxint (7fffffff)
3835    bne     1f
3836
3837    mov     r0, r4                      @ recover arg
3838    mov     r1, r5
3839    ldr     r3, .LOP_DOUBLE_TO_INT_min         @ (double)minint, hi
3840    mov     r2, #0                      @ (double)minint, lo
3841    bl      __aeabi_dcmple              @ is arg <= minint?
3842    cmp     r0, #0                      @ nonzero == yes
3843    movne   r0, #0x80000000             @ return minint (80000000)
3844    bne     1f
3845
3846    mov     r0, r4                      @ recover arg
3847    mov     r1, r5
3848    mov     r2, r4                      @ compare against self
3849    mov     r3, r5
3850    bl      __aeabi_dcmpeq              @ is arg == self?
3851    cmp     r0, #0                      @ zero == no
3852    beq     1f                          @ return zero for NaN
3853
3854    mov     r0, r4                      @ recover arg
3855    mov     r1, r5
3856    bl      __aeabi_d2iz                @ convert double to int
3857
38581:
3859    add     sp, sp, #4
3860    ldmfd   sp!, {r4, r5, pc}
3861
3862.LOP_DOUBLE_TO_INT_maxlo:
3863    .word   0xffc00000                  @ maxint, as a double (low word)
3864.LOP_DOUBLE_TO_INT_maxhi:
3865    .word   0x41dfffff                  @ maxint, as a double (high word)
3866.LOP_DOUBLE_TO_INT_min:
3867    .word   0xc1e00000                  @ minint, as a double (high word)
3868#endif
3869
3870
3871/* ------------------------------ */
3872    .balign 64
3873.L_OP_DOUBLE_TO_LONG: /* 0x8b */
3874/* File: armv5te/OP_DOUBLE_TO_LONG.S */
3875@include "armv5te/unopWide.S" {"instr":"bl      __aeabi_d2lz"}
3876/* File: armv5te/unopWide.S */
3877    /*
3878     * Generic 64-bit unary operation.  Provide an "instr" line that
3879     * specifies an instruction that performs "result = op r0/r1".
3880     * This could be an ARM instruction or a function call.
3881     *
3882     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3883     */
3884    /* unop vA, vB */
3885    mov     r9, rINST, lsr #8           @ r9<- A+
3886    mov     r3, rINST, lsr #12          @ r3<- B
3887    and     r9, r9, #15
3888    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3889    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3890    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3891    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3892                               @ optional op; may set condition codes
3893    bl      d2l_doconv                              @ r0/r1<- op, r2-r3 changed
3894    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3895    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3896    GOTO_OPCODE(ip)                     @ jump to next instruction
3897    /* 12-13 instructions */
3898
3899
3900
3901
3902/* ------------------------------ */
3903    .balign 64
3904.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
3905/* File: armv5te/OP_DOUBLE_TO_FLOAT.S */
3906/* File: armv5te/unopNarrower.S */
3907    /*
3908     * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
3909     * that specifies an instruction that performs "result = op r0/r1", where
3910     * "result" is a 32-bit quantity in r0.
3911     *
3912     * For: long-to-float, double-to-int, double-to-float
3913     *
3914     * (This would work for long-to-int, but that instruction is actually
3915     * an exact match for OP_MOVE.)
3916     */
3917    /* unop vA, vB */
3918    mov     r3, rINST, lsr #12          @ r3<- B
3919    mov     r9, rINST, lsr #8           @ r9<- A+
3920    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3921    and     r9, r9, #15
3922    ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
3923    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3924                               @ optional op; may set condition codes
3925    bl      __aeabi_d2f                              @ r0<- op, r0-r3 changed
3926    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3927    SET_VREG(r0, r9)                    @ vA<- r0
3928    GOTO_OPCODE(ip)                     @ jump to next instruction
3929    /* 10-11 instructions */
3930
3931
3932/* ------------------------------ */
3933    .balign 64
3934.L_OP_INT_TO_BYTE: /* 0x8d */
3935/* File: armv5te/OP_INT_TO_BYTE.S */
3936/* File: armv5te/unop.S */
3937    /*
3938     * Generic 32-bit unary operation.  Provide an "instr" line that
3939     * specifies an instruction that performs "result = op r0".
3940     * This could be an ARM instruction or a function call.
3941     *
3942     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3943     *      int-to-byte, int-to-char, int-to-short
3944     */
3945    /* unop vA, vB */
3946    mov     r3, rINST, lsr #12          @ r3<- B
3947    mov     r9, rINST, lsr #8           @ r9<- A+
3948    GET_VREG(r0, r3)                    @ r0<- vB
3949    and     r9, r9, #15
3950    mov     r0, r0, asl #24                           @ optional op; may set condition codes
3951    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3952    mov     r0, r0, asr #24                              @ 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    /* 9-10 instructions */
3957
3958
3959/* ------------------------------ */
3960    .balign 64
3961.L_OP_INT_TO_CHAR: /* 0x8e */
3962/* File: armv5te/OP_INT_TO_CHAR.S */
3963/* File: armv5te/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    mov     r9, rINST, lsr #8           @ r9<- A+
3975    GET_VREG(r0, r3)                    @ r0<- vB
3976    and     r9, r9, #15
3977    mov     r0, r0, asl #16                           @ optional op; may set condition codes
3978    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3979    mov     r0, r0, lsr #16                              @ r0<- op, r0-r3 changed
3980    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3981    SET_VREG(r0, r9)                    @ vAA<- r0
3982    GOTO_OPCODE(ip)                     @ jump to next instruction
3983    /* 9-10 instructions */
3984
3985
3986/* ------------------------------ */
3987    .balign 64
3988.L_OP_INT_TO_SHORT: /* 0x8f */
3989/* File: armv5te/OP_INT_TO_SHORT.S */
3990/* File: armv5te/unop.S */
3991    /*
3992     * Generic 32-bit unary operation.  Provide an "instr" line that
3993     * specifies an instruction that performs "result = op r0".
3994     * This could be an ARM instruction or a function call.
3995     *
3996     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3997     *      int-to-byte, int-to-char, int-to-short
3998     */
3999    /* unop vA, vB */
4000    mov     r3, rINST, lsr #12          @ r3<- B
4001    mov     r9, rINST, lsr #8           @ r9<- A+
4002    GET_VREG(r0, r3)                    @ r0<- vB
4003    and     r9, r9, #15
4004    mov     r0, r0, asl #16                           @ optional op; may set condition codes
4005    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4006    mov     r0, r0, asr #16                              @ r0<- op, r0-r3 changed
4007    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4008    SET_VREG(r0, r9)                    @ vAA<- r0
4009    GOTO_OPCODE(ip)                     @ jump to next instruction
4010    /* 9-10 instructions */
4011
4012
4013/* ------------------------------ */
4014    .balign 64
4015.L_OP_ADD_INT: /* 0x90 */
4016/* File: armv5te/OP_ADD_INT.S */
4017/* File: armv5te/binop.S */
4018    /*
4019     * Generic 32-bit binary operation.  Provide an "instr" line that
4020     * specifies an instruction that performs "result = r0 op r1".
4021     * This could be an ARM instruction or a function call.  (If the result
4022     * comes back in a register other than r0, you can override "result".)
4023     *
4024     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4025     * vCC (r1).  Useful for integer division and modulus.  Note that we
4026     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4027     * handles it correctly.
4028     *
4029     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4030     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4031     *      mul-float, div-float, rem-float
4032     */
4033    /* binop vAA, vBB, vCC */
4034    FETCH(r0, 1)                        @ r0<- CCBB
4035    mov     r9, rINST, lsr #8           @ r9<- AA
4036    mov     r3, r0, lsr #8              @ r3<- CC
4037    and     r2, r0, #255                @ r2<- BB
4038    GET_VREG(r1, r3)                    @ r1<- vCC
4039    GET_VREG(r0, r2)                    @ r0<- vBB
4040    .if 0
4041    cmp     r1, #0                      @ is second operand zero?
4042    beq     common_errDivideByZero
4043    .endif
4044
4045    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4046                               @ optional op; may set condition codes
4047    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
4048    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4049    SET_VREG(r0, r9)               @ vAA<- r0
4050    GOTO_OPCODE(ip)                     @ jump to next instruction
4051    /* 11-14 instructions */
4052
4053
4054
4055/* ------------------------------ */
4056    .balign 64
4057.L_OP_SUB_INT: /* 0x91 */
4058/* File: armv5te/OP_SUB_INT.S */
4059/* File: armv5te/binop.S */
4060    /*
4061     * Generic 32-bit binary operation.  Provide an "instr" line that
4062     * specifies an instruction that performs "result = r0 op r1".
4063     * This could be an ARM instruction or a function call.  (If the result
4064     * comes back in a register other than r0, you can override "result".)
4065     *
4066     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4067     * vCC (r1).  Useful for integer division and modulus.  Note that we
4068     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4069     * handles it correctly.
4070     *
4071     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4072     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4073     *      mul-float, div-float, rem-float
4074     */
4075    /* binop vAA, vBB, vCC */
4076    FETCH(r0, 1)                        @ r0<- CCBB
4077    mov     r9, rINST, lsr #8           @ r9<- AA
4078    mov     r3, r0, lsr #8              @ r3<- CC
4079    and     r2, r0, #255                @ r2<- BB
4080    GET_VREG(r1, r3)                    @ r1<- vCC
4081    GET_VREG(r0, r2)                    @ r0<- vBB
4082    .if 0
4083    cmp     r1, #0                      @ is second operand zero?
4084    beq     common_errDivideByZero
4085    .endif
4086
4087    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4088                               @ optional op; may set condition codes
4089    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
4090    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4091    SET_VREG(r0, r9)               @ vAA<- r0
4092    GOTO_OPCODE(ip)                     @ jump to next instruction
4093    /* 11-14 instructions */
4094
4095
4096
4097/* ------------------------------ */
4098    .balign 64
4099.L_OP_MUL_INT: /* 0x92 */
4100/* File: armv5te/OP_MUL_INT.S */
4101/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
4102/* File: armv5te/binop.S */
4103    /*
4104     * Generic 32-bit binary operation.  Provide an "instr" line that
4105     * specifies an instruction that performs "result = r0 op r1".
4106     * This could be an ARM instruction or a function call.  (If the result
4107     * comes back in a register other than r0, you can override "result".)
4108     *
4109     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4110     * vCC (r1).  Useful for integer division and modulus.  Note that we
4111     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4112     * handles it correctly.
4113     *
4114     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4115     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4116     *      mul-float, div-float, rem-float
4117     */
4118    /* binop vAA, vBB, vCC */
4119    FETCH(r0, 1)                        @ r0<- CCBB
4120    mov     r9, rINST, lsr #8           @ r9<- AA
4121    mov     r3, r0, lsr #8              @ r3<- CC
4122    and     r2, r0, #255                @ r2<- BB
4123    GET_VREG(r1, r3)                    @ r1<- vCC
4124    GET_VREG(r0, r2)                    @ r0<- vBB
4125    .if 0
4126    cmp     r1, #0                      @ is second operand zero?
4127    beq     common_errDivideByZero
4128    .endif
4129
4130    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4131                               @ optional op; may set condition codes
4132    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
4133    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4134    SET_VREG(r0, r9)               @ vAA<- r0
4135    GOTO_OPCODE(ip)                     @ jump to next instruction
4136    /* 11-14 instructions */
4137
4138
4139
4140/* ------------------------------ */
4141    .balign 64
4142.L_OP_DIV_INT: /* 0x93 */
4143/* File: armv5te/OP_DIV_INT.S */
4144/* File: armv5te/binop.S */
4145    /*
4146     * Generic 32-bit binary operation.  Provide an "instr" line that
4147     * specifies an instruction that performs "result = r0 op r1".
4148     * This could be an ARM instruction or a function call.  (If the result
4149     * comes back in a register other than r0, you can override "result".)
4150     *
4151     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4152     * vCC (r1).  Useful for integer division and modulus.  Note that we
4153     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4154     * handles it correctly.
4155     *
4156     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4157     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4158     *      mul-float, div-float, rem-float
4159     */
4160    /* binop vAA, vBB, vCC */
4161    FETCH(r0, 1)                        @ r0<- CCBB
4162    mov     r9, rINST, lsr #8           @ r9<- AA
4163    mov     r3, r0, lsr #8              @ r3<- CC
4164    and     r2, r0, #255                @ r2<- BB
4165    GET_VREG(r1, r3)                    @ r1<- vCC
4166    GET_VREG(r0, r2)                    @ r0<- vBB
4167    .if 1
4168    cmp     r1, #0                      @ is second operand zero?
4169    beq     common_errDivideByZero
4170    .endif
4171
4172    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4173                               @ optional op; may set condition codes
4174    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
4175    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4176    SET_VREG(r0, r9)               @ vAA<- r0
4177    GOTO_OPCODE(ip)                     @ jump to next instruction
4178    /* 11-14 instructions */
4179
4180
4181
4182/* ------------------------------ */
4183    .balign 64
4184.L_OP_REM_INT: /* 0x94 */
4185/* File: armv5te/OP_REM_INT.S */
4186/* idivmod returns quotient in r0 and remainder in r1 */
4187/* File: armv5te/binop.S */
4188    /*
4189     * Generic 32-bit binary operation.  Provide an "instr" line that
4190     * specifies an instruction that performs "result = r0 op r1".
4191     * This could be an ARM instruction or a function call.  (If the result
4192     * comes back in a register other than r0, you can override "result".)
4193     *
4194     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4195     * vCC (r1).  Useful for integer division and modulus.  Note that we
4196     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4197     * handles it correctly.
4198     *
4199     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4200     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4201     *      mul-float, div-float, rem-float
4202     */
4203    /* binop vAA, vBB, vCC */
4204    FETCH(r0, 1)                        @ r0<- CCBB
4205    mov     r9, rINST, lsr #8           @ r9<- AA
4206    mov     r3, r0, lsr #8              @ r3<- CC
4207    and     r2, r0, #255                @ r2<- BB
4208    GET_VREG(r1, r3)                    @ r1<- vCC
4209    GET_VREG(r0, r2)                    @ r0<- vBB
4210    .if 1
4211    cmp     r1, #0                      @ is second operand zero?
4212    beq     common_errDivideByZero
4213    .endif
4214
4215    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4216                               @ optional op; may set condition codes
4217    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
4218    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4219    SET_VREG(r1, r9)               @ vAA<- r1
4220    GOTO_OPCODE(ip)                     @ jump to next instruction
4221    /* 11-14 instructions */
4222
4223
4224
4225/* ------------------------------ */
4226    .balign 64
4227.L_OP_AND_INT: /* 0x95 */
4228/* File: armv5te/OP_AND_INT.S */
4229/* File: armv5te/binop.S */
4230    /*
4231     * Generic 32-bit binary operation.  Provide an "instr" line that
4232     * specifies an instruction that performs "result = r0 op r1".
4233     * This could be an ARM instruction or a function call.  (If the result
4234     * comes back in a register other than r0, you can override "result".)
4235     *
4236     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4237     * vCC (r1).  Useful for integer division and modulus.  Note that we
4238     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4239     * handles it correctly.
4240     *
4241     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4242     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4243     *      mul-float, div-float, rem-float
4244     */
4245    /* binop vAA, vBB, vCC */
4246    FETCH(r0, 1)                        @ r0<- CCBB
4247    mov     r9, rINST, lsr #8           @ r9<- AA
4248    mov     r3, r0, lsr #8              @ r3<- CC
4249    and     r2, r0, #255                @ r2<- BB
4250    GET_VREG(r1, r3)                    @ r1<- vCC
4251    GET_VREG(r0, r2)                    @ r0<- vBB
4252    .if 0
4253    cmp     r1, #0                      @ is second operand zero?
4254    beq     common_errDivideByZero
4255    .endif
4256
4257    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4258                               @ optional op; may set condition codes
4259    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
4260    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4261    SET_VREG(r0, r9)               @ vAA<- r0
4262    GOTO_OPCODE(ip)                     @ jump to next instruction
4263    /* 11-14 instructions */
4264
4265
4266
4267/* ------------------------------ */
4268    .balign 64
4269.L_OP_OR_INT: /* 0x96 */
4270/* File: armv5te/OP_OR_INT.S */
4271/* File: armv5te/binop.S */
4272    /*
4273     * Generic 32-bit binary operation.  Provide an "instr" line that
4274     * specifies an instruction that performs "result = r0 op r1".
4275     * This could be an ARM instruction or a function call.  (If the result
4276     * comes back in a register other than r0, you can override "result".)
4277     *
4278     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4279     * vCC (r1).  Useful for integer division and modulus.  Note that we
4280     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4281     * handles it correctly.
4282     *
4283     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4284     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4285     *      mul-float, div-float, rem-float
4286     */
4287    /* binop vAA, vBB, vCC */
4288    FETCH(r0, 1)                        @ r0<- CCBB
4289    mov     r9, rINST, lsr #8           @ r9<- AA
4290    mov     r3, r0, lsr #8              @ r3<- CC
4291    and     r2, r0, #255                @ r2<- BB
4292    GET_VREG(r1, r3)                    @ r1<- vCC
4293    GET_VREG(r0, r2)                    @ r0<- vBB
4294    .if 0
4295    cmp     r1, #0                      @ is second operand zero?
4296    beq     common_errDivideByZero
4297    .endif
4298
4299    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4300                               @ optional op; may set condition codes
4301    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
4302    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4303    SET_VREG(r0, r9)               @ vAA<- r0
4304    GOTO_OPCODE(ip)                     @ jump to next instruction
4305    /* 11-14 instructions */
4306
4307
4308
4309/* ------------------------------ */
4310    .balign 64
4311.L_OP_XOR_INT: /* 0x97 */
4312/* File: armv5te/OP_XOR_INT.S */
4313/* File: armv5te/binop.S */
4314    /*
4315     * Generic 32-bit binary operation.  Provide an "instr" line that
4316     * specifies an instruction that performs "result = r0 op r1".
4317     * This could be an ARM instruction or a function call.  (If the result
4318     * comes back in a register other than r0, you can override "result".)
4319     *
4320     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4321     * vCC (r1).  Useful for integer division and modulus.  Note that we
4322     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4323     * handles it correctly.
4324     *
4325     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4326     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4327     *      mul-float, div-float, rem-float
4328     */
4329    /* binop vAA, vBB, vCC */
4330    FETCH(r0, 1)                        @ r0<- CCBB
4331    mov     r9, rINST, lsr #8           @ r9<- AA
4332    mov     r3, r0, lsr #8              @ r3<- CC
4333    and     r2, r0, #255                @ r2<- BB
4334    GET_VREG(r1, r3)                    @ r1<- vCC
4335    GET_VREG(r0, r2)                    @ r0<- vBB
4336    .if 0
4337    cmp     r1, #0                      @ is second operand zero?
4338    beq     common_errDivideByZero
4339    .endif
4340
4341    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4342                               @ optional op; may set condition codes
4343    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
4344    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4345    SET_VREG(r0, r9)               @ vAA<- r0
4346    GOTO_OPCODE(ip)                     @ jump to next instruction
4347    /* 11-14 instructions */
4348
4349
4350
4351/* ------------------------------ */
4352    .balign 64
4353.L_OP_SHL_INT: /* 0x98 */
4354/* File: armv5te/OP_SHL_INT.S */
4355/* File: armv5te/binop.S */
4356    /*
4357     * Generic 32-bit binary operation.  Provide an "instr" line that
4358     * specifies an instruction that performs "result = r0 op r1".
4359     * This could be an ARM instruction or a function call.  (If the result
4360     * comes back in a register other than r0, you can override "result".)
4361     *
4362     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4363     * vCC (r1).  Useful for integer division and modulus.  Note that we
4364     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4365     * handles it correctly.
4366     *
4367     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4368     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4369     *      mul-float, div-float, rem-float
4370     */
4371    /* binop vAA, vBB, vCC */
4372    FETCH(r0, 1)                        @ r0<- CCBB
4373    mov     r9, rINST, lsr #8           @ r9<- AA
4374    mov     r3, r0, lsr #8              @ r3<- CC
4375    and     r2, r0, #255                @ r2<- BB
4376    GET_VREG(r1, r3)                    @ r1<- vCC
4377    GET_VREG(r0, r2)                    @ r0<- vBB
4378    .if 0
4379    cmp     r1, #0                      @ is second operand zero?
4380    beq     common_errDivideByZero
4381    .endif
4382
4383    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4384    and     r1, r1, #31                           @ optional op; may set condition codes
4385    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
4386    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4387    SET_VREG(r0, r9)               @ vAA<- r0
4388    GOTO_OPCODE(ip)                     @ jump to next instruction
4389    /* 11-14 instructions */
4390
4391
4392
4393/* ------------------------------ */
4394    .balign 64
4395.L_OP_SHR_INT: /* 0x99 */
4396/* File: armv5te/OP_SHR_INT.S */
4397/* File: armv5te/binop.S */
4398    /*
4399     * Generic 32-bit binary operation.  Provide an "instr" line that
4400     * specifies an instruction that performs "result = r0 op r1".
4401     * This could be an ARM instruction or a function call.  (If the result
4402     * comes back in a register other than r0, you can override "result".)
4403     *
4404     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4405     * vCC (r1).  Useful for integer division and modulus.  Note that we
4406     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4407     * handles it correctly.
4408     *
4409     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4410     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4411     *      mul-float, div-float, rem-float
4412     */
4413    /* binop vAA, vBB, vCC */
4414    FETCH(r0, 1)                        @ r0<- CCBB
4415    mov     r9, rINST, lsr #8           @ r9<- AA
4416    mov     r3, r0, lsr #8              @ r3<- CC
4417    and     r2, r0, #255                @ r2<- BB
4418    GET_VREG(r1, r3)                    @ r1<- vCC
4419    GET_VREG(r0, r2)                    @ r0<- vBB
4420    .if 0
4421    cmp     r1, #0                      @ is second operand zero?
4422    beq     common_errDivideByZero
4423    .endif
4424
4425    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4426    and     r1, r1, #31                           @ optional op; may set condition codes
4427    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
4428    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4429    SET_VREG(r0, r9)               @ vAA<- r0
4430    GOTO_OPCODE(ip)                     @ jump to next instruction
4431    /* 11-14 instructions */
4432
4433
4434
4435/* ------------------------------ */
4436    .balign 64
4437.L_OP_USHR_INT: /* 0x9a */
4438/* File: armv5te/OP_USHR_INT.S */
4439/* File: armv5te/binop.S */
4440    /*
4441     * Generic 32-bit binary operation.  Provide an "instr" line that
4442     * specifies an instruction that performs "result = r0 op r1".
4443     * This could be an ARM instruction or a function call.  (If the result
4444     * comes back in a register other than r0, you can override "result".)
4445     *
4446     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4447     * vCC (r1).  Useful for integer division and modulus.  Note that we
4448     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4449     * handles it correctly.
4450     *
4451     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4452     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4453     *      mul-float, div-float, rem-float
4454     */
4455    /* binop vAA, vBB, vCC */
4456    FETCH(r0, 1)                        @ r0<- CCBB
4457    mov     r9, rINST, lsr #8           @ r9<- AA
4458    mov     r3, r0, lsr #8              @ r3<- CC
4459    and     r2, r0, #255                @ r2<- BB
4460    GET_VREG(r1, r3)                    @ r1<- vCC
4461    GET_VREG(r0, r2)                    @ r0<- vBB
4462    .if 0
4463    cmp     r1, #0                      @ is second operand zero?
4464    beq     common_errDivideByZero
4465    .endif
4466
4467    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4468    and     r1, r1, #31                           @ optional op; may set condition codes
4469    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
4470    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4471    SET_VREG(r0, r9)               @ vAA<- r0
4472    GOTO_OPCODE(ip)                     @ jump to next instruction
4473    /* 11-14 instructions */
4474
4475
4476
4477/* ------------------------------ */
4478    .balign 64
4479.L_OP_ADD_LONG: /* 0x9b */
4480/* File: armv5te/OP_ADD_LONG.S */
4481/* File: armv5te/binopWide.S */
4482    /*
4483     * Generic 64-bit binary operation.  Provide an "instr" line that
4484     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4485     * This could be an ARM instruction or a function call.  (If the result
4486     * comes back in a register other than r0, you can override "result".)
4487     *
4488     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4489     * vCC (r1).  Useful for integer division and modulus.
4490     *
4491     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4492     *      xor-long, add-double, sub-double, mul-double, div-double,
4493     *      rem-double
4494     *
4495     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4496     */
4497    /* binop vAA, vBB, vCC */
4498    FETCH(r0, 1)                        @ r0<- CCBB
4499    mov     r9, rINST, lsr #8           @ r9<- AA
4500    and     r2, r0, #255                @ r2<- BB
4501    mov     r3, r0, lsr #8              @ r3<- CC
4502    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4503    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4504    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4505    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4506    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4507    .if 0
4508    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4509    beq     common_errDivideByZero
4510    .endif
4511    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4512
4513    adds    r0, r0, r2                           @ optional op; may set condition codes
4514    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
4515    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4516    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4517    GOTO_OPCODE(ip)                     @ jump to next instruction
4518    /* 14-17 instructions */
4519
4520
4521
4522/* ------------------------------ */
4523    .balign 64
4524.L_OP_SUB_LONG: /* 0x9c */
4525/* File: armv5te/OP_SUB_LONG.S */
4526/* File: armv5te/binopWide.S */
4527    /*
4528     * Generic 64-bit binary operation.  Provide an "instr" line that
4529     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4530     * This could be an ARM instruction or a function call.  (If the result
4531     * comes back in a register other than r0, you can override "result".)
4532     *
4533     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4534     * vCC (r1).  Useful for integer division and modulus.
4535     *
4536     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4537     *      xor-long, add-double, sub-double, mul-double, div-double,
4538     *      rem-double
4539     *
4540     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4541     */
4542    /* binop vAA, vBB, vCC */
4543    FETCH(r0, 1)                        @ r0<- CCBB
4544    mov     r9, rINST, lsr #8           @ r9<- AA
4545    and     r2, r0, #255                @ r2<- BB
4546    mov     r3, r0, lsr #8              @ r3<- CC
4547    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4548    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4549    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4550    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4551    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4552    .if 0
4553    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4554    beq     common_errDivideByZero
4555    .endif
4556    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4557
4558    subs    r0, r0, r2                           @ optional op; may set condition codes
4559    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
4560    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4561    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4562    GOTO_OPCODE(ip)                     @ jump to next instruction
4563    /* 14-17 instructions */
4564
4565
4566
4567/* ------------------------------ */
4568    .balign 64
4569.L_OP_MUL_LONG: /* 0x9d */
4570/* File: armv5te/OP_MUL_LONG.S */
4571    /*
4572     * Signed 64-bit integer multiply.
4573     *
4574     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
4575     *        WX
4576     *      x YZ
4577     *  --------
4578     *     ZW ZX
4579     *  YW YX
4580     *
4581     * The low word of the result holds ZX, the high word holds
4582     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
4583     * it doesn't fit in the low 64 bits.
4584     *
4585     * Unlike most ARM math operations, multiply instructions have
4586     * restrictions on using the same register more than once (Rd and Rm
4587     * cannot be the same).
4588     */
4589    /* mul-long vAA, vBB, vCC */
4590    FETCH(r0, 1)                        @ r0<- CCBB
4591    and     r2, r0, #255                @ r2<- BB
4592    mov     r3, r0, lsr #8              @ r3<- CC
4593    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4594    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4595    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4596    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4597    mul     ip, r2, r1                  @  ip<- ZxW
4598    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
4599    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
4600    mov     r0, rINST, lsr #8           @ r0<- AA
4601    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
4602    add     r0, rFP, r0, lsl #2         @ r0<- &fp[AA]
4603    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4604    b       .LOP_MUL_LONG_finish
4605
4606/* ------------------------------ */
4607    .balign 64
4608.L_OP_DIV_LONG: /* 0x9e */
4609/* File: armv5te/OP_DIV_LONG.S */
4610/* File: armv5te/binopWide.S */
4611    /*
4612     * Generic 64-bit binary operation.  Provide an "instr" line that
4613     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4614     * This could be an ARM instruction or a function call.  (If the result
4615     * comes back in a register other than r0, you can override "result".)
4616     *
4617     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4618     * vCC (r1).  Useful for integer division and modulus.
4619     *
4620     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4621     *      xor-long, add-double, sub-double, mul-double, div-double,
4622     *      rem-double
4623     *
4624     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4625     */
4626    /* binop vAA, vBB, vCC */
4627    FETCH(r0, 1)                        @ r0<- CCBB
4628    mov     r9, rINST, lsr #8           @ r9<- AA
4629    and     r2, r0, #255                @ r2<- BB
4630    mov     r3, r0, lsr #8              @ r3<- CC
4631    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4632    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4633    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4634    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4635    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4636    .if 1
4637    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4638    beq     common_errDivideByZero
4639    .endif
4640    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4641
4642                               @ optional op; may set condition codes
4643    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4644    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4645    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4646    GOTO_OPCODE(ip)                     @ jump to next instruction
4647    /* 14-17 instructions */
4648
4649
4650
4651/* ------------------------------ */
4652    .balign 64
4653.L_OP_REM_LONG: /* 0x9f */
4654/* File: armv5te/OP_REM_LONG.S */
4655/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
4656/* File: armv5te/binopWide.S */
4657    /*
4658     * Generic 64-bit binary operation.  Provide an "instr" line that
4659     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4660     * This could be an ARM instruction or a function call.  (If the result
4661     * comes back in a register other than r0, you can override "result".)
4662     *
4663     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4664     * vCC (r1).  Useful for integer division and modulus.
4665     *
4666     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4667     *      xor-long, add-double, sub-double, mul-double, div-double,
4668     *      rem-double
4669     *
4670     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4671     */
4672    /* binop vAA, vBB, vCC */
4673    FETCH(r0, 1)                        @ r0<- CCBB
4674    mov     r9, rINST, lsr #8           @ r9<- AA
4675    and     r2, r0, #255                @ r2<- BB
4676    mov     r3, r0, lsr #8              @ r3<- CC
4677    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4678    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4679    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4680    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4681    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4682    .if 1
4683    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4684    beq     common_errDivideByZero
4685    .endif
4686    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4687
4688                               @ optional op; may set condition codes
4689    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4690    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4691    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
4692    GOTO_OPCODE(ip)                     @ jump to next instruction
4693    /* 14-17 instructions */
4694
4695
4696
4697/* ------------------------------ */
4698    .balign 64
4699.L_OP_AND_LONG: /* 0xa0 */
4700/* File: armv5te/OP_AND_LONG.S */
4701/* File: armv5te/binopWide.S */
4702    /*
4703     * Generic 64-bit binary operation.  Provide an "instr" line that
4704     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4705     * This could be an ARM instruction or a function call.  (If the result
4706     * comes back in a register other than r0, you can override "result".)
4707     *
4708     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4709     * vCC (r1).  Useful for integer division and modulus.
4710     *
4711     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4712     *      xor-long, add-double, sub-double, mul-double, div-double,
4713     *      rem-double
4714     *
4715     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4716     */
4717    /* binop vAA, vBB, vCC */
4718    FETCH(r0, 1)                        @ r0<- CCBB
4719    mov     r9, rINST, lsr #8           @ r9<- AA
4720    and     r2, r0, #255                @ r2<- BB
4721    mov     r3, r0, lsr #8              @ r3<- CC
4722    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4723    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4724    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4725    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4726    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4727    .if 0
4728    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4729    beq     common_errDivideByZero
4730    .endif
4731    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4732
4733    and     r0, r0, r2                           @ optional op; may set condition codes
4734    and     r1, r1, r3                              @ result<- op, r0-r3 changed
4735    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4736    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4737    GOTO_OPCODE(ip)                     @ jump to next instruction
4738    /* 14-17 instructions */
4739
4740
4741
4742/* ------------------------------ */
4743    .balign 64
4744.L_OP_OR_LONG: /* 0xa1 */
4745/* File: armv5te/OP_OR_LONG.S */
4746/* File: armv5te/binopWide.S */
4747    /*
4748     * Generic 64-bit binary operation.  Provide an "instr" line that
4749     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4750     * This could be an ARM instruction or a function call.  (If the result
4751     * comes back in a register other than r0, you can override "result".)
4752     *
4753     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4754     * vCC (r1).  Useful for integer division and modulus.
4755     *
4756     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4757     *      xor-long, add-double, sub-double, mul-double, div-double,
4758     *      rem-double
4759     *
4760     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4761     */
4762    /* binop vAA, vBB, vCC */
4763    FETCH(r0, 1)                        @ r0<- CCBB
4764    mov     r9, rINST, lsr #8           @ r9<- AA
4765    and     r2, r0, #255                @ r2<- BB
4766    mov     r3, r0, lsr #8              @ r3<- CC
4767    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4768    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4769    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4770    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4771    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4772    .if 0
4773    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4774    beq     common_errDivideByZero
4775    .endif
4776    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4777
4778    orr     r0, r0, r2                           @ optional op; may set condition codes
4779    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
4780    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4781    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4782    GOTO_OPCODE(ip)                     @ jump to next instruction
4783    /* 14-17 instructions */
4784
4785
4786
4787/* ------------------------------ */
4788    .balign 64
4789.L_OP_XOR_LONG: /* 0xa2 */
4790/* File: armv5te/OP_XOR_LONG.S */
4791/* File: armv5te/binopWide.S */
4792    /*
4793     * Generic 64-bit binary operation.  Provide an "instr" line that
4794     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4795     * This could be an ARM instruction or a function call.  (If the result
4796     * comes back in a register other than r0, you can override "result".)
4797     *
4798     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4799     * vCC (r1).  Useful for integer division and modulus.
4800     *
4801     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4802     *      xor-long, add-double, sub-double, mul-double, div-double,
4803     *      rem-double
4804     *
4805     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4806     */
4807    /* binop vAA, vBB, vCC */
4808    FETCH(r0, 1)                        @ r0<- CCBB
4809    mov     r9, rINST, lsr #8           @ r9<- AA
4810    and     r2, r0, #255                @ r2<- BB
4811    mov     r3, r0, lsr #8              @ r3<- CC
4812    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4813    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4814    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4815    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4816    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4817    .if 0
4818    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4819    beq     common_errDivideByZero
4820    .endif
4821    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4822
4823    eor     r0, r0, r2                           @ optional op; may set condition codes
4824    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
4825    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4826    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4827    GOTO_OPCODE(ip)                     @ jump to next instruction
4828    /* 14-17 instructions */
4829
4830
4831
4832/* ------------------------------ */
4833    .balign 64
4834.L_OP_SHL_LONG: /* 0xa3 */
4835/* File: armv5te/OP_SHL_LONG.S */
4836    /*
4837     * Long integer shift.  This is different from the generic 32/64-bit
4838     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4839     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4840     * 6 bits of the shift distance.
4841     */
4842    /* shl-long vAA, vBB, vCC */
4843    FETCH(r0, 1)                        @ r0<- CCBB
4844    mov     r9, rINST, lsr #8           @ r9<- AA
4845    and     r3, r0, #255                @ r3<- BB
4846    mov     r0, r0, lsr #8              @ r0<- CC
4847    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4848    GET_VREG(r2, r0)                    @ r2<- vCC
4849    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4850    and     r2, r2, #63                 @ r2<- r2 & 0x3f
4851    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4852
4853    mov     r1, r1, asl r2              @  r1<- r1 << r2
4854    rsb     r3, r2, #32                 @  r3<- 32 - r2
4855    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
4856    subs    ip, r2, #32                 @  ip<- r2 - 32
4857    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
4858    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4859    b       .LOP_SHL_LONG_finish
4860
4861/* ------------------------------ */
4862    .balign 64
4863.L_OP_SHR_LONG: /* 0xa4 */
4864/* File: armv5te/OP_SHR_LONG.S */
4865    /*
4866     * Long integer shift.  This is different from the generic 32/64-bit
4867     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4868     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4869     * 6 bits of the shift distance.
4870     */
4871    /* shr-long vAA, vBB, vCC */
4872    FETCH(r0, 1)                        @ r0<- CCBB
4873    mov     r9, rINST, lsr #8           @ r9<- AA
4874    and     r3, r0, #255                @ r3<- BB
4875    mov     r0, r0, lsr #8              @ r0<- CC
4876    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4877    GET_VREG(r2, r0)                    @ r2<- vCC
4878    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4879    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4880    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4881
4882    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4883    rsb     r3, r2, #32                 @  r3<- 32 - r2
4884    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4885    subs    ip, r2, #32                 @  ip<- r2 - 32
4886    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
4887    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4888    b       .LOP_SHR_LONG_finish
4889
4890/* ------------------------------ */
4891    .balign 64
4892.L_OP_USHR_LONG: /* 0xa5 */
4893/* File: armv5te/OP_USHR_LONG.S */
4894    /*
4895     * Long integer shift.  This is different from the generic 32/64-bit
4896     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4897     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4898     * 6 bits of the shift distance.
4899     */
4900    /* ushr-long vAA, vBB, vCC */
4901    FETCH(r0, 1)                        @ r0<- CCBB
4902    mov     r9, rINST, lsr #8           @ r9<- AA
4903    and     r3, r0, #255                @ r3<- BB
4904    mov     r0, r0, lsr #8              @ r0<- CC
4905    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4906    GET_VREG(r2, r0)                    @ r2<- vCC
4907    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4908    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4909    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4910
4911    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4912    rsb     r3, r2, #32                 @  r3<- 32 - r2
4913    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4914    subs    ip, r2, #32                 @  ip<- r2 - 32
4915    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
4916    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4917    b       .LOP_USHR_LONG_finish
4918
4919/* ------------------------------ */
4920    .balign 64
4921.L_OP_ADD_FLOAT: /* 0xa6 */
4922/* File: armv5te/OP_ADD_FLOAT.S */
4923/* File: armv5te/binop.S */
4924    /*
4925     * Generic 32-bit binary operation.  Provide an "instr" line that
4926     * specifies an instruction that performs "result = r0 op r1".
4927     * This could be an ARM instruction or a function call.  (If the result
4928     * comes back in a register other than r0, you can override "result".)
4929     *
4930     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4931     * vCC (r1).  Useful for integer division and modulus.  Note that we
4932     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4933     * handles it correctly.
4934     *
4935     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4936     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4937     *      mul-float, div-float, rem-float
4938     */
4939    /* binop vAA, vBB, vCC */
4940    FETCH(r0, 1)                        @ r0<- CCBB
4941    mov     r9, rINST, lsr #8           @ r9<- AA
4942    mov     r3, r0, lsr #8              @ r3<- CC
4943    and     r2, r0, #255                @ r2<- BB
4944    GET_VREG(r1, r3)                    @ r1<- vCC
4945    GET_VREG(r0, r2)                    @ r0<- vBB
4946    .if 0
4947    cmp     r1, #0                      @ is second operand zero?
4948    beq     common_errDivideByZero
4949    .endif
4950
4951    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4952                               @ optional op; may set condition codes
4953    bl      __aeabi_fadd                              @ r0<- op, r0-r3 changed
4954    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4955    SET_VREG(r0, r9)               @ vAA<- r0
4956    GOTO_OPCODE(ip)                     @ jump to next instruction
4957    /* 11-14 instructions */
4958
4959
4960
4961/* ------------------------------ */
4962    .balign 64
4963.L_OP_SUB_FLOAT: /* 0xa7 */
4964/* File: armv5te/OP_SUB_FLOAT.S */
4965/* File: armv5te/binop.S */
4966    /*
4967     * Generic 32-bit binary operation.  Provide an "instr" line that
4968     * specifies an instruction that performs "result = r0 op r1".
4969     * This could be an ARM instruction or a function call.  (If the result
4970     * comes back in a register other than r0, you can override "result".)
4971     *
4972     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4973     * vCC (r1).  Useful for integer division and modulus.  Note that we
4974     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4975     * handles it correctly.
4976     *
4977     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4978     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4979     *      mul-float, div-float, rem-float
4980     */
4981    /* binop vAA, vBB, vCC */
4982    FETCH(r0, 1)                        @ r0<- CCBB
4983    mov     r9, rINST, lsr #8           @ r9<- AA
4984    mov     r3, r0, lsr #8              @ r3<- CC
4985    and     r2, r0, #255                @ r2<- BB
4986    GET_VREG(r1, r3)                    @ r1<- vCC
4987    GET_VREG(r0, r2)                    @ r0<- vBB
4988    .if 0
4989    cmp     r1, #0                      @ is second operand zero?
4990    beq     common_errDivideByZero
4991    .endif
4992
4993    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4994                               @ optional op; may set condition codes
4995    bl      __aeabi_fsub                              @ r0<- op, r0-r3 changed
4996    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4997    SET_VREG(r0, r9)               @ vAA<- r0
4998    GOTO_OPCODE(ip)                     @ jump to next instruction
4999    /* 11-14 instructions */
5000
5001
5002
5003/* ------------------------------ */
5004    .balign 64
5005.L_OP_MUL_FLOAT: /* 0xa8 */
5006/* File: armv5te/OP_MUL_FLOAT.S */
5007/* File: armv5te/binop.S */
5008    /*
5009     * Generic 32-bit binary operation.  Provide an "instr" line that
5010     * specifies an instruction that performs "result = r0 op r1".
5011     * This could be an ARM instruction or a function call.  (If the result
5012     * comes back in a register other than r0, you can override "result".)
5013     *
5014     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5015     * vCC (r1).  Useful for integer division and modulus.  Note that we
5016     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5017     * handles it correctly.
5018     *
5019     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5020     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5021     *      mul-float, div-float, rem-float
5022     */
5023    /* binop vAA, vBB, vCC */
5024    FETCH(r0, 1)                        @ r0<- CCBB
5025    mov     r9, rINST, lsr #8           @ r9<- AA
5026    mov     r3, r0, lsr #8              @ r3<- CC
5027    and     r2, r0, #255                @ r2<- BB
5028    GET_VREG(r1, r3)                    @ r1<- vCC
5029    GET_VREG(r0, r2)                    @ r0<- vBB
5030    .if 0
5031    cmp     r1, #0                      @ is second operand zero?
5032    beq     common_errDivideByZero
5033    .endif
5034
5035    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5036                               @ optional op; may set condition codes
5037    bl      __aeabi_fmul                              @ r0<- op, r0-r3 changed
5038    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5039    SET_VREG(r0, r9)               @ vAA<- r0
5040    GOTO_OPCODE(ip)                     @ jump to next instruction
5041    /* 11-14 instructions */
5042
5043
5044
5045/* ------------------------------ */
5046    .balign 64
5047.L_OP_DIV_FLOAT: /* 0xa9 */
5048/* File: armv5te/OP_DIV_FLOAT.S */
5049/* File: armv5te/binop.S */
5050    /*
5051     * Generic 32-bit binary operation.  Provide an "instr" line that
5052     * specifies an instruction that performs "result = r0 op r1".
5053     * This could be an ARM instruction or a function call.  (If the result
5054     * comes back in a register other than r0, you can override "result".)
5055     *
5056     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5057     * vCC (r1).  Useful for integer division and modulus.  Note that we
5058     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5059     * handles it correctly.
5060     *
5061     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5062     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5063     *      mul-float, div-float, rem-float
5064     */
5065    /* binop vAA, vBB, vCC */
5066    FETCH(r0, 1)                        @ r0<- CCBB
5067    mov     r9, rINST, lsr #8           @ r9<- AA
5068    mov     r3, r0, lsr #8              @ r3<- CC
5069    and     r2, r0, #255                @ r2<- BB
5070    GET_VREG(r1, r3)                    @ r1<- vCC
5071    GET_VREG(r0, r2)                    @ r0<- vBB
5072    .if 0
5073    cmp     r1, #0                      @ is second operand zero?
5074    beq     common_errDivideByZero
5075    .endif
5076
5077    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5078                               @ optional op; may set condition codes
5079    bl      __aeabi_fdiv                              @ r0<- op, r0-r3 changed
5080    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5081    SET_VREG(r0, r9)               @ vAA<- r0
5082    GOTO_OPCODE(ip)                     @ jump to next instruction
5083    /* 11-14 instructions */
5084
5085
5086
5087/* ------------------------------ */
5088    .balign 64
5089.L_OP_REM_FLOAT: /* 0xaa */
5090/* File: armv5te/OP_REM_FLOAT.S */
5091/* EABI doesn't define a float remainder function, but libm does */
5092/* File: armv5te/binop.S */
5093    /*
5094     * Generic 32-bit binary operation.  Provide an "instr" line that
5095     * specifies an instruction that performs "result = r0 op r1".
5096     * This could be an ARM instruction or a function call.  (If the result
5097     * comes back in a register other than r0, you can override "result".)
5098     *
5099     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5100     * vCC (r1).  Useful for integer division and modulus.  Note that we
5101     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5102     * handles it correctly.
5103     *
5104     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5105     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5106     *      mul-float, div-float, rem-float
5107     */
5108    /* binop vAA, vBB, vCC */
5109    FETCH(r0, 1)                        @ r0<- CCBB
5110    mov     r9, rINST, lsr #8           @ r9<- AA
5111    mov     r3, r0, lsr #8              @ r3<- CC
5112    and     r2, r0, #255                @ r2<- BB
5113    GET_VREG(r1, r3)                    @ r1<- vCC
5114    GET_VREG(r0, r2)                    @ r0<- vBB
5115    .if 0
5116    cmp     r1, #0                      @ is second operand zero?
5117    beq     common_errDivideByZero
5118    .endif
5119
5120    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5121                               @ optional op; may set condition codes
5122    bl      fmodf                              @ r0<- op, r0-r3 changed
5123    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5124    SET_VREG(r0, r9)               @ vAA<- r0
5125    GOTO_OPCODE(ip)                     @ jump to next instruction
5126    /* 11-14 instructions */
5127
5128
5129
5130/* ------------------------------ */
5131    .balign 64
5132.L_OP_ADD_DOUBLE: /* 0xab */
5133/* File: armv5te/OP_ADD_DOUBLE.S */
5134/* File: armv5te/binopWide.S */
5135    /*
5136     * Generic 64-bit binary operation.  Provide an "instr" line that
5137     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5138     * This could be an ARM instruction or a function call.  (If the result
5139     * comes back in a register other than r0, you can override "result".)
5140     *
5141     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5142     * vCC (r1).  Useful for integer division and modulus.
5143     *
5144     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5145     *      xor-long, add-double, sub-double, mul-double, div-double,
5146     *      rem-double
5147     *
5148     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5149     */
5150    /* binop vAA, vBB, vCC */
5151    FETCH(r0, 1)                        @ r0<- CCBB
5152    mov     r9, rINST, lsr #8           @ r9<- AA
5153    and     r2, r0, #255                @ r2<- BB
5154    mov     r3, r0, lsr #8              @ r3<- CC
5155    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5156    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5157    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5158    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5159    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5160    .if 0
5161    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5162    beq     common_errDivideByZero
5163    .endif
5164    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5165
5166                               @ optional op; may set condition codes
5167    bl      __aeabi_dadd                              @ result<- op, r0-r3 changed
5168    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5169    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5170    GOTO_OPCODE(ip)                     @ jump to next instruction
5171    /* 14-17 instructions */
5172
5173
5174
5175/* ------------------------------ */
5176    .balign 64
5177.L_OP_SUB_DOUBLE: /* 0xac */
5178/* File: armv5te/OP_SUB_DOUBLE.S */
5179/* File: armv5te/binopWide.S */
5180    /*
5181     * Generic 64-bit binary operation.  Provide an "instr" line that
5182     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5183     * This could be an ARM instruction or a function call.  (If the result
5184     * comes back in a register other than r0, you can override "result".)
5185     *
5186     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5187     * vCC (r1).  Useful for integer division and modulus.
5188     *
5189     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5190     *      xor-long, add-double, sub-double, mul-double, div-double,
5191     *      rem-double
5192     *
5193     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5194     */
5195    /* binop vAA, vBB, vCC */
5196    FETCH(r0, 1)                        @ r0<- CCBB
5197    mov     r9, rINST, lsr #8           @ r9<- AA
5198    and     r2, r0, #255                @ r2<- BB
5199    mov     r3, r0, lsr #8              @ r3<- CC
5200    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5201    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5202    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5203    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5204    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5205    .if 0
5206    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5207    beq     common_errDivideByZero
5208    .endif
5209    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5210
5211                               @ optional op; may set condition codes
5212    bl      __aeabi_dsub                              @ result<- op, r0-r3 changed
5213    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5214    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5215    GOTO_OPCODE(ip)                     @ jump to next instruction
5216    /* 14-17 instructions */
5217
5218
5219
5220/* ------------------------------ */
5221    .balign 64
5222.L_OP_MUL_DOUBLE: /* 0xad */
5223/* File: armv5te/OP_MUL_DOUBLE.S */
5224/* File: armv5te/binopWide.S */
5225    /*
5226     * Generic 64-bit binary operation.  Provide an "instr" line that
5227     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5228     * This could be an ARM instruction or a function call.  (If the result
5229     * comes back in a register other than r0, you can override "result".)
5230     *
5231     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5232     * vCC (r1).  Useful for integer division and modulus.
5233     *
5234     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5235     *      xor-long, add-double, sub-double, mul-double, div-double,
5236     *      rem-double
5237     *
5238     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5239     */
5240    /* binop vAA, vBB, vCC */
5241    FETCH(r0, 1)                        @ r0<- CCBB
5242    mov     r9, rINST, lsr #8           @ r9<- AA
5243    and     r2, r0, #255                @ r2<- BB
5244    mov     r3, r0, lsr #8              @ r3<- CC
5245    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5246    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5247    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5248    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5249    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5250    .if 0
5251    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5252    beq     common_errDivideByZero
5253    .endif
5254    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5255
5256                               @ optional op; may set condition codes
5257    bl      __aeabi_dmul                              @ result<- op, r0-r3 changed
5258    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5259    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5260    GOTO_OPCODE(ip)                     @ jump to next instruction
5261    /* 14-17 instructions */
5262
5263
5264
5265/* ------------------------------ */
5266    .balign 64
5267.L_OP_DIV_DOUBLE: /* 0xae */
5268/* File: armv5te/OP_DIV_DOUBLE.S */
5269/* File: armv5te/binopWide.S */
5270    /*
5271     * Generic 64-bit binary operation.  Provide an "instr" line that
5272     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5273     * This could be an ARM instruction or a function call.  (If the result
5274     * comes back in a register other than r0, you can override "result".)
5275     *
5276     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5277     * vCC (r1).  Useful for integer division and modulus.
5278     *
5279     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5280     *      xor-long, add-double, sub-double, mul-double, div-double,
5281     *      rem-double
5282     *
5283     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5284     */
5285    /* binop vAA, vBB, vCC */
5286    FETCH(r0, 1)                        @ r0<- CCBB
5287    mov     r9, rINST, lsr #8           @ r9<- AA
5288    and     r2, r0, #255                @ r2<- BB
5289    mov     r3, r0, lsr #8              @ r3<- CC
5290    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5291    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5292    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5293    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5294    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5295    .if 0
5296    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5297    beq     common_errDivideByZero
5298    .endif
5299    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5300
5301                               @ optional op; may set condition codes
5302    bl      __aeabi_ddiv                              @ result<- op, r0-r3 changed
5303    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5304    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5305    GOTO_OPCODE(ip)                     @ jump to next instruction
5306    /* 14-17 instructions */
5307
5308
5309
5310/* ------------------------------ */
5311    .balign 64
5312.L_OP_REM_DOUBLE: /* 0xaf */
5313/* File: armv5te/OP_REM_DOUBLE.S */
5314/* EABI doesn't define a double remainder function, but libm does */
5315/* File: armv5te/binopWide.S */
5316    /*
5317     * Generic 64-bit binary operation.  Provide an "instr" line that
5318     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5319     * This could be an ARM instruction or a function call.  (If the result
5320     * comes back in a register other than r0, you can override "result".)
5321     *
5322     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5323     * vCC (r1).  Useful for integer division and modulus.
5324     *
5325     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5326     *      xor-long, add-double, sub-double, mul-double, div-double,
5327     *      rem-double
5328     *
5329     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5330     */
5331    /* binop vAA, vBB, vCC */
5332    FETCH(r0, 1)                        @ r0<- CCBB
5333    mov     r9, rINST, lsr #8           @ r9<- AA
5334    and     r2, r0, #255                @ r2<- BB
5335    mov     r3, r0, lsr #8              @ r3<- CC
5336    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5337    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5338    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5339    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5340    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5341    .if 0
5342    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5343    beq     common_errDivideByZero
5344    .endif
5345    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5346
5347                               @ optional op; may set condition codes
5348    bl      fmod                              @ result<- op, r0-r3 changed
5349    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5350    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5351    GOTO_OPCODE(ip)                     @ jump to next instruction
5352    /* 14-17 instructions */
5353
5354
5355
5356/* ------------------------------ */
5357    .balign 64
5358.L_OP_ADD_INT_2ADDR: /* 0xb0 */
5359/* File: armv5te/OP_ADD_INT_2ADDR.S */
5360/* File: armv5te/binop2addr.S */
5361    /*
5362     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5363     * that specifies an instruction that performs "result = r0 op r1".
5364     * This could be an ARM instruction or a function call.  (If the result
5365     * comes back in a register other than r0, you can override "result".)
5366     *
5367     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5368     * vCC (r1).  Useful for integer division and modulus.
5369     *
5370     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5371     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5372     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5373     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5374     */
5375    /* binop/2addr vA, vB */
5376    mov     r9, rINST, lsr #8           @ r9<- A+
5377    mov     r3, rINST, lsr #12          @ r3<- B
5378    and     r9, r9, #15
5379    GET_VREG(r0, r9)                    @ r0<- vA
5380    GET_VREG(r1, r3)                    @ r1<- vB
5381    .if 0
5382    cmp     r1, #0                      @ is second operand zero?
5383    beq     common_errDivideByZero
5384    .endif
5385    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5386
5387                               @ optional op; may set condition codes
5388    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
5389    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5390    SET_VREG(r0, r9)               @ vAA<- r0
5391    GOTO_OPCODE(ip)                     @ jump to next instruction
5392    /* 10-13 instructions */
5393
5394
5395
5396/* ------------------------------ */
5397    .balign 64
5398.L_OP_SUB_INT_2ADDR: /* 0xb1 */
5399/* File: armv5te/OP_SUB_INT_2ADDR.S */
5400/* File: armv5te/binop2addr.S */
5401    /*
5402     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5403     * that specifies an instruction that performs "result = r0 op r1".
5404     * This could be an ARM instruction or a function call.  (If the result
5405     * comes back in a register other than r0, you can override "result".)
5406     *
5407     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5408     * vCC (r1).  Useful for integer division and modulus.
5409     *
5410     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5411     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5412     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5413     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5414     */
5415    /* binop/2addr vA, vB */
5416    mov     r9, rINST, lsr #8           @ r9<- A+
5417    mov     r3, rINST, lsr #12          @ r3<- B
5418    and     r9, r9, #15
5419    GET_VREG(r0, r9)                    @ r0<- vA
5420    GET_VREG(r1, r3)                    @ r1<- vB
5421    .if 0
5422    cmp     r1, #0                      @ is second operand zero?
5423    beq     common_errDivideByZero
5424    .endif
5425    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5426
5427                               @ optional op; may set condition codes
5428    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
5429    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5430    SET_VREG(r0, r9)               @ vAA<- r0
5431    GOTO_OPCODE(ip)                     @ jump to next instruction
5432    /* 10-13 instructions */
5433
5434
5435
5436/* ------------------------------ */
5437    .balign 64
5438.L_OP_MUL_INT_2ADDR: /* 0xb2 */
5439/* File: armv5te/OP_MUL_INT_2ADDR.S */
5440/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
5441/* File: armv5te/binop2addr.S */
5442    /*
5443     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5444     * that specifies an instruction that performs "result = r0 op r1".
5445     * This could be an ARM instruction or a function call.  (If the result
5446     * comes back in a register other than r0, you can override "result".)
5447     *
5448     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5449     * vCC (r1).  Useful for integer division and modulus.
5450     *
5451     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5452     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5453     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5454     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5455     */
5456    /* binop/2addr vA, vB */
5457    mov     r9, rINST, lsr #8           @ r9<- A+
5458    mov     r3, rINST, lsr #12          @ r3<- B
5459    and     r9, r9, #15
5460    GET_VREG(r0, r9)                    @ r0<- vA
5461    GET_VREG(r1, r3)                    @ r1<- vB
5462    .if 0
5463    cmp     r1, #0                      @ is second operand zero?
5464    beq     common_errDivideByZero
5465    .endif
5466    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5467
5468                               @ optional op; may set condition codes
5469    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
5470    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5471    SET_VREG(r0, r9)               @ vAA<- r0
5472    GOTO_OPCODE(ip)                     @ jump to next instruction
5473    /* 10-13 instructions */
5474
5475
5476
5477/* ------------------------------ */
5478    .balign 64
5479.L_OP_DIV_INT_2ADDR: /* 0xb3 */
5480/* File: armv5te/OP_DIV_INT_2ADDR.S */
5481/* File: armv5te/binop2addr.S */
5482    /*
5483     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5484     * that specifies an instruction that performs "result = r0 op r1".
5485     * This could be an ARM instruction or a function call.  (If the result
5486     * comes back in a register other than r0, you can override "result".)
5487     *
5488     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5489     * vCC (r1).  Useful for integer division and modulus.
5490     *
5491     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5492     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5493     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5494     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5495     */
5496    /* binop/2addr vA, vB */
5497    mov     r9, rINST, lsr #8           @ r9<- A+
5498    mov     r3, rINST, lsr #12          @ r3<- B
5499    and     r9, r9, #15
5500    GET_VREG(r0, r9)                    @ r0<- vA
5501    GET_VREG(r1, r3)                    @ r1<- vB
5502    .if 1
5503    cmp     r1, #0                      @ is second operand zero?
5504    beq     common_errDivideByZero
5505    .endif
5506    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5507
5508                               @ optional op; may set condition codes
5509    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
5510    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5511    SET_VREG(r0, r9)               @ vAA<- r0
5512    GOTO_OPCODE(ip)                     @ jump to next instruction
5513    /* 10-13 instructions */
5514
5515
5516
5517/* ------------------------------ */
5518    .balign 64
5519.L_OP_REM_INT_2ADDR: /* 0xb4 */
5520/* File: armv5te/OP_REM_INT_2ADDR.S */
5521/* idivmod returns quotient in r0 and remainder in r1 */
5522/* File: armv5te/binop2addr.S */
5523    /*
5524     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5525     * that specifies an instruction that performs "result = r0 op r1".
5526     * This could be an ARM instruction or a function call.  (If the result
5527     * comes back in a register other than r0, you can override "result".)
5528     *
5529     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5530     * vCC (r1).  Useful for integer division and modulus.
5531     *
5532     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5533     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5534     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5535     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5536     */
5537    /* binop/2addr vA, vB */
5538    mov     r9, rINST, lsr #8           @ r9<- A+
5539    mov     r3, rINST, lsr #12          @ r3<- B
5540    and     r9, r9, #15
5541    GET_VREG(r0, r9)                    @ r0<- vA
5542    GET_VREG(r1, r3)                    @ r1<- vB
5543    .if 1
5544    cmp     r1, #0                      @ is second operand zero?
5545    beq     common_errDivideByZero
5546    .endif
5547    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5548
5549                               @ optional op; may set condition codes
5550    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
5551    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5552    SET_VREG(r1, r9)               @ vAA<- r1
5553    GOTO_OPCODE(ip)                     @ jump to next instruction
5554    /* 10-13 instructions */
5555
5556
5557
5558/* ------------------------------ */
5559    .balign 64
5560.L_OP_AND_INT_2ADDR: /* 0xb5 */
5561/* File: armv5te/OP_AND_INT_2ADDR.S */
5562/* File: armv5te/binop2addr.S */
5563    /*
5564     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5565     * that specifies an instruction that performs "result = r0 op r1".
5566     * This could be an ARM instruction or a function call.  (If the result
5567     * comes back in a register other than r0, you can override "result".)
5568     *
5569     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5570     * vCC (r1).  Useful for integer division and modulus.
5571     *
5572     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5573     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5574     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5575     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5576     */
5577    /* binop/2addr vA, vB */
5578    mov     r9, rINST, lsr #8           @ r9<- A+
5579    mov     r3, rINST, lsr #12          @ r3<- B
5580    and     r9, r9, #15
5581    GET_VREG(r0, r9)                    @ r0<- vA
5582    GET_VREG(r1, r3)                    @ r1<- vB
5583    .if 0
5584    cmp     r1, #0                      @ is second operand zero?
5585    beq     common_errDivideByZero
5586    .endif
5587    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5588
5589                               @ optional op; may set condition codes
5590    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
5591    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5592    SET_VREG(r0, r9)               @ vAA<- r0
5593    GOTO_OPCODE(ip)                     @ jump to next instruction
5594    /* 10-13 instructions */
5595
5596
5597
5598/* ------------------------------ */
5599    .balign 64
5600.L_OP_OR_INT_2ADDR: /* 0xb6 */
5601/* File: armv5te/OP_OR_INT_2ADDR.S */
5602/* File: armv5te/binop2addr.S */
5603    /*
5604     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5605     * that specifies an instruction that performs "result = r0 op r1".
5606     * This could be an ARM instruction or a function call.  (If the result
5607     * comes back in a register other than r0, you can override "result".)
5608     *
5609     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5610     * vCC (r1).  Useful for integer division and modulus.
5611     *
5612     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5613     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5614     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5615     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5616     */
5617    /* binop/2addr vA, vB */
5618    mov     r9, rINST, lsr #8           @ r9<- A+
5619    mov     r3, rINST, lsr #12          @ r3<- B
5620    and     r9, r9, #15
5621    GET_VREG(r0, r9)                    @ r0<- vA
5622    GET_VREG(r1, r3)                    @ r1<- vB
5623    .if 0
5624    cmp     r1, #0                      @ is second operand zero?
5625    beq     common_errDivideByZero
5626    .endif
5627    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5628
5629                               @ optional op; may set condition codes
5630    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
5631    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5632    SET_VREG(r0, r9)               @ vAA<- r0
5633    GOTO_OPCODE(ip)                     @ jump to next instruction
5634    /* 10-13 instructions */
5635
5636
5637
5638/* ------------------------------ */
5639    .balign 64
5640.L_OP_XOR_INT_2ADDR: /* 0xb7 */
5641/* File: armv5te/OP_XOR_INT_2ADDR.S */
5642/* File: armv5te/binop2addr.S */
5643    /*
5644     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5645     * that specifies an instruction that performs "result = r0 op r1".
5646     * This could be an ARM instruction or a function call.  (If the result
5647     * comes back in a register other than r0, you can override "result".)
5648     *
5649     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5650     * vCC (r1).  Useful for integer division and modulus.
5651     *
5652     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5653     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5654     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5655     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5656     */
5657    /* binop/2addr vA, vB */
5658    mov     r9, rINST, lsr #8           @ r9<- A+
5659    mov     r3, rINST, lsr #12          @ r3<- B
5660    and     r9, r9, #15
5661    GET_VREG(r0, r9)                    @ r0<- vA
5662    GET_VREG(r1, r3)                    @ r1<- vB
5663    .if 0
5664    cmp     r1, #0                      @ is second operand zero?
5665    beq     common_errDivideByZero
5666    .endif
5667    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5668
5669                               @ optional op; may set condition codes
5670    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
5671    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5672    SET_VREG(r0, r9)               @ vAA<- r0
5673    GOTO_OPCODE(ip)                     @ jump to next instruction
5674    /* 10-13 instructions */
5675
5676
5677
5678/* ------------------------------ */
5679    .balign 64
5680.L_OP_SHL_INT_2ADDR: /* 0xb8 */
5681/* File: armv5te/OP_SHL_INT_2ADDR.S */
5682/* File: armv5te/binop2addr.S */
5683    /*
5684     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5685     * that specifies an instruction that performs "result = r0 op r1".
5686     * This could be an ARM instruction or a function call.  (If the result
5687     * comes back in a register other than r0, you can override "result".)
5688     *
5689     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5690     * vCC (r1).  Useful for integer division and modulus.
5691     *
5692     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5693     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5694     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5695     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5696     */
5697    /* binop/2addr vA, vB */
5698    mov     r9, rINST, lsr #8           @ r9<- A+
5699    mov     r3, rINST, lsr #12          @ r3<- B
5700    and     r9, r9, #15
5701    GET_VREG(r0, r9)                    @ r0<- vA
5702    GET_VREG(r1, r3)                    @ r1<- vB
5703    .if 0
5704    cmp     r1, #0                      @ is second operand zero?
5705    beq     common_errDivideByZero
5706    .endif
5707    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5708
5709    and     r1, r1, #31                           @ optional op; may set condition codes
5710    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
5711    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5712    SET_VREG(r0, r9)               @ vAA<- r0
5713    GOTO_OPCODE(ip)                     @ jump to next instruction
5714    /* 10-13 instructions */
5715
5716
5717
5718/* ------------------------------ */
5719    .balign 64
5720.L_OP_SHR_INT_2ADDR: /* 0xb9 */
5721/* File: armv5te/OP_SHR_INT_2ADDR.S */
5722/* File: armv5te/binop2addr.S */
5723    /*
5724     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5725     * that specifies an instruction that performs "result = r0 op r1".
5726     * This could be an ARM instruction or a function call.  (If the result
5727     * comes back in a register other than r0, you can override "result".)
5728     *
5729     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5730     * vCC (r1).  Useful for integer division and modulus.
5731     *
5732     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5733     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5734     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5735     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5736     */
5737    /* binop/2addr vA, vB */
5738    mov     r9, rINST, lsr #8           @ r9<- A+
5739    mov     r3, rINST, lsr #12          @ r3<- B
5740    and     r9, r9, #15
5741    GET_VREG(r0, r9)                    @ r0<- vA
5742    GET_VREG(r1, r3)                    @ r1<- vB
5743    .if 0
5744    cmp     r1, #0                      @ is second operand zero?
5745    beq     common_errDivideByZero
5746    .endif
5747    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5748
5749    and     r1, r1, #31                           @ optional op; may set condition codes
5750    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
5751    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5752    SET_VREG(r0, r9)               @ vAA<- r0
5753    GOTO_OPCODE(ip)                     @ jump to next instruction
5754    /* 10-13 instructions */
5755
5756
5757
5758/* ------------------------------ */
5759    .balign 64
5760.L_OP_USHR_INT_2ADDR: /* 0xba */
5761/* File: armv5te/OP_USHR_INT_2ADDR.S */
5762/* File: armv5te/binop2addr.S */
5763    /*
5764     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5765     * that specifies an instruction that performs "result = r0 op r1".
5766     * This could be an ARM instruction or a function call.  (If the result
5767     * comes back in a register other than r0, you can override "result".)
5768     *
5769     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5770     * vCC (r1).  Useful for integer division and modulus.
5771     *
5772     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5773     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5774     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5775     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5776     */
5777    /* binop/2addr vA, vB */
5778    mov     r9, rINST, lsr #8           @ r9<- A+
5779    mov     r3, rINST, lsr #12          @ r3<- B
5780    and     r9, r9, #15
5781    GET_VREG(r0, r9)                    @ r0<- vA
5782    GET_VREG(r1, r3)                    @ r1<- vB
5783    .if 0
5784    cmp     r1, #0                      @ is second operand zero?
5785    beq     common_errDivideByZero
5786    .endif
5787    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5788
5789    and     r1, r1, #31                           @ optional op; may set condition codes
5790    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
5791    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5792    SET_VREG(r0, r9)               @ vAA<- r0
5793    GOTO_OPCODE(ip)                     @ jump to next instruction
5794    /* 10-13 instructions */
5795
5796
5797
5798/* ------------------------------ */
5799    .balign 64
5800.L_OP_ADD_LONG_2ADDR: /* 0xbb */
5801/* File: armv5te/OP_ADD_LONG_2ADDR.S */
5802/* File: armv5te/binopWide2addr.S */
5803    /*
5804     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5805     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5806     * This could be an ARM instruction or a function call.  (If the result
5807     * comes back in a register other than r0, you can override "result".)
5808     *
5809     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5810     * vCC (r1).  Useful for integer division and modulus.
5811     *
5812     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5813     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5814     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5815     *      rem-double/2addr
5816     */
5817    /* binop/2addr vA, vB */
5818    mov     r9, rINST, lsr #8           @ r9<- A+
5819    mov     r1, rINST, lsr #12          @ r1<- B
5820    and     r9, r9, #15
5821    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5822    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5823    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5824    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5825    .if 0
5826    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5827    beq     common_errDivideByZero
5828    .endif
5829    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5830
5831    adds    r0, r0, r2                           @ optional op; may set condition codes
5832    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
5833    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5834    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5835    GOTO_OPCODE(ip)                     @ jump to next instruction
5836    /* 12-15 instructions */
5837
5838
5839
5840/* ------------------------------ */
5841    .balign 64
5842.L_OP_SUB_LONG_2ADDR: /* 0xbc */
5843/* File: armv5te/OP_SUB_LONG_2ADDR.S */
5844/* File: armv5te/binopWide2addr.S */
5845    /*
5846     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5847     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5848     * This could be an ARM instruction or a function call.  (If the result
5849     * comes back in a register other than r0, you can override "result".)
5850     *
5851     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5852     * vCC (r1).  Useful for integer division and modulus.
5853     *
5854     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5855     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5856     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5857     *      rem-double/2addr
5858     */
5859    /* binop/2addr vA, vB */
5860    mov     r9, rINST, lsr #8           @ r9<- A+
5861    mov     r1, rINST, lsr #12          @ r1<- B
5862    and     r9, r9, #15
5863    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5864    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5865    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5866    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5867    .if 0
5868    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5869    beq     common_errDivideByZero
5870    .endif
5871    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5872
5873    subs    r0, r0, r2                           @ optional op; may set condition codes
5874    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
5875    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5876    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5877    GOTO_OPCODE(ip)                     @ jump to next instruction
5878    /* 12-15 instructions */
5879
5880
5881
5882/* ------------------------------ */
5883    .balign 64
5884.L_OP_MUL_LONG_2ADDR: /* 0xbd */
5885/* File: armv5te/OP_MUL_LONG_2ADDR.S */
5886    /*
5887     * Signed 64-bit integer multiply, "/2addr" version.
5888     *
5889     * See OP_MUL_LONG for an explanation.
5890     *
5891     * We get a little tight on registers, so to avoid looking up &fp[A]
5892     * again we stuff it into rINST.
5893     */
5894    /* mul-long/2addr vA, vB */
5895    mov     r9, rINST, lsr #8           @ r9<- A+
5896    mov     r1, rINST, lsr #12          @ r1<- B
5897    and     r9, r9, #15
5898    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5899    add     rINST, rFP, r9, lsl #2      @ rINST<- &fp[A]
5900    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5901    ldmia   rINST, {r0-r1}              @ r0/r1<- vAA/vAA+1
5902    mul     ip, r2, r1                  @  ip<- ZxW
5903    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
5904    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
5905    mov     r0, rINST                   @ r0<- &fp[A] (free up rINST)
5906    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5907    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
5908    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5909    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
5910    GOTO_OPCODE(ip)                     @ jump to next instruction
5911
5912
5913/* ------------------------------ */
5914    .balign 64
5915.L_OP_DIV_LONG_2ADDR: /* 0xbe */
5916/* File: armv5te/OP_DIV_LONG_2ADDR.S */
5917/* File: armv5te/binopWide2addr.S */
5918    /*
5919     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5920     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5921     * This could be an ARM instruction or a function call.  (If the result
5922     * comes back in a register other than r0, you can override "result".)
5923     *
5924     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5925     * vCC (r1).  Useful for integer division and modulus.
5926     *
5927     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5928     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5929     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5930     *      rem-double/2addr
5931     */
5932    /* binop/2addr vA, vB */
5933    mov     r9, rINST, lsr #8           @ r9<- A+
5934    mov     r1, rINST, lsr #12          @ r1<- B
5935    and     r9, r9, #15
5936    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5937    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5938    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5939    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5940    .if 1
5941    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5942    beq     common_errDivideByZero
5943    .endif
5944    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5945
5946                               @ optional op; may set condition codes
5947    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5948    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5949    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5950    GOTO_OPCODE(ip)                     @ jump to next instruction
5951    /* 12-15 instructions */
5952
5953
5954
5955/* ------------------------------ */
5956    .balign 64
5957.L_OP_REM_LONG_2ADDR: /* 0xbf */
5958/* File: armv5te/OP_REM_LONG_2ADDR.S */
5959/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
5960/* File: armv5te/binopWide2addr.S */
5961    /*
5962     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5963     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5964     * This could be an ARM instruction or a function call.  (If the result
5965     * comes back in a register other than r0, you can override "result".)
5966     *
5967     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5968     * vCC (r1).  Useful for integer division and modulus.
5969     *
5970     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5971     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5972     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5973     *      rem-double/2addr
5974     */
5975    /* binop/2addr vA, vB */
5976    mov     r9, rINST, lsr #8           @ r9<- A+
5977    mov     r1, rINST, lsr #12          @ r1<- B
5978    and     r9, r9, #15
5979    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5980    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5981    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5982    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5983    .if 1
5984    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5985    beq     common_errDivideByZero
5986    .endif
5987    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5988
5989                               @ optional op; may set condition codes
5990    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5991    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5992    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
5993    GOTO_OPCODE(ip)                     @ jump to next instruction
5994    /* 12-15 instructions */
5995
5996
5997
5998/* ------------------------------ */
5999    .balign 64
6000.L_OP_AND_LONG_2ADDR: /* 0xc0 */
6001/* File: armv5te/OP_AND_LONG_2ADDR.S */
6002/* File: armv5te/binopWide2addr.S */
6003    /*
6004     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6005     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6006     * This could be an ARM instruction or a function call.  (If the result
6007     * comes back in a register other than r0, you can override "result".)
6008     *
6009     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6010     * vCC (r1).  Useful for integer division and modulus.
6011     *
6012     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6013     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6014     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6015     *      rem-double/2addr
6016     */
6017    /* binop/2addr vA, vB */
6018    mov     r9, rINST, lsr #8           @ r9<- A+
6019    mov     r1, rINST, lsr #12          @ r1<- B
6020    and     r9, r9, #15
6021    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6022    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6023    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6024    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6025    .if 0
6026    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6027    beq     common_errDivideByZero
6028    .endif
6029    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6030
6031    and     r0, r0, r2                           @ optional op; may set condition codes
6032    and     r1, r1, r3                              @ result<- op, r0-r3 changed
6033    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6034    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6035    GOTO_OPCODE(ip)                     @ jump to next instruction
6036    /* 12-15 instructions */
6037
6038
6039
6040/* ------------------------------ */
6041    .balign 64
6042.L_OP_OR_LONG_2ADDR: /* 0xc1 */
6043/* File: armv5te/OP_OR_LONG_2ADDR.S */
6044/* File: armv5te/binopWide2addr.S */
6045    /*
6046     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6047     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6048     * This could be an ARM instruction or a function call.  (If the result
6049     * comes back in a register other than r0, you can override "result".)
6050     *
6051     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6052     * vCC (r1).  Useful for integer division and modulus.
6053     *
6054     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6055     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6056     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6057     *      rem-double/2addr
6058     */
6059    /* binop/2addr vA, vB */
6060    mov     r9, rINST, lsr #8           @ r9<- A+
6061    mov     r1, rINST, lsr #12          @ r1<- B
6062    and     r9, r9, #15
6063    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6064    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6065    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6066    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6067    .if 0
6068    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6069    beq     common_errDivideByZero
6070    .endif
6071    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6072
6073    orr     r0, r0, r2                           @ optional op; may set condition codes
6074    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
6075    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6076    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6077    GOTO_OPCODE(ip)                     @ jump to next instruction
6078    /* 12-15 instructions */
6079
6080
6081
6082/* ------------------------------ */
6083    .balign 64
6084.L_OP_XOR_LONG_2ADDR: /* 0xc2 */
6085/* File: armv5te/OP_XOR_LONG_2ADDR.S */
6086/* File: armv5te/binopWide2addr.S */
6087    /*
6088     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6089     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6090     * This could be an ARM instruction or a function call.  (If the result
6091     * comes back in a register other than r0, you can override "result".)
6092     *
6093     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6094     * vCC (r1).  Useful for integer division and modulus.
6095     *
6096     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6097     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6098     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6099     *      rem-double/2addr
6100     */
6101    /* binop/2addr vA, vB */
6102    mov     r9, rINST, lsr #8           @ r9<- A+
6103    mov     r1, rINST, lsr #12          @ r1<- B
6104    and     r9, r9, #15
6105    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6106    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6107    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6108    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6109    .if 0
6110    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6111    beq     common_errDivideByZero
6112    .endif
6113    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6114
6115    eor     r0, r0, r2                           @ optional op; may set condition codes
6116    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
6117    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6118    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6119    GOTO_OPCODE(ip)                     @ jump to next instruction
6120    /* 12-15 instructions */
6121
6122
6123
6124/* ------------------------------ */
6125    .balign 64
6126.L_OP_SHL_LONG_2ADDR: /* 0xc3 */
6127/* File: armv5te/OP_SHL_LONG_2ADDR.S */
6128    /*
6129     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6130     * 32-bit shift distance.
6131     */
6132    /* shl-long/2addr vA, vB */
6133    mov     r9, rINST, lsr #8           @ r9<- A+
6134    mov     r3, rINST, lsr #12          @ r3<- B
6135    and     r9, r9, #15
6136    GET_VREG(r2, r3)                    @ r2<- vB
6137    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6138    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6139    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6140
6141    mov     r1, r1, asl r2              @  r1<- r1 << r2
6142    rsb     r3, r2, #32                 @  r3<- 32 - r2
6143    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
6144    subs    ip, r2, #32                 @  ip<- r2 - 32
6145    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6146    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
6147    mov     r0, r0, asl r2              @  r0<- r0 << r2
6148    b       .LOP_SHL_LONG_2ADDR_finish
6149
6150/* ------------------------------ */
6151    .balign 64
6152.L_OP_SHR_LONG_2ADDR: /* 0xc4 */
6153/* File: armv5te/OP_SHR_LONG_2ADDR.S */
6154    /*
6155     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6156     * 32-bit shift distance.
6157     */
6158    /* shr-long/2addr vA, vB */
6159    mov     r9, rINST, lsr #8           @ r9<- A+
6160    mov     r3, rINST, lsr #12          @ r3<- B
6161    and     r9, r9, #15
6162    GET_VREG(r2, r3)                    @ r2<- vB
6163    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6164    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6165    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6166
6167    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6168    rsb     r3, r2, #32                 @  r3<- 32 - r2
6169    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6170    subs    ip, r2, #32                 @  ip<- r2 - 32
6171    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6172    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
6173    mov     r1, r1, asr r2              @  r1<- r1 >> r2
6174    b       .LOP_SHR_LONG_2ADDR_finish
6175
6176/* ------------------------------ */
6177    .balign 64
6178.L_OP_USHR_LONG_2ADDR: /* 0xc5 */
6179/* File: armv5te/OP_USHR_LONG_2ADDR.S */
6180    /*
6181     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6182     * 32-bit shift distance.
6183     */
6184    /* ushr-long/2addr vA, vB */
6185    mov     r9, rINST, lsr #8           @ r9<- A+
6186    mov     r3, rINST, lsr #12          @ r3<- B
6187    and     r9, r9, #15
6188    GET_VREG(r2, r3)                    @ r2<- vB
6189    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6190    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6191    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6192
6193    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6194    rsb     r3, r2, #32                 @  r3<- 32 - r2
6195    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6196    subs    ip, r2, #32                 @  ip<- r2 - 32
6197    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6198    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
6199    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
6200    b       .LOP_USHR_LONG_2ADDR_finish
6201
6202/* ------------------------------ */
6203    .balign 64
6204.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
6205/* File: armv5te/OP_ADD_FLOAT_2ADDR.S */
6206/* File: armv5te/binop2addr.S */
6207    /*
6208     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6209     * that specifies an instruction that performs "result = r0 op r1".
6210     * This could be an ARM instruction or a function call.  (If the result
6211     * comes back in a register other than r0, you can override "result".)
6212     *
6213     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6214     * vCC (r1).  Useful for integer division and modulus.
6215     *
6216     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6217     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6218     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6219     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6220     */
6221    /* binop/2addr vA, vB */
6222    mov     r9, rINST, lsr #8           @ r9<- A+
6223    mov     r3, rINST, lsr #12          @ r3<- B
6224    and     r9, r9, #15
6225    GET_VREG(r0, r9)                    @ r0<- vA
6226    GET_VREG(r1, r3)                    @ r1<- vB
6227    .if 0
6228    cmp     r1, #0                      @ is second operand zero?
6229    beq     common_errDivideByZero
6230    .endif
6231    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6232
6233                               @ optional op; may set condition codes
6234    bl      __aeabi_fadd                              @ r0<- op, r0-r3 changed
6235    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6236    SET_VREG(r0, r9)               @ vAA<- r0
6237    GOTO_OPCODE(ip)                     @ jump to next instruction
6238    /* 10-13 instructions */
6239
6240
6241
6242/* ------------------------------ */
6243    .balign 64
6244.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
6245/* File: armv5te/OP_SUB_FLOAT_2ADDR.S */
6246/* File: armv5te/binop2addr.S */
6247    /*
6248     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6249     * that specifies an instruction that performs "result = r0 op r1".
6250     * This could be an ARM instruction or a function call.  (If the result
6251     * comes back in a register other than r0, you can override "result".)
6252     *
6253     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6254     * vCC (r1).  Useful for integer division and modulus.
6255     *
6256     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6257     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6258     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6259     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6260     */
6261    /* binop/2addr vA, vB */
6262    mov     r9, rINST, lsr #8           @ r9<- A+
6263    mov     r3, rINST, lsr #12          @ r3<- B
6264    and     r9, r9, #15
6265    GET_VREG(r0, r9)                    @ r0<- vA
6266    GET_VREG(r1, r3)                    @ r1<- vB
6267    .if 0
6268    cmp     r1, #0                      @ is second operand zero?
6269    beq     common_errDivideByZero
6270    .endif
6271    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6272
6273                               @ optional op; may set condition codes
6274    bl      __aeabi_fsub                              @ r0<- op, r0-r3 changed
6275    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6276    SET_VREG(r0, r9)               @ vAA<- r0
6277    GOTO_OPCODE(ip)                     @ jump to next instruction
6278    /* 10-13 instructions */
6279
6280
6281
6282/* ------------------------------ */
6283    .balign 64
6284.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
6285/* File: armv5te/OP_MUL_FLOAT_2ADDR.S */
6286/* File: armv5te/binop2addr.S */
6287    /*
6288     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6289     * that specifies an instruction that performs "result = r0 op r1".
6290     * This could be an ARM instruction or a function call.  (If the result
6291     * comes back in a register other than r0, you can override "result".)
6292     *
6293     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6294     * vCC (r1).  Useful for integer division and modulus.
6295     *
6296     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6297     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6298     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6299     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6300     */
6301    /* binop/2addr vA, vB */
6302    mov     r9, rINST, lsr #8           @ r9<- A+
6303    mov     r3, rINST, lsr #12          @ r3<- B
6304    and     r9, r9, #15
6305    GET_VREG(r0, r9)                    @ r0<- vA
6306    GET_VREG(r1, r3)                    @ r1<- vB
6307    .if 0
6308    cmp     r1, #0                      @ is second operand zero?
6309    beq     common_errDivideByZero
6310    .endif
6311    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6312
6313                               @ optional op; may set condition codes
6314    bl      __aeabi_fmul                              @ r0<- op, r0-r3 changed
6315    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6316    SET_VREG(r0, r9)               @ vAA<- r0
6317    GOTO_OPCODE(ip)                     @ jump to next instruction
6318    /* 10-13 instructions */
6319
6320
6321
6322/* ------------------------------ */
6323    .balign 64
6324.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
6325/* File: armv5te/OP_DIV_FLOAT_2ADDR.S */
6326/* File: armv5te/binop2addr.S */
6327    /*
6328     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6329     * that specifies an instruction that performs "result = r0 op r1".
6330     * This could be an ARM instruction or a function call.  (If the result
6331     * comes back in a register other than r0, you can override "result".)
6332     *
6333     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6334     * vCC (r1).  Useful for integer division and modulus.
6335     *
6336     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6337     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6338     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6339     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6340     */
6341    /* binop/2addr vA, vB */
6342    mov     r9, rINST, lsr #8           @ r9<- A+
6343    mov     r3, rINST, lsr #12          @ r3<- B
6344    and     r9, r9, #15
6345    GET_VREG(r0, r9)                    @ r0<- vA
6346    GET_VREG(r1, r3)                    @ r1<- vB
6347    .if 0
6348    cmp     r1, #0                      @ is second operand zero?
6349    beq     common_errDivideByZero
6350    .endif
6351    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6352
6353                               @ optional op; may set condition codes
6354    bl      __aeabi_fdiv                              @ r0<- op, r0-r3 changed
6355    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6356    SET_VREG(r0, r9)               @ vAA<- r0
6357    GOTO_OPCODE(ip)                     @ jump to next instruction
6358    /* 10-13 instructions */
6359
6360
6361
6362/* ------------------------------ */
6363    .balign 64
6364.L_OP_REM_FLOAT_2ADDR: /* 0xca */
6365/* File: armv5te/OP_REM_FLOAT_2ADDR.S */
6366/* EABI doesn't define a float remainder function, but libm does */
6367/* File: armv5te/binop2addr.S */
6368    /*
6369     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6370     * that specifies an instruction that performs "result = r0 op r1".
6371     * This could be an ARM instruction or a function call.  (If the result
6372     * comes back in a register other than r0, you can override "result".)
6373     *
6374     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6375     * vCC (r1).  Useful for integer division and modulus.
6376     *
6377     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6378     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6379     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6380     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6381     */
6382    /* binop/2addr vA, vB */
6383    mov     r9, rINST, lsr #8           @ r9<- A+
6384    mov     r3, rINST, lsr #12          @ r3<- B
6385    and     r9, r9, #15
6386    GET_VREG(r0, r9)                    @ r0<- vA
6387    GET_VREG(r1, r3)                    @ r1<- vB
6388    .if 0
6389    cmp     r1, #0                      @ is second operand zero?
6390    beq     common_errDivideByZero
6391    .endif
6392    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6393
6394                               @ optional op; may set condition codes
6395    bl      fmodf                              @ r0<- op, r0-r3 changed
6396    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6397    SET_VREG(r0, r9)               @ vAA<- r0
6398    GOTO_OPCODE(ip)                     @ jump to next instruction
6399    /* 10-13 instructions */
6400
6401
6402
6403/* ------------------------------ */
6404    .balign 64
6405.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
6406/* File: armv5te/OP_ADD_DOUBLE_2ADDR.S */
6407/* File: armv5te/binopWide2addr.S */
6408    /*
6409     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6410     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6411     * This could be an ARM instruction or a function call.  (If the result
6412     * comes back in a register other than r0, you can override "result".)
6413     *
6414     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6415     * vCC (r1).  Useful for integer division and modulus.
6416     *
6417     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6418     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6419     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6420     *      rem-double/2addr
6421     */
6422    /* binop/2addr vA, vB */
6423    mov     r9, rINST, lsr #8           @ r9<- A+
6424    mov     r1, rINST, lsr #12          @ r1<- B
6425    and     r9, r9, #15
6426    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6427    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6428    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6429    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6430    .if 0
6431    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6432    beq     common_errDivideByZero
6433    .endif
6434    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6435
6436                               @ optional op; may set condition codes
6437    bl      __aeabi_dadd                              @ result<- op, r0-r3 changed
6438    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6439    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6440    GOTO_OPCODE(ip)                     @ jump to next instruction
6441    /* 12-15 instructions */
6442
6443
6444
6445/* ------------------------------ */
6446    .balign 64
6447.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
6448/* File: armv5te/OP_SUB_DOUBLE_2ADDR.S */
6449/* File: armv5te/binopWide2addr.S */
6450    /*
6451     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6452     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6453     * This could be an ARM instruction or a function call.  (If the result
6454     * comes back in a register other than r0, you can override "result".)
6455     *
6456     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6457     * vCC (r1).  Useful for integer division and modulus.
6458     *
6459     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6460     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6461     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6462     *      rem-double/2addr
6463     */
6464    /* binop/2addr vA, vB */
6465    mov     r9, rINST, lsr #8           @ r9<- A+
6466    mov     r1, rINST, lsr #12          @ r1<- B
6467    and     r9, r9, #15
6468    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6469    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6470    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6471    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6472    .if 0
6473    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6474    beq     common_errDivideByZero
6475    .endif
6476    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6477
6478                               @ optional op; may set condition codes
6479    bl      __aeabi_dsub                              @ result<- op, r0-r3 changed
6480    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6481    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6482    GOTO_OPCODE(ip)                     @ jump to next instruction
6483    /* 12-15 instructions */
6484
6485
6486
6487/* ------------------------------ */
6488    .balign 64
6489.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
6490/* File: armv5te/OP_MUL_DOUBLE_2ADDR.S */
6491/* File: armv5te/binopWide2addr.S */
6492    /*
6493     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6494     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6495     * This could be an ARM instruction or a function call.  (If the result
6496     * comes back in a register other than r0, you can override "result".)
6497     *
6498     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6499     * vCC (r1).  Useful for integer division and modulus.
6500     *
6501     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6502     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6503     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6504     *      rem-double/2addr
6505     */
6506    /* binop/2addr vA, vB */
6507    mov     r9, rINST, lsr #8           @ r9<- A+
6508    mov     r1, rINST, lsr #12          @ r1<- B
6509    and     r9, r9, #15
6510    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6511    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6512    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6513    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6514    .if 0
6515    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6516    beq     common_errDivideByZero
6517    .endif
6518    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6519
6520                               @ optional op; may set condition codes
6521    bl      __aeabi_dmul                              @ result<- op, r0-r3 changed
6522    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6523    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6524    GOTO_OPCODE(ip)                     @ jump to next instruction
6525    /* 12-15 instructions */
6526
6527
6528
6529/* ------------------------------ */
6530    .balign 64
6531.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
6532/* File: armv5te/OP_DIV_DOUBLE_2ADDR.S */
6533/* File: armv5te/binopWide2addr.S */
6534    /*
6535     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6536     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6537     * This could be an ARM instruction or a function call.  (If the result
6538     * comes back in a register other than r0, you can override "result".)
6539     *
6540     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6541     * vCC (r1).  Useful for integer division and modulus.
6542     *
6543     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6544     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6545     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6546     *      rem-double/2addr
6547     */
6548    /* binop/2addr vA, vB */
6549    mov     r9, rINST, lsr #8           @ r9<- A+
6550    mov     r1, rINST, lsr #12          @ r1<- B
6551    and     r9, r9, #15
6552    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6553    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6554    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6555    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6556    .if 0
6557    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6558    beq     common_errDivideByZero
6559    .endif
6560    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6561
6562                               @ optional op; may set condition codes
6563    bl      __aeabi_ddiv                              @ result<- op, r0-r3 changed
6564    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6565    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6566    GOTO_OPCODE(ip)                     @ jump to next instruction
6567    /* 12-15 instructions */
6568
6569
6570
6571/* ------------------------------ */
6572    .balign 64
6573.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
6574/* File: armv5te/OP_REM_DOUBLE_2ADDR.S */
6575/* EABI doesn't define a double remainder function, but libm does */
6576/* File: armv5te/binopWide2addr.S */
6577    /*
6578     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6579     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6580     * This could be an ARM instruction or a function call.  (If the result
6581     * comes back in a register other than r0, you can override "result".)
6582     *
6583     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6584     * vCC (r1).  Useful for integer division and modulus.
6585     *
6586     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6587     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6588     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6589     *      rem-double/2addr
6590     */
6591    /* binop/2addr vA, vB */
6592    mov     r9, rINST, lsr #8           @ r9<- A+
6593    mov     r1, rINST, lsr #12          @ r1<- B
6594    and     r9, r9, #15
6595    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6596    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6597    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6598    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6599    .if 0
6600    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6601    beq     common_errDivideByZero
6602    .endif
6603    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6604
6605                               @ optional op; may set condition codes
6606    bl      fmod                              @ result<- op, r0-r3 changed
6607    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6608    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6609    GOTO_OPCODE(ip)                     @ jump to next instruction
6610    /* 12-15 instructions */
6611
6612
6613
6614/* ------------------------------ */
6615    .balign 64
6616.L_OP_ADD_INT_LIT16: /* 0xd0 */
6617/* File: armv5te/OP_ADD_INT_LIT16.S */
6618/* File: armv5te/binopLit16.S */
6619    /*
6620     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6621     * that specifies an instruction that performs "result = r0 op r1".
6622     * This could be an ARM instruction or a function call.  (If the result
6623     * comes back in a register other than r0, you can override "result".)
6624     *
6625     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6626     * vCC (r1).  Useful for integer division and modulus.
6627     *
6628     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6629     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6630     */
6631    /* binop/lit16 vA, vB, #+CCCC */
6632    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6633    mov     r2, rINST, lsr #12          @ r2<- B
6634    mov     r9, rINST, lsr #8           @ r9<- A+
6635    GET_VREG(r0, r2)                    @ r0<- vB
6636    and     r9, r9, #15
6637    .if 0
6638    cmp     r1, #0                      @ is second operand zero?
6639    beq     common_errDivideByZero
6640    .endif
6641    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6642
6643    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6644    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6645    SET_VREG(r0, r9)               @ vAA<- r0
6646    GOTO_OPCODE(ip)                     @ jump to next instruction
6647    /* 10-13 instructions */
6648
6649
6650
6651/* ------------------------------ */
6652    .balign 64
6653.L_OP_RSUB_INT: /* 0xd1 */
6654/* File: armv5te/OP_RSUB_INT.S */
6655/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
6656/* File: armv5te/binopLit16.S */
6657    /*
6658     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6659     * that specifies an instruction that performs "result = r0 op r1".
6660     * This could be an ARM instruction or a function call.  (If the result
6661     * comes back in a register other than r0, you can override "result".)
6662     *
6663     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6664     * vCC (r1).  Useful for integer division and modulus.
6665     *
6666     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6667     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6668     */
6669    /* binop/lit16 vA, vB, #+CCCC */
6670    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6671    mov     r2, rINST, lsr #12          @ r2<- B
6672    mov     r9, rINST, lsr #8           @ r9<- A+
6673    GET_VREG(r0, r2)                    @ r0<- vB
6674    and     r9, r9, #15
6675    .if 0
6676    cmp     r1, #0                      @ is second operand zero?
6677    beq     common_errDivideByZero
6678    .endif
6679    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6680
6681    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6682    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6683    SET_VREG(r0, r9)               @ vAA<- r0
6684    GOTO_OPCODE(ip)                     @ jump to next instruction
6685    /* 10-13 instructions */
6686
6687
6688
6689/* ------------------------------ */
6690    .balign 64
6691.L_OP_MUL_INT_LIT16: /* 0xd2 */
6692/* File: armv5te/OP_MUL_INT_LIT16.S */
6693/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6694/* File: armv5te/binopLit16.S */
6695    /*
6696     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6697     * that specifies an instruction that performs "result = r0 op r1".
6698     * This could be an ARM instruction or a function call.  (If the result
6699     * comes back in a register other than r0, you can override "result".)
6700     *
6701     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6702     * vCC (r1).  Useful for integer division and modulus.
6703     *
6704     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6705     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6706     */
6707    /* binop/lit16 vA, vB, #+CCCC */
6708    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6709    mov     r2, rINST, lsr #12          @ r2<- B
6710    mov     r9, rINST, lsr #8           @ r9<- A+
6711    GET_VREG(r0, r2)                    @ r0<- vB
6712    and     r9, r9, #15
6713    .if 0
6714    cmp     r1, #0                      @ is second operand zero?
6715    beq     common_errDivideByZero
6716    .endif
6717    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6718
6719    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6720    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6721    SET_VREG(r0, r9)               @ vAA<- r0
6722    GOTO_OPCODE(ip)                     @ jump to next instruction
6723    /* 10-13 instructions */
6724
6725
6726
6727/* ------------------------------ */
6728    .balign 64
6729.L_OP_DIV_INT_LIT16: /* 0xd3 */
6730/* File: armv5te/OP_DIV_INT_LIT16.S */
6731/* File: armv5te/binopLit16.S */
6732    /*
6733     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6734     * that specifies an instruction that performs "result = r0 op r1".
6735     * This could be an ARM instruction or a function call.  (If the result
6736     * comes back in a register other than r0, you can override "result".)
6737     *
6738     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6739     * vCC (r1).  Useful for integer division and modulus.
6740     *
6741     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6742     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6743     */
6744    /* binop/lit16 vA, vB, #+CCCC */
6745    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6746    mov     r2, rINST, lsr #12          @ r2<- B
6747    mov     r9, rINST, lsr #8           @ r9<- A+
6748    GET_VREG(r0, r2)                    @ r0<- vB
6749    and     r9, r9, #15
6750    .if 1
6751    cmp     r1, #0                      @ is second operand zero?
6752    beq     common_errDivideByZero
6753    .endif
6754    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6755
6756    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6757    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6758    SET_VREG(r0, r9)               @ vAA<- r0
6759    GOTO_OPCODE(ip)                     @ jump to next instruction
6760    /* 10-13 instructions */
6761
6762
6763
6764/* ------------------------------ */
6765    .balign 64
6766.L_OP_REM_INT_LIT16: /* 0xd4 */
6767/* File: armv5te/OP_REM_INT_LIT16.S */
6768/* idivmod returns quotient in r0 and remainder in r1 */
6769/* File: armv5te/binopLit16.S */
6770    /*
6771     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6772     * that specifies an instruction that performs "result = r0 op r1".
6773     * This could be an ARM instruction or a function call.  (If the result
6774     * comes back in a register other than r0, you can override "result".)
6775     *
6776     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6777     * vCC (r1).  Useful for integer division and modulus.
6778     *
6779     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6780     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6781     */
6782    /* binop/lit16 vA, vB, #+CCCC */
6783    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6784    mov     r2, rINST, lsr #12          @ r2<- B
6785    mov     r9, rINST, lsr #8           @ r9<- A+
6786    GET_VREG(r0, r2)                    @ r0<- vB
6787    and     r9, r9, #15
6788    .if 1
6789    cmp     r1, #0                      @ is second operand zero?
6790    beq     common_errDivideByZero
6791    .endif
6792    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6793
6794    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6795    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6796    SET_VREG(r1, r9)               @ vAA<- r1
6797    GOTO_OPCODE(ip)                     @ jump to next instruction
6798    /* 10-13 instructions */
6799
6800
6801
6802/* ------------------------------ */
6803    .balign 64
6804.L_OP_AND_INT_LIT16: /* 0xd5 */
6805/* File: armv5te/OP_AND_INT_LIT16.S */
6806/* File: armv5te/binopLit16.S */
6807    /*
6808     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6809     * that specifies an instruction that performs "result = r0 op r1".
6810     * This could be an ARM instruction or a function call.  (If the result
6811     * comes back in a register other than r0, you can override "result".)
6812     *
6813     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6814     * vCC (r1).  Useful for integer division and modulus.
6815     *
6816     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6817     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6818     */
6819    /* binop/lit16 vA, vB, #+CCCC */
6820    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6821    mov     r2, rINST, lsr #12          @ r2<- B
6822    mov     r9, rINST, lsr #8           @ r9<- A+
6823    GET_VREG(r0, r2)                    @ r0<- vB
6824    and     r9, r9, #15
6825    .if 0
6826    cmp     r1, #0                      @ is second operand zero?
6827    beq     common_errDivideByZero
6828    .endif
6829    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6830
6831    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6832    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6833    SET_VREG(r0, r9)               @ vAA<- r0
6834    GOTO_OPCODE(ip)                     @ jump to next instruction
6835    /* 10-13 instructions */
6836
6837
6838
6839/* ------------------------------ */
6840    .balign 64
6841.L_OP_OR_INT_LIT16: /* 0xd6 */
6842/* File: armv5te/OP_OR_INT_LIT16.S */
6843/* File: armv5te/binopLit16.S */
6844    /*
6845     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6846     * that specifies an instruction that performs "result = r0 op r1".
6847     * This could be an ARM instruction or a function call.  (If the result
6848     * comes back in a register other than r0, you can override "result".)
6849     *
6850     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6851     * vCC (r1).  Useful for integer division and modulus.
6852     *
6853     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6854     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6855     */
6856    /* binop/lit16 vA, vB, #+CCCC */
6857    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6858    mov     r2, rINST, lsr #12          @ r2<- B
6859    mov     r9, rINST, lsr #8           @ r9<- A+
6860    GET_VREG(r0, r2)                    @ r0<- vB
6861    and     r9, r9, #15
6862    .if 0
6863    cmp     r1, #0                      @ is second operand zero?
6864    beq     common_errDivideByZero
6865    .endif
6866    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6867
6868    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6869    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6870    SET_VREG(r0, r9)               @ vAA<- r0
6871    GOTO_OPCODE(ip)                     @ jump to next instruction
6872    /* 10-13 instructions */
6873
6874
6875
6876/* ------------------------------ */
6877    .balign 64
6878.L_OP_XOR_INT_LIT16: /* 0xd7 */
6879/* File: armv5te/OP_XOR_INT_LIT16.S */
6880/* File: armv5te/binopLit16.S */
6881    /*
6882     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6883     * that specifies an instruction that performs "result = r0 op r1".
6884     * This could be an ARM instruction or a function call.  (If the result
6885     * comes back in a register other than r0, you can override "result".)
6886     *
6887     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6888     * vCC (r1).  Useful for integer division and modulus.
6889     *
6890     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6891     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6892     */
6893    /* binop/lit16 vA, vB, #+CCCC */
6894    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6895    mov     r2, rINST, lsr #12          @ r2<- B
6896    mov     r9, rINST, lsr #8           @ r9<- A+
6897    GET_VREG(r0, r2)                    @ r0<- vB
6898    and     r9, r9, #15
6899    .if 0
6900    cmp     r1, #0                      @ is second operand zero?
6901    beq     common_errDivideByZero
6902    .endif
6903    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6904
6905    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
6906    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6907    SET_VREG(r0, r9)               @ vAA<- r0
6908    GOTO_OPCODE(ip)                     @ jump to next instruction
6909    /* 10-13 instructions */
6910
6911
6912
6913/* ------------------------------ */
6914    .balign 64
6915.L_OP_ADD_INT_LIT8: /* 0xd8 */
6916/* File: armv5te/OP_ADD_INT_LIT8.S */
6917/* File: armv5te/binopLit8.S */
6918    /*
6919     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6920     * that specifies an instruction that performs "result = r0 op r1".
6921     * This could be an ARM instruction or a function call.  (If the result
6922     * comes back in a register other than r0, you can override "result".)
6923     *
6924     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6925     * vCC (r1).  Useful for integer division and modulus.
6926     *
6927     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6928     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6929     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6930     */
6931    /* binop/lit8 vAA, vBB, #+CC */
6932    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6933    mov     r9, rINST, lsr #8           @ r9<- AA
6934    and     r2, r3, #255                @ r2<- BB
6935    GET_VREG(r0, r2)                    @ r0<- vBB
6936    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6937    .if 0
6938    @cmp     r1, #0                      @ is second operand zero?
6939    beq     common_errDivideByZero
6940    .endif
6941    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6942
6943                               @ optional op; may set condition codes
6944    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6945    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6946    SET_VREG(r0, r9)               @ vAA<- r0
6947    GOTO_OPCODE(ip)                     @ jump to next instruction
6948    /* 10-12 instructions */
6949
6950
6951
6952/* ------------------------------ */
6953    .balign 64
6954.L_OP_RSUB_INT_LIT8: /* 0xd9 */
6955/* File: armv5te/OP_RSUB_INT_LIT8.S */
6956/* File: armv5te/binopLit8.S */
6957    /*
6958     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6959     * that specifies an instruction that performs "result = r0 op r1".
6960     * This could be an ARM instruction or a function call.  (If the result
6961     * comes back in a register other than r0, you can override "result".)
6962     *
6963     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6964     * vCC (r1).  Useful for integer division and modulus.
6965     *
6966     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6967     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6968     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6969     */
6970    /* binop/lit8 vAA, vBB, #+CC */
6971    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6972    mov     r9, rINST, lsr #8           @ r9<- AA
6973    and     r2, r3, #255                @ r2<- BB
6974    GET_VREG(r0, r2)                    @ r0<- vBB
6975    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6976    .if 0
6977    @cmp     r1, #0                      @ is second operand zero?
6978    beq     common_errDivideByZero
6979    .endif
6980    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6981
6982                               @ optional op; may set condition codes
6983    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6984    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6985    SET_VREG(r0, r9)               @ vAA<- r0
6986    GOTO_OPCODE(ip)                     @ jump to next instruction
6987    /* 10-12 instructions */
6988
6989
6990
6991/* ------------------------------ */
6992    .balign 64
6993.L_OP_MUL_INT_LIT8: /* 0xda */
6994/* File: armv5te/OP_MUL_INT_LIT8.S */
6995/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6996/* File: armv5te/binopLit8.S */
6997    /*
6998     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6999     * that specifies an instruction that performs "result = r0 op r1".
7000     * This could be an ARM instruction or a function call.  (If the result
7001     * comes back in a register other than r0, you can override "result".)
7002     *
7003     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7004     * vCC (r1).  Useful for integer division and modulus.
7005     *
7006     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7007     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7008     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7009     */
7010    /* binop/lit8 vAA, vBB, #+CC */
7011    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7012    mov     r9, rINST, lsr #8           @ r9<- AA
7013    and     r2, r3, #255                @ r2<- BB
7014    GET_VREG(r0, r2)                    @ r0<- vBB
7015    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7016    .if 0
7017    @cmp     r1, #0                      @ is second operand zero?
7018    beq     common_errDivideByZero
7019    .endif
7020    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7021
7022                               @ optional op; may set condition codes
7023    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
7024    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7025    SET_VREG(r0, r9)               @ vAA<- r0
7026    GOTO_OPCODE(ip)                     @ jump to next instruction
7027    /* 10-12 instructions */
7028
7029
7030
7031/* ------------------------------ */
7032    .balign 64
7033.L_OP_DIV_INT_LIT8: /* 0xdb */
7034/* File: armv5te/OP_DIV_INT_LIT8.S */
7035/* File: armv5te/binopLit8.S */
7036    /*
7037     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7038     * that specifies an instruction that performs "result = r0 op r1".
7039     * This could be an ARM instruction or a function call.  (If the result
7040     * comes back in a register other than r0, you can override "result".)
7041     *
7042     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7043     * vCC (r1).  Useful for integer division and modulus.
7044     *
7045     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7046     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7047     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7048     */
7049    /* binop/lit8 vAA, vBB, #+CC */
7050    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7051    mov     r9, rINST, lsr #8           @ r9<- AA
7052    and     r2, r3, #255                @ r2<- BB
7053    GET_VREG(r0, r2)                    @ r0<- vBB
7054    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7055    .if 1
7056    @cmp     r1, #0                      @ is second operand zero?
7057    beq     common_errDivideByZero
7058    .endif
7059    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7060
7061                               @ optional op; may set condition codes
7062    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
7063    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7064    SET_VREG(r0, r9)               @ vAA<- r0
7065    GOTO_OPCODE(ip)                     @ jump to next instruction
7066    /* 10-12 instructions */
7067
7068
7069
7070/* ------------------------------ */
7071    .balign 64
7072.L_OP_REM_INT_LIT8: /* 0xdc */
7073/* File: armv5te/OP_REM_INT_LIT8.S */
7074/* idivmod returns quotient in r0 and remainder in r1 */
7075/* File: armv5te/binopLit8.S */
7076    /*
7077     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7078     * that specifies an instruction that performs "result = r0 op r1".
7079     * This could be an ARM instruction or a function call.  (If the result
7080     * comes back in a register other than r0, you can override "result".)
7081     *
7082     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7083     * vCC (r1).  Useful for integer division and modulus.
7084     *
7085     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7086     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7087     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7088     */
7089    /* binop/lit8 vAA, vBB, #+CC */
7090    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7091    mov     r9, rINST, lsr #8           @ r9<- AA
7092    and     r2, r3, #255                @ r2<- BB
7093    GET_VREG(r0, r2)                    @ r0<- vBB
7094    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7095    .if 1
7096    @cmp     r1, #0                      @ is second operand zero?
7097    beq     common_errDivideByZero
7098    .endif
7099    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7100
7101                               @ optional op; may set condition codes
7102    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
7103    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7104    SET_VREG(r1, r9)               @ vAA<- r1
7105    GOTO_OPCODE(ip)                     @ jump to next instruction
7106    /* 10-12 instructions */
7107
7108
7109
7110/* ------------------------------ */
7111    .balign 64
7112.L_OP_AND_INT_LIT8: /* 0xdd */
7113/* File: armv5te/OP_AND_INT_LIT8.S */
7114/* File: armv5te/binopLit8.S */
7115    /*
7116     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7117     * that specifies an instruction that performs "result = r0 op r1".
7118     * This could be an ARM instruction or a function call.  (If the result
7119     * comes back in a register other than r0, you can override "result".)
7120     *
7121     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7122     * vCC (r1).  Useful for integer division and modulus.
7123     *
7124     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7125     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7126     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7127     */
7128    /* binop/lit8 vAA, vBB, #+CC */
7129    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7130    mov     r9, rINST, lsr #8           @ r9<- AA
7131    and     r2, r3, #255                @ r2<- BB
7132    GET_VREG(r0, r2)                    @ r0<- vBB
7133    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7134    .if 0
7135    @cmp     r1, #0                      @ is second operand zero?
7136    beq     common_errDivideByZero
7137    .endif
7138    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7139
7140                               @ optional op; may set condition codes
7141    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
7142    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7143    SET_VREG(r0, r9)               @ vAA<- r0
7144    GOTO_OPCODE(ip)                     @ jump to next instruction
7145    /* 10-12 instructions */
7146
7147
7148
7149/* ------------------------------ */
7150    .balign 64
7151.L_OP_OR_INT_LIT8: /* 0xde */
7152/* File: armv5te/OP_OR_INT_LIT8.S */
7153/* File: armv5te/binopLit8.S */
7154    /*
7155     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7156     * that specifies an instruction that performs "result = r0 op r1".
7157     * This could be an ARM instruction or a function call.  (If the result
7158     * comes back in a register other than r0, you can override "result".)
7159     *
7160     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7161     * vCC (r1).  Useful for integer division and modulus.
7162     *
7163     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7164     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7165     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7166     */
7167    /* binop/lit8 vAA, vBB, #+CC */
7168    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7169    mov     r9, rINST, lsr #8           @ r9<- AA
7170    and     r2, r3, #255                @ r2<- BB
7171    GET_VREG(r0, r2)                    @ r0<- vBB
7172    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7173    .if 0
7174    @cmp     r1, #0                      @ is second operand zero?
7175    beq     common_errDivideByZero
7176    .endif
7177    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7178
7179                               @ optional op; may set condition codes
7180    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
7181    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7182    SET_VREG(r0, r9)               @ vAA<- r0
7183    GOTO_OPCODE(ip)                     @ jump to next instruction
7184    /* 10-12 instructions */
7185
7186
7187
7188/* ------------------------------ */
7189    .balign 64
7190.L_OP_XOR_INT_LIT8: /* 0xdf */
7191/* File: armv5te/OP_XOR_INT_LIT8.S */
7192/* File: armv5te/binopLit8.S */
7193    /*
7194     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7195     * that specifies an instruction that performs "result = r0 op r1".
7196     * This could be an ARM instruction or a function call.  (If the result
7197     * comes back in a register other than r0, you can override "result".)
7198     *
7199     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7200     * vCC (r1).  Useful for integer division and modulus.
7201     *
7202     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7203     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7204     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7205     */
7206    /* binop/lit8 vAA, vBB, #+CC */
7207    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7208    mov     r9, rINST, lsr #8           @ r9<- AA
7209    and     r2, r3, #255                @ r2<- BB
7210    GET_VREG(r0, r2)                    @ r0<- vBB
7211    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7212    .if 0
7213    @cmp     r1, #0                      @ is second operand zero?
7214    beq     common_errDivideByZero
7215    .endif
7216    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7217
7218                               @ optional op; may set condition codes
7219    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
7220    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7221    SET_VREG(r0, r9)               @ vAA<- r0
7222    GOTO_OPCODE(ip)                     @ jump to next instruction
7223    /* 10-12 instructions */
7224
7225
7226
7227/* ------------------------------ */
7228    .balign 64
7229.L_OP_SHL_INT_LIT8: /* 0xe0 */
7230/* File: armv5te/OP_SHL_INT_LIT8.S */
7231/* File: armv5te/binopLit8.S */
7232    /*
7233     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7234     * that specifies an instruction that performs "result = r0 op r1".
7235     * This could be an ARM instruction or a function call.  (If the result
7236     * comes back in a register other than r0, you can override "result".)
7237     *
7238     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7239     * vCC (r1).  Useful for integer division and modulus.
7240     *
7241     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7242     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7243     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7244     */
7245    /* binop/lit8 vAA, vBB, #+CC */
7246    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7247    mov     r9, rINST, lsr #8           @ r9<- AA
7248    and     r2, r3, #255                @ r2<- BB
7249    GET_VREG(r0, r2)                    @ r0<- vBB
7250    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7251    .if 0
7252    @cmp     r1, #0                      @ is second operand zero?
7253    beq     common_errDivideByZero
7254    .endif
7255    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7256
7257    and     r1, r1, #31                           @ optional op; may set condition codes
7258    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
7259    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7260    SET_VREG(r0, r9)               @ vAA<- r0
7261    GOTO_OPCODE(ip)                     @ jump to next instruction
7262    /* 10-12 instructions */
7263
7264
7265
7266/* ------------------------------ */
7267    .balign 64
7268.L_OP_SHR_INT_LIT8: /* 0xe1 */
7269/* File: armv5te/OP_SHR_INT_LIT8.S */
7270/* File: armv5te/binopLit8.S */
7271    /*
7272     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7273     * that specifies an instruction that performs "result = r0 op r1".
7274     * This could be an ARM instruction or a function call.  (If the result
7275     * comes back in a register other than r0, you can override "result".)
7276     *
7277     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7278     * vCC (r1).  Useful for integer division and modulus.
7279     *
7280     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7281     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7282     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7283     */
7284    /* binop/lit8 vAA, vBB, #+CC */
7285    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7286    mov     r9, rINST, lsr #8           @ r9<- AA
7287    and     r2, r3, #255                @ r2<- BB
7288    GET_VREG(r0, r2)                    @ r0<- vBB
7289    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7290    .if 0
7291    @cmp     r1, #0                      @ is second operand zero?
7292    beq     common_errDivideByZero
7293    .endif
7294    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7295
7296    and     r1, r1, #31                           @ optional op; may set condition codes
7297    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
7298    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7299    SET_VREG(r0, r9)               @ vAA<- r0
7300    GOTO_OPCODE(ip)                     @ jump to next instruction
7301    /* 10-12 instructions */
7302
7303
7304
7305/* ------------------------------ */
7306    .balign 64
7307.L_OP_USHR_INT_LIT8: /* 0xe2 */
7308/* File: armv5te/OP_USHR_INT_LIT8.S */
7309/* File: armv5te/binopLit8.S */
7310    /*
7311     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7312     * that specifies an instruction that performs "result = r0 op r1".
7313     * This could be an ARM instruction or a function call.  (If the result
7314     * comes back in a register other than r0, you can override "result".)
7315     *
7316     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7317     * vCC (r1).  Useful for integer division and modulus.
7318     *
7319     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7320     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7321     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7322     */
7323    /* binop/lit8 vAA, vBB, #+CC */
7324    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7325    mov     r9, rINST, lsr #8           @ r9<- AA
7326    and     r2, r3, #255                @ r2<- BB
7327    GET_VREG(r0, r2)                    @ r0<- vBB
7328    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7329    .if 0
7330    @cmp     r1, #0                      @ is second operand zero?
7331    beq     common_errDivideByZero
7332    .endif
7333    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7334
7335    and     r1, r1, #31                           @ optional op; may set condition codes
7336    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
7337    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7338    SET_VREG(r0, r9)               @ vAA<- r0
7339    GOTO_OPCODE(ip)                     @ jump to next instruction
7340    /* 10-12 instructions */
7341
7342
7343
7344/* ------------------------------ */
7345    .balign 64
7346.L_OP_UNUSED_E3: /* 0xe3 */
7347/* File: armv5te/OP_UNUSED_E3.S */
7348/* File: armv5te/unused.S */
7349    bl      common_abort
7350
7351
7352
7353/* ------------------------------ */
7354    .balign 64
7355.L_OP_UNUSED_E4: /* 0xe4 */
7356/* File: armv5te/OP_UNUSED_E4.S */
7357/* File: armv5te/unused.S */
7358    bl      common_abort
7359
7360
7361
7362/* ------------------------------ */
7363    .balign 64
7364.L_OP_UNUSED_E5: /* 0xe5 */
7365/* File: armv5te/OP_UNUSED_E5.S */
7366/* File: armv5te/unused.S */
7367    bl      common_abort
7368
7369
7370
7371/* ------------------------------ */
7372    .balign 64
7373.L_OP_UNUSED_E6: /* 0xe6 */
7374/* File: armv5te/OP_UNUSED_E6.S */
7375/* File: armv5te/unused.S */
7376    bl      common_abort
7377
7378
7379
7380/* ------------------------------ */
7381    .balign 64
7382.L_OP_UNUSED_E7: /* 0xe7 */
7383/* File: armv5te/OP_UNUSED_E7.S */
7384/* File: armv5te/unused.S */
7385    bl      common_abort
7386
7387
7388
7389/* ------------------------------ */
7390    .balign 64
7391.L_OP_UNUSED_E8: /* 0xe8 */
7392/* File: armv5te/OP_UNUSED_E8.S */
7393/* File: armv5te/unused.S */
7394    bl      common_abort
7395
7396
7397
7398/* ------------------------------ */
7399    .balign 64
7400.L_OP_UNUSED_E9: /* 0xe9 */
7401/* File: armv5te/OP_UNUSED_E9.S */
7402/* File: armv5te/unused.S */
7403    bl      common_abort
7404
7405
7406
7407/* ------------------------------ */
7408    .balign 64
7409.L_OP_UNUSED_EA: /* 0xea */
7410/* File: armv5te/OP_UNUSED_EA.S */
7411/* File: armv5te/unused.S */
7412    bl      common_abort
7413
7414
7415
7416/* ------------------------------ */
7417    .balign 64
7418.L_OP_UNUSED_EB: /* 0xeb */
7419/* File: armv5te/OP_UNUSED_EB.S */
7420/* File: armv5te/unused.S */
7421    bl      common_abort
7422
7423
7424
7425/* ------------------------------ */
7426    .balign 64
7427.L_OP_UNUSED_EC: /* 0xec */
7428/* File: armv5te/OP_UNUSED_EC.S */
7429/* File: armv5te/unused.S */
7430    bl      common_abort
7431
7432
7433
7434/* ------------------------------ */
7435    .balign 64
7436.L_OP_UNUSED_ED: /* 0xed */
7437/* File: armv5te/OP_UNUSED_ED.S */
7438/* File: armv5te/unused.S */
7439    bl      common_abort
7440
7441
7442
7443/* ------------------------------ */
7444    .balign 64
7445.L_OP_EXECUTE_INLINE: /* 0xee */
7446/* File: armv5te/OP_EXECUTE_INLINE.S */
7447    /*
7448     * Execute a "native inline" instruction.
7449     *
7450     * We need to call:
7451     *  dvmPerformInlineOp4Std(arg0, arg1, arg2, arg3, &retval, ref)
7452     *
7453     * The first four args are in r0-r3, but the last two must be pushed
7454     * onto the stack.
7455     */
7456    /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
7457    FETCH(r10, 1)                       @ r10<- BBBB
7458    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7459    EXPORT_PC()                         @ can throw
7460    sub     sp, sp, #8                  @ make room for arg(s)
7461    mov     r0, rINST, lsr #12          @ r0<- B
7462    str     r1, [sp]                    @ push &glue->retval
7463    bl      .LOP_EXECUTE_INLINE_continue        @ make call; will return after
7464    add     sp, sp, #8                  @ pop stack
7465    cmp     r0, #0                      @ test boolean result of inline
7466    beq     common_exceptionThrown      @ returned false, handle exception
7467    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7468    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7469    GOTO_OPCODE(ip)                     @ jump to next instruction
7470
7471/* ------------------------------ */
7472    .balign 64
7473.L_OP_UNUSED_EF: /* 0xef */
7474/* File: armv5te/OP_UNUSED_EF.S */
7475/* File: armv5te/unused.S */
7476    bl      common_abort
7477
7478
7479
7480/* ------------------------------ */
7481    .balign 64
7482.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
7483/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
7484    /*
7485     * invoke-direct-empty is a no-op in a "standard" interpreter.
7486     */
7487    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7488    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7489    GOTO_OPCODE(ip)                     @ execute it
7490
7491/* ------------------------------ */
7492    .balign 64
7493.L_OP_UNUSED_F1: /* 0xf1 */
7494/* File: armv5te/OP_UNUSED_F1.S */
7495/* File: armv5te/unused.S */
7496    bl      common_abort
7497
7498
7499
7500/* ------------------------------ */
7501    .balign 64
7502.L_OP_IGET_QUICK: /* 0xf2 */
7503/* File: armv5te/OP_IGET_QUICK.S */
7504    /* For: iget-quick, iget-object-quick */
7505    /* op vA, vB, offset@CCCC */
7506    mov     r2, rINST, lsr #12          @ r2<- B
7507    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7508    FETCH(r1, 1)                        @ r1<- field byte offset
7509    cmp     r3, #0                      @ check object for null
7510    mov     r2, rINST, lsr #8           @ r2<- A(+)
7511    beq     common_errNullObject        @ object was null
7512    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7513    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7514    and     r2, r2, #15
7515    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7516    SET_VREG(r0, r2)                    @ fp[A]<- r0
7517    GOTO_OPCODE(ip)                     @ jump to next instruction
7518
7519
7520/* ------------------------------ */
7521    .balign 64
7522.L_OP_IGET_WIDE_QUICK: /* 0xf3 */
7523/* File: armv5te/OP_IGET_WIDE_QUICK.S */
7524    /* iget-wide-quick vA, vB, offset@CCCC */
7525    mov     r2, rINST, lsr #12          @ r2<- B
7526    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7527    FETCH(r1, 1)                        @ r1<- field byte offset
7528    cmp     r3, #0                      @ check object for null
7529    mov     r2, rINST, lsr #8           @ r2<- A(+)
7530    beq     common_errNullObject        @ object was null
7531    ldrd    r0, [r3, r1]                @ r0<- obj.field (64 bits, aligned)
7532    and     r2, r2, #15
7533    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7534    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
7535    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7536    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
7537    GOTO_OPCODE(ip)                     @ jump to next instruction
7538
7539
7540/* ------------------------------ */
7541    .balign 64
7542.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
7543/* File: armv5te/OP_IGET_OBJECT_QUICK.S */
7544/* File: armv5te/OP_IGET_QUICK.S */
7545    /* For: iget-quick, iget-object-quick */
7546    /* op vA, vB, offset@CCCC */
7547    mov     r2, rINST, lsr #12          @ r2<- B
7548    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7549    FETCH(r1, 1)                        @ r1<- field byte offset
7550    cmp     r3, #0                      @ check object for null
7551    mov     r2, rINST, lsr #8           @ r2<- A(+)
7552    beq     common_errNullObject        @ object was null
7553    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7554    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7555    and     r2, r2, #15
7556    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7557    SET_VREG(r0, r2)                    @ fp[A]<- r0
7558    GOTO_OPCODE(ip)                     @ jump to next instruction
7559
7560
7561
7562/* ------------------------------ */
7563    .balign 64
7564.L_OP_IPUT_QUICK: /* 0xf5 */
7565/* File: armv5te/OP_IPUT_QUICK.S */
7566    /* For: iput-quick, iput-object-quick */
7567    /* op vA, vB, offset@CCCC */
7568    mov     r2, rINST, lsr #12          @ r2<- B
7569    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7570    FETCH(r1, 1)                        @ r1<- field byte offset
7571    cmp     r3, #0                      @ check object for null
7572    mov     r2, rINST, lsr #8           @ r2<- A(+)
7573    beq     common_errNullObject        @ object was null
7574    and     r2, r2, #15
7575    GET_VREG(r0, r2)                    @ r0<- fp[A]
7576    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7577    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7578    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7579    GOTO_OPCODE(ip)                     @ jump to next instruction
7580
7581
7582/* ------------------------------ */
7583    .balign 64
7584.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
7585/* File: armv5te/OP_IPUT_WIDE_QUICK.S */
7586    /* iput-wide-quick vA, vB, offset@CCCC */
7587    mov     r0, rINST, lsr #8           @ r0<- A(+)
7588    mov     r1, rINST, lsr #12          @ r1<- B
7589    and     r0, r0, #15
7590    GET_VREG(r2, r1)                    @ r2<- fp[B], the object pointer
7591    add     r3, rFP, r0, lsl #2         @ r3<- &fp[A]
7592    cmp     r2, #0                      @ check object for null
7593    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[A]
7594    beq     common_errNullObject        @ object was null
7595    FETCH(r3, 1)                        @ r3<- field byte offset
7596    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7597    strd    r0, [r2, r3]                @ obj.field (64 bits, aligned)<- r0/r1
7598    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7599    GOTO_OPCODE(ip)                     @ jump to next instruction
7600
7601
7602/* ------------------------------ */
7603    .balign 64
7604.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
7605/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
7606/* File: armv5te/OP_IPUT_QUICK.S */
7607    /* For: iput-quick, iput-object-quick */
7608    /* op vA, vB, offset@CCCC */
7609    mov     r2, rINST, lsr #12          @ r2<- B
7610    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7611    FETCH(r1, 1)                        @ r1<- field byte offset
7612    cmp     r3, #0                      @ check object for null
7613    mov     r2, rINST, lsr #8           @ r2<- A(+)
7614    beq     common_errNullObject        @ object was null
7615    and     r2, r2, #15
7616    GET_VREG(r0, r2)                    @ r0<- fp[A]
7617    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7618    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7619    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7620    GOTO_OPCODE(ip)                     @ jump to next instruction
7621
7622
7623
7624/* ------------------------------ */
7625    .balign 64
7626.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
7627/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7628    /*
7629     * Handle an optimized virtual method call.
7630     *
7631     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7632     */
7633    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7634    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7635    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7636    FETCH(r1, 1)                        @ r1<- BBBB
7637    .if     (!0)
7638    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7639    .endif
7640    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7641    cmp     r2, #0                      @ is "this" null?
7642    beq     common_errNullObject        @ null "this", throw exception
7643    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7644    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7645    EXPORT_PC()                         @ invoke must export
7646    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7647    bl      common_invokeMethodNoRange @ continue on
7648
7649/* ------------------------------ */
7650    .balign 64
7651.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
7652/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
7653/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7654    /*
7655     * Handle an optimized virtual method call.
7656     *
7657     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7658     */
7659    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7660    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7661    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7662    FETCH(r1, 1)                        @ r1<- BBBB
7663    .if     (!1)
7664    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7665    .endif
7666    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7667    cmp     r2, #0                      @ is "this" null?
7668    beq     common_errNullObject        @ null "this", throw exception
7669    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7670    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7671    EXPORT_PC()                         @ invoke must export
7672    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7673    bl      common_invokeMethodRange @ continue on
7674
7675
7676/* ------------------------------ */
7677    .balign 64
7678.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
7679/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7680    /*
7681     * Handle an optimized "super" method call.
7682     *
7683     * for: [opt] invoke-super-quick, invoke-super-quick/range
7684     */
7685    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7686    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7687    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7688    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7689    .if     (!0)
7690    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7691    .endif
7692    FETCH(r1, 1)                        @ r1<- BBBB
7693    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7694    EXPORT_PC()                         @ must export for invoke
7695    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7696    GET_VREG(r3, r10)                   @ r3<- "this"
7697    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7698    cmp     r3, #0                      @ null "this" ref?
7699    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7700    beq     common_errNullObject        @ "this" is null, throw exception
7701    bl      common_invokeMethodNoRange @ continue on
7702
7703
7704/* ------------------------------ */
7705    .balign 64
7706.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
7707/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
7708/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7709    /*
7710     * Handle an optimized "super" method call.
7711     *
7712     * for: [opt] invoke-super-quick, invoke-super-quick/range
7713     */
7714    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7715    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7716    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7717    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7718    .if     (!1)
7719    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7720    .endif
7721    FETCH(r1, 1)                        @ r1<- BBBB
7722    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7723    EXPORT_PC()                         @ must export for invoke
7724    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7725    GET_VREG(r3, r10)                   @ r3<- "this"
7726    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7727    cmp     r3, #0                      @ null "this" ref?
7728    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7729    beq     common_errNullObject        @ "this" is null, throw exception
7730    bl      common_invokeMethodRange @ continue on
7731
7732
7733
7734/* ------------------------------ */
7735    .balign 64
7736.L_OP_UNUSED_FC: /* 0xfc */
7737/* File: armv5te/OP_UNUSED_FC.S */
7738/* File: armv5te/unused.S */
7739    bl      common_abort
7740
7741
7742
7743/* ------------------------------ */
7744    .balign 64
7745.L_OP_UNUSED_FD: /* 0xfd */
7746/* File: armv5te/OP_UNUSED_FD.S */
7747/* File: armv5te/unused.S */
7748    bl      common_abort
7749
7750
7751
7752/* ------------------------------ */
7753    .balign 64
7754.L_OP_UNUSED_FE: /* 0xfe */
7755/* File: armv5te/OP_UNUSED_FE.S */
7756/* File: armv5te/unused.S */
7757    bl      common_abort
7758
7759
7760
7761/* ------------------------------ */
7762    .balign 64
7763.L_OP_UNUSED_FF: /* 0xff */
7764/* File: armv5te/OP_UNUSED_FF.S */
7765/* File: armv5te/unused.S */
7766    bl      common_abort
7767
7768
7769
7770
7771    .balign 64
7772    .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
7773    .global dvmAsmInstructionEnd
7774dvmAsmInstructionEnd:
7775
7776/*
7777 * ===========================================================================
7778 *  Sister implementations
7779 * ===========================================================================
7780 */
7781    .global dvmAsmSisterStart
7782    .type   dvmAsmSisterStart, %function
7783    .text
7784    .balign 4
7785dvmAsmSisterStart:
7786
7787/* continuation for OP_CONST_STRING */
7788
7789    /*
7790     * Continuation if the String has not yet been resolved.
7791     *  r1: BBBB (String ref)
7792     *  r9: target register
7793     */
7794.LOP_CONST_STRING_resolve:
7795    EXPORT_PC()
7796    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7797    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7798    bl      dvmResolveString            @ r0<- String reference
7799    cmp     r0, #0                      @ failed?
7800    beq     common_exceptionThrown      @ yup, handle the exception
7801    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7802    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7803    SET_VREG(r0, r9)                    @ vAA<- r0
7804    GOTO_OPCODE(ip)                     @ jump to next instruction
7805
7806
7807/* continuation for OP_CONST_STRING_JUMBO */
7808
7809    /*
7810     * Continuation if the String has not yet been resolved.
7811     *  r1: BBBBBBBB (String ref)
7812     *  r9: target register
7813     */
7814.LOP_CONST_STRING_JUMBO_resolve:
7815    EXPORT_PC()
7816    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7817    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7818    bl      dvmResolveString            @ r0<- String reference
7819    cmp     r0, #0                      @ failed?
7820    beq     common_exceptionThrown      @ yup, handle the exception
7821    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7822    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7823    SET_VREG(r0, r9)                    @ vAA<- r0
7824    GOTO_OPCODE(ip)                     @ jump to next instruction
7825
7826
7827/* continuation for OP_CONST_CLASS */
7828
7829    /*
7830     * Continuation if the Class has not yet been resolved.
7831     *  r1: BBBB (Class ref)
7832     *  r9: target register
7833     */
7834.LOP_CONST_CLASS_resolve:
7835    EXPORT_PC()
7836    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7837    mov     r2, #1                      @ r2<- true
7838    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7839    bl      dvmResolveClass             @ r0<- Class reference
7840    cmp     r0, #0                      @ failed?
7841    beq     common_exceptionThrown      @ yup, handle the exception
7842    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7843    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7844    SET_VREG(r0, r9)                    @ vAA<- r0
7845    GOTO_OPCODE(ip)                     @ jump to next instruction
7846
7847
7848/* continuation for OP_CHECK_CAST */
7849
7850    /*
7851     * Trivial test failed, need to perform full check.  This is common.
7852     *  r0 holds obj->clazz
7853     *  r1 holds class resolved from BBBB
7854     *  r9 holds object
7855     */
7856.LOP_CHECK_CAST_fullcheck:
7857    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7858    cmp     r0, #0                      @ failed?
7859    bne     .LOP_CHECK_CAST_okay            @ no, success
7860
7861    @ A cast has failed.  We need to throw a ClassCastException with the
7862    @ class of the object that failed to be cast.
7863    EXPORT_PC()                         @ about to throw
7864    ldr     r3, [r9, #offObject_clazz]  @ r3<- obj->clazz
7865    ldr     r0, .LstrClassCastExceptionPtr
7866    ldr     r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor
7867    bl      dvmThrowExceptionWithClassMessage
7868    b       common_exceptionThrown
7869
7870    /*
7871     * Resolution required.  This is the least-likely path.
7872     *
7873     *  r2 holds BBBB
7874     *  r9 holds object
7875     */
7876.LOP_CHECK_CAST_resolve:
7877    EXPORT_PC()                         @ resolve() could throw
7878    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7879    mov     r1, r2                      @ r1<- BBBB
7880    mov     r2, #0                      @ r2<- false
7881    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7882    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7883    cmp     r0, #0                      @ got null?
7884    beq     common_exceptionThrown      @ yes, handle exception
7885    mov     r1, r0                      @ r1<- class resolved from BBB
7886    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
7887    b       .LOP_CHECK_CAST_resolved        @ pick up where we left off
7888
7889.LstrClassCastExceptionPtr:
7890    .word   .LstrClassCastException
7891
7892
7893/* continuation for OP_INSTANCE_OF */
7894
7895    /*
7896     * Trivial test failed, need to perform full check.  This is common.
7897     *  r0 holds obj->clazz
7898     *  r1 holds class resolved from BBBB
7899     *  r9 holds A
7900     */
7901.LOP_INSTANCE_OF_fullcheck:
7902    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7903    @ fall through to OP_INSTANCE_OF_store
7904
7905    /*
7906     * r0 holds boolean result
7907     * r9 holds A
7908     */
7909.LOP_INSTANCE_OF_store:
7910    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7911    SET_VREG(r0, r9)                    @ vA<- r0
7912    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7913    GOTO_OPCODE(ip)                     @ jump to next instruction
7914
7915    /*
7916     * Trivial test succeeded, save and bail.
7917     *  r9 holds A
7918     */
7919.LOP_INSTANCE_OF_trivial:
7920    mov     r0, #1                      @ indicate success
7921    @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
7922    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7923    SET_VREG(r0, r9)                    @ vA<- r0
7924    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7925    GOTO_OPCODE(ip)                     @ jump to next instruction
7926
7927    /*
7928     * Resolution required.  This is the least-likely path.
7929     *
7930     *  r3 holds BBBB
7931     *  r9 holds A
7932     */
7933.LOP_INSTANCE_OF_resolve:
7934    EXPORT_PC()                         @ resolve() could throw
7935    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7936    mov     r1, r3                      @ r1<- BBBB
7937    mov     r2, #1                      @ r2<- true
7938    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7939    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7940    cmp     r0, #0                      @ got null?
7941    beq     common_exceptionThrown      @ yes, handle exception
7942    mov     r1, r0                      @ r1<- class resolved from BBB
7943    mov     r3, rINST, lsr #12          @ r3<- B
7944    GET_VREG(r0, r3)                    @ r0<- vB (object)
7945    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
7946    b       .LOP_INSTANCE_OF_resolved        @ pick up where we left off
7947
7948
7949/* continuation for OP_NEW_INSTANCE */
7950
7951    .balign 32                          @ minimize cache lines
7952.LOP_NEW_INSTANCE_finish: @ r0=class
7953    bl      dvmAllocObject              @ r0<- new object
7954    mov     r3, rINST, lsr #8           @ r3<- AA
7955    cmp     r0, #0                      @ failed?
7956    beq     common_exceptionThrown      @ yes, handle the exception
7957    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7958    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7959    SET_VREG(r0, r3)                    @ vAA<- r0
7960    GOTO_OPCODE(ip)                     @ jump to next instruction
7961
7962    /*
7963     * Class initialization required.
7964     *
7965     *  r0 holds class object
7966     */
7967.LOP_NEW_INSTANCE_needinit:
7968    mov     r9, r0                      @ save r0
7969    bl      dvmInitClass                @ initialize class
7970    cmp     r0, #0                      @ check boolean result
7971    mov     r0, r9                      @ restore r0
7972    bne     .LOP_NEW_INSTANCE_initialized     @ success, continue
7973    b       common_exceptionThrown      @ failed, deal with init exception
7974
7975    /*
7976     * Resolution required.  This is the least-likely path.
7977     *
7978     *  r1 holds BBBB
7979     */
7980.LOP_NEW_INSTANCE_resolve:
7981    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7982    mov     r2, #0                      @ r2<- false
7983    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7984    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7985    cmp     r0, #0                      @ got null?
7986    bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
7987    b       common_exceptionThrown      @ yes, handle exception
7988
7989    /*
7990     * We can't instantiate an abstract class or interface, so throw an
7991     * InstantiationError with the class descriptor as the message.
7992     *
7993     *  r0 holds class object
7994     */
7995.LOP_NEW_INSTANCE_abstract:
7996    ldr     r1, [r0, #offClassObject_descriptor]
7997    ldr     r0, .LstrInstantiationErrorPtr
7998    bl      dvmThrowExceptionWithClassMessage
7999    b       common_exceptionThrown
8000
8001.LstrInstantiationErrorPtr:
8002    .word   .LstrInstantiationError
8003
8004
8005/* continuation for OP_NEW_ARRAY */
8006
8007
8008    /*
8009     * Resolve class.  (This is an uncommon case.)
8010     *
8011     *  r1 holds array length
8012     *  r2 holds class ref CCCC
8013     */
8014.LOP_NEW_ARRAY_resolve:
8015    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8016    mov     r9, r1                      @ r9<- length (save)
8017    mov     r1, r2                      @ r1<- CCCC
8018    mov     r2, #0                      @ r2<- false
8019    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8020    bl      dvmResolveClass             @ r0<- call(clazz, ref)
8021    cmp     r0, #0                      @ got null?
8022    mov     r1, r9                      @ r1<- length (restore)
8023    beq     common_exceptionThrown      @ yes, handle exception
8024    @ fall through to OP_NEW_ARRAY_finish
8025
8026    /*
8027     * Finish allocation.
8028     *
8029     *  r0 holds class
8030     *  r1 holds array length
8031     */
8032.LOP_NEW_ARRAY_finish:
8033    mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
8034    bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
8035    cmp     r0, #0                      @ failed?
8036    mov     r2, rINST, lsr #8           @ r2<- A+
8037    beq     common_exceptionThrown      @ yes, handle the exception
8038    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8039    and     r2, r2, #15                 @ r2<- A
8040    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8041    SET_VREG(r0, r2)                    @ vA<- r0
8042    GOTO_OPCODE(ip)                     @ jump to next instruction
8043
8044
8045/* continuation for OP_FILLED_NEW_ARRAY */
8046
8047    /*
8048     * On entry:
8049     *  r0 holds array class
8050     *  r10 holds AA or BA
8051     */
8052.LOP_FILLED_NEW_ARRAY_continue:
8053    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8054    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8055    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
8056    .if     0
8057    mov     r1, r10                     @ r1<- AA (length)
8058    .else
8059    mov     r1, r10, lsr #4             @ r1<- B (length)
8060    .endif
8061    cmp     r3, #'I'                    @ array of ints?
8062    cmpne   r3, #'L'                    @ array of objects?
8063    cmpne   r3, #'['                    @ array of arrays?
8064    mov     r9, r1                      @ save length in r9
8065    bne     .LOP_FILLED_NEW_ARRAY_notimpl         @ no, not handled yet
8066    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8067    cmp     r0, #0                      @ null return?
8068    beq     common_exceptionThrown      @ alloc failed, handle exception
8069
8070    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8071    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
8072    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8073    subs    r9, r9, #1                  @ length--, check for neg
8074    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8075    bmi     2f                          @ was zero, bail
8076
8077    @ copy values from registers into the array
8078    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8079    .if     0
8080    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
80811:  ldr     r3, [r2], #4                @ r3<- *r2++
8082    subs    r9, r9, #1                  @ count--
8083    str     r3, [r0], #4                @ *contents++ = vX
8084    bpl     1b
8085    @ continue at 2
8086    .else
8087    cmp     r9, #4                      @ length was initially 5?
8088    and     r2, r10, #15                @ r2<- A
8089    bne     1f                          @ <= 4 args, branch
8090    GET_VREG(r3, r2)                    @ r3<- vA
8091    sub     r9, r9, #1                  @ count--
8092    str     r3, [r0, #16]               @ contents[4] = vA
80931:  and     r2, r1, #15                 @ r2<- F/E/D/C
8094    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8095    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8096    subs    r9, r9, #1                  @ count--
8097    str     r3, [r0], #4                @ *contents++ = vX
8098    bpl     1b
8099    @ continue at 2
8100    .endif
8101
81022:
8103    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
8104    GOTO_OPCODE(ip)                     @ execute it
8105
8106    /*
8107     * Throw an exception indicating that we have not implemented this
8108     * mode of filled-new-array.
8109     */
8110.LOP_FILLED_NEW_ARRAY_notimpl:
8111    ldr     r0, .L_strInternalError
8112    ldr     r1, .L_strFilledNewArrayNotImpl
8113    bl      dvmThrowException
8114    b       common_exceptionThrown
8115
8116    .if     (!0)                 @ define in one or the other, not both
8117.L_strFilledNewArrayNotImpl:
8118    .word   .LstrFilledNewArrayNotImpl
8119.L_strInternalError:
8120    .word   .LstrInternalError
8121    .endif
8122
8123
8124/* continuation for OP_FILLED_NEW_ARRAY_RANGE */
8125
8126    /*
8127     * On entry:
8128     *  r0 holds array class
8129     *  r10 holds AA or BA
8130     */
8131.LOP_FILLED_NEW_ARRAY_RANGE_continue:
8132    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8133    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8134    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
8135    .if     1
8136    mov     r1, r10                     @ r1<- AA (length)
8137    .else
8138    mov     r1, r10, lsr #4             @ r1<- B (length)
8139    .endif
8140    cmp     r3, #'I'                    @ array of ints?
8141    cmpne   r3, #'L'                    @ array of objects?
8142    cmpne   r3, #'['                    @ array of arrays?
8143    mov     r9, r1                      @ save length in r9
8144    bne     .LOP_FILLED_NEW_ARRAY_RANGE_notimpl         @ no, not handled yet
8145    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8146    cmp     r0, #0                      @ null return?
8147    beq     common_exceptionThrown      @ alloc failed, handle exception
8148
8149    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8150    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
8151    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8152    subs    r9, r9, #1                  @ length--, check for neg
8153    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8154    bmi     2f                          @ was zero, bail
8155
8156    @ copy values from registers into the array
8157    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8158    .if     1
8159    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
81601:  ldr     r3, [r2], #4                @ r3<- *r2++
8161    subs    r9, r9, #1                  @ count--
8162    str     r3, [r0], #4                @ *contents++ = vX
8163    bpl     1b
8164    @ continue at 2
8165    .else
8166    cmp     r9, #4                      @ length was initially 5?
8167    and     r2, r10, #15                @ r2<- A
8168    bne     1f                          @ <= 4 args, branch
8169    GET_VREG(r3, r2)                    @ r3<- vA
8170    sub     r9, r9, #1                  @ count--
8171    str     r3, [r0, #16]               @ contents[4] = vA
81721:  and     r2, r1, #15                 @ r2<- F/E/D/C
8173    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8174    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8175    subs    r9, r9, #1                  @ count--
8176    str     r3, [r0], #4                @ *contents++ = vX
8177    bpl     1b
8178    @ continue at 2
8179    .endif
8180
81812:
8182    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
8183    GOTO_OPCODE(ip)                     @ execute it
8184
8185    /*
8186     * Throw an exception indicating that we have not implemented this
8187     * mode of filled-new-array.
8188     */
8189.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
8190    ldr     r0, .L_strInternalError
8191    ldr     r1, .L_strFilledNewArrayNotImpl
8192    bl      dvmThrowException
8193    b       common_exceptionThrown
8194
8195    .if     (!1)                 @ define in one or the other, not both
8196.L_strFilledNewArrayNotImpl:
8197    .word   .LstrFilledNewArrayNotImpl
8198.L_strInternalError:
8199    .word   .LstrInternalError
8200    .endif
8201
8202
8203/* continuation for OP_CMPL_FLOAT */
8204
8205    @ Test for NaN with a second comparison.  EABI forbids testing bit
8206    @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8207    @ make the library call.
8208.LOP_CMPL_FLOAT_gt_or_nan:
8209    mov     r1, r9                      @ reverse order
8210    mov     r0, r10
8211    bl      __aeabi_cfcmple             @ r0<- Z set if eq, C clear if <
8212    @bleq    common_abort
8213    movcc   r1, #1                      @ (greater than) r1<- 1
8214    bcc     .LOP_CMPL_FLOAT_finish
8215    mvn     r1, #0                            @ r1<- 1 or -1 for NaN
8216    b       .LOP_CMPL_FLOAT_finish
8217
8218
8219#if 0       /* "clasic" form */
8220    FETCH(r0, 1)                        @ r0<- CCBB
8221    and     r2, r0, #255                @ r2<- BB
8222    mov     r3, r0, lsr #8              @ r3<- CC
8223    GET_VREG(r9, r2)                    @ r9<- vBB
8224    GET_VREG(r10, r3)                   @ r10<- vCC
8225    mov     r0, r9                      @ r0<- vBB
8226    mov     r1, r10                     @ r1<- vCC
8227    bl      __aeabi_fcmpeq              @ r0<- (vBB == vCC)
8228    cmp     r0, #0                      @ equal?
8229    movne   r1, #0                      @ yes, result is 0
8230    bne     OP_CMPL_FLOAT_finish
8231    mov     r0, r9                      @ r0<- vBB
8232    mov     r1, r10                     @ r1<- vCC
8233    bl      __aeabi_fcmplt              @ r0<- (vBB < vCC)
8234    cmp     r0, #0                      @ less than?
8235    b       OP_CMPL_FLOAT_continue
8236@%break
8237
8238OP_CMPL_FLOAT_continue:
8239    mvnne   r1, #0                      @ yes, result is -1
8240    bne     OP_CMPL_FLOAT_finish
8241    mov     r0, r9                      @ r0<- vBB
8242    mov     r1, r10                     @ r1<- vCC
8243    bl      __aeabi_fcmpgt              @ r0<- (vBB > vCC)
8244    cmp     r0, #0                      @ greater than?
8245    beq     OP_CMPL_FLOAT_nan               @ no, must be NaN
8246    mov     r1, #1                      @ yes, result is 1
8247    @ fall through to _finish
8248
8249OP_CMPL_FLOAT_finish:
8250    mov     r3, rINST, lsr #8           @ r3<- AA
8251    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8252    SET_VREG(r1, r3)                    @ vAA<- r1
8253    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8254    GOTO_OPCODE(ip)                     @ jump to next instruction
8255
8256    /*
8257     * This is expected to be uncommon, so we double-branch (once to here,
8258     * again back to _finish).
8259     */
8260OP_CMPL_FLOAT_nan:
8261    mvn     r1, #0                            @ r1<- 1 or -1 for NaN
8262    b       OP_CMPL_FLOAT_finish
8263
8264#endif
8265
8266
8267/* continuation for OP_CMPG_FLOAT */
8268
8269    @ Test for NaN with a second comparison.  EABI forbids testing bit
8270    @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8271    @ make the library call.
8272.LOP_CMPG_FLOAT_gt_or_nan:
8273    mov     r1, r9                      @ reverse order
8274    mov     r0, r10
8275    bl      __aeabi_cfcmple             @ r0<- Z set if eq, C clear if <
8276    @bleq    common_abort
8277    movcc   r1, #1                      @ (greater than) r1<- 1
8278    bcc     .LOP_CMPG_FLOAT_finish
8279    mov     r1, #1                            @ r1<- 1 or -1 for NaN
8280    b       .LOP_CMPG_FLOAT_finish
8281
8282
8283#if 0       /* "clasic" form */
8284    FETCH(r0, 1)                        @ r0<- CCBB
8285    and     r2, r0, #255                @ r2<- BB
8286    mov     r3, r0, lsr #8              @ r3<- CC
8287    GET_VREG(r9, r2)                    @ r9<- vBB
8288    GET_VREG(r10, r3)                   @ r10<- vCC
8289    mov     r0, r9                      @ r0<- vBB
8290    mov     r1, r10                     @ r1<- vCC
8291    bl      __aeabi_fcmpeq              @ r0<- (vBB == vCC)
8292    cmp     r0, #0                      @ equal?
8293    movne   r1, #0                      @ yes, result is 0
8294    bne     OP_CMPG_FLOAT_finish
8295    mov     r0, r9                      @ r0<- vBB
8296    mov     r1, r10                     @ r1<- vCC
8297    bl      __aeabi_fcmplt              @ r0<- (vBB < vCC)
8298    cmp     r0, #0                      @ less than?
8299    b       OP_CMPG_FLOAT_continue
8300@%break
8301
8302OP_CMPG_FLOAT_continue:
8303    mvnne   r1, #0                      @ yes, result is -1
8304    bne     OP_CMPG_FLOAT_finish
8305    mov     r0, r9                      @ r0<- vBB
8306    mov     r1, r10                     @ r1<- vCC
8307    bl      __aeabi_fcmpgt              @ r0<- (vBB > vCC)
8308    cmp     r0, #0                      @ greater than?
8309    beq     OP_CMPG_FLOAT_nan               @ no, must be NaN
8310    mov     r1, #1                      @ yes, result is 1
8311    @ fall through to _finish
8312
8313OP_CMPG_FLOAT_finish:
8314    mov     r3, rINST, lsr #8           @ r3<- AA
8315    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8316    SET_VREG(r1, r3)                    @ vAA<- r1
8317    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8318    GOTO_OPCODE(ip)                     @ jump to next instruction
8319
8320    /*
8321     * This is expected to be uncommon, so we double-branch (once to here,
8322     * again back to _finish).
8323     */
8324OP_CMPG_FLOAT_nan:
8325    mov     r1, #1                            @ r1<- 1 or -1 for NaN
8326    b       OP_CMPG_FLOAT_finish
8327
8328#endif
8329
8330
8331/* continuation for OP_CMPL_DOUBLE */
8332
8333    @ Test for NaN with a second comparison.  EABI forbids testing bit
8334    @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8335    @ make the library call.
8336.LOP_CMPL_DOUBLE_gt_or_nan:
8337    ldmia   r10, {r0-r1}                @ reverse order
8338    ldmia   r9, {r2-r3}
8339    bl      __aeabi_cdcmple             @ r0<- Z set if eq, C clear if <
8340    @bleq    common_abort
8341    movcc   r1, #1                      @ (greater than) r1<- 1
8342    bcc     .LOP_CMPL_DOUBLE_finish
8343    mvn     r1, #0                            @ r1<- 1 or -1 for NaN
8344    b       .LOP_CMPL_DOUBLE_finish
8345
8346
8347/* continuation for OP_CMPG_DOUBLE */
8348
8349    @ Test for NaN with a second comparison.  EABI forbids testing bit
8350    @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8351    @ make the library call.
8352.LOP_CMPG_DOUBLE_gt_or_nan:
8353    ldmia   r10, {r0-r1}                @ reverse order
8354    ldmia   r9, {r2-r3}
8355    bl      __aeabi_cdcmple             @ r0<- Z set if eq, C clear if <
8356    @bleq    common_abort
8357    movcc   r1, #1                      @ (greater than) r1<- 1
8358    bcc     .LOP_CMPG_DOUBLE_finish
8359    mov     r1, #1                            @ r1<- 1 or -1 for NaN
8360    b       .LOP_CMPG_DOUBLE_finish
8361
8362
8363/* continuation for OP_CMP_LONG */
8364
8365.LOP_CMP_LONG_less:
8366    mvn     r1, #0                      @ r1<- -1
8367    @ Want to cond code the next mov so we can avoid branch, but don't see it;
8368    @ instead, we just replicate the tail end.
8369    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8370    SET_VREG(r1, r9)                    @ vAA<- r1
8371    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8372    GOTO_OPCODE(ip)                     @ jump to next instruction
8373
8374.LOP_CMP_LONG_greater:
8375    mov     r1, #1                      @ r1<- 1
8376    @ fall through to _finish
8377
8378.LOP_CMP_LONG_finish:
8379    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8380    SET_VREG(r1, r9)                    @ vAA<- r1
8381    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8382    GOTO_OPCODE(ip)                     @ jump to next instruction
8383
8384
8385/* continuation for OP_AGET_WIDE */
8386
8387.LOP_AGET_WIDE_finish:
8388    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8389    ldrd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8390    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
8391    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8392    stmia   r9, {r2-r3}                 @ vAA/vAA+1<- r2/r3
8393    GOTO_OPCODE(ip)                     @ jump to next instruction
8394
8395
8396/* continuation for OP_APUT_WIDE */
8397
8398.LOP_APUT_WIDE_finish:
8399    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8400    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
8401    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8402    strd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8403    GOTO_OPCODE(ip)                     @ jump to next instruction
8404
8405
8406/* continuation for OP_APUT_OBJECT */
8407    /*
8408     * On entry:
8409     *  r1 = vBB (arrayObj)
8410     *  r9 = vAA (obj)
8411     *  r10 = offset into array (vBB + vCC * width)
8412     */
8413.LOP_APUT_OBJECT_finish:
8414    cmp     r9, #0                      @ storing null reference?
8415    beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
8416    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
8417    ldr     r1, [r1, #offObject_clazz]  @ r1<- arrayObj->clazz
8418    bl      dvmCanPutArrayElement       @ test object type vs. array type
8419    cmp     r0, #0                      @ okay?
8420    beq     common_errArrayStore        @ no
8421.LOP_APUT_OBJECT_skip_check:
8422    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8423    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8424    str     r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
8425    GOTO_OPCODE(ip)                     @ jump to next instruction
8426
8427
8428/* continuation for OP_IGET */
8429
8430    /*
8431     * Currently:
8432     *  r0 holds resolved field
8433     *  r9 holds object
8434     */
8435.LOP_IGET_finish:
8436    @bl      common_squeak0
8437    cmp     r9, #0                      @ check object for null
8438    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8439    beq     common_errNullObject        @ object was null
8440    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8441    mov     r2, rINST, lsr #8           @ r2<- A+
8442    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8443    and     r2, r2, #15                 @ r2<- A
8444    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8445    SET_VREG(r0, r2)                    @ fp[A]<- r0
8446    GOTO_OPCODE(ip)                     @ jump to next instruction
8447
8448
8449/* continuation for OP_IGET_WIDE */
8450
8451    /*
8452     * Currently:
8453     *  r0 holds resolved field
8454     *  r9 holds object
8455     */
8456.LOP_IGET_WIDE_finish:
8457    cmp     r9, #0                      @ check object for null
8458    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8459    beq     common_errNullObject        @ object was null
8460    mov     r2, rINST, lsr #8           @ r2<- A+
8461    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
8462    and     r2, r2, #15                 @ r2<- A
8463    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8464    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
8465    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8466    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
8467    GOTO_OPCODE(ip)                     @ jump to next instruction
8468
8469
8470/* continuation for OP_IGET_OBJECT */
8471
8472    /*
8473     * Currently:
8474     *  r0 holds resolved field
8475     *  r9 holds object
8476     */
8477.LOP_IGET_OBJECT_finish:
8478    @bl      common_squeak0
8479    cmp     r9, #0                      @ check object for null
8480    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8481    beq     common_errNullObject        @ object was null
8482    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8483    mov     r2, rINST, lsr #8           @ r2<- A+
8484    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8485    and     r2, r2, #15                 @ r2<- A
8486    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8487    SET_VREG(r0, r2)                    @ fp[A]<- r0
8488    GOTO_OPCODE(ip)                     @ jump to next instruction
8489
8490
8491/* continuation for OP_IGET_BOOLEAN */
8492
8493    /*
8494     * Currently:
8495     *  r0 holds resolved field
8496     *  r9 holds object
8497     */
8498.LOP_IGET_BOOLEAN_finish:
8499    @bl      common_squeak1
8500    cmp     r9, #0                      @ check object for null
8501    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8502    beq     common_errNullObject        @ object was null
8503    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8504    mov     r2, rINST, lsr #8           @ r2<- A+
8505    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8506    and     r2, r2, #15                 @ r2<- A
8507    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8508    SET_VREG(r0, r2)                    @ fp[A]<- r0
8509    GOTO_OPCODE(ip)                     @ jump to next instruction
8510
8511
8512/* continuation for OP_IGET_BYTE */
8513
8514    /*
8515     * Currently:
8516     *  r0 holds resolved field
8517     *  r9 holds object
8518     */
8519.LOP_IGET_BYTE_finish:
8520    @bl      common_squeak2
8521    cmp     r9, #0                      @ check object for null
8522    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8523    beq     common_errNullObject        @ object was null
8524    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8525    mov     r2, rINST, lsr #8           @ r2<- A+
8526    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8527    and     r2, r2, #15                 @ r2<- A
8528    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8529    SET_VREG(r0, r2)                    @ fp[A]<- r0
8530    GOTO_OPCODE(ip)                     @ jump to next instruction
8531
8532
8533/* continuation for OP_IGET_CHAR */
8534
8535    /*
8536     * Currently:
8537     *  r0 holds resolved field
8538     *  r9 holds object
8539     */
8540.LOP_IGET_CHAR_finish:
8541    @bl      common_squeak3
8542    cmp     r9, #0                      @ check object for null
8543    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8544    beq     common_errNullObject        @ object was null
8545    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8546    mov     r2, rINST, lsr #8           @ r2<- A+
8547    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8548    and     r2, r2, #15                 @ r2<- A
8549    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8550    SET_VREG(r0, r2)                    @ fp[A]<- r0
8551    GOTO_OPCODE(ip)                     @ jump to next instruction
8552
8553
8554/* continuation for OP_IGET_SHORT */
8555
8556    /*
8557     * Currently:
8558     *  r0 holds resolved field
8559     *  r9 holds object
8560     */
8561.LOP_IGET_SHORT_finish:
8562    @bl      common_squeak4
8563    cmp     r9, #0                      @ check object for null
8564    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8565    beq     common_errNullObject        @ object was null
8566    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8567    mov     r2, rINST, lsr #8           @ r2<- A+
8568    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8569    and     r2, r2, #15                 @ r2<- A
8570    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8571    SET_VREG(r0, r2)                    @ fp[A]<- r0
8572    GOTO_OPCODE(ip)                     @ jump to next instruction
8573
8574
8575/* continuation for OP_IPUT */
8576
8577    /*
8578     * Currently:
8579     *  r0 holds resolved field
8580     *  r9 holds object
8581     */
8582.LOP_IPUT_finish:
8583    @bl      common_squeak0
8584    mov     r1, rINST, lsr #8           @ r1<- A+
8585    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8586    and     r1, r1, #15                 @ r1<- A
8587    cmp     r9, #0                      @ check object for null
8588    GET_VREG(r0, r1)                    @ r0<- fp[A]
8589    beq     common_errNullObject        @ object was null
8590    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8591    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8592    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8593    GOTO_OPCODE(ip)                     @ jump to next instruction
8594
8595
8596/* continuation for OP_IPUT_WIDE */
8597
8598    /*
8599     * Currently:
8600     *  r0 holds resolved field
8601     *  r9 holds object
8602     */
8603.LOP_IPUT_WIDE_finish:
8604    mov     r2, rINST, lsr #8           @ r2<- A+
8605    cmp     r9, #0                      @ check object for null
8606    and     r2, r2, #15                 @ r2<- A
8607    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8608    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
8609    beq     common_errNullObject        @ object was null
8610    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8611    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
8612    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8613    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0
8614    GOTO_OPCODE(ip)                     @ jump to next instruction
8615
8616
8617/* continuation for OP_IPUT_OBJECT */
8618
8619    /*
8620     * Currently:
8621     *  r0 holds resolved field
8622     *  r9 holds object
8623     */
8624.LOP_IPUT_OBJECT_finish:
8625    @bl      common_squeak0
8626    mov     r1, rINST, lsr #8           @ r1<- A+
8627    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8628    and     r1, r1, #15                 @ r1<- A
8629    cmp     r9, #0                      @ check object for null
8630    GET_VREG(r0, r1)                    @ r0<- fp[A]
8631    beq     common_errNullObject        @ object was null
8632    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8633    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8634    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8635    GOTO_OPCODE(ip)                     @ jump to next instruction
8636
8637
8638/* continuation for OP_IPUT_BOOLEAN */
8639
8640    /*
8641     * Currently:
8642     *  r0 holds resolved field
8643     *  r9 holds object
8644     */
8645.LOP_IPUT_BOOLEAN_finish:
8646    @bl      common_squeak1
8647    mov     r1, rINST, lsr #8           @ r1<- A+
8648    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8649    and     r1, r1, #15                 @ r1<- A
8650    cmp     r9, #0                      @ check object for null
8651    GET_VREG(r0, r1)                    @ r0<- fp[A]
8652    beq     common_errNullObject        @ object was null
8653    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8654    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8655    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8656    GOTO_OPCODE(ip)                     @ jump to next instruction
8657
8658
8659/* continuation for OP_IPUT_BYTE */
8660
8661    /*
8662     * Currently:
8663     *  r0 holds resolved field
8664     *  r9 holds object
8665     */
8666.LOP_IPUT_BYTE_finish:
8667    @bl      common_squeak2
8668    mov     r1, rINST, lsr #8           @ r1<- A+
8669    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8670    and     r1, r1, #15                 @ r1<- A
8671    cmp     r9, #0                      @ check object for null
8672    GET_VREG(r0, r1)                    @ r0<- fp[A]
8673    beq     common_errNullObject        @ object was null
8674    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8675    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8676    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8677    GOTO_OPCODE(ip)                     @ jump to next instruction
8678
8679
8680/* continuation for OP_IPUT_CHAR */
8681
8682    /*
8683     * Currently:
8684     *  r0 holds resolved field
8685     *  r9 holds object
8686     */
8687.LOP_IPUT_CHAR_finish:
8688    @bl      common_squeak3
8689    mov     r1, rINST, lsr #8           @ r1<- A+
8690    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8691    and     r1, r1, #15                 @ r1<- A
8692    cmp     r9, #0                      @ check object for null
8693    GET_VREG(r0, r1)                    @ r0<- fp[A]
8694    beq     common_errNullObject        @ object was null
8695    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8696    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8697    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8698    GOTO_OPCODE(ip)                     @ jump to next instruction
8699
8700
8701/* continuation for OP_IPUT_SHORT */
8702
8703    /*
8704     * Currently:
8705     *  r0 holds resolved field
8706     *  r9 holds object
8707     */
8708.LOP_IPUT_SHORT_finish:
8709    @bl      common_squeak4
8710    mov     r1, rINST, lsr #8           @ r1<- A+
8711    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8712    and     r1, r1, #15                 @ r1<- A
8713    cmp     r9, #0                      @ check object for null
8714    GET_VREG(r0, r1)                    @ r0<- fp[A]
8715    beq     common_errNullObject        @ object was null
8716    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8717    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8718    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8719    GOTO_OPCODE(ip)                     @ jump to next instruction
8720
8721
8722/* continuation for OP_SGET */
8723
8724    /*
8725     * Continuation if the field has not yet been resolved.
8726     *  r1: BBBB field ref
8727     */
8728.LOP_SGET_resolve:
8729    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8730    EXPORT_PC()                         @ resolve() could throw, so export now
8731    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8732    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8733    cmp     r0, #0                      @ success?
8734    bne     .LOP_SGET_finish          @ yes, finish
8735    b       common_exceptionThrown      @ no, handle exception
8736
8737
8738/* continuation for OP_SGET_WIDE */
8739
8740    /*
8741     * Continuation if the field has not yet been resolved.
8742     *  r1: BBBB field ref
8743     */
8744.LOP_SGET_WIDE_resolve:
8745    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8746    EXPORT_PC()                         @ resolve() could throw, so export now
8747    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8748    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8749    cmp     r0, #0                      @ success?
8750    bne     .LOP_SGET_WIDE_finish          @ yes, finish
8751    b       common_exceptionThrown      @ no, handle exception
8752
8753
8754/* continuation for OP_SGET_OBJECT */
8755
8756    /*
8757     * Continuation if the field has not yet been resolved.
8758     *  r1: BBBB field ref
8759     */
8760.LOP_SGET_OBJECT_resolve:
8761    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8762    EXPORT_PC()                         @ resolve() could throw, so export now
8763    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8764    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8765    cmp     r0, #0                      @ success?
8766    bne     .LOP_SGET_OBJECT_finish          @ yes, finish
8767    b       common_exceptionThrown      @ no, handle exception
8768
8769
8770/* continuation for OP_SGET_BOOLEAN */
8771
8772    /*
8773     * Continuation if the field has not yet been resolved.
8774     *  r1: BBBB field ref
8775     */
8776.LOP_SGET_BOOLEAN_resolve:
8777    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8778    EXPORT_PC()                         @ resolve() could throw, so export now
8779    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8780    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8781    cmp     r0, #0                      @ success?
8782    bne     .LOP_SGET_BOOLEAN_finish          @ yes, finish
8783    b       common_exceptionThrown      @ no, handle exception
8784
8785
8786/* continuation for OP_SGET_BYTE */
8787
8788    /*
8789     * Continuation if the field has not yet been resolved.
8790     *  r1: BBBB field ref
8791     */
8792.LOP_SGET_BYTE_resolve:
8793    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8794    EXPORT_PC()                         @ resolve() could throw, so export now
8795    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8796    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8797    cmp     r0, #0                      @ success?
8798    bne     .LOP_SGET_BYTE_finish          @ yes, finish
8799    b       common_exceptionThrown      @ no, handle exception
8800
8801
8802/* continuation for OP_SGET_CHAR */
8803
8804    /*
8805     * Continuation if the field has not yet been resolved.
8806     *  r1: BBBB field ref
8807     */
8808.LOP_SGET_CHAR_resolve:
8809    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8810    EXPORT_PC()                         @ resolve() could throw, so export now
8811    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8812    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8813    cmp     r0, #0                      @ success?
8814    bne     .LOP_SGET_CHAR_finish          @ yes, finish
8815    b       common_exceptionThrown      @ no, handle exception
8816
8817
8818/* continuation for OP_SGET_SHORT */
8819
8820    /*
8821     * Continuation if the field has not yet been resolved.
8822     *  r1: BBBB field ref
8823     */
8824.LOP_SGET_SHORT_resolve:
8825    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8826    EXPORT_PC()                         @ resolve() could throw, so export now
8827    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8828    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8829    cmp     r0, #0                      @ success?
8830    bne     .LOP_SGET_SHORT_finish          @ yes, finish
8831    b       common_exceptionThrown      @ no, handle exception
8832
8833
8834/* continuation for OP_SPUT */
8835
8836    /*
8837     * Continuation if the field has not yet been resolved.
8838     *  r1: BBBB field ref
8839     */
8840.LOP_SPUT_resolve:
8841    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8842    EXPORT_PC()                         @ resolve() could throw, so export now
8843    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8844    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8845    cmp     r0, #0                      @ success?
8846    bne     .LOP_SPUT_finish          @ yes, finish
8847    b       common_exceptionThrown      @ no, handle exception
8848
8849
8850/* continuation for OP_SPUT_WIDE */
8851
8852    /*
8853     * Continuation if the field has not yet been resolved.
8854     *  r1: BBBB field ref
8855     *  r9: &fp[AA]
8856     */
8857.LOP_SPUT_WIDE_resolve:
8858    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8859    EXPORT_PC()                         @ resolve() could throw, so export now
8860    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8861    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8862    cmp     r0, #0                      @ success?
8863    bne     .LOP_SPUT_WIDE_finish          @ yes, finish
8864    b       common_exceptionThrown      @ no, handle exception
8865
8866
8867/* continuation for OP_SPUT_OBJECT */
8868
8869    /*
8870     * Continuation if the field has not yet been resolved.
8871     *  r1: BBBB field ref
8872     */
8873.LOP_SPUT_OBJECT_resolve:
8874    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8875    EXPORT_PC()                         @ resolve() could throw, so export now
8876    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8877    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8878    cmp     r0, #0                      @ success?
8879    bne     .LOP_SPUT_OBJECT_finish          @ yes, finish
8880    b       common_exceptionThrown      @ no, handle exception
8881
8882
8883/* continuation for OP_SPUT_BOOLEAN */
8884
8885    /*
8886     * Continuation if the field has not yet been resolved.
8887     *  r1: BBBB field ref
8888     */
8889.LOP_SPUT_BOOLEAN_resolve:
8890    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8891    EXPORT_PC()                         @ resolve() could throw, so export now
8892    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8893    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8894    cmp     r0, #0                      @ success?
8895    bne     .LOP_SPUT_BOOLEAN_finish          @ yes, finish
8896    b       common_exceptionThrown      @ no, handle exception
8897
8898
8899/* continuation for OP_SPUT_BYTE */
8900
8901    /*
8902     * Continuation if the field has not yet been resolved.
8903     *  r1: BBBB field ref
8904     */
8905.LOP_SPUT_BYTE_resolve:
8906    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8907    EXPORT_PC()                         @ resolve() could throw, so export now
8908    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8909    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8910    cmp     r0, #0                      @ success?
8911    bne     .LOP_SPUT_BYTE_finish          @ yes, finish
8912    b       common_exceptionThrown      @ no, handle exception
8913
8914
8915/* continuation for OP_SPUT_CHAR */
8916
8917    /*
8918     * Continuation if the field has not yet been resolved.
8919     *  r1: BBBB field ref
8920     */
8921.LOP_SPUT_CHAR_resolve:
8922    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8923    EXPORT_PC()                         @ resolve() could throw, so export now
8924    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8925    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8926    cmp     r0, #0                      @ success?
8927    bne     .LOP_SPUT_CHAR_finish          @ yes, finish
8928    b       common_exceptionThrown      @ no, handle exception
8929
8930
8931/* continuation for OP_SPUT_SHORT */
8932
8933    /*
8934     * Continuation if the field has not yet been resolved.
8935     *  r1: BBBB field ref
8936     */
8937.LOP_SPUT_SHORT_resolve:
8938    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8939    EXPORT_PC()                         @ resolve() could throw, so export now
8940    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8941    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8942    cmp     r0, #0                      @ success?
8943    bne     .LOP_SPUT_SHORT_finish          @ yes, finish
8944    b       common_exceptionThrown      @ no, handle exception
8945
8946
8947/* continuation for OP_INVOKE_VIRTUAL */
8948
8949    /*
8950     * At this point:
8951     *  r0 = resolved base method
8952     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8953     */
8954.LOP_INVOKE_VIRTUAL_continue:
8955    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8956    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8957    cmp     r1, #0                      @ is "this" null?
8958    beq     common_errNullObject        @ null "this", throw exception
8959    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8960    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8961    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8962    bl      common_invokeMethodNoRange @ continue on
8963
8964
8965/* continuation for OP_INVOKE_SUPER */
8966
8967    /*
8968     * At this point:
8969     *  r0 = resolved base method
8970     *  r9 = method->clazz
8971     */
8972.LOP_INVOKE_SUPER_continue:
8973    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8974    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8975    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8976    EXPORT_PC()                         @ must export for invoke
8977    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8978    bcs     .LOP_INVOKE_SUPER_nsm             @ method not present in superclass
8979    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8980    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8981    bl      common_invokeMethodNoRange @ continue on
8982
8983.LOP_INVOKE_SUPER_resolve:
8984    mov     r0, r9                      @ r0<- method->clazz
8985    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8986    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8987    cmp     r0, #0                      @ got null?
8988    bne     .LOP_INVOKE_SUPER_continue        @ no, continue
8989    b       common_exceptionThrown      @ yes, handle exception
8990
8991    /*
8992     * Throw a NoSuchMethodError with the method name as the message.
8993     *  r0 = resolved base method
8994     */
8995.LOP_INVOKE_SUPER_nsm:
8996    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8997    b       common_errNoSuchMethod
8998
8999
9000/* continuation for OP_INVOKE_DIRECT */
9001
9002    /*
9003     * On entry:
9004     *  r1 = reference (BBBB or CCCC)
9005     *  r10 = "this" register
9006     */
9007.LOP_INVOKE_DIRECT_resolve:
9008    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
9009    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
9010    mov     r2, #METHOD_DIRECT          @ resolver method type
9011    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
9012    cmp     r0, #0                      @ got null?
9013    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
9014    bne     .LOP_INVOKE_DIRECT_finish          @ no, continue
9015    b       common_exceptionThrown      @ yes, handle exception
9016
9017
9018/* continuation for OP_INVOKE_VIRTUAL_RANGE */
9019
9020    /*
9021     * At this point:
9022     *  r0 = resolved base method
9023     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
9024     */
9025.LOP_INVOKE_VIRTUAL_RANGE_continue:
9026    GET_VREG(r1, r10)                   @ r1<- "this" ptr
9027    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
9028    cmp     r1, #0                      @ is "this" null?
9029    beq     common_errNullObject        @ null "this", throw exception
9030    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
9031    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
9032    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
9033    bl      common_invokeMethodRange @ continue on
9034
9035
9036/* continuation for OP_INVOKE_SUPER_RANGE */
9037
9038    /*
9039     * At this point:
9040     *  r0 = resolved base method
9041     *  r9 = method->clazz
9042     */
9043.LOP_INVOKE_SUPER_RANGE_continue:
9044    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
9045    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
9046    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
9047    EXPORT_PC()                         @ must export for invoke
9048    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
9049    bcs     .LOP_INVOKE_SUPER_RANGE_nsm             @ method not present in superclass
9050    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
9051    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
9052    bl      common_invokeMethodRange @ continue on
9053
9054.LOP_INVOKE_SUPER_RANGE_resolve:
9055    mov     r0, r9                      @ r0<- method->clazz
9056    mov     r2, #METHOD_VIRTUAL         @ resolver method type
9057    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
9058    cmp     r0, #0                      @ got null?
9059    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ no, continue
9060    b       common_exceptionThrown      @ yes, handle exception
9061
9062    /*
9063     * Throw a NoSuchMethodError with the method name as the message.
9064     *  r0 = resolved base method
9065     */
9066.LOP_INVOKE_SUPER_RANGE_nsm:
9067    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
9068    b       common_errNoSuchMethod
9069
9070
9071/* continuation for OP_INVOKE_DIRECT_RANGE */
9072
9073    /*
9074     * On entry:
9075     *  r1 = reference (BBBB or CCCC)
9076     *  r10 = "this" register
9077     */
9078.LOP_INVOKE_DIRECT_RANGE_resolve:
9079    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
9080    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
9081    mov     r2, #METHOD_DIRECT          @ resolver method type
9082    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
9083    cmp     r0, #0                      @ got null?
9084    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
9085    bne     .LOP_INVOKE_DIRECT_RANGE_finish          @ no, continue
9086    b       common_exceptionThrown      @ yes, handle exception
9087
9088
9089/* continuation for OP_FLOAT_TO_LONG */
9090/*
9091 * Convert the float in r0 to a long in r0/r1.
9092 *
9093 * We have to clip values to long min/max per the specification.  The
9094 * expected common case is a "reasonable" value that converts directly
9095 * to modest integer.  The EABI convert function isn't doing this for us.
9096 */
9097f2l_doconv:
9098    stmfd   sp!, {r4, lr}
9099    mov     r1, #0x5f000000             @ (float)maxlong
9100    mov     r4, r0
9101    bl      __aeabi_fcmpge              @ is arg >= maxlong?
9102    cmp     r0, #0                      @ nonzero == yes
9103    mvnne   r0, #0                      @ return maxlong (7fffffff)
9104    mvnne   r1, #0x80000000
9105    ldmnefd sp!, {r4, pc}
9106
9107    mov     r0, r4                      @ recover arg
9108    mov     r1, #0xdf000000             @ (float)minlong
9109    bl      __aeabi_fcmple              @ is arg <= minlong?
9110    cmp     r0, #0                      @ nonzero == yes
9111    movne   r0, #0                      @ return minlong (80000000)
9112    movne   r1, #0x80000000
9113    ldmnefd sp!, {r4, pc}
9114
9115    mov     r0, r4                      @ recover arg
9116    mov     r1, r4
9117    bl      __aeabi_fcmpeq              @ is arg == self?
9118    cmp     r0, #0                      @ zero == no
9119    moveq   r1, #0                      @ return zero for NaN
9120    ldmeqfd sp!, {r4, pc}
9121
9122    mov     r0, r4                      @ recover arg
9123    bl      __aeabi_f2lz                @ convert float to long
9124    ldmfd   sp!, {r4, pc}
9125
9126
9127/* continuation for OP_DOUBLE_TO_LONG */
9128/*
9129 * Convert the double in r0/r1 to a long in r0/r1.
9130 *
9131 * We have to clip values to long min/max per the specification.  The
9132 * expected common case is a "reasonable" value that converts directly
9133 * to modest integer.  The EABI convert function isn't doing this for us.
9134 */
9135d2l_doconv:
9136    stmfd   sp!, {r4, r5, lr}           @ save regs
9137    ldr     r3, .LOP_DOUBLE_TO_LONG_max         @ (double)maxlong, hi
9138    sub     sp, sp, #4                  @ align for EABI
9139    mov     r2, #0                      @ (double)maxlong, lo
9140    mov     r4, r0                      @ save r0
9141    mov     r5, r1                      @  and r1
9142    bl      __aeabi_dcmpge              @ is arg >= maxlong?
9143    cmp     r0, #0                      @ nonzero == yes
9144    mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
9145    mvnne   r1, #0x80000000
9146    bne     1f
9147
9148    mov     r0, r4                      @ recover arg
9149    mov     r1, r5
9150    ldr     r3, .LOP_DOUBLE_TO_LONG_min         @ (double)minlong, hi
9151    mov     r2, #0                      @ (double)minlong, lo
9152    bl      __aeabi_dcmple              @ is arg <= minlong?
9153    cmp     r0, #0                      @ nonzero == yes
9154    movne   r0, #0                      @ return minlong (8000000000000000)
9155    movne   r1, #0x80000000
9156    bne     1f
9157
9158    mov     r0, r4                      @ recover arg
9159    mov     r1, r5
9160    mov     r2, r4                      @ compare against self
9161    mov     r3, r5
9162    bl      __aeabi_dcmpeq              @ is arg == self?
9163    cmp     r0, #0                      @ zero == no
9164    moveq   r1, #0                      @ return zero for NaN
9165    beq     1f
9166
9167    mov     r0, r4                      @ recover arg
9168    mov     r1, r5
9169    bl      __aeabi_d2lz                @ convert double to long
9170
91711:
9172    add     sp, sp, #4
9173    ldmfd   sp!, {r4, r5, pc}
9174
9175.LOP_DOUBLE_TO_LONG_max:
9176    .word   0x43e00000                  @ maxlong, as a double (high word)
9177.LOP_DOUBLE_TO_LONG_min:
9178    .word   0xc3e00000                  @ minlong, as a double (high word)
9179
9180
9181/* continuation for OP_MUL_LONG */
9182
9183.LOP_MUL_LONG_finish:
9184    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9185    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
9186    GOTO_OPCODE(ip)                     @ jump to next instruction
9187
9188
9189/* continuation for OP_SHL_LONG */
9190
9191.LOP_SHL_LONG_finish:
9192    mov     r0, r0, asl r2              @  r0<- r0 << r2
9193    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9194    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9195    GOTO_OPCODE(ip)                     @ jump to next instruction
9196
9197
9198/* continuation for OP_SHR_LONG */
9199
9200.LOP_SHR_LONG_finish:
9201    mov     r1, r1, asr r2              @  r1<- r1 >> r2
9202    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9203    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9204    GOTO_OPCODE(ip)                     @ jump to next instruction
9205
9206
9207/* continuation for OP_USHR_LONG */
9208
9209.LOP_USHR_LONG_finish:
9210    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
9211    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9212    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9213    GOTO_OPCODE(ip)                     @ jump to next instruction
9214
9215
9216/* continuation for OP_SHL_LONG_2ADDR */
9217
9218.LOP_SHL_LONG_2ADDR_finish:
9219    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9220    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9221    GOTO_OPCODE(ip)                     @ jump to next instruction
9222
9223
9224/* continuation for OP_SHR_LONG_2ADDR */
9225
9226.LOP_SHR_LONG_2ADDR_finish:
9227    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9228    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9229    GOTO_OPCODE(ip)                     @ jump to next instruction
9230
9231
9232/* continuation for OP_USHR_LONG_2ADDR */
9233
9234.LOP_USHR_LONG_2ADDR_finish:
9235    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9236    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9237    GOTO_OPCODE(ip)                     @ jump to next instruction
9238
9239
9240/* continuation for OP_EXECUTE_INLINE */
9241
9242    /*
9243     * Extract args, call function.
9244     *  r0 = #of args (0-4)
9245     *  r10 = call index
9246     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
9247     *
9248     * Other ideas:
9249     * - Use a jump table from the main piece to jump directly into the
9250     *   AND/LDR pairs.  Costs a data load, saves a branch.
9251     * - Have five separate pieces that do the loading, so we can work the
9252     *   interleave a little better.  Increases code size.
9253     */
9254.LOP_EXECUTE_INLINE_continue:
9255    rsb     r0, r0, #4                  @ r0<- 4-r0
9256    FETCH(r9, 2)                        @ r9<- FEDC
9257    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
9258    bl      common_abort                @ (skipped due to ARM prefetch)
92594:  and     ip, r9, #0xf000             @ isolate F
9260    ldr     r3, [rFP, ip, lsr #10]      @ r3<- vF (shift right 12, left 2)
92613:  and     ip, r9, #0x0f00             @ isolate E
9262    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vE
92632:  and     ip, r9, #0x00f0             @ isolate D
9264    ldr     r1, [rFP, ip, lsr #2]       @ r1<- vD
92651:  and     ip, r9, #0x000f             @ isolate C
9266    ldr     r0, [rFP, ip, lsl #2]       @ r0<- vC
92670:
9268    ldr     r9, .LOP_EXECUTE_INLINE_table       @ table of InlineOperation
9269    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
9270    @ (not reached)
9271
9272.LOP_EXECUTE_INLINE_table:
9273    .word   gDvmInlineOpsTable
9274
9275
9276    .size   dvmAsmSisterStart, .-dvmAsmSisterStart
9277    .global dvmAsmSisterEnd
9278dvmAsmSisterEnd:
9279
9280/* File: armv5te/footer.S */
9281/*
9282 * ===========================================================================
9283 *  Common subroutines and data
9284 * ===========================================================================
9285 */
9286
9287    .text
9288    .align  2
9289
9290/*
9291 * Common code when a backward branch is taken.
9292 *
9293 * On entry:
9294 *  r9 is PC adjustment *in bytes*
9295 */
9296common_backwardBranch:
9297    mov     r0, #kInterpEntryInstr
9298    bl      common_periodicChecks
9299    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9300    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9301    GOTO_OPCODE(ip)                     @ jump to next instruction
9302
9303
9304/*
9305 * Need to see if the thread needs to be suspended or debugger/profiler
9306 * activity has begun.
9307 *
9308 * TODO: if JDWP isn't running, zero out pDebuggerActive pointer so we don't
9309 * have to do the second ldr.
9310 *
9311 * TODO: reduce this so we're just checking a single location.
9312 *
9313 * On entry:
9314 *  r0 is reentry type, e.g. kInterpEntryInstr
9315 *  r9 is trampoline PC adjustment *in bytes*
9316 */
9317common_periodicChecks:
9318    ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
9319
9320#if defined(WITH_DEBUGGER)
9321    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9322#endif
9323#if defined(WITH_PROFILER)
9324    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9325#endif
9326
9327    ldr     r3, [r3]                    @ r3<- suspendCount (int)
9328
9329#if defined(WITH_DEBUGGER)
9330    ldrb    r1, [r1]                    @ r1<- debuggerActive (boolean)
9331#endif
9332#if defined (WITH_PROFILER)
9333    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9334#endif
9335
9336    cmp     r3, #0                      @ suspend pending?
9337    bne     2f                          @ yes, do full suspension check
9338
9339#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
9340# if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
9341    orrs    r1, r1, r2                  @ r1<- r1 | r2
9342    cmp     r1, #0                      @ debugger attached or profiler started?
9343# elif defined(WITH_DEBUGGER)
9344    cmp     r1, #0                      @ debugger attached?
9345# elif defined(WITH_PROFILER)
9346    cmp     r2, #0                      @ profiler started?
9347# endif
9348    bne     3f                          @ debugger/profiler, switch interp
9349#endif
9350
9351    bx      lr                          @ nothing to do, return
9352
93532:  @ check suspend
9354    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9355    EXPORT_PC()                         @ need for precise GC
9356    b       dvmCheckSuspendPending      @ suspend if necessary, then return
9357
93583:  @ debugger/profiler enabled, bail out
9359    add     rPC, rPC, r9                @ update rPC
9360    str     r0, [rGLUE, #offGlue_entryPoint]
9361    mov     r1, #1                      @ "want switch" = true
9362    b       common_gotoBail
9363
9364
9365/*
9366 * The equivalent of "goto bail", this calls through the "bail handler".
9367 *
9368 * State registers will be saved to the "glue" area before bailing.
9369 *
9370 * On entry:
9371 *  r1 is "bool changeInterp", indicating if we want to switch to the
9372 *     other interpreter or just bail all the way out
9373 */
9374common_gotoBail:
9375    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9376    mov     r0, rGLUE                   @ r0<- glue ptr
9377    b       dvmMterpStdBail             @ call(glue, changeInterp)
9378
9379    @add     r1, r1, #1                  @ using (boolean+1)
9380    @add     r0, rGLUE, #offGlue_jmpBuf  @ r0<- &glue->jmpBuf
9381    @bl      _longjmp                    @ does not return
9382    @bl      common_abort
9383
9384
9385/*
9386 * Common code for method invocation with range.
9387 *
9388 * On entry:
9389 *  r0 is "Method* methodToCall", the method we're trying to call
9390 */
9391common_invokeMethodRange:
9392.LinvokeNewRange:
9393    @ prepare to copy args to "outs" area of current frame
9394    movs    r2, rINST, lsr #8           @ r2<- AA (arg count) -- test for zero
9395    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9396    beq     .LinvokeArgsDone            @ if no args, skip the rest
9397    FETCH(r1, 2)                        @ r1<- CCCC
9398
9399    @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
9400    @ (very few methods have > 10 args; could unroll for common cases)
9401    add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
9402    sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
94031:  ldr     r1, [r3], #4                @ val = *fp++
9404    subs    r2, r2, #1                  @ count--
9405    str     r1, [r10], #4               @ *outs++ = val
9406    bne     1b                          @ ...while count != 0
9407    b       .LinvokeArgsDone
9408
9409/*
9410 * Common code for method invocation without range.
9411 *
9412 * On entry:
9413 *  r0 is "Method* methodToCall", the method we're trying to call
9414 */
9415common_invokeMethodNoRange:
9416.LinvokeNewNoRange:
9417    @ prepare to copy args to "outs" area of current frame
9418    movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
9419    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9420    beq     .LinvokeArgsDone            @ if no args, skip the rest
9421    FETCH(r1, 2)                        @ r1<- GFED
9422
9423    @ r0=methodToCall, r1=GFED, r2=count, r10=outs
9424.LinvokeNonRange:
9425    rsb     r2, r2, #5                  @ r2<- 5-r2
9426    add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
9427    bl      common_abort                @ (skipped due to ARM prefetch)
94285:  and     ip, rINST, #0x0f00          @ isolate A
9429    ldr     r3, [rFP, ip, lsr #6]       @ r3<- vA (shift right 8, left 2)
9430    mov     r0, r0                      @ nop
9431    str     r3, [r10, #-4]!             @ *--outs = vA
94324:  and     ip, r1, #0xf000             @ isolate G
9433    ldr     r3, [rFP, ip, lsr #10]      @ r3<- vG (shift right 12, left 2)
9434    mov     r0, r0                      @ nop
9435    str     r3, [r10, #-4]!             @ *--outs = vG
94363:  and     ip, r1, #0x0f00             @ isolate F
9437    ldr     r3, [rFP, ip, lsr #6]       @ r3<- vF
9438    mov     r0, r0                      @ nop
9439    str     r3, [r10, #-4]!             @ *--outs = vF
94402:  and     ip, r1, #0x00f0             @ isolate E
9441    ldr     r3, [rFP, ip, lsr #2]       @ r3<- vE
9442    mov     r0, r0                      @ nop
9443    str     r3, [r10, #-4]!             @ *--outs = vE
94441:  and     ip, r1, #0x000f             @ isolate D
9445    ldr     r3, [rFP, ip, lsl #2]       @ r3<- vD
9446    mov     r0, r0                      @ nop
9447    str     r3, [r10, #-4]!             @ *--outs = vD
94480:  @ fall through to .LinvokeArgsDone
9449
9450.LinvokeArgsDone: @ r0=methodToCall
9451    @ find space for the new stack frame, check for overflow
9452    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
9453    ldrh    r2, [r0, #offMethod_registersSize]  @ r2<- methodToCall->regsSize
9454    ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
9455    sub     r1, r1, r2, lsl #2          @ r1<- newFp (old savearea - regsSize)
9456    SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
9457@    bl      common_dumpRegs
9458    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
9459    sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
9460    cmp     r3, r9                      @ bottom < interpStackEnd?
9461    blt     .LstackOverflow             @ yes, this frame will overflow stack
9462
9463    @ set up newSaveArea
9464#ifdef EASY_GDB
9465    SAVEAREA_FROM_FP(ip, rFP)           @ ip<- stack save area
9466    str     ip, [r10, #offStackSaveArea_prevSave]
9467#endif
9468    str     rFP, [r10, #offStackSaveArea_prevFrame]
9469    str     rPC, [r10, #offStackSaveArea_savedPc]
9470    str     r0, [r10, #offStackSaveArea_method]
9471
9472    ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
9473    tst     r3, #ACC_NATIVE
9474    bne     .LinvokeNative
9475
9476    /*
9477    stmfd   sp!, {r0-r3}
9478    bl      common_printNewline
9479    mov     r0, rFP
9480    mov     r1, #0
9481    bl      dvmDumpFp
9482    ldmfd   sp!, {r0-r3}
9483    stmfd   sp!, {r0-r3}
9484    mov     r0, r1
9485    mov     r1, r10
9486    bl      dvmDumpFp
9487    bl      common_printNewline
9488    ldmfd   sp!, {r0-r3}
9489    */
9490
9491    @ Update "glue" values for the new method
9492    @ r0=methodToCall, r1=newFp
9493    ldr     r3, [r0, #offMethod_clazz]      @ r3<- method->clazz
9494    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
9495    ldr     r3, [r3, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
9496    ldr     rPC, [r0, #offMethod_insns]     @ rPC<- method->insns
9497    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
9498    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
9499    FETCH_INST()                            @ load rINST from rPC
9500    mov     rFP, r1                         @ fp = newFp
9501    GET_INST_OPCODE(ip)                     @ extract opcode from rINST
9502    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
9503    GOTO_OPCODE(ip)                         @ jump to next instruction
9504
9505.LinvokeNative:
9506    @ Prep for the native call
9507    @ r0=methodToCall, r1=newFp, r10=newSaveArea
9508    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
9509    ldr     r9, [r3, #offThread_jniLocal_nextEntry] @ r9<- thread->refNext
9510    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
9511    str     r9, [r10, #offStackSaveArea_localRefTop] @newFp->localRefTop=refNext
9512    mov     r9, r3                      @ r9<- glue->self (preserve)
9513
9514    mov     r2, r0                      @ r2<- methodToCall
9515    mov     r0, r1                      @ r0<- newFp (points to args)
9516    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
9517
9518#ifdef ASSIST_DEBUGGER
9519    /* insert fake function header to help gdb find the stack frame */
9520    b       .Lskip
9521    .type   dalvik_mterp, %function
9522dalvik_mterp:
9523    .fnstart
9524    MTERP_ENTRY1
9525    MTERP_ENTRY2
9526.Lskip:
9527#endif
9528
9529    @mov     lr, pc                      @ set return addr
9530    @ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
9531    LDR_PC_LR "[r2, #offMethod_nativeFunc]"
9532
9533    @ native return; r9=self, r10=newSaveArea
9534    @ equivalent to dvmPopJniLocals
9535    ldr     r0, [r10, #offStackSaveArea_localRefTop] @ r0<- newSave->localRefTop
9536    ldr     r1, [r9, #offThread_exception] @ check for exception
9537    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
9538    cmp     r1, #0                      @ null?
9539    str     r0, [r9, #offThread_jniLocal_nextEntry] @ self->refNext<- r0
9540    bne     common_exceptionThrown      @ no, handle exception
9541
9542    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
9543    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9544    GOTO_OPCODE(ip)                     @ jump to next instruction
9545
9546.LstackOverflow:
9547    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
9548    bl      dvmHandleStackOverflow
9549    b       common_exceptionThrown
9550#ifdef ASSIST_DEBUGGER
9551    .fnend
9552#endif
9553
9554
9555    /*
9556     * Common code for method invocation, calling through "glue code".
9557     *
9558     * TODO: now that we have range and non-range invoke handlers, this
9559     *       needs to be split into two.  Maybe just create entry points
9560     *       that set r9 and jump here?
9561     *
9562     * On entry:
9563     *  r0 is "Method* methodToCall", the method we're trying to call
9564     *  r9 is "bool methodCallRange", indicating if this is a /range variant
9565     */
9566     .if    0
9567.LinvokeOld:
9568    sub     sp, sp, #8                  @ space for args + pad
9569    FETCH(ip, 2)                        @ ip<- FEDC or CCCC
9570    mov     r2, r0                      @ A2<- methodToCall
9571    mov     r0, rGLUE                   @ A0<- glue
9572    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9573    mov     r1, r9                      @ A1<- methodCallRange
9574    mov     r3, rINST, lsr #8           @ A3<- AA
9575    str     ip, [sp, #0]                @ A4<- ip
9576    bl      dvmMterp_invokeMethod       @ call the C invokeMethod
9577    add     sp, sp, #8                  @ remove arg area
9578    b       common_resumeAfterGlueCall  @ continue to next instruction
9579    .endif
9580
9581
9582
9583/*
9584 * Common code for handling a return instruction.
9585 *
9586 * This does not return.
9587 */
9588common_returnFromMethod:
9589.LreturnNew:
9590    mov     r0, #kInterpEntryReturn
9591    mov     r9, #0
9592    bl      common_periodicChecks
9593
9594    SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
9595    ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
9596    ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
9597                                        @ r2<- method we're returning to
9598    cmp     r2, #0                      @ is this a break frame?
9599    mov     r1, #0                      @ "want switch" = false
9600    beq     common_gotoBail             @ break frame, bail out completely
9601
9602    ldr     rPC, [r0, #offStackSaveArea_savedPc] @ pc = saveArea->savedPc
9603    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
9604    str     r2, [rGLUE, #offGlue_method]    @ glue->method = newSave->method
9605    str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
9606    ldr     r1, [r2, #offMethod_clazz]      @ r1<- method->clazz
9607    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
9608    ldr     r1, [r1, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
9609    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9610    str     r1, [rGLUE, #offGlue_methodClassDex]
9611    GOTO_OPCODE(ip)                     @ jump to next instruction
9612
9613    /*
9614     * Return handling, calls through "glue code".
9615     */
9616     .if    0
9617.LreturnOld:
9618    SAVE_PC_FP_TO_GLUE()                @ export state
9619    mov     r0, rGLUE                   @ arg to function
9620    bl      dvmMterp_returnFromMethod
9621    b       common_resumeAfterGlueCall
9622    .endif
9623
9624
9625/*
9626 * Somebody has thrown an exception.  Handle it.
9627 *
9628 * If the exception processing code returns to us (instead of falling
9629 * out of the interpreter), continue with whatever the next instruction
9630 * now happens to be.
9631 *
9632 * This does not return.
9633 */
9634common_exceptionThrown:
9635.LexceptionNew:
9636    mov     r0, #kInterpEntryThrow
9637    mov     r9, #0
9638    bl      common_periodicChecks
9639
9640    ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
9641    ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
9642    mov     r1, r10                     @ r1<- self
9643    mov     r0, r9                      @ r0<- exception
9644    bl      dvmAddTrackedAlloc          @ don't let the exception be GCed
9645    mov     r3, #0                      @ r3<- NULL
9646    str     r3, [r10, #offThread_exception] @ self->exception = NULL
9647
9648    /* set up args and a local for "&fp" */
9649    /* (str sp, [sp, #-4]!  would be perfect here, but is discouraged) */
9650    str     rFP, [sp, #-4]!             @ *--sp = fp
9651    mov     ip, sp                      @ ip<- &fp
9652    mov     r3, #0                      @ r3<- false
9653    str     ip, [sp, #-4]!              @ *--sp = &fp
9654    ldr     r1, [rGLUE, #offGlue_method] @ r1<- glue->method
9655    mov     r0, r10                     @ r0<- self
9656    ldr     r1, [r1, #offMethod_insns]  @ r1<- method->insns
9657    mov     r2, r9                      @ r2<- exception
9658    sub     r1, rPC, r1                 @ r1<- pc - method->insns
9659    mov     r1, r1, asr #1              @ r1<- offset in code units
9660
9661    /* call, r0 gets catchRelPc (a code-unit offset) */
9662    bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
9663
9664    /* fix earlier stack overflow if necessary; may trash rFP */
9665    ldrb    r1, [r10, #offThread_stackOverflowed]
9666    cmp     r1, #0                      @ did we overflow earlier?
9667    beq     1f                          @ no, skip ahead
9668    mov     rFP, r0                     @ save relPc result in rFP
9669    mov     r0, r10                     @ r0<- self
9670    bl      dvmCleanupStackOverflow     @ call(self)
9671    mov     r0, rFP                     @ restore result
96721:
9673
9674    /* update frame pointer and check result from dvmFindCatchBlock */
9675    ldr     rFP, [sp, #4]               @ retrieve the updated rFP
9676    cmp     r0, #0                      @ is catchRelPc < 0?
9677    add     sp, sp, #8                  @ restore stack
9678    bmi     .LnotCaughtLocally
9679
9680    /* adjust locals to match self->curFrame and updated PC */
9681    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
9682    ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
9683    str     r1, [rGLUE, #offGlue_method]    @ glue->method = new method
9684    ldr     r2, [r1, #offMethod_clazz]      @ r2<- method->clazz
9685    ldr     r3, [r1, #offMethod_insns]      @ r3<- method->insns
9686    ldr     r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
9687    add     rPC, r3, r0, asl #1             @ rPC<- method->insns + catchRelPc
9688    str     r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
9689
9690    /* release the tracked alloc on the exception */
9691    mov     r0, r9                      @ r0<- exception
9692    mov     r1, r10                     @ r1<- self
9693    bl      dvmReleaseTrackedAlloc      @ release the exception
9694
9695    /* restore the exception if the handler wants it */
9696    FETCH_INST()                        @ load rINST from rPC
9697    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9698    cmp     ip, #OP_MOVE_EXCEPTION      @ is it "move-exception"?
9699    streq   r9, [r10, #offThread_exception] @ yes, restore the exception
9700    GOTO_OPCODE(ip)                     @ jump to next instruction
9701
9702.LnotCaughtLocally: @ r9=exception, r10=self
9703    /* fix stack overflow if necessary */
9704    ldrb    r1, [r10, #offThread_stackOverflowed]
9705    cmp     r1, #0                      @ did we overflow earlier?
9706    movne   r0, r10                     @ if yes: r0<- self
9707    blne    dvmCleanupStackOverflow     @ if yes: call(self)
9708
9709    @ may want to show "not caught locally" debug messages here
9710#if DVM_SHOW_EXCEPTION >= 2
9711    /* call __android_log_print(prio, tag, format, ...) */
9712    /* "Exception %s from %s:%d not caught locally" */
9713    @ dvmLineNumFromPC(method, pc - method->insns)
9714    ldr     r0, [rGLUE, #offGlue_method]
9715    ldr     r1, [r0, #offMethod_insns]
9716    sub     r1, rPC, r1
9717    asr     r1, r1, #1
9718    bl      dvmLineNumFromPC
9719    str     r0, [sp, #-4]!
9720    @ dvmGetMethodSourceFile(method)
9721    ldr     r0, [rGLUE, #offGlue_method]
9722    bl      dvmGetMethodSourceFile
9723    str     r0, [sp, #-4]!
9724    @ exception->clazz->descriptor
9725    ldr     r3, [r9, #offObject_clazz]
9726    ldr     r3, [r3, #offClassObject_descriptor]
9727    @
9728    ldr     r2, strExceptionNotCaughtLocally
9729    ldr     r1, strLogTag
9730    mov     r0, #3                      @ LOG_DEBUG
9731    bl      __android_log_print
9732#endif
9733    str     r9, [r10, #offThread_exception] @ restore exception
9734    mov     r0, r9                      @ r0<- exception
9735    mov     r1, r10                     @ r1<- self
9736    bl      dvmReleaseTrackedAlloc      @ release the exception
9737    mov     r1, #0                      @ "want switch" = false
9738    b       common_gotoBail             @ bail out
9739
9740
9741    /*
9742     * Exception handling, calls through "glue code".
9743     */
9744    .if     0
9745.LexceptionOld:
9746    SAVE_PC_FP_TO_GLUE()                @ export state
9747    mov     r0, rGLUE                   @ arg to function
9748    bl      dvmMterp_exceptionThrown
9749    b       common_resumeAfterGlueCall
9750    .endif
9751
9752
9753/*
9754 * After returning from a "glued" function, pull out the updated
9755 * values and start executing at the next instruction.
9756 */
9757common_resumeAfterGlueCall:
9758    LOAD_PC_FP_FROM_GLUE()              @ pull rPC and rFP out of glue
9759    FETCH_INST()                        @ load rINST from rPC
9760    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9761    GOTO_OPCODE(ip)                     @ jump to next instruction
9762
9763/*
9764 * Invalid array index.
9765 */
9766common_errArrayIndex:
9767    EXPORT_PC()
9768    ldr     r0, strArrayIndexException
9769    mov     r1, #0
9770    bl      dvmThrowException
9771    b       common_exceptionThrown
9772
9773/*
9774 * Invalid array value.
9775 */
9776common_errArrayStore:
9777    EXPORT_PC()
9778    ldr     r0, strArrayStoreException
9779    mov     r1, #0
9780    bl      dvmThrowException
9781    b       common_exceptionThrown
9782
9783/*
9784 * Integer divide or mod by zero.
9785 */
9786common_errDivideByZero:
9787    EXPORT_PC()
9788    ldr     r0, strArithmeticException
9789    ldr     r1, strDivideByZero
9790    bl      dvmThrowException
9791    b       common_exceptionThrown
9792
9793/*
9794 * Attempt to allocate an array with a negative size.
9795 */
9796common_errNegativeArraySize:
9797    EXPORT_PC()
9798    ldr     r0, strNegativeArraySizeException
9799    mov     r1, #0
9800    bl      dvmThrowException
9801    b       common_exceptionThrown
9802
9803/*
9804 * Invocation of a non-existent method.
9805 */
9806common_errNoSuchMethod:
9807    EXPORT_PC()
9808    ldr     r0, strNoSuchMethodError
9809    mov     r1, #0
9810    bl      dvmThrowException
9811    b       common_exceptionThrown
9812
9813/*
9814 * We encountered a null object when we weren't expecting one.  We
9815 * export the PC, throw a NullPointerException, and goto the exception
9816 * processing code.
9817 */
9818common_errNullObject:
9819    EXPORT_PC()
9820    ldr     r0, strNullPointerException
9821    mov     r1, #0
9822    bl      dvmThrowException
9823    b       common_exceptionThrown
9824
9825/*
9826 * For debugging, cause an immediate fault.  The source address will
9827 * be in lr (use a bl instruction to jump here).
9828 */
9829common_abort:
9830    ldr     pc, .LdeadFood
9831.LdeadFood:
9832    .word   0xdeadf00d
9833
9834/*
9835 * Spit out a "we were here", preserving all registers.  (The attempt
9836 * to save ip won't work, but we need to save an even number of
9837 * registers for EABI 64-bit stack alignment.)
9838 */
9839    .macro  SQUEAK num
9840common_squeak\num:
9841    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9842    ldr     r0, strSqueak
9843    mov     r1, #\num
9844    bl      printf
9845    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9846    bx      lr
9847    .endm
9848
9849    SQUEAK  0
9850    SQUEAK  1
9851    SQUEAK  2
9852    SQUEAK  3
9853    SQUEAK  4
9854    SQUEAK  5
9855
9856/*
9857 * Spit out the number in r0, preserving registers.
9858 */
9859common_printNum:
9860    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9861    mov     r1, r0
9862    ldr     r0, strSqueak
9863    bl      printf
9864    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9865    bx      lr
9866
9867/*
9868 * Print a newline, preserving registers.
9869 */
9870common_printNewline:
9871    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9872    ldr     r0, strNewline
9873    bl      printf
9874    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9875    bx      lr
9876
9877    /*
9878     * Print the 32-bit quantity in r0 as a hex value, preserving registers.
9879     */
9880common_printHex:
9881    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9882    mov     r1, r0
9883    ldr     r0, strPrintHex
9884    bl      printf
9885    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9886    bx      lr
9887
9888/*
9889 * Print the 64-bit quantity in r0-r1, preserving registers.
9890 */
9891common_printLong:
9892    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9893    mov     r3, r1
9894    mov     r2, r0
9895    ldr     r0, strPrintLong
9896    bl      printf
9897    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9898    bx      lr
9899
9900/*
9901 * Print full method info.  Pass the Method* in r0.  Preserves regs.
9902 */
9903common_printMethod:
9904    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9905    bl      dvmMterpPrintMethod
9906    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9907    bx      lr
9908
9909/*
9910 * Call a C helper function that dumps regs and possibly some
9911 * additional info.  Requires the C function to be compiled in.
9912 */
9913    .if     0
9914common_dumpRegs:
9915    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9916    bl      dvmMterpDumpArmRegs
9917    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9918    bx      lr
9919    .endif
9920
9921
9922/*
9923 * String references, must be close to the code that uses them.
9924 */
9925    .align  2
9926strArithmeticException:
9927    .word   .LstrArithmeticException
9928strArrayIndexException:
9929    .word   .LstrArrayIndexException
9930strArrayStoreException:
9931    .word   .LstrArrayStoreException
9932strDivideByZero:
9933    .word   .LstrDivideByZero
9934strNegativeArraySizeException:
9935    .word   .LstrNegativeArraySizeException
9936strNoSuchMethodError:
9937    .word   .LstrNoSuchMethodError
9938strNullPointerException:
9939    .word   .LstrNullPointerException
9940
9941strLogTag:
9942    .word   .LstrLogTag
9943strExceptionNotCaughtLocally:
9944    .word   .LstrExceptionNotCaughtLocally
9945
9946strNewline:
9947    .word   .LstrNewline
9948strSqueak:
9949    .word   .LstrSqueak
9950strPrintHex:
9951    .word   .LstrPrintHex
9952strPrintLong:
9953    .word   .LstrPrintLong
9954
9955/*
9956 * Zero-terminated ASCII string data.
9957 *
9958 * On ARM we have two choices: do like gcc does, and LDR from a .word
9959 * with the address, or use an ADR pseudo-op to get the address
9960 * directly.  ADR saves 4 bytes and an indirection, but it's using a
9961 * PC-relative addressing mode and hence has a limited range, which
9962 * makes it not work well with mergeable string sections.
9963 */
9964    .section .rodata.str1.4,"aMS",%progbits,1
9965
9966.LstrBadEntryPoint:
9967    .asciz  "Bad entry point %d\n"
9968.LstrArithmeticException:
9969    .asciz  "Ljava/lang/ArithmeticException;"
9970.LstrArrayIndexException:
9971    .asciz  "Ljava/lang/ArrayIndexOutOfBoundsException;"
9972.LstrArrayStoreException:
9973    .asciz  "Ljava/lang/ArrayStoreException;"
9974.LstrClassCastException:
9975    .asciz  "Ljava/lang/ClassCastException;"
9976.LstrDivideByZero:
9977    .asciz  "divide by zero"
9978.LstrFilledNewArrayNotImpl:
9979    .asciz  "filled-new-array only implemented for objects and 'int'"
9980.LstrInternalError:
9981    .asciz  "Ljava/lang/InternalError;"
9982.LstrInstantiationError:
9983    .asciz  "Ljava/lang/InstantiationError;"
9984.LstrNegativeArraySizeException:
9985    .asciz  "Ljava/lang/NegativeArraySizeException;"
9986.LstrNoSuchMethodError:
9987    .asciz  "Ljava/lang/NoSuchMethodError;"
9988.LstrNullPointerException:
9989    .asciz  "Ljava/lang/NullPointerException;"
9990
9991.LstrLogTag:
9992    .asciz  "mterp"
9993.LstrExceptionNotCaughtLocally:
9994    .asciz  "Exception %s from %s:%d not caught locally\n"
9995
9996.LstrNewline:
9997    .asciz  "\n"
9998.LstrSqueak:
9999    .asciz  "<%d>"
10000.LstrPrintHex:
10001    .asciz  "<0x%x>"
10002.LstrPrintLong:
10003    .asciz  "<%lld>"
10004
10005
10006