InterpAsm-armv4t.S revision 3a1aedbc9777eab6275a360b93b81b079464238e
1/*
2 * This file was generated automatically by gen-mterp.py for 'armv4t'.
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 * The operation performed here is similar to FETCH_ADVANCE_INST, except the
128 * src and dest registers are parameterized (not hard-wired to rPC and rINST).
129 */
130#define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \
131        ldrh    _dreg, [_sreg, #(_count*2)]!
132
133/*
134 * Fetch the next instruction from an offset specified by _reg.  Updates
135 * rPC to point to the next instruction.  "_reg" must specify the distance
136 * in bytes, *not* 16-bit code units, and may be a signed value.
137 *
138 * We want to write "ldrh rINST, [rPC, _reg, lsl #2]!", but some of the
139 * bits that hold the shift distance are used for the half/byte/sign flags.
140 * In some cases we can pre-double _reg for free, so we require a byte offset
141 * here.
142 */
143#define FETCH_ADVANCE_INST_RB(_reg) ldrh    rINST, [rPC, _reg]!
144
145/*
146 * Fetch a half-word code unit from an offset past the current PC.  The
147 * "_count" value is in 16-bit code units.  Does not advance rPC.
148 *
149 * The "_S" variant works the same but treats the value as signed.
150 */
151#define FETCH(_reg, _count)     ldrh    _reg, [rPC, #(_count*2)]
152#define FETCH_S(_reg, _count)   ldrsh   _reg, [rPC, #(_count*2)]
153
154/*
155 * Fetch one byte from an offset past the current PC.  Pass in the same
156 * "_count" as you would for FETCH, and an additional 0/1 indicating which
157 * byte of the halfword you want (lo/hi).
158 */
159#define FETCH_B(_reg, _count, _byte) ldrb     _reg, [rPC, #(_count*2+_byte)]
160
161/*
162 * Put the instruction's opcode field into the specified register.
163 */
164#define GET_INST_OPCODE(_reg)   and     _reg, rINST, #255
165
166/*
167 * Put the prefetched instruction's opcode field into the specified register.
168 */
169#define GET_PREFETCHED_OPCODE(_oreg, _ireg)   and     _oreg, _ireg, #255
170
171/*
172 * Begin executing the opcode in _reg.  Because this only jumps within the
173 * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork.
174 */
175#define GOTO_OPCODE(_reg)       add     pc, rIBASE, _reg, lsl #6
176
177/*
178 * Get/set the 32-bit value from a Dalvik register.
179 */
180#define GET_VREG(_reg, _vreg)   ldr     _reg, [rFP, _vreg, lsl #2]
181#define SET_VREG(_reg, _vreg)   str     _reg, [rFP, _vreg, lsl #2]
182
183/*
184 * This is a #include, not a %include, because we want the C pre-processor
185 * to expand the macros into assembler assignment statements.
186 */
187#include "../common/asm-constants.h"
188
189
190/* File: armv5te/platform.S */
191/*
192 * ===========================================================================
193 *  CPU-version-specific defines
194 * ===========================================================================
195 */
196
197/*
198 * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5.  Essentially a
199 * one-way branch.
200 *
201 * May modify IP.  Does not modify LR.
202 */
203.macro  LDR_PC source
204    ldr     pc, \source
205.endm
206
207/*
208 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5.
209 * Jump to subroutine.
210 *
211 * May modify IP and LR.
212 */
213.macro  LDR_PC_LR source
214    mov     lr, pc
215    ldr     pc, \source
216.endm
217
218/*
219 * Macro for "LDMFD SP!, {...regs...,PC}".
220 *
221 * May modify IP and LR.
222 */
223.macro  LDMFD_PC regs
224    ldmfd   sp!, {\regs,pc}
225.endm
226
227
228/* File: armv5te/entry.S */
229/*
230 * Copyright (C) 2008 The Android Open Source Project
231 *
232 * Licensed under the Apache License, Version 2.0 (the "License");
233 * you may not use this file except in compliance with the License.
234 * You may obtain a copy of the License at
235 *
236 *      http://www.apache.org/licenses/LICENSE-2.0
237 *
238 * Unless required by applicable law or agreed to in writing, software
239 * distributed under the License is distributed on an "AS IS" BASIS,
240 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
241 * See the License for the specific language governing permissions and
242 * limitations under the License.
243 */
244/*
245 * Interpreter entry point.
246 */
247
248/*
249 * We don't have formal stack frames, so gdb scans upward in the code
250 * to find the start of the function (a label with the %function type),
251 * and then looks at the next few instructions to figure out what
252 * got pushed onto the stack.  From this it figures out how to restore
253 * the registers, including PC, for the previous stack frame.  If gdb
254 * sees a non-function label, it stops scanning, so either we need to
255 * have nothing but assembler-local labels between the entry point and
256 * the break, or we need to fake it out.
257 *
258 * When this is defined, we add some stuff to make gdb less confused.
259 */
260#define ASSIST_DEBUGGER 1
261
262    .text
263    .align  2
264    .global dvmMterpStdRun
265    .type   dvmMterpStdRun, %function
266
267/*
268 * On entry:
269 *  r0  MterpGlue* glue
270 *
271 * This function returns a boolean "changeInterp" value.  The return comes
272 * via a call to dvmMterpStdBail().
273 */
274dvmMterpStdRun:
275#define MTERP_ENTRY1 \
276    .save {r4-r10,fp,lr}; \
277    stmfd   sp!, {r4-r10,fp,lr}         @ save 9 regs
278#define MTERP_ENTRY2 \
279    .pad    #4; \
280    sub     sp, sp, #4                  @ align 64
281
282    .fnstart
283    MTERP_ENTRY1
284    MTERP_ENTRY2
285
286    /* save stack pointer, add magic word for debuggerd */
287    str     sp, [r0, #offGlue_bailPtr]  @ save SP for eventual return
288
289    /* set up "named" registers, figure out entry point */
290    mov     rGLUE, r0                   @ set rGLUE
291    ldrb    r1, [r0, #offGlue_entryPoint]   @ InterpEntry enum is char
292    LOAD_PC_FP_FROM_GLUE()              @ load rPC and rFP from "glue"
293    adr     rIBASE, dvmAsmInstructionStart  @ set rIBASE
294    cmp     r1, #kInterpEntryInstr      @ usual case?
295    bne     .Lnot_instr                 @ no, handle it
296
297    /* start executing the instruction at rPC */
298    FETCH_INST()                        @ load rINST from rPC
299    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
300    GOTO_OPCODE(ip)                     @ jump to next instruction
301
302.Lnot_instr:
303    cmp     r1, #kInterpEntryReturn     @ were we returning from a method?
304    beq     common_returnFromMethod
305
306.Lnot_return:
307    cmp     r1, #kInterpEntryThrow      @ were we throwing an exception?
308    beq     common_exceptionThrown
309
310.Lbad_arg:
311    ldr     r0, strBadEntryPoint
312    @ r1 holds value of entryPoint
313    bl      printf
314    bl      dvmAbort
315    .fnend
316
317
318    .global dvmMterpStdBail
319    .type   dvmMterpStdBail, %function
320
321/*
322 * Restore the stack pointer and PC from the save point established on entry.
323 * This is essentially the same as a longjmp, but should be cheaper.  The
324 * last instruction causes us to return to whoever called dvmMterpStdRun.
325 *
326 * We pushed some registers on the stack in dvmMterpStdRun, then saved
327 * SP and LR.  Here we restore SP, restore the registers, and then restore
328 * LR to PC.
329 *
330 * On entry:
331 *  r0  MterpGlue* glue
332 *  r1  bool changeInterp
333 */
334dvmMterpStdBail:
335    ldr     sp, [r0, #offGlue_bailPtr]      @ sp<- saved SP
336    mov     r0, r1                          @ return the changeInterp value
337    add     sp, sp, #4                      @ un-align 64
338    LDMFD_PC "r4-r10,fp"                    @ restore 9 regs and return
339
340
341/*
342 * String references.
343 */
344strBadEntryPoint:
345    .word   .LstrBadEntryPoint
346
347
348
349    .global dvmAsmInstructionStart
350    .type   dvmAsmInstructionStart, %function
351dvmAsmInstructionStart = .L_OP_NOP
352    .text
353
354/* ------------------------------ */
355    .balign 64
356.L_OP_NOP: /* 0x00 */
357/* File: armv5te/OP_NOP.S */
358    FETCH_ADVANCE_INST(1)               @ advance to next instr, load rINST
359    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
360    GOTO_OPCODE(ip)                     @ execute it
361
362#ifdef ASSIST_DEBUGGER
363    /* insert fake function header to help gdb find the stack frame */
364    .type   dalvik_inst, %function
365dalvik_inst:
366    .fnstart
367    MTERP_ENTRY1
368    MTERP_ENTRY2
369    .fnend
370#endif
371
372
373/* ------------------------------ */
374    .balign 64
375.L_OP_MOVE: /* 0x01 */
376/* File: armv5te/OP_MOVE.S */
377    /* for move, move-object, long-to-int */
378    /* op vA, vB */
379    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
380    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
381    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
382    GET_VREG(r2, r1)                    @ r2<- fp[B]
383    and     r0, r0, #15
384    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
385    SET_VREG(r2, r0)                    @ fp[A]<- r2
386    GOTO_OPCODE(ip)                     @ execute next instruction
387
388
389/* ------------------------------ */
390    .balign 64
391.L_OP_MOVE_FROM16: /* 0x02 */
392/* File: armv5te/OP_MOVE_FROM16.S */
393    /* for: move/from16, move-object/from16 */
394    /* op vAA, vBBBB */
395    FETCH(r1, 1)                        @ r1<- BBBB
396    mov     r0, rINST, lsr #8           @ r0<- AA
397    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
398    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
399    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
400    SET_VREG(r2, r0)                    @ fp[AA]<- r2
401    GOTO_OPCODE(ip)                     @ jump to next instruction
402
403
404/* ------------------------------ */
405    .balign 64
406.L_OP_MOVE_16: /* 0x03 */
407/* File: armv5te/OP_MOVE_16.S */
408    /* for: move/16, move-object/16 */
409    /* op vAAAA, vBBBB */
410    FETCH(r1, 2)                        @ r1<- BBBB
411    FETCH(r0, 1)                        @ r0<- AAAA
412    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
413    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
414    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
415    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
416    GOTO_OPCODE(ip)                     @ jump to next instruction
417
418
419/* ------------------------------ */
420    .balign 64
421.L_OP_MOVE_WIDE: /* 0x04 */
422/* File: armv5te/OP_MOVE_WIDE.S */
423    /* move-wide vA, vB */
424    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
425    mov     r2, rINST, lsr #8           @ r2<- A(+)
426    mov     r3, rINST, lsr #12          @ r3<- B
427    and     r2, r2, #15
428    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
429    add     r2, rFP, r2, lsl #2         @ r2<- &fp[A]
430    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[B]
431    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
432    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
433    stmia   r2, {r0-r1}                 @ fp[A]<- r0/r1
434    GOTO_OPCODE(ip)                     @ jump to next instruction
435
436
437/* ------------------------------ */
438    .balign 64
439.L_OP_MOVE_WIDE_FROM16: /* 0x05 */
440/* File: armv5te/OP_MOVE_WIDE_FROM16.S */
441    /* move-wide/from16 vAA, vBBBB */
442    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
443    FETCH(r3, 1)                        @ r3<- BBBB
444    mov     r2, rINST, lsr #8           @ r2<- AA
445    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
446    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
447    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
448    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
449    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
450    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
451    GOTO_OPCODE(ip)                     @ jump to next instruction
452
453
454/* ------------------------------ */
455    .balign 64
456.L_OP_MOVE_WIDE_16: /* 0x06 */
457/* File: armv5te/OP_MOVE_WIDE_16.S */
458    /* move-wide/16 vAAAA, vBBBB */
459    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
460    FETCH(r3, 2)                        @ r3<- BBBB
461    FETCH(r2, 1)                        @ r2<- AAAA
462    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
463    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AAAA]
464    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
465    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
466    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
467    stmia   r2, {r0-r1}                 @ fp[AAAA]<- r0/r1
468    GOTO_OPCODE(ip)                     @ jump to next instruction
469
470
471/* ------------------------------ */
472    .balign 64
473.L_OP_MOVE_OBJECT: /* 0x07 */
474/* File: armv5te/OP_MOVE_OBJECT.S */
475/* File: armv5te/OP_MOVE.S */
476    /* for move, move-object, long-to-int */
477    /* op vA, vB */
478    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
479    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
480    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
481    GET_VREG(r2, r1)                    @ r2<- fp[B]
482    and     r0, r0, #15
483    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
484    SET_VREG(r2, r0)                    @ fp[A]<- r2
485    GOTO_OPCODE(ip)                     @ execute next instruction
486
487
488
489/* ------------------------------ */
490    .balign 64
491.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
492/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */
493/* File: armv5te/OP_MOVE_FROM16.S */
494    /* for: move/from16, move-object/from16 */
495    /* op vAA, vBBBB */
496    FETCH(r1, 1)                        @ r1<- BBBB
497    mov     r0, rINST, lsr #8           @ r0<- AA
498    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
499    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
500    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
501    SET_VREG(r2, r0)                    @ fp[AA]<- r2
502    GOTO_OPCODE(ip)                     @ jump to next instruction
503
504
505
506/* ------------------------------ */
507    .balign 64
508.L_OP_MOVE_OBJECT_16: /* 0x09 */
509/* File: armv5te/OP_MOVE_OBJECT_16.S */
510/* File: armv5te/OP_MOVE_16.S */
511    /* for: move/16, move-object/16 */
512    /* op vAAAA, vBBBB */
513    FETCH(r1, 2)                        @ r1<- BBBB
514    FETCH(r0, 1)                        @ r0<- AAAA
515    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
516    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
517    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
518    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
519    GOTO_OPCODE(ip)                     @ jump to next instruction
520
521
522
523/* ------------------------------ */
524    .balign 64
525.L_OP_MOVE_RESULT: /* 0x0a */
526/* File: armv5te/OP_MOVE_RESULT.S */
527    /* for: move-result, move-result-object */
528    /* op vAA */
529    mov     r2, rINST, lsr #8           @ r2<- AA
530    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
531    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
532    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
533    SET_VREG(r0, r2)                    @ fp[AA]<- r0
534    GOTO_OPCODE(ip)                     @ jump to next instruction
535
536
537/* ------------------------------ */
538    .balign 64
539.L_OP_MOVE_RESULT_WIDE: /* 0x0b */
540/* File: armv5te/OP_MOVE_RESULT_WIDE.S */
541    /* move-result-wide vAA */
542    mov     r2, rINST, lsr #8           @ r2<- AA
543    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
544    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
545    ldmia   r3, {r0-r1}                 @ r0/r1<- retval.j
546    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
547    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
548    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
549    GOTO_OPCODE(ip)                     @ jump to next instruction
550
551
552/* ------------------------------ */
553    .balign 64
554.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
555/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */
556/* File: armv5te/OP_MOVE_RESULT.S */
557    /* for: move-result, move-result-object */
558    /* op vAA */
559    mov     r2, rINST, lsr #8           @ r2<- AA
560    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
561    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
562    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
563    SET_VREG(r0, r2)                    @ fp[AA]<- r0
564    GOTO_OPCODE(ip)                     @ jump to next instruction
565
566
567
568/* ------------------------------ */
569    .balign 64
570.L_OP_MOVE_EXCEPTION: /* 0x0d */
571/* File: armv5te/OP_MOVE_EXCEPTION.S */
572    /* move-exception vAA */
573    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
574    mov     r2, rINST, lsr #8           @ r2<- AA
575    ldr     r3, [r0, #offThread_exception]  @ r3<- dvmGetException bypass
576    mov     r1, #0                      @ r1<- 0
577    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
578    SET_VREG(r3, r2)                    @ fp[AA]<- exception obj
579    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
580    str     r1, [r0, #offThread_exception]  @ dvmClearException bypass
581    GOTO_OPCODE(ip)                     @ jump to next instruction
582
583
584/* ------------------------------ */
585    .balign 64
586.L_OP_RETURN_VOID: /* 0x0e */
587/* File: armv5te/OP_RETURN_VOID.S */
588    b       common_returnFromMethod
589
590
591/* ------------------------------ */
592    .balign 64
593.L_OP_RETURN: /* 0x0f */
594/* File: armv5te/OP_RETURN.S */
595    /*
596     * Return a 32-bit value.  Copies the return value into the "glue"
597     * structure, then jumps to the return handler.
598     *
599     * for: return, return-object
600     */
601    /* op vAA */
602    mov     r2, rINST, lsr #8           @ r2<- AA
603    GET_VREG(r0, r2)                    @ r0<- vAA
604    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
605    b       common_returnFromMethod
606
607
608/* ------------------------------ */
609    .balign 64
610.L_OP_RETURN_WIDE: /* 0x10 */
611/* File: armv5te/OP_RETURN_WIDE.S */
612    /*
613     * Return a 64-bit value.  Copies the return value into the "glue"
614     * structure, then jumps to the return handler.
615     */
616    /* return-wide vAA */
617    mov     r2, rINST, lsr #8           @ r2<- AA
618    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
619    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
620    ldmia   r2, {r0-r1}                 @ r0/r1 <- vAA/vAA+1
621    stmia   r3, {r0-r1}                 @ retval<- r0/r1
622    b       common_returnFromMethod
623
624
625/* ------------------------------ */
626    .balign 64
627.L_OP_RETURN_OBJECT: /* 0x11 */
628/* File: armv5te/OP_RETURN_OBJECT.S */
629/* File: armv5te/OP_RETURN.S */
630    /*
631     * Return a 32-bit value.  Copies the return value into the "glue"
632     * structure, then jumps to the return handler.
633     *
634     * for: return, return-object
635     */
636    /* op vAA */
637    mov     r2, rINST, lsr #8           @ r2<- AA
638    GET_VREG(r0, r2)                    @ r0<- vAA
639    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
640    b       common_returnFromMethod
641
642
643
644/* ------------------------------ */
645    .balign 64
646.L_OP_CONST_4: /* 0x12 */
647/* File: armv5te/OP_CONST_4.S */
648    /* const/4 vA, #+B */
649    mov     r1, rINST, lsl #16          @ r1<- Bxxx0000
650    mov     r0, rINST, lsr #8           @ r0<- A+
651    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
652    mov     r1, r1, asr #28             @ r1<- sssssssB (sign-extended)
653    and     r0, r0, #15
654    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
655    SET_VREG(r1, r0)                    @ fp[A]<- r1
656    GOTO_OPCODE(ip)                     @ execute next instruction
657
658
659/* ------------------------------ */
660    .balign 64
661.L_OP_CONST_16: /* 0x13 */
662/* File: armv5te/OP_CONST_16.S */
663    /* const/16 vAA, #+BBBB */
664    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
665    mov     r3, rINST, lsr #8           @ r3<- AA
666    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
667    SET_VREG(r0, r3)                    @ vAA<- r0
668    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
669    GOTO_OPCODE(ip)                     @ jump to next instruction
670
671
672/* ------------------------------ */
673    .balign 64
674.L_OP_CONST: /* 0x14 */
675/* File: armv5te/OP_CONST.S */
676    /* const vAA, #+BBBBbbbb */
677    mov     r3, rINST, lsr #8           @ r3<- AA
678    FETCH(r0, 1)                        @ r0<- bbbb (low)
679    FETCH(r1, 2)                        @ r1<- BBBB (high)
680    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
681    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
682    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
683    SET_VREG(r0, r3)                    @ vAA<- r0
684    GOTO_OPCODE(ip)                     @ jump to next instruction
685
686
687/* ------------------------------ */
688    .balign 64
689.L_OP_CONST_HIGH16: /* 0x15 */
690/* File: armv5te/OP_CONST_HIGH16.S */
691    /* const/high16 vAA, #+BBBB0000 */
692    FETCH(r0, 1)                        @ r0<- 0000BBBB (zero-extended)
693    mov     r3, rINST, lsr #8           @ r3<- AA
694    mov     r0, r0, lsl #16             @ r0<- BBBB0000
695    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
696    SET_VREG(r0, r3)                    @ vAA<- r0
697    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
698    GOTO_OPCODE(ip)                     @ jump to next instruction
699
700
701/* ------------------------------ */
702    .balign 64
703.L_OP_CONST_WIDE_16: /* 0x16 */
704/* File: armv5te/OP_CONST_WIDE_16.S */
705    /* const-wide/16 vAA, #+BBBB */
706    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
707    mov     r3, rINST, lsr #8           @ r3<- AA
708    mov     r1, r0, asr #31             @ r1<- ssssssss
709    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
710    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
711    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
712    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
713    GOTO_OPCODE(ip)                     @ jump to next instruction
714
715
716/* ------------------------------ */
717    .balign 64
718.L_OP_CONST_WIDE_32: /* 0x17 */
719/* File: armv5te/OP_CONST_WIDE_32.S */
720    /* const-wide/32 vAA, #+BBBBbbbb */
721    FETCH(r0, 1)                        @ r0<- 0000bbbb (low)
722    mov     r3, rINST, lsr #8           @ r3<- AA
723    FETCH_S(r2, 2)                      @ r2<- ssssBBBB (high)
724    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
725    orr     r0, r0, r2, lsl #16         @ r0<- BBBBbbbb
726    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
727    mov     r1, r0, asr #31             @ r1<- ssssssss
728    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
729    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
730    GOTO_OPCODE(ip)                     @ jump to next instruction
731
732
733/* ------------------------------ */
734    .balign 64
735.L_OP_CONST_WIDE: /* 0x18 */
736/* File: armv5te/OP_CONST_WIDE.S */
737    /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
738    FETCH(r0, 1)                        @ r0<- bbbb (low)
739    FETCH(r1, 2)                        @ r1<- BBBB (low middle)
740    FETCH(r2, 3)                        @ r2<- hhhh (high middle)
741    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb (low word)
742    FETCH(r3, 4)                        @ r3<- HHHH (high)
743    mov     r9, rINST, lsr #8           @ r9<- AA
744    orr     r1, r2, r3, lsl #16         @ r1<- HHHHhhhh (high word)
745    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
746    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
747    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
748    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
749    GOTO_OPCODE(ip)                     @ jump to next instruction
750
751
752/* ------------------------------ */
753    .balign 64
754.L_OP_CONST_WIDE_HIGH16: /* 0x19 */
755/* File: armv5te/OP_CONST_WIDE_HIGH16.S */
756    /* const-wide/high16 vAA, #+BBBB000000000000 */
757    FETCH(r1, 1)                        @ r1<- 0000BBBB (zero-extended)
758    mov     r3, rINST, lsr #8           @ r3<- AA
759    mov     r0, #0                      @ r0<- 00000000
760    mov     r1, r1, lsl #16             @ r1<- BBBB0000
761    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
762    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
763    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
764    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
765    GOTO_OPCODE(ip)                     @ jump to next instruction
766
767
768/* ------------------------------ */
769    .balign 64
770.L_OP_CONST_STRING: /* 0x1a */
771/* File: armv5te/OP_CONST_STRING.S */
772    /* const/string vAA, String@BBBB */
773    FETCH(r1, 1)                        @ r1<- BBBB
774    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
775    mov     r9, rINST, lsr #8           @ r9<- AA
776    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
777    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
778    cmp     r0, #0                      @ not yet resolved?
779    beq     .LOP_CONST_STRING_resolve
780    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
781    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
782    SET_VREG(r0, r9)                    @ vAA<- r0
783    GOTO_OPCODE(ip)                     @ jump to next instruction
784
785/* ------------------------------ */
786    .balign 64
787.L_OP_CONST_STRING_JUMBO: /* 0x1b */
788/* File: armv5te/OP_CONST_STRING_JUMBO.S */
789    /* const/string vAA, String@BBBBBBBB */
790    FETCH(r0, 1)                        @ r0<- bbbb (low)
791    FETCH(r1, 2)                        @ r1<- BBBB (high)
792    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
793    mov     r9, rINST, lsr #8           @ r9<- AA
794    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
795    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
796    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
797    cmp     r0, #0
798    beq     .LOP_CONST_STRING_JUMBO_resolve
799    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
800    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
801    SET_VREG(r0, r9)                    @ vAA<- r0
802    GOTO_OPCODE(ip)                     @ jump to next instruction
803
804/* ------------------------------ */
805    .balign 64
806.L_OP_CONST_CLASS: /* 0x1c */
807/* File: armv5te/OP_CONST_CLASS.S */
808    /* const/class vAA, Class@BBBB */
809    FETCH(r1, 1)                        @ r1<- BBBB
810    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
811    mov     r9, rINST, lsr #8           @ r9<- AA
812    ldr     r2, [r2, #offDvmDex_pResClasses]   @ r2<- dvmDex->pResClasses
813    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResClasses[BBBB]
814    cmp     r0, #0                      @ not yet resolved?
815    beq     .LOP_CONST_CLASS_resolve
816    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
817    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
818    SET_VREG(r0, r9)                    @ vAA<- r0
819    GOTO_OPCODE(ip)                     @ jump to next instruction
820
821/* ------------------------------ */
822    .balign 64
823.L_OP_MONITOR_ENTER: /* 0x1d */
824/* File: armv5te/OP_MONITOR_ENTER.S */
825    /*
826     * Synchronize on an object.
827     */
828    /* monitor-enter vAA */
829    mov     r2, rINST, lsr #8           @ r2<- AA
830    GET_VREG(r1, r2)                    @ r1<- vAA (object)
831    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
832    cmp     r1, #0                      @ null object?
833    EXPORT_PC()                         @ need for precise GC, MONITOR_TRACKING
834    beq     common_errNullObject        @ null object, throw an exception
835    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
836    bl      dvmLockObject               @ call(self, obj)
837#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */
838    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
839    ldr     r1, [r0, #offThread_exception] @ check for exception
840    cmp     r1, #0
841    bne     common_exceptionThrown      @ exception raised, bail out
842#endif
843    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
844    GOTO_OPCODE(ip)                     @ jump to next instruction
845
846
847/* ------------------------------ */
848    .balign 64
849.L_OP_MONITOR_EXIT: /* 0x1e */
850/* File: armv5te/OP_MONITOR_EXIT.S */
851    /*
852     * Unlock an object.
853     *
854     * Exceptions that occur when unlocking a monitor need to appear as
855     * if they happened at the following instruction.  See the Dalvik
856     * instruction spec.
857     */
858    /* monitor-exit vAA */
859    mov     r2, rINST, lsr #8           @ r2<- AA
860    EXPORT_PC()                         @ before fetch: export the PC
861    GET_VREG(r1, r2)                    @ r1<- vAA (object)
862    cmp     r1, #0                      @ null object?
863    beq     common_errNullObject        @ yes
864    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
865    bl      dvmUnlockObject             @ r0<- success for unlock(self, obj)
866    cmp     r0, #0                      @ failed?
867    beq     common_exceptionThrown      @ yes, exception is pending
868    FETCH_ADVANCE_INST(1)               @ before throw: advance rPC, load rINST
869    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
870    GOTO_OPCODE(ip)                     @ jump to next instruction
871
872
873/* ------------------------------ */
874    .balign 64
875.L_OP_CHECK_CAST: /* 0x1f */
876/* File: armv5te/OP_CHECK_CAST.S */
877    /*
878     * Check to see if a cast from one class to another is allowed.
879     */
880    /* check-cast vAA, class@BBBB */
881    mov     r3, rINST, lsr #8           @ r3<- AA
882    FETCH(r2, 1)                        @ r2<- BBBB
883    GET_VREG(r9, r3)                    @ r9<- object
884    ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- pDvmDex
885    cmp     r9, #0                      @ is object null?
886    ldr     r0, [r0, #offDvmDex_pResClasses]    @ r0<- pDvmDex->pResClasses
887    beq     .LOP_CHECK_CAST_okay            @ null obj, cast always succeeds
888    ldr     r1, [r0, r2, lsl #2]        @ r1<- resolved class
889    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
890    cmp     r1, #0                      @ have we resolved this before?
891    beq     .LOP_CHECK_CAST_resolve         @ not resolved, do it now
892.LOP_CHECK_CAST_resolved:
893    cmp     r0, r1                      @ same class (trivial success)?
894    bne     .LOP_CHECK_CAST_fullcheck       @ no, do full check
895.LOP_CHECK_CAST_okay:
896    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
897    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
898    GOTO_OPCODE(ip)                     @ jump to next instruction
899
900/* ------------------------------ */
901    .balign 64
902.L_OP_INSTANCE_OF: /* 0x20 */
903/* File: armv5te/OP_INSTANCE_OF.S */
904    /*
905     * Check to see if an object reference is an instance of a class.
906     *
907     * Most common situation is a non-null object, being compared against
908     * an already-resolved class.
909     */
910    /* instance-of vA, vB, class@CCCC */
911    mov     r3, rINST, lsr #12          @ r3<- B
912    mov     r9, rINST, lsr #8           @ r9<- A+
913    GET_VREG(r0, r3)                    @ r0<- vB (object)
914    and     r9, r9, #15                 @ r9<- A
915    cmp     r0, #0                      @ is object null?
916    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- pDvmDex
917    beq     .LOP_INSTANCE_OF_store           @ null obj, not an instance, store r0
918    FETCH(r3, 1)                        @ r3<- CCCC
919    ldr     r2, [r2, #offDvmDex_pResClasses]    @ r2<- pDvmDex->pResClasses
920    ldr     r1, [r2, r3, lsl #2]        @ r1<- resolved class
921    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
922    cmp     r1, #0                      @ have we resolved this before?
923    beq     .LOP_INSTANCE_OF_resolve         @ not resolved, do it now
924.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class
925    cmp     r0, r1                      @ same class (trivial success)?
926    beq     .LOP_INSTANCE_OF_trivial         @ yes, trivial finish
927    b       .LOP_INSTANCE_OF_fullcheck       @ no, do full check
928
929/* ------------------------------ */
930    .balign 64
931.L_OP_ARRAY_LENGTH: /* 0x21 */
932/* File: armv5te/OP_ARRAY_LENGTH.S */
933    /*
934     * Return the length of an array.
935     */
936    mov     r1, rINST, lsr #12          @ r1<- B
937    mov     r2, rINST, lsr #8           @ r2<- A+
938    GET_VREG(r0, r1)                    @ r0<- vB (object ref)
939    and     r2, r2, #15                 @ r2<- A
940    cmp     r0, #0                      @ is object null?
941    beq     common_errNullObject        @ yup, fail
942    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
943    ldr     r3, [r0, #offArrayObject_length]    @ r3<- array length
944    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
945    SET_VREG(r3, r2)                    @ vB<- length
946    GOTO_OPCODE(ip)                     @ jump to next instruction
947
948
949/* ------------------------------ */
950    .balign 64
951.L_OP_NEW_INSTANCE: /* 0x22 */
952/* File: armv5te/OP_NEW_INSTANCE.S */
953    /*
954     * Create a new instance of a class.
955     */
956    /* new-instance vAA, class@BBBB */
957    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
958    FETCH(r1, 1)                        @ r1<- BBBB
959    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
960    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
961    EXPORT_PC()                         @ req'd for init, resolve, alloc
962    cmp     r0, #0                      @ already resolved?
963    beq     .LOP_NEW_INSTANCE_resolve         @ no, resolve it now
964.LOP_NEW_INSTANCE_resolved:   @ r0=class
965    ldrb    r1, [r0, #offClassObject_status]    @ r1<- ClassStatus enum
966    cmp     r1, #CLASS_INITIALIZED      @ has class been initialized?
967    bne     .LOP_NEW_INSTANCE_needinit        @ no, init class now
968.LOP_NEW_INSTANCE_initialized: @ r0=class
969    ldr     r3, [r0, #offClassObject_accessFlags]   @ r3<- clazz->accessFlags
970    tst     r3, #(ACC_INTERFACE|ACC_ABSTRACT)   @ abstract or interface?
971    mov     r1, #ALLOC_DONT_TRACK       @ flags for alloc call
972    beq     .LOP_NEW_INSTANCE_finish          @ concrete class, continue
973    b       .LOP_NEW_INSTANCE_abstract        @ fail
974
975/* ------------------------------ */
976    .balign 64
977.L_OP_NEW_ARRAY: /* 0x23 */
978/* File: armv5te/OP_NEW_ARRAY.S */
979    /*
980     * Allocate an array of objects, specified with the array class
981     * and a count.
982     *
983     * The verifier guarantees that this is an array class, so we don't
984     * check for it here.
985     */
986    /* new-array vA, vB, class@CCCC */
987    mov     r0, rINST, lsr #12          @ r0<- B
988    FETCH(r2, 1)                        @ r2<- CCCC
989    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
990    GET_VREG(r1, r0)                    @ r1<- vB (array length)
991    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
992    cmp     r1, #0                      @ check length
993    ldr     r0, [r3, r2, lsl #2]        @ r0<- resolved class
994    bmi     common_errNegativeArraySize @ negative length, bail
995    cmp     r0, #0                      @ already resolved?
996    EXPORT_PC()                         @ req'd for resolve, alloc
997    bne     .LOP_NEW_ARRAY_finish          @ resolved, continue
998    b       .LOP_NEW_ARRAY_resolve         @ do resolve now
999
1000/* ------------------------------ */
1001    .balign 64
1002.L_OP_FILLED_NEW_ARRAY: /* 0x24 */
1003/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1004    /*
1005     * Create a new array with elements filled from registers.
1006     *
1007     * for: filled-new-array, filled-new-array/range
1008     */
1009    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1010    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1011    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1012    FETCH(r1, 1)                        @ r1<- BBBB
1013    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1014    EXPORT_PC()                         @ need for resolve and alloc
1015    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1016    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1017    cmp     r0, #0                      @ already resolved?
1018    bne     .LOP_FILLED_NEW_ARRAY_continue        @ yes, continue on
10198:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1020    mov     r2, #0                      @ r2<- false
1021    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1022    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1023    cmp     r0, #0                      @ got null?
1024    beq     common_exceptionThrown      @ yes, handle exception
1025    b       .LOP_FILLED_NEW_ARRAY_continue
1026
1027/* ------------------------------ */
1028    .balign 64
1029.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
1030/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */
1031/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1032    /*
1033     * Create a new array with elements filled from registers.
1034     *
1035     * for: filled-new-array, filled-new-array/range
1036     */
1037    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1038    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1039    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1040    FETCH(r1, 1)                        @ r1<- BBBB
1041    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1042    EXPORT_PC()                         @ need for resolve and alloc
1043    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1044    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1045    cmp     r0, #0                      @ already resolved?
1046    bne     .LOP_FILLED_NEW_ARRAY_RANGE_continue        @ yes, continue on
10478:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1048    mov     r2, #0                      @ r2<- false
1049    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1050    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1051    cmp     r0, #0                      @ got null?
1052    beq     common_exceptionThrown      @ yes, handle exception
1053    b       .LOP_FILLED_NEW_ARRAY_RANGE_continue
1054
1055
1056/* ------------------------------ */
1057    .balign 64
1058.L_OP_FILL_ARRAY_DATA: /* 0x26 */
1059/* File: armv5te/OP_FILL_ARRAY_DATA.S */
1060    /* fill-array-data vAA, +BBBBBBBB */
1061    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1062    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1063    mov     r3, rINST, lsr #8           @ r3<- AA
1064    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
1065    GET_VREG(r0, r3)                    @ r0<- vAA (array object)
1066    add     r1, rPC, r1, lsl #1         @ r1<- PC + BBBBbbbb*2 (array data off.)
1067    EXPORT_PC();
1068    bl      dvmInterpHandleFillArrayData@ fill the array with predefined data
1069    cmp     r0, #0                      @ 0 means an exception is thrown
1070    beq     common_exceptionThrown      @ has exception
1071    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
1072    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1073    GOTO_OPCODE(ip)                     @ jump to next instruction
1074
1075/* ------------------------------ */
1076    .balign 64
1077.L_OP_THROW: /* 0x27 */
1078/* File: armv5te/OP_THROW.S */
1079    /*
1080     * Throw an exception object in the current thread.
1081     */
1082    /* throw vAA */
1083    mov     r2, rINST, lsr #8           @ r2<- AA
1084    GET_VREG(r1, r2)                    @ r1<- vAA (exception object)
1085    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
1086    cmp     r1, #0                      @ null object?
1087    beq     common_errNullObject        @ yes, throw an NPE instead
1088    @ bypass dvmSetException, just store it
1089    str     r1, [r0, #offThread_exception]  @ thread->exception<- obj
1090    b       common_exceptionThrown
1091
1092
1093/* ------------------------------ */
1094    .balign 64
1095.L_OP_GOTO: /* 0x28 */
1096/* File: armv5te/OP_GOTO.S */
1097    /*
1098     * Unconditional branch, 8-bit offset.
1099     *
1100     * The branch distance is a signed code-unit offset, which we need to
1101     * double to get a byte offset.
1102     */
1103    /* goto +AA */
1104    mov     r0, rINST, lsl #16          @ r0<- AAxx0000
1105    movs    r9, r0, asr #24             @ r9<- ssssssAA (sign-extended)
1106    mov     r9, r9, lsl #1              @ r9<- byte offset
1107    bmi     common_backwardBranch       @ backward branch, do periodic checks
1108    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1109    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1110    GOTO_OPCODE(ip)                     @ jump to next instruction
1111
1112
1113/* ------------------------------ */
1114    .balign 64
1115.L_OP_GOTO_16: /* 0x29 */
1116/* File: armv5te/OP_GOTO_16.S */
1117    /*
1118     * Unconditional branch, 16-bit offset.
1119     *
1120     * The branch distance is a signed code-unit offset, which we need to
1121     * double to get a byte offset.
1122     */
1123    /* goto/16 +AAAA */
1124    FETCH_S(r0, 1)                      @ r0<- ssssAAAA (sign-extended)
1125    movs    r9, r0, asl #1              @ r9<- byte offset, check sign
1126    bmi     common_backwardBranch       @ backward branch, do periodic checks
1127    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1128    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1129    GOTO_OPCODE(ip)                     @ jump to next instruction
1130
1131
1132/* ------------------------------ */
1133    .balign 64
1134.L_OP_GOTO_32: /* 0x2a */
1135/* File: armv5te/OP_GOTO_32.S */
1136    /*
1137     * Unconditional branch, 32-bit offset.
1138     *
1139     * The branch distance is a signed code-unit offset, which we need to
1140     * double to get a byte offset.
1141     *
1142     * Unlike most opcodes, this one is allowed to branch to itself, so
1143     * our "backward branch" test must be "<=0" instead of "<0".  The ORRS
1144     * instruction doesn't affect the V flag, so we need to clear it
1145     * explicitly.
1146     */
1147    /* goto/32 +AAAAAAAA */
1148    FETCH(r0, 1)                        @ r0<- aaaa (lo)
1149    FETCH(r1, 2)                        @ r1<- AAAA (hi)
1150    cmp     ip, ip                      @ (clear V flag during stall)
1151    orrs    r0, r0, r1, lsl #16         @ r0<- AAAAaaaa, check sign
1152    mov     r9, r0, asl #1              @ r9<- byte offset
1153    ble     common_backwardBranch       @ backward branch, do periodic checks
1154    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1155    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1156    GOTO_OPCODE(ip)                     @ jump to next instruction
1157
1158
1159/* ------------------------------ */
1160    .balign 64
1161.L_OP_PACKED_SWITCH: /* 0x2b */
1162/* File: armv5te/OP_PACKED_SWITCH.S */
1163    /*
1164     * Handle a packed-switch or sparse-switch instruction.  In both cases
1165     * we decode it and hand it off to a helper function.
1166     *
1167     * We don't really expect backward branches in a switch statement, but
1168     * they're perfectly legal, so we check for them here.
1169     *
1170     * for: packed-switch, sparse-switch
1171     */
1172    /* op vAA, +BBBB */
1173    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1174    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1175    mov     r3, rINST, lsr #8           @ r3<- AA
1176    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1177    GET_VREG(r1, r3)                    @ r1<- vAA
1178    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1179    bl      dvmInterpHandlePackedSwitch                       @ r0<- code-unit branch offset
1180    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1181    bmi     common_backwardBranch       @ backward branch, do periodic checks
1182    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1183    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1184    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1185    GOTO_OPCODE(ip)                     @ jump to next instruction
1186
1187
1188/* ------------------------------ */
1189    .balign 64
1190.L_OP_SPARSE_SWITCH: /* 0x2c */
1191/* File: armv5te/OP_SPARSE_SWITCH.S */
1192/* File: armv5te/OP_PACKED_SWITCH.S */
1193    /*
1194     * Handle a packed-switch or sparse-switch instruction.  In both cases
1195     * we decode it and hand it off to a helper function.
1196     *
1197     * We don't really expect backward branches in a switch statement, but
1198     * they're perfectly legal, so we check for them here.
1199     *
1200     * for: packed-switch, sparse-switch
1201     */
1202    /* op vAA, +BBBB */
1203    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1204    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1205    mov     r3, rINST, lsr #8           @ r3<- AA
1206    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1207    GET_VREG(r1, r3)                    @ r1<- vAA
1208    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1209    bl      dvmInterpHandleSparseSwitch                       @ r0<- code-unit branch offset
1210    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1211    bmi     common_backwardBranch       @ backward branch, do periodic checks
1212    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1213    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1214    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1215    GOTO_OPCODE(ip)                     @ jump to next instruction
1216
1217
1218
1219/* ------------------------------ */
1220    .balign 64
1221.L_OP_CMPL_FLOAT: /* 0x2d */
1222/* File: armv5te/OP_CMPL_FLOAT.S */
1223    /*
1224     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1225     * destination register based on the results of the comparison.
1226     *
1227     * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1228     * on what value we'd like to return when one of the operands is NaN.
1229     *
1230     * The operation we're implementing is:
1231     *   if (x == y)
1232     *     return 0;
1233     *   else if (x < y)
1234     *     return -1;
1235     *   else if (x > y)
1236     *     return 1;
1237     *   else
1238     *     return {-1,1};  // one or both operands was NaN
1239     *
1240     * The straightforward implementation requires 3 calls to functions
1241     * that return a result in r0.  We can do it with two calls if our
1242     * EABI library supports __aeabi_cfcmple (only one if we want to check
1243     * for NaN directly):
1244     *   check x <= y
1245     *     if <, return -1
1246     *     if ==, return 0
1247     *   check y <= x
1248     *     if <, return 1
1249     *   return {-1,1}
1250     *
1251     * for: cmpl-float, cmpg-float
1252     */
1253    /* op vAA, vBB, vCC */
1254    FETCH(r0, 1)                        @ r0<- CCBB
1255    and     r2, r0, #255                @ r2<- BB
1256    mov     r3, r0, lsr #8              @ r3<- CC
1257    GET_VREG(r9, r2)                    @ r9<- vBB
1258    GET_VREG(r10, r3)                   @ r10<- vCC
1259    mov     r0, r9                      @ copy to arg registers
1260    mov     r1, r10
1261    bl      __aeabi_cfcmple             @ cmp <=: C clear if <, Z set if eq
1262    bhi     .LOP_CMPL_FLOAT_gt_or_nan       @ C set and Z clear, disambiguate
1263    mvncc   r1, #0                      @ (less than) r1<- -1
1264    moveq   r1, #0                      @ (equal) r1<- 0, trumps less than
1265.LOP_CMPL_FLOAT_finish:
1266    mov     r3, rINST, lsr #8           @ r3<- AA
1267    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1268    SET_VREG(r1, r3)                    @ vAA<- r1
1269    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1270    GOTO_OPCODE(ip)                     @ jump to next instruction
1271
1272/* ------------------------------ */
1273    .balign 64
1274.L_OP_CMPG_FLOAT: /* 0x2e */
1275/* File: armv5te/OP_CMPG_FLOAT.S */
1276/* File: armv5te/OP_CMPL_FLOAT.S */
1277    /*
1278     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1279     * destination register based on the results of the comparison.
1280     *
1281     * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1282     * on what value we'd like to return when one of the operands is NaN.
1283     *
1284     * The operation we're implementing is:
1285     *   if (x == y)
1286     *     return 0;
1287     *   else if (x < y)
1288     *     return -1;
1289     *   else if (x > y)
1290     *     return 1;
1291     *   else
1292     *     return {-1,1};  // one or both operands was NaN
1293     *
1294     * The straightforward implementation requires 3 calls to functions
1295     * that return a result in r0.  We can do it with two calls if our
1296     * EABI library supports __aeabi_cfcmple (only one if we want to check
1297     * for NaN directly):
1298     *   check x <= y
1299     *     if <, return -1
1300     *     if ==, return 0
1301     *   check y <= x
1302     *     if <, return 1
1303     *   return {-1,1}
1304     *
1305     * for: cmpl-float, cmpg-float
1306     */
1307    /* op vAA, vBB, vCC */
1308    FETCH(r0, 1)                        @ r0<- CCBB
1309    and     r2, r0, #255                @ r2<- BB
1310    mov     r3, r0, lsr #8              @ r3<- CC
1311    GET_VREG(r9, r2)                    @ r9<- vBB
1312    GET_VREG(r10, r3)                   @ r10<- vCC
1313    mov     r0, r9                      @ copy to arg registers
1314    mov     r1, r10
1315    bl      __aeabi_cfcmple             @ cmp <=: C clear if <, Z set if eq
1316    bhi     .LOP_CMPG_FLOAT_gt_or_nan       @ C set and Z clear, disambiguate
1317    mvncc   r1, #0                      @ (less than) r1<- -1
1318    moveq   r1, #0                      @ (equal) r1<- 0, trumps less than
1319.LOP_CMPG_FLOAT_finish:
1320    mov     r3, rINST, lsr #8           @ r3<- AA
1321    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1322    SET_VREG(r1, r3)                    @ vAA<- r1
1323    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1324    GOTO_OPCODE(ip)                     @ jump to next instruction
1325
1326
1327/* ------------------------------ */
1328    .balign 64
1329.L_OP_CMPL_DOUBLE: /* 0x2f */
1330/* File: armv5te/OP_CMPL_DOUBLE.S */
1331    /*
1332     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1333     * destination register based on the results of the comparison.
1334     *
1335     * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1336     * on what value we'd like to return when one of the operands is NaN.
1337     *
1338     * See OP_CMPL_FLOAT for an explanation.
1339     *
1340     * For: cmpl-double, cmpg-double
1341     */
1342    /* op vAA, vBB, vCC */
1343    FETCH(r0, 1)                        @ r0<- CCBB
1344    and     r9, r0, #255                @ r9<- BB
1345    mov     r10, r0, lsr #8             @ r10<- CC
1346    add     r9, rFP, r9, lsl #2         @ r9<- &fp[BB]
1347    add     r10, rFP, r10, lsl #2       @ r10<- &fp[CC]
1348    ldmia   r9, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1349    ldmia   r10, {r2-r3}                @ r2/r3<- vCC/vCC+1
1350    bl      __aeabi_cdcmple             @ cmp <=: C clear if <, Z set if eq
1351    bhi     .LOP_CMPL_DOUBLE_gt_or_nan       @ C set and Z clear, disambiguate
1352    mvncc   r1, #0                      @ (less than) r1<- -1
1353    moveq   r1, #0                      @ (equal) r1<- 0, trumps less than
1354.LOP_CMPL_DOUBLE_finish:
1355    mov     r3, rINST, lsr #8           @ r3<- AA
1356    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1357    SET_VREG(r1, r3)                    @ vAA<- r1
1358    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1359    GOTO_OPCODE(ip)                     @ jump to next instruction
1360
1361/* ------------------------------ */
1362    .balign 64
1363.L_OP_CMPG_DOUBLE: /* 0x30 */
1364/* File: armv5te/OP_CMPG_DOUBLE.S */
1365/* File: armv5te/OP_CMPL_DOUBLE.S */
1366    /*
1367     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1368     * destination register based on the results of the comparison.
1369     *
1370     * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1371     * on what value we'd like to return when one of the operands is NaN.
1372     *
1373     * See OP_CMPL_FLOAT for an explanation.
1374     *
1375     * For: cmpl-double, cmpg-double
1376     */
1377    /* op vAA, vBB, vCC */
1378    FETCH(r0, 1)                        @ r0<- CCBB
1379    and     r9, r0, #255                @ r9<- BB
1380    mov     r10, r0, lsr #8             @ r10<- CC
1381    add     r9, rFP, r9, lsl #2         @ r9<- &fp[BB]
1382    add     r10, rFP, r10, lsl #2       @ r10<- &fp[CC]
1383    ldmia   r9, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1384    ldmia   r10, {r2-r3}                @ r2/r3<- vCC/vCC+1
1385    bl      __aeabi_cdcmple             @ cmp <=: C clear if <, Z set if eq
1386    bhi     .LOP_CMPG_DOUBLE_gt_or_nan       @ C set and Z clear, disambiguate
1387    mvncc   r1, #0                      @ (less than) r1<- -1
1388    moveq   r1, #0                      @ (equal) r1<- 0, trumps less than
1389.LOP_CMPG_DOUBLE_finish:
1390    mov     r3, rINST, lsr #8           @ r3<- AA
1391    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1392    SET_VREG(r1, r3)                    @ vAA<- r1
1393    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1394    GOTO_OPCODE(ip)                     @ jump to next instruction
1395
1396
1397/* ------------------------------ */
1398    .balign 64
1399.L_OP_CMP_LONG: /* 0x31 */
1400/* File: armv5te/OP_CMP_LONG.S */
1401    /*
1402     * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
1403     * register based on the results of the comparison.
1404     *
1405     * We load the full values with LDM, but in practice many values could
1406     * be resolved by only looking at the high word.  This could be made
1407     * faster or slower by splitting the LDM into a pair of LDRs.
1408     *
1409     * If we just wanted to set condition flags, we could do this:
1410     *  subs    ip, r0, r2
1411     *  sbcs    ip, r1, r3
1412     *  subeqs  ip, r0, r2
1413     * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
1414     * integer value, which we can do with 2 conditional mov/mvn instructions
1415     * (set 1, set -1; if they're equal we already have 0 in ip), giving
1416     * us a constant 5-cycle path plus a branch at the end to the
1417     * instruction epilogue code.  The multi-compare approach below needs
1418     * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
1419     * in the worst case (the 64-bit values are equal).
1420     */
1421    /* cmp-long vAA, vBB, vCC */
1422    FETCH(r0, 1)                        @ r0<- CCBB
1423    mov     r9, rINST, lsr #8           @ r9<- AA
1424    and     r2, r0, #255                @ r2<- BB
1425    mov     r3, r0, lsr #8              @ r3<- CC
1426    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
1427    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
1428    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1429    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
1430    cmp     r1, r3                      @ compare (vBB+1, vCC+1)
1431    blt     .LOP_CMP_LONG_less            @ signed compare on high part
1432    bgt     .LOP_CMP_LONG_greater
1433    subs    r1, r0, r2                  @ r1<- r0 - r2
1434    bhi     .LOP_CMP_LONG_greater         @ unsigned compare on low part
1435    bne     .LOP_CMP_LONG_less
1436    b       .LOP_CMP_LONG_finish          @ equal; r1 already holds 0
1437
1438/* ------------------------------ */
1439    .balign 64
1440.L_OP_IF_EQ: /* 0x32 */
1441/* File: armv5te/OP_IF_EQ.S */
1442/* File: armv5te/bincmp.S */
1443    /*
1444     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1445     * fragment that specifies the *reverse* comparison to perform, e.g.
1446     * for "if-le" you would use "gt".
1447     *
1448     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1449     */
1450    /* if-cmp vA, vB, +CCCC */
1451    mov     r0, rINST, lsr #8           @ r0<- A+
1452    mov     r1, rINST, lsr #12          @ r1<- B
1453    and     r0, r0, #15
1454    GET_VREG(r3, r1)                    @ r3<- vB
1455    GET_VREG(r2, r0)                    @ r2<- vA
1456    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1457    cmp     r2, r3                      @ compare (vA, vB)
1458    bne  1f                      @ branch to 1 if comparison failed
1459    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1460    movs    r9, r9, asl #1              @ convert to bytes, check sign
1461    bmi     common_backwardBranch       @ yes, do periodic checks
14621:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1463    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1464    GOTO_OPCODE(ip)                     @ jump to next instruction
1465
1466
1467
1468/* ------------------------------ */
1469    .balign 64
1470.L_OP_IF_NE: /* 0x33 */
1471/* File: armv5te/OP_IF_NE.S */
1472/* File: armv5te/bincmp.S */
1473    /*
1474     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1475     * fragment that specifies the *reverse* comparison to perform, e.g.
1476     * for "if-le" you would use "gt".
1477     *
1478     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1479     */
1480    /* if-cmp vA, vB, +CCCC */
1481    mov     r0, rINST, lsr #8           @ r0<- A+
1482    mov     r1, rINST, lsr #12          @ r1<- B
1483    and     r0, r0, #15
1484    GET_VREG(r3, r1)                    @ r3<- vB
1485    GET_VREG(r2, r0)                    @ r2<- vA
1486    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1487    cmp     r2, r3                      @ compare (vA, vB)
1488    beq  1f                      @ branch to 1 if comparison failed
1489    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1490    movs    r9, r9, asl #1              @ convert to bytes, check sign
1491    bmi     common_backwardBranch       @ yes, do periodic checks
14921:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1493    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1494    GOTO_OPCODE(ip)                     @ jump to next instruction
1495
1496
1497
1498/* ------------------------------ */
1499    .balign 64
1500.L_OP_IF_LT: /* 0x34 */
1501/* File: armv5te/OP_IF_LT.S */
1502/* File: armv5te/bincmp.S */
1503    /*
1504     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1505     * fragment that specifies the *reverse* comparison to perform, e.g.
1506     * for "if-le" you would use "gt".
1507     *
1508     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1509     */
1510    /* if-cmp vA, vB, +CCCC */
1511    mov     r0, rINST, lsr #8           @ r0<- A+
1512    mov     r1, rINST, lsr #12          @ r1<- B
1513    and     r0, r0, #15
1514    GET_VREG(r3, r1)                    @ r3<- vB
1515    GET_VREG(r2, r0)                    @ r2<- vA
1516    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1517    cmp     r2, r3                      @ compare (vA, vB)
1518    bge  1f                      @ branch to 1 if comparison failed
1519    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1520    movs    r9, r9, asl #1              @ convert to bytes, check sign
1521    bmi     common_backwardBranch       @ yes, do periodic checks
15221:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1523    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1524    GOTO_OPCODE(ip)                     @ jump to next instruction
1525
1526
1527
1528/* ------------------------------ */
1529    .balign 64
1530.L_OP_IF_GE: /* 0x35 */
1531/* File: armv5te/OP_IF_GE.S */
1532/* File: armv5te/bincmp.S */
1533    /*
1534     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1535     * fragment that specifies the *reverse* comparison to perform, e.g.
1536     * for "if-le" you would use "gt".
1537     *
1538     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1539     */
1540    /* if-cmp vA, vB, +CCCC */
1541    mov     r0, rINST, lsr #8           @ r0<- A+
1542    mov     r1, rINST, lsr #12          @ r1<- B
1543    and     r0, r0, #15
1544    GET_VREG(r3, r1)                    @ r3<- vB
1545    GET_VREG(r2, r0)                    @ r2<- vA
1546    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1547    cmp     r2, r3                      @ compare (vA, vB)
1548    blt  1f                      @ branch to 1 if comparison failed
1549    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1550    movs    r9, r9, asl #1              @ convert to bytes, check sign
1551    bmi     common_backwardBranch       @ yes, do periodic checks
15521:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1553    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1554    GOTO_OPCODE(ip)                     @ jump to next instruction
1555
1556
1557
1558/* ------------------------------ */
1559    .balign 64
1560.L_OP_IF_GT: /* 0x36 */
1561/* File: armv5te/OP_IF_GT.S */
1562/* File: armv5te/bincmp.S */
1563    /*
1564     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1565     * fragment that specifies the *reverse* comparison to perform, e.g.
1566     * for "if-le" you would use "gt".
1567     *
1568     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1569     */
1570    /* if-cmp vA, vB, +CCCC */
1571    mov     r0, rINST, lsr #8           @ r0<- A+
1572    mov     r1, rINST, lsr #12          @ r1<- B
1573    and     r0, r0, #15
1574    GET_VREG(r3, r1)                    @ r3<- vB
1575    GET_VREG(r2, r0)                    @ r2<- vA
1576    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1577    cmp     r2, r3                      @ compare (vA, vB)
1578    ble  1f                      @ branch to 1 if comparison failed
1579    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1580    movs    r9, r9, asl #1              @ convert to bytes, check sign
1581    bmi     common_backwardBranch       @ yes, do periodic checks
15821:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1583    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1584    GOTO_OPCODE(ip)                     @ jump to next instruction
1585
1586
1587
1588/* ------------------------------ */
1589    .balign 64
1590.L_OP_IF_LE: /* 0x37 */
1591/* File: armv5te/OP_IF_LE.S */
1592/* File: armv5te/bincmp.S */
1593    /*
1594     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1595     * fragment that specifies the *reverse* comparison to perform, e.g.
1596     * for "if-le" you would use "gt".
1597     *
1598     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1599     */
1600    /* if-cmp vA, vB, +CCCC */
1601    mov     r0, rINST, lsr #8           @ r0<- A+
1602    mov     r1, rINST, lsr #12          @ r1<- B
1603    and     r0, r0, #15
1604    GET_VREG(r3, r1)                    @ r3<- vB
1605    GET_VREG(r2, r0)                    @ r2<- vA
1606    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1607    cmp     r2, r3                      @ compare (vA, vB)
1608    bgt  1f                      @ branch to 1 if comparison failed
1609    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1610    movs    r9, r9, asl #1              @ convert to bytes, check sign
1611    bmi     common_backwardBranch       @ yes, do periodic checks
16121:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1613    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1614    GOTO_OPCODE(ip)                     @ jump to next instruction
1615
1616
1617
1618/* ------------------------------ */
1619    .balign 64
1620.L_OP_IF_EQZ: /* 0x38 */
1621/* File: armv5te/OP_IF_EQZ.S */
1622/* File: armv5te/zcmp.S */
1623    /*
1624     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1625     * fragment that specifies the *reverse* comparison to perform, e.g.
1626     * for "if-le" you would use "gt".
1627     *
1628     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1629     */
1630    /* if-cmp vAA, +BBBB */
1631    mov     r0, rINST, lsr #8           @ r0<- AA
1632    GET_VREG(r2, r0)                    @ r2<- vAA
1633    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1634    cmp     r2, #0                      @ compare (vA, 0)
1635    bne  1f                      @ branch to 1 if comparison failed
1636    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1637    movs    r9, r9, asl #1              @ convert to bytes, check sign
1638    bmi     common_backwardBranch       @ backward branch, do periodic checks
16391:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1640    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1641    GOTO_OPCODE(ip)                     @ jump to next instruction
1642
1643
1644
1645/* ------------------------------ */
1646    .balign 64
1647.L_OP_IF_NEZ: /* 0x39 */
1648/* File: armv5te/OP_IF_NEZ.S */
1649/* File: armv5te/zcmp.S */
1650    /*
1651     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1652     * fragment that specifies the *reverse* comparison to perform, e.g.
1653     * for "if-le" you would use "gt".
1654     *
1655     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1656     */
1657    /* if-cmp vAA, +BBBB */
1658    mov     r0, rINST, lsr #8           @ r0<- AA
1659    GET_VREG(r2, r0)                    @ r2<- vAA
1660    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1661    cmp     r2, #0                      @ compare (vA, 0)
1662    beq  1f                      @ branch to 1 if comparison failed
1663    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1664    movs    r9, r9, asl #1              @ convert to bytes, check sign
1665    bmi     common_backwardBranch       @ backward branch, do periodic checks
16661:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1667    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1668    GOTO_OPCODE(ip)                     @ jump to next instruction
1669
1670
1671
1672/* ------------------------------ */
1673    .balign 64
1674.L_OP_IF_LTZ: /* 0x3a */
1675/* File: armv5te/OP_IF_LTZ.S */
1676/* File: armv5te/zcmp.S */
1677    /*
1678     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1679     * fragment that specifies the *reverse* comparison to perform, e.g.
1680     * for "if-le" you would use "gt".
1681     *
1682     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1683     */
1684    /* if-cmp vAA, +BBBB */
1685    mov     r0, rINST, lsr #8           @ r0<- AA
1686    GET_VREG(r2, r0)                    @ r2<- vAA
1687    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1688    cmp     r2, #0                      @ compare (vA, 0)
1689    bge  1f                      @ branch to 1 if comparison failed
1690    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1691    movs    r9, r9, asl #1              @ convert to bytes, check sign
1692    bmi     common_backwardBranch       @ backward branch, do periodic checks
16931:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1694    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1695    GOTO_OPCODE(ip)                     @ jump to next instruction
1696
1697
1698
1699/* ------------------------------ */
1700    .balign 64
1701.L_OP_IF_GEZ: /* 0x3b */
1702/* File: armv5te/OP_IF_GEZ.S */
1703/* File: armv5te/zcmp.S */
1704    /*
1705     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1706     * fragment that specifies the *reverse* comparison to perform, e.g.
1707     * for "if-le" you would use "gt".
1708     *
1709     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1710     */
1711    /* if-cmp vAA, +BBBB */
1712    mov     r0, rINST, lsr #8           @ r0<- AA
1713    GET_VREG(r2, r0)                    @ r2<- vAA
1714    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1715    cmp     r2, #0                      @ compare (vA, 0)
1716    blt  1f                      @ branch to 1 if comparison failed
1717    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1718    movs    r9, r9, asl #1              @ convert to bytes, check sign
1719    bmi     common_backwardBranch       @ backward branch, do periodic checks
17201:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1721    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1722    GOTO_OPCODE(ip)                     @ jump to next instruction
1723
1724
1725
1726/* ------------------------------ */
1727    .balign 64
1728.L_OP_IF_GTZ: /* 0x3c */
1729/* File: armv5te/OP_IF_GTZ.S */
1730/* File: armv5te/zcmp.S */
1731    /*
1732     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1733     * fragment that specifies the *reverse* comparison to perform, e.g.
1734     * for "if-le" you would use "gt".
1735     *
1736     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1737     */
1738    /* if-cmp vAA, +BBBB */
1739    mov     r0, rINST, lsr #8           @ r0<- AA
1740    GET_VREG(r2, r0)                    @ r2<- vAA
1741    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1742    cmp     r2, #0                      @ compare (vA, 0)
1743    ble  1f                      @ branch to 1 if comparison failed
1744    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1745    movs    r9, r9, asl #1              @ convert to bytes, check sign
1746    bmi     common_backwardBranch       @ backward branch, do periodic checks
17471:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1748    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1749    GOTO_OPCODE(ip)                     @ jump to next instruction
1750
1751
1752
1753/* ------------------------------ */
1754    .balign 64
1755.L_OP_IF_LEZ: /* 0x3d */
1756/* File: armv5te/OP_IF_LEZ.S */
1757/* File: armv5te/zcmp.S */
1758    /*
1759     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1760     * fragment that specifies the *reverse* comparison to perform, e.g.
1761     * for "if-le" you would use "gt".
1762     *
1763     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1764     */
1765    /* if-cmp vAA, +BBBB */
1766    mov     r0, rINST, lsr #8           @ r0<- AA
1767    GET_VREG(r2, r0)                    @ r2<- vAA
1768    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1769    cmp     r2, #0                      @ compare (vA, 0)
1770    bgt  1f                      @ branch to 1 if comparison failed
1771    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1772    movs    r9, r9, asl #1              @ convert to bytes, check sign
1773    bmi     common_backwardBranch       @ backward branch, do periodic checks
17741:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1775    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1776    GOTO_OPCODE(ip)                     @ jump to next instruction
1777
1778
1779
1780/* ------------------------------ */
1781    .balign 64
1782.L_OP_UNUSED_3E: /* 0x3e */
1783/* File: armv5te/OP_UNUSED_3E.S */
1784/* File: armv5te/unused.S */
1785    bl      common_abort
1786
1787
1788
1789/* ------------------------------ */
1790    .balign 64
1791.L_OP_UNUSED_3F: /* 0x3f */
1792/* File: armv5te/OP_UNUSED_3F.S */
1793/* File: armv5te/unused.S */
1794    bl      common_abort
1795
1796
1797
1798/* ------------------------------ */
1799    .balign 64
1800.L_OP_UNUSED_40: /* 0x40 */
1801/* File: armv5te/OP_UNUSED_40.S */
1802/* File: armv5te/unused.S */
1803    bl      common_abort
1804
1805
1806
1807/* ------------------------------ */
1808    .balign 64
1809.L_OP_UNUSED_41: /* 0x41 */
1810/* File: armv5te/OP_UNUSED_41.S */
1811/* File: armv5te/unused.S */
1812    bl      common_abort
1813
1814
1815
1816/* ------------------------------ */
1817    .balign 64
1818.L_OP_UNUSED_42: /* 0x42 */
1819/* File: armv5te/OP_UNUSED_42.S */
1820/* File: armv5te/unused.S */
1821    bl      common_abort
1822
1823
1824
1825/* ------------------------------ */
1826    .balign 64
1827.L_OP_UNUSED_43: /* 0x43 */
1828/* File: armv5te/OP_UNUSED_43.S */
1829/* File: armv5te/unused.S */
1830    bl      common_abort
1831
1832
1833
1834/* ------------------------------ */
1835    .balign 64
1836.L_OP_AGET: /* 0x44 */
1837/* File: armv5te/OP_AGET.S */
1838    /*
1839     * Array get, 32 bits or less.  vAA <- vBB[vCC].
1840     *
1841     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
1842     * instructions.  We use a pair of FETCH_Bs instead.
1843     *
1844     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1845     */
1846    /* op vAA, vBB, vCC */
1847    FETCH_B(r2, 1, 0)                   @ r2<- BB
1848    mov     r9, rINST, lsr #8           @ r9<- AA
1849    FETCH_B(r3, 1, 1)                   @ r3<- CC
1850    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
1851    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
1852    cmp     r0, #0                      @ null array object?
1853    beq     common_errNullObject        @ yes, bail
1854    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
1855    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
1856    cmp     r1, r3                      @ compare unsigned index, length
1857    bcs     common_errArrayIndex        @ index >= length, bail
1858    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1859    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
1860    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1861    SET_VREG(r2, r9)                    @ vAA<- r2
1862    GOTO_OPCODE(ip)                     @ jump to next instruction
1863
1864
1865/* ------------------------------ */
1866    .balign 64
1867.L_OP_AGET_WIDE: /* 0x45 */
1868/* File: armv4t/OP_AGET_WIDE.S */
1869    /*
1870     * Array get, 64 bits.  vAA <- vBB[vCC].
1871     *
1872     * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD.
1873     */
1874    /* aget-wide vAA, vBB, vCC */
1875    FETCH(r0, 1)                        @ r0<- CCBB
1876    mov     r9, rINST, lsr #8           @ r9<- AA
1877    and     r2, r0, #255                @ r2<- BB
1878    mov     r3, r0, lsr #8              @ r3<- CC
1879    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
1880    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
1881    cmp     r0, #0                      @ null array object?
1882    beq     common_errNullObject        @ yes, bail
1883    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
1884    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
1885    cmp     r1, r3                      @ compare unsigned index, length
1886    bcc     .LOP_AGET_WIDE_finish          @ okay, continue below
1887    b       common_errArrayIndex        @ index >= length, bail
1888    @ May want to swap the order of these two branches depending on how the
1889    @ branch prediction (if any) handles conditional forward branches vs.
1890    @ unconditional forward branches.
1891
1892/* ------------------------------ */
1893    .balign 64
1894.L_OP_AGET_OBJECT: /* 0x46 */
1895/* File: armv5te/OP_AGET_OBJECT.S */
1896/* File: armv5te/OP_AGET.S */
1897    /*
1898     * Array get, 32 bits or less.  vAA <- vBB[vCC].
1899     *
1900     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
1901     * instructions.  We use a pair of FETCH_Bs instead.
1902     *
1903     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1904     */
1905    /* op vAA, vBB, vCC */
1906    FETCH_B(r2, 1, 0)                   @ r2<- BB
1907    mov     r9, rINST, lsr #8           @ r9<- AA
1908    FETCH_B(r3, 1, 1)                   @ r3<- CC
1909    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
1910    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
1911    cmp     r0, #0                      @ null array object?
1912    beq     common_errNullObject        @ yes, bail
1913    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
1914    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
1915    cmp     r1, r3                      @ compare unsigned index, length
1916    bcs     common_errArrayIndex        @ index >= length, bail
1917    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1918    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
1919    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1920    SET_VREG(r2, r9)                    @ vAA<- r2
1921    GOTO_OPCODE(ip)                     @ jump to next instruction
1922
1923
1924
1925/* ------------------------------ */
1926    .balign 64
1927.L_OP_AGET_BOOLEAN: /* 0x47 */
1928/* File: armv5te/OP_AGET_BOOLEAN.S */
1929/* File: armv5te/OP_AGET.S */
1930    /*
1931     * Array get, 32 bits or less.  vAA <- vBB[vCC].
1932     *
1933     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
1934     * instructions.  We use a pair of FETCH_Bs instead.
1935     *
1936     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1937     */
1938    /* op vAA, vBB, vCC */
1939    FETCH_B(r2, 1, 0)                   @ r2<- BB
1940    mov     r9, rINST, lsr #8           @ r9<- AA
1941    FETCH_B(r3, 1, 1)                   @ r3<- CC
1942    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
1943    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
1944    cmp     r0, #0                      @ null array object?
1945    beq     common_errNullObject        @ yes, bail
1946    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
1947    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
1948    cmp     r1, r3                      @ compare unsigned index, length
1949    bcs     common_errArrayIndex        @ index >= length, bail
1950    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1951    ldrb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
1952    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1953    SET_VREG(r2, r9)                    @ vAA<- r2
1954    GOTO_OPCODE(ip)                     @ jump to next instruction
1955
1956
1957
1958/* ------------------------------ */
1959    .balign 64
1960.L_OP_AGET_BYTE: /* 0x48 */
1961/* File: armv5te/OP_AGET_BYTE.S */
1962/* File: armv5te/OP_AGET.S */
1963    /*
1964     * Array get, 32 bits or less.  vAA <- vBB[vCC].
1965     *
1966     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
1967     * instructions.  We use a pair of FETCH_Bs instead.
1968     *
1969     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1970     */
1971    /* op vAA, vBB, vCC */
1972    FETCH_B(r2, 1, 0)                   @ r2<- BB
1973    mov     r9, rINST, lsr #8           @ r9<- AA
1974    FETCH_B(r3, 1, 1)                   @ r3<- CC
1975    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
1976    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
1977    cmp     r0, #0                      @ null array object?
1978    beq     common_errNullObject        @ yes, bail
1979    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
1980    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
1981    cmp     r1, r3                      @ compare unsigned index, length
1982    bcs     common_errArrayIndex        @ index >= length, bail
1983    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1984    ldrsb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
1985    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1986    SET_VREG(r2, r9)                    @ vAA<- r2
1987    GOTO_OPCODE(ip)                     @ jump to next instruction
1988
1989
1990
1991/* ------------------------------ */
1992    .balign 64
1993.L_OP_AGET_CHAR: /* 0x49 */
1994/* File: armv5te/OP_AGET_CHAR.S */
1995/* File: armv5te/OP_AGET.S */
1996    /*
1997     * Array get, 32 bits or less.  vAA <- vBB[vCC].
1998     *
1999     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2000     * instructions.  We use a pair of FETCH_Bs instead.
2001     *
2002     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2003     */
2004    /* op vAA, vBB, vCC */
2005    FETCH_B(r2, 1, 0)                   @ r2<- BB
2006    mov     r9, rINST, lsr #8           @ r9<- AA
2007    FETCH_B(r3, 1, 1)                   @ r3<- CC
2008    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2009    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2010    cmp     r0, #0                      @ null array object?
2011    beq     common_errNullObject        @ yes, bail
2012    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2013    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2014    cmp     r1, r3                      @ compare unsigned index, length
2015    bcs     common_errArrayIndex        @ index >= length, bail
2016    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2017    ldrh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2018    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2019    SET_VREG(r2, r9)                    @ vAA<- r2
2020    GOTO_OPCODE(ip)                     @ jump to next instruction
2021
2022
2023
2024/* ------------------------------ */
2025    .balign 64
2026.L_OP_AGET_SHORT: /* 0x4a */
2027/* File: armv5te/OP_AGET_SHORT.S */
2028/* File: armv5te/OP_AGET.S */
2029    /*
2030     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2031     *
2032     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2033     * instructions.  We use a pair of FETCH_Bs instead.
2034     *
2035     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2036     */
2037    /* op vAA, vBB, vCC */
2038    FETCH_B(r2, 1, 0)                   @ r2<- BB
2039    mov     r9, rINST, lsr #8           @ r9<- AA
2040    FETCH_B(r3, 1, 1)                   @ r3<- CC
2041    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2042    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2043    cmp     r0, #0                      @ null array object?
2044    beq     common_errNullObject        @ yes, bail
2045    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2046    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2047    cmp     r1, r3                      @ compare unsigned index, length
2048    bcs     common_errArrayIndex        @ index >= length, bail
2049    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2050    ldrsh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2051    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2052    SET_VREG(r2, r9)                    @ vAA<- r2
2053    GOTO_OPCODE(ip)                     @ jump to next instruction
2054
2055
2056
2057/* ------------------------------ */
2058    .balign 64
2059.L_OP_APUT: /* 0x4b */
2060/* File: armv5te/OP_APUT.S */
2061    /*
2062     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2063     *
2064     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2065     * instructions.  We use a pair of FETCH_Bs instead.
2066     *
2067     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2068     */
2069    /* op vAA, vBB, vCC */
2070    FETCH_B(r2, 1, 0)                   @ r2<- BB
2071    mov     r9, rINST, lsr #8           @ r9<- AA
2072    FETCH_B(r3, 1, 1)                   @ r3<- CC
2073    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2074    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2075    cmp     r0, #0                      @ null array object?
2076    beq     common_errNullObject        @ yes, bail
2077    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2078    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2079    cmp     r1, r3                      @ compare unsigned index, length
2080    bcs     common_errArrayIndex        @ index >= length, bail
2081    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2082    GET_VREG(r2, r9)                    @ r2<- vAA
2083    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2084    str  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2085    GOTO_OPCODE(ip)                     @ jump to next instruction
2086
2087
2088/* ------------------------------ */
2089    .balign 64
2090.L_OP_APUT_WIDE: /* 0x4c */
2091/* File: armv4t/OP_APUT_WIDE.S */
2092    /*
2093     * Array put, 64 bits.  vBB[vCC] <- vAA.
2094     */
2095    /* aput-wide vAA, vBB, vCC */
2096    FETCH(r0, 1)                        @ r0<- CCBB
2097    mov     r9, rINST, lsr #8           @ r9<- AA
2098    and     r2, r0, #255                @ r2<- BB
2099    mov     r3, r0, lsr #8              @ r3<- CC
2100    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2101    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2102    cmp     r0, #0                      @ null array object?
2103    beq     common_errNullObject        @ yes, bail
2104    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2105    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2106    cmp     r1, r3                      @ compare unsigned index, length
2107    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2108    bcc     .LOP_APUT_WIDE_finish          @ okay, continue below
2109    b       common_errArrayIndex        @ index >= length, bail
2110    @ May want to swap the order of these two branches depending on how the
2111    @ branch prediction (if any) handles conditional forward branches vs.
2112    @ unconditional forward branches.
2113
2114/* ------------------------------ */
2115    .balign 64
2116.L_OP_APUT_OBJECT: /* 0x4d */
2117/* File: armv5te/OP_APUT_OBJECT.S */
2118    /*
2119     * Store an object into an array.  vBB[vCC] <- vAA.
2120     *
2121     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2122     * instructions.  We use a pair of FETCH_Bs instead.
2123     */
2124    /* op vAA, vBB, vCC */
2125    FETCH(r0, 1)                        @ r0<- CCBB
2126    mov     r9, rINST, lsr #8           @ r9<- AA
2127    and     r2, r0, #255                @ r2<- BB
2128    mov     r3, r0, lsr #8              @ r3<- CC
2129    GET_VREG(r1, r2)                    @ r1<- vBB (array object)
2130    GET_VREG(r0, r3)                    @ r0<- vCC (requested index)
2131    cmp     r1, #0                      @ null array object?
2132    GET_VREG(r9, r9)                    @ r9<- vAA
2133    beq     common_errNullObject        @ yes, bail
2134    ldr     r3, [r1, #offArrayObject_length]    @ r3<- arrayObj->length
2135    add     r10, r1, r0, lsl #2         @ r10<- arrayObj + index*width
2136    cmp     r0, r3                      @ compare unsigned index, length
2137    bcc     .LOP_APUT_OBJECT_finish          @ we're okay, continue on
2138    b       common_errArrayIndex        @ index >= length, bail
2139
2140
2141/* ------------------------------ */
2142    .balign 64
2143.L_OP_APUT_BOOLEAN: /* 0x4e */
2144/* File: armv5te/OP_APUT_BOOLEAN.S */
2145/* File: armv5te/OP_APUT.S */
2146    /*
2147     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2148     *
2149     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2150     * instructions.  We use a pair of FETCH_Bs instead.
2151     *
2152     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2153     */
2154    /* op vAA, vBB, vCC */
2155    FETCH_B(r2, 1, 0)                   @ r2<- BB
2156    mov     r9, rINST, lsr #8           @ r9<- AA
2157    FETCH_B(r3, 1, 1)                   @ r3<- CC
2158    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2159    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2160    cmp     r0, #0                      @ null array object?
2161    beq     common_errNullObject        @ yes, bail
2162    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2163    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2164    cmp     r1, r3                      @ compare unsigned index, length
2165    bcs     common_errArrayIndex        @ index >= length, bail
2166    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2167    GET_VREG(r2, r9)                    @ r2<- vAA
2168    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2169    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2170    GOTO_OPCODE(ip)                     @ jump to next instruction
2171
2172
2173
2174/* ------------------------------ */
2175    .balign 64
2176.L_OP_APUT_BYTE: /* 0x4f */
2177/* File: armv5te/OP_APUT_BYTE.S */
2178/* File: armv5te/OP_APUT.S */
2179    /*
2180     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2181     *
2182     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2183     * instructions.  We use a pair of FETCH_Bs instead.
2184     *
2185     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2186     */
2187    /* op vAA, vBB, vCC */
2188    FETCH_B(r2, 1, 0)                   @ r2<- BB
2189    mov     r9, rINST, lsr #8           @ r9<- AA
2190    FETCH_B(r3, 1, 1)                   @ r3<- CC
2191    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2192    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2193    cmp     r0, #0                      @ null array object?
2194    beq     common_errNullObject        @ yes, bail
2195    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2196    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2197    cmp     r1, r3                      @ compare unsigned index, length
2198    bcs     common_errArrayIndex        @ index >= length, bail
2199    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2200    GET_VREG(r2, r9)                    @ r2<- vAA
2201    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2202    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2203    GOTO_OPCODE(ip)                     @ jump to next instruction
2204
2205
2206
2207/* ------------------------------ */
2208    .balign 64
2209.L_OP_APUT_CHAR: /* 0x50 */
2210/* File: armv5te/OP_APUT_CHAR.S */
2211/* File: armv5te/OP_APUT.S */
2212    /*
2213     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2214     *
2215     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2216     * instructions.  We use a pair of FETCH_Bs instead.
2217     *
2218     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2219     */
2220    /* op vAA, vBB, vCC */
2221    FETCH_B(r2, 1, 0)                   @ r2<- BB
2222    mov     r9, rINST, lsr #8           @ r9<- AA
2223    FETCH_B(r3, 1, 1)                   @ r3<- CC
2224    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2225    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2226    cmp     r0, #0                      @ null array object?
2227    beq     common_errNullObject        @ yes, bail
2228    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2229    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2230    cmp     r1, r3                      @ compare unsigned index, length
2231    bcs     common_errArrayIndex        @ index >= length, bail
2232    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2233    GET_VREG(r2, r9)                    @ r2<- vAA
2234    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2235    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2236    GOTO_OPCODE(ip)                     @ jump to next instruction
2237
2238
2239
2240/* ------------------------------ */
2241    .balign 64
2242.L_OP_APUT_SHORT: /* 0x51 */
2243/* File: armv5te/OP_APUT_SHORT.S */
2244/* File: armv5te/OP_APUT.S */
2245    /*
2246     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2247     *
2248     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2249     * instructions.  We use a pair of FETCH_Bs instead.
2250     *
2251     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2252     */
2253    /* op vAA, vBB, vCC */
2254    FETCH_B(r2, 1, 0)                   @ r2<- BB
2255    mov     r9, rINST, lsr #8           @ r9<- AA
2256    FETCH_B(r3, 1, 1)                   @ r3<- CC
2257    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2258    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2259    cmp     r0, #0                      @ null array object?
2260    beq     common_errNullObject        @ yes, bail
2261    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2262    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2263    cmp     r1, r3                      @ compare unsigned index, length
2264    bcs     common_errArrayIndex        @ index >= length, bail
2265    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2266    GET_VREG(r2, r9)                    @ r2<- vAA
2267    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2268    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2269    GOTO_OPCODE(ip)                     @ jump to next instruction
2270
2271
2272
2273/* ------------------------------ */
2274    .balign 64
2275.L_OP_IGET: /* 0x52 */
2276/* File: armv5te/OP_IGET.S */
2277    /*
2278     * General 32-bit instance field get.
2279     *
2280     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2281     */
2282    /* op vA, vB, field@CCCC */
2283    mov     r0, rINST, lsr #12          @ r0<- B
2284    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2285    FETCH(r1, 1)                        @ r1<- field ref CCCC
2286    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2287    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2288    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2289    cmp     r0, #0                      @ is resolved entry null?
2290    bne     .LOP_IGET_finish          @ no, already resolved
22918:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2292    EXPORT_PC()                         @ resolve() could throw
2293    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2294    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2295    cmp     r0, #0
2296    bne     .LOP_IGET_finish
2297    b       common_exceptionThrown
2298
2299/* ------------------------------ */
2300    .balign 64
2301.L_OP_IGET_WIDE: /* 0x53 */
2302/* File: armv4t/OP_IGET_WIDE.S */
2303    /*
2304     * Wide 32-bit instance field get.
2305     */
2306    /* iget-wide vA, vB, field@CCCC */
2307    mov     r0, rINST, lsr #12          @ r0<- B
2308    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2309    FETCH(r1, 1)                        @ r1<- field ref CCCC
2310    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2311    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2312    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2313    cmp     r0, #0                      @ is resolved entry null?
2314    bne     .LOP_IGET_WIDE_finish          @ no, already resolved
23158:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2316    EXPORT_PC()                         @ resolve() could throw
2317    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2318    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2319    cmp     r0, #0
2320    bne     .LOP_IGET_WIDE_finish
2321    b       common_exceptionThrown
2322
2323/* ------------------------------ */
2324    .balign 64
2325.L_OP_IGET_OBJECT: /* 0x54 */
2326/* File: armv5te/OP_IGET_OBJECT.S */
2327/* File: armv5te/OP_IGET.S */
2328    /*
2329     * General 32-bit instance field get.
2330     *
2331     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2332     */
2333    /* op vA, vB, field@CCCC */
2334    mov     r0, rINST, lsr #12          @ r0<- B
2335    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2336    FETCH(r1, 1)                        @ r1<- field ref CCCC
2337    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2338    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2339    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2340    cmp     r0, #0                      @ is resolved entry null?
2341    bne     .LOP_IGET_OBJECT_finish          @ no, already resolved
23428:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2343    EXPORT_PC()                         @ resolve() could throw
2344    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2345    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2346    cmp     r0, #0
2347    bne     .LOP_IGET_OBJECT_finish
2348    b       common_exceptionThrown
2349
2350
2351/* ------------------------------ */
2352    .balign 64
2353.L_OP_IGET_BOOLEAN: /* 0x55 */
2354/* File: armv5te/OP_IGET_BOOLEAN.S */
2355@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" }
2356/* File: armv5te/OP_IGET.S */
2357    /*
2358     * General 32-bit instance field get.
2359     *
2360     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2361     */
2362    /* op vA, vB, field@CCCC */
2363    mov     r0, rINST, lsr #12          @ r0<- B
2364    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2365    FETCH(r1, 1)                        @ r1<- field ref CCCC
2366    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2367    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2368    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2369    cmp     r0, #0                      @ is resolved entry null?
2370    bne     .LOP_IGET_BOOLEAN_finish          @ no, already resolved
23718:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2372    EXPORT_PC()                         @ resolve() could throw
2373    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2374    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2375    cmp     r0, #0
2376    bne     .LOP_IGET_BOOLEAN_finish
2377    b       common_exceptionThrown
2378
2379
2380/* ------------------------------ */
2381    .balign 64
2382.L_OP_IGET_BYTE: /* 0x56 */
2383/* File: armv5te/OP_IGET_BYTE.S */
2384@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" }
2385/* File: armv5te/OP_IGET.S */
2386    /*
2387     * General 32-bit instance field get.
2388     *
2389     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2390     */
2391    /* op vA, vB, field@CCCC */
2392    mov     r0, rINST, lsr #12          @ r0<- B
2393    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2394    FETCH(r1, 1)                        @ r1<- field ref CCCC
2395    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2396    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2397    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2398    cmp     r0, #0                      @ is resolved entry null?
2399    bne     .LOP_IGET_BYTE_finish          @ no, already resolved
24008:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2401    EXPORT_PC()                         @ resolve() could throw
2402    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2403    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2404    cmp     r0, #0
2405    bne     .LOP_IGET_BYTE_finish
2406    b       common_exceptionThrown
2407
2408
2409/* ------------------------------ */
2410    .balign 64
2411.L_OP_IGET_CHAR: /* 0x57 */
2412/* File: armv5te/OP_IGET_CHAR.S */
2413@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" }
2414/* File: armv5te/OP_IGET.S */
2415    /*
2416     * General 32-bit instance field get.
2417     *
2418     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2419     */
2420    /* op vA, vB, field@CCCC */
2421    mov     r0, rINST, lsr #12          @ r0<- B
2422    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2423    FETCH(r1, 1)                        @ r1<- field ref CCCC
2424    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2425    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2426    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2427    cmp     r0, #0                      @ is resolved entry null?
2428    bne     .LOP_IGET_CHAR_finish          @ no, already resolved
24298:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2430    EXPORT_PC()                         @ resolve() could throw
2431    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2432    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2433    cmp     r0, #0
2434    bne     .LOP_IGET_CHAR_finish
2435    b       common_exceptionThrown
2436
2437
2438/* ------------------------------ */
2439    .balign 64
2440.L_OP_IGET_SHORT: /* 0x58 */
2441/* File: armv5te/OP_IGET_SHORT.S */
2442@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" }
2443/* File: armv5te/OP_IGET.S */
2444    /*
2445     * General 32-bit instance field get.
2446     *
2447     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2448     */
2449    /* op vA, vB, field@CCCC */
2450    mov     r0, rINST, lsr #12          @ r0<- B
2451    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2452    FETCH(r1, 1)                        @ r1<- field ref CCCC
2453    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2454    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2455    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2456    cmp     r0, #0                      @ is resolved entry null?
2457    bne     .LOP_IGET_SHORT_finish          @ no, already resolved
24588:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2459    EXPORT_PC()                         @ resolve() could throw
2460    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2461    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2462    cmp     r0, #0
2463    bne     .LOP_IGET_SHORT_finish
2464    b       common_exceptionThrown
2465
2466
2467/* ------------------------------ */
2468    .balign 64
2469.L_OP_IPUT: /* 0x59 */
2470/* File: armv5te/OP_IPUT.S */
2471    /*
2472     * General 32-bit instance field put.
2473     *
2474     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2475     */
2476    /* op vA, vB, field@CCCC */
2477    mov     r0, rINST, lsr #12          @ r0<- B
2478    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2479    FETCH(r1, 1)                        @ r1<- field ref CCCC
2480    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2481    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2482    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2483    cmp     r0, #0                      @ is resolved entry null?
2484    bne     .LOP_IPUT_finish          @ no, already resolved
24858:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2486    EXPORT_PC()                         @ resolve() could throw
2487    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2488    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2489    cmp     r0, #0                      @ success?
2490    bne     .LOP_IPUT_finish          @ yes, finish up
2491    b       common_exceptionThrown
2492
2493/* ------------------------------ */
2494    .balign 64
2495.L_OP_IPUT_WIDE: /* 0x5a */
2496/* File: armv4t/OP_IPUT_WIDE.S */
2497    /* iput-wide vA, vB, field@CCCC */
2498    mov     r0, rINST, lsr #12          @ r0<- B
2499    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2500    FETCH(r1, 1)                        @ r1<- field ref CCCC
2501    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2502    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2503    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2504    cmp     r0, #0                      @ is resolved entry null?
2505    bne     .LOP_IPUT_WIDE_finish          @ no, already resolved
25068:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2507    EXPORT_PC()                         @ resolve() could throw
2508    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2509    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2510    cmp     r0, #0                      @ success?
2511    bne     .LOP_IPUT_WIDE_finish          @ yes, finish up
2512    b       common_exceptionThrown
2513
2514/* ------------------------------ */
2515    .balign 64
2516.L_OP_IPUT_OBJECT: /* 0x5b */
2517/* File: armv5te/OP_IPUT_OBJECT.S */
2518/* File: armv5te/OP_IPUT.S */
2519    /*
2520     * General 32-bit instance field put.
2521     *
2522     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2523     */
2524    /* op vA, vB, field@CCCC */
2525    mov     r0, rINST, lsr #12          @ r0<- B
2526    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2527    FETCH(r1, 1)                        @ r1<- field ref CCCC
2528    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2529    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2530    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2531    cmp     r0, #0                      @ is resolved entry null?
2532    bne     .LOP_IPUT_OBJECT_finish          @ no, already resolved
25338:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2534    EXPORT_PC()                         @ resolve() could throw
2535    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2536    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2537    cmp     r0, #0                      @ success?
2538    bne     .LOP_IPUT_OBJECT_finish          @ yes, finish up
2539    b       common_exceptionThrown
2540
2541
2542/* ------------------------------ */
2543    .balign 64
2544.L_OP_IPUT_BOOLEAN: /* 0x5c */
2545/* File: armv5te/OP_IPUT_BOOLEAN.S */
2546@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" }
2547/* File: armv5te/OP_IPUT.S */
2548    /*
2549     * General 32-bit instance field put.
2550     *
2551     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2552     */
2553    /* op vA, vB, field@CCCC */
2554    mov     r0, rINST, lsr #12          @ r0<- B
2555    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2556    FETCH(r1, 1)                        @ r1<- field ref CCCC
2557    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2558    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2559    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2560    cmp     r0, #0                      @ is resolved entry null?
2561    bne     .LOP_IPUT_BOOLEAN_finish          @ no, already resolved
25628:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2563    EXPORT_PC()                         @ resolve() could throw
2564    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2565    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2566    cmp     r0, #0                      @ success?
2567    bne     .LOP_IPUT_BOOLEAN_finish          @ yes, finish up
2568    b       common_exceptionThrown
2569
2570
2571/* ------------------------------ */
2572    .balign 64
2573.L_OP_IPUT_BYTE: /* 0x5d */
2574/* File: armv5te/OP_IPUT_BYTE.S */
2575@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" }
2576/* File: armv5te/OP_IPUT.S */
2577    /*
2578     * General 32-bit instance field put.
2579     *
2580     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2581     */
2582    /* op vA, vB, field@CCCC */
2583    mov     r0, rINST, lsr #12          @ r0<- B
2584    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2585    FETCH(r1, 1)                        @ r1<- field ref CCCC
2586    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2587    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2588    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2589    cmp     r0, #0                      @ is resolved entry null?
2590    bne     .LOP_IPUT_BYTE_finish          @ no, already resolved
25918:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2592    EXPORT_PC()                         @ resolve() could throw
2593    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2594    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2595    cmp     r0, #0                      @ success?
2596    bne     .LOP_IPUT_BYTE_finish          @ yes, finish up
2597    b       common_exceptionThrown
2598
2599
2600/* ------------------------------ */
2601    .balign 64
2602.L_OP_IPUT_CHAR: /* 0x5e */
2603/* File: armv5te/OP_IPUT_CHAR.S */
2604@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" }
2605/* File: armv5te/OP_IPUT.S */
2606    /*
2607     * General 32-bit instance field put.
2608     *
2609     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2610     */
2611    /* op vA, vB, field@CCCC */
2612    mov     r0, rINST, lsr #12          @ r0<- B
2613    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2614    FETCH(r1, 1)                        @ r1<- field ref CCCC
2615    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2616    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2617    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2618    cmp     r0, #0                      @ is resolved entry null?
2619    bne     .LOP_IPUT_CHAR_finish          @ no, already resolved
26208:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2621    EXPORT_PC()                         @ resolve() could throw
2622    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2623    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2624    cmp     r0, #0                      @ success?
2625    bne     .LOP_IPUT_CHAR_finish          @ yes, finish up
2626    b       common_exceptionThrown
2627
2628
2629/* ------------------------------ */
2630    .balign 64
2631.L_OP_IPUT_SHORT: /* 0x5f */
2632/* File: armv5te/OP_IPUT_SHORT.S */
2633@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" }
2634/* File: armv5te/OP_IPUT.S */
2635    /*
2636     * General 32-bit instance field put.
2637     *
2638     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2639     */
2640    /* op vA, vB, field@CCCC */
2641    mov     r0, rINST, lsr #12          @ r0<- B
2642    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2643    FETCH(r1, 1)                        @ r1<- field ref CCCC
2644    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2645    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2646    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2647    cmp     r0, #0                      @ is resolved entry null?
2648    bne     .LOP_IPUT_SHORT_finish          @ no, already resolved
26498:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2650    EXPORT_PC()                         @ resolve() could throw
2651    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2652    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2653    cmp     r0, #0                      @ success?
2654    bne     .LOP_IPUT_SHORT_finish          @ yes, finish up
2655    b       common_exceptionThrown
2656
2657
2658/* ------------------------------ */
2659    .balign 64
2660.L_OP_SGET: /* 0x60 */
2661/* File: armv5te/OP_SGET.S */
2662    /*
2663     * General 32-bit SGET handler.
2664     *
2665     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2666     */
2667    /* op vAA, field@BBBB */
2668    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2669    FETCH(r1, 1)                        @ r1<- field ref BBBB
2670    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2671    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2672    cmp     r0, #0                      @ is resolved entry null?
2673    beq     .LOP_SGET_resolve         @ yes, do resolve
2674.LOP_SGET_finish: @ field ptr in r0
2675    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2676    mov     r2, rINST, lsr #8           @ r2<- AA
2677    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2678    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2679    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2680    GOTO_OPCODE(ip)                     @ jump to next instruction
2681
2682/* ------------------------------ */
2683    .balign 64
2684.L_OP_SGET_WIDE: /* 0x61 */
2685/* File: armv4t/OP_SGET_WIDE.S */
2686    /*
2687     * 64-bit SGET handler.
2688     */
2689    /* sget-wide vAA, field@BBBB */
2690    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2691    FETCH(r1, 1)                        @ r1<- field ref BBBB
2692    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2693    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2694    cmp     r0, #0                      @ is resolved entry null?
2695    beq     .LOP_SGET_WIDE_resolve         @ yes, do resolve
2696.LOP_SGET_WIDE_finish:
2697    mov     r1, rINST, lsr #8           @ r1<- AA
2698    add     r0, r0, #offStaticField_value
2699    ldmia   r0, {r2-r3}                 @ r2/r3<- field value (aligned)
2700    add     r1, rFP, r1, lsl #2         @ r1<- &fp[AA]
2701    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2702    stmia   r1, {r2-r3}                 @ vAA/vAA+1<- r2/r3
2703    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2704    GOTO_OPCODE(ip)                     @ jump to next instruction
2705
2706/* ------------------------------ */
2707    .balign 64
2708.L_OP_SGET_OBJECT: /* 0x62 */
2709/* File: armv5te/OP_SGET_OBJECT.S */
2710/* File: armv5te/OP_SGET.S */
2711    /*
2712     * General 32-bit SGET handler.
2713     *
2714     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2715     */
2716    /* op vAA, field@BBBB */
2717    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2718    FETCH(r1, 1)                        @ r1<- field ref BBBB
2719    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2720    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2721    cmp     r0, #0                      @ is resolved entry null?
2722    beq     .LOP_SGET_OBJECT_resolve         @ yes, do resolve
2723.LOP_SGET_OBJECT_finish: @ field ptr in r0
2724    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2725    mov     r2, rINST, lsr #8           @ r2<- AA
2726    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2727    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2728    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2729    GOTO_OPCODE(ip)                     @ jump to next instruction
2730
2731
2732/* ------------------------------ */
2733    .balign 64
2734.L_OP_SGET_BOOLEAN: /* 0x63 */
2735/* File: armv5te/OP_SGET_BOOLEAN.S */
2736/* File: armv5te/OP_SGET.S */
2737    /*
2738     * General 32-bit SGET handler.
2739     *
2740     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2741     */
2742    /* op vAA, field@BBBB */
2743    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2744    FETCH(r1, 1)                        @ r1<- field ref BBBB
2745    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2746    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2747    cmp     r0, #0                      @ is resolved entry null?
2748    beq     .LOP_SGET_BOOLEAN_resolve         @ yes, do resolve
2749.LOP_SGET_BOOLEAN_finish: @ field ptr in r0
2750    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2751    mov     r2, rINST, lsr #8           @ r2<- AA
2752    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2753    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2754    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2755    GOTO_OPCODE(ip)                     @ jump to next instruction
2756
2757
2758/* ------------------------------ */
2759    .balign 64
2760.L_OP_SGET_BYTE: /* 0x64 */
2761/* File: armv5te/OP_SGET_BYTE.S */
2762/* File: armv5te/OP_SGET.S */
2763    /*
2764     * General 32-bit SGET handler.
2765     *
2766     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2767     */
2768    /* op vAA, field@BBBB */
2769    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2770    FETCH(r1, 1)                        @ r1<- field ref BBBB
2771    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2772    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2773    cmp     r0, #0                      @ is resolved entry null?
2774    beq     .LOP_SGET_BYTE_resolve         @ yes, do resolve
2775.LOP_SGET_BYTE_finish: @ field ptr in r0
2776    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2777    mov     r2, rINST, lsr #8           @ r2<- AA
2778    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2779    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2780    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2781    GOTO_OPCODE(ip)                     @ jump to next instruction
2782
2783
2784/* ------------------------------ */
2785    .balign 64
2786.L_OP_SGET_CHAR: /* 0x65 */
2787/* File: armv5te/OP_SGET_CHAR.S */
2788/* File: armv5te/OP_SGET.S */
2789    /*
2790     * General 32-bit SGET handler.
2791     *
2792     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2793     */
2794    /* op vAA, field@BBBB */
2795    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2796    FETCH(r1, 1)                        @ r1<- field ref BBBB
2797    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2798    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2799    cmp     r0, #0                      @ is resolved entry null?
2800    beq     .LOP_SGET_CHAR_resolve         @ yes, do resolve
2801.LOP_SGET_CHAR_finish: @ field ptr in r0
2802    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2803    mov     r2, rINST, lsr #8           @ r2<- AA
2804    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2805    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2806    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2807    GOTO_OPCODE(ip)                     @ jump to next instruction
2808
2809
2810/* ------------------------------ */
2811    .balign 64
2812.L_OP_SGET_SHORT: /* 0x66 */
2813/* File: armv5te/OP_SGET_SHORT.S */
2814/* File: armv5te/OP_SGET.S */
2815    /*
2816     * General 32-bit SGET handler.
2817     *
2818     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2819     */
2820    /* op vAA, field@BBBB */
2821    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2822    FETCH(r1, 1)                        @ r1<- field ref BBBB
2823    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2824    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2825    cmp     r0, #0                      @ is resolved entry null?
2826    beq     .LOP_SGET_SHORT_resolve         @ yes, do resolve
2827.LOP_SGET_SHORT_finish: @ field ptr in r0
2828    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2829    mov     r2, rINST, lsr #8           @ r2<- AA
2830    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2831    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2832    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2833    GOTO_OPCODE(ip)                     @ jump to next instruction
2834
2835
2836/* ------------------------------ */
2837    .balign 64
2838.L_OP_SPUT: /* 0x67 */
2839/* File: armv5te/OP_SPUT.S */
2840    /*
2841     * General 32-bit SPUT handler.
2842     *
2843     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2844     */
2845    /* op vAA, field@BBBB */
2846    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2847    FETCH(r1, 1)                        @ r1<- field ref BBBB
2848    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2849    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2850    cmp     r0, #0                      @ is resolved entry null?
2851    beq     .LOP_SPUT_resolve         @ yes, do resolve
2852.LOP_SPUT_finish:   @ field ptr in r0
2853    mov     r2, rINST, lsr #8           @ r2<- AA
2854    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2855    GET_VREG(r1, r2)                    @ r1<- fp[AA]
2856    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2857    str     r1, [r0, #offStaticField_value] @ field<- vAA
2858    GOTO_OPCODE(ip)                     @ jump to next instruction
2859
2860/* ------------------------------ */
2861    .balign 64
2862.L_OP_SPUT_WIDE: /* 0x68 */
2863/* File: armv4t/OP_SPUT_WIDE.S */
2864    /*
2865     * 64-bit SPUT handler.
2866     */
2867    /* sput-wide vAA, field@BBBB */
2868    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2869    FETCH(r1, 1)                        @ r1<- field ref BBBB
2870    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2871    mov     r9, rINST, lsr #8           @ r9<- AA
2872    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2873    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2874    cmp     r0, #0                      @ is resolved entry null?
2875    beq     .LOP_SPUT_WIDE_resolve         @ yes, do resolve
2876.LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9
2877    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2878    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
2879    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2880    add     r0, r0, #offStaticField_value
2881    stmia   r0, {r2-r3}                 @ field<- vAA/vAA+1
2882    GOTO_OPCODE(ip)                     @ jump to next instruction
2883
2884/* ------------------------------ */
2885    .balign 64
2886.L_OP_SPUT_OBJECT: /* 0x69 */
2887/* File: armv5te/OP_SPUT_OBJECT.S */
2888/* File: armv5te/OP_SPUT.S */
2889    /*
2890     * General 32-bit SPUT handler.
2891     *
2892     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2893     */
2894    /* op vAA, field@BBBB */
2895    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2896    FETCH(r1, 1)                        @ r1<- field ref BBBB
2897    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2898    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2899    cmp     r0, #0                      @ is resolved entry null?
2900    beq     .LOP_SPUT_OBJECT_resolve         @ yes, do resolve
2901.LOP_SPUT_OBJECT_finish:   @ field ptr in r0
2902    mov     r2, rINST, lsr #8           @ r2<- AA
2903    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2904    GET_VREG(r1, r2)                    @ r1<- fp[AA]
2905    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2906    str     r1, [r0, #offStaticField_value] @ field<- vAA
2907    GOTO_OPCODE(ip)                     @ jump to next instruction
2908
2909
2910/* ------------------------------ */
2911    .balign 64
2912.L_OP_SPUT_BOOLEAN: /* 0x6a */
2913/* File: armv5te/OP_SPUT_BOOLEAN.S */
2914/* File: armv5te/OP_SPUT.S */
2915    /*
2916     * General 32-bit SPUT handler.
2917     *
2918     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2919     */
2920    /* op vAA, field@BBBB */
2921    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2922    FETCH(r1, 1)                        @ r1<- field ref BBBB
2923    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2924    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2925    cmp     r0, #0                      @ is resolved entry null?
2926    beq     .LOP_SPUT_BOOLEAN_resolve         @ yes, do resolve
2927.LOP_SPUT_BOOLEAN_finish:   @ field ptr in r0
2928    mov     r2, rINST, lsr #8           @ r2<- AA
2929    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2930    GET_VREG(r1, r2)                    @ r1<- fp[AA]
2931    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2932    str     r1, [r0, #offStaticField_value] @ field<- vAA
2933    GOTO_OPCODE(ip)                     @ jump to next instruction
2934
2935
2936/* ------------------------------ */
2937    .balign 64
2938.L_OP_SPUT_BYTE: /* 0x6b */
2939/* File: armv5te/OP_SPUT_BYTE.S */
2940/* File: armv5te/OP_SPUT.S */
2941    /*
2942     * General 32-bit SPUT handler.
2943     *
2944     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2945     */
2946    /* op vAA, field@BBBB */
2947    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2948    FETCH(r1, 1)                        @ r1<- field ref BBBB
2949    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2950    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2951    cmp     r0, #0                      @ is resolved entry null?
2952    beq     .LOP_SPUT_BYTE_resolve         @ yes, do resolve
2953.LOP_SPUT_BYTE_finish:   @ field ptr in r0
2954    mov     r2, rINST, lsr #8           @ r2<- AA
2955    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2956    GET_VREG(r1, r2)                    @ r1<- fp[AA]
2957    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2958    str     r1, [r0, #offStaticField_value] @ field<- vAA
2959    GOTO_OPCODE(ip)                     @ jump to next instruction
2960
2961
2962/* ------------------------------ */
2963    .balign 64
2964.L_OP_SPUT_CHAR: /* 0x6c */
2965/* File: armv5te/OP_SPUT_CHAR.S */
2966/* File: armv5te/OP_SPUT.S */
2967    /*
2968     * General 32-bit SPUT handler.
2969     *
2970     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2971     */
2972    /* op vAA, field@BBBB */
2973    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2974    FETCH(r1, 1)                        @ r1<- field ref BBBB
2975    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2976    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2977    cmp     r0, #0                      @ is resolved entry null?
2978    beq     .LOP_SPUT_CHAR_resolve         @ yes, do resolve
2979.LOP_SPUT_CHAR_finish:   @ field ptr in r0
2980    mov     r2, rINST, lsr #8           @ r2<- AA
2981    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2982    GET_VREG(r1, r2)                    @ r1<- fp[AA]
2983    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2984    str     r1, [r0, #offStaticField_value] @ field<- vAA
2985    GOTO_OPCODE(ip)                     @ jump to next instruction
2986
2987
2988/* ------------------------------ */
2989    .balign 64
2990.L_OP_SPUT_SHORT: /* 0x6d */
2991/* File: armv5te/OP_SPUT_SHORT.S */
2992/* File: armv5te/OP_SPUT.S */
2993    /*
2994     * General 32-bit SPUT handler.
2995     *
2996     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2997     */
2998    /* op vAA, field@BBBB */
2999    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3000    FETCH(r1, 1)                        @ r1<- field ref BBBB
3001    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3002    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3003    cmp     r0, #0                      @ is resolved entry null?
3004    beq     .LOP_SPUT_SHORT_resolve         @ yes, do resolve
3005.LOP_SPUT_SHORT_finish:   @ field ptr in r0
3006    mov     r2, rINST, lsr #8           @ r2<- AA
3007    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3008    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3009    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3010    str     r1, [r0, #offStaticField_value] @ field<- vAA
3011    GOTO_OPCODE(ip)                     @ jump to next instruction
3012
3013
3014/* ------------------------------ */
3015    .balign 64
3016.L_OP_INVOKE_VIRTUAL: /* 0x6e */
3017/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3018    /*
3019     * Handle a virtual method call.
3020     *
3021     * for: invoke-virtual, invoke-virtual/range
3022     */
3023    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3024    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3025    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3026    FETCH(r1, 1)                        @ r1<- BBBB
3027    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3028    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3029    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3030    .if     (!0)
3031    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3032    .endif
3033    cmp     r0, #0                      @ already resolved?
3034    EXPORT_PC()                         @ must export for invoke
3035    bne     .LOP_INVOKE_VIRTUAL_continue        @ yes, continue on
3036    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3037    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3038    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3039    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3040    cmp     r0, #0                      @ got null?
3041    bne     .LOP_INVOKE_VIRTUAL_continue        @ no, continue
3042    b       common_exceptionThrown      @ yes, handle exception
3043
3044/* ------------------------------ */
3045    .balign 64
3046.L_OP_INVOKE_SUPER: /* 0x6f */
3047/* File: armv5te/OP_INVOKE_SUPER.S */
3048    /*
3049     * Handle a "super" method call.
3050     *
3051     * for: invoke-super, invoke-super/range
3052     */
3053    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3054    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3055    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3056    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3057    .if     (!0)
3058    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3059    .endif
3060    FETCH(r1, 1)                        @ r1<- BBBB
3061    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3062    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3063    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3064    cmp     r2, #0                      @ null "this"?
3065    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3066    beq     common_errNullObject        @ null "this", throw exception
3067    cmp     r0, #0                      @ already resolved?
3068    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3069    EXPORT_PC()                         @ must export for invoke
3070    bne     .LOP_INVOKE_SUPER_continue        @ resolved, continue on
3071    b       .LOP_INVOKE_SUPER_resolve         @ do resolve now
3072
3073/* ------------------------------ */
3074    .balign 64
3075.L_OP_INVOKE_DIRECT: /* 0x70 */
3076/* File: armv5te/OP_INVOKE_DIRECT.S */
3077    /*
3078     * Handle a direct method call.
3079     *
3080     * (We could defer the "is 'this' pointer null" test to the common
3081     * method invocation code, and use a flag to indicate that static
3082     * calls don't count.  If we do this as part of copying the arguments
3083     * out we could avoiding loading the first arg twice.)
3084     *
3085     * for: invoke-direct, invoke-direct/range
3086     */
3087    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3088    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3089    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3090    FETCH(r1, 1)                        @ r1<- BBBB
3091    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3092    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3093    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3094    .if     (!0)
3095    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3096    .endif
3097    cmp     r0, #0                      @ already resolved?
3098    EXPORT_PC()                         @ must export for invoke
3099    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3100    beq     .LOP_INVOKE_DIRECT_resolve         @ not resolved, do it now
3101.LOP_INVOKE_DIRECT_finish:
3102    cmp     r2, #0                      @ null "this" ref?
3103    bne     common_invokeMethodNoRange   @ no, continue on
3104    b       common_errNullObject        @ yes, throw exception
3105
3106/* ------------------------------ */
3107    .balign 64
3108.L_OP_INVOKE_STATIC: /* 0x71 */
3109/* File: armv5te/OP_INVOKE_STATIC.S */
3110    /*
3111     * Handle a static method call.
3112     *
3113     * for: invoke-static, invoke-static/range
3114     */
3115    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3116    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3117    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3118    FETCH(r1, 1)                        @ r1<- BBBB
3119    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3120    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3121    cmp     r0, #0                      @ already resolved?
3122    EXPORT_PC()                         @ must export for invoke
3123    bne     common_invokeMethodNoRange @ yes, continue on
31240:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3125    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3126    mov     r2, #METHOD_STATIC          @ resolver method type
3127    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3128    cmp     r0, #0                      @ got null?
3129    bne     common_invokeMethodNoRange @ no, continue
3130    b       common_exceptionThrown      @ yes, handle exception
3131
3132
3133/* ------------------------------ */
3134    .balign 64
3135.L_OP_INVOKE_INTERFACE: /* 0x72 */
3136/* File: armv5te/OP_INVOKE_INTERFACE.S */
3137    /*
3138     * Handle an interface method call.
3139     *
3140     * for: invoke-interface, invoke-interface/range
3141     */
3142    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3143    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3144    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3145    FETCH(r1, 1)                        @ r1<- BBBB
3146    .if     (!0)
3147    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3148    .endif
3149    EXPORT_PC()                         @ must export for invoke
3150    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3151    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3152    cmp     r0, #0                      @ null obj?
3153    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3154    beq     common_errNullObject        @ yes, fail
3155    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3156    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3157    cmp     r0, #0                      @ failed?
3158    beq     common_exceptionThrown      @ yes, handle exception
3159    b       common_invokeMethodNoRange @ jump to common handler
3160
3161
3162/* ------------------------------ */
3163    .balign 64
3164.L_OP_UNUSED_73: /* 0x73 */
3165/* File: armv5te/OP_UNUSED_73.S */
3166/* File: armv5te/unused.S */
3167    bl      common_abort
3168
3169
3170
3171/* ------------------------------ */
3172    .balign 64
3173.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
3174/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */
3175/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3176    /*
3177     * Handle a virtual method call.
3178     *
3179     * for: invoke-virtual, invoke-virtual/range
3180     */
3181    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3182    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3183    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3184    FETCH(r1, 1)                        @ r1<- BBBB
3185    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3186    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3187    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3188    .if     (!1)
3189    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3190    .endif
3191    cmp     r0, #0                      @ already resolved?
3192    EXPORT_PC()                         @ must export for invoke
3193    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ yes, continue on
3194    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3195    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3196    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3197    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3198    cmp     r0, #0                      @ got null?
3199    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ no, continue
3200    b       common_exceptionThrown      @ yes, handle exception
3201
3202
3203/* ------------------------------ */
3204    .balign 64
3205.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
3206/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */
3207/* File: armv5te/OP_INVOKE_SUPER.S */
3208    /*
3209     * Handle a "super" method call.
3210     *
3211     * for: invoke-super, invoke-super/range
3212     */
3213    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3214    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3215    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3216    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3217    .if     (!1)
3218    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3219    .endif
3220    FETCH(r1, 1)                        @ r1<- BBBB
3221    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3222    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3223    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3224    cmp     r2, #0                      @ null "this"?
3225    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3226    beq     common_errNullObject        @ null "this", throw exception
3227    cmp     r0, #0                      @ already resolved?
3228    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3229    EXPORT_PC()                         @ must export for invoke
3230    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ resolved, continue on
3231    b       .LOP_INVOKE_SUPER_RANGE_resolve         @ do resolve now
3232
3233
3234/* ------------------------------ */
3235    .balign 64
3236.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
3237/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */
3238/* File: armv5te/OP_INVOKE_DIRECT.S */
3239    /*
3240     * Handle a direct method call.
3241     *
3242     * (We could defer the "is 'this' pointer null" test to the common
3243     * method invocation code, and use a flag to indicate that static
3244     * calls don't count.  If we do this as part of copying the arguments
3245     * out we could avoiding loading the first arg twice.)
3246     *
3247     * for: invoke-direct, invoke-direct/range
3248     */
3249    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3250    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3251    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3252    FETCH(r1, 1)                        @ r1<- BBBB
3253    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3254    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3255    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3256    .if     (!1)
3257    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3258    .endif
3259    cmp     r0, #0                      @ already resolved?
3260    EXPORT_PC()                         @ must export for invoke
3261    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3262    beq     .LOP_INVOKE_DIRECT_RANGE_resolve         @ not resolved, do it now
3263.LOP_INVOKE_DIRECT_RANGE_finish:
3264    cmp     r2, #0                      @ null "this" ref?
3265    bne     common_invokeMethodRange   @ no, continue on
3266    b       common_errNullObject        @ yes, throw exception
3267
3268
3269/* ------------------------------ */
3270    .balign 64
3271.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
3272/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */
3273/* File: armv5te/OP_INVOKE_STATIC.S */
3274    /*
3275     * Handle a static method call.
3276     *
3277     * for: invoke-static, invoke-static/range
3278     */
3279    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3280    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3281    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3282    FETCH(r1, 1)                        @ r1<- BBBB
3283    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3284    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3285    cmp     r0, #0                      @ already resolved?
3286    EXPORT_PC()                         @ must export for invoke
3287    bne     common_invokeMethodRange @ yes, continue on
32880:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3289    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3290    mov     r2, #METHOD_STATIC          @ resolver method type
3291    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3292    cmp     r0, #0                      @ got null?
3293    bne     common_invokeMethodRange @ no, continue
3294    b       common_exceptionThrown      @ yes, handle exception
3295
3296
3297
3298/* ------------------------------ */
3299    .balign 64
3300.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
3301/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */
3302/* File: armv5te/OP_INVOKE_INTERFACE.S */
3303    /*
3304     * Handle an interface method call.
3305     *
3306     * for: invoke-interface, invoke-interface/range
3307     */
3308    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3309    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3310    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3311    FETCH(r1, 1)                        @ r1<- BBBB
3312    .if     (!1)
3313    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3314    .endif
3315    EXPORT_PC()                         @ must export for invoke
3316    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3317    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3318    cmp     r0, #0                      @ null obj?
3319    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3320    beq     common_errNullObject        @ yes, fail
3321    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3322    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3323    cmp     r0, #0                      @ failed?
3324    beq     common_exceptionThrown      @ yes, handle exception
3325    b       common_invokeMethodRange @ jump to common handler
3326
3327
3328
3329/* ------------------------------ */
3330    .balign 64
3331.L_OP_UNUSED_79: /* 0x79 */
3332/* File: armv5te/OP_UNUSED_79.S */
3333/* File: armv5te/unused.S */
3334    bl      common_abort
3335
3336
3337
3338/* ------------------------------ */
3339    .balign 64
3340.L_OP_UNUSED_7A: /* 0x7a */
3341/* File: armv5te/OP_UNUSED_7A.S */
3342/* File: armv5te/unused.S */
3343    bl      common_abort
3344
3345
3346
3347/* ------------------------------ */
3348    .balign 64
3349.L_OP_NEG_INT: /* 0x7b */
3350/* File: armv5te/OP_NEG_INT.S */
3351/* File: armv5te/unop.S */
3352    /*
3353     * Generic 32-bit unary operation.  Provide an "instr" line that
3354     * specifies an instruction that performs "result = op r0".
3355     * This could be an ARM instruction or a function call.
3356     *
3357     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3358     *      int-to-byte, int-to-char, int-to-short
3359     */
3360    /* unop vA, vB */
3361    mov     r3, rINST, lsr #12          @ r3<- B
3362    mov     r9, rINST, lsr #8           @ r9<- A+
3363    GET_VREG(r0, r3)                    @ r0<- vB
3364    and     r9, r9, #15
3365                               @ optional op; may set condition codes
3366    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3367    rsb     r0, r0, #0                              @ r0<- op, r0-r3 changed
3368    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3369    SET_VREG(r0, r9)                    @ vAA<- r0
3370    GOTO_OPCODE(ip)                     @ jump to next instruction
3371    /* 9-10 instructions */
3372
3373
3374/* ------------------------------ */
3375    .balign 64
3376.L_OP_NOT_INT: /* 0x7c */
3377/* File: armv5te/OP_NOT_INT.S */
3378/* File: armv5te/unop.S */
3379    /*
3380     * Generic 32-bit unary operation.  Provide an "instr" line that
3381     * specifies an instruction that performs "result = op r0".
3382     * This could be an ARM instruction or a function call.
3383     *
3384     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3385     *      int-to-byte, int-to-char, int-to-short
3386     */
3387    /* unop vA, vB */
3388    mov     r3, rINST, lsr #12          @ r3<- B
3389    mov     r9, rINST, lsr #8           @ r9<- A+
3390    GET_VREG(r0, r3)                    @ r0<- vB
3391    and     r9, r9, #15
3392                               @ optional op; may set condition codes
3393    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3394    mvn     r0, r0                              @ r0<- op, r0-r3 changed
3395    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3396    SET_VREG(r0, r9)                    @ vAA<- r0
3397    GOTO_OPCODE(ip)                     @ jump to next instruction
3398    /* 9-10 instructions */
3399
3400
3401/* ------------------------------ */
3402    .balign 64
3403.L_OP_NEG_LONG: /* 0x7d */
3404/* File: armv5te/OP_NEG_LONG.S */
3405/* File: armv5te/unopWide.S */
3406    /*
3407     * Generic 64-bit unary operation.  Provide an "instr" line that
3408     * specifies an instruction that performs "result = op r0/r1".
3409     * This could be an ARM instruction or a function call.
3410     *
3411     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3412     */
3413    /* unop vA, vB */
3414    mov     r9, rINST, lsr #8           @ r9<- A+
3415    mov     r3, rINST, lsr #12          @ r3<- B
3416    and     r9, r9, #15
3417    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3418    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3419    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3420    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3421    rsbs    r0, r0, #0                           @ optional op; may set condition codes
3422    rsc     r1, r1, #0                              @ r0/r1<- op, r2-r3 changed
3423    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3424    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3425    GOTO_OPCODE(ip)                     @ jump to next instruction
3426    /* 12-13 instructions */
3427
3428
3429
3430/* ------------------------------ */
3431    .balign 64
3432.L_OP_NOT_LONG: /* 0x7e */
3433/* File: armv5te/OP_NOT_LONG.S */
3434/* File: armv5te/unopWide.S */
3435    /*
3436     * Generic 64-bit unary operation.  Provide an "instr" line that
3437     * specifies an instruction that performs "result = op r0/r1".
3438     * This could be an ARM instruction or a function call.
3439     *
3440     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3441     */
3442    /* unop vA, vB */
3443    mov     r9, rINST, lsr #8           @ r9<- A+
3444    mov     r3, rINST, lsr #12          @ r3<- B
3445    and     r9, r9, #15
3446    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3447    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3448    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3449    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3450    mvn     r0, r0                           @ optional op; may set condition codes
3451    mvn     r1, r1                              @ r0/r1<- op, r2-r3 changed
3452    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3453    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3454    GOTO_OPCODE(ip)                     @ jump to next instruction
3455    /* 12-13 instructions */
3456
3457
3458
3459/* ------------------------------ */
3460    .balign 64
3461.L_OP_NEG_FLOAT: /* 0x7f */
3462/* File: armv5te/OP_NEG_FLOAT.S */
3463/* File: armv5te/unop.S */
3464    /*
3465     * Generic 32-bit unary operation.  Provide an "instr" line that
3466     * specifies an instruction that performs "result = op r0".
3467     * This could be an ARM instruction or a function call.
3468     *
3469     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3470     *      int-to-byte, int-to-char, int-to-short
3471     */
3472    /* unop vA, vB */
3473    mov     r3, rINST, lsr #12          @ r3<- B
3474    mov     r9, rINST, lsr #8           @ r9<- A+
3475    GET_VREG(r0, r3)                    @ r0<- vB
3476    and     r9, r9, #15
3477                               @ optional op; may set condition codes
3478    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3479    add     r0, r0, #0x80000000                              @ r0<- op, r0-r3 changed
3480    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3481    SET_VREG(r0, r9)                    @ vAA<- r0
3482    GOTO_OPCODE(ip)                     @ jump to next instruction
3483    /* 9-10 instructions */
3484
3485
3486/* ------------------------------ */
3487    .balign 64
3488.L_OP_NEG_DOUBLE: /* 0x80 */
3489/* File: armv5te/OP_NEG_DOUBLE.S */
3490/* File: armv5te/unopWide.S */
3491    /*
3492     * Generic 64-bit unary operation.  Provide an "instr" line that
3493     * specifies an instruction that performs "result = op r0/r1".
3494     * This could be an ARM instruction or a function call.
3495     *
3496     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3497     */
3498    /* unop vA, vB */
3499    mov     r9, rINST, lsr #8           @ r9<- A+
3500    mov     r3, rINST, lsr #12          @ r3<- B
3501    and     r9, r9, #15
3502    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3503    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3504    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3505    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3506                               @ optional op; may set condition codes
3507    add     r1, r1, #0x80000000                              @ r0/r1<- op, r2-r3 changed
3508    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3509    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3510    GOTO_OPCODE(ip)                     @ jump to next instruction
3511    /* 12-13 instructions */
3512
3513
3514
3515/* ------------------------------ */
3516    .balign 64
3517.L_OP_INT_TO_LONG: /* 0x81 */
3518/* File: armv5te/OP_INT_TO_LONG.S */
3519/* File: armv5te/unopWider.S */
3520    /*
3521     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3522     * that specifies an instruction that performs "result = op r0", where
3523     * "result" is a 64-bit quantity in r0/r1.
3524     *
3525     * For: int-to-long, int-to-double, float-to-long, float-to-double
3526     */
3527    /* unop vA, vB */
3528    mov     r9, rINST, lsr #8           @ r9<- A+
3529    mov     r3, rINST, lsr #12          @ r3<- B
3530    and     r9, r9, #15
3531    GET_VREG(r0, r3)                    @ r0<- vB
3532    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3533                               @ optional op; may set condition codes
3534    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3535    mov     r1, r0, asr #31                              @ r0<- op, r0-r3 changed
3536    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3537    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3538    GOTO_OPCODE(ip)                     @ jump to next instruction
3539    /* 10-11 instructions */
3540
3541
3542/* ------------------------------ */
3543    .balign 64
3544.L_OP_INT_TO_FLOAT: /* 0x82 */
3545/* File: armv5te/OP_INT_TO_FLOAT.S */
3546/* File: armv5te/unop.S */
3547    /*
3548     * Generic 32-bit unary operation.  Provide an "instr" line that
3549     * specifies an instruction that performs "result = op r0".
3550     * This could be an ARM instruction or a function call.
3551     *
3552     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3553     *      int-to-byte, int-to-char, int-to-short
3554     */
3555    /* unop vA, vB */
3556    mov     r3, rINST, lsr #12          @ r3<- B
3557    mov     r9, rINST, lsr #8           @ r9<- A+
3558    GET_VREG(r0, r3)                    @ r0<- vB
3559    and     r9, r9, #15
3560                               @ optional op; may set condition codes
3561    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3562    bl      __aeabi_i2f                              @ r0<- op, r0-r3 changed
3563    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3564    SET_VREG(r0, r9)                    @ vAA<- r0
3565    GOTO_OPCODE(ip)                     @ jump to next instruction
3566    /* 9-10 instructions */
3567
3568
3569/* ------------------------------ */
3570    .balign 64
3571.L_OP_INT_TO_DOUBLE: /* 0x83 */
3572/* File: armv5te/OP_INT_TO_DOUBLE.S */
3573/* File: armv5te/unopWider.S */
3574    /*
3575     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3576     * that specifies an instruction that performs "result = op r0", where
3577     * "result" is a 64-bit quantity in r0/r1.
3578     *
3579     * For: int-to-long, int-to-double, float-to-long, float-to-double
3580     */
3581    /* unop vA, vB */
3582    mov     r9, rINST, lsr #8           @ r9<- A+
3583    mov     r3, rINST, lsr #12          @ r3<- B
3584    and     r9, r9, #15
3585    GET_VREG(r0, r3)                    @ r0<- vB
3586    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3587                               @ optional op; may set condition codes
3588    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3589    bl      __aeabi_i2d                              @ r0<- op, r0-r3 changed
3590    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3591    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3592    GOTO_OPCODE(ip)                     @ jump to next instruction
3593    /* 10-11 instructions */
3594
3595
3596/* ------------------------------ */
3597    .balign 64
3598.L_OP_LONG_TO_INT: /* 0x84 */
3599/* File: armv5te/OP_LONG_TO_INT.S */
3600/* we ignore the high word, making this equivalent to a 32-bit reg move */
3601/* File: armv5te/OP_MOVE.S */
3602    /* for move, move-object, long-to-int */
3603    /* op vA, vB */
3604    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
3605    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
3606    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3607    GET_VREG(r2, r1)                    @ r2<- fp[B]
3608    and     r0, r0, #15
3609    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
3610    SET_VREG(r2, r0)                    @ fp[A]<- r2
3611    GOTO_OPCODE(ip)                     @ execute next instruction
3612
3613
3614
3615/* ------------------------------ */
3616    .balign 64
3617.L_OP_LONG_TO_FLOAT: /* 0x85 */
3618/* File: armv5te/OP_LONG_TO_FLOAT.S */
3619/* File: armv5te/unopNarrower.S */
3620    /*
3621     * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
3622     * that specifies an instruction that performs "result = op r0/r1", where
3623     * "result" is a 32-bit quantity in r0.
3624     *
3625     * For: long-to-float, double-to-int, double-to-float
3626     *
3627     * (This would work for long-to-int, but that instruction is actually
3628     * an exact match for OP_MOVE.)
3629     */
3630    /* unop vA, vB */
3631    mov     r3, rINST, lsr #12          @ r3<- B
3632    mov     r9, rINST, lsr #8           @ r9<- A+
3633    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3634    and     r9, r9, #15
3635    ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
3636    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3637                               @ optional op; may set condition codes
3638    bl      __aeabi_l2f                              @ r0<- op, r0-r3 changed
3639    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3640    SET_VREG(r0, r9)                    @ vA<- r0
3641    GOTO_OPCODE(ip)                     @ jump to next instruction
3642    /* 10-11 instructions */
3643
3644
3645/* ------------------------------ */
3646    .balign 64
3647.L_OP_LONG_TO_DOUBLE: /* 0x86 */
3648/* File: armv5te/OP_LONG_TO_DOUBLE.S */
3649/* File: armv5te/unopWide.S */
3650    /*
3651     * Generic 64-bit unary operation.  Provide an "instr" line that
3652     * specifies an instruction that performs "result = op r0/r1".
3653     * This could be an ARM instruction or a function call.
3654     *
3655     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3656     */
3657    /* unop vA, vB */
3658    mov     r9, rINST, lsr #8           @ r9<- A+
3659    mov     r3, rINST, lsr #12          @ r3<- B
3660    and     r9, r9, #15
3661    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3662    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3663    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3664    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3665                               @ optional op; may set condition codes
3666    bl      __aeabi_l2d                              @ r0/r1<- op, r2-r3 changed
3667    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3668    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3669    GOTO_OPCODE(ip)                     @ jump to next instruction
3670    /* 12-13 instructions */
3671
3672
3673
3674/* ------------------------------ */
3675    .balign 64
3676.L_OP_FLOAT_TO_INT: /* 0x87 */
3677/* File: armv5te/OP_FLOAT_TO_INT.S */
3678/* EABI appears to have Java-style conversions of +inf/-inf/NaN */
3679/* File: armv5te/unop.S */
3680    /*
3681     * Generic 32-bit unary operation.  Provide an "instr" line that
3682     * specifies an instruction that performs "result = op r0".
3683     * This could be an ARM instruction or a function call.
3684     *
3685     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3686     *      int-to-byte, int-to-char, int-to-short
3687     */
3688    /* unop vA, vB */
3689    mov     r3, rINST, lsr #12          @ r3<- B
3690    mov     r9, rINST, lsr #8           @ r9<- A+
3691    GET_VREG(r0, r3)                    @ r0<- vB
3692    and     r9, r9, #15
3693                               @ optional op; may set condition codes
3694    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3695    bl      __aeabi_f2iz                              @ r0<- op, r0-r3 changed
3696    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3697    SET_VREG(r0, r9)                    @ vAA<- r0
3698    GOTO_OPCODE(ip)                     @ jump to next instruction
3699    /* 9-10 instructions */
3700
3701
3702#if 0
3703@include "armv5te/unop.S" {"instr":"bl      f2i_doconv"}
3704@break
3705/*
3706 * Convert the float in r0 to an int in r0.
3707 *
3708 * We have to clip values to int min/max per the specification.  The
3709 * expected common case is a "reasonable" value that converts directly
3710 * to modest integer.  The EABI convert function isn't doing this for us.
3711 */
3712f2i_doconv:
3713    stmfd   sp!, {r4, lr}
3714    mov     r1, #0x4f000000             @ (float)maxint
3715    mov     r4, r0
3716    bl      __aeabi_fcmpge              @ is arg >= maxint?
3717    cmp     r0, #0                      @ nonzero == yes
3718    mvnne   r0, #0x80000000             @ return maxint (7fffffff)
3719    ldmnefd sp!, {r4, pc}
3720
3721    mov     r0, r4                      @ recover arg
3722    mov     r1, #0xcf000000             @ (float)minint
3723    bl      __aeabi_fcmple              @ is arg <= minint?
3724    cmp     r0, #0                      @ nonzero == yes
3725    movne   r0, #0x80000000             @ return minint (80000000)
3726    ldmnefd sp!, {r4, pc}
3727
3728    mov     r0, r4                      @ recover arg
3729    mov     r1, r4
3730    bl      __aeabi_fcmpeq              @ is arg == self?
3731    cmp     r0, #0                      @ zero == no
3732    ldmeqfd sp!, {r4, pc}               @ return zero for NaN
3733
3734    mov     r0, r4                      @ recover arg
3735    bl      __aeabi_f2iz                @ convert float to int
3736    ldmfd   sp!, {r4, pc}
3737#endif
3738
3739
3740/* ------------------------------ */
3741    .balign 64
3742.L_OP_FLOAT_TO_LONG: /* 0x88 */
3743/* File: armv5te/OP_FLOAT_TO_LONG.S */
3744@include "armv5te/unopWider.S" {"instr":"bl      __aeabi_f2lz"}
3745/* File: armv5te/unopWider.S */
3746    /*
3747     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3748     * that specifies an instruction that performs "result = op r0", where
3749     * "result" is a 64-bit quantity in r0/r1.
3750     *
3751     * For: int-to-long, int-to-double, float-to-long, float-to-double
3752     */
3753    /* unop vA, vB */
3754    mov     r9, rINST, lsr #8           @ r9<- A+
3755    mov     r3, rINST, lsr #12          @ r3<- B
3756    and     r9, r9, #15
3757    GET_VREG(r0, r3)                    @ r0<- vB
3758    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3759                               @ optional op; may set condition codes
3760    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3761    bl      f2l_doconv                              @ r0<- op, r0-r3 changed
3762    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3763    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3764    GOTO_OPCODE(ip)                     @ jump to next instruction
3765    /* 10-11 instructions */
3766
3767
3768
3769/* ------------------------------ */
3770    .balign 64
3771.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
3772/* File: armv5te/OP_FLOAT_TO_DOUBLE.S */
3773/* File: armv5te/unopWider.S */
3774    /*
3775     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3776     * that specifies an instruction that performs "result = op r0", where
3777     * "result" is a 64-bit quantity in r0/r1.
3778     *
3779     * For: int-to-long, int-to-double, float-to-long, float-to-double
3780     */
3781    /* unop vA, vB */
3782    mov     r9, rINST, lsr #8           @ r9<- A+
3783    mov     r3, rINST, lsr #12          @ r3<- B
3784    and     r9, r9, #15
3785    GET_VREG(r0, r3)                    @ r0<- vB
3786    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3787                               @ optional op; may set condition codes
3788    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3789    bl      __aeabi_f2d                              @ r0<- op, r0-r3 changed
3790    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3791    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3792    GOTO_OPCODE(ip)                     @ jump to next instruction
3793    /* 10-11 instructions */
3794
3795
3796/* ------------------------------ */
3797    .balign 64
3798.L_OP_DOUBLE_TO_INT: /* 0x8a */
3799/* File: armv5te/OP_DOUBLE_TO_INT.S */
3800/* EABI appears to have Java-style conversions of +inf/-inf/NaN */
3801/* File: armv5te/unopNarrower.S */
3802    /*
3803     * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
3804     * that specifies an instruction that performs "result = op r0/r1", where
3805     * "result" is a 32-bit quantity in r0.
3806     *
3807     * For: long-to-float, double-to-int, double-to-float
3808     *
3809     * (This would work for long-to-int, but that instruction is actually
3810     * an exact match for OP_MOVE.)
3811     */
3812    /* unop vA, vB */
3813    mov     r3, rINST, lsr #12          @ r3<- B
3814    mov     r9, rINST, lsr #8           @ r9<- A+
3815    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3816    and     r9, r9, #15
3817    ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
3818    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3819                               @ optional op; may set condition codes
3820    bl      __aeabi_d2iz                              @ r0<- op, r0-r3 changed
3821    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3822    SET_VREG(r0, r9)                    @ vA<- r0
3823    GOTO_OPCODE(ip)                     @ jump to next instruction
3824    /* 10-11 instructions */
3825
3826
3827#if 0
3828@include "armv5te/unopNarrower.S" {"instr":"bl      d2i_doconv"}
3829@break
3830/*
3831 * Convert the double in r0/r1 to an int in r0.
3832 *
3833 * We have to clip values to int min/max per the specification.  The
3834 * expected common case is a "reasonable" value that converts directly
3835 * to modest integer.  The EABI convert function isn't doing this for us.
3836 */
3837d2i_doconv:
3838    stmfd   sp!, {r4, r5, lr}           @ save regs
3839    ldr     r2, .LOP_DOUBLE_TO_INT_maxlo       @ (double)maxint, lo
3840    ldr     r3, .LOP_DOUBLE_TO_INT_maxhi       @ (double)maxint, hi
3841    sub     sp, sp, #4                  @ align for EABI
3842    mov     r4, r0                      @ save r0
3843    mov     r5, r1                      @  and r1
3844    bl      __aeabi_dcmpge              @ is arg >= maxint?
3845    cmp     r0, #0                      @ nonzero == yes
3846    mvnne   r0, #0x80000000             @ return maxint (7fffffff)
3847    bne     1f
3848
3849    mov     r0, r4                      @ recover arg
3850    mov     r1, r5
3851    ldr     r3, .LOP_DOUBLE_TO_INT_min         @ (double)minint, hi
3852    mov     r2, #0                      @ (double)minint, lo
3853    bl      __aeabi_dcmple              @ is arg <= minint?
3854    cmp     r0, #0                      @ nonzero == yes
3855    movne   r0, #0x80000000             @ return minint (80000000)
3856    bne     1f
3857
3858    mov     r0, r4                      @ recover arg
3859    mov     r1, r5
3860    mov     r2, r4                      @ compare against self
3861    mov     r3, r5
3862    bl      __aeabi_dcmpeq              @ is arg == self?
3863    cmp     r0, #0                      @ zero == no
3864    beq     1f                          @ return zero for NaN
3865
3866    mov     r0, r4                      @ recover arg
3867    mov     r1, r5
3868    bl      __aeabi_d2iz                @ convert double to int
3869
38701:
3871    add     sp, sp, #4
3872    ldmfd   sp!, {r4, r5, pc}
3873
3874.LOP_DOUBLE_TO_INT_maxlo:
3875    .word   0xffc00000                  @ maxint, as a double (low word)
3876.LOP_DOUBLE_TO_INT_maxhi:
3877    .word   0x41dfffff                  @ maxint, as a double (high word)
3878.LOP_DOUBLE_TO_INT_min:
3879    .word   0xc1e00000                  @ minint, as a double (high word)
3880#endif
3881
3882
3883/* ------------------------------ */
3884    .balign 64
3885.L_OP_DOUBLE_TO_LONG: /* 0x8b */
3886/* File: armv5te/OP_DOUBLE_TO_LONG.S */
3887@include "armv5te/unopWide.S" {"instr":"bl      __aeabi_d2lz"}
3888/* File: armv5te/unopWide.S */
3889    /*
3890     * Generic 64-bit unary operation.  Provide an "instr" line that
3891     * specifies an instruction that performs "result = op r0/r1".
3892     * This could be an ARM instruction or a function call.
3893     *
3894     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3895     */
3896    /* unop vA, vB */
3897    mov     r9, rINST, lsr #8           @ r9<- A+
3898    mov     r3, rINST, lsr #12          @ r3<- B
3899    and     r9, r9, #15
3900    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3901    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3902    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3903    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3904                               @ optional op; may set condition codes
3905    bl      d2l_doconv                              @ r0/r1<- op, r2-r3 changed
3906    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3907    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3908    GOTO_OPCODE(ip)                     @ jump to next instruction
3909    /* 12-13 instructions */
3910
3911
3912
3913
3914/* ------------------------------ */
3915    .balign 64
3916.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
3917/* File: armv5te/OP_DOUBLE_TO_FLOAT.S */
3918/* File: armv5te/unopNarrower.S */
3919    /*
3920     * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
3921     * that specifies an instruction that performs "result = op r0/r1", where
3922     * "result" is a 32-bit quantity in r0.
3923     *
3924     * For: long-to-float, double-to-int, double-to-float
3925     *
3926     * (This would work for long-to-int, but that instruction is actually
3927     * an exact match for OP_MOVE.)
3928     */
3929    /* unop vA, vB */
3930    mov     r3, rINST, lsr #12          @ r3<- B
3931    mov     r9, rINST, lsr #8           @ r9<- A+
3932    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3933    and     r9, r9, #15
3934    ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
3935    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3936                               @ optional op; may set condition codes
3937    bl      __aeabi_d2f                              @ r0<- op, r0-r3 changed
3938    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3939    SET_VREG(r0, r9)                    @ vA<- r0
3940    GOTO_OPCODE(ip)                     @ jump to next instruction
3941    /* 10-11 instructions */
3942
3943
3944/* ------------------------------ */
3945    .balign 64
3946.L_OP_INT_TO_BYTE: /* 0x8d */
3947/* File: armv5te/OP_INT_TO_BYTE.S */
3948/* File: armv5te/unop.S */
3949    /*
3950     * Generic 32-bit unary operation.  Provide an "instr" line that
3951     * specifies an instruction that performs "result = op r0".
3952     * This could be an ARM instruction or a function call.
3953     *
3954     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3955     *      int-to-byte, int-to-char, int-to-short
3956     */
3957    /* unop vA, vB */
3958    mov     r3, rINST, lsr #12          @ r3<- B
3959    mov     r9, rINST, lsr #8           @ r9<- A+
3960    GET_VREG(r0, r3)                    @ r0<- vB
3961    and     r9, r9, #15
3962    mov     r0, r0, asl #24                           @ optional op; may set condition codes
3963    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3964    mov     r0, r0, asr #24                              @ r0<- op, r0-r3 changed
3965    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3966    SET_VREG(r0, r9)                    @ vAA<- r0
3967    GOTO_OPCODE(ip)                     @ jump to next instruction
3968    /* 9-10 instructions */
3969
3970
3971/* ------------------------------ */
3972    .balign 64
3973.L_OP_INT_TO_CHAR: /* 0x8e */
3974/* File: armv5te/OP_INT_TO_CHAR.S */
3975/* File: armv5te/unop.S */
3976    /*
3977     * Generic 32-bit unary operation.  Provide an "instr" line that
3978     * specifies an instruction that performs "result = op r0".
3979     * This could be an ARM instruction or a function call.
3980     *
3981     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3982     *      int-to-byte, int-to-char, int-to-short
3983     */
3984    /* unop vA, vB */
3985    mov     r3, rINST, lsr #12          @ r3<- B
3986    mov     r9, rINST, lsr #8           @ r9<- A+
3987    GET_VREG(r0, r3)                    @ r0<- vB
3988    and     r9, r9, #15
3989    mov     r0, r0, asl #16                           @ optional op; may set condition codes
3990    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3991    mov     r0, r0, lsr #16                              @ r0<- op, r0-r3 changed
3992    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3993    SET_VREG(r0, r9)                    @ vAA<- r0
3994    GOTO_OPCODE(ip)                     @ jump to next instruction
3995    /* 9-10 instructions */
3996
3997
3998/* ------------------------------ */
3999    .balign 64
4000.L_OP_INT_TO_SHORT: /* 0x8f */
4001/* File: armv5te/OP_INT_TO_SHORT.S */
4002/* File: armv5te/unop.S */
4003    /*
4004     * Generic 32-bit unary operation.  Provide an "instr" line that
4005     * specifies an instruction that performs "result = op r0".
4006     * This could be an ARM instruction or a function call.
4007     *
4008     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4009     *      int-to-byte, int-to-char, int-to-short
4010     */
4011    /* unop vA, vB */
4012    mov     r3, rINST, lsr #12          @ r3<- B
4013    mov     r9, rINST, lsr #8           @ r9<- A+
4014    GET_VREG(r0, r3)                    @ r0<- vB
4015    and     r9, r9, #15
4016    mov     r0, r0, asl #16                           @ optional op; may set condition codes
4017    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4018    mov     r0, r0, asr #16                              @ r0<- op, r0-r3 changed
4019    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4020    SET_VREG(r0, r9)                    @ vAA<- r0
4021    GOTO_OPCODE(ip)                     @ jump to next instruction
4022    /* 9-10 instructions */
4023
4024
4025/* ------------------------------ */
4026    .balign 64
4027.L_OP_ADD_INT: /* 0x90 */
4028/* File: armv5te/OP_ADD_INT.S */
4029/* File: armv5te/binop.S */
4030    /*
4031     * Generic 32-bit binary operation.  Provide an "instr" line that
4032     * specifies an instruction that performs "result = r0 op r1".
4033     * This could be an ARM instruction or a function call.  (If the result
4034     * comes back in a register other than r0, you can override "result".)
4035     *
4036     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4037     * vCC (r1).  Useful for integer division and modulus.  Note that we
4038     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4039     * handles it correctly.
4040     *
4041     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4042     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4043     *      mul-float, div-float, rem-float
4044     */
4045    /* binop vAA, vBB, vCC */
4046    FETCH(r0, 1)                        @ r0<- CCBB
4047    mov     r9, rINST, lsr #8           @ r9<- AA
4048    mov     r3, r0, lsr #8              @ r3<- CC
4049    and     r2, r0, #255                @ r2<- BB
4050    GET_VREG(r1, r3)                    @ r1<- vCC
4051    GET_VREG(r0, r2)                    @ r0<- vBB
4052    .if 0
4053    cmp     r1, #0                      @ is second operand zero?
4054    beq     common_errDivideByZero
4055    .endif
4056
4057    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4058                               @ optional op; may set condition codes
4059    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
4060    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4061    SET_VREG(r0, r9)               @ vAA<- r0
4062    GOTO_OPCODE(ip)                     @ jump to next instruction
4063    /* 11-14 instructions */
4064
4065
4066
4067/* ------------------------------ */
4068    .balign 64
4069.L_OP_SUB_INT: /* 0x91 */
4070/* File: armv5te/OP_SUB_INT.S */
4071/* File: armv5te/binop.S */
4072    /*
4073     * Generic 32-bit binary operation.  Provide an "instr" line that
4074     * specifies an instruction that performs "result = r0 op r1".
4075     * This could be an ARM instruction or a function call.  (If the result
4076     * comes back in a register other than r0, you can override "result".)
4077     *
4078     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4079     * vCC (r1).  Useful for integer division and modulus.  Note that we
4080     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4081     * handles it correctly.
4082     *
4083     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4084     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4085     *      mul-float, div-float, rem-float
4086     */
4087    /* binop vAA, vBB, vCC */
4088    FETCH(r0, 1)                        @ r0<- CCBB
4089    mov     r9, rINST, lsr #8           @ r9<- AA
4090    mov     r3, r0, lsr #8              @ r3<- CC
4091    and     r2, r0, #255                @ r2<- BB
4092    GET_VREG(r1, r3)                    @ r1<- vCC
4093    GET_VREG(r0, r2)                    @ r0<- vBB
4094    .if 0
4095    cmp     r1, #0                      @ is second operand zero?
4096    beq     common_errDivideByZero
4097    .endif
4098
4099    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4100                               @ optional op; may set condition codes
4101    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
4102    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4103    SET_VREG(r0, r9)               @ vAA<- r0
4104    GOTO_OPCODE(ip)                     @ jump to next instruction
4105    /* 11-14 instructions */
4106
4107
4108
4109/* ------------------------------ */
4110    .balign 64
4111.L_OP_MUL_INT: /* 0x92 */
4112/* File: armv5te/OP_MUL_INT.S */
4113/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
4114/* File: armv5te/binop.S */
4115    /*
4116     * Generic 32-bit binary operation.  Provide an "instr" line that
4117     * specifies an instruction that performs "result = r0 op r1".
4118     * This could be an ARM instruction or a function call.  (If the result
4119     * comes back in a register other than r0, you can override "result".)
4120     *
4121     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4122     * vCC (r1).  Useful for integer division and modulus.  Note that we
4123     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4124     * handles it correctly.
4125     *
4126     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4127     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4128     *      mul-float, div-float, rem-float
4129     */
4130    /* binop vAA, vBB, vCC */
4131    FETCH(r0, 1)                        @ r0<- CCBB
4132    mov     r9, rINST, lsr #8           @ r9<- AA
4133    mov     r3, r0, lsr #8              @ r3<- CC
4134    and     r2, r0, #255                @ r2<- BB
4135    GET_VREG(r1, r3)                    @ r1<- vCC
4136    GET_VREG(r0, r2)                    @ r0<- vBB
4137    .if 0
4138    cmp     r1, #0                      @ is second operand zero?
4139    beq     common_errDivideByZero
4140    .endif
4141
4142    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4143                               @ optional op; may set condition codes
4144    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
4145    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4146    SET_VREG(r0, r9)               @ vAA<- r0
4147    GOTO_OPCODE(ip)                     @ jump to next instruction
4148    /* 11-14 instructions */
4149
4150
4151
4152/* ------------------------------ */
4153    .balign 64
4154.L_OP_DIV_INT: /* 0x93 */
4155/* File: armv5te/OP_DIV_INT.S */
4156/* File: armv5te/binop.S */
4157    /*
4158     * Generic 32-bit binary operation.  Provide an "instr" line that
4159     * specifies an instruction that performs "result = r0 op r1".
4160     * This could be an ARM instruction or a function call.  (If the result
4161     * comes back in a register other than r0, you can override "result".)
4162     *
4163     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4164     * vCC (r1).  Useful for integer division and modulus.  Note that we
4165     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4166     * handles it correctly.
4167     *
4168     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4169     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4170     *      mul-float, div-float, rem-float
4171     */
4172    /* binop vAA, vBB, vCC */
4173    FETCH(r0, 1)                        @ r0<- CCBB
4174    mov     r9, rINST, lsr #8           @ r9<- AA
4175    mov     r3, r0, lsr #8              @ r3<- CC
4176    and     r2, r0, #255                @ r2<- BB
4177    GET_VREG(r1, r3)                    @ r1<- vCC
4178    GET_VREG(r0, r2)                    @ r0<- vBB
4179    .if 1
4180    cmp     r1, #0                      @ is second operand zero?
4181    beq     common_errDivideByZero
4182    .endif
4183
4184    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4185                               @ optional op; may set condition codes
4186    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
4187    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4188    SET_VREG(r0, r9)               @ vAA<- r0
4189    GOTO_OPCODE(ip)                     @ jump to next instruction
4190    /* 11-14 instructions */
4191
4192
4193
4194/* ------------------------------ */
4195    .balign 64
4196.L_OP_REM_INT: /* 0x94 */
4197/* File: armv5te/OP_REM_INT.S */
4198/* idivmod returns quotient in r0 and remainder in r1 */
4199/* File: armv5te/binop.S */
4200    /*
4201     * Generic 32-bit binary operation.  Provide an "instr" line that
4202     * specifies an instruction that performs "result = r0 op r1".
4203     * This could be an ARM instruction or a function call.  (If the result
4204     * comes back in a register other than r0, you can override "result".)
4205     *
4206     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4207     * vCC (r1).  Useful for integer division and modulus.  Note that we
4208     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4209     * handles it correctly.
4210     *
4211     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4212     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4213     *      mul-float, div-float, rem-float
4214     */
4215    /* binop vAA, vBB, vCC */
4216    FETCH(r0, 1)                        @ r0<- CCBB
4217    mov     r9, rINST, lsr #8           @ r9<- AA
4218    mov     r3, r0, lsr #8              @ r3<- CC
4219    and     r2, r0, #255                @ r2<- BB
4220    GET_VREG(r1, r3)                    @ r1<- vCC
4221    GET_VREG(r0, r2)                    @ r0<- vBB
4222    .if 1
4223    cmp     r1, #0                      @ is second operand zero?
4224    beq     common_errDivideByZero
4225    .endif
4226
4227    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4228                               @ optional op; may set condition codes
4229    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
4230    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4231    SET_VREG(r1, r9)               @ vAA<- r1
4232    GOTO_OPCODE(ip)                     @ jump to next instruction
4233    /* 11-14 instructions */
4234
4235
4236
4237/* ------------------------------ */
4238    .balign 64
4239.L_OP_AND_INT: /* 0x95 */
4240/* File: armv5te/OP_AND_INT.S */
4241/* File: armv5te/binop.S */
4242    /*
4243     * Generic 32-bit binary operation.  Provide an "instr" line that
4244     * specifies an instruction that performs "result = r0 op r1".
4245     * This could be an ARM instruction or a function call.  (If the result
4246     * comes back in a register other than r0, you can override "result".)
4247     *
4248     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4249     * vCC (r1).  Useful for integer division and modulus.  Note that we
4250     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4251     * handles it correctly.
4252     *
4253     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4254     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4255     *      mul-float, div-float, rem-float
4256     */
4257    /* binop vAA, vBB, vCC */
4258    FETCH(r0, 1)                        @ r0<- CCBB
4259    mov     r9, rINST, lsr #8           @ r9<- AA
4260    mov     r3, r0, lsr #8              @ r3<- CC
4261    and     r2, r0, #255                @ r2<- BB
4262    GET_VREG(r1, r3)                    @ r1<- vCC
4263    GET_VREG(r0, r2)                    @ r0<- vBB
4264    .if 0
4265    cmp     r1, #0                      @ is second operand zero?
4266    beq     common_errDivideByZero
4267    .endif
4268
4269    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4270                               @ optional op; may set condition codes
4271    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
4272    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4273    SET_VREG(r0, r9)               @ vAA<- r0
4274    GOTO_OPCODE(ip)                     @ jump to next instruction
4275    /* 11-14 instructions */
4276
4277
4278
4279/* ------------------------------ */
4280    .balign 64
4281.L_OP_OR_INT: /* 0x96 */
4282/* File: armv5te/OP_OR_INT.S */
4283/* File: armv5te/binop.S */
4284    /*
4285     * Generic 32-bit binary operation.  Provide an "instr" line that
4286     * specifies an instruction that performs "result = r0 op r1".
4287     * This could be an ARM instruction or a function call.  (If the result
4288     * comes back in a register other than r0, you can override "result".)
4289     *
4290     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4291     * vCC (r1).  Useful for integer division and modulus.  Note that we
4292     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4293     * handles it correctly.
4294     *
4295     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4296     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4297     *      mul-float, div-float, rem-float
4298     */
4299    /* binop vAA, vBB, vCC */
4300    FETCH(r0, 1)                        @ r0<- CCBB
4301    mov     r9, rINST, lsr #8           @ r9<- AA
4302    mov     r3, r0, lsr #8              @ r3<- CC
4303    and     r2, r0, #255                @ r2<- BB
4304    GET_VREG(r1, r3)                    @ r1<- vCC
4305    GET_VREG(r0, r2)                    @ r0<- vBB
4306    .if 0
4307    cmp     r1, #0                      @ is second operand zero?
4308    beq     common_errDivideByZero
4309    .endif
4310
4311    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4312                               @ optional op; may set condition codes
4313    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
4314    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4315    SET_VREG(r0, r9)               @ vAA<- r0
4316    GOTO_OPCODE(ip)                     @ jump to next instruction
4317    /* 11-14 instructions */
4318
4319
4320
4321/* ------------------------------ */
4322    .balign 64
4323.L_OP_XOR_INT: /* 0x97 */
4324/* File: armv5te/OP_XOR_INT.S */
4325/* File: armv5te/binop.S */
4326    /*
4327     * Generic 32-bit binary operation.  Provide an "instr" line that
4328     * specifies an instruction that performs "result = r0 op r1".
4329     * This could be an ARM instruction or a function call.  (If the result
4330     * comes back in a register other than r0, you can override "result".)
4331     *
4332     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4333     * vCC (r1).  Useful for integer division and modulus.  Note that we
4334     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4335     * handles it correctly.
4336     *
4337     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4338     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4339     *      mul-float, div-float, rem-float
4340     */
4341    /* binop vAA, vBB, vCC */
4342    FETCH(r0, 1)                        @ r0<- CCBB
4343    mov     r9, rINST, lsr #8           @ r9<- AA
4344    mov     r3, r0, lsr #8              @ r3<- CC
4345    and     r2, r0, #255                @ r2<- BB
4346    GET_VREG(r1, r3)                    @ r1<- vCC
4347    GET_VREG(r0, r2)                    @ r0<- vBB
4348    .if 0
4349    cmp     r1, #0                      @ is second operand zero?
4350    beq     common_errDivideByZero
4351    .endif
4352
4353    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4354                               @ optional op; may set condition codes
4355    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
4356    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4357    SET_VREG(r0, r9)               @ vAA<- r0
4358    GOTO_OPCODE(ip)                     @ jump to next instruction
4359    /* 11-14 instructions */
4360
4361
4362
4363/* ------------------------------ */
4364    .balign 64
4365.L_OP_SHL_INT: /* 0x98 */
4366/* File: armv5te/OP_SHL_INT.S */
4367/* File: armv5te/binop.S */
4368    /*
4369     * Generic 32-bit binary operation.  Provide an "instr" line that
4370     * specifies an instruction that performs "result = r0 op r1".
4371     * This could be an ARM instruction or a function call.  (If the result
4372     * comes back in a register other than r0, you can override "result".)
4373     *
4374     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4375     * vCC (r1).  Useful for integer division and modulus.  Note that we
4376     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4377     * handles it correctly.
4378     *
4379     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4380     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4381     *      mul-float, div-float, rem-float
4382     */
4383    /* binop vAA, vBB, vCC */
4384    FETCH(r0, 1)                        @ r0<- CCBB
4385    mov     r9, rINST, lsr #8           @ r9<- AA
4386    mov     r3, r0, lsr #8              @ r3<- CC
4387    and     r2, r0, #255                @ r2<- BB
4388    GET_VREG(r1, r3)                    @ r1<- vCC
4389    GET_VREG(r0, r2)                    @ r0<- vBB
4390    .if 0
4391    cmp     r1, #0                      @ is second operand zero?
4392    beq     common_errDivideByZero
4393    .endif
4394
4395    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4396    and     r1, r1, #31                           @ optional op; may set condition codes
4397    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
4398    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4399    SET_VREG(r0, r9)               @ vAA<- r0
4400    GOTO_OPCODE(ip)                     @ jump to next instruction
4401    /* 11-14 instructions */
4402
4403
4404
4405/* ------------------------------ */
4406    .balign 64
4407.L_OP_SHR_INT: /* 0x99 */
4408/* File: armv5te/OP_SHR_INT.S */
4409/* File: armv5te/binop.S */
4410    /*
4411     * Generic 32-bit binary operation.  Provide an "instr" line that
4412     * specifies an instruction that performs "result = r0 op r1".
4413     * This could be an ARM instruction or a function call.  (If the result
4414     * comes back in a register other than r0, you can override "result".)
4415     *
4416     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4417     * vCC (r1).  Useful for integer division and modulus.  Note that we
4418     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4419     * handles it correctly.
4420     *
4421     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4422     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4423     *      mul-float, div-float, rem-float
4424     */
4425    /* binop vAA, vBB, vCC */
4426    FETCH(r0, 1)                        @ r0<- CCBB
4427    mov     r9, rINST, lsr #8           @ r9<- AA
4428    mov     r3, r0, lsr #8              @ r3<- CC
4429    and     r2, r0, #255                @ r2<- BB
4430    GET_VREG(r1, r3)                    @ r1<- vCC
4431    GET_VREG(r0, r2)                    @ r0<- vBB
4432    .if 0
4433    cmp     r1, #0                      @ is second operand zero?
4434    beq     common_errDivideByZero
4435    .endif
4436
4437    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4438    and     r1, r1, #31                           @ optional op; may set condition codes
4439    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
4440    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4441    SET_VREG(r0, r9)               @ vAA<- r0
4442    GOTO_OPCODE(ip)                     @ jump to next instruction
4443    /* 11-14 instructions */
4444
4445
4446
4447/* ------------------------------ */
4448    .balign 64
4449.L_OP_USHR_INT: /* 0x9a */
4450/* File: armv5te/OP_USHR_INT.S */
4451/* File: armv5te/binop.S */
4452    /*
4453     * Generic 32-bit binary operation.  Provide an "instr" line that
4454     * specifies an instruction that performs "result = r0 op r1".
4455     * This could be an ARM instruction or a function call.  (If the result
4456     * comes back in a register other than r0, you can override "result".)
4457     *
4458     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4459     * vCC (r1).  Useful for integer division and modulus.  Note that we
4460     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4461     * handles it correctly.
4462     *
4463     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4464     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4465     *      mul-float, div-float, rem-float
4466     */
4467    /* binop vAA, vBB, vCC */
4468    FETCH(r0, 1)                        @ r0<- CCBB
4469    mov     r9, rINST, lsr #8           @ r9<- AA
4470    mov     r3, r0, lsr #8              @ r3<- CC
4471    and     r2, r0, #255                @ r2<- BB
4472    GET_VREG(r1, r3)                    @ r1<- vCC
4473    GET_VREG(r0, r2)                    @ r0<- vBB
4474    .if 0
4475    cmp     r1, #0                      @ is second operand zero?
4476    beq     common_errDivideByZero
4477    .endif
4478
4479    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4480    and     r1, r1, #31                           @ optional op; may set condition codes
4481    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
4482    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4483    SET_VREG(r0, r9)               @ vAA<- r0
4484    GOTO_OPCODE(ip)                     @ jump to next instruction
4485    /* 11-14 instructions */
4486
4487
4488
4489/* ------------------------------ */
4490    .balign 64
4491.L_OP_ADD_LONG: /* 0x9b */
4492/* File: armv5te/OP_ADD_LONG.S */
4493/* File: armv5te/binopWide.S */
4494    /*
4495     * Generic 64-bit binary operation.  Provide an "instr" line that
4496     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4497     * This could be an ARM instruction or a function call.  (If the result
4498     * comes back in a register other than r0, you can override "result".)
4499     *
4500     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4501     * vCC (r1).  Useful for integer division and modulus.
4502     *
4503     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4504     *      xor-long, add-double, sub-double, mul-double, div-double,
4505     *      rem-double
4506     *
4507     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4508     */
4509    /* binop vAA, vBB, vCC */
4510    FETCH(r0, 1)                        @ r0<- CCBB
4511    mov     r9, rINST, lsr #8           @ r9<- AA
4512    and     r2, r0, #255                @ r2<- BB
4513    mov     r3, r0, lsr #8              @ r3<- CC
4514    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4515    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4516    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4517    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4518    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4519    .if 0
4520    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4521    beq     common_errDivideByZero
4522    .endif
4523    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4524
4525    adds    r0, r0, r2                           @ optional op; may set condition codes
4526    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
4527    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4528    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4529    GOTO_OPCODE(ip)                     @ jump to next instruction
4530    /* 14-17 instructions */
4531
4532
4533
4534/* ------------------------------ */
4535    .balign 64
4536.L_OP_SUB_LONG: /* 0x9c */
4537/* File: armv5te/OP_SUB_LONG.S */
4538/* File: armv5te/binopWide.S */
4539    /*
4540     * Generic 64-bit binary operation.  Provide an "instr" line that
4541     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4542     * This could be an ARM instruction or a function call.  (If the result
4543     * comes back in a register other than r0, you can override "result".)
4544     *
4545     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4546     * vCC (r1).  Useful for integer division and modulus.
4547     *
4548     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4549     *      xor-long, add-double, sub-double, mul-double, div-double,
4550     *      rem-double
4551     *
4552     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4553     */
4554    /* binop vAA, vBB, vCC */
4555    FETCH(r0, 1)                        @ r0<- CCBB
4556    mov     r9, rINST, lsr #8           @ r9<- AA
4557    and     r2, r0, #255                @ r2<- BB
4558    mov     r3, r0, lsr #8              @ r3<- CC
4559    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4560    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4561    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4562    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4563    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4564    .if 0
4565    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4566    beq     common_errDivideByZero
4567    .endif
4568    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4569
4570    subs    r0, r0, r2                           @ optional op; may set condition codes
4571    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
4572    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4573    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4574    GOTO_OPCODE(ip)                     @ jump to next instruction
4575    /* 14-17 instructions */
4576
4577
4578
4579/* ------------------------------ */
4580    .balign 64
4581.L_OP_MUL_LONG: /* 0x9d */
4582/* File: armv5te/OP_MUL_LONG.S */
4583    /*
4584     * Signed 64-bit integer multiply.
4585     *
4586     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
4587     *        WX
4588     *      x YZ
4589     *  --------
4590     *     ZW ZX
4591     *  YW YX
4592     *
4593     * The low word of the result holds ZX, the high word holds
4594     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
4595     * it doesn't fit in the low 64 bits.
4596     *
4597     * Unlike most ARM math operations, multiply instructions have
4598     * restrictions on using the same register more than once (Rd and Rm
4599     * cannot be the same).
4600     */
4601    /* mul-long vAA, vBB, vCC */
4602    FETCH(r0, 1)                        @ r0<- CCBB
4603    and     r2, r0, #255                @ r2<- BB
4604    mov     r3, r0, lsr #8              @ r3<- CC
4605    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4606    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4607    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4608    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4609    mul     ip, r2, r1                  @  ip<- ZxW
4610    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
4611    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
4612    mov     r0, rINST, lsr #8           @ r0<- AA
4613    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
4614    add     r0, rFP, r0, lsl #2         @ r0<- &fp[AA]
4615    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4616    b       .LOP_MUL_LONG_finish
4617
4618/* ------------------------------ */
4619    .balign 64
4620.L_OP_DIV_LONG: /* 0x9e */
4621/* File: armv5te/OP_DIV_LONG.S */
4622/* File: armv5te/binopWide.S */
4623    /*
4624     * Generic 64-bit binary operation.  Provide an "instr" line that
4625     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4626     * This could be an ARM instruction or a function call.  (If the result
4627     * comes back in a register other than r0, you can override "result".)
4628     *
4629     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4630     * vCC (r1).  Useful for integer division and modulus.
4631     *
4632     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4633     *      xor-long, add-double, sub-double, mul-double, div-double,
4634     *      rem-double
4635     *
4636     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4637     */
4638    /* binop vAA, vBB, vCC */
4639    FETCH(r0, 1)                        @ r0<- CCBB
4640    mov     r9, rINST, lsr #8           @ r9<- AA
4641    and     r2, r0, #255                @ r2<- BB
4642    mov     r3, r0, lsr #8              @ r3<- CC
4643    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4644    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4645    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4646    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4647    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4648    .if 1
4649    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4650    beq     common_errDivideByZero
4651    .endif
4652    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4653
4654                               @ optional op; may set condition codes
4655    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4656    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4657    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4658    GOTO_OPCODE(ip)                     @ jump to next instruction
4659    /* 14-17 instructions */
4660
4661
4662
4663/* ------------------------------ */
4664    .balign 64
4665.L_OP_REM_LONG: /* 0x9f */
4666/* File: armv5te/OP_REM_LONG.S */
4667/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
4668/* File: armv5te/binopWide.S */
4669    /*
4670     * Generic 64-bit binary operation.  Provide an "instr" line that
4671     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4672     * This could be an ARM instruction or a function call.  (If the result
4673     * comes back in a register other than r0, you can override "result".)
4674     *
4675     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4676     * vCC (r1).  Useful for integer division and modulus.
4677     *
4678     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4679     *      xor-long, add-double, sub-double, mul-double, div-double,
4680     *      rem-double
4681     *
4682     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4683     */
4684    /* binop vAA, vBB, vCC */
4685    FETCH(r0, 1)                        @ r0<- CCBB
4686    mov     r9, rINST, lsr #8           @ r9<- AA
4687    and     r2, r0, #255                @ r2<- BB
4688    mov     r3, r0, lsr #8              @ r3<- CC
4689    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4690    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4691    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4692    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4693    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4694    .if 1
4695    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4696    beq     common_errDivideByZero
4697    .endif
4698    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4699
4700                               @ optional op; may set condition codes
4701    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4702    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4703    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
4704    GOTO_OPCODE(ip)                     @ jump to next instruction
4705    /* 14-17 instructions */
4706
4707
4708
4709/* ------------------------------ */
4710    .balign 64
4711.L_OP_AND_LONG: /* 0xa0 */
4712/* File: armv5te/OP_AND_LONG.S */
4713/* File: armv5te/binopWide.S */
4714    /*
4715     * Generic 64-bit binary operation.  Provide an "instr" line that
4716     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4717     * This could be an ARM instruction or a function call.  (If the result
4718     * comes back in a register other than r0, you can override "result".)
4719     *
4720     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4721     * vCC (r1).  Useful for integer division and modulus.
4722     *
4723     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4724     *      xor-long, add-double, sub-double, mul-double, div-double,
4725     *      rem-double
4726     *
4727     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4728     */
4729    /* binop vAA, vBB, vCC */
4730    FETCH(r0, 1)                        @ r0<- CCBB
4731    mov     r9, rINST, lsr #8           @ r9<- AA
4732    and     r2, r0, #255                @ r2<- BB
4733    mov     r3, r0, lsr #8              @ r3<- CC
4734    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4735    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4736    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4737    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4738    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4739    .if 0
4740    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4741    beq     common_errDivideByZero
4742    .endif
4743    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4744
4745    and     r0, r0, r2                           @ optional op; may set condition codes
4746    and     r1, r1, r3                              @ result<- op, r0-r3 changed
4747    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4748    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4749    GOTO_OPCODE(ip)                     @ jump to next instruction
4750    /* 14-17 instructions */
4751
4752
4753
4754/* ------------------------------ */
4755    .balign 64
4756.L_OP_OR_LONG: /* 0xa1 */
4757/* File: armv5te/OP_OR_LONG.S */
4758/* File: armv5te/binopWide.S */
4759    /*
4760     * Generic 64-bit binary operation.  Provide an "instr" line that
4761     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4762     * This could be an ARM instruction or a function call.  (If the result
4763     * comes back in a register other than r0, you can override "result".)
4764     *
4765     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4766     * vCC (r1).  Useful for integer division and modulus.
4767     *
4768     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4769     *      xor-long, add-double, sub-double, mul-double, div-double,
4770     *      rem-double
4771     *
4772     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4773     */
4774    /* binop vAA, vBB, vCC */
4775    FETCH(r0, 1)                        @ r0<- CCBB
4776    mov     r9, rINST, lsr #8           @ r9<- AA
4777    and     r2, r0, #255                @ r2<- BB
4778    mov     r3, r0, lsr #8              @ r3<- CC
4779    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4780    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4781    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4782    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4783    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4784    .if 0
4785    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4786    beq     common_errDivideByZero
4787    .endif
4788    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4789
4790    orr     r0, r0, r2                           @ optional op; may set condition codes
4791    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
4792    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4793    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4794    GOTO_OPCODE(ip)                     @ jump to next instruction
4795    /* 14-17 instructions */
4796
4797
4798
4799/* ------------------------------ */
4800    .balign 64
4801.L_OP_XOR_LONG: /* 0xa2 */
4802/* File: armv5te/OP_XOR_LONG.S */
4803/* File: armv5te/binopWide.S */
4804    /*
4805     * Generic 64-bit binary operation.  Provide an "instr" line that
4806     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4807     * This could be an ARM instruction or a function call.  (If the result
4808     * comes back in a register other than r0, you can override "result".)
4809     *
4810     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4811     * vCC (r1).  Useful for integer division and modulus.
4812     *
4813     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4814     *      xor-long, add-double, sub-double, mul-double, div-double,
4815     *      rem-double
4816     *
4817     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4818     */
4819    /* binop vAA, vBB, vCC */
4820    FETCH(r0, 1)                        @ r0<- CCBB
4821    mov     r9, rINST, lsr #8           @ r9<- AA
4822    and     r2, r0, #255                @ r2<- BB
4823    mov     r3, r0, lsr #8              @ r3<- CC
4824    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4825    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4826    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4827    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4828    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4829    .if 0
4830    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4831    beq     common_errDivideByZero
4832    .endif
4833    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4834
4835    eor     r0, r0, r2                           @ optional op; may set condition codes
4836    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
4837    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4838    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4839    GOTO_OPCODE(ip)                     @ jump to next instruction
4840    /* 14-17 instructions */
4841
4842
4843
4844/* ------------------------------ */
4845    .balign 64
4846.L_OP_SHL_LONG: /* 0xa3 */
4847/* File: armv5te/OP_SHL_LONG.S */
4848    /*
4849     * Long integer shift.  This is different from the generic 32/64-bit
4850     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4851     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4852     * 6 bits of the shift distance.
4853     */
4854    /* shl-long vAA, vBB, vCC */
4855    FETCH(r0, 1)                        @ r0<- CCBB
4856    mov     r9, rINST, lsr #8           @ r9<- AA
4857    and     r3, r0, #255                @ r3<- BB
4858    mov     r0, r0, lsr #8              @ r0<- CC
4859    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4860    GET_VREG(r2, r0)                    @ r2<- vCC
4861    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4862    and     r2, r2, #63                 @ r2<- r2 & 0x3f
4863    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4864
4865    mov     r1, r1, asl r2              @  r1<- r1 << r2
4866    rsb     r3, r2, #32                 @  r3<- 32 - r2
4867    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
4868    subs    ip, r2, #32                 @  ip<- r2 - 32
4869    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
4870    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4871    b       .LOP_SHL_LONG_finish
4872
4873/* ------------------------------ */
4874    .balign 64
4875.L_OP_SHR_LONG: /* 0xa4 */
4876/* File: armv5te/OP_SHR_LONG.S */
4877    /*
4878     * Long integer shift.  This is different from the generic 32/64-bit
4879     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4880     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4881     * 6 bits of the shift distance.
4882     */
4883    /* shr-long vAA, vBB, vCC */
4884    FETCH(r0, 1)                        @ r0<- CCBB
4885    mov     r9, rINST, lsr #8           @ r9<- AA
4886    and     r3, r0, #255                @ r3<- BB
4887    mov     r0, r0, lsr #8              @ r0<- CC
4888    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4889    GET_VREG(r2, r0)                    @ r2<- vCC
4890    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4891    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4892    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4893
4894    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4895    rsb     r3, r2, #32                 @  r3<- 32 - r2
4896    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4897    subs    ip, r2, #32                 @  ip<- r2 - 32
4898    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
4899    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4900    b       .LOP_SHR_LONG_finish
4901
4902/* ------------------------------ */
4903    .balign 64
4904.L_OP_USHR_LONG: /* 0xa5 */
4905/* File: armv5te/OP_USHR_LONG.S */
4906    /*
4907     * Long integer shift.  This is different from the generic 32/64-bit
4908     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4909     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4910     * 6 bits of the shift distance.
4911     */
4912    /* ushr-long vAA, vBB, vCC */
4913    FETCH(r0, 1)                        @ r0<- CCBB
4914    mov     r9, rINST, lsr #8           @ r9<- AA
4915    and     r3, r0, #255                @ r3<- BB
4916    mov     r0, r0, lsr #8              @ r0<- CC
4917    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4918    GET_VREG(r2, r0)                    @ r2<- vCC
4919    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4920    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4921    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4922
4923    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4924    rsb     r3, r2, #32                 @  r3<- 32 - r2
4925    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4926    subs    ip, r2, #32                 @  ip<- r2 - 32
4927    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
4928    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4929    b       .LOP_USHR_LONG_finish
4930
4931/* ------------------------------ */
4932    .balign 64
4933.L_OP_ADD_FLOAT: /* 0xa6 */
4934/* File: armv5te/OP_ADD_FLOAT.S */
4935/* File: armv5te/binop.S */
4936    /*
4937     * Generic 32-bit binary operation.  Provide an "instr" line that
4938     * specifies an instruction that performs "result = r0 op r1".
4939     * This could be an ARM instruction or a function call.  (If the result
4940     * comes back in a register other than r0, you can override "result".)
4941     *
4942     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4943     * vCC (r1).  Useful for integer division and modulus.  Note that we
4944     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4945     * handles it correctly.
4946     *
4947     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4948     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4949     *      mul-float, div-float, rem-float
4950     */
4951    /* binop vAA, vBB, vCC */
4952    FETCH(r0, 1)                        @ r0<- CCBB
4953    mov     r9, rINST, lsr #8           @ r9<- AA
4954    mov     r3, r0, lsr #8              @ r3<- CC
4955    and     r2, r0, #255                @ r2<- BB
4956    GET_VREG(r1, r3)                    @ r1<- vCC
4957    GET_VREG(r0, r2)                    @ r0<- vBB
4958    .if 0
4959    cmp     r1, #0                      @ is second operand zero?
4960    beq     common_errDivideByZero
4961    .endif
4962
4963    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4964                               @ optional op; may set condition codes
4965    bl      __aeabi_fadd                              @ r0<- op, r0-r3 changed
4966    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4967    SET_VREG(r0, r9)               @ vAA<- r0
4968    GOTO_OPCODE(ip)                     @ jump to next instruction
4969    /* 11-14 instructions */
4970
4971
4972
4973/* ------------------------------ */
4974    .balign 64
4975.L_OP_SUB_FLOAT: /* 0xa7 */
4976/* File: armv5te/OP_SUB_FLOAT.S */
4977/* File: armv5te/binop.S */
4978    /*
4979     * Generic 32-bit binary operation.  Provide an "instr" line that
4980     * specifies an instruction that performs "result = r0 op r1".
4981     * This could be an ARM instruction or a function call.  (If the result
4982     * comes back in a register other than r0, you can override "result".)
4983     *
4984     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4985     * vCC (r1).  Useful for integer division and modulus.  Note that we
4986     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4987     * handles it correctly.
4988     *
4989     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4990     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4991     *      mul-float, div-float, rem-float
4992     */
4993    /* binop vAA, vBB, vCC */
4994    FETCH(r0, 1)                        @ r0<- CCBB
4995    mov     r9, rINST, lsr #8           @ r9<- AA
4996    mov     r3, r0, lsr #8              @ r3<- CC
4997    and     r2, r0, #255                @ r2<- BB
4998    GET_VREG(r1, r3)                    @ r1<- vCC
4999    GET_VREG(r0, r2)                    @ r0<- vBB
5000    .if 0
5001    cmp     r1, #0                      @ is second operand zero?
5002    beq     common_errDivideByZero
5003    .endif
5004
5005    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5006                               @ optional op; may set condition codes
5007    bl      __aeabi_fsub                              @ r0<- op, r0-r3 changed
5008    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5009    SET_VREG(r0, r9)               @ vAA<- r0
5010    GOTO_OPCODE(ip)                     @ jump to next instruction
5011    /* 11-14 instructions */
5012
5013
5014
5015/* ------------------------------ */
5016    .balign 64
5017.L_OP_MUL_FLOAT: /* 0xa8 */
5018/* File: armv5te/OP_MUL_FLOAT.S */
5019/* File: armv5te/binop.S */
5020    /*
5021     * Generic 32-bit binary operation.  Provide an "instr" line that
5022     * specifies an instruction that performs "result = r0 op r1".
5023     * This could be an ARM instruction or a function call.  (If the result
5024     * comes back in a register other than r0, you can override "result".)
5025     *
5026     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5027     * vCC (r1).  Useful for integer division and modulus.  Note that we
5028     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5029     * handles it correctly.
5030     *
5031     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5032     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5033     *      mul-float, div-float, rem-float
5034     */
5035    /* binop vAA, vBB, vCC */
5036    FETCH(r0, 1)                        @ r0<- CCBB
5037    mov     r9, rINST, lsr #8           @ r9<- AA
5038    mov     r3, r0, lsr #8              @ r3<- CC
5039    and     r2, r0, #255                @ r2<- BB
5040    GET_VREG(r1, r3)                    @ r1<- vCC
5041    GET_VREG(r0, r2)                    @ r0<- vBB
5042    .if 0
5043    cmp     r1, #0                      @ is second operand zero?
5044    beq     common_errDivideByZero
5045    .endif
5046
5047    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5048                               @ optional op; may set condition codes
5049    bl      __aeabi_fmul                              @ r0<- op, r0-r3 changed
5050    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5051    SET_VREG(r0, r9)               @ vAA<- r0
5052    GOTO_OPCODE(ip)                     @ jump to next instruction
5053    /* 11-14 instructions */
5054
5055
5056
5057/* ------------------------------ */
5058    .balign 64
5059.L_OP_DIV_FLOAT: /* 0xa9 */
5060/* File: armv5te/OP_DIV_FLOAT.S */
5061/* File: armv5te/binop.S */
5062    /*
5063     * Generic 32-bit binary operation.  Provide an "instr" line that
5064     * specifies an instruction that performs "result = r0 op r1".
5065     * This could be an ARM instruction or a function call.  (If the result
5066     * comes back in a register other than r0, you can override "result".)
5067     *
5068     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5069     * vCC (r1).  Useful for integer division and modulus.  Note that we
5070     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5071     * handles it correctly.
5072     *
5073     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5074     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5075     *      mul-float, div-float, rem-float
5076     */
5077    /* binop vAA, vBB, vCC */
5078    FETCH(r0, 1)                        @ r0<- CCBB
5079    mov     r9, rINST, lsr #8           @ r9<- AA
5080    mov     r3, r0, lsr #8              @ r3<- CC
5081    and     r2, r0, #255                @ r2<- BB
5082    GET_VREG(r1, r3)                    @ r1<- vCC
5083    GET_VREG(r0, r2)                    @ r0<- vBB
5084    .if 0
5085    cmp     r1, #0                      @ is second operand zero?
5086    beq     common_errDivideByZero
5087    .endif
5088
5089    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5090                               @ optional op; may set condition codes
5091    bl      __aeabi_fdiv                              @ r0<- op, r0-r3 changed
5092    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5093    SET_VREG(r0, r9)               @ vAA<- r0
5094    GOTO_OPCODE(ip)                     @ jump to next instruction
5095    /* 11-14 instructions */
5096
5097
5098
5099/* ------------------------------ */
5100    .balign 64
5101.L_OP_REM_FLOAT: /* 0xaa */
5102/* File: armv5te/OP_REM_FLOAT.S */
5103/* EABI doesn't define a float remainder function, but libm does */
5104/* File: armv5te/binop.S */
5105    /*
5106     * Generic 32-bit binary operation.  Provide an "instr" line that
5107     * specifies an instruction that performs "result = r0 op r1".
5108     * This could be an ARM instruction or a function call.  (If the result
5109     * comes back in a register other than r0, you can override "result".)
5110     *
5111     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5112     * vCC (r1).  Useful for integer division and modulus.  Note that we
5113     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5114     * handles it correctly.
5115     *
5116     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5117     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5118     *      mul-float, div-float, rem-float
5119     */
5120    /* binop vAA, vBB, vCC */
5121    FETCH(r0, 1)                        @ r0<- CCBB
5122    mov     r9, rINST, lsr #8           @ r9<- AA
5123    mov     r3, r0, lsr #8              @ r3<- CC
5124    and     r2, r0, #255                @ r2<- BB
5125    GET_VREG(r1, r3)                    @ r1<- vCC
5126    GET_VREG(r0, r2)                    @ r0<- vBB
5127    .if 0
5128    cmp     r1, #0                      @ is second operand zero?
5129    beq     common_errDivideByZero
5130    .endif
5131
5132    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5133                               @ optional op; may set condition codes
5134    bl      fmodf                              @ r0<- op, r0-r3 changed
5135    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5136    SET_VREG(r0, r9)               @ vAA<- r0
5137    GOTO_OPCODE(ip)                     @ jump to next instruction
5138    /* 11-14 instructions */
5139
5140
5141
5142/* ------------------------------ */
5143    .balign 64
5144.L_OP_ADD_DOUBLE: /* 0xab */
5145/* File: armv5te/OP_ADD_DOUBLE.S */
5146/* File: armv5te/binopWide.S */
5147    /*
5148     * Generic 64-bit binary operation.  Provide an "instr" line that
5149     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5150     * This could be an ARM instruction or a function call.  (If the result
5151     * comes back in a register other than r0, you can override "result".)
5152     *
5153     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5154     * vCC (r1).  Useful for integer division and modulus.
5155     *
5156     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5157     *      xor-long, add-double, sub-double, mul-double, div-double,
5158     *      rem-double
5159     *
5160     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5161     */
5162    /* binop vAA, vBB, vCC */
5163    FETCH(r0, 1)                        @ r0<- CCBB
5164    mov     r9, rINST, lsr #8           @ r9<- AA
5165    and     r2, r0, #255                @ r2<- BB
5166    mov     r3, r0, lsr #8              @ r3<- CC
5167    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5168    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5169    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5170    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5171    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5172    .if 0
5173    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5174    beq     common_errDivideByZero
5175    .endif
5176    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5177
5178                               @ optional op; may set condition codes
5179    bl      __aeabi_dadd                              @ result<- op, r0-r3 changed
5180    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5181    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5182    GOTO_OPCODE(ip)                     @ jump to next instruction
5183    /* 14-17 instructions */
5184
5185
5186
5187/* ------------------------------ */
5188    .balign 64
5189.L_OP_SUB_DOUBLE: /* 0xac */
5190/* File: armv5te/OP_SUB_DOUBLE.S */
5191/* File: armv5te/binopWide.S */
5192    /*
5193     * Generic 64-bit binary operation.  Provide an "instr" line that
5194     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5195     * This could be an ARM instruction or a function call.  (If the result
5196     * comes back in a register other than r0, you can override "result".)
5197     *
5198     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5199     * vCC (r1).  Useful for integer division and modulus.
5200     *
5201     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5202     *      xor-long, add-double, sub-double, mul-double, div-double,
5203     *      rem-double
5204     *
5205     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5206     */
5207    /* binop vAA, vBB, vCC */
5208    FETCH(r0, 1)                        @ r0<- CCBB
5209    mov     r9, rINST, lsr #8           @ r9<- AA
5210    and     r2, r0, #255                @ r2<- BB
5211    mov     r3, r0, lsr #8              @ r3<- CC
5212    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5213    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5214    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5215    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5216    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5217    .if 0
5218    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5219    beq     common_errDivideByZero
5220    .endif
5221    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5222
5223                               @ optional op; may set condition codes
5224    bl      __aeabi_dsub                              @ result<- op, r0-r3 changed
5225    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5226    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5227    GOTO_OPCODE(ip)                     @ jump to next instruction
5228    /* 14-17 instructions */
5229
5230
5231
5232/* ------------------------------ */
5233    .balign 64
5234.L_OP_MUL_DOUBLE: /* 0xad */
5235/* File: armv5te/OP_MUL_DOUBLE.S */
5236/* File: armv5te/binopWide.S */
5237    /*
5238     * Generic 64-bit binary operation.  Provide an "instr" line that
5239     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5240     * This could be an ARM instruction or a function call.  (If the result
5241     * comes back in a register other than r0, you can override "result".)
5242     *
5243     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5244     * vCC (r1).  Useful for integer division and modulus.
5245     *
5246     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5247     *      xor-long, add-double, sub-double, mul-double, div-double,
5248     *      rem-double
5249     *
5250     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5251     */
5252    /* binop vAA, vBB, vCC */
5253    FETCH(r0, 1)                        @ r0<- CCBB
5254    mov     r9, rINST, lsr #8           @ r9<- AA
5255    and     r2, r0, #255                @ r2<- BB
5256    mov     r3, r0, lsr #8              @ r3<- CC
5257    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5258    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5259    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5260    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5261    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5262    .if 0
5263    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5264    beq     common_errDivideByZero
5265    .endif
5266    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5267
5268                               @ optional op; may set condition codes
5269    bl      __aeabi_dmul                              @ result<- op, r0-r3 changed
5270    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5271    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5272    GOTO_OPCODE(ip)                     @ jump to next instruction
5273    /* 14-17 instructions */
5274
5275
5276
5277/* ------------------------------ */
5278    .balign 64
5279.L_OP_DIV_DOUBLE: /* 0xae */
5280/* File: armv5te/OP_DIV_DOUBLE.S */
5281/* File: armv5te/binopWide.S */
5282    /*
5283     * Generic 64-bit binary operation.  Provide an "instr" line that
5284     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5285     * This could be an ARM instruction or a function call.  (If the result
5286     * comes back in a register other than r0, you can override "result".)
5287     *
5288     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5289     * vCC (r1).  Useful for integer division and modulus.
5290     *
5291     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5292     *      xor-long, add-double, sub-double, mul-double, div-double,
5293     *      rem-double
5294     *
5295     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5296     */
5297    /* binop vAA, vBB, vCC */
5298    FETCH(r0, 1)                        @ r0<- CCBB
5299    mov     r9, rINST, lsr #8           @ r9<- AA
5300    and     r2, r0, #255                @ r2<- BB
5301    mov     r3, r0, lsr #8              @ r3<- CC
5302    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5303    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5304    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5305    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5306    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5307    .if 0
5308    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5309    beq     common_errDivideByZero
5310    .endif
5311    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5312
5313                               @ optional op; may set condition codes
5314    bl      __aeabi_ddiv                              @ result<- op, r0-r3 changed
5315    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5316    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5317    GOTO_OPCODE(ip)                     @ jump to next instruction
5318    /* 14-17 instructions */
5319
5320
5321
5322/* ------------------------------ */
5323    .balign 64
5324.L_OP_REM_DOUBLE: /* 0xaf */
5325/* File: armv5te/OP_REM_DOUBLE.S */
5326/* EABI doesn't define a double remainder function, but libm does */
5327/* File: armv5te/binopWide.S */
5328    /*
5329     * Generic 64-bit binary operation.  Provide an "instr" line that
5330     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5331     * This could be an ARM instruction or a function call.  (If the result
5332     * comes back in a register other than r0, you can override "result".)
5333     *
5334     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5335     * vCC (r1).  Useful for integer division and modulus.
5336     *
5337     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5338     *      xor-long, add-double, sub-double, mul-double, div-double,
5339     *      rem-double
5340     *
5341     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5342     */
5343    /* binop vAA, vBB, vCC */
5344    FETCH(r0, 1)                        @ r0<- CCBB
5345    mov     r9, rINST, lsr #8           @ r9<- AA
5346    and     r2, r0, #255                @ r2<- BB
5347    mov     r3, r0, lsr #8              @ r3<- CC
5348    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5349    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5350    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5351    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5352    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5353    .if 0
5354    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5355    beq     common_errDivideByZero
5356    .endif
5357    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5358
5359                               @ optional op; may set condition codes
5360    bl      fmod                              @ result<- op, r0-r3 changed
5361    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5362    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5363    GOTO_OPCODE(ip)                     @ jump to next instruction
5364    /* 14-17 instructions */
5365
5366
5367
5368/* ------------------------------ */
5369    .balign 64
5370.L_OP_ADD_INT_2ADDR: /* 0xb0 */
5371/* File: armv5te/OP_ADD_INT_2ADDR.S */
5372/* File: armv5te/binop2addr.S */
5373    /*
5374     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5375     * that specifies an instruction that performs "result = r0 op r1".
5376     * This could be an ARM instruction or a function call.  (If the result
5377     * comes back in a register other than r0, you can override "result".)
5378     *
5379     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5380     * vCC (r1).  Useful for integer division and modulus.
5381     *
5382     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5383     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5384     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5385     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5386     */
5387    /* binop/2addr vA, vB */
5388    mov     r9, rINST, lsr #8           @ r9<- A+
5389    mov     r3, rINST, lsr #12          @ r3<- B
5390    and     r9, r9, #15
5391    GET_VREG(r0, r9)                    @ r0<- vA
5392    GET_VREG(r1, r3)                    @ r1<- vB
5393    .if 0
5394    cmp     r1, #0                      @ is second operand zero?
5395    beq     common_errDivideByZero
5396    .endif
5397    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5398
5399                               @ optional op; may set condition codes
5400    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
5401    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5402    SET_VREG(r0, r9)               @ vAA<- r0
5403    GOTO_OPCODE(ip)                     @ jump to next instruction
5404    /* 10-13 instructions */
5405
5406
5407
5408/* ------------------------------ */
5409    .balign 64
5410.L_OP_SUB_INT_2ADDR: /* 0xb1 */
5411/* File: armv5te/OP_SUB_INT_2ADDR.S */
5412/* File: armv5te/binop2addr.S */
5413    /*
5414     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5415     * that specifies an instruction that performs "result = r0 op r1".
5416     * This could be an ARM instruction or a function call.  (If the result
5417     * comes back in a register other than r0, you can override "result".)
5418     *
5419     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5420     * vCC (r1).  Useful for integer division and modulus.
5421     *
5422     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5423     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5424     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5425     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5426     */
5427    /* binop/2addr vA, vB */
5428    mov     r9, rINST, lsr #8           @ r9<- A+
5429    mov     r3, rINST, lsr #12          @ r3<- B
5430    and     r9, r9, #15
5431    GET_VREG(r0, r9)                    @ r0<- vA
5432    GET_VREG(r1, r3)                    @ r1<- vB
5433    .if 0
5434    cmp     r1, #0                      @ is second operand zero?
5435    beq     common_errDivideByZero
5436    .endif
5437    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5438
5439                               @ optional op; may set condition codes
5440    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
5441    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5442    SET_VREG(r0, r9)               @ vAA<- r0
5443    GOTO_OPCODE(ip)                     @ jump to next instruction
5444    /* 10-13 instructions */
5445
5446
5447
5448/* ------------------------------ */
5449    .balign 64
5450.L_OP_MUL_INT_2ADDR: /* 0xb2 */
5451/* File: armv5te/OP_MUL_INT_2ADDR.S */
5452/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
5453/* File: armv5te/binop2addr.S */
5454    /*
5455     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5456     * that specifies an instruction that performs "result = r0 op r1".
5457     * This could be an ARM instruction or a function call.  (If the result
5458     * comes back in a register other than r0, you can override "result".)
5459     *
5460     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5461     * vCC (r1).  Useful for integer division and modulus.
5462     *
5463     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5464     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5465     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5466     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5467     */
5468    /* binop/2addr vA, vB */
5469    mov     r9, rINST, lsr #8           @ r9<- A+
5470    mov     r3, rINST, lsr #12          @ r3<- B
5471    and     r9, r9, #15
5472    GET_VREG(r0, r9)                    @ r0<- vA
5473    GET_VREG(r1, r3)                    @ r1<- vB
5474    .if 0
5475    cmp     r1, #0                      @ is second operand zero?
5476    beq     common_errDivideByZero
5477    .endif
5478    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5479
5480                               @ optional op; may set condition codes
5481    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
5482    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5483    SET_VREG(r0, r9)               @ vAA<- r0
5484    GOTO_OPCODE(ip)                     @ jump to next instruction
5485    /* 10-13 instructions */
5486
5487
5488
5489/* ------------------------------ */
5490    .balign 64
5491.L_OP_DIV_INT_2ADDR: /* 0xb3 */
5492/* File: armv5te/OP_DIV_INT_2ADDR.S */
5493/* File: armv5te/binop2addr.S */
5494    /*
5495     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5496     * that specifies an instruction that performs "result = r0 op r1".
5497     * This could be an ARM instruction or a function call.  (If the result
5498     * comes back in a register other than r0, you can override "result".)
5499     *
5500     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5501     * vCC (r1).  Useful for integer division and modulus.
5502     *
5503     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5504     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5505     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5506     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5507     */
5508    /* binop/2addr vA, vB */
5509    mov     r9, rINST, lsr #8           @ r9<- A+
5510    mov     r3, rINST, lsr #12          @ r3<- B
5511    and     r9, r9, #15
5512    GET_VREG(r0, r9)                    @ r0<- vA
5513    GET_VREG(r1, r3)                    @ r1<- vB
5514    .if 1
5515    cmp     r1, #0                      @ is second operand zero?
5516    beq     common_errDivideByZero
5517    .endif
5518    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5519
5520                               @ optional op; may set condition codes
5521    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
5522    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5523    SET_VREG(r0, r9)               @ vAA<- r0
5524    GOTO_OPCODE(ip)                     @ jump to next instruction
5525    /* 10-13 instructions */
5526
5527
5528
5529/* ------------------------------ */
5530    .balign 64
5531.L_OP_REM_INT_2ADDR: /* 0xb4 */
5532/* File: armv5te/OP_REM_INT_2ADDR.S */
5533/* idivmod returns quotient in r0 and remainder in r1 */
5534/* File: armv5te/binop2addr.S */
5535    /*
5536     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5537     * that specifies an instruction that performs "result = r0 op r1".
5538     * This could be an ARM instruction or a function call.  (If the result
5539     * comes back in a register other than r0, you can override "result".)
5540     *
5541     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5542     * vCC (r1).  Useful for integer division and modulus.
5543     *
5544     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5545     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5546     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5547     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5548     */
5549    /* binop/2addr vA, vB */
5550    mov     r9, rINST, lsr #8           @ r9<- A+
5551    mov     r3, rINST, lsr #12          @ r3<- B
5552    and     r9, r9, #15
5553    GET_VREG(r0, r9)                    @ r0<- vA
5554    GET_VREG(r1, r3)                    @ r1<- vB
5555    .if 1
5556    cmp     r1, #0                      @ is second operand zero?
5557    beq     common_errDivideByZero
5558    .endif
5559    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5560
5561                               @ optional op; may set condition codes
5562    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
5563    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5564    SET_VREG(r1, r9)               @ vAA<- r1
5565    GOTO_OPCODE(ip)                     @ jump to next instruction
5566    /* 10-13 instructions */
5567
5568
5569
5570/* ------------------------------ */
5571    .balign 64
5572.L_OP_AND_INT_2ADDR: /* 0xb5 */
5573/* File: armv5te/OP_AND_INT_2ADDR.S */
5574/* File: armv5te/binop2addr.S */
5575    /*
5576     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5577     * that specifies an instruction that performs "result = r0 op r1".
5578     * This could be an ARM instruction or a function call.  (If the result
5579     * comes back in a register other than r0, you can override "result".)
5580     *
5581     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5582     * vCC (r1).  Useful for integer division and modulus.
5583     *
5584     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5585     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5586     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5587     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5588     */
5589    /* binop/2addr vA, vB */
5590    mov     r9, rINST, lsr #8           @ r9<- A+
5591    mov     r3, rINST, lsr #12          @ r3<- B
5592    and     r9, r9, #15
5593    GET_VREG(r0, r9)                    @ r0<- vA
5594    GET_VREG(r1, r3)                    @ r1<- vB
5595    .if 0
5596    cmp     r1, #0                      @ is second operand zero?
5597    beq     common_errDivideByZero
5598    .endif
5599    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5600
5601                               @ optional op; may set condition codes
5602    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
5603    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5604    SET_VREG(r0, r9)               @ vAA<- r0
5605    GOTO_OPCODE(ip)                     @ jump to next instruction
5606    /* 10-13 instructions */
5607
5608
5609
5610/* ------------------------------ */
5611    .balign 64
5612.L_OP_OR_INT_2ADDR: /* 0xb6 */
5613/* File: armv5te/OP_OR_INT_2ADDR.S */
5614/* File: armv5te/binop2addr.S */
5615    /*
5616     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5617     * that specifies an instruction that performs "result = r0 op r1".
5618     * This could be an ARM instruction or a function call.  (If the result
5619     * comes back in a register other than r0, you can override "result".)
5620     *
5621     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5622     * vCC (r1).  Useful for integer division and modulus.
5623     *
5624     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5625     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5626     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5627     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5628     */
5629    /* binop/2addr vA, vB */
5630    mov     r9, rINST, lsr #8           @ r9<- A+
5631    mov     r3, rINST, lsr #12          @ r3<- B
5632    and     r9, r9, #15
5633    GET_VREG(r0, r9)                    @ r0<- vA
5634    GET_VREG(r1, r3)                    @ r1<- vB
5635    .if 0
5636    cmp     r1, #0                      @ is second operand zero?
5637    beq     common_errDivideByZero
5638    .endif
5639    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5640
5641                               @ optional op; may set condition codes
5642    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
5643    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5644    SET_VREG(r0, r9)               @ vAA<- r0
5645    GOTO_OPCODE(ip)                     @ jump to next instruction
5646    /* 10-13 instructions */
5647
5648
5649
5650/* ------------------------------ */
5651    .balign 64
5652.L_OP_XOR_INT_2ADDR: /* 0xb7 */
5653/* File: armv5te/OP_XOR_INT_2ADDR.S */
5654/* File: armv5te/binop2addr.S */
5655    /*
5656     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5657     * that specifies an instruction that performs "result = r0 op r1".
5658     * This could be an ARM instruction or a function call.  (If the result
5659     * comes back in a register other than r0, you can override "result".)
5660     *
5661     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5662     * vCC (r1).  Useful for integer division and modulus.
5663     *
5664     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5665     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5666     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5667     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5668     */
5669    /* binop/2addr vA, vB */
5670    mov     r9, rINST, lsr #8           @ r9<- A+
5671    mov     r3, rINST, lsr #12          @ r3<- B
5672    and     r9, r9, #15
5673    GET_VREG(r0, r9)                    @ r0<- vA
5674    GET_VREG(r1, r3)                    @ r1<- vB
5675    .if 0
5676    cmp     r1, #0                      @ is second operand zero?
5677    beq     common_errDivideByZero
5678    .endif
5679    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5680
5681                               @ optional op; may set condition codes
5682    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
5683    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5684    SET_VREG(r0, r9)               @ vAA<- r0
5685    GOTO_OPCODE(ip)                     @ jump to next instruction
5686    /* 10-13 instructions */
5687
5688
5689
5690/* ------------------------------ */
5691    .balign 64
5692.L_OP_SHL_INT_2ADDR: /* 0xb8 */
5693/* File: armv5te/OP_SHL_INT_2ADDR.S */
5694/* File: armv5te/binop2addr.S */
5695    /*
5696     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5697     * that specifies an instruction that performs "result = r0 op r1".
5698     * This could be an ARM instruction or a function call.  (If the result
5699     * comes back in a register other than r0, you can override "result".)
5700     *
5701     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5702     * vCC (r1).  Useful for integer division and modulus.
5703     *
5704     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5705     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5706     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5707     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5708     */
5709    /* binop/2addr vA, vB */
5710    mov     r9, rINST, lsr #8           @ r9<- A+
5711    mov     r3, rINST, lsr #12          @ r3<- B
5712    and     r9, r9, #15
5713    GET_VREG(r0, r9)                    @ r0<- vA
5714    GET_VREG(r1, r3)                    @ r1<- vB
5715    .if 0
5716    cmp     r1, #0                      @ is second operand zero?
5717    beq     common_errDivideByZero
5718    .endif
5719    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5720
5721    and     r1, r1, #31                           @ optional op; may set condition codes
5722    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
5723    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5724    SET_VREG(r0, r9)               @ vAA<- r0
5725    GOTO_OPCODE(ip)                     @ jump to next instruction
5726    /* 10-13 instructions */
5727
5728
5729
5730/* ------------------------------ */
5731    .balign 64
5732.L_OP_SHR_INT_2ADDR: /* 0xb9 */
5733/* File: armv5te/OP_SHR_INT_2ADDR.S */
5734/* File: armv5te/binop2addr.S */
5735    /*
5736     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5737     * that specifies an instruction that performs "result = r0 op r1".
5738     * This could be an ARM instruction or a function call.  (If the result
5739     * comes back in a register other than r0, you can override "result".)
5740     *
5741     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5742     * vCC (r1).  Useful for integer division and modulus.
5743     *
5744     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5745     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5746     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5747     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5748     */
5749    /* binop/2addr vA, vB */
5750    mov     r9, rINST, lsr #8           @ r9<- A+
5751    mov     r3, rINST, lsr #12          @ r3<- B
5752    and     r9, r9, #15
5753    GET_VREG(r0, r9)                    @ r0<- vA
5754    GET_VREG(r1, r3)                    @ r1<- vB
5755    .if 0
5756    cmp     r1, #0                      @ is second operand zero?
5757    beq     common_errDivideByZero
5758    .endif
5759    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5760
5761    and     r1, r1, #31                           @ optional op; may set condition codes
5762    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
5763    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5764    SET_VREG(r0, r9)               @ vAA<- r0
5765    GOTO_OPCODE(ip)                     @ jump to next instruction
5766    /* 10-13 instructions */
5767
5768
5769
5770/* ------------------------------ */
5771    .balign 64
5772.L_OP_USHR_INT_2ADDR: /* 0xba */
5773/* File: armv5te/OP_USHR_INT_2ADDR.S */
5774/* File: armv5te/binop2addr.S */
5775    /*
5776     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5777     * that specifies an instruction that performs "result = r0 op r1".
5778     * This could be an ARM instruction or a function call.  (If the result
5779     * comes back in a register other than r0, you can override "result".)
5780     *
5781     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5782     * vCC (r1).  Useful for integer division and modulus.
5783     *
5784     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5785     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5786     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5787     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5788     */
5789    /* binop/2addr vA, vB */
5790    mov     r9, rINST, lsr #8           @ r9<- A+
5791    mov     r3, rINST, lsr #12          @ r3<- B
5792    and     r9, r9, #15
5793    GET_VREG(r0, r9)                    @ r0<- vA
5794    GET_VREG(r1, r3)                    @ r1<- vB
5795    .if 0
5796    cmp     r1, #0                      @ is second operand zero?
5797    beq     common_errDivideByZero
5798    .endif
5799    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5800
5801    and     r1, r1, #31                           @ optional op; may set condition codes
5802    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
5803    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5804    SET_VREG(r0, r9)               @ vAA<- r0
5805    GOTO_OPCODE(ip)                     @ jump to next instruction
5806    /* 10-13 instructions */
5807
5808
5809
5810/* ------------------------------ */
5811    .balign 64
5812.L_OP_ADD_LONG_2ADDR: /* 0xbb */
5813/* File: armv5te/OP_ADD_LONG_2ADDR.S */
5814/* File: armv5te/binopWide2addr.S */
5815    /*
5816     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5817     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5818     * This could be an ARM instruction or a function call.  (If the result
5819     * comes back in a register other than r0, you can override "result".)
5820     *
5821     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5822     * vCC (r1).  Useful for integer division and modulus.
5823     *
5824     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5825     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5826     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5827     *      rem-double/2addr
5828     */
5829    /* binop/2addr vA, vB */
5830    mov     r9, rINST, lsr #8           @ r9<- A+
5831    mov     r1, rINST, lsr #12          @ r1<- B
5832    and     r9, r9, #15
5833    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5834    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5835    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5836    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5837    .if 0
5838    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5839    beq     common_errDivideByZero
5840    .endif
5841    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5842
5843    adds    r0, r0, r2                           @ optional op; may set condition codes
5844    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
5845    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5846    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5847    GOTO_OPCODE(ip)                     @ jump to next instruction
5848    /* 12-15 instructions */
5849
5850
5851
5852/* ------------------------------ */
5853    .balign 64
5854.L_OP_SUB_LONG_2ADDR: /* 0xbc */
5855/* File: armv5te/OP_SUB_LONG_2ADDR.S */
5856/* File: armv5te/binopWide2addr.S */
5857    /*
5858     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5859     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5860     * This could be an ARM instruction or a function call.  (If the result
5861     * comes back in a register other than r0, you can override "result".)
5862     *
5863     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5864     * vCC (r1).  Useful for integer division and modulus.
5865     *
5866     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5867     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5868     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5869     *      rem-double/2addr
5870     */
5871    /* binop/2addr vA, vB */
5872    mov     r9, rINST, lsr #8           @ r9<- A+
5873    mov     r1, rINST, lsr #12          @ r1<- B
5874    and     r9, r9, #15
5875    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5876    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5877    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5878    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5879    .if 0
5880    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5881    beq     common_errDivideByZero
5882    .endif
5883    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5884
5885    subs    r0, r0, r2                           @ optional op; may set condition codes
5886    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
5887    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5888    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5889    GOTO_OPCODE(ip)                     @ jump to next instruction
5890    /* 12-15 instructions */
5891
5892
5893
5894/* ------------------------------ */
5895    .balign 64
5896.L_OP_MUL_LONG_2ADDR: /* 0xbd */
5897/* File: armv5te/OP_MUL_LONG_2ADDR.S */
5898    /*
5899     * Signed 64-bit integer multiply, "/2addr" version.
5900     *
5901     * See OP_MUL_LONG for an explanation.
5902     *
5903     * We get a little tight on registers, so to avoid looking up &fp[A]
5904     * again we stuff it into rINST.
5905     */
5906    /* mul-long/2addr vA, vB */
5907    mov     r9, rINST, lsr #8           @ r9<- A+
5908    mov     r1, rINST, lsr #12          @ r1<- B
5909    and     r9, r9, #15
5910    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5911    add     rINST, rFP, r9, lsl #2      @ rINST<- &fp[A]
5912    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5913    ldmia   rINST, {r0-r1}              @ r0/r1<- vAA/vAA+1
5914    mul     ip, r2, r1                  @  ip<- ZxW
5915    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
5916    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
5917    mov     r0, rINST                   @ r0<- &fp[A] (free up rINST)
5918    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5919    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
5920    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5921    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
5922    GOTO_OPCODE(ip)                     @ jump to next instruction
5923
5924
5925/* ------------------------------ */
5926    .balign 64
5927.L_OP_DIV_LONG_2ADDR: /* 0xbe */
5928/* File: armv5te/OP_DIV_LONG_2ADDR.S */
5929/* File: armv5te/binopWide2addr.S */
5930    /*
5931     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5932     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5933     * This could be an ARM instruction or a function call.  (If the result
5934     * comes back in a register other than r0, you can override "result".)
5935     *
5936     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5937     * vCC (r1).  Useful for integer division and modulus.
5938     *
5939     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5940     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5941     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5942     *      rem-double/2addr
5943     */
5944    /* binop/2addr vA, vB */
5945    mov     r9, rINST, lsr #8           @ r9<- A+
5946    mov     r1, rINST, lsr #12          @ r1<- B
5947    and     r9, r9, #15
5948    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5949    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5950    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5951    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5952    .if 1
5953    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5954    beq     common_errDivideByZero
5955    .endif
5956    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5957
5958                               @ optional op; may set condition codes
5959    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5960    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5961    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5962    GOTO_OPCODE(ip)                     @ jump to next instruction
5963    /* 12-15 instructions */
5964
5965
5966
5967/* ------------------------------ */
5968    .balign 64
5969.L_OP_REM_LONG_2ADDR: /* 0xbf */
5970/* File: armv5te/OP_REM_LONG_2ADDR.S */
5971/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
5972/* File: armv5te/binopWide2addr.S */
5973    /*
5974     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5975     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5976     * This could be an ARM instruction or a function call.  (If the result
5977     * comes back in a register other than r0, you can override "result".)
5978     *
5979     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5980     * vCC (r1).  Useful for integer division and modulus.
5981     *
5982     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5983     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5984     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5985     *      rem-double/2addr
5986     */
5987    /* binop/2addr vA, vB */
5988    mov     r9, rINST, lsr #8           @ r9<- A+
5989    mov     r1, rINST, lsr #12          @ r1<- B
5990    and     r9, r9, #15
5991    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5992    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5993    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5994    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5995    .if 1
5996    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5997    beq     common_errDivideByZero
5998    .endif
5999    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6000
6001                               @ optional op; may set condition codes
6002    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
6003    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6004    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
6005    GOTO_OPCODE(ip)                     @ jump to next instruction
6006    /* 12-15 instructions */
6007
6008
6009
6010/* ------------------------------ */
6011    .balign 64
6012.L_OP_AND_LONG_2ADDR: /* 0xc0 */
6013/* File: armv5te/OP_AND_LONG_2ADDR.S */
6014/* File: armv5te/binopWide2addr.S */
6015    /*
6016     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6017     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6018     * This could be an ARM instruction or a function call.  (If the result
6019     * comes back in a register other than r0, you can override "result".)
6020     *
6021     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6022     * vCC (r1).  Useful for integer division and modulus.
6023     *
6024     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6025     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6026     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6027     *      rem-double/2addr
6028     */
6029    /* binop/2addr vA, vB */
6030    mov     r9, rINST, lsr #8           @ r9<- A+
6031    mov     r1, rINST, lsr #12          @ r1<- B
6032    and     r9, r9, #15
6033    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6034    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6035    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6036    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6037    .if 0
6038    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6039    beq     common_errDivideByZero
6040    .endif
6041    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6042
6043    and     r0, r0, r2                           @ optional op; may set condition codes
6044    and     r1, r1, r3                              @ result<- op, r0-r3 changed
6045    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6046    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6047    GOTO_OPCODE(ip)                     @ jump to next instruction
6048    /* 12-15 instructions */
6049
6050
6051
6052/* ------------------------------ */
6053    .balign 64
6054.L_OP_OR_LONG_2ADDR: /* 0xc1 */
6055/* File: armv5te/OP_OR_LONG_2ADDR.S */
6056/* File: armv5te/binopWide2addr.S */
6057    /*
6058     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6059     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6060     * This could be an ARM instruction or a function call.  (If the result
6061     * comes back in a register other than r0, you can override "result".)
6062     *
6063     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6064     * vCC (r1).  Useful for integer division and modulus.
6065     *
6066     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6067     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6068     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6069     *      rem-double/2addr
6070     */
6071    /* binop/2addr vA, vB */
6072    mov     r9, rINST, lsr #8           @ r9<- A+
6073    mov     r1, rINST, lsr #12          @ r1<- B
6074    and     r9, r9, #15
6075    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6076    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6077    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6078    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6079    .if 0
6080    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6081    beq     common_errDivideByZero
6082    .endif
6083    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6084
6085    orr     r0, r0, r2                           @ optional op; may set condition codes
6086    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
6087    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6088    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6089    GOTO_OPCODE(ip)                     @ jump to next instruction
6090    /* 12-15 instructions */
6091
6092
6093
6094/* ------------------------------ */
6095    .balign 64
6096.L_OP_XOR_LONG_2ADDR: /* 0xc2 */
6097/* File: armv5te/OP_XOR_LONG_2ADDR.S */
6098/* File: armv5te/binopWide2addr.S */
6099    /*
6100     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6101     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6102     * This could be an ARM instruction or a function call.  (If the result
6103     * comes back in a register other than r0, you can override "result".)
6104     *
6105     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6106     * vCC (r1).  Useful for integer division and modulus.
6107     *
6108     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6109     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6110     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6111     *      rem-double/2addr
6112     */
6113    /* binop/2addr vA, vB */
6114    mov     r9, rINST, lsr #8           @ r9<- A+
6115    mov     r1, rINST, lsr #12          @ r1<- B
6116    and     r9, r9, #15
6117    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6118    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6119    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6120    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6121    .if 0
6122    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6123    beq     common_errDivideByZero
6124    .endif
6125    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6126
6127    eor     r0, r0, r2                           @ optional op; may set condition codes
6128    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
6129    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6130    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6131    GOTO_OPCODE(ip)                     @ jump to next instruction
6132    /* 12-15 instructions */
6133
6134
6135
6136/* ------------------------------ */
6137    .balign 64
6138.L_OP_SHL_LONG_2ADDR: /* 0xc3 */
6139/* File: armv5te/OP_SHL_LONG_2ADDR.S */
6140    /*
6141     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6142     * 32-bit shift distance.
6143     */
6144    /* shl-long/2addr vA, vB */
6145    mov     r9, rINST, lsr #8           @ r9<- A+
6146    mov     r3, rINST, lsr #12          @ r3<- B
6147    and     r9, r9, #15
6148    GET_VREG(r2, r3)                    @ r2<- vB
6149    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6150    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6151    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6152
6153    mov     r1, r1, asl r2              @  r1<- r1 << r2
6154    rsb     r3, r2, #32                 @  r3<- 32 - r2
6155    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
6156    subs    ip, r2, #32                 @  ip<- r2 - 32
6157    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6158    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
6159    mov     r0, r0, asl r2              @  r0<- r0 << r2
6160    b       .LOP_SHL_LONG_2ADDR_finish
6161
6162/* ------------------------------ */
6163    .balign 64
6164.L_OP_SHR_LONG_2ADDR: /* 0xc4 */
6165/* File: armv5te/OP_SHR_LONG_2ADDR.S */
6166    /*
6167     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6168     * 32-bit shift distance.
6169     */
6170    /* shr-long/2addr vA, vB */
6171    mov     r9, rINST, lsr #8           @ r9<- A+
6172    mov     r3, rINST, lsr #12          @ r3<- B
6173    and     r9, r9, #15
6174    GET_VREG(r2, r3)                    @ r2<- vB
6175    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6176    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6177    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6178
6179    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6180    rsb     r3, r2, #32                 @  r3<- 32 - r2
6181    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6182    subs    ip, r2, #32                 @  ip<- r2 - 32
6183    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6184    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
6185    mov     r1, r1, asr r2              @  r1<- r1 >> r2
6186    b       .LOP_SHR_LONG_2ADDR_finish
6187
6188/* ------------------------------ */
6189    .balign 64
6190.L_OP_USHR_LONG_2ADDR: /* 0xc5 */
6191/* File: armv5te/OP_USHR_LONG_2ADDR.S */
6192    /*
6193     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6194     * 32-bit shift distance.
6195     */
6196    /* ushr-long/2addr vA, vB */
6197    mov     r9, rINST, lsr #8           @ r9<- A+
6198    mov     r3, rINST, lsr #12          @ r3<- B
6199    and     r9, r9, #15
6200    GET_VREG(r2, r3)                    @ r2<- vB
6201    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6202    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6203    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6204
6205    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6206    rsb     r3, r2, #32                 @  r3<- 32 - r2
6207    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6208    subs    ip, r2, #32                 @  ip<- r2 - 32
6209    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6210    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
6211    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
6212    b       .LOP_USHR_LONG_2ADDR_finish
6213
6214/* ------------------------------ */
6215    .balign 64
6216.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
6217/* File: armv5te/OP_ADD_FLOAT_2ADDR.S */
6218/* File: armv5te/binop2addr.S */
6219    /*
6220     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6221     * that specifies an instruction that performs "result = r0 op r1".
6222     * This could be an ARM instruction or a function call.  (If the result
6223     * comes back in a register other than r0, you can override "result".)
6224     *
6225     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6226     * vCC (r1).  Useful for integer division and modulus.
6227     *
6228     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6229     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6230     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6231     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6232     */
6233    /* binop/2addr vA, vB */
6234    mov     r9, rINST, lsr #8           @ r9<- A+
6235    mov     r3, rINST, lsr #12          @ r3<- B
6236    and     r9, r9, #15
6237    GET_VREG(r0, r9)                    @ r0<- vA
6238    GET_VREG(r1, r3)                    @ r1<- vB
6239    .if 0
6240    cmp     r1, #0                      @ is second operand zero?
6241    beq     common_errDivideByZero
6242    .endif
6243    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6244
6245                               @ optional op; may set condition codes
6246    bl      __aeabi_fadd                              @ r0<- op, r0-r3 changed
6247    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6248    SET_VREG(r0, r9)               @ vAA<- r0
6249    GOTO_OPCODE(ip)                     @ jump to next instruction
6250    /* 10-13 instructions */
6251
6252
6253
6254/* ------------------------------ */
6255    .balign 64
6256.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
6257/* File: armv5te/OP_SUB_FLOAT_2ADDR.S */
6258/* File: armv5te/binop2addr.S */
6259    /*
6260     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6261     * that specifies an instruction that performs "result = r0 op r1".
6262     * This could be an ARM instruction or a function call.  (If the result
6263     * comes back in a register other than r0, you can override "result".)
6264     *
6265     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6266     * vCC (r1).  Useful for integer division and modulus.
6267     *
6268     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6269     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6270     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6271     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6272     */
6273    /* binop/2addr vA, vB */
6274    mov     r9, rINST, lsr #8           @ r9<- A+
6275    mov     r3, rINST, lsr #12          @ r3<- B
6276    and     r9, r9, #15
6277    GET_VREG(r0, r9)                    @ r0<- vA
6278    GET_VREG(r1, r3)                    @ r1<- vB
6279    .if 0
6280    cmp     r1, #0                      @ is second operand zero?
6281    beq     common_errDivideByZero
6282    .endif
6283    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6284
6285                               @ optional op; may set condition codes
6286    bl      __aeabi_fsub                              @ r0<- op, r0-r3 changed
6287    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6288    SET_VREG(r0, r9)               @ vAA<- r0
6289    GOTO_OPCODE(ip)                     @ jump to next instruction
6290    /* 10-13 instructions */
6291
6292
6293
6294/* ------------------------------ */
6295    .balign 64
6296.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
6297/* File: armv5te/OP_MUL_FLOAT_2ADDR.S */
6298/* File: armv5te/binop2addr.S */
6299    /*
6300     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6301     * that specifies an instruction that performs "result = r0 op r1".
6302     * This could be an ARM instruction or a function call.  (If the result
6303     * comes back in a register other than r0, you can override "result".)
6304     *
6305     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6306     * vCC (r1).  Useful for integer division and modulus.
6307     *
6308     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6309     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6310     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6311     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6312     */
6313    /* binop/2addr vA, vB */
6314    mov     r9, rINST, lsr #8           @ r9<- A+
6315    mov     r3, rINST, lsr #12          @ r3<- B
6316    and     r9, r9, #15
6317    GET_VREG(r0, r9)                    @ r0<- vA
6318    GET_VREG(r1, r3)                    @ r1<- vB
6319    .if 0
6320    cmp     r1, #0                      @ is second operand zero?
6321    beq     common_errDivideByZero
6322    .endif
6323    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6324
6325                               @ optional op; may set condition codes
6326    bl      __aeabi_fmul                              @ r0<- op, r0-r3 changed
6327    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6328    SET_VREG(r0, r9)               @ vAA<- r0
6329    GOTO_OPCODE(ip)                     @ jump to next instruction
6330    /* 10-13 instructions */
6331
6332
6333
6334/* ------------------------------ */
6335    .balign 64
6336.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
6337/* File: armv5te/OP_DIV_FLOAT_2ADDR.S */
6338/* File: armv5te/binop2addr.S */
6339    /*
6340     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6341     * that specifies an instruction that performs "result = r0 op r1".
6342     * This could be an ARM instruction or a function call.  (If the result
6343     * comes back in a register other than r0, you can override "result".)
6344     *
6345     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6346     * vCC (r1).  Useful for integer division and modulus.
6347     *
6348     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6349     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6350     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6351     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6352     */
6353    /* binop/2addr vA, vB */
6354    mov     r9, rINST, lsr #8           @ r9<- A+
6355    mov     r3, rINST, lsr #12          @ r3<- B
6356    and     r9, r9, #15
6357    GET_VREG(r0, r9)                    @ r0<- vA
6358    GET_VREG(r1, r3)                    @ r1<- vB
6359    .if 0
6360    cmp     r1, #0                      @ is second operand zero?
6361    beq     common_errDivideByZero
6362    .endif
6363    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6364
6365                               @ optional op; may set condition codes
6366    bl      __aeabi_fdiv                              @ r0<- op, r0-r3 changed
6367    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6368    SET_VREG(r0, r9)               @ vAA<- r0
6369    GOTO_OPCODE(ip)                     @ jump to next instruction
6370    /* 10-13 instructions */
6371
6372
6373
6374/* ------------------------------ */
6375    .balign 64
6376.L_OP_REM_FLOAT_2ADDR: /* 0xca */
6377/* File: armv5te/OP_REM_FLOAT_2ADDR.S */
6378/* EABI doesn't define a float remainder function, but libm does */
6379/* File: armv5te/binop2addr.S */
6380    /*
6381     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6382     * that specifies an instruction that performs "result = r0 op r1".
6383     * This could be an ARM instruction or a function call.  (If the result
6384     * comes back in a register other than r0, you can override "result".)
6385     *
6386     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6387     * vCC (r1).  Useful for integer division and modulus.
6388     *
6389     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6390     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6391     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6392     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6393     */
6394    /* binop/2addr vA, vB */
6395    mov     r9, rINST, lsr #8           @ r9<- A+
6396    mov     r3, rINST, lsr #12          @ r3<- B
6397    and     r9, r9, #15
6398    GET_VREG(r0, r9)                    @ r0<- vA
6399    GET_VREG(r1, r3)                    @ r1<- vB
6400    .if 0
6401    cmp     r1, #0                      @ is second operand zero?
6402    beq     common_errDivideByZero
6403    .endif
6404    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6405
6406                               @ optional op; may set condition codes
6407    bl      fmodf                              @ r0<- op, r0-r3 changed
6408    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6409    SET_VREG(r0, r9)               @ vAA<- r0
6410    GOTO_OPCODE(ip)                     @ jump to next instruction
6411    /* 10-13 instructions */
6412
6413
6414
6415/* ------------------------------ */
6416    .balign 64
6417.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
6418/* File: armv5te/OP_ADD_DOUBLE_2ADDR.S */
6419/* File: armv5te/binopWide2addr.S */
6420    /*
6421     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6422     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6423     * This could be an ARM instruction or a function call.  (If the result
6424     * comes back in a register other than r0, you can override "result".)
6425     *
6426     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6427     * vCC (r1).  Useful for integer division and modulus.
6428     *
6429     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6430     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6431     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6432     *      rem-double/2addr
6433     */
6434    /* binop/2addr vA, vB */
6435    mov     r9, rINST, lsr #8           @ r9<- A+
6436    mov     r1, rINST, lsr #12          @ r1<- B
6437    and     r9, r9, #15
6438    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6439    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6440    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6441    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6442    .if 0
6443    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6444    beq     common_errDivideByZero
6445    .endif
6446    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6447
6448                               @ optional op; may set condition codes
6449    bl      __aeabi_dadd                              @ result<- op, r0-r3 changed
6450    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6451    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6452    GOTO_OPCODE(ip)                     @ jump to next instruction
6453    /* 12-15 instructions */
6454
6455
6456
6457/* ------------------------------ */
6458    .balign 64
6459.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
6460/* File: armv5te/OP_SUB_DOUBLE_2ADDR.S */
6461/* File: armv5te/binopWide2addr.S */
6462    /*
6463     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6464     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6465     * This could be an ARM instruction or a function call.  (If the result
6466     * comes back in a register other than r0, you can override "result".)
6467     *
6468     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6469     * vCC (r1).  Useful for integer division and modulus.
6470     *
6471     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6472     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6473     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6474     *      rem-double/2addr
6475     */
6476    /* binop/2addr vA, vB */
6477    mov     r9, rINST, lsr #8           @ r9<- A+
6478    mov     r1, rINST, lsr #12          @ r1<- B
6479    and     r9, r9, #15
6480    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6481    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6482    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6483    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6484    .if 0
6485    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6486    beq     common_errDivideByZero
6487    .endif
6488    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6489
6490                               @ optional op; may set condition codes
6491    bl      __aeabi_dsub                              @ result<- op, r0-r3 changed
6492    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6493    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6494    GOTO_OPCODE(ip)                     @ jump to next instruction
6495    /* 12-15 instructions */
6496
6497
6498
6499/* ------------------------------ */
6500    .balign 64
6501.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
6502/* File: armv5te/OP_MUL_DOUBLE_2ADDR.S */
6503/* File: armv5te/binopWide2addr.S */
6504    /*
6505     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6506     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6507     * This could be an ARM instruction or a function call.  (If the result
6508     * comes back in a register other than r0, you can override "result".)
6509     *
6510     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6511     * vCC (r1).  Useful for integer division and modulus.
6512     *
6513     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6514     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6515     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6516     *      rem-double/2addr
6517     */
6518    /* binop/2addr vA, vB */
6519    mov     r9, rINST, lsr #8           @ r9<- A+
6520    mov     r1, rINST, lsr #12          @ r1<- B
6521    and     r9, r9, #15
6522    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6523    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6524    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6525    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6526    .if 0
6527    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6528    beq     common_errDivideByZero
6529    .endif
6530    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6531
6532                               @ optional op; may set condition codes
6533    bl      __aeabi_dmul                              @ result<- op, r0-r3 changed
6534    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6535    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6536    GOTO_OPCODE(ip)                     @ jump to next instruction
6537    /* 12-15 instructions */
6538
6539
6540
6541/* ------------------------------ */
6542    .balign 64
6543.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
6544/* File: armv5te/OP_DIV_DOUBLE_2ADDR.S */
6545/* File: armv5te/binopWide2addr.S */
6546    /*
6547     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6548     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6549     * This could be an ARM instruction or a function call.  (If the result
6550     * comes back in a register other than r0, you can override "result".)
6551     *
6552     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6553     * vCC (r1).  Useful for integer division and modulus.
6554     *
6555     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6556     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6557     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6558     *      rem-double/2addr
6559     */
6560    /* binop/2addr vA, vB */
6561    mov     r9, rINST, lsr #8           @ r9<- A+
6562    mov     r1, rINST, lsr #12          @ r1<- B
6563    and     r9, r9, #15
6564    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6565    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6566    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6567    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6568    .if 0
6569    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6570    beq     common_errDivideByZero
6571    .endif
6572    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6573
6574                               @ optional op; may set condition codes
6575    bl      __aeabi_ddiv                              @ result<- op, r0-r3 changed
6576    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6577    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6578    GOTO_OPCODE(ip)                     @ jump to next instruction
6579    /* 12-15 instructions */
6580
6581
6582
6583/* ------------------------------ */
6584    .balign 64
6585.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
6586/* File: armv5te/OP_REM_DOUBLE_2ADDR.S */
6587/* EABI doesn't define a double remainder function, but libm does */
6588/* File: armv5te/binopWide2addr.S */
6589    /*
6590     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6591     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6592     * This could be an ARM instruction or a function call.  (If the result
6593     * comes back in a register other than r0, you can override "result".)
6594     *
6595     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6596     * vCC (r1).  Useful for integer division and modulus.
6597     *
6598     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6599     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6600     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6601     *      rem-double/2addr
6602     */
6603    /* binop/2addr vA, vB */
6604    mov     r9, rINST, lsr #8           @ r9<- A+
6605    mov     r1, rINST, lsr #12          @ r1<- B
6606    and     r9, r9, #15
6607    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6608    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6609    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6610    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6611    .if 0
6612    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6613    beq     common_errDivideByZero
6614    .endif
6615    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6616
6617                               @ optional op; may set condition codes
6618    bl      fmod                              @ result<- op, r0-r3 changed
6619    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6620    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6621    GOTO_OPCODE(ip)                     @ jump to next instruction
6622    /* 12-15 instructions */
6623
6624
6625
6626/* ------------------------------ */
6627    .balign 64
6628.L_OP_ADD_INT_LIT16: /* 0xd0 */
6629/* File: armv5te/OP_ADD_INT_LIT16.S */
6630/* File: armv5te/binopLit16.S */
6631    /*
6632     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6633     * that specifies an instruction that performs "result = r0 op r1".
6634     * This could be an ARM instruction or a function call.  (If the result
6635     * comes back in a register other than r0, you can override "result".)
6636     *
6637     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6638     * vCC (r1).  Useful for integer division and modulus.
6639     *
6640     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6641     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6642     */
6643    /* binop/lit16 vA, vB, #+CCCC */
6644    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6645    mov     r2, rINST, lsr #12          @ r2<- B
6646    mov     r9, rINST, lsr #8           @ r9<- A+
6647    GET_VREG(r0, r2)                    @ r0<- vB
6648    and     r9, r9, #15
6649    .if 0
6650    cmp     r1, #0                      @ is second operand zero?
6651    beq     common_errDivideByZero
6652    .endif
6653    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6654
6655    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6656    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6657    SET_VREG(r0, r9)               @ vAA<- r0
6658    GOTO_OPCODE(ip)                     @ jump to next instruction
6659    /* 10-13 instructions */
6660
6661
6662
6663/* ------------------------------ */
6664    .balign 64
6665.L_OP_RSUB_INT: /* 0xd1 */
6666/* File: armv5te/OP_RSUB_INT.S */
6667/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
6668/* File: armv5te/binopLit16.S */
6669    /*
6670     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6671     * that specifies an instruction that performs "result = r0 op r1".
6672     * This could be an ARM instruction or a function call.  (If the result
6673     * comes back in a register other than r0, you can override "result".)
6674     *
6675     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6676     * vCC (r1).  Useful for integer division and modulus.
6677     *
6678     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6679     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6680     */
6681    /* binop/lit16 vA, vB, #+CCCC */
6682    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6683    mov     r2, rINST, lsr #12          @ r2<- B
6684    mov     r9, rINST, lsr #8           @ r9<- A+
6685    GET_VREG(r0, r2)                    @ r0<- vB
6686    and     r9, r9, #15
6687    .if 0
6688    cmp     r1, #0                      @ is second operand zero?
6689    beq     common_errDivideByZero
6690    .endif
6691    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6692
6693    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6694    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6695    SET_VREG(r0, r9)               @ vAA<- r0
6696    GOTO_OPCODE(ip)                     @ jump to next instruction
6697    /* 10-13 instructions */
6698
6699
6700
6701/* ------------------------------ */
6702    .balign 64
6703.L_OP_MUL_INT_LIT16: /* 0xd2 */
6704/* File: armv5te/OP_MUL_INT_LIT16.S */
6705/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6706/* File: armv5te/binopLit16.S */
6707    /*
6708     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6709     * that specifies an instruction that performs "result = r0 op r1".
6710     * This could be an ARM instruction or a function call.  (If the result
6711     * comes back in a register other than r0, you can override "result".)
6712     *
6713     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6714     * vCC (r1).  Useful for integer division and modulus.
6715     *
6716     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6717     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6718     */
6719    /* binop/lit16 vA, vB, #+CCCC */
6720    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6721    mov     r2, rINST, lsr #12          @ r2<- B
6722    mov     r9, rINST, lsr #8           @ r9<- A+
6723    GET_VREG(r0, r2)                    @ r0<- vB
6724    and     r9, r9, #15
6725    .if 0
6726    cmp     r1, #0                      @ is second operand zero?
6727    beq     common_errDivideByZero
6728    .endif
6729    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6730
6731    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6732    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6733    SET_VREG(r0, r9)               @ vAA<- r0
6734    GOTO_OPCODE(ip)                     @ jump to next instruction
6735    /* 10-13 instructions */
6736
6737
6738
6739/* ------------------------------ */
6740    .balign 64
6741.L_OP_DIV_INT_LIT16: /* 0xd3 */
6742/* File: armv5te/OP_DIV_INT_LIT16.S */
6743/* File: armv5te/binopLit16.S */
6744    /*
6745     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6746     * that specifies an instruction that performs "result = r0 op r1".
6747     * This could be an ARM instruction or a function call.  (If the result
6748     * comes back in a register other than r0, you can override "result".)
6749     *
6750     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6751     * vCC (r1).  Useful for integer division and modulus.
6752     *
6753     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6754     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6755     */
6756    /* binop/lit16 vA, vB, #+CCCC */
6757    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6758    mov     r2, rINST, lsr #12          @ r2<- B
6759    mov     r9, rINST, lsr #8           @ r9<- A+
6760    GET_VREG(r0, r2)                    @ r0<- vB
6761    and     r9, r9, #15
6762    .if 1
6763    cmp     r1, #0                      @ is second operand zero?
6764    beq     common_errDivideByZero
6765    .endif
6766    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6767
6768    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6769    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6770    SET_VREG(r0, r9)               @ vAA<- r0
6771    GOTO_OPCODE(ip)                     @ jump to next instruction
6772    /* 10-13 instructions */
6773
6774
6775
6776/* ------------------------------ */
6777    .balign 64
6778.L_OP_REM_INT_LIT16: /* 0xd4 */
6779/* File: armv5te/OP_REM_INT_LIT16.S */
6780/* idivmod returns quotient in r0 and remainder in r1 */
6781/* File: armv5te/binopLit16.S */
6782    /*
6783     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6784     * that specifies an instruction that performs "result = r0 op r1".
6785     * This could be an ARM instruction or a function call.  (If the result
6786     * comes back in a register other than r0, you can override "result".)
6787     *
6788     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6789     * vCC (r1).  Useful for integer division and modulus.
6790     *
6791     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6792     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6793     */
6794    /* binop/lit16 vA, vB, #+CCCC */
6795    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6796    mov     r2, rINST, lsr #12          @ r2<- B
6797    mov     r9, rINST, lsr #8           @ r9<- A+
6798    GET_VREG(r0, r2)                    @ r0<- vB
6799    and     r9, r9, #15
6800    .if 1
6801    cmp     r1, #0                      @ is second operand zero?
6802    beq     common_errDivideByZero
6803    .endif
6804    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6805
6806    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6807    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6808    SET_VREG(r1, r9)               @ vAA<- r1
6809    GOTO_OPCODE(ip)                     @ jump to next instruction
6810    /* 10-13 instructions */
6811
6812
6813
6814/* ------------------------------ */
6815    .balign 64
6816.L_OP_AND_INT_LIT16: /* 0xd5 */
6817/* File: armv5te/OP_AND_INT_LIT16.S */
6818/* File: armv5te/binopLit16.S */
6819    /*
6820     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6821     * that specifies an instruction that performs "result = r0 op r1".
6822     * This could be an ARM instruction or a function call.  (If the result
6823     * comes back in a register other than r0, you can override "result".)
6824     *
6825     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6826     * vCC (r1).  Useful for integer division and modulus.
6827     *
6828     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6829     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6830     */
6831    /* binop/lit16 vA, vB, #+CCCC */
6832    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6833    mov     r2, rINST, lsr #12          @ r2<- B
6834    mov     r9, rINST, lsr #8           @ r9<- A+
6835    GET_VREG(r0, r2)                    @ r0<- vB
6836    and     r9, r9, #15
6837    .if 0
6838    cmp     r1, #0                      @ is second operand zero?
6839    beq     common_errDivideByZero
6840    .endif
6841    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6842
6843    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6844    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6845    SET_VREG(r0, r9)               @ vAA<- r0
6846    GOTO_OPCODE(ip)                     @ jump to next instruction
6847    /* 10-13 instructions */
6848
6849
6850
6851/* ------------------------------ */
6852    .balign 64
6853.L_OP_OR_INT_LIT16: /* 0xd6 */
6854/* File: armv5te/OP_OR_INT_LIT16.S */
6855/* File: armv5te/binopLit16.S */
6856    /*
6857     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6858     * that specifies an instruction that performs "result = r0 op r1".
6859     * This could be an ARM instruction or a function call.  (If the result
6860     * comes back in a register other than r0, you can override "result".)
6861     *
6862     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6863     * vCC (r1).  Useful for integer division and modulus.
6864     *
6865     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6866     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6867     */
6868    /* binop/lit16 vA, vB, #+CCCC */
6869    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6870    mov     r2, rINST, lsr #12          @ r2<- B
6871    mov     r9, rINST, lsr #8           @ r9<- A+
6872    GET_VREG(r0, r2)                    @ r0<- vB
6873    and     r9, r9, #15
6874    .if 0
6875    cmp     r1, #0                      @ is second operand zero?
6876    beq     common_errDivideByZero
6877    .endif
6878    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6879
6880    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6881    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6882    SET_VREG(r0, r9)               @ vAA<- r0
6883    GOTO_OPCODE(ip)                     @ jump to next instruction
6884    /* 10-13 instructions */
6885
6886
6887
6888/* ------------------------------ */
6889    .balign 64
6890.L_OP_XOR_INT_LIT16: /* 0xd7 */
6891/* File: armv5te/OP_XOR_INT_LIT16.S */
6892/* File: armv5te/binopLit16.S */
6893    /*
6894     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6895     * that specifies an instruction that performs "result = r0 op r1".
6896     * This could be an ARM instruction or a function call.  (If the result
6897     * comes back in a register other than r0, you can override "result".)
6898     *
6899     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6900     * vCC (r1).  Useful for integer division and modulus.
6901     *
6902     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6903     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6904     */
6905    /* binop/lit16 vA, vB, #+CCCC */
6906    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6907    mov     r2, rINST, lsr #12          @ r2<- B
6908    mov     r9, rINST, lsr #8           @ r9<- A+
6909    GET_VREG(r0, r2)                    @ r0<- vB
6910    and     r9, r9, #15
6911    .if 0
6912    cmp     r1, #0                      @ is second operand zero?
6913    beq     common_errDivideByZero
6914    .endif
6915    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6916
6917    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
6918    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6919    SET_VREG(r0, r9)               @ vAA<- r0
6920    GOTO_OPCODE(ip)                     @ jump to next instruction
6921    /* 10-13 instructions */
6922
6923
6924
6925/* ------------------------------ */
6926    .balign 64
6927.L_OP_ADD_INT_LIT8: /* 0xd8 */
6928/* File: armv5te/OP_ADD_INT_LIT8.S */
6929/* File: armv5te/binopLit8.S */
6930    /*
6931     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6932     * that specifies an instruction that performs "result = r0 op r1".
6933     * This could be an ARM instruction or a function call.  (If the result
6934     * comes back in a register other than r0, you can override "result".)
6935     *
6936     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6937     * vCC (r1).  Useful for integer division and modulus.
6938     *
6939     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6940     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6941     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6942     */
6943    /* binop/lit8 vAA, vBB, #+CC */
6944    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6945    mov     r9, rINST, lsr #8           @ r9<- AA
6946    and     r2, r3, #255                @ r2<- BB
6947    GET_VREG(r0, r2)                    @ r0<- vBB
6948    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6949    .if 0
6950    @cmp     r1, #0                      @ is second operand zero?
6951    beq     common_errDivideByZero
6952    .endif
6953    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6954
6955                               @ optional op; may set condition codes
6956    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6957    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6958    SET_VREG(r0, r9)               @ vAA<- r0
6959    GOTO_OPCODE(ip)                     @ jump to next instruction
6960    /* 10-12 instructions */
6961
6962
6963
6964/* ------------------------------ */
6965    .balign 64
6966.L_OP_RSUB_INT_LIT8: /* 0xd9 */
6967/* File: armv5te/OP_RSUB_INT_LIT8.S */
6968/* File: armv5te/binopLit8.S */
6969    /*
6970     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6971     * that specifies an instruction that performs "result = r0 op r1".
6972     * This could be an ARM instruction or a function call.  (If the result
6973     * comes back in a register other than r0, you can override "result".)
6974     *
6975     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6976     * vCC (r1).  Useful for integer division and modulus.
6977     *
6978     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6979     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6980     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6981     */
6982    /* binop/lit8 vAA, vBB, #+CC */
6983    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6984    mov     r9, rINST, lsr #8           @ r9<- AA
6985    and     r2, r3, #255                @ r2<- BB
6986    GET_VREG(r0, r2)                    @ r0<- vBB
6987    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6988    .if 0
6989    @cmp     r1, #0                      @ is second operand zero?
6990    beq     common_errDivideByZero
6991    .endif
6992    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6993
6994                               @ optional op; may set condition codes
6995    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6996    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6997    SET_VREG(r0, r9)               @ vAA<- r0
6998    GOTO_OPCODE(ip)                     @ jump to next instruction
6999    /* 10-12 instructions */
7000
7001
7002
7003/* ------------------------------ */
7004    .balign 64
7005.L_OP_MUL_INT_LIT8: /* 0xda */
7006/* File: armv5te/OP_MUL_INT_LIT8.S */
7007/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
7008/* File: armv5te/binopLit8.S */
7009    /*
7010     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7011     * that specifies an instruction that performs "result = r0 op r1".
7012     * This could be an ARM instruction or a function call.  (If the result
7013     * comes back in a register other than r0, you can override "result".)
7014     *
7015     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7016     * vCC (r1).  Useful for integer division and modulus.
7017     *
7018     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7019     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7020     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7021     */
7022    /* binop/lit8 vAA, vBB, #+CC */
7023    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7024    mov     r9, rINST, lsr #8           @ r9<- AA
7025    and     r2, r3, #255                @ r2<- BB
7026    GET_VREG(r0, r2)                    @ r0<- vBB
7027    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7028    .if 0
7029    @cmp     r1, #0                      @ is second operand zero?
7030    beq     common_errDivideByZero
7031    .endif
7032    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7033
7034                               @ optional op; may set condition codes
7035    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
7036    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7037    SET_VREG(r0, r9)               @ vAA<- r0
7038    GOTO_OPCODE(ip)                     @ jump to next instruction
7039    /* 10-12 instructions */
7040
7041
7042
7043/* ------------------------------ */
7044    .balign 64
7045.L_OP_DIV_INT_LIT8: /* 0xdb */
7046/* File: armv5te/OP_DIV_INT_LIT8.S */
7047/* File: armv5te/binopLit8.S */
7048    /*
7049     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7050     * that specifies an instruction that performs "result = r0 op r1".
7051     * This could be an ARM instruction or a function call.  (If the result
7052     * comes back in a register other than r0, you can override "result".)
7053     *
7054     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7055     * vCC (r1).  Useful for integer division and modulus.
7056     *
7057     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7058     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7059     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7060     */
7061    /* binop/lit8 vAA, vBB, #+CC */
7062    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7063    mov     r9, rINST, lsr #8           @ r9<- AA
7064    and     r2, r3, #255                @ r2<- BB
7065    GET_VREG(r0, r2)                    @ r0<- vBB
7066    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7067    .if 1
7068    @cmp     r1, #0                      @ is second operand zero?
7069    beq     common_errDivideByZero
7070    .endif
7071    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7072
7073                               @ optional op; may set condition codes
7074    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
7075    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7076    SET_VREG(r0, r9)               @ vAA<- r0
7077    GOTO_OPCODE(ip)                     @ jump to next instruction
7078    /* 10-12 instructions */
7079
7080
7081
7082/* ------------------------------ */
7083    .balign 64
7084.L_OP_REM_INT_LIT8: /* 0xdc */
7085/* File: armv5te/OP_REM_INT_LIT8.S */
7086/* idivmod returns quotient in r0 and remainder in r1 */
7087/* File: armv5te/binopLit8.S */
7088    /*
7089     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7090     * that specifies an instruction that performs "result = r0 op r1".
7091     * This could be an ARM instruction or a function call.  (If the result
7092     * comes back in a register other than r0, you can override "result".)
7093     *
7094     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7095     * vCC (r1).  Useful for integer division and modulus.
7096     *
7097     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7098     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7099     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7100     */
7101    /* binop/lit8 vAA, vBB, #+CC */
7102    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7103    mov     r9, rINST, lsr #8           @ r9<- AA
7104    and     r2, r3, #255                @ r2<- BB
7105    GET_VREG(r0, r2)                    @ r0<- vBB
7106    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7107    .if 1
7108    @cmp     r1, #0                      @ is second operand zero?
7109    beq     common_errDivideByZero
7110    .endif
7111    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7112
7113                               @ optional op; may set condition codes
7114    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
7115    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7116    SET_VREG(r1, r9)               @ vAA<- r1
7117    GOTO_OPCODE(ip)                     @ jump to next instruction
7118    /* 10-12 instructions */
7119
7120
7121
7122/* ------------------------------ */
7123    .balign 64
7124.L_OP_AND_INT_LIT8: /* 0xdd */
7125/* File: armv5te/OP_AND_INT_LIT8.S */
7126/* File: armv5te/binopLit8.S */
7127    /*
7128     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7129     * that specifies an instruction that performs "result = r0 op r1".
7130     * This could be an ARM instruction or a function call.  (If the result
7131     * comes back in a register other than r0, you can override "result".)
7132     *
7133     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7134     * vCC (r1).  Useful for integer division and modulus.
7135     *
7136     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7137     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7138     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7139     */
7140    /* binop/lit8 vAA, vBB, #+CC */
7141    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7142    mov     r9, rINST, lsr #8           @ r9<- AA
7143    and     r2, r3, #255                @ r2<- BB
7144    GET_VREG(r0, r2)                    @ r0<- vBB
7145    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7146    .if 0
7147    @cmp     r1, #0                      @ is second operand zero?
7148    beq     common_errDivideByZero
7149    .endif
7150    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7151
7152                               @ optional op; may set condition codes
7153    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
7154    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7155    SET_VREG(r0, r9)               @ vAA<- r0
7156    GOTO_OPCODE(ip)                     @ jump to next instruction
7157    /* 10-12 instructions */
7158
7159
7160
7161/* ------------------------------ */
7162    .balign 64
7163.L_OP_OR_INT_LIT8: /* 0xde */
7164/* File: armv5te/OP_OR_INT_LIT8.S */
7165/* File: armv5te/binopLit8.S */
7166    /*
7167     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7168     * that specifies an instruction that performs "result = r0 op r1".
7169     * This could be an ARM instruction or a function call.  (If the result
7170     * comes back in a register other than r0, you can override "result".)
7171     *
7172     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7173     * vCC (r1).  Useful for integer division and modulus.
7174     *
7175     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7176     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7177     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7178     */
7179    /* binop/lit8 vAA, vBB, #+CC */
7180    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7181    mov     r9, rINST, lsr #8           @ r9<- AA
7182    and     r2, r3, #255                @ r2<- BB
7183    GET_VREG(r0, r2)                    @ r0<- vBB
7184    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7185    .if 0
7186    @cmp     r1, #0                      @ is second operand zero?
7187    beq     common_errDivideByZero
7188    .endif
7189    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7190
7191                               @ optional op; may set condition codes
7192    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
7193    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7194    SET_VREG(r0, r9)               @ vAA<- r0
7195    GOTO_OPCODE(ip)                     @ jump to next instruction
7196    /* 10-12 instructions */
7197
7198
7199
7200/* ------------------------------ */
7201    .balign 64
7202.L_OP_XOR_INT_LIT8: /* 0xdf */
7203/* File: armv5te/OP_XOR_INT_LIT8.S */
7204/* File: armv5te/binopLit8.S */
7205    /*
7206     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7207     * that specifies an instruction that performs "result = r0 op r1".
7208     * This could be an ARM instruction or a function call.  (If the result
7209     * comes back in a register other than r0, you can override "result".)
7210     *
7211     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7212     * vCC (r1).  Useful for integer division and modulus.
7213     *
7214     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7215     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7216     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7217     */
7218    /* binop/lit8 vAA, vBB, #+CC */
7219    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7220    mov     r9, rINST, lsr #8           @ r9<- AA
7221    and     r2, r3, #255                @ r2<- BB
7222    GET_VREG(r0, r2)                    @ r0<- vBB
7223    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7224    .if 0
7225    @cmp     r1, #0                      @ is second operand zero?
7226    beq     common_errDivideByZero
7227    .endif
7228    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7229
7230                               @ optional op; may set condition codes
7231    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
7232    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7233    SET_VREG(r0, r9)               @ vAA<- r0
7234    GOTO_OPCODE(ip)                     @ jump to next instruction
7235    /* 10-12 instructions */
7236
7237
7238
7239/* ------------------------------ */
7240    .balign 64
7241.L_OP_SHL_INT_LIT8: /* 0xe0 */
7242/* File: armv5te/OP_SHL_INT_LIT8.S */
7243/* File: armv5te/binopLit8.S */
7244    /*
7245     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7246     * that specifies an instruction that performs "result = r0 op r1".
7247     * This could be an ARM instruction or a function call.  (If the result
7248     * comes back in a register other than r0, you can override "result".)
7249     *
7250     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7251     * vCC (r1).  Useful for integer division and modulus.
7252     *
7253     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7254     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7255     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7256     */
7257    /* binop/lit8 vAA, vBB, #+CC */
7258    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7259    mov     r9, rINST, lsr #8           @ r9<- AA
7260    and     r2, r3, #255                @ r2<- BB
7261    GET_VREG(r0, r2)                    @ r0<- vBB
7262    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7263    .if 0
7264    @cmp     r1, #0                      @ is second operand zero?
7265    beq     common_errDivideByZero
7266    .endif
7267    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7268
7269    and     r1, r1, #31                           @ optional op; may set condition codes
7270    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
7271    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7272    SET_VREG(r0, r9)               @ vAA<- r0
7273    GOTO_OPCODE(ip)                     @ jump to next instruction
7274    /* 10-12 instructions */
7275
7276
7277
7278/* ------------------------------ */
7279    .balign 64
7280.L_OP_SHR_INT_LIT8: /* 0xe1 */
7281/* File: armv5te/OP_SHR_INT_LIT8.S */
7282/* File: armv5te/binopLit8.S */
7283    /*
7284     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7285     * that specifies an instruction that performs "result = r0 op r1".
7286     * This could be an ARM instruction or a function call.  (If the result
7287     * comes back in a register other than r0, you can override "result".)
7288     *
7289     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7290     * vCC (r1).  Useful for integer division and modulus.
7291     *
7292     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7293     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7294     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7295     */
7296    /* binop/lit8 vAA, vBB, #+CC */
7297    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7298    mov     r9, rINST, lsr #8           @ r9<- AA
7299    and     r2, r3, #255                @ r2<- BB
7300    GET_VREG(r0, r2)                    @ r0<- vBB
7301    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7302    .if 0
7303    @cmp     r1, #0                      @ is second operand zero?
7304    beq     common_errDivideByZero
7305    .endif
7306    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7307
7308    and     r1, r1, #31                           @ optional op; may set condition codes
7309    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
7310    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7311    SET_VREG(r0, r9)               @ vAA<- r0
7312    GOTO_OPCODE(ip)                     @ jump to next instruction
7313    /* 10-12 instructions */
7314
7315
7316
7317/* ------------------------------ */
7318    .balign 64
7319.L_OP_USHR_INT_LIT8: /* 0xe2 */
7320/* File: armv5te/OP_USHR_INT_LIT8.S */
7321/* File: armv5te/binopLit8.S */
7322    /*
7323     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7324     * that specifies an instruction that performs "result = r0 op r1".
7325     * This could be an ARM instruction or a function call.  (If the result
7326     * comes back in a register other than r0, you can override "result".)
7327     *
7328     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7329     * vCC (r1).  Useful for integer division and modulus.
7330     *
7331     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7332     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7333     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7334     */
7335    /* binop/lit8 vAA, vBB, #+CC */
7336    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7337    mov     r9, rINST, lsr #8           @ r9<- AA
7338    and     r2, r3, #255                @ r2<- BB
7339    GET_VREG(r0, r2)                    @ r0<- vBB
7340    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7341    .if 0
7342    @cmp     r1, #0                      @ is second operand zero?
7343    beq     common_errDivideByZero
7344    .endif
7345    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7346
7347    and     r1, r1, #31                           @ optional op; may set condition codes
7348    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
7349    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7350    SET_VREG(r0, r9)               @ vAA<- r0
7351    GOTO_OPCODE(ip)                     @ jump to next instruction
7352    /* 10-12 instructions */
7353
7354
7355
7356/* ------------------------------ */
7357    .balign 64
7358.L_OP_UNUSED_E3: /* 0xe3 */
7359/* File: armv5te/OP_UNUSED_E3.S */
7360/* File: armv5te/unused.S */
7361    bl      common_abort
7362
7363
7364
7365/* ------------------------------ */
7366    .balign 64
7367.L_OP_UNUSED_E4: /* 0xe4 */
7368/* File: armv5te/OP_UNUSED_E4.S */
7369/* File: armv5te/unused.S */
7370    bl      common_abort
7371
7372
7373
7374/* ------------------------------ */
7375    .balign 64
7376.L_OP_UNUSED_E5: /* 0xe5 */
7377/* File: armv5te/OP_UNUSED_E5.S */
7378/* File: armv5te/unused.S */
7379    bl      common_abort
7380
7381
7382
7383/* ------------------------------ */
7384    .balign 64
7385.L_OP_UNUSED_E6: /* 0xe6 */
7386/* File: armv5te/OP_UNUSED_E6.S */
7387/* File: armv5te/unused.S */
7388    bl      common_abort
7389
7390
7391
7392/* ------------------------------ */
7393    .balign 64
7394.L_OP_UNUSED_E7: /* 0xe7 */
7395/* File: armv5te/OP_UNUSED_E7.S */
7396/* File: armv5te/unused.S */
7397    bl      common_abort
7398
7399
7400
7401/* ------------------------------ */
7402    .balign 64
7403.L_OP_UNUSED_E8: /* 0xe8 */
7404/* File: armv5te/OP_UNUSED_E8.S */
7405/* File: armv5te/unused.S */
7406    bl      common_abort
7407
7408
7409
7410/* ------------------------------ */
7411    .balign 64
7412.L_OP_UNUSED_E9: /* 0xe9 */
7413/* File: armv5te/OP_UNUSED_E9.S */
7414/* File: armv5te/unused.S */
7415    bl      common_abort
7416
7417
7418
7419/* ------------------------------ */
7420    .balign 64
7421.L_OP_UNUSED_EA: /* 0xea */
7422/* File: armv5te/OP_UNUSED_EA.S */
7423/* File: armv5te/unused.S */
7424    bl      common_abort
7425
7426
7427
7428/* ------------------------------ */
7429    .balign 64
7430.L_OP_UNUSED_EB: /* 0xeb */
7431/* File: armv5te/OP_UNUSED_EB.S */
7432/* File: armv5te/unused.S */
7433    bl      common_abort
7434
7435
7436
7437/* ------------------------------ */
7438    .balign 64
7439.L_OP_UNUSED_EC: /* 0xec */
7440/* File: armv5te/OP_UNUSED_EC.S */
7441/* File: armv5te/unused.S */
7442    bl      common_abort
7443
7444
7445
7446/* ------------------------------ */
7447    .balign 64
7448.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
7449/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
7450    /*
7451     * Handle a throw-verification-error instruction.  This throws an
7452     * exception for an error discovered during verification.  The
7453     * exception is indicated by AA, with some detail provided by BBBB.
7454     */
7455    /* op AA, ref@BBBB */
7456    ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- glue->methodClassDex
7457    FETCH(r2, 1)                        @ r2<- BBBB
7458    mov     r1, rINST, lsr #8           @ r1<- AA
7459    bl      dvmThrowVerificationError   @ always throws
7460    b       common_exceptionThrown      @ handle exception
7461
7462
7463/* ------------------------------ */
7464    .balign 64
7465.L_OP_EXECUTE_INLINE: /* 0xee */
7466/* File: armv5te/OP_EXECUTE_INLINE.S */
7467    /*
7468     * Execute a "native inline" instruction.
7469     *
7470     * We need to call:
7471     *  dvmPerformInlineOp4Std(arg0, arg1, arg2, arg3, &retval, ref)
7472     *
7473     * The first four args are in r0-r3, but the last two must be pushed
7474     * onto the stack.
7475     */
7476    /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
7477    FETCH(r10, 1)                       @ r10<- BBBB
7478    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7479    EXPORT_PC()                         @ can throw
7480    sub     sp, sp, #8                  @ make room for arg(s)
7481    mov     r0, rINST, lsr #12          @ r0<- B
7482    str     r1, [sp]                    @ push &glue->retval
7483    bl      .LOP_EXECUTE_INLINE_continue        @ make call; will return after
7484    add     sp, sp, #8                  @ pop stack
7485    cmp     r0, #0                      @ test boolean result of inline
7486    beq     common_exceptionThrown      @ returned false, handle exception
7487    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7488    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7489    GOTO_OPCODE(ip)                     @ jump to next instruction
7490
7491/* ------------------------------ */
7492    .balign 64
7493.L_OP_UNUSED_EF: /* 0xef */
7494/* File: armv5te/OP_UNUSED_EF.S */
7495/* File: armv5te/unused.S */
7496    bl      common_abort
7497
7498
7499
7500/* ------------------------------ */
7501    .balign 64
7502.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
7503/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
7504    /*
7505     * invoke-direct-empty is a no-op in a "standard" interpreter.
7506     */
7507    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7508    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7509    GOTO_OPCODE(ip)                     @ execute it
7510
7511/* ------------------------------ */
7512    .balign 64
7513.L_OP_UNUSED_F1: /* 0xf1 */
7514/* File: armv5te/OP_UNUSED_F1.S */
7515/* File: armv5te/unused.S */
7516    bl      common_abort
7517
7518
7519
7520/* ------------------------------ */
7521    .balign 64
7522.L_OP_IGET_QUICK: /* 0xf2 */
7523/* File: armv5te/OP_IGET_QUICK.S */
7524    /* For: iget-quick, iget-object-quick */
7525    /* op vA, vB, offset@CCCC */
7526    mov     r2, rINST, lsr #12          @ r2<- B
7527    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7528    FETCH(r1, 1)                        @ r1<- field byte offset
7529    cmp     r3, #0                      @ check object for null
7530    mov     r2, rINST, lsr #8           @ r2<- A(+)
7531    beq     common_errNullObject        @ object was null
7532    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7533    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7534    and     r2, r2, #15
7535    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7536    SET_VREG(r0, r2)                    @ fp[A]<- r0
7537    GOTO_OPCODE(ip)                     @ jump to next instruction
7538
7539
7540/* ------------------------------ */
7541    .balign 64
7542.L_OP_IGET_WIDE_QUICK: /* 0xf3 */
7543/* File: armv4t/OP_IGET_WIDE_QUICK.S */
7544    /* iget-wide-quick vA, vB, offset@CCCC */
7545    mov     r2, rINST, lsr #12          @ r2<- B
7546    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7547    FETCH(r1, 1)                        @ r1<- field byte offset
7548    cmp     r3, #0                      @ check object for null
7549    mov     r2, rINST, lsr #8           @ r2<- A(+)
7550    beq     common_errNullObject        @ object was null
7551    add     r9, r3, r1                  @ r9<- object + offset
7552    ldmia   r9, {r0-r1}                 @ r0/r1<- obj.field (64 bits, aligned)
7553    and     r2, r2, #15                 @ r2<- A
7554    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7555    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
7556    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7557    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
7558    GOTO_OPCODE(ip)                     @ jump to next instruction
7559
7560
7561/* ------------------------------ */
7562    .balign 64
7563.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
7564/* File: armv5te/OP_IGET_OBJECT_QUICK.S */
7565/* File: armv5te/OP_IGET_QUICK.S */
7566    /* For: iget-quick, iget-object-quick */
7567    /* op vA, vB, offset@CCCC */
7568    mov     r2, rINST, lsr #12          @ r2<- B
7569    GET_VREG(r3, r2)                    @ r3<- object we're operating on
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    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7575    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7576    and     r2, r2, #15
7577    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7578    SET_VREG(r0, r2)                    @ fp[A]<- r0
7579    GOTO_OPCODE(ip)                     @ jump to next instruction
7580
7581
7582
7583/* ------------------------------ */
7584    .balign 64
7585.L_OP_IPUT_QUICK: /* 0xf5 */
7586/* File: armv5te/OP_IPUT_QUICK.S */
7587    /* For: iput-quick, iput-object-quick */
7588    /* op vA, vB, offset@CCCC */
7589    mov     r2, rINST, lsr #12          @ r2<- B
7590    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7591    FETCH(r1, 1)                        @ r1<- field byte offset
7592    cmp     r3, #0                      @ check object for null
7593    mov     r2, rINST, lsr #8           @ r2<- A(+)
7594    beq     common_errNullObject        @ object was null
7595    and     r2, r2, #15
7596    GET_VREG(r0, r2)                    @ r0<- fp[A]
7597    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7598    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7599    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7600    GOTO_OPCODE(ip)                     @ jump to next instruction
7601
7602
7603/* ------------------------------ */
7604    .balign 64
7605.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
7606/* File: armv4t/OP_IPUT_WIDE_QUICK.S */
7607    /* iput-wide-quick vA, vB, offset@CCCC */
7608    mov     r0, rINST, lsr #8           @ r0<- A(+)
7609    mov     r1, rINST, lsr #12          @ r1<- B
7610    and     r0, r0, #15
7611    GET_VREG(r2, r1)                    @ r2<- fp[B], the object pointer
7612    add     r3, rFP, r0, lsl #2         @ r3<- &fp[A]
7613    cmp     r2, #0                      @ check object for null
7614    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[A]
7615    beq     common_errNullObject        @ object was null
7616    FETCH(r3, 1)                        @ r3<- field byte offset
7617    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7618    add     r2, r2, r3                  @ r2<- object + byte offset
7619    stmia   r2, {r0-r1}                 @ obj.field (64 bits, aligned)<- r0/r1
7620    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7621    GOTO_OPCODE(ip)                     @ jump to next instruction
7622
7623
7624/* ------------------------------ */
7625    .balign 64
7626.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
7627/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
7628/* File: armv5te/OP_IPUT_QUICK.S */
7629    /* For: iput-quick, iput-object-quick */
7630    /* op vA, vB, offset@CCCC */
7631    mov     r2, rINST, lsr #12          @ r2<- B
7632    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7633    FETCH(r1, 1)                        @ r1<- field byte offset
7634    cmp     r3, #0                      @ check object for null
7635    mov     r2, rINST, lsr #8           @ r2<- A(+)
7636    beq     common_errNullObject        @ object was null
7637    and     r2, r2, #15
7638    GET_VREG(r0, r2)                    @ r0<- fp[A]
7639    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7640    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7641    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7642    GOTO_OPCODE(ip)                     @ jump to next instruction
7643
7644
7645
7646/* ------------------------------ */
7647    .balign 64
7648.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
7649/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7650    /*
7651     * Handle an optimized virtual method call.
7652     *
7653     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7654     */
7655    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7656    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7657    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7658    FETCH(r1, 1)                        @ r1<- BBBB
7659    .if     (!0)
7660    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7661    .endif
7662    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7663    cmp     r2, #0                      @ is "this" null?
7664    beq     common_errNullObject        @ null "this", throw exception
7665    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7666    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7667    EXPORT_PC()                         @ invoke must export
7668    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7669    bl      common_invokeMethodNoRange @ continue on
7670
7671/* ------------------------------ */
7672    .balign 64
7673.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
7674/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
7675/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7676    /*
7677     * Handle an optimized virtual method call.
7678     *
7679     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7680     */
7681    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7682    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7683    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7684    FETCH(r1, 1)                        @ r1<- BBBB
7685    .if     (!1)
7686    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7687    .endif
7688    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7689    cmp     r2, #0                      @ is "this" null?
7690    beq     common_errNullObject        @ null "this", throw exception
7691    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7692    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7693    EXPORT_PC()                         @ invoke must export
7694    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7695    bl      common_invokeMethodRange @ continue on
7696
7697
7698/* ------------------------------ */
7699    .balign 64
7700.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
7701/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7702    /*
7703     * Handle an optimized "super" method call.
7704     *
7705     * for: [opt] invoke-super-quick, invoke-super-quick/range
7706     */
7707    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7708    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7709    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7710    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7711    .if     (!0)
7712    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7713    .endif
7714    FETCH(r1, 1)                        @ r1<- BBBB
7715    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7716    EXPORT_PC()                         @ must export for invoke
7717    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7718    GET_VREG(r3, r10)                   @ r3<- "this"
7719    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7720    cmp     r3, #0                      @ null "this" ref?
7721    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7722    beq     common_errNullObject        @ "this" is null, throw exception
7723    bl      common_invokeMethodNoRange @ continue on
7724
7725
7726/* ------------------------------ */
7727    .balign 64
7728.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
7729/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
7730/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7731    /*
7732     * Handle an optimized "super" method call.
7733     *
7734     * for: [opt] invoke-super-quick, invoke-super-quick/range
7735     */
7736    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7737    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7738    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7739    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7740    .if     (!1)
7741    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7742    .endif
7743    FETCH(r1, 1)                        @ r1<- BBBB
7744    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7745    EXPORT_PC()                         @ must export for invoke
7746    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7747    GET_VREG(r3, r10)                   @ r3<- "this"
7748    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7749    cmp     r3, #0                      @ null "this" ref?
7750    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7751    beq     common_errNullObject        @ "this" is null, throw exception
7752    bl      common_invokeMethodRange @ continue on
7753
7754
7755
7756/* ------------------------------ */
7757    .balign 64
7758.L_OP_UNUSED_FC: /* 0xfc */
7759/* File: armv5te/OP_UNUSED_FC.S */
7760/* File: armv5te/unused.S */
7761    bl      common_abort
7762
7763
7764
7765/* ------------------------------ */
7766    .balign 64
7767.L_OP_UNUSED_FD: /* 0xfd */
7768/* File: armv5te/OP_UNUSED_FD.S */
7769/* File: armv5te/unused.S */
7770    bl      common_abort
7771
7772
7773
7774/* ------------------------------ */
7775    .balign 64
7776.L_OP_UNUSED_FE: /* 0xfe */
7777/* File: armv5te/OP_UNUSED_FE.S */
7778/* File: armv5te/unused.S */
7779    bl      common_abort
7780
7781
7782
7783/* ------------------------------ */
7784    .balign 64
7785.L_OP_UNUSED_FF: /* 0xff */
7786/* File: armv5te/OP_UNUSED_FF.S */
7787/* File: armv5te/unused.S */
7788    bl      common_abort
7789
7790
7791
7792
7793    .balign 64
7794    .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
7795    .global dvmAsmInstructionEnd
7796dvmAsmInstructionEnd:
7797
7798/*
7799 * ===========================================================================
7800 *  Sister implementations
7801 * ===========================================================================
7802 */
7803    .global dvmAsmSisterStart
7804    .type   dvmAsmSisterStart, %function
7805    .text
7806    .balign 4
7807dvmAsmSisterStart:
7808
7809/* continuation for OP_CONST_STRING */
7810
7811    /*
7812     * Continuation if the String has not yet been resolved.
7813     *  r1: BBBB (String ref)
7814     *  r9: target register
7815     */
7816.LOP_CONST_STRING_resolve:
7817    EXPORT_PC()
7818    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7819    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7820    bl      dvmResolveString            @ r0<- String reference
7821    cmp     r0, #0                      @ failed?
7822    beq     common_exceptionThrown      @ yup, handle the exception
7823    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7824    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7825    SET_VREG(r0, r9)                    @ vAA<- r0
7826    GOTO_OPCODE(ip)                     @ jump to next instruction
7827
7828
7829/* continuation for OP_CONST_STRING_JUMBO */
7830
7831    /*
7832     * Continuation if the String has not yet been resolved.
7833     *  r1: BBBBBBBB (String ref)
7834     *  r9: target register
7835     */
7836.LOP_CONST_STRING_JUMBO_resolve:
7837    EXPORT_PC()
7838    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7839    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7840    bl      dvmResolveString            @ r0<- String reference
7841    cmp     r0, #0                      @ failed?
7842    beq     common_exceptionThrown      @ yup, handle the exception
7843    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7844    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7845    SET_VREG(r0, r9)                    @ vAA<- r0
7846    GOTO_OPCODE(ip)                     @ jump to next instruction
7847
7848
7849/* continuation for OP_CONST_CLASS */
7850
7851    /*
7852     * Continuation if the Class has not yet been resolved.
7853     *  r1: BBBB (Class ref)
7854     *  r9: target register
7855     */
7856.LOP_CONST_CLASS_resolve:
7857    EXPORT_PC()
7858    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7859    mov     r2, #1                      @ r2<- true
7860    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7861    bl      dvmResolveClass             @ r0<- Class reference
7862    cmp     r0, #0                      @ failed?
7863    beq     common_exceptionThrown      @ yup, handle the exception
7864    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7865    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7866    SET_VREG(r0, r9)                    @ vAA<- r0
7867    GOTO_OPCODE(ip)                     @ jump to next instruction
7868
7869
7870/* continuation for OP_CHECK_CAST */
7871
7872    /*
7873     * Trivial test failed, need to perform full check.  This is common.
7874     *  r0 holds obj->clazz
7875     *  r1 holds class resolved from BBBB
7876     *  r9 holds object
7877     */
7878.LOP_CHECK_CAST_fullcheck:
7879    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7880    cmp     r0, #0                      @ failed?
7881    bne     .LOP_CHECK_CAST_okay            @ no, success
7882
7883    @ A cast has failed.  We need to throw a ClassCastException with the
7884    @ class of the object that failed to be cast.
7885    EXPORT_PC()                         @ about to throw
7886    ldr     r3, [r9, #offObject_clazz]  @ r3<- obj->clazz
7887    ldr     r0, .LstrClassCastExceptionPtr
7888    ldr     r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor
7889    bl      dvmThrowExceptionWithClassMessage
7890    b       common_exceptionThrown
7891
7892    /*
7893     * Resolution required.  This is the least-likely path.
7894     *
7895     *  r2 holds BBBB
7896     *  r9 holds object
7897     */
7898.LOP_CHECK_CAST_resolve:
7899    EXPORT_PC()                         @ resolve() could throw
7900    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7901    mov     r1, r2                      @ r1<- BBBB
7902    mov     r2, #0                      @ r2<- false
7903    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7904    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7905    cmp     r0, #0                      @ got null?
7906    beq     common_exceptionThrown      @ yes, handle exception
7907    mov     r1, r0                      @ r1<- class resolved from BBB
7908    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
7909    b       .LOP_CHECK_CAST_resolved        @ pick up where we left off
7910
7911.LstrClassCastExceptionPtr:
7912    .word   .LstrClassCastException
7913
7914
7915/* continuation for OP_INSTANCE_OF */
7916
7917    /*
7918     * Trivial test failed, need to perform full check.  This is common.
7919     *  r0 holds obj->clazz
7920     *  r1 holds class resolved from BBBB
7921     *  r9 holds A
7922     */
7923.LOP_INSTANCE_OF_fullcheck:
7924    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7925    @ fall through to OP_INSTANCE_OF_store
7926
7927    /*
7928     * r0 holds boolean result
7929     * r9 holds A
7930     */
7931.LOP_INSTANCE_OF_store:
7932    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7933    SET_VREG(r0, r9)                    @ vA<- r0
7934    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7935    GOTO_OPCODE(ip)                     @ jump to next instruction
7936
7937    /*
7938     * Trivial test succeeded, save and bail.
7939     *  r9 holds A
7940     */
7941.LOP_INSTANCE_OF_trivial:
7942    mov     r0, #1                      @ indicate success
7943    @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
7944    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7945    SET_VREG(r0, r9)                    @ vA<- r0
7946    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7947    GOTO_OPCODE(ip)                     @ jump to next instruction
7948
7949    /*
7950     * Resolution required.  This is the least-likely path.
7951     *
7952     *  r3 holds BBBB
7953     *  r9 holds A
7954     */
7955.LOP_INSTANCE_OF_resolve:
7956    EXPORT_PC()                         @ resolve() could throw
7957    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7958    mov     r1, r3                      @ r1<- BBBB
7959    mov     r2, #1                      @ r2<- true
7960    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7961    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7962    cmp     r0, #0                      @ got null?
7963    beq     common_exceptionThrown      @ yes, handle exception
7964    mov     r1, r0                      @ r1<- class resolved from BBB
7965    mov     r3, rINST, lsr #12          @ r3<- B
7966    GET_VREG(r0, r3)                    @ r0<- vB (object)
7967    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
7968    b       .LOP_INSTANCE_OF_resolved        @ pick up where we left off
7969
7970
7971/* continuation for OP_NEW_INSTANCE */
7972
7973    .balign 32                          @ minimize cache lines
7974.LOP_NEW_INSTANCE_finish: @ r0=class
7975    bl      dvmAllocObject              @ r0<- new object
7976    mov     r3, rINST, lsr #8           @ r3<- AA
7977    cmp     r0, #0                      @ failed?
7978    beq     common_exceptionThrown      @ yes, handle the exception
7979    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7980    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7981    SET_VREG(r0, r3)                    @ vAA<- r0
7982    GOTO_OPCODE(ip)                     @ jump to next instruction
7983
7984    /*
7985     * Class initialization required.
7986     *
7987     *  r0 holds class object
7988     */
7989.LOP_NEW_INSTANCE_needinit:
7990    mov     r9, r0                      @ save r0
7991    bl      dvmInitClass                @ initialize class
7992    cmp     r0, #0                      @ check boolean result
7993    mov     r0, r9                      @ restore r0
7994    bne     .LOP_NEW_INSTANCE_initialized     @ success, continue
7995    b       common_exceptionThrown      @ failed, deal with init exception
7996
7997    /*
7998     * Resolution required.  This is the least-likely path.
7999     *
8000     *  r1 holds BBBB
8001     */
8002.LOP_NEW_INSTANCE_resolve:
8003    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8004    mov     r2, #0                      @ r2<- false
8005    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8006    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
8007    cmp     r0, #0                      @ got null?
8008    bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
8009    b       common_exceptionThrown      @ yes, handle exception
8010
8011    /*
8012     * We can't instantiate an abstract class or interface, so throw an
8013     * InstantiationError with the class descriptor as the message.
8014     *
8015     *  r0 holds class object
8016     */
8017.LOP_NEW_INSTANCE_abstract:
8018    ldr     r1, [r0, #offClassObject_descriptor]
8019    ldr     r0, .LstrInstantiationErrorPtr
8020    bl      dvmThrowExceptionWithClassMessage
8021    b       common_exceptionThrown
8022
8023.LstrInstantiationErrorPtr:
8024    .word   .LstrInstantiationError
8025
8026
8027/* continuation for OP_NEW_ARRAY */
8028
8029
8030    /*
8031     * Resolve class.  (This is an uncommon case.)
8032     *
8033     *  r1 holds array length
8034     *  r2 holds class ref CCCC
8035     */
8036.LOP_NEW_ARRAY_resolve:
8037    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8038    mov     r9, r1                      @ r9<- length (save)
8039    mov     r1, r2                      @ r1<- CCCC
8040    mov     r2, #0                      @ r2<- false
8041    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8042    bl      dvmResolveClass             @ r0<- call(clazz, ref)
8043    cmp     r0, #0                      @ got null?
8044    mov     r1, r9                      @ r1<- length (restore)
8045    beq     common_exceptionThrown      @ yes, handle exception
8046    @ fall through to OP_NEW_ARRAY_finish
8047
8048    /*
8049     * Finish allocation.
8050     *
8051     *  r0 holds class
8052     *  r1 holds array length
8053     */
8054.LOP_NEW_ARRAY_finish:
8055    mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
8056    bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
8057    cmp     r0, #0                      @ failed?
8058    mov     r2, rINST, lsr #8           @ r2<- A+
8059    beq     common_exceptionThrown      @ yes, handle the exception
8060    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8061    and     r2, r2, #15                 @ r2<- A
8062    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8063    SET_VREG(r0, r2)                    @ vA<- r0
8064    GOTO_OPCODE(ip)                     @ jump to next instruction
8065
8066
8067/* continuation for OP_FILLED_NEW_ARRAY */
8068
8069    /*
8070     * On entry:
8071     *  r0 holds array class
8072     *  r10 holds AA or BA
8073     */
8074.LOP_FILLED_NEW_ARRAY_continue:
8075    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8076    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8077    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
8078    .if     0
8079    mov     r1, r10                     @ r1<- AA (length)
8080    .else
8081    mov     r1, r10, lsr #4             @ r1<- B (length)
8082    .endif
8083    cmp     r3, #'I'                    @ array of ints?
8084    cmpne   r3, #'L'                    @ array of objects?
8085    cmpne   r3, #'['                    @ array of arrays?
8086    mov     r9, r1                      @ save length in r9
8087    bne     .LOP_FILLED_NEW_ARRAY_notimpl         @ no, not handled yet
8088    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8089    cmp     r0, #0                      @ null return?
8090    beq     common_exceptionThrown      @ alloc failed, handle exception
8091
8092    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8093    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
8094    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8095    subs    r9, r9, #1                  @ length--, check for neg
8096    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8097    bmi     2f                          @ was zero, bail
8098
8099    @ copy values from registers into the array
8100    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8101    .if     0
8102    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
81031:  ldr     r3, [r2], #4                @ r3<- *r2++
8104    subs    r9, r9, #1                  @ count--
8105    str     r3, [r0], #4                @ *contents++ = vX
8106    bpl     1b
8107    @ continue at 2
8108    .else
8109    cmp     r9, #4                      @ length was initially 5?
8110    and     r2, r10, #15                @ r2<- A
8111    bne     1f                          @ <= 4 args, branch
8112    GET_VREG(r3, r2)                    @ r3<- vA
8113    sub     r9, r9, #1                  @ count--
8114    str     r3, [r0, #16]               @ contents[4] = vA
81151:  and     r2, r1, #15                 @ r2<- F/E/D/C
8116    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8117    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8118    subs    r9, r9, #1                  @ count--
8119    str     r3, [r0], #4                @ *contents++ = vX
8120    bpl     1b
8121    @ continue at 2
8122    .endif
8123
81242:
8125    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
8126    GOTO_OPCODE(ip)                     @ execute it
8127
8128    /*
8129     * Throw an exception indicating that we have not implemented this
8130     * mode of filled-new-array.
8131     */
8132.LOP_FILLED_NEW_ARRAY_notimpl:
8133    ldr     r0, .L_strInternalError
8134    ldr     r1, .L_strFilledNewArrayNotImpl
8135    bl      dvmThrowException
8136    b       common_exceptionThrown
8137
8138    .if     (!0)                 @ define in one or the other, not both
8139.L_strFilledNewArrayNotImpl:
8140    .word   .LstrFilledNewArrayNotImpl
8141.L_strInternalError:
8142    .word   .LstrInternalError
8143    .endif
8144
8145
8146/* continuation for OP_FILLED_NEW_ARRAY_RANGE */
8147
8148    /*
8149     * On entry:
8150     *  r0 holds array class
8151     *  r10 holds AA or BA
8152     */
8153.LOP_FILLED_NEW_ARRAY_RANGE_continue:
8154    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8155    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8156    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
8157    .if     1
8158    mov     r1, r10                     @ r1<- AA (length)
8159    .else
8160    mov     r1, r10, lsr #4             @ r1<- B (length)
8161    .endif
8162    cmp     r3, #'I'                    @ array of ints?
8163    cmpne   r3, #'L'                    @ array of objects?
8164    cmpne   r3, #'['                    @ array of arrays?
8165    mov     r9, r1                      @ save length in r9
8166    bne     .LOP_FILLED_NEW_ARRAY_RANGE_notimpl         @ no, not handled yet
8167    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8168    cmp     r0, #0                      @ null return?
8169    beq     common_exceptionThrown      @ alloc failed, handle exception
8170
8171    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8172    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
8173    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8174    subs    r9, r9, #1                  @ length--, check for neg
8175    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8176    bmi     2f                          @ was zero, bail
8177
8178    @ copy values from registers into the array
8179    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8180    .if     1
8181    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
81821:  ldr     r3, [r2], #4                @ r3<- *r2++
8183    subs    r9, r9, #1                  @ count--
8184    str     r3, [r0], #4                @ *contents++ = vX
8185    bpl     1b
8186    @ continue at 2
8187    .else
8188    cmp     r9, #4                      @ length was initially 5?
8189    and     r2, r10, #15                @ r2<- A
8190    bne     1f                          @ <= 4 args, branch
8191    GET_VREG(r3, r2)                    @ r3<- vA
8192    sub     r9, r9, #1                  @ count--
8193    str     r3, [r0, #16]               @ contents[4] = vA
81941:  and     r2, r1, #15                 @ r2<- F/E/D/C
8195    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8196    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8197    subs    r9, r9, #1                  @ count--
8198    str     r3, [r0], #4                @ *contents++ = vX
8199    bpl     1b
8200    @ continue at 2
8201    .endif
8202
82032:
8204    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
8205    GOTO_OPCODE(ip)                     @ execute it
8206
8207    /*
8208     * Throw an exception indicating that we have not implemented this
8209     * mode of filled-new-array.
8210     */
8211.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
8212    ldr     r0, .L_strInternalError
8213    ldr     r1, .L_strFilledNewArrayNotImpl
8214    bl      dvmThrowException
8215    b       common_exceptionThrown
8216
8217    .if     (!1)                 @ define in one or the other, not both
8218.L_strFilledNewArrayNotImpl:
8219    .word   .LstrFilledNewArrayNotImpl
8220.L_strInternalError:
8221    .word   .LstrInternalError
8222    .endif
8223
8224
8225/* continuation for OP_CMPL_FLOAT */
8226
8227    @ Test for NaN with a second comparison.  EABI forbids testing bit
8228    @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8229    @ make the library call.
8230.LOP_CMPL_FLOAT_gt_or_nan:
8231    mov     r1, r9                      @ reverse order
8232    mov     r0, r10
8233    bl      __aeabi_cfcmple             @ r0<- Z set if eq, C clear if <
8234    @bleq    common_abort
8235    movcc   r1, #1                      @ (greater than) r1<- 1
8236    bcc     .LOP_CMPL_FLOAT_finish
8237    mvn     r1, #0                            @ r1<- 1 or -1 for NaN
8238    b       .LOP_CMPL_FLOAT_finish
8239
8240
8241#if 0       /* "clasic" form */
8242    FETCH(r0, 1)                        @ r0<- CCBB
8243    and     r2, r0, #255                @ r2<- BB
8244    mov     r3, r0, lsr #8              @ r3<- CC
8245    GET_VREG(r9, r2)                    @ r9<- vBB
8246    GET_VREG(r10, r3)                   @ r10<- vCC
8247    mov     r0, r9                      @ r0<- vBB
8248    mov     r1, r10                     @ r1<- vCC
8249    bl      __aeabi_fcmpeq              @ r0<- (vBB == vCC)
8250    cmp     r0, #0                      @ equal?
8251    movne   r1, #0                      @ yes, result is 0
8252    bne     OP_CMPL_FLOAT_finish
8253    mov     r0, r9                      @ r0<- vBB
8254    mov     r1, r10                     @ r1<- vCC
8255    bl      __aeabi_fcmplt              @ r0<- (vBB < vCC)
8256    cmp     r0, #0                      @ less than?
8257    b       OP_CMPL_FLOAT_continue
8258@%break
8259
8260OP_CMPL_FLOAT_continue:
8261    mvnne   r1, #0                      @ yes, result is -1
8262    bne     OP_CMPL_FLOAT_finish
8263    mov     r0, r9                      @ r0<- vBB
8264    mov     r1, r10                     @ r1<- vCC
8265    bl      __aeabi_fcmpgt              @ r0<- (vBB > vCC)
8266    cmp     r0, #0                      @ greater than?
8267    beq     OP_CMPL_FLOAT_nan               @ no, must be NaN
8268    mov     r1, #1                      @ yes, result is 1
8269    @ fall through to _finish
8270
8271OP_CMPL_FLOAT_finish:
8272    mov     r3, rINST, lsr #8           @ r3<- AA
8273    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8274    SET_VREG(r1, r3)                    @ vAA<- r1
8275    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8276    GOTO_OPCODE(ip)                     @ jump to next instruction
8277
8278    /*
8279     * This is expected to be uncommon, so we double-branch (once to here,
8280     * again back to _finish).
8281     */
8282OP_CMPL_FLOAT_nan:
8283    mvn     r1, #0                            @ r1<- 1 or -1 for NaN
8284    b       OP_CMPL_FLOAT_finish
8285
8286#endif
8287
8288
8289/* continuation for OP_CMPG_FLOAT */
8290
8291    @ Test for NaN with a second comparison.  EABI forbids testing bit
8292    @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8293    @ make the library call.
8294.LOP_CMPG_FLOAT_gt_or_nan:
8295    mov     r1, r9                      @ reverse order
8296    mov     r0, r10
8297    bl      __aeabi_cfcmple             @ r0<- Z set if eq, C clear if <
8298    @bleq    common_abort
8299    movcc   r1, #1                      @ (greater than) r1<- 1
8300    bcc     .LOP_CMPG_FLOAT_finish
8301    mov     r1, #1                            @ r1<- 1 or -1 for NaN
8302    b       .LOP_CMPG_FLOAT_finish
8303
8304
8305#if 0       /* "clasic" form */
8306    FETCH(r0, 1)                        @ r0<- CCBB
8307    and     r2, r0, #255                @ r2<- BB
8308    mov     r3, r0, lsr #8              @ r3<- CC
8309    GET_VREG(r9, r2)                    @ r9<- vBB
8310    GET_VREG(r10, r3)                   @ r10<- vCC
8311    mov     r0, r9                      @ r0<- vBB
8312    mov     r1, r10                     @ r1<- vCC
8313    bl      __aeabi_fcmpeq              @ r0<- (vBB == vCC)
8314    cmp     r0, #0                      @ equal?
8315    movne   r1, #0                      @ yes, result is 0
8316    bne     OP_CMPG_FLOAT_finish
8317    mov     r0, r9                      @ r0<- vBB
8318    mov     r1, r10                     @ r1<- vCC
8319    bl      __aeabi_fcmplt              @ r0<- (vBB < vCC)
8320    cmp     r0, #0                      @ less than?
8321    b       OP_CMPG_FLOAT_continue
8322@%break
8323
8324OP_CMPG_FLOAT_continue:
8325    mvnne   r1, #0                      @ yes, result is -1
8326    bne     OP_CMPG_FLOAT_finish
8327    mov     r0, r9                      @ r0<- vBB
8328    mov     r1, r10                     @ r1<- vCC
8329    bl      __aeabi_fcmpgt              @ r0<- (vBB > vCC)
8330    cmp     r0, #0                      @ greater than?
8331    beq     OP_CMPG_FLOAT_nan               @ no, must be NaN
8332    mov     r1, #1                      @ yes, result is 1
8333    @ fall through to _finish
8334
8335OP_CMPG_FLOAT_finish:
8336    mov     r3, rINST, lsr #8           @ r3<- AA
8337    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8338    SET_VREG(r1, r3)                    @ vAA<- r1
8339    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8340    GOTO_OPCODE(ip)                     @ jump to next instruction
8341
8342    /*
8343     * This is expected to be uncommon, so we double-branch (once to here,
8344     * again back to _finish).
8345     */
8346OP_CMPG_FLOAT_nan:
8347    mov     r1, #1                            @ r1<- 1 or -1 for NaN
8348    b       OP_CMPG_FLOAT_finish
8349
8350#endif
8351
8352
8353/* continuation for OP_CMPL_DOUBLE */
8354
8355    @ Test for NaN with a second comparison.  EABI forbids testing bit
8356    @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8357    @ make the library call.
8358.LOP_CMPL_DOUBLE_gt_or_nan:
8359    ldmia   r10, {r0-r1}                @ reverse order
8360    ldmia   r9, {r2-r3}
8361    bl      __aeabi_cdcmple             @ r0<- Z set if eq, C clear if <
8362    @bleq    common_abort
8363    movcc   r1, #1                      @ (greater than) r1<- 1
8364    bcc     .LOP_CMPL_DOUBLE_finish
8365    mvn     r1, #0                            @ r1<- 1 or -1 for NaN
8366    b       .LOP_CMPL_DOUBLE_finish
8367
8368
8369/* continuation for OP_CMPG_DOUBLE */
8370
8371    @ Test for NaN with a second comparison.  EABI forbids testing bit
8372    @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8373    @ make the library call.
8374.LOP_CMPG_DOUBLE_gt_or_nan:
8375    ldmia   r10, {r0-r1}                @ reverse order
8376    ldmia   r9, {r2-r3}
8377    bl      __aeabi_cdcmple             @ r0<- Z set if eq, C clear if <
8378    @bleq    common_abort
8379    movcc   r1, #1                      @ (greater than) r1<- 1
8380    bcc     .LOP_CMPG_DOUBLE_finish
8381    mov     r1, #1                            @ r1<- 1 or -1 for NaN
8382    b       .LOP_CMPG_DOUBLE_finish
8383
8384
8385/* continuation for OP_CMP_LONG */
8386
8387.LOP_CMP_LONG_less:
8388    mvn     r1, #0                      @ r1<- -1
8389    @ Want to cond code the next mov so we can avoid branch, but don't see it;
8390    @ instead, we just replicate the tail end.
8391    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8392    SET_VREG(r1, r9)                    @ vAA<- r1
8393    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8394    GOTO_OPCODE(ip)                     @ jump to next instruction
8395
8396.LOP_CMP_LONG_greater:
8397    mov     r1, #1                      @ r1<- 1
8398    @ fall through to _finish
8399
8400.LOP_CMP_LONG_finish:
8401    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8402    SET_VREG(r1, r9)                    @ vAA<- r1
8403    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8404    GOTO_OPCODE(ip)                     @ jump to next instruction
8405
8406
8407/* continuation for OP_AGET_WIDE */
8408
8409.LOP_AGET_WIDE_finish:
8410    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8411    add     r0, r0, #offArrayObject_contents
8412    ldmia   r0, {r2-r3}                 @ r2/r3 <- vBB[vCC]
8413    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
8414    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8415    stmia   r9, {r2-r3}                 @ vAA/vAA+1<- r2/r3
8416    GOTO_OPCODE(ip)                     @ jump to next instruction
8417
8418
8419/* continuation for OP_APUT_WIDE */
8420
8421.LOP_APUT_WIDE_finish:
8422    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8423    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
8424    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8425    add     r0, #offArrayObject_contents
8426    stmia   r0, {r2-r3}                 @ vBB[vCC] <- r2/r3
8427    GOTO_OPCODE(ip)                     @ jump to next instruction
8428
8429
8430/* continuation for OP_APUT_OBJECT */
8431    /*
8432     * On entry:
8433     *  r1 = vBB (arrayObj)
8434     *  r9 = vAA (obj)
8435     *  r10 = offset into array (vBB + vCC * width)
8436     */
8437.LOP_APUT_OBJECT_finish:
8438    cmp     r9, #0                      @ storing null reference?
8439    beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
8440    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
8441    ldr     r1, [r1, #offObject_clazz]  @ r1<- arrayObj->clazz
8442    bl      dvmCanPutArrayElement       @ test object type vs. array type
8443    cmp     r0, #0                      @ okay?
8444    beq     common_errArrayStore        @ no
8445.LOP_APUT_OBJECT_skip_check:
8446    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8447    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8448    str     r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
8449    GOTO_OPCODE(ip)                     @ jump to next instruction
8450
8451
8452/* continuation for OP_IGET */
8453
8454    /*
8455     * Currently:
8456     *  r0 holds resolved field
8457     *  r9 holds object
8458     */
8459.LOP_IGET_finish:
8460    @bl      common_squeak0
8461    cmp     r9, #0                      @ check object for null
8462    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8463    beq     common_errNullObject        @ object was null
8464    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8465    mov     r2, rINST, lsr #8           @ r2<- A+
8466    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8467    and     r2, r2, #15                 @ r2<- A
8468    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8469    SET_VREG(r0, r2)                    @ fp[A]<- r0
8470    GOTO_OPCODE(ip)                     @ jump to next instruction
8471
8472
8473/* continuation for OP_IGET_WIDE */
8474
8475    /*
8476     * Currently:
8477     *  r0 holds resolved field
8478     *  r9 holds object
8479     */
8480.LOP_IGET_WIDE_finish:
8481    cmp     r9, #0                      @ check object for null
8482    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8483    beq     common_errNullObject        @ object was null
8484    mov     r2, rINST, lsr #8           @ r2<- A+
8485    add     r9, r9, r3                  @ r9<- obj + field offset
8486    ldmia   r9, {r0-r1}                 @ r0/r1<- obj.field (64-bit align ok)
8487    and     r2, r2, #15                 @ r2<- A
8488    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8489    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
8490    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8491    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
8492    GOTO_OPCODE(ip)                     @ jump to next instruction
8493
8494
8495/* continuation for OP_IGET_OBJECT */
8496
8497    /*
8498     * Currently:
8499     *  r0 holds resolved field
8500     *  r9 holds object
8501     */
8502.LOP_IGET_OBJECT_finish:
8503    @bl      common_squeak0
8504    cmp     r9, #0                      @ check object for null
8505    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8506    beq     common_errNullObject        @ object was null
8507    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8508    mov     r2, rINST, lsr #8           @ r2<- A+
8509    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8510    and     r2, r2, #15                 @ r2<- A
8511    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8512    SET_VREG(r0, r2)                    @ fp[A]<- r0
8513    GOTO_OPCODE(ip)                     @ jump to next instruction
8514
8515
8516/* continuation for OP_IGET_BOOLEAN */
8517
8518    /*
8519     * Currently:
8520     *  r0 holds resolved field
8521     *  r9 holds object
8522     */
8523.LOP_IGET_BOOLEAN_finish:
8524    @bl      common_squeak1
8525    cmp     r9, #0                      @ check object for null
8526    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8527    beq     common_errNullObject        @ object was null
8528    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8529    mov     r2, rINST, lsr #8           @ r2<- A+
8530    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8531    and     r2, r2, #15                 @ r2<- A
8532    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8533    SET_VREG(r0, r2)                    @ fp[A]<- r0
8534    GOTO_OPCODE(ip)                     @ jump to next instruction
8535
8536
8537/* continuation for OP_IGET_BYTE */
8538
8539    /*
8540     * Currently:
8541     *  r0 holds resolved field
8542     *  r9 holds object
8543     */
8544.LOP_IGET_BYTE_finish:
8545    @bl      common_squeak2
8546    cmp     r9, #0                      @ check object for null
8547    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8548    beq     common_errNullObject        @ object was null
8549    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8550    mov     r2, rINST, lsr #8           @ r2<- A+
8551    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8552    and     r2, r2, #15                 @ r2<- A
8553    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8554    SET_VREG(r0, r2)                    @ fp[A]<- r0
8555    GOTO_OPCODE(ip)                     @ jump to next instruction
8556
8557
8558/* continuation for OP_IGET_CHAR */
8559
8560    /*
8561     * Currently:
8562     *  r0 holds resolved field
8563     *  r9 holds object
8564     */
8565.LOP_IGET_CHAR_finish:
8566    @bl      common_squeak3
8567    cmp     r9, #0                      @ check object for null
8568    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8569    beq     common_errNullObject        @ object was null
8570    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8571    mov     r2, rINST, lsr #8           @ r2<- A+
8572    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8573    and     r2, r2, #15                 @ r2<- A
8574    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8575    SET_VREG(r0, r2)                    @ fp[A]<- r0
8576    GOTO_OPCODE(ip)                     @ jump to next instruction
8577
8578
8579/* continuation for OP_IGET_SHORT */
8580
8581    /*
8582     * Currently:
8583     *  r0 holds resolved field
8584     *  r9 holds object
8585     */
8586.LOP_IGET_SHORT_finish:
8587    @bl      common_squeak4
8588    cmp     r9, #0                      @ check object for null
8589    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8590    beq     common_errNullObject        @ object was null
8591    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8592    mov     r2, rINST, lsr #8           @ r2<- A+
8593    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8594    and     r2, r2, #15                 @ r2<- A
8595    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8596    SET_VREG(r0, r2)                    @ fp[A]<- r0
8597    GOTO_OPCODE(ip)                     @ jump to next instruction
8598
8599
8600/* continuation for OP_IPUT */
8601
8602    /*
8603     * Currently:
8604     *  r0 holds resolved field
8605     *  r9 holds object
8606     */
8607.LOP_IPUT_finish:
8608    @bl      common_squeak0
8609    mov     r1, rINST, lsr #8           @ r1<- A+
8610    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8611    and     r1, r1, #15                 @ r1<- A
8612    cmp     r9, #0                      @ check object for null
8613    GET_VREG(r0, r1)                    @ r0<- fp[A]
8614    beq     common_errNullObject        @ object was null
8615    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8616    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8617    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8618    GOTO_OPCODE(ip)                     @ jump to next instruction
8619
8620
8621/* continuation for OP_IPUT_WIDE */
8622
8623    /*
8624     * Currently:
8625     *  r0 holds resolved field
8626     *  r9 holds object
8627     */
8628.LOP_IPUT_WIDE_finish:
8629    mov     r2, rINST, lsr #8           @ r2<- A+
8630    cmp     r9, #0                      @ check object for null
8631    and     r2, r2, #15                 @ r2<- A
8632    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8633    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
8634    beq     common_errNullObject        @ object was null
8635    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8636    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
8637    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8638    add     r9, r9, r3                  @ r9<- object + byte offset
8639    stmia   r9, {r0-r1}                 @ obj.field (64 bits, aligned)<- r0/r1
8640    GOTO_OPCODE(ip)                     @ jump to next instruction
8641
8642
8643/* continuation for OP_IPUT_OBJECT */
8644
8645    /*
8646     * Currently:
8647     *  r0 holds resolved field
8648     *  r9 holds object
8649     */
8650.LOP_IPUT_OBJECT_finish:
8651    @bl      common_squeak0
8652    mov     r1, rINST, lsr #8           @ r1<- A+
8653    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8654    and     r1, r1, #15                 @ r1<- A
8655    cmp     r9, #0                      @ check object for null
8656    GET_VREG(r0, r1)                    @ r0<- fp[A]
8657    beq     common_errNullObject        @ object was null
8658    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8659    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8660    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8661    GOTO_OPCODE(ip)                     @ jump to next instruction
8662
8663
8664/* continuation for OP_IPUT_BOOLEAN */
8665
8666    /*
8667     * Currently:
8668     *  r0 holds resolved field
8669     *  r9 holds object
8670     */
8671.LOP_IPUT_BOOLEAN_finish:
8672    @bl      common_squeak1
8673    mov     r1, rINST, lsr #8           @ r1<- A+
8674    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8675    and     r1, r1, #15                 @ r1<- A
8676    cmp     r9, #0                      @ check object for null
8677    GET_VREG(r0, r1)                    @ r0<- fp[A]
8678    beq     common_errNullObject        @ object was null
8679    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8680    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8681    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8682    GOTO_OPCODE(ip)                     @ jump to next instruction
8683
8684
8685/* continuation for OP_IPUT_BYTE */
8686
8687    /*
8688     * Currently:
8689     *  r0 holds resolved field
8690     *  r9 holds object
8691     */
8692.LOP_IPUT_BYTE_finish:
8693    @bl      common_squeak2
8694    mov     r1, rINST, lsr #8           @ r1<- A+
8695    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8696    and     r1, r1, #15                 @ r1<- A
8697    cmp     r9, #0                      @ check object for null
8698    GET_VREG(r0, r1)                    @ r0<- fp[A]
8699    beq     common_errNullObject        @ object was null
8700    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8701    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8702    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8703    GOTO_OPCODE(ip)                     @ jump to next instruction
8704
8705
8706/* continuation for OP_IPUT_CHAR */
8707
8708    /*
8709     * Currently:
8710     *  r0 holds resolved field
8711     *  r9 holds object
8712     */
8713.LOP_IPUT_CHAR_finish:
8714    @bl      common_squeak3
8715    mov     r1, rINST, lsr #8           @ r1<- A+
8716    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8717    and     r1, r1, #15                 @ r1<- A
8718    cmp     r9, #0                      @ check object for null
8719    GET_VREG(r0, r1)                    @ r0<- fp[A]
8720    beq     common_errNullObject        @ object was null
8721    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8722    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8723    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8724    GOTO_OPCODE(ip)                     @ jump to next instruction
8725
8726
8727/* continuation for OP_IPUT_SHORT */
8728
8729    /*
8730     * Currently:
8731     *  r0 holds resolved field
8732     *  r9 holds object
8733     */
8734.LOP_IPUT_SHORT_finish:
8735    @bl      common_squeak4
8736    mov     r1, rINST, lsr #8           @ r1<- A+
8737    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8738    and     r1, r1, #15                 @ r1<- A
8739    cmp     r9, #0                      @ check object for null
8740    GET_VREG(r0, r1)                    @ r0<- fp[A]
8741    beq     common_errNullObject        @ object was null
8742    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8743    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8744    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8745    GOTO_OPCODE(ip)                     @ jump to next instruction
8746
8747
8748/* continuation for OP_SGET */
8749
8750    /*
8751     * Continuation if the field has not yet been resolved.
8752     *  r1: BBBB field ref
8753     */
8754.LOP_SGET_resolve:
8755    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8756    EXPORT_PC()                         @ resolve() could throw, so export now
8757    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8758    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8759    cmp     r0, #0                      @ success?
8760    bne     .LOP_SGET_finish          @ yes, finish
8761    b       common_exceptionThrown      @ no, handle exception
8762
8763
8764/* continuation for OP_SGET_WIDE */
8765
8766    /*
8767     * Continuation if the field has not yet been resolved.
8768     *  r1: BBBB field ref
8769     */
8770.LOP_SGET_WIDE_resolve:
8771    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8772    EXPORT_PC()                         @ resolve() could throw, so export now
8773    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8774    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8775    cmp     r0, #0                      @ success?
8776    bne     .LOP_SGET_WIDE_finish          @ yes, finish
8777    b       common_exceptionThrown      @ no, handle exception
8778
8779
8780/* continuation for OP_SGET_OBJECT */
8781
8782    /*
8783     * Continuation if the field has not yet been resolved.
8784     *  r1: BBBB field ref
8785     */
8786.LOP_SGET_OBJECT_resolve:
8787    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8788    EXPORT_PC()                         @ resolve() could throw, so export now
8789    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8790    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8791    cmp     r0, #0                      @ success?
8792    bne     .LOP_SGET_OBJECT_finish          @ yes, finish
8793    b       common_exceptionThrown      @ no, handle exception
8794
8795
8796/* continuation for OP_SGET_BOOLEAN */
8797
8798    /*
8799     * Continuation if the field has not yet been resolved.
8800     *  r1: BBBB field ref
8801     */
8802.LOP_SGET_BOOLEAN_resolve:
8803    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8804    EXPORT_PC()                         @ resolve() could throw, so export now
8805    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8806    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8807    cmp     r0, #0                      @ success?
8808    bne     .LOP_SGET_BOOLEAN_finish          @ yes, finish
8809    b       common_exceptionThrown      @ no, handle exception
8810
8811
8812/* continuation for OP_SGET_BYTE */
8813
8814    /*
8815     * Continuation if the field has not yet been resolved.
8816     *  r1: BBBB field ref
8817     */
8818.LOP_SGET_BYTE_resolve:
8819    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8820    EXPORT_PC()                         @ resolve() could throw, so export now
8821    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8822    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8823    cmp     r0, #0                      @ success?
8824    bne     .LOP_SGET_BYTE_finish          @ yes, finish
8825    b       common_exceptionThrown      @ no, handle exception
8826
8827
8828/* continuation for OP_SGET_CHAR */
8829
8830    /*
8831     * Continuation if the field has not yet been resolved.
8832     *  r1: BBBB field ref
8833     */
8834.LOP_SGET_CHAR_resolve:
8835    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8836    EXPORT_PC()                         @ resolve() could throw, so export now
8837    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8838    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8839    cmp     r0, #0                      @ success?
8840    bne     .LOP_SGET_CHAR_finish          @ yes, finish
8841    b       common_exceptionThrown      @ no, handle exception
8842
8843
8844/* continuation for OP_SGET_SHORT */
8845
8846    /*
8847     * Continuation if the field has not yet been resolved.
8848     *  r1: BBBB field ref
8849     */
8850.LOP_SGET_SHORT_resolve:
8851    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8852    EXPORT_PC()                         @ resolve() could throw, so export now
8853    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8854    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8855    cmp     r0, #0                      @ success?
8856    bne     .LOP_SGET_SHORT_finish          @ yes, finish
8857    b       common_exceptionThrown      @ no, handle exception
8858
8859
8860/* continuation for OP_SPUT */
8861
8862    /*
8863     * Continuation if the field has not yet been resolved.
8864     *  r1: BBBB field ref
8865     */
8866.LOP_SPUT_resolve:
8867    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8868    EXPORT_PC()                         @ resolve() could throw, so export now
8869    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8870    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8871    cmp     r0, #0                      @ success?
8872    bne     .LOP_SPUT_finish          @ yes, finish
8873    b       common_exceptionThrown      @ no, handle exception
8874
8875
8876/* continuation for OP_SPUT_WIDE */
8877
8878    /*
8879     * Continuation if the field has not yet been resolved.
8880     *  r1: BBBB field ref
8881     *  r9: &fp[AA]
8882     */
8883.LOP_SPUT_WIDE_resolve:
8884    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8885    EXPORT_PC()                         @ resolve() could throw, so export now
8886    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8887    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8888    cmp     r0, #0                      @ success?
8889    bne     .LOP_SPUT_WIDE_finish          @ yes, finish
8890    b       common_exceptionThrown      @ no, handle exception
8891
8892
8893/* continuation for OP_SPUT_OBJECT */
8894
8895    /*
8896     * Continuation if the field has not yet been resolved.
8897     *  r1: BBBB field ref
8898     */
8899.LOP_SPUT_OBJECT_resolve:
8900    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8901    EXPORT_PC()                         @ resolve() could throw, so export now
8902    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8903    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8904    cmp     r0, #0                      @ success?
8905    bne     .LOP_SPUT_OBJECT_finish          @ yes, finish
8906    b       common_exceptionThrown      @ no, handle exception
8907
8908
8909/* continuation for OP_SPUT_BOOLEAN */
8910
8911    /*
8912     * Continuation if the field has not yet been resolved.
8913     *  r1: BBBB field ref
8914     */
8915.LOP_SPUT_BOOLEAN_resolve:
8916    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8917    EXPORT_PC()                         @ resolve() could throw, so export now
8918    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8919    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8920    cmp     r0, #0                      @ success?
8921    bne     .LOP_SPUT_BOOLEAN_finish          @ yes, finish
8922    b       common_exceptionThrown      @ no, handle exception
8923
8924
8925/* continuation for OP_SPUT_BYTE */
8926
8927    /*
8928     * Continuation if the field has not yet been resolved.
8929     *  r1: BBBB field ref
8930     */
8931.LOP_SPUT_BYTE_resolve:
8932    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8933    EXPORT_PC()                         @ resolve() could throw, so export now
8934    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8935    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8936    cmp     r0, #0                      @ success?
8937    bne     .LOP_SPUT_BYTE_finish          @ yes, finish
8938    b       common_exceptionThrown      @ no, handle exception
8939
8940
8941/* continuation for OP_SPUT_CHAR */
8942
8943    /*
8944     * Continuation if the field has not yet been resolved.
8945     *  r1: BBBB field ref
8946     */
8947.LOP_SPUT_CHAR_resolve:
8948    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8949    EXPORT_PC()                         @ resolve() could throw, so export now
8950    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8951    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8952    cmp     r0, #0                      @ success?
8953    bne     .LOP_SPUT_CHAR_finish          @ yes, finish
8954    b       common_exceptionThrown      @ no, handle exception
8955
8956
8957/* continuation for OP_SPUT_SHORT */
8958
8959    /*
8960     * Continuation if the field has not yet been resolved.
8961     *  r1: BBBB field ref
8962     */
8963.LOP_SPUT_SHORT_resolve:
8964    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8965    EXPORT_PC()                         @ resolve() could throw, so export now
8966    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8967    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8968    cmp     r0, #0                      @ success?
8969    bne     .LOP_SPUT_SHORT_finish          @ yes, finish
8970    b       common_exceptionThrown      @ no, handle exception
8971
8972
8973/* continuation for OP_INVOKE_VIRTUAL */
8974
8975    /*
8976     * At this point:
8977     *  r0 = resolved base method
8978     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8979     */
8980.LOP_INVOKE_VIRTUAL_continue:
8981    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8982    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8983    cmp     r1, #0                      @ is "this" null?
8984    beq     common_errNullObject        @ null "this", throw exception
8985    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8986    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8987    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8988    bl      common_invokeMethodNoRange @ continue on
8989
8990
8991/* continuation for OP_INVOKE_SUPER */
8992
8993    /*
8994     * At this point:
8995     *  r0 = resolved base method
8996     *  r9 = method->clazz
8997     */
8998.LOP_INVOKE_SUPER_continue:
8999    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
9000    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
9001    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
9002    EXPORT_PC()                         @ must export for invoke
9003    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
9004    bcs     .LOP_INVOKE_SUPER_nsm             @ method not present in superclass
9005    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
9006    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
9007    bl      common_invokeMethodNoRange @ continue on
9008
9009.LOP_INVOKE_SUPER_resolve:
9010    mov     r0, r9                      @ r0<- method->clazz
9011    mov     r2, #METHOD_VIRTUAL         @ resolver method type
9012    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
9013    cmp     r0, #0                      @ got null?
9014    bne     .LOP_INVOKE_SUPER_continue        @ no, continue
9015    b       common_exceptionThrown      @ yes, handle exception
9016
9017    /*
9018     * Throw a NoSuchMethodError with the method name as the message.
9019     *  r0 = resolved base method
9020     */
9021.LOP_INVOKE_SUPER_nsm:
9022    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
9023    b       common_errNoSuchMethod
9024
9025
9026/* continuation for OP_INVOKE_DIRECT */
9027
9028    /*
9029     * On entry:
9030     *  r1 = reference (BBBB or CCCC)
9031     *  r10 = "this" register
9032     */
9033.LOP_INVOKE_DIRECT_resolve:
9034    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
9035    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
9036    mov     r2, #METHOD_DIRECT          @ resolver method type
9037    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
9038    cmp     r0, #0                      @ got null?
9039    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
9040    bne     .LOP_INVOKE_DIRECT_finish          @ no, continue
9041    b       common_exceptionThrown      @ yes, handle exception
9042
9043
9044/* continuation for OP_INVOKE_VIRTUAL_RANGE */
9045
9046    /*
9047     * At this point:
9048     *  r0 = resolved base method
9049     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
9050     */
9051.LOP_INVOKE_VIRTUAL_RANGE_continue:
9052    GET_VREG(r1, r10)                   @ r1<- "this" ptr
9053    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
9054    cmp     r1, #0                      @ is "this" null?
9055    beq     common_errNullObject        @ null "this", throw exception
9056    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
9057    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
9058    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
9059    bl      common_invokeMethodRange @ continue on
9060
9061
9062/* continuation for OP_INVOKE_SUPER_RANGE */
9063
9064    /*
9065     * At this point:
9066     *  r0 = resolved base method
9067     *  r9 = method->clazz
9068     */
9069.LOP_INVOKE_SUPER_RANGE_continue:
9070    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
9071    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
9072    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
9073    EXPORT_PC()                         @ must export for invoke
9074    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
9075    bcs     .LOP_INVOKE_SUPER_RANGE_nsm             @ method not present in superclass
9076    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
9077    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
9078    bl      common_invokeMethodRange @ continue on
9079
9080.LOP_INVOKE_SUPER_RANGE_resolve:
9081    mov     r0, r9                      @ r0<- method->clazz
9082    mov     r2, #METHOD_VIRTUAL         @ resolver method type
9083    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
9084    cmp     r0, #0                      @ got null?
9085    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ no, continue
9086    b       common_exceptionThrown      @ yes, handle exception
9087
9088    /*
9089     * Throw a NoSuchMethodError with the method name as the message.
9090     *  r0 = resolved base method
9091     */
9092.LOP_INVOKE_SUPER_RANGE_nsm:
9093    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
9094    b       common_errNoSuchMethod
9095
9096
9097/* continuation for OP_INVOKE_DIRECT_RANGE */
9098
9099    /*
9100     * On entry:
9101     *  r1 = reference (BBBB or CCCC)
9102     *  r10 = "this" register
9103     */
9104.LOP_INVOKE_DIRECT_RANGE_resolve:
9105    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
9106    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
9107    mov     r2, #METHOD_DIRECT          @ resolver method type
9108    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
9109    cmp     r0, #0                      @ got null?
9110    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
9111    bne     .LOP_INVOKE_DIRECT_RANGE_finish          @ no, continue
9112    b       common_exceptionThrown      @ yes, handle exception
9113
9114
9115/* continuation for OP_FLOAT_TO_LONG */
9116/*
9117 * Convert the float in r0 to a long in r0/r1.
9118 *
9119 * We have to clip values to long min/max per the specification.  The
9120 * expected common case is a "reasonable" value that converts directly
9121 * to modest integer.  The EABI convert function isn't doing this for us.
9122 */
9123f2l_doconv:
9124    stmfd   sp!, {r4, lr}
9125    mov     r1, #0x5f000000             @ (float)maxlong
9126    mov     r4, r0
9127    bl      __aeabi_fcmpge              @ is arg >= maxlong?
9128    cmp     r0, #0                      @ nonzero == yes
9129    mvnne   r0, #0                      @ return maxlong (7fffffff)
9130    mvnne   r1, #0x80000000
9131    ldmnefd sp!, {r4, pc}
9132
9133    mov     r0, r4                      @ recover arg
9134    mov     r1, #0xdf000000             @ (float)minlong
9135    bl      __aeabi_fcmple              @ is arg <= minlong?
9136    cmp     r0, #0                      @ nonzero == yes
9137    movne   r0, #0                      @ return minlong (80000000)
9138    movne   r1, #0x80000000
9139    ldmnefd sp!, {r4, pc}
9140
9141    mov     r0, r4                      @ recover arg
9142    mov     r1, r4
9143    bl      __aeabi_fcmpeq              @ is arg == self?
9144    cmp     r0, #0                      @ zero == no
9145    moveq   r1, #0                      @ return zero for NaN
9146    ldmeqfd sp!, {r4, pc}
9147
9148    mov     r0, r4                      @ recover arg
9149    bl      __aeabi_f2lz                @ convert float to long
9150    ldmfd   sp!, {r4, pc}
9151
9152
9153/* continuation for OP_DOUBLE_TO_LONG */
9154/*
9155 * Convert the double in r0/r1 to a long in r0/r1.
9156 *
9157 * We have to clip values to long min/max per the specification.  The
9158 * expected common case is a "reasonable" value that converts directly
9159 * to modest integer.  The EABI convert function isn't doing this for us.
9160 */
9161d2l_doconv:
9162    stmfd   sp!, {r4, r5, lr}           @ save regs
9163    ldr     r3, .LOP_DOUBLE_TO_LONG_max         @ (double)maxlong, hi
9164    sub     sp, sp, #4                  @ align for EABI
9165    mov     r2, #0                      @ (double)maxlong, lo
9166    mov     r4, r0                      @ save r0
9167    mov     r5, r1                      @  and r1
9168    bl      __aeabi_dcmpge              @ is arg >= maxlong?
9169    cmp     r0, #0                      @ nonzero == yes
9170    mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
9171    mvnne   r1, #0x80000000
9172    bne     1f
9173
9174    mov     r0, r4                      @ recover arg
9175    mov     r1, r5
9176    ldr     r3, .LOP_DOUBLE_TO_LONG_min         @ (double)minlong, hi
9177    mov     r2, #0                      @ (double)minlong, lo
9178    bl      __aeabi_dcmple              @ is arg <= minlong?
9179    cmp     r0, #0                      @ nonzero == yes
9180    movne   r0, #0                      @ return minlong (8000000000000000)
9181    movne   r1, #0x80000000
9182    bne     1f
9183
9184    mov     r0, r4                      @ recover arg
9185    mov     r1, r5
9186    mov     r2, r4                      @ compare against self
9187    mov     r3, r5
9188    bl      __aeabi_dcmpeq              @ is arg == self?
9189    cmp     r0, #0                      @ zero == no
9190    moveq   r1, #0                      @ return zero for NaN
9191    beq     1f
9192
9193    mov     r0, r4                      @ recover arg
9194    mov     r1, r5
9195    bl      __aeabi_d2lz                @ convert double to long
9196
91971:
9198    add     sp, sp, #4
9199    ldmfd   sp!, {r4, r5, pc}
9200
9201.LOP_DOUBLE_TO_LONG_max:
9202    .word   0x43e00000                  @ maxlong, as a double (high word)
9203.LOP_DOUBLE_TO_LONG_min:
9204    .word   0xc3e00000                  @ minlong, as a double (high word)
9205
9206
9207/* continuation for OP_MUL_LONG */
9208
9209.LOP_MUL_LONG_finish:
9210    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9211    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
9212    GOTO_OPCODE(ip)                     @ jump to next instruction
9213
9214
9215/* continuation for OP_SHL_LONG */
9216
9217.LOP_SHL_LONG_finish:
9218    mov     r0, r0, asl r2              @  r0<- r0 << r2
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 */
9225
9226.LOP_SHR_LONG_finish:
9227    mov     r1, r1, asr r2              @  r1<- r1 >> r2
9228    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9229    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9230    GOTO_OPCODE(ip)                     @ jump to next instruction
9231
9232
9233/* continuation for OP_USHR_LONG */
9234
9235.LOP_USHR_LONG_finish:
9236    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
9237    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9238    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9239    GOTO_OPCODE(ip)                     @ jump to next instruction
9240
9241
9242/* continuation for OP_SHL_LONG_2ADDR */
9243
9244.LOP_SHL_LONG_2ADDR_finish:
9245    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9246    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9247    GOTO_OPCODE(ip)                     @ jump to next instruction
9248
9249
9250/* continuation for OP_SHR_LONG_2ADDR */
9251
9252.LOP_SHR_LONG_2ADDR_finish:
9253    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9254    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9255    GOTO_OPCODE(ip)                     @ jump to next instruction
9256
9257
9258/* continuation for OP_USHR_LONG_2ADDR */
9259
9260.LOP_USHR_LONG_2ADDR_finish:
9261    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9262    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9263    GOTO_OPCODE(ip)                     @ jump to next instruction
9264
9265
9266/* continuation for OP_EXECUTE_INLINE */
9267
9268    /*
9269     * Extract args, call function.
9270     *  r0 = #of args (0-4)
9271     *  r10 = call index
9272     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
9273     *
9274     * Other ideas:
9275     * - Use a jump table from the main piece to jump directly into the
9276     *   AND/LDR pairs.  Costs a data load, saves a branch.
9277     * - Have five separate pieces that do the loading, so we can work the
9278     *   interleave a little better.  Increases code size.
9279     */
9280.LOP_EXECUTE_INLINE_continue:
9281    rsb     r0, r0, #4                  @ r0<- 4-r0
9282    FETCH(r9, 2)                        @ r9<- FEDC
9283    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
9284    bl      common_abort                @ (skipped due to ARM prefetch)
92854:  and     ip, r9, #0xf000             @ isolate F
9286    ldr     r3, [rFP, ip, lsr #10]      @ r3<- vF (shift right 12, left 2)
92873:  and     ip, r9, #0x0f00             @ isolate E
9288    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vE
92892:  and     ip, r9, #0x00f0             @ isolate D
9290    ldr     r1, [rFP, ip, lsr #2]       @ r1<- vD
92911:  and     ip, r9, #0x000f             @ isolate C
9292    ldr     r0, [rFP, ip, lsl #2]       @ r0<- vC
92930:
9294    ldr     r9, .LOP_EXECUTE_INLINE_table       @ table of InlineOperation
9295    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
9296    @ (not reached)
9297
9298.LOP_EXECUTE_INLINE_table:
9299    .word   gDvmInlineOpsTable
9300
9301
9302    .size   dvmAsmSisterStart, .-dvmAsmSisterStart
9303    .global dvmAsmSisterEnd
9304dvmAsmSisterEnd:
9305
9306/* File: armv5te/footer.S */
9307/*
9308 * ===========================================================================
9309 *  Common subroutines and data
9310 * ===========================================================================
9311 */
9312
9313    .text
9314    .align  2
9315
9316/*
9317 * Common code when a backward branch is taken.
9318 *
9319 * On entry:
9320 *  r9 is PC adjustment *in bytes*
9321 */
9322common_backwardBranch:
9323    mov     r0, #kInterpEntryInstr
9324    bl      common_periodicChecks
9325    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9326    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9327    GOTO_OPCODE(ip)                     @ jump to next instruction
9328
9329
9330/*
9331 * Need to see if the thread needs to be suspended or debugger/profiler
9332 * activity has begun.
9333 *
9334 * TODO: if JDWP isn't running, zero out pDebuggerActive pointer so we don't
9335 * have to do the second ldr.
9336 *
9337 * TODO: reduce this so we're just checking a single location.
9338 *
9339 * On entry:
9340 *  r0 is reentry type, e.g. kInterpEntryInstr
9341 *  r9 is trampoline PC adjustment *in bytes*
9342 */
9343common_periodicChecks:
9344    ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
9345
9346#if defined(WITH_DEBUGGER)
9347    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9348#endif
9349#if defined(WITH_PROFILER)
9350    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9351#endif
9352
9353    ldr     r3, [r3]                    @ r3<- suspendCount (int)
9354
9355#if defined(WITH_DEBUGGER)
9356    ldrb    r1, [r1]                    @ r1<- debuggerActive (boolean)
9357#endif
9358#if defined (WITH_PROFILER)
9359    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9360#endif
9361
9362    cmp     r3, #0                      @ suspend pending?
9363    bne     2f                          @ yes, do full suspension check
9364
9365#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
9366# if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
9367    orrs    r1, r1, r2                  @ r1<- r1 | r2
9368    cmp     r1, #0                      @ debugger attached or profiler started?
9369# elif defined(WITH_DEBUGGER)
9370    cmp     r1, #0                      @ debugger attached?
9371# elif defined(WITH_PROFILER)
9372    cmp     r2, #0                      @ profiler started?
9373# endif
9374    bne     3f                          @ debugger/profiler, switch interp
9375#endif
9376
9377    bx      lr                          @ nothing to do, return
9378
93792:  @ check suspend
9380    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9381    EXPORT_PC()                         @ need for precise GC
9382    b       dvmCheckSuspendPending      @ suspend if necessary, then return
9383
93843:  @ debugger/profiler enabled, bail out
9385    add     rPC, rPC, r9                @ update rPC
9386    str     r0, [rGLUE, #offGlue_entryPoint]
9387    mov     r1, #1                      @ "want switch" = true
9388    b       common_gotoBail
9389
9390
9391/*
9392 * The equivalent of "goto bail", this calls through the "bail handler".
9393 *
9394 * State registers will be saved to the "glue" area before bailing.
9395 *
9396 * On entry:
9397 *  r1 is "bool changeInterp", indicating if we want to switch to the
9398 *     other interpreter or just bail all the way out
9399 */
9400common_gotoBail:
9401    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9402    mov     r0, rGLUE                   @ r0<- glue ptr
9403    b       dvmMterpStdBail             @ call(glue, changeInterp)
9404
9405    @add     r1, r1, #1                  @ using (boolean+1)
9406    @add     r0, rGLUE, #offGlue_jmpBuf  @ r0<- &glue->jmpBuf
9407    @bl      _longjmp                    @ does not return
9408    @bl      common_abort
9409
9410
9411/*
9412 * Common code for method invocation with range.
9413 *
9414 * On entry:
9415 *  r0 is "Method* methodToCall", the method we're trying to call
9416 */
9417common_invokeMethodRange:
9418.LinvokeNewRange:
9419    @ prepare to copy args to "outs" area of current frame
9420    movs    r2, rINST, lsr #8           @ r2<- AA (arg count) -- test for zero
9421    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9422    beq     .LinvokeArgsDone            @ if no args, skip the rest
9423    FETCH(r1, 2)                        @ r1<- CCCC
9424
9425    @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
9426    @ (very few methods have > 10 args; could unroll for common cases)
9427    add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
9428    sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
9429    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
94301:  ldr     r1, [r3], #4                @ val = *fp++
9431    subs    r2, r2, #1                  @ count--
9432    str     r1, [r10], #4               @ *outs++ = val
9433    bne     1b                          @ ...while count != 0
9434    ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
9435    b       .LinvokeArgsDone
9436
9437/*
9438 * Common code for method invocation without range.
9439 *
9440 * On entry:
9441 *  r0 is "Method* methodToCall", the method we're trying to call
9442 */
9443common_invokeMethodNoRange:
9444.LinvokeNewNoRange:
9445    @ prepare to copy args to "outs" area of current frame
9446    movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
9447    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9448    FETCH(r1, 2)                        @ r1<- GFED (load here to hide latency)
9449    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
9450    ldrh    r3, [r0, #offMethod_outsSize]  @ r3<- methodToCall->outsSize
9451    beq     .LinvokeArgsDone
9452
9453    @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
9454.LinvokeNonRange:
9455    rsb     r2, r2, #5                  @ r2<- 5-r2
9456    add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
9457    bl      common_abort                @ (skipped due to ARM prefetch)
94585:  and     ip, rINST, #0x0f00          @ isolate A
9459    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vA (shift right 8, left 2)
9460    mov     r0, r0                      @ nop
9461    str     r2, [r10, #-4]!             @ *--outs = vA
94624:  and     ip, r1, #0xf000             @ isolate G
9463    ldr     r2, [rFP, ip, lsr #10]      @ r2<- vG (shift right 12, left 2)
9464    mov     r0, r0                      @ nop
9465    str     r2, [r10, #-4]!             @ *--outs = vG
94663:  and     ip, r1, #0x0f00             @ isolate F
9467    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vF
9468    mov     r0, r0                      @ nop
9469    str     r2, [r10, #-4]!             @ *--outs = vF
94702:  and     ip, r1, #0x00f0             @ isolate E
9471    ldr     r2, [rFP, ip, lsr #2]       @ r2<- vE
9472    mov     r0, r0                      @ nop
9473    str     r2, [r10, #-4]!             @ *--outs = vE
94741:  and     ip, r1, #0x000f             @ isolate D
9475    ldr     r2, [rFP, ip, lsl #2]       @ r2<- vD
9476    mov     r0, r0                      @ nop
9477    str     r2, [r10, #-4]!             @ *--outs = vD
94780:  @ fall through to .LinvokeArgsDone
9479
9480.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
9481    ldr     r2, [r0, #offMethod_insns]  @ r2<- method->insns
9482    ldr     rINST, [r0, #offMethod_clazz]  @ rINST<- method->clazz
9483    @ find space for the new stack frame, check for overflow
9484    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
9485    sub     r1, r1, r9, lsl #2          @ r1<- newFp (old savearea - regsSize)
9486    SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
9487@    bl      common_dumpRegs
9488    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
9489    sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
9490    cmp     r3, r9                      @ bottom < interpStackEnd?
9491    ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
9492    blt     .LstackOverflow             @ yes, this frame will overflow stack
9493
9494    @ set up newSaveArea
9495#ifdef EASY_GDB
9496    SAVEAREA_FROM_FP(ip, rFP)           @ ip<- stack save area
9497    str     ip, [r10, #offStackSaveArea_prevSave]
9498#endif
9499    str     rFP, [r10, #offStackSaveArea_prevFrame]
9500    str     rPC, [r10, #offStackSaveArea_savedPc]
9501    str     r0, [r10, #offStackSaveArea_method]
9502    tst     r3, #ACC_NATIVE
9503    bne     .LinvokeNative
9504
9505    /*
9506    stmfd   sp!, {r0-r3}
9507    bl      common_printNewline
9508    mov     r0, rFP
9509    mov     r1, #0
9510    bl      dvmDumpFp
9511    ldmfd   sp!, {r0-r3}
9512    stmfd   sp!, {r0-r3}
9513    mov     r0, r1
9514    mov     r1, r10
9515    bl      dvmDumpFp
9516    bl      common_printNewline
9517    ldmfd   sp!, {r0-r3}
9518    */
9519
9520    ldrh    r9, [r2]                        @ r9 <- load INST from new PC
9521    ldr     r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
9522    mov     rPC, r2                         @ publish new rPC
9523    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
9524
9525    @ Update "glue" values for the new method
9526    @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
9527    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
9528    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
9529    mov     rFP, r1                         @ fp = newFp
9530    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
9531    mov     rINST, r9                       @ publish new rINST
9532    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
9533    GOTO_OPCODE(ip)                         @ jump to next instruction
9534
9535.LinvokeNative:
9536    @ Prep for the native call
9537    @ r0=methodToCall, r1=newFp, r10=newSaveArea
9538    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
9539    ldr     r9, [r3, #offThread_jniLocal_nextEntry] @ r9<- thread->refNext
9540    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
9541    str     r9, [r10, #offStackSaveArea_localRefTop] @newFp->localRefTop=refNext
9542    mov     r9, r3                      @ r9<- glue->self (preserve)
9543
9544    mov     r2, r0                      @ r2<- methodToCall
9545    mov     r0, r1                      @ r0<- newFp (points to args)
9546    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
9547
9548#ifdef ASSIST_DEBUGGER
9549    /* insert fake function header to help gdb find the stack frame */
9550    b       .Lskip
9551    .type   dalvik_mterp, %function
9552dalvik_mterp:
9553    .fnstart
9554    MTERP_ENTRY1
9555    MTERP_ENTRY2
9556.Lskip:
9557#endif
9558
9559    @mov     lr, pc                      @ set return addr
9560    @ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
9561    LDR_PC_LR "[r2, #offMethod_nativeFunc]"
9562
9563    @ native return; r9=self, r10=newSaveArea
9564    @ equivalent to dvmPopJniLocals
9565    ldr     r0, [r10, #offStackSaveArea_localRefTop] @ r0<- newSave->localRefTop
9566    ldr     r1, [r9, #offThread_exception] @ check for exception
9567    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
9568    cmp     r1, #0                      @ null?
9569    str     r0, [r9, #offThread_jniLocal_nextEntry] @ self->refNext<- r0
9570    bne     common_exceptionThrown      @ no, handle exception
9571
9572    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
9573    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9574    GOTO_OPCODE(ip)                     @ jump to next instruction
9575
9576.LstackOverflow:
9577    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
9578    bl      dvmHandleStackOverflow
9579    b       common_exceptionThrown
9580#ifdef ASSIST_DEBUGGER
9581    .fnend
9582#endif
9583
9584
9585    /*
9586     * Common code for method invocation, calling through "glue code".
9587     *
9588     * TODO: now that we have range and non-range invoke handlers, this
9589     *       needs to be split into two.  Maybe just create entry points
9590     *       that set r9 and jump here?
9591     *
9592     * On entry:
9593     *  r0 is "Method* methodToCall", the method we're trying to call
9594     *  r9 is "bool methodCallRange", indicating if this is a /range variant
9595     */
9596     .if    0
9597.LinvokeOld:
9598    sub     sp, sp, #8                  @ space for args + pad
9599    FETCH(ip, 2)                        @ ip<- FEDC or CCCC
9600    mov     r2, r0                      @ A2<- methodToCall
9601    mov     r0, rGLUE                   @ A0<- glue
9602    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9603    mov     r1, r9                      @ A1<- methodCallRange
9604    mov     r3, rINST, lsr #8           @ A3<- AA
9605    str     ip, [sp, #0]                @ A4<- ip
9606    bl      dvmMterp_invokeMethod       @ call the C invokeMethod
9607    add     sp, sp, #8                  @ remove arg area
9608    b       common_resumeAfterGlueCall  @ continue to next instruction
9609    .endif
9610
9611
9612
9613/*
9614 * Common code for handling a return instruction.
9615 *
9616 * This does not return.
9617 */
9618common_returnFromMethod:
9619.LreturnNew:
9620    mov     r0, #kInterpEntryReturn
9621    mov     r9, #0
9622    bl      common_periodicChecks
9623
9624    SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
9625    ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
9626    ldr     r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
9627    ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
9628                                        @ r2<- method we're returning to
9629    ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
9630    cmp     r2, #0                      @ is this a break frame?
9631    ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
9632    mov     r1, #0                      @ "want switch" = false
9633    beq     common_gotoBail             @ break frame, bail out completely
9634
9635    PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
9636    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
9637    ldr     r1, [r10, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
9638    str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
9639    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9640    mov     rPC, r9                     @ publish new rPC
9641    str     r1, [rGLUE, #offGlue_methodClassDex]
9642    GOTO_OPCODE(ip)                     @ jump to next instruction
9643
9644    /*
9645     * Return handling, calls through "glue code".
9646     */
9647     .if    0
9648.LreturnOld:
9649    SAVE_PC_FP_TO_GLUE()                @ export state
9650    mov     r0, rGLUE                   @ arg to function
9651    bl      dvmMterp_returnFromMethod
9652    b       common_resumeAfterGlueCall
9653    .endif
9654
9655
9656/*
9657 * Somebody has thrown an exception.  Handle it.
9658 *
9659 * If the exception processing code returns to us (instead of falling
9660 * out of the interpreter), continue with whatever the next instruction
9661 * now happens to be.
9662 *
9663 * This does not return.
9664 */
9665common_exceptionThrown:
9666.LexceptionNew:
9667    mov     r0, #kInterpEntryThrow
9668    mov     r9, #0
9669    bl      common_periodicChecks
9670
9671    ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
9672    ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
9673    mov     r1, r10                     @ r1<- self
9674    mov     r0, r9                      @ r0<- exception
9675    bl      dvmAddTrackedAlloc          @ don't let the exception be GCed
9676    mov     r3, #0                      @ r3<- NULL
9677    str     r3, [r10, #offThread_exception] @ self->exception = NULL
9678
9679    /* set up args and a local for "&fp" */
9680    /* (str sp, [sp, #-4]!  would be perfect here, but is discouraged) */
9681    str     rFP, [sp, #-4]!             @ *--sp = fp
9682    mov     ip, sp                      @ ip<- &fp
9683    mov     r3, #0                      @ r3<- false
9684    str     ip, [sp, #-4]!              @ *--sp = &fp
9685    ldr     r1, [rGLUE, #offGlue_method] @ r1<- glue->method
9686    mov     r0, r10                     @ r0<- self
9687    ldr     r1, [r1, #offMethod_insns]  @ r1<- method->insns
9688    mov     r2, r9                      @ r2<- exception
9689    sub     r1, rPC, r1                 @ r1<- pc - method->insns
9690    mov     r1, r1, asr #1              @ r1<- offset in code units
9691
9692    /* call, r0 gets catchRelPc (a code-unit offset) */
9693    bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
9694
9695    /* fix earlier stack overflow if necessary; may trash rFP */
9696    ldrb    r1, [r10, #offThread_stackOverflowed]
9697    cmp     r1, #0                      @ did we overflow earlier?
9698    beq     1f                          @ no, skip ahead
9699    mov     rFP, r0                     @ save relPc result in rFP
9700    mov     r0, r10                     @ r0<- self
9701    bl      dvmCleanupStackOverflow     @ call(self)
9702    mov     r0, rFP                     @ restore result
97031:
9704
9705    /* update frame pointer and check result from dvmFindCatchBlock */
9706    ldr     rFP, [sp, #4]               @ retrieve the updated rFP
9707    cmp     r0, #0                      @ is catchRelPc < 0?
9708    add     sp, sp, #8                  @ restore stack
9709    bmi     .LnotCaughtLocally
9710
9711    /* adjust locals to match self->curFrame and updated PC */
9712    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
9713    ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
9714    str     r1, [rGLUE, #offGlue_method]    @ glue->method = new method
9715    ldr     r2, [r1, #offMethod_clazz]      @ r2<- method->clazz
9716    ldr     r3, [r1, #offMethod_insns]      @ r3<- method->insns
9717    ldr     r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
9718    add     rPC, r3, r0, asl #1             @ rPC<- method->insns + catchRelPc
9719    str     r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
9720
9721    /* release the tracked alloc on the exception */
9722    mov     r0, r9                      @ r0<- exception
9723    mov     r1, r10                     @ r1<- self
9724    bl      dvmReleaseTrackedAlloc      @ release the exception
9725
9726    /* restore the exception if the handler wants it */
9727    FETCH_INST()                        @ load rINST from rPC
9728    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9729    cmp     ip, #OP_MOVE_EXCEPTION      @ is it "move-exception"?
9730    streq   r9, [r10, #offThread_exception] @ yes, restore the exception
9731    GOTO_OPCODE(ip)                     @ jump to next instruction
9732
9733.LnotCaughtLocally: @ r9=exception, r10=self
9734    /* fix stack overflow if necessary */
9735    ldrb    r1, [r10, #offThread_stackOverflowed]
9736    cmp     r1, #0                      @ did we overflow earlier?
9737    movne   r0, r10                     @ if yes: r0<- self
9738    blne    dvmCleanupStackOverflow     @ if yes: call(self)
9739
9740    @ may want to show "not caught locally" debug messages here
9741#if DVM_SHOW_EXCEPTION >= 2
9742    /* call __android_log_print(prio, tag, format, ...) */
9743    /* "Exception %s from %s:%d not caught locally" */
9744    @ dvmLineNumFromPC(method, pc - method->insns)
9745    ldr     r0, [rGLUE, #offGlue_method]
9746    ldr     r1, [r0, #offMethod_insns]
9747    sub     r1, rPC, r1
9748    asr     r1, r1, #1
9749    bl      dvmLineNumFromPC
9750    str     r0, [sp, #-4]!
9751    @ dvmGetMethodSourceFile(method)
9752    ldr     r0, [rGLUE, #offGlue_method]
9753    bl      dvmGetMethodSourceFile
9754    str     r0, [sp, #-4]!
9755    @ exception->clazz->descriptor
9756    ldr     r3, [r9, #offObject_clazz]
9757    ldr     r3, [r3, #offClassObject_descriptor]
9758    @
9759    ldr     r2, strExceptionNotCaughtLocally
9760    ldr     r1, strLogTag
9761    mov     r0, #3                      @ LOG_DEBUG
9762    bl      __android_log_print
9763#endif
9764    str     r9, [r10, #offThread_exception] @ restore exception
9765    mov     r0, r9                      @ r0<- exception
9766    mov     r1, r10                     @ r1<- self
9767    bl      dvmReleaseTrackedAlloc      @ release the exception
9768    mov     r1, #0                      @ "want switch" = false
9769    b       common_gotoBail             @ bail out
9770
9771
9772    /*
9773     * Exception handling, calls through "glue code".
9774     */
9775    .if     0
9776.LexceptionOld:
9777    SAVE_PC_FP_TO_GLUE()                @ export state
9778    mov     r0, rGLUE                   @ arg to function
9779    bl      dvmMterp_exceptionThrown
9780    b       common_resumeAfterGlueCall
9781    .endif
9782
9783
9784/*
9785 * After returning from a "glued" function, pull out the updated
9786 * values and start executing at the next instruction.
9787 */
9788common_resumeAfterGlueCall:
9789    LOAD_PC_FP_FROM_GLUE()              @ pull rPC and rFP out of glue
9790    FETCH_INST()                        @ load rINST from rPC
9791    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9792    GOTO_OPCODE(ip)                     @ jump to next instruction
9793
9794/*
9795 * Invalid array index.
9796 */
9797common_errArrayIndex:
9798    EXPORT_PC()
9799    ldr     r0, strArrayIndexException
9800    mov     r1, #0
9801    bl      dvmThrowException
9802    b       common_exceptionThrown
9803
9804/*
9805 * Invalid array value.
9806 */
9807common_errArrayStore:
9808    EXPORT_PC()
9809    ldr     r0, strArrayStoreException
9810    mov     r1, #0
9811    bl      dvmThrowException
9812    b       common_exceptionThrown
9813
9814/*
9815 * Integer divide or mod by zero.
9816 */
9817common_errDivideByZero:
9818    EXPORT_PC()
9819    ldr     r0, strArithmeticException
9820    ldr     r1, strDivideByZero
9821    bl      dvmThrowException
9822    b       common_exceptionThrown
9823
9824/*
9825 * Attempt to allocate an array with a negative size.
9826 */
9827common_errNegativeArraySize:
9828    EXPORT_PC()
9829    ldr     r0, strNegativeArraySizeException
9830    mov     r1, #0
9831    bl      dvmThrowException
9832    b       common_exceptionThrown
9833
9834/*
9835 * Invocation of a non-existent method.
9836 */
9837common_errNoSuchMethod:
9838    EXPORT_PC()
9839    ldr     r0, strNoSuchMethodError
9840    mov     r1, #0
9841    bl      dvmThrowException
9842    b       common_exceptionThrown
9843
9844/*
9845 * We encountered a null object when we weren't expecting one.  We
9846 * export the PC, throw a NullPointerException, and goto the exception
9847 * processing code.
9848 */
9849common_errNullObject:
9850    EXPORT_PC()
9851    ldr     r0, strNullPointerException
9852    mov     r1, #0
9853    bl      dvmThrowException
9854    b       common_exceptionThrown
9855
9856/*
9857 * For debugging, cause an immediate fault.  The source address will
9858 * be in lr (use a bl instruction to jump here).
9859 */
9860common_abort:
9861    ldr     pc, .LdeadFood
9862.LdeadFood:
9863    .word   0xdeadf00d
9864
9865/*
9866 * Spit out a "we were here", preserving all registers.  (The attempt
9867 * to save ip won't work, but we need to save an even number of
9868 * registers for EABI 64-bit stack alignment.)
9869 */
9870    .macro  SQUEAK num
9871common_squeak\num:
9872    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9873    ldr     r0, strSqueak
9874    mov     r1, #\num
9875    bl      printf
9876    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9877    bx      lr
9878    .endm
9879
9880    SQUEAK  0
9881    SQUEAK  1
9882    SQUEAK  2
9883    SQUEAK  3
9884    SQUEAK  4
9885    SQUEAK  5
9886
9887/*
9888 * Spit out the number in r0, preserving registers.
9889 */
9890common_printNum:
9891    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9892    mov     r1, r0
9893    ldr     r0, strSqueak
9894    bl      printf
9895    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9896    bx      lr
9897
9898/*
9899 * Print a newline, preserving registers.
9900 */
9901common_printNewline:
9902    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9903    ldr     r0, strNewline
9904    bl      printf
9905    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9906    bx      lr
9907
9908    /*
9909     * Print the 32-bit quantity in r0 as a hex value, preserving registers.
9910     */
9911common_printHex:
9912    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9913    mov     r1, r0
9914    ldr     r0, strPrintHex
9915    bl      printf
9916    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9917    bx      lr
9918
9919/*
9920 * Print the 64-bit quantity in r0-r1, preserving registers.
9921 */
9922common_printLong:
9923    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9924    mov     r3, r1
9925    mov     r2, r0
9926    ldr     r0, strPrintLong
9927    bl      printf
9928    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9929    bx      lr
9930
9931/*
9932 * Print full method info.  Pass the Method* in r0.  Preserves regs.
9933 */
9934common_printMethod:
9935    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9936    bl      dvmMterpPrintMethod
9937    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9938    bx      lr
9939
9940/*
9941 * Call a C helper function that dumps regs and possibly some
9942 * additional info.  Requires the C function to be compiled in.
9943 */
9944    .if     0
9945common_dumpRegs:
9946    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9947    bl      dvmMterpDumpArmRegs
9948    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9949    bx      lr
9950    .endif
9951
9952
9953/*
9954 * String references, must be close to the code that uses them.
9955 */
9956    .align  2
9957strArithmeticException:
9958    .word   .LstrArithmeticException
9959strArrayIndexException:
9960    .word   .LstrArrayIndexException
9961strArrayStoreException:
9962    .word   .LstrArrayStoreException
9963strDivideByZero:
9964    .word   .LstrDivideByZero
9965strNegativeArraySizeException:
9966    .word   .LstrNegativeArraySizeException
9967strNoSuchMethodError:
9968    .word   .LstrNoSuchMethodError
9969strNullPointerException:
9970    .word   .LstrNullPointerException
9971
9972strLogTag:
9973    .word   .LstrLogTag
9974strExceptionNotCaughtLocally:
9975    .word   .LstrExceptionNotCaughtLocally
9976
9977strNewline:
9978    .word   .LstrNewline
9979strSqueak:
9980    .word   .LstrSqueak
9981strPrintHex:
9982    .word   .LstrPrintHex
9983strPrintLong:
9984    .word   .LstrPrintLong
9985
9986/*
9987 * Zero-terminated ASCII string data.
9988 *
9989 * On ARM we have two choices: do like gcc does, and LDR from a .word
9990 * with the address, or use an ADR pseudo-op to get the address
9991 * directly.  ADR saves 4 bytes and an indirection, but it's using a
9992 * PC-relative addressing mode and hence has a limited range, which
9993 * makes it not work well with mergeable string sections.
9994 */
9995    .section .rodata.str1.4,"aMS",%progbits,1
9996
9997.LstrBadEntryPoint:
9998    .asciz  "Bad entry point %d\n"
9999.LstrArithmeticException:
10000    .asciz  "Ljava/lang/ArithmeticException;"
10001.LstrArrayIndexException:
10002    .asciz  "Ljava/lang/ArrayIndexOutOfBoundsException;"
10003.LstrArrayStoreException:
10004    .asciz  "Ljava/lang/ArrayStoreException;"
10005.LstrClassCastException:
10006    .asciz  "Ljava/lang/ClassCastException;"
10007.LstrDivideByZero:
10008    .asciz  "divide by zero"
10009.LstrFilledNewArrayNotImpl:
10010    .asciz  "filled-new-array only implemented for objects and 'int'"
10011.LstrInternalError:
10012    .asciz  "Ljava/lang/InternalError;"
10013.LstrInstantiationError:
10014    .asciz  "Ljava/lang/InstantiationError;"
10015.LstrNegativeArraySizeException:
10016    .asciz  "Ljava/lang/NegativeArraySizeException;"
10017.LstrNoSuchMethodError:
10018    .asciz  "Ljava/lang/NoSuchMethodError;"
10019.LstrNullPointerException:
10020    .asciz  "Ljava/lang/NullPointerException;"
10021
10022.LstrLogTag:
10023    .asciz  "mterp"
10024.LstrExceptionNotCaughtLocally:
10025    .asciz  "Exception %s from %s:%d not caught locally\n"
10026
10027.LstrNewline:
10028    .asciz  "\n"
10029.LstrSqueak:
10030    .asciz  "<%d>"
10031.LstrPrintHex:
10032    .asciz  "<0x%x>"
10033.LstrPrintLong:
10034    .asciz  "<%lld>"
10035
10036
10037