blob: e2e0defabb35354d30a66314a387ea81e725995d [file] [log] [blame]
Andy McFaddena5069fb2009-06-19 15:20:12 -07001/*
2 * This file was generated automatically by gen-mterp.py for 'armv7-a'.
3 *
4 * --> DO NOT EDIT <--
5 */
6
7/* File: armv5te/header.S */
8/*
9 * Copyright (C) 2008 The Android Open Source Project
10 *
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 * http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
22 */
23/*
24 * ARMv5 definitions and declarations.
25 */
26
27/*
28ARM EABI general notes:
29
30r0-r3 hold first 4 args to a method; they are not preserved across method calls
31r4-r8 are available for general use
32r9 is given special treatment in some situations, but not for us
33r10 (sl) seems to be generally available
34r11 (fp) is used by gcc (unless -fomit-frame-pointer is set)
35r12 (ip) is scratch -- not preserved across method calls
36r13 (sp) should be managed carefully in case a signal arrives
37r14 (lr) must be preserved
38r15 (pc) can be tinkered with directly
39
40r0 holds returns of <= 4 bytes
41r0-r1 hold returns of 8 bytes, low word in r0
42
43Callee must save/restore r4+ (except r12) if it modifies them. If VFP
44is present, registers s16-s31 (a/k/a d8-d15, a/k/a q4-q7) must be preserved,
45s0-s15 (d0-d7, q0-a3) do not need to be.
46
47Stack is "full descending". Only the arguments that don't fit in the first 4
48registers are placed on the stack. "sp" points at the first stacked argument
49(i.e. the 5th arg).
50
51VFP: single-precision results in s0, double-precision results in d0.
52
53In the EABI, "sp" must be 64-bit aligned on entry to a function, and any
5464-bit quantities (long long, double) must be 64-bit aligned.
55*/
56
57/*
58Mterp and ARM notes:
59
60The following registers have fixed assignments:
61
62 reg nick purpose
63 r4 rPC interpreted program counter, used for fetching instructions
64 r5 rFP interpreted frame pointer, used for accessing locals and args
65 r6 rGLUE MterpGlue pointer
66 r7 rINST first 16-bit code unit of current instruction
67 r8 rIBASE interpreted instruction base pointer, used for computed goto
68
69Macros are provided for common operations. Each macro MUST emit only
70one instruction to make instruction-counting easier. They MUST NOT alter
71unspecified registers or condition codes.
72*/
73
74/* single-purpose registers, given names for clarity */
75#define rPC r4
76#define rFP r5
77#define rGLUE r6
78#define rINST r7
79#define rIBASE r8
80
81/* save/restore the PC and/or FP from the glue struct */
82#define LOAD_PC_FROM_GLUE() ldr rPC, [rGLUE, #offGlue_pc]
83#define SAVE_PC_TO_GLUE() str rPC, [rGLUE, #offGlue_pc]
84#define LOAD_FP_FROM_GLUE() ldr rFP, [rGLUE, #offGlue_fp]
85#define SAVE_FP_TO_GLUE() str rFP, [rGLUE, #offGlue_fp]
86#define LOAD_PC_FP_FROM_GLUE() ldmia rGLUE, {rPC, rFP}
87#define SAVE_PC_FP_TO_GLUE() stmia rGLUE, {rPC, rFP}
88
89/*
90 * "export" the PC to the stack frame, f/b/o future exception objects. Must
91 * be done *before* something calls dvmThrowException.
92 *
93 * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e.
94 * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc)
95 *
96 * It's okay to do this more than once.
97 */
98#define EXPORT_PC() \
99 str rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)]
100
101/*
102 * Given a frame pointer, find the stack save area.
103 *
104 * In C this is "((StackSaveArea*)(_fp) -1)".
105 */
106#define SAVEAREA_FROM_FP(_reg, _fpreg) \
107 sub _reg, _fpreg, #sizeofStackSaveArea
108
109/*
110 * Fetch the next instruction from rPC into rINST. Does not advance rPC.
111 */
112#define FETCH_INST() ldrh rINST, [rPC]
113
114/*
115 * Fetch the next instruction from the specified offset. Advances rPC
116 * to point to the next instruction. "_count" is in 16-bit code units.
117 *
118 * Because of the limited size of immediate constants on ARM, this is only
119 * suitable for small forward movements (i.e. don't try to implement "goto"
120 * with this).
121 *
122 * This must come AFTER anything that can throw an exception, or the
123 * exception catch may miss. (This also implies that it must come after
124 * EXPORT_PC().)
125 */
126#define FETCH_ADVANCE_INST(_count) ldrh rINST, [rPC, #(_count*2)]!
127
128/*
129 * The operation performed here is similar to FETCH_ADVANCE_INST, except the
130 * src and dest registers are parameterized (not hard-wired to rPC and rINST).
131 */
132#define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \
133 ldrh _dreg, [_sreg, #(_count*2)]!
134
135/*
136 * Fetch the next instruction from an offset specified by _reg. Updates
137 * rPC to point to the next instruction. "_reg" must specify the distance
138 * in bytes, *not* 16-bit code units, and may be a signed value.
139 *
140 * We want to write "ldrh rINST, [rPC, _reg, lsl #2]!", but some of the
141 * bits that hold the shift distance are used for the half/byte/sign flags.
142 * In some cases we can pre-double _reg for free, so we require a byte offset
143 * here.
144 */
145#define FETCH_ADVANCE_INST_RB(_reg) ldrh rINST, [rPC, _reg]!
146
147/*
148 * Fetch a half-word code unit from an offset past the current PC. The
149 * "_count" value is in 16-bit code units. Does not advance rPC.
150 *
151 * The "_S" variant works the same but treats the value as signed.
152 */
153#define FETCH(_reg, _count) ldrh _reg, [rPC, #(_count*2)]
154#define FETCH_S(_reg, _count) ldrsh _reg, [rPC, #(_count*2)]
155
156/*
157 * Fetch one byte from an offset past the current PC. Pass in the same
158 * "_count" as you would for FETCH, and an additional 0/1 indicating which
159 * byte of the halfword you want (lo/hi).
160 */
161#define FETCH_B(_reg, _count, _byte) ldrb _reg, [rPC, #(_count*2+_byte)]
162
163/*
164 * Put the instruction's opcode field into the specified register.
165 */
166#define GET_INST_OPCODE(_reg) and _reg, rINST, #255
167
168/*
169 * Put the prefetched instruction's opcode field into the specified register.
170 */
171#define GET_PREFETCHED_OPCODE(_oreg, _ireg) and _oreg, _ireg, #255
172
173/*
174 * Begin executing the opcode in _reg. Because this only jumps within the
175 * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork.
176 */
177#define GOTO_OPCODE(_reg) add pc, rIBASE, _reg, lsl #6
178#define GOTO_OPCODE_IFEQ(_reg) addeq pc, rIBASE, _reg, lsl #6
179#define GOTO_OPCODE_IFNE(_reg) addne pc, rIBASE, _reg, lsl #6
180
181/*
182 * Get/set the 32-bit value from a Dalvik register.
183 */
184#define GET_VREG(_reg, _vreg) ldr _reg, [rFP, _vreg, lsl #2]
185#define SET_VREG(_reg, _vreg) str _reg, [rFP, _vreg, lsl #2]
186
187#if defined(WITH_JIT)
Andy McFaddena5069fb2009-06-19 15:20:12 -0700188#define GET_JIT_PROF_TABLE(_reg) ldr _reg,[rGLUE,#offGlue_pJitProfTable]
Bill Buzbeed7269912009-11-10 14:31:32 -0800189#define GET_JIT_THRESHOLD(_reg) ldr _reg,[rGLUE,#offGlue_jitThreshold]
Andy McFaddena5069fb2009-06-19 15:20:12 -0700190#endif
191
192/*
193 * Convert a virtual register index into an address.
194 */
195#define VREG_INDEX_TO_ADDR(_reg, _vreg) \
196 add _reg, rFP, _vreg, lsl #2
197
198/*
199 * This is a #include, not a %include, because we want the C pre-processor
200 * to expand the macros into assembler assignment statements.
201 */
202#include "../common/asm-constants.h"
203
Ben Cheng7b133ef2010-02-04 16:15:59 -0800204#if defined(WITH_JIT)
205#include "../common/jit-config.h"
206#endif
Andy McFaddena5069fb2009-06-19 15:20:12 -0700207
208/* File: armv5te/platform.S */
209/*
210 * ===========================================================================
211 * CPU-version-specific defines
212 * ===========================================================================
213 */
214
215/*
216 * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5. Essentially a
217 * one-way branch.
218 *
219 * May modify IP. Does not modify LR.
220 */
221.macro LDR_PC source
222 ldr pc, \source
223.endm
224
225/*
226 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5.
227 * Jump to subroutine.
228 *
229 * May modify IP and LR.
230 */
231.macro LDR_PC_LR source
232 mov lr, pc
233 ldr pc, \source
234.endm
235
236/*
237 * Macro for "LDMFD SP!, {...regs...,PC}".
238 *
239 * May modify IP and LR.
240 */
241.macro LDMFD_PC regs
242 ldmfd sp!, {\regs,pc}
243.endm
244
245
246/* File: armv5te/entry.S */
247/*
248 * Copyright (C) 2008 The Android Open Source Project
249 *
250 * Licensed under the Apache License, Version 2.0 (the "License");
251 * you may not use this file except in compliance with the License.
252 * You may obtain a copy of the License at
253 *
254 * http://www.apache.org/licenses/LICENSE-2.0
255 *
256 * Unless required by applicable law or agreed to in writing, software
257 * distributed under the License is distributed on an "AS IS" BASIS,
258 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
259 * See the License for the specific language governing permissions and
260 * limitations under the License.
261 */
262/*
263 * Interpreter entry point.
264 */
265
266/*
267 * We don't have formal stack frames, so gdb scans upward in the code
268 * to find the start of the function (a label with the %function type),
269 * and then looks at the next few instructions to figure out what
270 * got pushed onto the stack. From this it figures out how to restore
271 * the registers, including PC, for the previous stack frame. If gdb
272 * sees a non-function label, it stops scanning, so either we need to
273 * have nothing but assembler-local labels between the entry point and
274 * the break, or we need to fake it out.
275 *
276 * When this is defined, we add some stuff to make gdb less confused.
277 */
278#define ASSIST_DEBUGGER 1
279
280 .text
281 .align 2
282 .global dvmMterpStdRun
283 .type dvmMterpStdRun, %function
284
285/*
286 * On entry:
287 * r0 MterpGlue* glue
288 *
289 * This function returns a boolean "changeInterp" value. The return comes
290 * via a call to dvmMterpStdBail().
291 */
292dvmMterpStdRun:
293#define MTERP_ENTRY1 \
294 .save {r4-r10,fp,lr}; \
295 stmfd sp!, {r4-r10,fp,lr} @ save 9 regs
296#define MTERP_ENTRY2 \
297 .pad #4; \
298 sub sp, sp, #4 @ align 64
299
300 .fnstart
301 MTERP_ENTRY1
302 MTERP_ENTRY2
303
304 /* save stack pointer, add magic word for debuggerd */
305 str sp, [r0, #offGlue_bailPtr] @ save SP for eventual return
306
307 /* set up "named" registers, figure out entry point */
308 mov rGLUE, r0 @ set rGLUE
Bill Buzbee51ae4422010-03-12 15:15:35 -0800309 ldr r1, [r0, #offGlue_entryPoint] @ enum is 4 bytes in aapcs-EABI
Andy McFaddena5069fb2009-06-19 15:20:12 -0700310 LOAD_PC_FP_FROM_GLUE() @ load rPC and rFP from "glue"
311 adr rIBASE, dvmAsmInstructionStart @ set rIBASE
312 cmp r1, #kInterpEntryInstr @ usual case?
313 bne .Lnot_instr @ no, handle it
314
315#if defined(WITH_JIT)
Ben Chengd5adae12010-03-26 17:45:28 -0700316.LentryInstr:
Ben Cheng7a0bcd02010-01-22 16:45:45 -0800317 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
Andy McFaddena5069fb2009-06-19 15:20:12 -0700318 /* Entry is always a possible trace start */
319 GET_JIT_PROF_TABLE(r0)
320 FETCH_INST()
Ben Cheng7a0bcd02010-01-22 16:45:45 -0800321 mov r1, #0 @ prepare the value for the new state
322 str r1, [r10, #offThread_inJitCodeCache] @ back to the interp land
Andy McFaddena5069fb2009-06-19 15:20:12 -0700323 cmp r0,#0
324 bne common_updateProfile
325 GET_INST_OPCODE(ip)
326 GOTO_OPCODE(ip)
327#else
328 /* start executing the instruction at rPC */
329 FETCH_INST() @ load rINST from rPC
330 GET_INST_OPCODE(ip) @ extract opcode from rINST
331 GOTO_OPCODE(ip) @ jump to next instruction
332#endif
333
334.Lnot_instr:
335 cmp r1, #kInterpEntryReturn @ were we returning from a method?
336 beq common_returnFromMethod
337
338.Lnot_return:
339 cmp r1, #kInterpEntryThrow @ were we throwing an exception?
340 beq common_exceptionThrown
341
342#if defined(WITH_JIT)
343.Lnot_throw:
Ben Chengd5adae12010-03-26 17:45:28 -0700344 ldr r10,[rGLUE, #offGlue_jitResumeNPC]
345 ldr r2,[rGLUE, #offGlue_jitResumeDPC]
Andy McFaddena5069fb2009-06-19 15:20:12 -0700346 cmp r1, #kInterpEntryResume @ resuming after Jit single-step?
347 bne .Lbad_arg
348 cmp rPC,r2
Ben Chengd5adae12010-03-26 17:45:28 -0700349 bne .LentryInstr @ must have branched, don't resume
350#if defined(WITH_SELF_VERIFICATION)
351 @ glue->entryPoint will be set in dvmSelfVerificationSaveState
352 b jitSVShadowRunStart @ re-enter the translation after the
353 @ single-stepped instruction
354 @noreturn
355#endif
Andy McFaddena5069fb2009-06-19 15:20:12 -0700356 mov r1, #kInterpEntryInstr
Bill Buzbee51ae4422010-03-12 15:15:35 -0800357 str r1, [rGLUE, #offGlue_entryPoint]
Ben Chengd5adae12010-03-26 17:45:28 -0700358 bx r10 @ re-enter the translation
Andy McFaddena5069fb2009-06-19 15:20:12 -0700359#endif
360
361.Lbad_arg:
362 ldr r0, strBadEntryPoint
363 @ r1 holds value of entryPoint
364 bl printf
365 bl dvmAbort
366 .fnend
367
368
369 .global dvmMterpStdBail
370 .type dvmMterpStdBail, %function
371
372/*
373 * Restore the stack pointer and PC from the save point established on entry.
374 * This is essentially the same as a longjmp, but should be cheaper. The
375 * last instruction causes us to return to whoever called dvmMterpStdRun.
376 *
377 * We pushed some registers on the stack in dvmMterpStdRun, then saved
378 * SP and LR. Here we restore SP, restore the registers, and then restore
379 * LR to PC.
380 *
381 * On entry:
382 * r0 MterpGlue* glue
383 * r1 bool changeInterp
384 */
385dvmMterpStdBail:
386 ldr sp, [r0, #offGlue_bailPtr] @ sp<- saved SP
387 mov r0, r1 @ return the changeInterp value
388 add sp, sp, #4 @ un-align 64
389 LDMFD_PC "r4-r10,fp" @ restore 9 regs and return
390
391
392/*
393 * String references.
394 */
395strBadEntryPoint:
396 .word .LstrBadEntryPoint
397
398
399
400 .global dvmAsmInstructionStart
401 .type dvmAsmInstructionStart, %function
402dvmAsmInstructionStart = .L_OP_NOP
403 .text
404
405/* ------------------------------ */
406 .balign 64
407.L_OP_NOP: /* 0x00 */
408/* File: armv5te/OP_NOP.S */
409 FETCH_ADVANCE_INST(1) @ advance to next instr, load rINST
410 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
411 GOTO_OPCODE(ip) @ execute it
412
413#ifdef ASSIST_DEBUGGER
414 /* insert fake function header to help gdb find the stack frame */
415 .type dalvik_inst, %function
416dalvik_inst:
417 .fnstart
418 MTERP_ENTRY1
419 MTERP_ENTRY2
420 .fnend
421#endif
422
423
424/* ------------------------------ */
425 .balign 64
426.L_OP_MOVE: /* 0x01 */
427/* File: armv6t2/OP_MOVE.S */
428 /* for move, move-object, long-to-int */
429 /* op vA, vB */
430 mov r1, rINST, lsr #12 @ r1<- B from 15:12
431 ubfx r0, rINST, #8, #4 @ r0<- A from 11:8
432 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
433 GET_VREG(r2, r1) @ r2<- fp[B]
434 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
435 SET_VREG(r2, r0) @ fp[A]<- r2
436 GOTO_OPCODE(ip) @ execute next instruction
437
438
439/* ------------------------------ */
440 .balign 64
441.L_OP_MOVE_FROM16: /* 0x02 */
442/* File: armv5te/OP_MOVE_FROM16.S */
443 /* for: move/from16, move-object/from16 */
444 /* op vAA, vBBBB */
445 FETCH(r1, 1) @ r1<- BBBB
446 mov r0, rINST, lsr #8 @ r0<- AA
447 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
448 GET_VREG(r2, r1) @ r2<- fp[BBBB]
449 GET_INST_OPCODE(ip) @ extract opcode from rINST
450 SET_VREG(r2, r0) @ fp[AA]<- r2
451 GOTO_OPCODE(ip) @ jump to next instruction
452
453
454/* ------------------------------ */
455 .balign 64
456.L_OP_MOVE_16: /* 0x03 */
457/* File: armv5te/OP_MOVE_16.S */
458 /* for: move/16, move-object/16 */
459 /* op vAAAA, vBBBB */
460 FETCH(r1, 2) @ r1<- BBBB
461 FETCH(r0, 1) @ r0<- AAAA
462 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
463 GET_VREG(r2, r1) @ r2<- fp[BBBB]
464 GET_INST_OPCODE(ip) @ extract opcode from rINST
465 SET_VREG(r2, r0) @ fp[AAAA]<- r2
466 GOTO_OPCODE(ip) @ jump to next instruction
467
468
469/* ------------------------------ */
470 .balign 64
471.L_OP_MOVE_WIDE: /* 0x04 */
472/* File: armv6t2/OP_MOVE_WIDE.S */
473 /* move-wide vA, vB */
474 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
475 mov r3, rINST, lsr #12 @ r3<- B
476 ubfx r2, rINST, #8, #4 @ r2<- A
477 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
478 add r2, rFP, r2, lsl #2 @ r2<- &fp[A]
479 ldmia r3, {r0-r1} @ r0/r1<- fp[B]
480 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
481 GET_INST_OPCODE(ip) @ extract opcode from rINST
482 stmia r2, {r0-r1} @ fp[A]<- r0/r1
483 GOTO_OPCODE(ip) @ jump to next instruction
484
485
486/* ------------------------------ */
487 .balign 64
488.L_OP_MOVE_WIDE_FROM16: /* 0x05 */
489/* File: armv5te/OP_MOVE_WIDE_FROM16.S */
490 /* move-wide/from16 vAA, vBBBB */
491 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
492 FETCH(r3, 1) @ r3<- BBBB
493 mov r2, rINST, lsr #8 @ r2<- AA
494 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB]
495 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA]
496 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB]
497 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
498 GET_INST_OPCODE(ip) @ extract opcode from rINST
499 stmia r2, {r0-r1} @ fp[AA]<- r0/r1
500 GOTO_OPCODE(ip) @ jump to next instruction
501
502
503/* ------------------------------ */
504 .balign 64
505.L_OP_MOVE_WIDE_16: /* 0x06 */
506/* File: armv5te/OP_MOVE_WIDE_16.S */
507 /* move-wide/16 vAAAA, vBBBB */
508 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
509 FETCH(r3, 2) @ r3<- BBBB
510 FETCH(r2, 1) @ r2<- AAAA
511 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB]
512 add r2, rFP, r2, lsl #2 @ r2<- &fp[AAAA]
513 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB]
514 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
515 GET_INST_OPCODE(ip) @ extract opcode from rINST
516 stmia r2, {r0-r1} @ fp[AAAA]<- r0/r1
517 GOTO_OPCODE(ip) @ jump to next instruction
518
519
520/* ------------------------------ */
521 .balign 64
522.L_OP_MOVE_OBJECT: /* 0x07 */
523/* File: armv5te/OP_MOVE_OBJECT.S */
524/* File: armv5te/OP_MOVE.S */
525 /* for move, move-object, long-to-int */
526 /* op vA, vB */
527 mov r1, rINST, lsr #12 @ r1<- B from 15:12
528 mov r0, rINST, lsr #8 @ r0<- A from 11:8
529 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
530 GET_VREG(r2, r1) @ r2<- fp[B]
531 and r0, r0, #15
532 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
533 SET_VREG(r2, r0) @ fp[A]<- r2
534 GOTO_OPCODE(ip) @ execute next instruction
535
536
537
538/* ------------------------------ */
539 .balign 64
540.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
541/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */
542/* File: armv5te/OP_MOVE_FROM16.S */
543 /* for: move/from16, move-object/from16 */
544 /* op vAA, vBBBB */
545 FETCH(r1, 1) @ r1<- BBBB
546 mov r0, rINST, lsr #8 @ r0<- AA
547 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
548 GET_VREG(r2, r1) @ r2<- fp[BBBB]
549 GET_INST_OPCODE(ip) @ extract opcode from rINST
550 SET_VREG(r2, r0) @ fp[AA]<- r2
551 GOTO_OPCODE(ip) @ jump to next instruction
552
553
554
555/* ------------------------------ */
556 .balign 64
557.L_OP_MOVE_OBJECT_16: /* 0x09 */
558/* File: armv5te/OP_MOVE_OBJECT_16.S */
559/* File: armv5te/OP_MOVE_16.S */
560 /* for: move/16, move-object/16 */
561 /* op vAAAA, vBBBB */
562 FETCH(r1, 2) @ r1<- BBBB
563 FETCH(r0, 1) @ r0<- AAAA
564 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
565 GET_VREG(r2, r1) @ r2<- fp[BBBB]
566 GET_INST_OPCODE(ip) @ extract opcode from rINST
567 SET_VREG(r2, r0) @ fp[AAAA]<- r2
568 GOTO_OPCODE(ip) @ jump to next instruction
569
570
571
572/* ------------------------------ */
573 .balign 64
574.L_OP_MOVE_RESULT: /* 0x0a */
575/* File: armv5te/OP_MOVE_RESULT.S */
576 /* for: move-result, move-result-object */
577 /* op vAA */
578 mov r2, rINST, lsr #8 @ r2<- AA
579 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
580 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i
581 GET_INST_OPCODE(ip) @ extract opcode from rINST
582 SET_VREG(r0, r2) @ fp[AA]<- r0
583 GOTO_OPCODE(ip) @ jump to next instruction
584
585
586/* ------------------------------ */
587 .balign 64
588.L_OP_MOVE_RESULT_WIDE: /* 0x0b */
589/* File: armv5te/OP_MOVE_RESULT_WIDE.S */
590 /* move-result-wide vAA */
591 mov r2, rINST, lsr #8 @ r2<- AA
592 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval
593 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA]
594 ldmia r3, {r0-r1} @ r0/r1<- retval.j
595 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
596 GET_INST_OPCODE(ip) @ extract opcode from rINST
597 stmia r2, {r0-r1} @ fp[AA]<- r0/r1
598 GOTO_OPCODE(ip) @ jump to next instruction
599
600
601/* ------------------------------ */
602 .balign 64
603.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
604/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */
605/* File: armv5te/OP_MOVE_RESULT.S */
606 /* for: move-result, move-result-object */
607 /* op vAA */
608 mov r2, rINST, lsr #8 @ r2<- AA
609 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
610 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i
611 GET_INST_OPCODE(ip) @ extract opcode from rINST
612 SET_VREG(r0, r2) @ fp[AA]<- r0
613 GOTO_OPCODE(ip) @ jump to next instruction
614
615
616
617/* ------------------------------ */
618 .balign 64
619.L_OP_MOVE_EXCEPTION: /* 0x0d */
620/* File: armv5te/OP_MOVE_EXCEPTION.S */
621 /* move-exception vAA */
622 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
623 mov r2, rINST, lsr #8 @ r2<- AA
624 ldr r3, [r0, #offThread_exception] @ r3<- dvmGetException bypass
625 mov r1, #0 @ r1<- 0
626 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
627 SET_VREG(r3, r2) @ fp[AA]<- exception obj
628 GET_INST_OPCODE(ip) @ extract opcode from rINST
629 str r1, [r0, #offThread_exception] @ dvmClearException bypass
630 GOTO_OPCODE(ip) @ jump to next instruction
631
632
633/* ------------------------------ */
634 .balign 64
635.L_OP_RETURN_VOID: /* 0x0e */
636/* File: armv5te/OP_RETURN_VOID.S */
637 b common_returnFromMethod
638
639
640/* ------------------------------ */
641 .balign 64
642.L_OP_RETURN: /* 0x0f */
643/* File: armv5te/OP_RETURN.S */
644 /*
645 * Return a 32-bit value. Copies the return value into the "glue"
646 * structure, then jumps to the return handler.
647 *
648 * for: return, return-object
649 */
650 /* op vAA */
651 mov r2, rINST, lsr #8 @ r2<- AA
652 GET_VREG(r0, r2) @ r0<- vAA
653 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
654 b common_returnFromMethod
655
656
657/* ------------------------------ */
658 .balign 64
659.L_OP_RETURN_WIDE: /* 0x10 */
660/* File: armv5te/OP_RETURN_WIDE.S */
661 /*
662 * Return a 64-bit value. Copies the return value into the "glue"
663 * structure, then jumps to the return handler.
664 */
665 /* return-wide vAA */
666 mov r2, rINST, lsr #8 @ r2<- AA
667 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA]
668 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval
669 ldmia r2, {r0-r1} @ r0/r1 <- vAA/vAA+1
670 stmia r3, {r0-r1} @ retval<- r0/r1
671 b common_returnFromMethod
672
673
674/* ------------------------------ */
675 .balign 64
676.L_OP_RETURN_OBJECT: /* 0x11 */
677/* File: armv5te/OP_RETURN_OBJECT.S */
678/* File: armv5te/OP_RETURN.S */
679 /*
680 * Return a 32-bit value. Copies the return value into the "glue"
681 * structure, then jumps to the return handler.
682 *
683 * for: return, return-object
684 */
685 /* op vAA */
686 mov r2, rINST, lsr #8 @ r2<- AA
687 GET_VREG(r0, r2) @ r0<- vAA
688 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
689 b common_returnFromMethod
690
691
692
693/* ------------------------------ */
694 .balign 64
695.L_OP_CONST_4: /* 0x12 */
696/* File: armv6t2/OP_CONST_4.S */
697 /* const/4 vA, #+B */
698 mov r1, rINST, lsl #16 @ r1<- Bxxx0000
699 ubfx r0, rINST, #8, #4 @ r0<- A
700 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
701 mov r1, r1, asr #28 @ r1<- sssssssB (sign-extended)
702 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
703 SET_VREG(r1, r0) @ fp[A]<- r1
704 GOTO_OPCODE(ip) @ execute next instruction
705
706
707/* ------------------------------ */
708 .balign 64
709.L_OP_CONST_16: /* 0x13 */
710/* File: armv5te/OP_CONST_16.S */
711 /* const/16 vAA, #+BBBB */
712 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended)
713 mov r3, rINST, lsr #8 @ r3<- AA
714 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
715 SET_VREG(r0, r3) @ vAA<- r0
716 GET_INST_OPCODE(ip) @ extract opcode from rINST
717 GOTO_OPCODE(ip) @ jump to next instruction
718
719
720/* ------------------------------ */
721 .balign 64
722.L_OP_CONST: /* 0x14 */
723/* File: armv5te/OP_CONST.S */
724 /* const vAA, #+BBBBbbbb */
725 mov r3, rINST, lsr #8 @ r3<- AA
726 FETCH(r0, 1) @ r0<- bbbb (low)
727 FETCH(r1, 2) @ r1<- BBBB (high)
728 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
729 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb
730 GET_INST_OPCODE(ip) @ extract opcode from rINST
731 SET_VREG(r0, r3) @ vAA<- r0
732 GOTO_OPCODE(ip) @ jump to next instruction
733
734
735/* ------------------------------ */
736 .balign 64
737.L_OP_CONST_HIGH16: /* 0x15 */
738/* File: armv5te/OP_CONST_HIGH16.S */
739 /* const/high16 vAA, #+BBBB0000 */
740 FETCH(r0, 1) @ r0<- 0000BBBB (zero-extended)
741 mov r3, rINST, lsr #8 @ r3<- AA
742 mov r0, r0, lsl #16 @ r0<- BBBB0000
743 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
744 SET_VREG(r0, r3) @ vAA<- r0
745 GET_INST_OPCODE(ip) @ extract opcode from rINST
746 GOTO_OPCODE(ip) @ jump to next instruction
747
748
749/* ------------------------------ */
750 .balign 64
751.L_OP_CONST_WIDE_16: /* 0x16 */
752/* File: armv5te/OP_CONST_WIDE_16.S */
753 /* const-wide/16 vAA, #+BBBB */
754 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended)
755 mov r3, rINST, lsr #8 @ r3<- AA
756 mov r1, r0, asr #31 @ r1<- ssssssss
757 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
758 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA]
759 GET_INST_OPCODE(ip) @ extract opcode from rINST
760 stmia r3, {r0-r1} @ vAA<- r0/r1
761 GOTO_OPCODE(ip) @ jump to next instruction
762
763
764/* ------------------------------ */
765 .balign 64
766.L_OP_CONST_WIDE_32: /* 0x17 */
767/* File: armv5te/OP_CONST_WIDE_32.S */
768 /* const-wide/32 vAA, #+BBBBbbbb */
769 FETCH(r0, 1) @ r0<- 0000bbbb (low)
770 mov r3, rINST, lsr #8 @ r3<- AA
771 FETCH_S(r2, 2) @ r2<- ssssBBBB (high)
772 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
773 orr r0, r0, r2, lsl #16 @ r0<- BBBBbbbb
774 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA]
775 mov r1, r0, asr #31 @ r1<- ssssssss
776 GET_INST_OPCODE(ip) @ extract opcode from rINST
777 stmia r3, {r0-r1} @ vAA<- r0/r1
778 GOTO_OPCODE(ip) @ jump to next instruction
779
780
781/* ------------------------------ */
782 .balign 64
783.L_OP_CONST_WIDE: /* 0x18 */
784/* File: armv5te/OP_CONST_WIDE.S */
785 /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
786 FETCH(r0, 1) @ r0<- bbbb (low)
787 FETCH(r1, 2) @ r1<- BBBB (low middle)
788 FETCH(r2, 3) @ r2<- hhhh (high middle)
789 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb (low word)
790 FETCH(r3, 4) @ r3<- HHHH (high)
791 mov r9, rINST, lsr #8 @ r9<- AA
792 orr r1, r2, r3, lsl #16 @ r1<- HHHHhhhh (high word)
793 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST
794 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
795 GET_INST_OPCODE(ip) @ extract opcode from rINST
796 stmia r9, {r0-r1} @ vAA<- r0/r1
797 GOTO_OPCODE(ip) @ jump to next instruction
798
799
800/* ------------------------------ */
801 .balign 64
802.L_OP_CONST_WIDE_HIGH16: /* 0x19 */
803/* File: armv5te/OP_CONST_WIDE_HIGH16.S */
804 /* const-wide/high16 vAA, #+BBBB000000000000 */
805 FETCH(r1, 1) @ r1<- 0000BBBB (zero-extended)
806 mov r3, rINST, lsr #8 @ r3<- AA
807 mov r0, #0 @ r0<- 00000000
808 mov r1, r1, lsl #16 @ r1<- BBBB0000
809 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
810 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA]
811 GET_INST_OPCODE(ip) @ extract opcode from rINST
812 stmia r3, {r0-r1} @ vAA<- r0/r1
813 GOTO_OPCODE(ip) @ jump to next instruction
814
815
816/* ------------------------------ */
817 .balign 64
818.L_OP_CONST_STRING: /* 0x1a */
819/* File: armv5te/OP_CONST_STRING.S */
820 /* const/string vAA, String@BBBB */
821 FETCH(r1, 1) @ r1<- BBBB
822 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex
823 mov r9, rINST, lsr #8 @ r9<- AA
824 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings
825 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB]
826 cmp r0, #0 @ not yet resolved?
827 beq .LOP_CONST_STRING_resolve
828 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
829 GET_INST_OPCODE(ip) @ extract opcode from rINST
830 SET_VREG(r0, r9) @ vAA<- r0
831 GOTO_OPCODE(ip) @ jump to next instruction
832
833/* ------------------------------ */
834 .balign 64
835.L_OP_CONST_STRING_JUMBO: /* 0x1b */
836/* File: armv5te/OP_CONST_STRING_JUMBO.S */
837 /* const/string vAA, String@BBBBBBBB */
838 FETCH(r0, 1) @ r0<- bbbb (low)
839 FETCH(r1, 2) @ r1<- BBBB (high)
840 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex
841 mov r9, rINST, lsr #8 @ r9<- AA
842 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings
843 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb
844 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB]
845 cmp r0, #0
846 beq .LOP_CONST_STRING_JUMBO_resolve
847 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
848 GET_INST_OPCODE(ip) @ extract opcode from rINST
849 SET_VREG(r0, r9) @ vAA<- r0
850 GOTO_OPCODE(ip) @ jump to next instruction
851
852/* ------------------------------ */
853 .balign 64
854.L_OP_CONST_CLASS: /* 0x1c */
855/* File: armv5te/OP_CONST_CLASS.S */
856 /* const/class vAA, Class@BBBB */
857 FETCH(r1, 1) @ r1<- BBBB
858 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex
859 mov r9, rINST, lsr #8 @ r9<- AA
860 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- dvmDex->pResClasses
861 ldr r0, [r2, r1, lsl #2] @ r0<- pResClasses[BBBB]
862 cmp r0, #0 @ not yet resolved?
863 beq .LOP_CONST_CLASS_resolve
864 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
865 GET_INST_OPCODE(ip) @ extract opcode from rINST
866 SET_VREG(r0, r9) @ vAA<- r0
867 GOTO_OPCODE(ip) @ jump to next instruction
868
869/* ------------------------------ */
870 .balign 64
871.L_OP_MONITOR_ENTER: /* 0x1d */
872/* File: armv5te/OP_MONITOR_ENTER.S */
873 /*
874 * Synchronize on an object.
875 */
876 /* monitor-enter vAA */
877 mov r2, rINST, lsr #8 @ r2<- AA
878 GET_VREG(r1, r2) @ r1<- vAA (object)
879 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
880 cmp r1, #0 @ null object?
881 EXPORT_PC() @ need for precise GC, MONITOR_TRACKING
882 beq common_errNullObject @ null object, throw an exception
883 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
884 bl dvmLockObject @ call(self, obj)
885#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */
886 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
887 ldr r1, [r0, #offThread_exception] @ check for exception
888 cmp r1, #0
889 bne common_exceptionThrown @ exception raised, bail out
890#endif
891 GET_INST_OPCODE(ip) @ extract opcode from rINST
892 GOTO_OPCODE(ip) @ jump to next instruction
893
894
895/* ------------------------------ */
896 .balign 64
897.L_OP_MONITOR_EXIT: /* 0x1e */
898/* File: armv5te/OP_MONITOR_EXIT.S */
899 /*
900 * Unlock an object.
901 *
902 * Exceptions that occur when unlocking a monitor need to appear as
903 * if they happened at the following instruction. See the Dalvik
904 * instruction spec.
905 */
906 /* monitor-exit vAA */
907 mov r2, rINST, lsr #8 @ r2<- AA
908 EXPORT_PC() @ before fetch: export the PC
909 GET_VREG(r1, r2) @ r1<- vAA (object)
910 cmp r1, #0 @ null object?
Bill Buzbee6bbdd6b2010-02-16 14:40:01 -0800911 beq 1f @ yes
Andy McFaddena5069fb2009-06-19 15:20:12 -0700912 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
913 bl dvmUnlockObject @ r0<- success for unlock(self, obj)
914 cmp r0, #0 @ failed?
Andy McFaddena5069fb2009-06-19 15:20:12 -0700915 FETCH_ADVANCE_INST(1) @ before throw: advance rPC, load rINST
Bill Buzbee6bbdd6b2010-02-16 14:40:01 -0800916 beq common_exceptionThrown @ yes, exception is pending
Andy McFaddena5069fb2009-06-19 15:20:12 -0700917 GET_INST_OPCODE(ip) @ extract opcode from rINST
918 GOTO_OPCODE(ip) @ jump to next instruction
Bill Buzbee6bbdd6b2010-02-16 14:40:01 -08009191:
920 FETCH_ADVANCE_INST(1) @ advance before throw
921 b common_errNullObject
Andy McFaddena5069fb2009-06-19 15:20:12 -0700922
923
924/* ------------------------------ */
925 .balign 64
926.L_OP_CHECK_CAST: /* 0x1f */
927/* File: armv5te/OP_CHECK_CAST.S */
928 /*
929 * Check to see if a cast from one class to another is allowed.
930 */
931 /* check-cast vAA, class@BBBB */
932 mov r3, rINST, lsr #8 @ r3<- AA
933 FETCH(r2, 1) @ r2<- BBBB
934 GET_VREG(r9, r3) @ r9<- object
935 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- pDvmDex
936 cmp r9, #0 @ is object null?
937 ldr r0, [r0, #offDvmDex_pResClasses] @ r0<- pDvmDex->pResClasses
938 beq .LOP_CHECK_CAST_okay @ null obj, cast always succeeds
939 ldr r1, [r0, r2, lsl #2] @ r1<- resolved class
940 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz
941 cmp r1, #0 @ have we resolved this before?
942 beq .LOP_CHECK_CAST_resolve @ not resolved, do it now
943.LOP_CHECK_CAST_resolved:
944 cmp r0, r1 @ same class (trivial success)?
945 bne .LOP_CHECK_CAST_fullcheck @ no, do full check
946.LOP_CHECK_CAST_okay:
947 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
948 GET_INST_OPCODE(ip) @ extract opcode from rINST
949 GOTO_OPCODE(ip) @ jump to next instruction
950
951/* ------------------------------ */
952 .balign 64
953.L_OP_INSTANCE_OF: /* 0x20 */
954/* File: armv5te/OP_INSTANCE_OF.S */
955 /*
956 * Check to see if an object reference is an instance of a class.
957 *
958 * Most common situation is a non-null object, being compared against
959 * an already-resolved class.
960 */
961 /* instance-of vA, vB, class@CCCC */
962 mov r3, rINST, lsr #12 @ r3<- B
963 mov r9, rINST, lsr #8 @ r9<- A+
964 GET_VREG(r0, r3) @ r0<- vB (object)
965 and r9, r9, #15 @ r9<- A
966 cmp r0, #0 @ is object null?
967 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- pDvmDex
968 beq .LOP_INSTANCE_OF_store @ null obj, not an instance, store r0
969 FETCH(r3, 1) @ r3<- CCCC
970 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- pDvmDex->pResClasses
971 ldr r1, [r2, r3, lsl #2] @ r1<- resolved class
972 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz
973 cmp r1, #0 @ have we resolved this before?
974 beq .LOP_INSTANCE_OF_resolve @ not resolved, do it now
975.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class
976 cmp r0, r1 @ same class (trivial success)?
977 beq .LOP_INSTANCE_OF_trivial @ yes, trivial finish
978 b .LOP_INSTANCE_OF_fullcheck @ no, do full check
979
980/* ------------------------------ */
981 .balign 64
982.L_OP_ARRAY_LENGTH: /* 0x21 */
983/* File: armv6t2/OP_ARRAY_LENGTH.S */
984 /*
985 * Return the length of an array.
986 */
987 mov r1, rINST, lsr #12 @ r1<- B
988 ubfx r2, rINST, #8, #4 @ r2<- A
989 GET_VREG(r0, r1) @ r0<- vB (object ref)
990 cmp r0, #0 @ is object null?
991 beq common_errNullObject @ yup, fail
992 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
993 ldr r3, [r0, #offArrayObject_length] @ r3<- array length
994 GET_INST_OPCODE(ip) @ extract opcode from rINST
995 SET_VREG(r3, r2) @ vB<- length
996 GOTO_OPCODE(ip) @ jump to next instruction
997
998
999/* ------------------------------ */
1000 .balign 64
1001.L_OP_NEW_INSTANCE: /* 0x22 */
1002/* File: armv5te/OP_NEW_INSTANCE.S */
1003 /*
1004 * Create a new instance of a class.
1005 */
1006 /* new-instance vAA, class@BBBB */
1007 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
1008 FETCH(r1, 1) @ r1<- BBBB
1009 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses
1010 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class
1011 EXPORT_PC() @ req'd for init, resolve, alloc
1012 cmp r0, #0 @ already resolved?
1013 beq .LOP_NEW_INSTANCE_resolve @ no, resolve it now
1014.LOP_NEW_INSTANCE_resolved: @ r0=class
1015 ldrb r1, [r0, #offClassObject_status] @ r1<- ClassStatus enum
1016 cmp r1, #CLASS_INITIALIZED @ has class been initialized?
1017 bne .LOP_NEW_INSTANCE_needinit @ no, init class now
1018.LOP_NEW_INSTANCE_initialized: @ r0=class
1019 mov r1, #ALLOC_DONT_TRACK @ flags for alloc call
1020 bl dvmAllocObject @ r0<- new object
1021 b .LOP_NEW_INSTANCE_finish @ continue
1022
1023/* ------------------------------ */
1024 .balign 64
1025.L_OP_NEW_ARRAY: /* 0x23 */
1026/* File: armv5te/OP_NEW_ARRAY.S */
1027 /*
1028 * Allocate an array of objects, specified with the array class
1029 * and a count.
1030 *
1031 * The verifier guarantees that this is an array class, so we don't
1032 * check for it here.
1033 */
1034 /* new-array vA, vB, class@CCCC */
1035 mov r0, rINST, lsr #12 @ r0<- B
1036 FETCH(r2, 1) @ r2<- CCCC
1037 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
1038 GET_VREG(r1, r0) @ r1<- vB (array length)
1039 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses
1040 cmp r1, #0 @ check length
1041 ldr r0, [r3, r2, lsl #2] @ r0<- resolved class
1042 bmi common_errNegativeArraySize @ negative length, bail
1043 cmp r0, #0 @ already resolved?
1044 EXPORT_PC() @ req'd for resolve, alloc
1045 bne .LOP_NEW_ARRAY_finish @ resolved, continue
1046 b .LOP_NEW_ARRAY_resolve @ do resolve now
1047
1048/* ------------------------------ */
1049 .balign 64
1050.L_OP_FILLED_NEW_ARRAY: /* 0x24 */
1051/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1052 /*
1053 * Create a new array with elements filled from registers.
1054 *
1055 * for: filled-new-array, filled-new-array/range
1056 */
1057 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1058 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1059 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
1060 FETCH(r1, 1) @ r1<- BBBB
1061 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses
1062 EXPORT_PC() @ need for resolve and alloc
1063 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class
1064 mov r10, rINST, lsr #8 @ r10<- AA or BA
1065 cmp r0, #0 @ already resolved?
1066 bne .LOP_FILLED_NEW_ARRAY_continue @ yes, continue on
10678: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1068 mov r2, #0 @ r2<- false
1069 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
1070 bl dvmResolveClass @ r0<- call(clazz, ref)
1071 cmp r0, #0 @ got null?
1072 beq common_exceptionThrown @ yes, handle exception
1073 b .LOP_FILLED_NEW_ARRAY_continue
1074
1075/* ------------------------------ */
1076 .balign 64
1077.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
1078/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */
1079/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1080 /*
1081 * Create a new array with elements filled from registers.
1082 *
1083 * for: filled-new-array, filled-new-array/range
1084 */
1085 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1086 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1087 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
1088 FETCH(r1, 1) @ r1<- BBBB
1089 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses
1090 EXPORT_PC() @ need for resolve and alloc
1091 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class
1092 mov r10, rINST, lsr #8 @ r10<- AA or BA
1093 cmp r0, #0 @ already resolved?
1094 bne .LOP_FILLED_NEW_ARRAY_RANGE_continue @ yes, continue on
10958: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1096 mov r2, #0 @ r2<- false
1097 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
1098 bl dvmResolveClass @ r0<- call(clazz, ref)
1099 cmp r0, #0 @ got null?
1100 beq common_exceptionThrown @ yes, handle exception
1101 b .LOP_FILLED_NEW_ARRAY_RANGE_continue
1102
1103
1104/* ------------------------------ */
1105 .balign 64
1106.L_OP_FILL_ARRAY_DATA: /* 0x26 */
1107/* File: armv5te/OP_FILL_ARRAY_DATA.S */
1108 /* fill-array-data vAA, +BBBBBBBB */
1109 FETCH(r0, 1) @ r0<- bbbb (lo)
1110 FETCH(r1, 2) @ r1<- BBBB (hi)
1111 mov r3, rINST, lsr #8 @ r3<- AA
1112 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb
1113 GET_VREG(r0, r3) @ r0<- vAA (array object)
1114 add r1, rPC, r1, lsl #1 @ r1<- PC + BBBBbbbb*2 (array data off.)
1115 EXPORT_PC();
1116 bl dvmInterpHandleFillArrayData@ fill the array with predefined data
1117 cmp r0, #0 @ 0 means an exception is thrown
1118 beq common_exceptionThrown @ has exception
1119 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
1120 GET_INST_OPCODE(ip) @ extract opcode from rINST
1121 GOTO_OPCODE(ip) @ jump to next instruction
1122
1123/* ------------------------------ */
1124 .balign 64
1125.L_OP_THROW: /* 0x27 */
1126/* File: armv5te/OP_THROW.S */
1127 /*
1128 * Throw an exception object in the current thread.
1129 */
1130 /* throw vAA */
1131 mov r2, rINST, lsr #8 @ r2<- AA
1132 GET_VREG(r1, r2) @ r1<- vAA (exception object)
1133 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
1134 cmp r1, #0 @ null object?
1135 beq common_errNullObject @ yes, throw an NPE instead
1136 @ bypass dvmSetException, just store it
1137 str r1, [r0, #offThread_exception] @ thread->exception<- obj
1138 b common_exceptionThrown
1139
1140
1141/* ------------------------------ */
1142 .balign 64
1143.L_OP_GOTO: /* 0x28 */
1144/* File: armv5te/OP_GOTO.S */
1145 /*
1146 * Unconditional branch, 8-bit offset.
1147 *
1148 * The branch distance is a signed code-unit offset, which we need to
1149 * double to get a byte offset.
1150 */
1151 /* goto +AA */
1152 mov r0, rINST, lsl #16 @ r0<- AAxx0000
1153 movs r9, r0, asr #24 @ r9<- ssssssAA (sign-extended)
1154 mov r9, r9, lsl #1 @ r9<- byte offset
1155 bmi common_backwardBranch @ backward branch, do periodic checks
1156#if defined(WITH_JIT)
1157 GET_JIT_PROF_TABLE(r0)
1158 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1159 cmp r0,#0
1160 bne common_updateProfile
1161 GET_INST_OPCODE(ip) @ extract opcode from rINST
1162 GOTO_OPCODE(ip) @ jump to next instruction
1163#else
1164 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1165 GET_INST_OPCODE(ip) @ extract opcode from rINST
1166 GOTO_OPCODE(ip) @ jump to next instruction
1167#endif
1168
1169/* ------------------------------ */
1170 .balign 64
1171.L_OP_GOTO_16: /* 0x29 */
1172/* File: armv5te/OP_GOTO_16.S */
1173 /*
1174 * Unconditional branch, 16-bit offset.
1175 *
1176 * The branch distance is a signed code-unit offset, which we need to
1177 * double to get a byte offset.
1178 */
1179 /* goto/16 +AAAA */
1180 FETCH_S(r0, 1) @ r0<- ssssAAAA (sign-extended)
1181 movs r9, r0, asl #1 @ r9<- byte offset, check sign
1182 bmi common_backwardBranch @ backward branch, do periodic checks
1183#if defined(WITH_JIT)
1184 GET_JIT_PROF_TABLE(r0)
1185 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1186 cmp r0,#0
1187 bne common_updateProfile
1188 GET_INST_OPCODE(ip) @ extract opcode from rINST
1189 GOTO_OPCODE(ip) @ jump to next instruction
1190#else
1191 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1192 GET_INST_OPCODE(ip) @ extract opcode from rINST
1193 GOTO_OPCODE(ip) @ jump to next instruction
1194#endif
1195
1196
1197/* ------------------------------ */
1198 .balign 64
1199.L_OP_GOTO_32: /* 0x2a */
1200/* File: armv5te/OP_GOTO_32.S */
1201 /*
1202 * Unconditional branch, 32-bit offset.
1203 *
1204 * The branch distance is a signed code-unit offset, which we need to
1205 * double to get a byte offset.
1206 *
1207 * Unlike most opcodes, this one is allowed to branch to itself, so
1208 * our "backward branch" test must be "<=0" instead of "<0". The ORRS
1209 * instruction doesn't affect the V flag, so we need to clear it
1210 * explicitly.
1211 */
1212 /* goto/32 +AAAAAAAA */
1213 FETCH(r0, 1) @ r0<- aaaa (lo)
1214 FETCH(r1, 2) @ r1<- AAAA (hi)
1215 cmp ip, ip @ (clear V flag during stall)
1216 orrs r0, r0, r1, lsl #16 @ r0<- AAAAaaaa, check sign
1217 mov r9, r0, asl #1 @ r9<- byte offset
1218 ble common_backwardBranch @ backward branch, do periodic checks
1219#if defined(WITH_JIT)
1220 GET_JIT_PROF_TABLE(r0)
1221 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1222 cmp r0,#0
1223 bne common_updateProfile
1224 GET_INST_OPCODE(ip) @ extract opcode from rINST
1225 GOTO_OPCODE(ip) @ jump to next instruction
1226#else
1227 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1228 GET_INST_OPCODE(ip) @ extract opcode from rINST
1229 GOTO_OPCODE(ip) @ jump to next instruction
1230#endif
1231
1232/* ------------------------------ */
1233 .balign 64
1234.L_OP_PACKED_SWITCH: /* 0x2b */
1235/* File: armv5te/OP_PACKED_SWITCH.S */
1236 /*
1237 * Handle a packed-switch or sparse-switch instruction. In both cases
1238 * we decode it and hand it off to a helper function.
1239 *
1240 * We don't really expect backward branches in a switch statement, but
1241 * they're perfectly legal, so we check for them here.
1242 *
1243 * for: packed-switch, sparse-switch
1244 */
1245 /* op vAA, +BBBB */
1246 FETCH(r0, 1) @ r0<- bbbb (lo)
1247 FETCH(r1, 2) @ r1<- BBBB (hi)
1248 mov r3, rINST, lsr #8 @ r3<- AA
1249 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb
1250 GET_VREG(r1, r3) @ r1<- vAA
1251 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2
1252 bl dvmInterpHandlePackedSwitch @ r0<- code-unit branch offset
1253 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign
1254 bmi common_backwardBranch @ backward branch, do periodic checks
1255 beq common_backwardBranch @ (want to use BLE but V is unknown)
1256#if defined(WITH_JIT)
1257 GET_JIT_PROF_TABLE(r0)
1258 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1259 cmp r0,#0
1260 bne common_updateProfile
1261 GET_INST_OPCODE(ip) @ extract opcode from rINST
1262 GOTO_OPCODE(ip) @ jump to next instruction
1263#else
1264 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1265 GET_INST_OPCODE(ip) @ extract opcode from rINST
1266 GOTO_OPCODE(ip) @ jump to next instruction
1267#endif
1268
1269
1270/* ------------------------------ */
1271 .balign 64
1272.L_OP_SPARSE_SWITCH: /* 0x2c */
1273/* File: armv5te/OP_SPARSE_SWITCH.S */
1274/* File: armv5te/OP_PACKED_SWITCH.S */
1275 /*
1276 * Handle a packed-switch or sparse-switch instruction. In both cases
1277 * we decode it and hand it off to a helper function.
1278 *
1279 * We don't really expect backward branches in a switch statement, but
1280 * they're perfectly legal, so we check for them here.
1281 *
1282 * for: packed-switch, sparse-switch
1283 */
1284 /* op vAA, +BBBB */
1285 FETCH(r0, 1) @ r0<- bbbb (lo)
1286 FETCH(r1, 2) @ r1<- BBBB (hi)
1287 mov r3, rINST, lsr #8 @ r3<- AA
1288 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb
1289 GET_VREG(r1, r3) @ r1<- vAA
1290 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2
1291 bl dvmInterpHandleSparseSwitch @ r0<- code-unit branch offset
1292 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign
1293 bmi common_backwardBranch @ backward branch, do periodic checks
1294 beq common_backwardBranch @ (want to use BLE but V is unknown)
1295#if defined(WITH_JIT)
1296 GET_JIT_PROF_TABLE(r0)
1297 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1298 cmp r0,#0
1299 bne common_updateProfile
1300 GET_INST_OPCODE(ip) @ extract opcode from rINST
1301 GOTO_OPCODE(ip) @ jump to next instruction
1302#else
1303 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1304 GET_INST_OPCODE(ip) @ extract opcode from rINST
1305 GOTO_OPCODE(ip) @ jump to next instruction
1306#endif
1307
1308
1309
1310/* ------------------------------ */
1311 .balign 64
1312.L_OP_CMPL_FLOAT: /* 0x2d */
1313/* File: arm-vfp/OP_CMPL_FLOAT.S */
1314 /*
1315 * Compare two floating-point values. Puts 0, 1, or -1 into the
1316 * destination register based on the results of the comparison.
1317 *
1318 * int compare(x, y) {
1319 * if (x == y) {
1320 * return 0;
1321 * } else if (x > y) {
1322 * return 1;
1323 * } else if (x < y) {
1324 * return -1;
1325 * } else {
1326 * return -1;
1327 * }
1328 * }
1329 */
1330 /* op vAA, vBB, vCC */
1331 FETCH(r0, 1) @ r0<- CCBB
Andy McFaddena5069fb2009-06-19 15:20:12 -07001332 mov r9, rINST, lsr #8 @ r9<- AA
Andy McFadden5162c5f2009-06-19 16:52:19 -07001333 and r2, r0, #255 @ r2<- BB
1334 mov r3, r0, lsr #8 @ r3<- CC
1335 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB
1336 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC
1337 flds s0, [r2] @ s0<- vBB
1338 flds s1, [r3] @ s1<- vCC
Andy McFaddena5069fb2009-06-19 15:20:12 -07001339 fcmpes s0, s1 @ compare (vBB, vCC)
1340 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
1341 mvn r0, #0 @ r0<- -1 (default)
1342 GET_INST_OPCODE(ip) @ extract opcode from rINST
1343 fmstat @ export status flags
1344 movgt r0, #1 @ (greater than) r1<- 1
1345 moveq r0, #0 @ (equal) r1<- 0
Andy McFadden5162c5f2009-06-19 16:52:19 -07001346 b .LOP_CMPL_FLOAT_finish @ argh
Andy McFaddena5069fb2009-06-19 15:20:12 -07001347
1348
1349/* ------------------------------ */
1350 .balign 64
1351.L_OP_CMPG_FLOAT: /* 0x2e */
1352/* File: arm-vfp/OP_CMPG_FLOAT.S */
1353 /*
1354 * Compare two floating-point values. Puts 0, 1, or -1 into the
1355 * destination register based on the results of the comparison.
1356 *
1357 * int compare(x, y) {
1358 * if (x == y) {
1359 * return 0;
1360 * } else if (x < y) {
1361 * return -1;
1362 * } else if (x > y) {
1363 * return 1;
1364 * } else {
1365 * return 1;
1366 * }
1367 * }
1368 */
1369 /* op vAA, vBB, vCC */
1370 FETCH(r0, 1) @ r0<- CCBB
Andy McFaddena5069fb2009-06-19 15:20:12 -07001371 mov r9, rINST, lsr #8 @ r9<- AA
Andy McFadden5162c5f2009-06-19 16:52:19 -07001372 and r2, r0, #255 @ r2<- BB
1373 mov r3, r0, lsr #8 @ r3<- CC
1374 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB
1375 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC
1376 flds s0, [r2] @ s0<- vBB
1377 flds s1, [r3] @ s1<- vCC
Andy McFaddena5069fb2009-06-19 15:20:12 -07001378 fcmpes s0, s1 @ compare (vBB, vCC)
1379 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
1380 mov r0, #1 @ r0<- 1 (default)
1381 GET_INST_OPCODE(ip) @ extract opcode from rINST
1382 fmstat @ export status flags
1383 mvnmi r0, #0 @ (less than) r1<- -1
1384 moveq r0, #0 @ (equal) r1<- 0
Andy McFadden5162c5f2009-06-19 16:52:19 -07001385 b .LOP_CMPG_FLOAT_finish @ argh
Andy McFaddena5069fb2009-06-19 15:20:12 -07001386
1387
1388/* ------------------------------ */
1389 .balign 64
1390.L_OP_CMPL_DOUBLE: /* 0x2f */
1391/* File: arm-vfp/OP_CMPL_DOUBLE.S */
1392 /*
1393 * Compare two floating-point values. Puts 0, 1, or -1 into the
1394 * destination register based on the results of the comparison.
1395 *
1396 * int compare(x, y) {
1397 * if (x == y) {
1398 * return 0;
1399 * } else if (x > y) {
1400 * return 1;
1401 * } else if (x < y) {
1402 * return -1;
1403 * } else {
1404 * return -1;
1405 * }
1406 * }
1407 */
1408 /* op vAA, vBB, vCC */
1409 FETCH(r0, 1) @ r0<- CCBB
Andy McFaddena5069fb2009-06-19 15:20:12 -07001410 mov r9, rINST, lsr #8 @ r9<- AA
Andy McFadden5162c5f2009-06-19 16:52:19 -07001411 and r2, r0, #255 @ r2<- BB
1412 mov r3, r0, lsr #8 @ r3<- CC
1413 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB
1414 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC
1415 fldd d0, [r2] @ d0<- vBB
1416 fldd d1, [r3] @ d1<- vCC
Andy McFaddena5069fb2009-06-19 15:20:12 -07001417 fcmped d0, d1 @ compare (vBB, vCC)
1418 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
1419 mvn r0, #0 @ r0<- -1 (default)
1420 GET_INST_OPCODE(ip) @ extract opcode from rINST
1421 fmstat @ export status flags
1422 movgt r0, #1 @ (greater than) r1<- 1
1423 moveq r0, #0 @ (equal) r1<- 0
Andy McFadden5162c5f2009-06-19 16:52:19 -07001424 b .LOP_CMPL_DOUBLE_finish @ argh
Andy McFaddena5069fb2009-06-19 15:20:12 -07001425
1426
1427/* ------------------------------ */
1428 .balign 64
1429.L_OP_CMPG_DOUBLE: /* 0x30 */
1430/* File: arm-vfp/OP_CMPG_DOUBLE.S */
1431 /*
1432 * Compare two floating-point values. Puts 0, 1, or -1 into the
1433 * destination register based on the results of the comparison.
1434 *
1435 * int compare(x, y) {
1436 * if (x == y) {
1437 * return 0;
1438 * } else if (x < y) {
1439 * return -1;
1440 * } else if (x > y) {
1441 * return 1;
1442 * } else {
1443 * return 1;
1444 * }
1445 * }
1446 */
1447 /* op vAA, vBB, vCC */
1448 FETCH(r0, 1) @ r0<- CCBB
Andy McFaddena5069fb2009-06-19 15:20:12 -07001449 mov r9, rINST, lsr #8 @ r9<- AA
Andy McFadden5162c5f2009-06-19 16:52:19 -07001450 and r2, r0, #255 @ r2<- BB
1451 mov r3, r0, lsr #8 @ r3<- CC
1452 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB
1453 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC
1454 fldd d0, [r2] @ d0<- vBB
1455 fldd d1, [r3] @ d1<- vCC
Andy McFaddena5069fb2009-06-19 15:20:12 -07001456 fcmped d0, d1 @ compare (vBB, vCC)
1457 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
1458 mov r0, #1 @ r0<- 1 (default)
1459 GET_INST_OPCODE(ip) @ extract opcode from rINST
1460 fmstat @ export status flags
1461 mvnmi r0, #0 @ (less than) r1<- -1
1462 moveq r0, #0 @ (equal) r1<- 0
Andy McFadden5162c5f2009-06-19 16:52:19 -07001463 b .LOP_CMPG_DOUBLE_finish @ argh
Andy McFaddena5069fb2009-06-19 15:20:12 -07001464
1465
1466/* ------------------------------ */
1467 .balign 64
1468.L_OP_CMP_LONG: /* 0x31 */
1469/* File: armv5te/OP_CMP_LONG.S */
1470 /*
1471 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination
1472 * register based on the results of the comparison.
1473 *
1474 * We load the full values with LDM, but in practice many values could
1475 * be resolved by only looking at the high word. This could be made
1476 * faster or slower by splitting the LDM into a pair of LDRs.
1477 *
1478 * If we just wanted to set condition flags, we could do this:
1479 * subs ip, r0, r2
1480 * sbcs ip, r1, r3
1481 * subeqs ip, r0, r2
1482 * Leaving { <0, 0, >0 } in ip. However, we have to set it to a specific
1483 * integer value, which we can do with 2 conditional mov/mvn instructions
1484 * (set 1, set -1; if they're equal we already have 0 in ip), giving
1485 * us a constant 5-cycle path plus a branch at the end to the
1486 * instruction epilogue code. The multi-compare approach below needs
1487 * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
1488 * in the worst case (the 64-bit values are equal).
1489 */
1490 /* cmp-long vAA, vBB, vCC */
1491 FETCH(r0, 1) @ r0<- CCBB
1492 mov r9, rINST, lsr #8 @ r9<- AA
1493 and r2, r0, #255 @ r2<- BB
1494 mov r3, r0, lsr #8 @ r3<- CC
1495 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
1496 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
1497 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
1498 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
1499 cmp r1, r3 @ compare (vBB+1, vCC+1)
1500 blt .LOP_CMP_LONG_less @ signed compare on high part
1501 bgt .LOP_CMP_LONG_greater
1502 subs r1, r0, r2 @ r1<- r0 - r2
1503 bhi .LOP_CMP_LONG_greater @ unsigned compare on low part
1504 bne .LOP_CMP_LONG_less
1505 b .LOP_CMP_LONG_finish @ equal; r1 already holds 0
1506
1507/* ------------------------------ */
1508 .balign 64
1509.L_OP_IF_EQ: /* 0x32 */
1510/* File: armv6t2/OP_IF_EQ.S */
1511/* File: armv6t2/bincmp.S */
1512 /*
1513 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1514 * fragment that specifies the *reverse* comparison to perform, e.g.
1515 * for "if-le" you would use "gt".
1516 *
1517 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1518 */
1519 /* if-cmp vA, vB, +CCCC */
1520 mov r1, rINST, lsr #12 @ r1<- B
1521 ubfx r0, rINST, #8, #4 @ r0<- A
1522 GET_VREG(r3, r1) @ r3<- vB
1523 GET_VREG(r2, r0) @ r2<- vA
1524 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1525 cmp r2, r3 @ compare (vA, vB)
1526 bne 1f @ branch to 1 if comparison failed
1527 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1528 movs r9, r9, asl #1 @ convert to bytes, check sign
1529 bmi common_backwardBranch @ yes, do periodic checks
15301:
1531#if defined(WITH_JIT)
1532 GET_JIT_PROF_TABLE(r0)
1533 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1534 b common_testUpdateProfile
1535#else
1536 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1537 GET_INST_OPCODE(ip) @ extract opcode from rINST
1538 GOTO_OPCODE(ip) @ jump to next instruction
1539#endif
1540
1541
1542
1543/* ------------------------------ */
1544 .balign 64
1545.L_OP_IF_NE: /* 0x33 */
1546/* File: armv6t2/OP_IF_NE.S */
1547/* File: armv6t2/bincmp.S */
1548 /*
1549 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1550 * fragment that specifies the *reverse* comparison to perform, e.g.
1551 * for "if-le" you would use "gt".
1552 *
1553 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1554 */
1555 /* if-cmp vA, vB, +CCCC */
1556 mov r1, rINST, lsr #12 @ r1<- B
1557 ubfx r0, rINST, #8, #4 @ r0<- A
1558 GET_VREG(r3, r1) @ r3<- vB
1559 GET_VREG(r2, r0) @ r2<- vA
1560 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1561 cmp r2, r3 @ compare (vA, vB)
1562 beq 1f @ branch to 1 if comparison failed
1563 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1564 movs r9, r9, asl #1 @ convert to bytes, check sign
1565 bmi common_backwardBranch @ yes, do periodic checks
15661:
1567#if defined(WITH_JIT)
1568 GET_JIT_PROF_TABLE(r0)
1569 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1570 b common_testUpdateProfile
1571#else
1572 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1573 GET_INST_OPCODE(ip) @ extract opcode from rINST
1574 GOTO_OPCODE(ip) @ jump to next instruction
1575#endif
1576
1577
1578
1579/* ------------------------------ */
1580 .balign 64
1581.L_OP_IF_LT: /* 0x34 */
1582/* File: armv6t2/OP_IF_LT.S */
1583/* File: armv6t2/bincmp.S */
1584 /*
1585 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1586 * fragment that specifies the *reverse* comparison to perform, e.g.
1587 * for "if-le" you would use "gt".
1588 *
1589 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1590 */
1591 /* if-cmp vA, vB, +CCCC */
1592 mov r1, rINST, lsr #12 @ r1<- B
1593 ubfx r0, rINST, #8, #4 @ r0<- A
1594 GET_VREG(r3, r1) @ r3<- vB
1595 GET_VREG(r2, r0) @ r2<- vA
1596 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1597 cmp r2, r3 @ compare (vA, vB)
1598 bge 1f @ branch to 1 if comparison failed
1599 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1600 movs r9, r9, asl #1 @ convert to bytes, check sign
1601 bmi common_backwardBranch @ yes, do periodic checks
16021:
1603#if defined(WITH_JIT)
1604 GET_JIT_PROF_TABLE(r0)
1605 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1606 b common_testUpdateProfile
1607#else
1608 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1609 GET_INST_OPCODE(ip) @ extract opcode from rINST
1610 GOTO_OPCODE(ip) @ jump to next instruction
1611#endif
1612
1613
1614
1615/* ------------------------------ */
1616 .balign 64
1617.L_OP_IF_GE: /* 0x35 */
1618/* File: armv6t2/OP_IF_GE.S */
1619/* File: armv6t2/bincmp.S */
1620 /*
1621 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1622 * fragment that specifies the *reverse* comparison to perform, e.g.
1623 * for "if-le" you would use "gt".
1624 *
1625 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1626 */
1627 /* if-cmp vA, vB, +CCCC */
1628 mov r1, rINST, lsr #12 @ r1<- B
1629 ubfx r0, rINST, #8, #4 @ r0<- A
1630 GET_VREG(r3, r1) @ r3<- vB
1631 GET_VREG(r2, r0) @ r2<- vA
1632 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1633 cmp r2, r3 @ compare (vA, vB)
1634 blt 1f @ branch to 1 if comparison failed
1635 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1636 movs r9, r9, asl #1 @ convert to bytes, check sign
1637 bmi common_backwardBranch @ yes, do periodic checks
16381:
1639#if defined(WITH_JIT)
1640 GET_JIT_PROF_TABLE(r0)
1641 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1642 b common_testUpdateProfile
1643#else
1644 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1645 GET_INST_OPCODE(ip) @ extract opcode from rINST
1646 GOTO_OPCODE(ip) @ jump to next instruction
1647#endif
1648
1649
1650
1651/* ------------------------------ */
1652 .balign 64
1653.L_OP_IF_GT: /* 0x36 */
1654/* File: armv6t2/OP_IF_GT.S */
1655/* File: armv6t2/bincmp.S */
1656 /*
1657 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1658 * fragment that specifies the *reverse* comparison to perform, e.g.
1659 * for "if-le" you would use "gt".
1660 *
1661 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1662 */
1663 /* if-cmp vA, vB, +CCCC */
1664 mov r1, rINST, lsr #12 @ r1<- B
1665 ubfx r0, rINST, #8, #4 @ r0<- A
1666 GET_VREG(r3, r1) @ r3<- vB
1667 GET_VREG(r2, r0) @ r2<- vA
1668 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1669 cmp r2, r3 @ compare (vA, vB)
1670 ble 1f @ branch to 1 if comparison failed
1671 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1672 movs r9, r9, asl #1 @ convert to bytes, check sign
1673 bmi common_backwardBranch @ yes, do periodic checks
16741:
1675#if defined(WITH_JIT)
1676 GET_JIT_PROF_TABLE(r0)
1677 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1678 b common_testUpdateProfile
1679#else
1680 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1681 GET_INST_OPCODE(ip) @ extract opcode from rINST
1682 GOTO_OPCODE(ip) @ jump to next instruction
1683#endif
1684
1685
1686
1687/* ------------------------------ */
1688 .balign 64
1689.L_OP_IF_LE: /* 0x37 */
1690/* File: armv6t2/OP_IF_LE.S */
1691/* File: armv6t2/bincmp.S */
1692 /*
1693 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1694 * fragment that specifies the *reverse* comparison to perform, e.g.
1695 * for "if-le" you would use "gt".
1696 *
1697 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1698 */
1699 /* if-cmp vA, vB, +CCCC */
1700 mov r1, rINST, lsr #12 @ r1<- B
1701 ubfx r0, rINST, #8, #4 @ r0<- A
1702 GET_VREG(r3, r1) @ r3<- vB
1703 GET_VREG(r2, r0) @ r2<- vA
1704 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1705 cmp r2, r3 @ compare (vA, vB)
1706 bgt 1f @ branch to 1 if comparison failed
1707 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1708 movs r9, r9, asl #1 @ convert to bytes, check sign
1709 bmi common_backwardBranch @ yes, do periodic checks
17101:
1711#if defined(WITH_JIT)
1712 GET_JIT_PROF_TABLE(r0)
1713 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1714 b common_testUpdateProfile
1715#else
1716 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1717 GET_INST_OPCODE(ip) @ extract opcode from rINST
1718 GOTO_OPCODE(ip) @ jump to next instruction
1719#endif
1720
1721
1722
1723/* ------------------------------ */
1724 .balign 64
1725.L_OP_IF_EQZ: /* 0x38 */
1726/* File: armv5te/OP_IF_EQZ.S */
1727/* File: armv5te/zcmp.S */
1728 /*
1729 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1730 * fragment that specifies the *reverse* comparison to perform, e.g.
1731 * for "if-le" you would use "gt".
1732 *
1733 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1734 */
1735 /* if-cmp vAA, +BBBB */
1736 mov r0, rINST, lsr #8 @ r0<- AA
1737 GET_VREG(r2, r0) @ r2<- vAA
1738 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1739 cmp r2, #0 @ compare (vA, 0)
1740 bne 1f @ branch to 1 if comparison failed
1741 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1742 movs r9, r9, asl #1 @ convert to bytes, check sign
1743 bmi common_backwardBranch @ backward branch, do periodic checks
17441:
1745#if defined(WITH_JIT)
1746 GET_JIT_PROF_TABLE(r0)
1747 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1748 cmp r0,#0
1749 bne common_updateProfile
1750 GET_INST_OPCODE(ip) @ extract opcode from rINST
1751 GOTO_OPCODE(ip) @ jump to next instruction
1752#else
1753 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1754 GET_INST_OPCODE(ip) @ extract opcode from rINST
1755 GOTO_OPCODE(ip) @ jump to next instruction
1756#endif
1757
1758
1759
1760/* ------------------------------ */
1761 .balign 64
1762.L_OP_IF_NEZ: /* 0x39 */
1763/* File: armv5te/OP_IF_NEZ.S */
1764/* File: armv5te/zcmp.S */
1765 /*
1766 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1767 * fragment that specifies the *reverse* comparison to perform, e.g.
1768 * for "if-le" you would use "gt".
1769 *
1770 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1771 */
1772 /* if-cmp vAA, +BBBB */
1773 mov r0, rINST, lsr #8 @ r0<- AA
1774 GET_VREG(r2, r0) @ r2<- vAA
1775 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1776 cmp r2, #0 @ compare (vA, 0)
1777 beq 1f @ branch to 1 if comparison failed
1778 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1779 movs r9, r9, asl #1 @ convert to bytes, check sign
1780 bmi common_backwardBranch @ backward branch, do periodic checks
17811:
1782#if defined(WITH_JIT)
1783 GET_JIT_PROF_TABLE(r0)
1784 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1785 cmp r0,#0
1786 bne common_updateProfile
1787 GET_INST_OPCODE(ip) @ extract opcode from rINST
1788 GOTO_OPCODE(ip) @ jump to next instruction
1789#else
1790 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1791 GET_INST_OPCODE(ip) @ extract opcode from rINST
1792 GOTO_OPCODE(ip) @ jump to next instruction
1793#endif
1794
1795
1796
1797/* ------------------------------ */
1798 .balign 64
1799.L_OP_IF_LTZ: /* 0x3a */
1800/* File: armv5te/OP_IF_LTZ.S */
1801/* File: armv5te/zcmp.S */
1802 /*
1803 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1804 * fragment that specifies the *reverse* comparison to perform, e.g.
1805 * for "if-le" you would use "gt".
1806 *
1807 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1808 */
1809 /* if-cmp vAA, +BBBB */
1810 mov r0, rINST, lsr #8 @ r0<- AA
1811 GET_VREG(r2, r0) @ r2<- vAA
1812 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1813 cmp r2, #0 @ compare (vA, 0)
1814 bge 1f @ branch to 1 if comparison failed
1815 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1816 movs r9, r9, asl #1 @ convert to bytes, check sign
1817 bmi common_backwardBranch @ backward branch, do periodic checks
18181:
1819#if defined(WITH_JIT)
1820 GET_JIT_PROF_TABLE(r0)
1821 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1822 cmp r0,#0
1823 bne common_updateProfile
1824 GET_INST_OPCODE(ip) @ extract opcode from rINST
1825 GOTO_OPCODE(ip) @ jump to next instruction
1826#else
1827 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1828 GET_INST_OPCODE(ip) @ extract opcode from rINST
1829 GOTO_OPCODE(ip) @ jump to next instruction
1830#endif
1831
1832
1833
1834/* ------------------------------ */
1835 .balign 64
1836.L_OP_IF_GEZ: /* 0x3b */
1837/* File: armv5te/OP_IF_GEZ.S */
1838/* File: armv5te/zcmp.S */
1839 /*
1840 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1841 * fragment that specifies the *reverse* comparison to perform, e.g.
1842 * for "if-le" you would use "gt".
1843 *
1844 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1845 */
1846 /* if-cmp vAA, +BBBB */
1847 mov r0, rINST, lsr #8 @ r0<- AA
1848 GET_VREG(r2, r0) @ r2<- vAA
1849 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1850 cmp r2, #0 @ compare (vA, 0)
1851 blt 1f @ branch to 1 if comparison failed
1852 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1853 movs r9, r9, asl #1 @ convert to bytes, check sign
1854 bmi common_backwardBranch @ backward branch, do periodic checks
18551:
1856#if defined(WITH_JIT)
1857 GET_JIT_PROF_TABLE(r0)
1858 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1859 cmp r0,#0
1860 bne common_updateProfile
1861 GET_INST_OPCODE(ip) @ extract opcode from rINST
1862 GOTO_OPCODE(ip) @ jump to next instruction
1863#else
1864 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1865 GET_INST_OPCODE(ip) @ extract opcode from rINST
1866 GOTO_OPCODE(ip) @ jump to next instruction
1867#endif
1868
1869
1870
1871/* ------------------------------ */
1872 .balign 64
1873.L_OP_IF_GTZ: /* 0x3c */
1874/* File: armv5te/OP_IF_GTZ.S */
1875/* File: armv5te/zcmp.S */
1876 /*
1877 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1878 * fragment that specifies the *reverse* comparison to perform, e.g.
1879 * for "if-le" you would use "gt".
1880 *
1881 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1882 */
1883 /* if-cmp vAA, +BBBB */
1884 mov r0, rINST, lsr #8 @ r0<- AA
1885 GET_VREG(r2, r0) @ r2<- vAA
1886 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1887 cmp r2, #0 @ compare (vA, 0)
1888 ble 1f @ branch to 1 if comparison failed
1889 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1890 movs r9, r9, asl #1 @ convert to bytes, check sign
1891 bmi common_backwardBranch @ backward branch, do periodic checks
18921:
1893#if defined(WITH_JIT)
1894 GET_JIT_PROF_TABLE(r0)
1895 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1896 cmp r0,#0
1897 bne common_updateProfile
1898 GET_INST_OPCODE(ip) @ extract opcode from rINST
1899 GOTO_OPCODE(ip) @ jump to next instruction
1900#else
1901 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1902 GET_INST_OPCODE(ip) @ extract opcode from rINST
1903 GOTO_OPCODE(ip) @ jump to next instruction
1904#endif
1905
1906
1907
1908/* ------------------------------ */
1909 .balign 64
1910.L_OP_IF_LEZ: /* 0x3d */
1911/* File: armv5te/OP_IF_LEZ.S */
1912/* File: armv5te/zcmp.S */
1913 /*
1914 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1915 * fragment that specifies the *reverse* comparison to perform, e.g.
1916 * for "if-le" you would use "gt".
1917 *
1918 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1919 */
1920 /* if-cmp vAA, +BBBB */
1921 mov r0, rINST, lsr #8 @ r0<- AA
1922 GET_VREG(r2, r0) @ r2<- vAA
1923 mov r9, #4 @ r0<- BYTE branch dist for not-taken
1924 cmp r2, #0 @ compare (vA, 0)
1925 bgt 1f @ branch to 1 if comparison failed
1926 FETCH_S(r9, 1) @ r9<- branch offset, in code units
1927 movs r9, r9, asl #1 @ convert to bytes, check sign
1928 bmi common_backwardBranch @ backward branch, do periodic checks
19291:
1930#if defined(WITH_JIT)
1931 GET_JIT_PROF_TABLE(r0)
1932 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1933 cmp r0,#0
1934 bne common_updateProfile
1935 GET_INST_OPCODE(ip) @ extract opcode from rINST
1936 GOTO_OPCODE(ip) @ jump to next instruction
1937#else
1938 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
1939 GET_INST_OPCODE(ip) @ extract opcode from rINST
1940 GOTO_OPCODE(ip) @ jump to next instruction
1941#endif
1942
1943
1944
1945/* ------------------------------ */
1946 .balign 64
1947.L_OP_UNUSED_3E: /* 0x3e */
1948/* File: armv5te/OP_UNUSED_3E.S */
1949/* File: armv5te/unused.S */
1950 bl common_abort
1951
1952
1953
1954/* ------------------------------ */
1955 .balign 64
1956.L_OP_UNUSED_3F: /* 0x3f */
1957/* File: armv5te/OP_UNUSED_3F.S */
1958/* File: armv5te/unused.S */
1959 bl common_abort
1960
1961
1962
1963/* ------------------------------ */
1964 .balign 64
1965.L_OP_UNUSED_40: /* 0x40 */
1966/* File: armv5te/OP_UNUSED_40.S */
1967/* File: armv5te/unused.S */
1968 bl common_abort
1969
1970
1971
1972/* ------------------------------ */
1973 .balign 64
1974.L_OP_UNUSED_41: /* 0x41 */
1975/* File: armv5te/OP_UNUSED_41.S */
1976/* File: armv5te/unused.S */
1977 bl common_abort
1978
1979
1980
1981/* ------------------------------ */
1982 .balign 64
1983.L_OP_UNUSED_42: /* 0x42 */
1984/* File: armv5te/OP_UNUSED_42.S */
1985/* File: armv5te/unused.S */
1986 bl common_abort
1987
1988
1989
1990/* ------------------------------ */
1991 .balign 64
1992.L_OP_UNUSED_43: /* 0x43 */
1993/* File: armv5te/OP_UNUSED_43.S */
1994/* File: armv5te/unused.S */
1995 bl common_abort
1996
1997
1998
1999/* ------------------------------ */
2000 .balign 64
2001.L_OP_AGET: /* 0x44 */
2002/* File: armv5te/OP_AGET.S */
2003 /*
2004 * Array get, 32 bits or less. vAA <- vBB[vCC].
2005 *
2006 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2007 * instructions. We use a pair of FETCH_Bs instead.
2008 *
2009 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2010 */
2011 /* op vAA, vBB, vCC */
2012 FETCH_B(r2, 1, 0) @ r2<- BB
2013 mov r9, rINST, lsr #8 @ r9<- AA
2014 FETCH_B(r3, 1, 1) @ r3<- CC
2015 GET_VREG(r0, r2) @ r0<- vBB (array object)
2016 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2017 cmp r0, #0 @ null array object?
2018 beq common_errNullObject @ yes, bail
2019 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2020 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width
2021 cmp r1, r3 @ compare unsigned index, length
2022 bcs common_errArrayIndex @ index >= length, bail
2023 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2024 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC]
2025 GET_INST_OPCODE(ip) @ extract opcode from rINST
2026 SET_VREG(r2, r9) @ vAA<- r2
2027 GOTO_OPCODE(ip) @ jump to next instruction
2028
2029
2030/* ------------------------------ */
2031 .balign 64
2032.L_OP_AGET_WIDE: /* 0x45 */
2033/* File: armv5te/OP_AGET_WIDE.S */
2034 /*
2035 * Array get, 64 bits. vAA <- vBB[vCC].
2036 *
2037 * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD.
2038 */
2039 /* aget-wide vAA, vBB, vCC */
2040 FETCH(r0, 1) @ r0<- CCBB
2041 mov r9, rINST, lsr #8 @ r9<- AA
2042 and r2, r0, #255 @ r2<- BB
2043 mov r3, r0, lsr #8 @ r3<- CC
2044 GET_VREG(r0, r2) @ r0<- vBB (array object)
2045 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2046 cmp r0, #0 @ null array object?
2047 beq common_errNullObject @ yes, bail
2048 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2049 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width
2050 cmp r1, r3 @ compare unsigned index, length
2051 bcc .LOP_AGET_WIDE_finish @ okay, continue below
2052 b common_errArrayIndex @ index >= length, bail
2053 @ May want to swap the order of these two branches depending on how the
2054 @ branch prediction (if any) handles conditional forward branches vs.
2055 @ unconditional forward branches.
2056
2057/* ------------------------------ */
2058 .balign 64
2059.L_OP_AGET_OBJECT: /* 0x46 */
2060/* File: armv5te/OP_AGET_OBJECT.S */
2061/* File: armv5te/OP_AGET.S */
2062 /*
2063 * Array get, 32 bits or less. vAA <- vBB[vCC].
2064 *
2065 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2066 * instructions. We use a pair of FETCH_Bs instead.
2067 *
2068 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2069 */
2070 /* op vAA, vBB, vCC */
2071 FETCH_B(r2, 1, 0) @ r2<- BB
2072 mov r9, rINST, lsr #8 @ r9<- AA
2073 FETCH_B(r3, 1, 1) @ r3<- CC
2074 GET_VREG(r0, r2) @ r0<- vBB (array object)
2075 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2076 cmp r0, #0 @ null array object?
2077 beq common_errNullObject @ yes, bail
2078 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2079 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width
2080 cmp r1, r3 @ compare unsigned index, length
2081 bcs common_errArrayIndex @ index >= length, bail
2082 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2083 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC]
2084 GET_INST_OPCODE(ip) @ extract opcode from rINST
2085 SET_VREG(r2, r9) @ vAA<- r2
2086 GOTO_OPCODE(ip) @ jump to next instruction
2087
2088
2089
2090/* ------------------------------ */
2091 .balign 64
2092.L_OP_AGET_BOOLEAN: /* 0x47 */
2093/* File: armv5te/OP_AGET_BOOLEAN.S */
2094/* File: armv5te/OP_AGET.S */
2095 /*
2096 * Array get, 32 bits or less. vAA <- vBB[vCC].
2097 *
2098 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2099 * instructions. We use a pair of FETCH_Bs instead.
2100 *
2101 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2102 */
2103 /* op vAA, vBB, vCC */
2104 FETCH_B(r2, 1, 0) @ r2<- BB
2105 mov r9, rINST, lsr #8 @ r9<- AA
2106 FETCH_B(r3, 1, 1) @ r3<- CC
2107 GET_VREG(r0, r2) @ r0<- vBB (array object)
2108 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2109 cmp r0, #0 @ null array object?
2110 beq common_errNullObject @ yes, bail
2111 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2112 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width
2113 cmp r1, r3 @ compare unsigned index, length
2114 bcs common_errArrayIndex @ index >= length, bail
2115 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2116 ldrb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC]
2117 GET_INST_OPCODE(ip) @ extract opcode from rINST
2118 SET_VREG(r2, r9) @ vAA<- r2
2119 GOTO_OPCODE(ip) @ jump to next instruction
2120
2121
2122
2123/* ------------------------------ */
2124 .balign 64
2125.L_OP_AGET_BYTE: /* 0x48 */
2126/* File: armv5te/OP_AGET_BYTE.S */
2127/* File: armv5te/OP_AGET.S */
2128 /*
2129 * Array get, 32 bits or less. vAA <- vBB[vCC].
2130 *
2131 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2132 * instructions. We use a pair of FETCH_Bs instead.
2133 *
2134 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2135 */
2136 /* op vAA, vBB, vCC */
2137 FETCH_B(r2, 1, 0) @ r2<- BB
2138 mov r9, rINST, lsr #8 @ r9<- AA
2139 FETCH_B(r3, 1, 1) @ r3<- CC
2140 GET_VREG(r0, r2) @ r0<- vBB (array object)
2141 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2142 cmp r0, #0 @ null array object?
2143 beq common_errNullObject @ yes, bail
2144 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2145 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width
2146 cmp r1, r3 @ compare unsigned index, length
2147 bcs common_errArrayIndex @ index >= length, bail
2148 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2149 ldrsb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC]
2150 GET_INST_OPCODE(ip) @ extract opcode from rINST
2151 SET_VREG(r2, r9) @ vAA<- r2
2152 GOTO_OPCODE(ip) @ jump to next instruction
2153
2154
2155
2156/* ------------------------------ */
2157 .balign 64
2158.L_OP_AGET_CHAR: /* 0x49 */
2159/* File: armv5te/OP_AGET_CHAR.S */
2160/* File: armv5te/OP_AGET.S */
2161 /*
2162 * Array get, 32 bits or less. vAA <- vBB[vCC].
2163 *
2164 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2165 * instructions. We use a pair of FETCH_Bs instead.
2166 *
2167 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2168 */
2169 /* op vAA, vBB, vCC */
2170 FETCH_B(r2, 1, 0) @ r2<- BB
2171 mov r9, rINST, lsr #8 @ r9<- AA
2172 FETCH_B(r3, 1, 1) @ r3<- CC
2173 GET_VREG(r0, r2) @ r0<- vBB (array object)
2174 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2175 cmp r0, #0 @ null array object?
2176 beq common_errNullObject @ yes, bail
2177 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2178 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width
2179 cmp r1, r3 @ compare unsigned index, length
2180 bcs common_errArrayIndex @ index >= length, bail
2181 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2182 ldrh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC]
2183 GET_INST_OPCODE(ip) @ extract opcode from rINST
2184 SET_VREG(r2, r9) @ vAA<- r2
2185 GOTO_OPCODE(ip) @ jump to next instruction
2186
2187
2188
2189/* ------------------------------ */
2190 .balign 64
2191.L_OP_AGET_SHORT: /* 0x4a */
2192/* File: armv5te/OP_AGET_SHORT.S */
2193/* File: armv5te/OP_AGET.S */
2194 /*
2195 * Array get, 32 bits or less. vAA <- vBB[vCC].
2196 *
2197 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2198 * instructions. We use a pair of FETCH_Bs instead.
2199 *
2200 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2201 */
2202 /* op vAA, vBB, vCC */
2203 FETCH_B(r2, 1, 0) @ r2<- BB
2204 mov r9, rINST, lsr #8 @ r9<- AA
2205 FETCH_B(r3, 1, 1) @ r3<- CC
2206 GET_VREG(r0, r2) @ r0<- vBB (array object)
2207 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2208 cmp r0, #0 @ null array object?
2209 beq common_errNullObject @ yes, bail
2210 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2211 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width
2212 cmp r1, r3 @ compare unsigned index, length
2213 bcs common_errArrayIndex @ index >= length, bail
2214 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2215 ldrsh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC]
2216 GET_INST_OPCODE(ip) @ extract opcode from rINST
2217 SET_VREG(r2, r9) @ vAA<- r2
2218 GOTO_OPCODE(ip) @ jump to next instruction
2219
2220
2221
2222/* ------------------------------ */
2223 .balign 64
2224.L_OP_APUT: /* 0x4b */
2225/* File: armv5te/OP_APUT.S */
2226 /*
2227 * Array put, 32 bits or less. vBB[vCC] <- vAA.
2228 *
2229 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2230 * instructions. We use a pair of FETCH_Bs instead.
2231 *
2232 * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2233 */
2234 /* op vAA, vBB, vCC */
2235 FETCH_B(r2, 1, 0) @ r2<- BB
2236 mov r9, rINST, lsr #8 @ r9<- AA
2237 FETCH_B(r3, 1, 1) @ r3<- CC
2238 GET_VREG(r0, r2) @ r0<- vBB (array object)
2239 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2240 cmp r0, #0 @ null array object?
2241 beq common_errNullObject @ yes, bail
2242 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2243 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width
2244 cmp r1, r3 @ compare unsigned index, length
2245 bcs common_errArrayIndex @ index >= length, bail
2246 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2247 GET_VREG(r2, r9) @ r2<- vAA
2248 GET_INST_OPCODE(ip) @ extract opcode from rINST
2249 str r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2
2250 GOTO_OPCODE(ip) @ jump to next instruction
2251
2252
2253/* ------------------------------ */
2254 .balign 64
2255.L_OP_APUT_WIDE: /* 0x4c */
2256/* File: armv5te/OP_APUT_WIDE.S */
2257 /*
2258 * Array put, 64 bits. vBB[vCC] <- vAA.
2259 *
2260 * Arrays of long/double are 64-bit aligned, so it's okay to use STRD.
2261 */
2262 /* aput-wide vAA, vBB, vCC */
2263 FETCH(r0, 1) @ r0<- CCBB
2264 mov r9, rINST, lsr #8 @ r9<- AA
2265 and r2, r0, #255 @ r2<- BB
2266 mov r3, r0, lsr #8 @ r3<- CC
2267 GET_VREG(r0, r2) @ r0<- vBB (array object)
2268 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2269 cmp r0, #0 @ null array object?
2270 beq common_errNullObject @ yes, bail
2271 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2272 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width
2273 cmp r1, r3 @ compare unsigned index, length
2274 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
2275 bcc .LOP_APUT_WIDE_finish @ okay, continue below
2276 b common_errArrayIndex @ index >= length, bail
2277 @ May want to swap the order of these two branches depending on how the
2278 @ branch prediction (if any) handles conditional forward branches vs.
2279 @ unconditional forward branches.
2280
2281/* ------------------------------ */
2282 .balign 64
2283.L_OP_APUT_OBJECT: /* 0x4d */
2284/* File: armv5te/OP_APUT_OBJECT.S */
2285 /*
2286 * Store an object into an array. vBB[vCC] <- vAA.
2287 *
2288 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2289 * instructions. We use a pair of FETCH_Bs instead.
2290 */
2291 /* op vAA, vBB, vCC */
2292 FETCH(r0, 1) @ r0<- CCBB
2293 mov r9, rINST, lsr #8 @ r9<- AA
2294 and r2, r0, #255 @ r2<- BB
2295 mov r3, r0, lsr #8 @ r3<- CC
2296 GET_VREG(r1, r2) @ r1<- vBB (array object)
2297 GET_VREG(r0, r3) @ r0<- vCC (requested index)
2298 cmp r1, #0 @ null array object?
2299 GET_VREG(r9, r9) @ r9<- vAA
2300 beq common_errNullObject @ yes, bail
2301 ldr r3, [r1, #offArrayObject_length] @ r3<- arrayObj->length
2302 add r10, r1, r0, lsl #2 @ r10<- arrayObj + index*width
2303 cmp r0, r3 @ compare unsigned index, length
2304 bcc .LOP_APUT_OBJECT_finish @ we're okay, continue on
2305 b common_errArrayIndex @ index >= length, bail
2306
2307
2308/* ------------------------------ */
2309 .balign 64
2310.L_OP_APUT_BOOLEAN: /* 0x4e */
2311/* File: armv5te/OP_APUT_BOOLEAN.S */
2312/* File: armv5te/OP_APUT.S */
2313 /*
2314 * Array put, 32 bits or less. vBB[vCC] <- vAA.
2315 *
2316 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2317 * instructions. We use a pair of FETCH_Bs instead.
2318 *
2319 * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2320 */
2321 /* op vAA, vBB, vCC */
2322 FETCH_B(r2, 1, 0) @ r2<- BB
2323 mov r9, rINST, lsr #8 @ r9<- AA
2324 FETCH_B(r3, 1, 1) @ r3<- CC
2325 GET_VREG(r0, r2) @ r0<- vBB (array object)
2326 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2327 cmp r0, #0 @ null array object?
2328 beq common_errNullObject @ yes, bail
2329 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2330 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width
2331 cmp r1, r3 @ compare unsigned index, length
2332 bcs common_errArrayIndex @ index >= length, bail
2333 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2334 GET_VREG(r2, r9) @ r2<- vAA
2335 GET_INST_OPCODE(ip) @ extract opcode from rINST
2336 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2
2337 GOTO_OPCODE(ip) @ jump to next instruction
2338
2339
2340
2341/* ------------------------------ */
2342 .balign 64
2343.L_OP_APUT_BYTE: /* 0x4f */
2344/* File: armv5te/OP_APUT_BYTE.S */
2345/* File: armv5te/OP_APUT.S */
2346 /*
2347 * Array put, 32 bits or less. vBB[vCC] <- vAA.
2348 *
2349 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2350 * instructions. We use a pair of FETCH_Bs instead.
2351 *
2352 * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2353 */
2354 /* op vAA, vBB, vCC */
2355 FETCH_B(r2, 1, 0) @ r2<- BB
2356 mov r9, rINST, lsr #8 @ r9<- AA
2357 FETCH_B(r3, 1, 1) @ r3<- CC
2358 GET_VREG(r0, r2) @ r0<- vBB (array object)
2359 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2360 cmp r0, #0 @ null array object?
2361 beq common_errNullObject @ yes, bail
2362 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2363 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width
2364 cmp r1, r3 @ compare unsigned index, length
2365 bcs common_errArrayIndex @ index >= length, bail
2366 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2367 GET_VREG(r2, r9) @ r2<- vAA
2368 GET_INST_OPCODE(ip) @ extract opcode from rINST
2369 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2
2370 GOTO_OPCODE(ip) @ jump to next instruction
2371
2372
2373
2374/* ------------------------------ */
2375 .balign 64
2376.L_OP_APUT_CHAR: /* 0x50 */
2377/* File: armv5te/OP_APUT_CHAR.S */
2378/* File: armv5te/OP_APUT.S */
2379 /*
2380 * Array put, 32 bits or less. vBB[vCC] <- vAA.
2381 *
2382 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2383 * instructions. We use a pair of FETCH_Bs instead.
2384 *
2385 * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2386 */
2387 /* op vAA, vBB, vCC */
2388 FETCH_B(r2, 1, 0) @ r2<- BB
2389 mov r9, rINST, lsr #8 @ r9<- AA
2390 FETCH_B(r3, 1, 1) @ r3<- CC
2391 GET_VREG(r0, r2) @ r0<- vBB (array object)
2392 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2393 cmp r0, #0 @ null array object?
2394 beq common_errNullObject @ yes, bail
2395 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2396 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width
2397 cmp r1, r3 @ compare unsigned index, length
2398 bcs common_errArrayIndex @ index >= length, bail
2399 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2400 GET_VREG(r2, r9) @ r2<- vAA
2401 GET_INST_OPCODE(ip) @ extract opcode from rINST
2402 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2
2403 GOTO_OPCODE(ip) @ jump to next instruction
2404
2405
2406
2407/* ------------------------------ */
2408 .balign 64
2409.L_OP_APUT_SHORT: /* 0x51 */
2410/* File: armv5te/OP_APUT_SHORT.S */
2411/* File: armv5te/OP_APUT.S */
2412 /*
2413 * Array put, 32 bits or less. vBB[vCC] <- vAA.
2414 *
2415 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2416 * instructions. We use a pair of FETCH_Bs instead.
2417 *
2418 * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2419 */
2420 /* op vAA, vBB, vCC */
2421 FETCH_B(r2, 1, 0) @ r2<- BB
2422 mov r9, rINST, lsr #8 @ r9<- AA
2423 FETCH_B(r3, 1, 1) @ r3<- CC
2424 GET_VREG(r0, r2) @ r0<- vBB (array object)
2425 GET_VREG(r1, r3) @ r1<- vCC (requested index)
2426 cmp r0, #0 @ null array object?
2427 beq common_errNullObject @ yes, bail
2428 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length
2429 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width
2430 cmp r1, r3 @ compare unsigned index, length
2431 bcs common_errArrayIndex @ index >= length, bail
2432 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2433 GET_VREG(r2, r9) @ r2<- vAA
2434 GET_INST_OPCODE(ip) @ extract opcode from rINST
2435 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2
2436 GOTO_OPCODE(ip) @ jump to next instruction
2437
2438
2439
2440/* ------------------------------ */
2441 .balign 64
2442.L_OP_IGET: /* 0x52 */
2443/* File: armv6t2/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_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_finish
2464 b common_exceptionThrown
2465
2466/* ------------------------------ */
2467 .balign 64
2468.L_OP_IGET_WIDE: /* 0x53 */
2469/* File: armv6t2/OP_IGET_WIDE.S */
2470 /*
2471 * Wide 32-bit instance field get.
2472 */
2473 /* iget-wide vA, vB, field@CCCC */
2474 mov r0, rINST, lsr #12 @ r0<- B
2475 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2476 FETCH(r1, 1) @ r1<- field ref CCCC
2477 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2478 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2479 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2480 cmp r0, #0 @ is resolved entry null?
2481 bne .LOP_IGET_WIDE_finish @ no, already resolved
24828: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2483 EXPORT_PC() @ resolve() could throw
2484 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2485 bl dvmResolveInstField @ r0<- resolved InstField ptr
2486 cmp r0, #0
2487 bne .LOP_IGET_WIDE_finish
2488 b common_exceptionThrown
2489
2490/* ------------------------------ */
2491 .balign 64
2492.L_OP_IGET_OBJECT: /* 0x54 */
2493/* File: armv5te/OP_IGET_OBJECT.S */
2494/* File: armv5te/OP_IGET.S */
2495 /*
2496 * General 32-bit instance field get.
2497 *
2498 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2499 */
2500 /* op vA, vB, field@CCCC */
2501 mov r0, rINST, lsr #12 @ r0<- B
2502 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2503 FETCH(r1, 1) @ r1<- field ref CCCC
2504 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2505 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2506 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2507 cmp r0, #0 @ is resolved entry null?
2508 bne .LOP_IGET_OBJECT_finish @ no, already resolved
25098: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2510 EXPORT_PC() @ resolve() could throw
2511 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2512 bl dvmResolveInstField @ r0<- resolved InstField ptr
2513 cmp r0, #0
2514 bne .LOP_IGET_OBJECT_finish
2515 b common_exceptionThrown
2516
2517
2518/* ------------------------------ */
2519 .balign 64
2520.L_OP_IGET_BOOLEAN: /* 0x55 */
2521/* File: armv5te/OP_IGET_BOOLEAN.S */
2522@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" }
2523/* File: armv5te/OP_IGET.S */
2524 /*
2525 * General 32-bit instance field get.
2526 *
2527 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2528 */
2529 /* op vA, vB, field@CCCC */
2530 mov r0, rINST, lsr #12 @ r0<- B
2531 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2532 FETCH(r1, 1) @ r1<- field ref CCCC
2533 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2534 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2535 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2536 cmp r0, #0 @ is resolved entry null?
2537 bne .LOP_IGET_BOOLEAN_finish @ no, already resolved
25388: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2539 EXPORT_PC() @ resolve() could throw
2540 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2541 bl dvmResolveInstField @ r0<- resolved InstField ptr
2542 cmp r0, #0
2543 bne .LOP_IGET_BOOLEAN_finish
2544 b common_exceptionThrown
2545
2546
2547/* ------------------------------ */
2548 .balign 64
2549.L_OP_IGET_BYTE: /* 0x56 */
2550/* File: armv5te/OP_IGET_BYTE.S */
2551@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" }
2552/* File: armv5te/OP_IGET.S */
2553 /*
2554 * General 32-bit instance field get.
2555 *
2556 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2557 */
2558 /* op vA, vB, field@CCCC */
2559 mov r0, rINST, lsr #12 @ r0<- B
2560 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2561 FETCH(r1, 1) @ r1<- field ref CCCC
2562 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2563 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2564 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2565 cmp r0, #0 @ is resolved entry null?
2566 bne .LOP_IGET_BYTE_finish @ no, already resolved
25678: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2568 EXPORT_PC() @ resolve() could throw
2569 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2570 bl dvmResolveInstField @ r0<- resolved InstField ptr
2571 cmp r0, #0
2572 bne .LOP_IGET_BYTE_finish
2573 b common_exceptionThrown
2574
2575
2576/* ------------------------------ */
2577 .balign 64
2578.L_OP_IGET_CHAR: /* 0x57 */
2579/* File: armv5te/OP_IGET_CHAR.S */
2580@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" }
2581/* File: armv5te/OP_IGET.S */
2582 /*
2583 * General 32-bit instance field get.
2584 *
2585 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2586 */
2587 /* op vA, vB, field@CCCC */
2588 mov r0, rINST, lsr #12 @ r0<- B
2589 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2590 FETCH(r1, 1) @ r1<- field ref CCCC
2591 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2592 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2593 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2594 cmp r0, #0 @ is resolved entry null?
2595 bne .LOP_IGET_CHAR_finish @ no, already resolved
25968: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2597 EXPORT_PC() @ resolve() could throw
2598 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2599 bl dvmResolveInstField @ r0<- resolved InstField ptr
2600 cmp r0, #0
2601 bne .LOP_IGET_CHAR_finish
2602 b common_exceptionThrown
2603
2604
2605/* ------------------------------ */
2606 .balign 64
2607.L_OP_IGET_SHORT: /* 0x58 */
2608/* File: armv5te/OP_IGET_SHORT.S */
2609@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" }
2610/* File: armv5te/OP_IGET.S */
2611 /*
2612 * General 32-bit instance field get.
2613 *
2614 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2615 */
2616 /* op vA, vB, field@CCCC */
2617 mov r0, rINST, lsr #12 @ r0<- B
2618 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2619 FETCH(r1, 1) @ r1<- field ref CCCC
2620 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2621 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2622 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2623 cmp r0, #0 @ is resolved entry null?
2624 bne .LOP_IGET_SHORT_finish @ no, already resolved
26258: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2626 EXPORT_PC() @ resolve() could throw
2627 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2628 bl dvmResolveInstField @ r0<- resolved InstField ptr
2629 cmp r0, #0
2630 bne .LOP_IGET_SHORT_finish
2631 b common_exceptionThrown
2632
2633
2634/* ------------------------------ */
2635 .balign 64
2636.L_OP_IPUT: /* 0x59 */
2637/* File: armv6t2/OP_IPUT.S */
2638 /*
2639 * General 32-bit instance field put.
2640 *
2641 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2642 */
2643 /* op vA, vB, field@CCCC */
2644 mov r0, rINST, lsr #12 @ r0<- B
2645 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2646 FETCH(r1, 1) @ r1<- field ref CCCC
2647 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2648 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2649 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2650 cmp r0, #0 @ is resolved entry null?
2651 bne .LOP_IPUT_finish @ no, already resolved
26528: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2653 EXPORT_PC() @ resolve() could throw
2654 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2655 bl dvmResolveInstField @ r0<- resolved InstField ptr
2656 cmp r0, #0 @ success?
2657 bne .LOP_IPUT_finish @ yes, finish up
2658 b common_exceptionThrown
2659
2660/* ------------------------------ */
2661 .balign 64
2662.L_OP_IPUT_WIDE: /* 0x5a */
2663/* File: armv6t2/OP_IPUT_WIDE.S */
2664 /* iput-wide vA, vB, field@CCCC */
2665 mov r0, rINST, lsr #12 @ r0<- B
2666 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2667 FETCH(r1, 1) @ r1<- field ref CCCC
2668 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2669 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2670 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2671 cmp r0, #0 @ is resolved entry null?
2672 bne .LOP_IPUT_WIDE_finish @ no, already resolved
26738: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2674 EXPORT_PC() @ resolve() could throw
2675 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2676 bl dvmResolveInstField @ r0<- resolved InstField ptr
2677 cmp r0, #0 @ success?
2678 bne .LOP_IPUT_WIDE_finish @ yes, finish up
2679 b common_exceptionThrown
2680
2681/* ------------------------------ */
2682 .balign 64
2683.L_OP_IPUT_OBJECT: /* 0x5b */
2684/* File: armv5te/OP_IPUT_OBJECT.S */
2685/* File: armv5te/OP_IPUT.S */
2686 /*
2687 * General 32-bit instance field put.
2688 *
2689 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2690 */
2691 /* op vA, vB, field@CCCC */
2692 mov r0, rINST, lsr #12 @ r0<- B
2693 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2694 FETCH(r1, 1) @ r1<- field ref CCCC
2695 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2696 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2697 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2698 cmp r0, #0 @ is resolved entry null?
2699 bne .LOP_IPUT_OBJECT_finish @ no, already resolved
27008: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2701 EXPORT_PC() @ resolve() could throw
2702 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2703 bl dvmResolveInstField @ r0<- resolved InstField ptr
2704 cmp r0, #0 @ success?
2705 bne .LOP_IPUT_OBJECT_finish @ yes, finish up
2706 b common_exceptionThrown
2707
2708
2709/* ------------------------------ */
2710 .balign 64
2711.L_OP_IPUT_BOOLEAN: /* 0x5c */
2712/* File: armv5te/OP_IPUT_BOOLEAN.S */
2713@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" }
2714/* File: armv5te/OP_IPUT.S */
2715 /*
2716 * General 32-bit instance field put.
2717 *
2718 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2719 */
2720 /* op vA, vB, field@CCCC */
2721 mov r0, rINST, lsr #12 @ r0<- B
2722 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2723 FETCH(r1, 1) @ r1<- field ref CCCC
2724 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2725 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2726 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2727 cmp r0, #0 @ is resolved entry null?
2728 bne .LOP_IPUT_BOOLEAN_finish @ no, already resolved
27298: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2730 EXPORT_PC() @ resolve() could throw
2731 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2732 bl dvmResolveInstField @ r0<- resolved InstField ptr
2733 cmp r0, #0 @ success?
2734 bne .LOP_IPUT_BOOLEAN_finish @ yes, finish up
2735 b common_exceptionThrown
2736
2737
2738/* ------------------------------ */
2739 .balign 64
2740.L_OP_IPUT_BYTE: /* 0x5d */
2741/* File: armv5te/OP_IPUT_BYTE.S */
2742@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" }
2743/* File: armv5te/OP_IPUT.S */
2744 /*
2745 * General 32-bit instance field put.
2746 *
2747 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2748 */
2749 /* op vA, vB, field@CCCC */
2750 mov r0, rINST, lsr #12 @ r0<- B
2751 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2752 FETCH(r1, 1) @ r1<- field ref CCCC
2753 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2754 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2755 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2756 cmp r0, #0 @ is resolved entry null?
2757 bne .LOP_IPUT_BYTE_finish @ no, already resolved
27588: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2759 EXPORT_PC() @ resolve() could throw
2760 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2761 bl dvmResolveInstField @ r0<- resolved InstField ptr
2762 cmp r0, #0 @ success?
2763 bne .LOP_IPUT_BYTE_finish @ yes, finish up
2764 b common_exceptionThrown
2765
2766
2767/* ------------------------------ */
2768 .balign 64
2769.L_OP_IPUT_CHAR: /* 0x5e */
2770/* File: armv5te/OP_IPUT_CHAR.S */
2771@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" }
2772/* File: armv5te/OP_IPUT.S */
2773 /*
2774 * General 32-bit instance field put.
2775 *
2776 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2777 */
2778 /* op vA, vB, field@CCCC */
2779 mov r0, rINST, lsr #12 @ r0<- B
2780 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2781 FETCH(r1, 1) @ r1<- field ref CCCC
2782 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2783 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2784 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2785 cmp r0, #0 @ is resolved entry null?
2786 bne .LOP_IPUT_CHAR_finish @ no, already resolved
27878: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2788 EXPORT_PC() @ resolve() could throw
2789 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2790 bl dvmResolveInstField @ r0<- resolved InstField ptr
2791 cmp r0, #0 @ success?
2792 bne .LOP_IPUT_CHAR_finish @ yes, finish up
2793 b common_exceptionThrown
2794
2795
2796/* ------------------------------ */
2797 .balign 64
2798.L_OP_IPUT_SHORT: /* 0x5f */
2799/* File: armv5te/OP_IPUT_SHORT.S */
2800@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" }
2801/* File: armv5te/OP_IPUT.S */
2802 /*
2803 * General 32-bit instance field put.
2804 *
2805 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2806 */
2807 /* op vA, vB, field@CCCC */
2808 mov r0, rINST, lsr #12 @ r0<- B
2809 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
2810 FETCH(r1, 1) @ r1<- field ref CCCC
2811 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2812 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
2813 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
2814 cmp r0, #0 @ is resolved entry null?
2815 bne .LOP_IPUT_SHORT_finish @ no, already resolved
28168: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
2817 EXPORT_PC() @ resolve() could throw
2818 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
2819 bl dvmResolveInstField @ r0<- resolved InstField ptr
2820 cmp r0, #0 @ success?
2821 bne .LOP_IPUT_SHORT_finish @ yes, finish up
2822 b common_exceptionThrown
2823
2824
2825/* ------------------------------ */
2826 .balign 64
2827.L_OP_SGET: /* 0x60 */
2828/* File: armv5te/OP_SGET.S */
2829 /*
2830 * General 32-bit SGET handler.
2831 *
2832 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2833 */
2834 /* op vAA, field@BBBB */
2835 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2836 FETCH(r1, 1) @ r1<- field ref BBBB
2837 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2838 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2839 cmp r0, #0 @ is resolved entry null?
2840 beq .LOP_SGET_resolve @ yes, do resolve
2841.LOP_SGET_finish: @ field ptr in r0
2842 ldr r1, [r0, #offStaticField_value] @ r1<- field value
2843 mov r2, rINST, lsr #8 @ r2<- AA
2844 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2845 SET_VREG(r1, r2) @ fp[AA]<- r1
2846 GET_INST_OPCODE(ip) @ extract opcode from rINST
2847 GOTO_OPCODE(ip) @ jump to next instruction
2848
2849/* ------------------------------ */
2850 .balign 64
2851.L_OP_SGET_WIDE: /* 0x61 */
2852/* File: armv5te/OP_SGET_WIDE.S */
2853 /*
2854 * 64-bit SGET handler.
2855 */
2856 /* sget-wide vAA, field@BBBB */
2857 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2858 FETCH(r1, 1) @ r1<- field ref BBBB
2859 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2860 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2861 cmp r0, #0 @ is resolved entry null?
2862 beq .LOP_SGET_WIDE_resolve @ yes, do resolve
2863.LOP_SGET_WIDE_finish:
Andy McFadden861b3382010-03-05 15:58:31 -08002864 mov r9, rINST, lsr #8 @ r9<- AA
2865 .if 0
2866 add r0, r0, #offStaticField_value @ r0<- pointer to data
2867 bl android_quasiatomic_read_64 @ r0/r1<- contents of field
2868 .else
2869 ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
2870 .endif
2871 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
Andy McFaddena5069fb2009-06-19 15:20:12 -07002872 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
Andy McFadden861b3382010-03-05 15:58:31 -08002873 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
Andy McFaddena5069fb2009-06-19 15:20:12 -07002874 GET_INST_OPCODE(ip) @ extract opcode from rINST
2875 GOTO_OPCODE(ip) @ jump to next instruction
2876
2877/* ------------------------------ */
2878 .balign 64
2879.L_OP_SGET_OBJECT: /* 0x62 */
2880/* File: armv5te/OP_SGET_OBJECT.S */
2881/* File: armv5te/OP_SGET.S */
2882 /*
2883 * General 32-bit SGET handler.
2884 *
2885 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2886 */
2887 /* op vAA, field@BBBB */
2888 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2889 FETCH(r1, 1) @ r1<- field ref BBBB
2890 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2891 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2892 cmp r0, #0 @ is resolved entry null?
2893 beq .LOP_SGET_OBJECT_resolve @ yes, do resolve
2894.LOP_SGET_OBJECT_finish: @ field ptr in r0
2895 ldr r1, [r0, #offStaticField_value] @ r1<- field value
2896 mov r2, rINST, lsr #8 @ r2<- AA
2897 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2898 SET_VREG(r1, r2) @ fp[AA]<- r1
2899 GET_INST_OPCODE(ip) @ extract opcode from rINST
2900 GOTO_OPCODE(ip) @ jump to next instruction
2901
2902
2903/* ------------------------------ */
2904 .balign 64
2905.L_OP_SGET_BOOLEAN: /* 0x63 */
2906/* File: armv5te/OP_SGET_BOOLEAN.S */
2907/* File: armv5te/OP_SGET.S */
2908 /*
2909 * General 32-bit SGET handler.
2910 *
2911 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2912 */
2913 /* op vAA, field@BBBB */
2914 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2915 FETCH(r1, 1) @ r1<- field ref BBBB
2916 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2917 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2918 cmp r0, #0 @ is resolved entry null?
2919 beq .LOP_SGET_BOOLEAN_resolve @ yes, do resolve
2920.LOP_SGET_BOOLEAN_finish: @ field ptr in r0
2921 ldr r1, [r0, #offStaticField_value] @ r1<- field value
2922 mov r2, rINST, lsr #8 @ r2<- AA
2923 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2924 SET_VREG(r1, r2) @ fp[AA]<- r1
2925 GET_INST_OPCODE(ip) @ extract opcode from rINST
2926 GOTO_OPCODE(ip) @ jump to next instruction
2927
2928
2929/* ------------------------------ */
2930 .balign 64
2931.L_OP_SGET_BYTE: /* 0x64 */
2932/* File: armv5te/OP_SGET_BYTE.S */
2933/* File: armv5te/OP_SGET.S */
2934 /*
2935 * General 32-bit SGET handler.
2936 *
2937 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2938 */
2939 /* op vAA, field@BBBB */
2940 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2941 FETCH(r1, 1) @ r1<- field ref BBBB
2942 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2943 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2944 cmp r0, #0 @ is resolved entry null?
2945 beq .LOP_SGET_BYTE_resolve @ yes, do resolve
2946.LOP_SGET_BYTE_finish: @ field ptr in r0
2947 ldr r1, [r0, #offStaticField_value] @ r1<- field value
2948 mov r2, rINST, lsr #8 @ r2<- AA
2949 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2950 SET_VREG(r1, r2) @ fp[AA]<- r1
2951 GET_INST_OPCODE(ip) @ extract opcode from rINST
2952 GOTO_OPCODE(ip) @ jump to next instruction
2953
2954
2955/* ------------------------------ */
2956 .balign 64
2957.L_OP_SGET_CHAR: /* 0x65 */
2958/* File: armv5te/OP_SGET_CHAR.S */
2959/* File: armv5te/OP_SGET.S */
2960 /*
2961 * General 32-bit SGET handler.
2962 *
2963 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2964 */
2965 /* op vAA, field@BBBB */
2966 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2967 FETCH(r1, 1) @ r1<- field ref BBBB
2968 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2969 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2970 cmp r0, #0 @ is resolved entry null?
2971 beq .LOP_SGET_CHAR_resolve @ yes, do resolve
2972.LOP_SGET_CHAR_finish: @ field ptr in r0
2973 ldr r1, [r0, #offStaticField_value] @ r1<- field value
2974 mov r2, rINST, lsr #8 @ r2<- AA
2975 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
2976 SET_VREG(r1, r2) @ fp[AA]<- r1
2977 GET_INST_OPCODE(ip) @ extract opcode from rINST
2978 GOTO_OPCODE(ip) @ jump to next instruction
2979
2980
2981/* ------------------------------ */
2982 .balign 64
2983.L_OP_SGET_SHORT: /* 0x66 */
2984/* File: armv5te/OP_SGET_SHORT.S */
2985/* File: armv5te/OP_SGET.S */
2986 /*
2987 * General 32-bit SGET handler.
2988 *
2989 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2990 */
2991 /* op vAA, field@BBBB */
2992 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
2993 FETCH(r1, 1) @ r1<- field ref BBBB
2994 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2995 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
2996 cmp r0, #0 @ is resolved entry null?
2997 beq .LOP_SGET_SHORT_resolve @ yes, do resolve
2998.LOP_SGET_SHORT_finish: @ field ptr in r0
2999 ldr r1, [r0, #offStaticField_value] @ r1<- field value
3000 mov r2, rINST, lsr #8 @ r2<- AA
3001 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
3002 SET_VREG(r1, r2) @ fp[AA]<- r1
3003 GET_INST_OPCODE(ip) @ extract opcode from rINST
3004 GOTO_OPCODE(ip) @ jump to next instruction
3005
3006
3007/* ------------------------------ */
3008 .balign 64
3009.L_OP_SPUT: /* 0x67 */
3010/* File: armv5te/OP_SPUT.S */
3011 /*
3012 * General 32-bit SPUT handler.
3013 *
3014 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3015 */
3016 /* op vAA, field@BBBB */
3017 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
3018 FETCH(r1, 1) @ r1<- field ref BBBB
3019 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3020 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
3021 cmp r0, #0 @ is resolved entry null?
3022 beq .LOP_SPUT_resolve @ yes, do resolve
3023.LOP_SPUT_finish: @ field ptr in r0
3024 mov r2, rINST, lsr #8 @ r2<- AA
3025 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
3026 GET_VREG(r1, r2) @ r1<- fp[AA]
3027 GET_INST_OPCODE(ip) @ extract opcode from rINST
3028 str r1, [r0, #offStaticField_value] @ field<- vAA
3029 GOTO_OPCODE(ip) @ jump to next instruction
3030
3031/* ------------------------------ */
3032 .balign 64
3033.L_OP_SPUT_WIDE: /* 0x68 */
3034/* File: armv5te/OP_SPUT_WIDE.S */
3035 /*
3036 * 64-bit SPUT handler.
3037 */
3038 /* sput-wide vAA, field@BBBB */
Andy McFadden861b3382010-03-05 15:58:31 -08003039 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex
Andy McFaddena5069fb2009-06-19 15:20:12 -07003040 FETCH(r1, 1) @ r1<- field ref BBBB
Andy McFadden861b3382010-03-05 15:58:31 -08003041 ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
Andy McFaddena5069fb2009-06-19 15:20:12 -07003042 mov r9, rINST, lsr #8 @ r9<- AA
Andy McFadden861b3382010-03-05 15:58:31 -08003043 ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr
Andy McFaddena5069fb2009-06-19 15:20:12 -07003044 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
Andy McFadden861b3382010-03-05 15:58:31 -08003045 cmp r2, #0 @ is resolved entry null?
Andy McFaddena5069fb2009-06-19 15:20:12 -07003046 beq .LOP_SPUT_WIDE_resolve @ yes, do resolve
Andy McFadden861b3382010-03-05 15:58:31 -08003047.LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9
Andy McFaddena5069fb2009-06-19 15:20:12 -07003048 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
Andy McFadden861b3382010-03-05 15:58:31 -08003049 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
3050 GET_INST_OPCODE(r10) @ extract opcode from rINST
3051 .if 0
3052 add r2, r2, #offStaticField_value @ r2<- pointer to data
3053 bl android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
3054 .else
3055 strd r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
3056 .endif
3057 GOTO_OPCODE(r10) @ jump to next instruction
Andy McFaddena5069fb2009-06-19 15:20:12 -07003058
3059/* ------------------------------ */
3060 .balign 64
3061.L_OP_SPUT_OBJECT: /* 0x69 */
3062/* File: armv5te/OP_SPUT_OBJECT.S */
3063/* File: armv5te/OP_SPUT.S */
3064 /*
3065 * General 32-bit SPUT handler.
3066 *
3067 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3068 */
3069 /* op vAA, field@BBBB */
3070 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
3071 FETCH(r1, 1) @ r1<- field ref BBBB
3072 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3073 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
3074 cmp r0, #0 @ is resolved entry null?
3075 beq .LOP_SPUT_OBJECT_resolve @ yes, do resolve
3076.LOP_SPUT_OBJECT_finish: @ field ptr in r0
3077 mov r2, rINST, lsr #8 @ r2<- AA
3078 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
3079 GET_VREG(r1, r2) @ r1<- fp[AA]
3080 GET_INST_OPCODE(ip) @ extract opcode from rINST
3081 str r1, [r0, #offStaticField_value] @ field<- vAA
3082 GOTO_OPCODE(ip) @ jump to next instruction
3083
3084
3085/* ------------------------------ */
3086 .balign 64
3087.L_OP_SPUT_BOOLEAN: /* 0x6a */
3088/* File: armv5te/OP_SPUT_BOOLEAN.S */
3089/* File: armv5te/OP_SPUT.S */
3090 /*
3091 * General 32-bit SPUT handler.
3092 *
3093 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3094 */
3095 /* op vAA, field@BBBB */
3096 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
3097 FETCH(r1, 1) @ r1<- field ref BBBB
3098 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3099 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
3100 cmp r0, #0 @ is resolved entry null?
3101 beq .LOP_SPUT_BOOLEAN_resolve @ yes, do resolve
3102.LOP_SPUT_BOOLEAN_finish: @ field ptr in r0
3103 mov r2, rINST, lsr #8 @ r2<- AA
3104 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
3105 GET_VREG(r1, r2) @ r1<- fp[AA]
3106 GET_INST_OPCODE(ip) @ extract opcode from rINST
3107 str r1, [r0, #offStaticField_value] @ field<- vAA
3108 GOTO_OPCODE(ip) @ jump to next instruction
3109
3110
3111/* ------------------------------ */
3112 .balign 64
3113.L_OP_SPUT_BYTE: /* 0x6b */
3114/* File: armv5te/OP_SPUT_BYTE.S */
3115/* File: armv5te/OP_SPUT.S */
3116 /*
3117 * General 32-bit SPUT handler.
3118 *
3119 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3120 */
3121 /* op vAA, field@BBBB */
3122 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
3123 FETCH(r1, 1) @ r1<- field ref BBBB
3124 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3125 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
3126 cmp r0, #0 @ is resolved entry null?
3127 beq .LOP_SPUT_BYTE_resolve @ yes, do resolve
3128.LOP_SPUT_BYTE_finish: @ field ptr in r0
3129 mov r2, rINST, lsr #8 @ r2<- AA
3130 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
3131 GET_VREG(r1, r2) @ r1<- fp[AA]
3132 GET_INST_OPCODE(ip) @ extract opcode from rINST
3133 str r1, [r0, #offStaticField_value] @ field<- vAA
3134 GOTO_OPCODE(ip) @ jump to next instruction
3135
3136
3137/* ------------------------------ */
3138 .balign 64
3139.L_OP_SPUT_CHAR: /* 0x6c */
3140/* File: armv5te/OP_SPUT_CHAR.S */
3141/* File: armv5te/OP_SPUT.S */
3142 /*
3143 * General 32-bit SPUT handler.
3144 *
3145 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3146 */
3147 /* op vAA, field@BBBB */
3148 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
3149 FETCH(r1, 1) @ r1<- field ref BBBB
3150 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3151 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
3152 cmp r0, #0 @ is resolved entry null?
3153 beq .LOP_SPUT_CHAR_resolve @ yes, do resolve
3154.LOP_SPUT_CHAR_finish: @ field ptr in r0
3155 mov r2, rINST, lsr #8 @ r2<- AA
3156 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
3157 GET_VREG(r1, r2) @ r1<- fp[AA]
3158 GET_INST_OPCODE(ip) @ extract opcode from rINST
3159 str r1, [r0, #offStaticField_value] @ field<- vAA
3160 GOTO_OPCODE(ip) @ jump to next instruction
3161
3162
3163/* ------------------------------ */
3164 .balign 64
3165.L_OP_SPUT_SHORT: /* 0x6d */
3166/* File: armv5te/OP_SPUT_SHORT.S */
3167/* File: armv5te/OP_SPUT.S */
3168 /*
3169 * General 32-bit SPUT handler.
3170 *
3171 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3172 */
3173 /* op vAA, field@BBBB */
3174 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
3175 FETCH(r1, 1) @ r1<- field ref BBBB
3176 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3177 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
3178 cmp r0, #0 @ is resolved entry null?
3179 beq .LOP_SPUT_SHORT_resolve @ yes, do resolve
3180.LOP_SPUT_SHORT_finish: @ field ptr in r0
3181 mov r2, rINST, lsr #8 @ r2<- AA
3182 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
3183 GET_VREG(r1, r2) @ r1<- fp[AA]
3184 GET_INST_OPCODE(ip) @ extract opcode from rINST
3185 str r1, [r0, #offStaticField_value] @ field<- vAA
3186 GOTO_OPCODE(ip) @ jump to next instruction
3187
3188
3189/* ------------------------------ */
3190 .balign 64
3191.L_OP_INVOKE_VIRTUAL: /* 0x6e */
3192/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3193 /*
3194 * Handle a virtual method call.
3195 *
3196 * for: invoke-virtual, invoke-virtual/range
3197 */
3198 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3199 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3200 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3201 FETCH(r1, 1) @ r1<- BBBB
3202 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3203 FETCH(r10, 2) @ r10<- GFED or CCCC
3204 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod
3205 .if (!0)
3206 and r10, r10, #15 @ r10<- D (or stays CCCC)
3207 .endif
3208 cmp r0, #0 @ already resolved?
3209 EXPORT_PC() @ must export for invoke
3210 bne .LOP_INVOKE_VIRTUAL_continue @ yes, continue on
3211 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3212 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
3213 mov r2, #METHOD_VIRTUAL @ resolver method type
3214 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
3215 cmp r0, #0 @ got null?
3216 bne .LOP_INVOKE_VIRTUAL_continue @ no, continue
3217 b common_exceptionThrown @ yes, handle exception
3218
3219/* ------------------------------ */
3220 .balign 64
3221.L_OP_INVOKE_SUPER: /* 0x6f */
3222/* File: armv5te/OP_INVOKE_SUPER.S */
3223 /*
3224 * Handle a "super" method call.
3225 *
3226 * for: invoke-super, invoke-super/range
3227 */
3228 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3229 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3230 FETCH(r10, 2) @ r10<- GFED or CCCC
3231 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3232 .if (!0)
3233 and r10, r10, #15 @ r10<- D (or stays CCCC)
3234 .endif
3235 FETCH(r1, 1) @ r1<- BBBB
3236 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3237 GET_VREG(r2, r10) @ r2<- "this" ptr
3238 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod
3239 cmp r2, #0 @ null "this"?
3240 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method
3241 beq common_errNullObject @ null "this", throw exception
3242 cmp r0, #0 @ already resolved?
3243 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz
3244 EXPORT_PC() @ must export for invoke
3245 bne .LOP_INVOKE_SUPER_continue @ resolved, continue on
3246 b .LOP_INVOKE_SUPER_resolve @ do resolve now
3247
3248/* ------------------------------ */
3249 .balign 64
3250.L_OP_INVOKE_DIRECT: /* 0x70 */
3251/* File: armv5te/OP_INVOKE_DIRECT.S */
3252 /*
3253 * Handle a direct method call.
3254 *
3255 * (We could defer the "is 'this' pointer null" test to the common
3256 * method invocation code, and use a flag to indicate that static
3257 * calls don't count. If we do this as part of copying the arguments
3258 * out we could avoiding loading the first arg twice.)
3259 *
3260 * for: invoke-direct, invoke-direct/range
3261 */
3262 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3263 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3264 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3265 FETCH(r1, 1) @ r1<- BBBB
3266 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3267 FETCH(r10, 2) @ r10<- GFED or CCCC
3268 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall
3269 .if (!0)
3270 and r10, r10, #15 @ r10<- D (or stays CCCC)
3271 .endif
3272 cmp r0, #0 @ already resolved?
3273 EXPORT_PC() @ must export for invoke
3274 GET_VREG(r2, r10) @ r2<- "this" ptr
3275 beq .LOP_INVOKE_DIRECT_resolve @ not resolved, do it now
3276.LOP_INVOKE_DIRECT_finish:
3277 cmp r2, #0 @ null "this" ref?
3278 bne common_invokeMethodNoRange @ no, continue on
3279 b common_errNullObject @ yes, throw exception
3280
3281/* ------------------------------ */
3282 .balign 64
3283.L_OP_INVOKE_STATIC: /* 0x71 */
3284/* File: armv5te/OP_INVOKE_STATIC.S */
3285 /*
3286 * Handle a static method call.
3287 *
3288 * for: invoke-static, invoke-static/range
3289 */
3290 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3291 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3292 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3293 FETCH(r1, 1) @ r1<- BBBB
3294 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3295 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall
3296 cmp r0, #0 @ already resolved?
3297 EXPORT_PC() @ must export for invoke
3298 bne common_invokeMethodNoRange @ yes, continue on
32990: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3300 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
3301 mov r2, #METHOD_STATIC @ resolver method type
3302 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
3303 cmp r0, #0 @ got null?
3304 bne common_invokeMethodNoRange @ no, continue
3305 b common_exceptionThrown @ yes, handle exception
3306
3307
3308/* ------------------------------ */
3309 .balign 64
3310.L_OP_INVOKE_INTERFACE: /* 0x72 */
3311/* File: armv5te/OP_INVOKE_INTERFACE.S */
3312 /*
3313 * Handle an interface method call.
3314 *
3315 * for: invoke-interface, invoke-interface/range
3316 */
3317 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3318 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3319 FETCH(r2, 2) @ r2<- FEDC or CCCC
3320 FETCH(r1, 1) @ r1<- BBBB
3321 .if (!0)
3322 and r2, r2, #15 @ r2<- C (or stays CCCC)
3323 .endif
3324 EXPORT_PC() @ must export for invoke
3325 GET_VREG(r0, r2) @ r0<- first arg ("this")
3326 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex
3327 cmp r0, #0 @ null obj?
3328 ldr r2, [rGLUE, #offGlue_method] @ r2<- method
3329 beq common_errNullObject @ yes, fail
3330 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz
3331 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3332 cmp r0, #0 @ failed?
3333 beq common_exceptionThrown @ yes, handle exception
3334 b common_invokeMethodNoRange @ jump to common handler
3335
3336
3337/* ------------------------------ */
3338 .balign 64
3339.L_OP_UNUSED_73: /* 0x73 */
3340/* File: armv5te/OP_UNUSED_73.S */
3341/* File: armv5te/unused.S */
3342 bl common_abort
3343
3344
3345
3346/* ------------------------------ */
3347 .balign 64
3348.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
3349/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */
3350/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3351 /*
3352 * Handle a virtual method call.
3353 *
3354 * for: invoke-virtual, invoke-virtual/range
3355 */
3356 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3357 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3358 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3359 FETCH(r1, 1) @ r1<- BBBB
3360 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3361 FETCH(r10, 2) @ r10<- GFED or CCCC
3362 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod
3363 .if (!1)
3364 and r10, r10, #15 @ r10<- D (or stays CCCC)
3365 .endif
3366 cmp r0, #0 @ already resolved?
3367 EXPORT_PC() @ must export for invoke
3368 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ yes, continue on
3369 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3370 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
3371 mov r2, #METHOD_VIRTUAL @ resolver method type
3372 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
3373 cmp r0, #0 @ got null?
3374 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ no, continue
3375 b common_exceptionThrown @ yes, handle exception
3376
3377
3378/* ------------------------------ */
3379 .balign 64
3380.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
3381/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */
3382/* File: armv5te/OP_INVOKE_SUPER.S */
3383 /*
3384 * Handle a "super" method call.
3385 *
3386 * for: invoke-super, invoke-super/range
3387 */
3388 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3389 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3390 FETCH(r10, 2) @ r10<- GFED or CCCC
3391 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3392 .if (!1)
3393 and r10, r10, #15 @ r10<- D (or stays CCCC)
3394 .endif
3395 FETCH(r1, 1) @ r1<- BBBB
3396 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3397 GET_VREG(r2, r10) @ r2<- "this" ptr
3398 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod
3399 cmp r2, #0 @ null "this"?
3400 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method
3401 beq common_errNullObject @ null "this", throw exception
3402 cmp r0, #0 @ already resolved?
3403 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz
3404 EXPORT_PC() @ must export for invoke
3405 bne .LOP_INVOKE_SUPER_RANGE_continue @ resolved, continue on
3406 b .LOP_INVOKE_SUPER_RANGE_resolve @ do resolve now
3407
3408
3409/* ------------------------------ */
3410 .balign 64
3411.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
3412/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */
3413/* File: armv5te/OP_INVOKE_DIRECT.S */
3414 /*
3415 * Handle a direct method call.
3416 *
3417 * (We could defer the "is 'this' pointer null" test to the common
3418 * method invocation code, and use a flag to indicate that static
3419 * calls don't count. If we do this as part of copying the arguments
3420 * out we could avoiding loading the first arg twice.)
3421 *
3422 * for: invoke-direct, invoke-direct/range
3423 */
3424 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3425 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3426 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3427 FETCH(r1, 1) @ r1<- BBBB
3428 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3429 FETCH(r10, 2) @ r10<- GFED or CCCC
3430 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall
3431 .if (!1)
3432 and r10, r10, #15 @ r10<- D (or stays CCCC)
3433 .endif
3434 cmp r0, #0 @ already resolved?
3435 EXPORT_PC() @ must export for invoke
3436 GET_VREG(r2, r10) @ r2<- "this" ptr
3437 beq .LOP_INVOKE_DIRECT_RANGE_resolve @ not resolved, do it now
3438.LOP_INVOKE_DIRECT_RANGE_finish:
3439 cmp r2, #0 @ null "this" ref?
3440 bne common_invokeMethodRange @ no, continue on
3441 b common_errNullObject @ yes, throw exception
3442
3443
3444/* ------------------------------ */
3445 .balign 64
3446.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
3447/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */
3448/* File: armv5te/OP_INVOKE_STATIC.S */
3449 /*
3450 * Handle a static method call.
3451 *
3452 * for: invoke-static, invoke-static/range
3453 */
3454 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3455 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3456 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex
3457 FETCH(r1, 1) @ r1<- BBBB
3458 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods
3459 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall
3460 cmp r0, #0 @ already resolved?
3461 EXPORT_PC() @ must export for invoke
3462 bne common_invokeMethodRange @ yes, continue on
34630: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3464 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
3465 mov r2, #METHOD_STATIC @ resolver method type
3466 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
3467 cmp r0, #0 @ got null?
3468 bne common_invokeMethodRange @ no, continue
3469 b common_exceptionThrown @ yes, handle exception
3470
3471
3472
3473/* ------------------------------ */
3474 .balign 64
3475.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
3476/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */
3477/* File: armv5te/OP_INVOKE_INTERFACE.S */
3478 /*
3479 * Handle an interface method call.
3480 *
3481 * for: invoke-interface, invoke-interface/range
3482 */
3483 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3484 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3485 FETCH(r2, 2) @ r2<- FEDC or CCCC
3486 FETCH(r1, 1) @ r1<- BBBB
3487 .if (!1)
3488 and r2, r2, #15 @ r2<- C (or stays CCCC)
3489 .endif
3490 EXPORT_PC() @ must export for invoke
3491 GET_VREG(r0, r2) @ r0<- first arg ("this")
3492 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex
3493 cmp r0, #0 @ null obj?
3494 ldr r2, [rGLUE, #offGlue_method] @ r2<- method
3495 beq common_errNullObject @ yes, fail
3496 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz
3497 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3498 cmp r0, #0 @ failed?
3499 beq common_exceptionThrown @ yes, handle exception
3500 b common_invokeMethodRange @ jump to common handler
3501
3502
3503
3504/* ------------------------------ */
3505 .balign 64
3506.L_OP_UNUSED_79: /* 0x79 */
3507/* File: armv5te/OP_UNUSED_79.S */
3508/* File: armv5te/unused.S */
3509 bl common_abort
3510
3511
3512
3513/* ------------------------------ */
3514 .balign 64
3515.L_OP_UNUSED_7A: /* 0x7a */
3516/* File: armv5te/OP_UNUSED_7A.S */
3517/* File: armv5te/unused.S */
3518 bl common_abort
3519
3520
3521
3522/* ------------------------------ */
3523 .balign 64
3524.L_OP_NEG_INT: /* 0x7b */
3525/* File: armv6t2/OP_NEG_INT.S */
3526/* File: armv6t2/unop.S */
3527 /*
3528 * Generic 32-bit unary operation. Provide an "instr" line that
3529 * specifies an instruction that performs "result = op r0".
3530 * This could be an ARM instruction or a function call.
3531 *
3532 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3533 * int-to-byte, int-to-char, int-to-short
3534 */
3535 /* unop vA, vB */
3536 mov r3, rINST, lsr #12 @ r3<- B
3537 ubfx r9, rINST, #8, #4 @ r9<- A
3538 GET_VREG(r0, r3) @ r0<- vB
3539 @ optional op; may set condition codes
3540 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3541 rsb r0, r0, #0 @ r0<- op, r0-r3 changed
3542 GET_INST_OPCODE(ip) @ extract opcode from rINST
3543 SET_VREG(r0, r9) @ vAA<- r0
3544 GOTO_OPCODE(ip) @ jump to next instruction
3545 /* 8-9 instructions */
3546
3547
3548/* ------------------------------ */
3549 .balign 64
3550.L_OP_NOT_INT: /* 0x7c */
3551/* File: armv6t2/OP_NOT_INT.S */
3552/* File: armv6t2/unop.S */
3553 /*
3554 * Generic 32-bit unary operation. Provide an "instr" line that
3555 * specifies an instruction that performs "result = op r0".
3556 * This could be an ARM instruction or a function call.
3557 *
3558 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3559 * int-to-byte, int-to-char, int-to-short
3560 */
3561 /* unop vA, vB */
3562 mov r3, rINST, lsr #12 @ r3<- B
3563 ubfx r9, rINST, #8, #4 @ r9<- A
3564 GET_VREG(r0, r3) @ r0<- vB
3565 @ optional op; may set condition codes
3566 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3567 mvn r0, r0 @ r0<- op, r0-r3 changed
3568 GET_INST_OPCODE(ip) @ extract opcode from rINST
3569 SET_VREG(r0, r9) @ vAA<- r0
3570 GOTO_OPCODE(ip) @ jump to next instruction
3571 /* 8-9 instructions */
3572
3573
3574/* ------------------------------ */
3575 .balign 64
3576.L_OP_NEG_LONG: /* 0x7d */
3577/* File: armv6t2/OP_NEG_LONG.S */
3578/* File: armv6t2/unopWide.S */
3579 /*
3580 * Generic 64-bit unary operation. Provide an "instr" line that
3581 * specifies an instruction that performs "result = op r0/r1".
3582 * This could be an ARM instruction or a function call.
3583 *
3584 * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3585 */
3586 /* unop vA, vB */
3587 mov r3, rINST, lsr #12 @ r3<- B
3588 ubfx r9, rINST, #8, #4 @ r9<- A
3589 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
3590 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3591 ldmia r3, {r0-r1} @ r0/r1<- vAA
3592 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3593 rsbs r0, r0, #0 @ optional op; may set condition codes
3594 rsc r1, r1, #0 @ r0/r1<- op, r2-r3 changed
3595 GET_INST_OPCODE(ip) @ extract opcode from rINST
3596 stmia r9, {r0-r1} @ vAA<- r0/r1
3597 GOTO_OPCODE(ip) @ jump to next instruction
3598 /* 10-11 instructions */
3599
3600
3601
3602/* ------------------------------ */
3603 .balign 64
3604.L_OP_NOT_LONG: /* 0x7e */
3605/* File: armv6t2/OP_NOT_LONG.S */
3606/* File: armv6t2/unopWide.S */
3607 /*
3608 * Generic 64-bit unary operation. Provide an "instr" line that
3609 * specifies an instruction that performs "result = op r0/r1".
3610 * This could be an ARM instruction or a function call.
3611 *
3612 * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3613 */
3614 /* unop vA, vB */
3615 mov r3, rINST, lsr #12 @ r3<- B
3616 ubfx r9, rINST, #8, #4 @ r9<- A
3617 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
3618 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3619 ldmia r3, {r0-r1} @ r0/r1<- vAA
3620 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3621 mvn r0, r0 @ optional op; may set condition codes
3622 mvn r1, r1 @ r0/r1<- op, r2-r3 changed
3623 GET_INST_OPCODE(ip) @ extract opcode from rINST
3624 stmia r9, {r0-r1} @ vAA<- r0/r1
3625 GOTO_OPCODE(ip) @ jump to next instruction
3626 /* 10-11 instructions */
3627
3628
3629
3630/* ------------------------------ */
3631 .balign 64
3632.L_OP_NEG_FLOAT: /* 0x7f */
3633/* File: armv6t2/OP_NEG_FLOAT.S */
3634/* File: armv6t2/unop.S */
3635 /*
3636 * Generic 32-bit unary operation. Provide an "instr" line that
3637 * specifies an instruction that performs "result = op r0".
3638 * This could be an ARM instruction or a function call.
3639 *
3640 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3641 * int-to-byte, int-to-char, int-to-short
3642 */
3643 /* unop vA, vB */
3644 mov r3, rINST, lsr #12 @ r3<- B
3645 ubfx r9, rINST, #8, #4 @ r9<- A
3646 GET_VREG(r0, r3) @ r0<- vB
3647 @ optional op; may set condition codes
3648 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3649 add r0, r0, #0x80000000 @ r0<- op, r0-r3 changed
3650 GET_INST_OPCODE(ip) @ extract opcode from rINST
3651 SET_VREG(r0, r9) @ vAA<- r0
3652 GOTO_OPCODE(ip) @ jump to next instruction
3653 /* 8-9 instructions */
3654
3655
3656/* ------------------------------ */
3657 .balign 64
3658.L_OP_NEG_DOUBLE: /* 0x80 */
3659/* File: armv6t2/OP_NEG_DOUBLE.S */
3660/* File: armv6t2/unopWide.S */
3661 /*
3662 * Generic 64-bit unary operation. Provide an "instr" line that
3663 * specifies an instruction that performs "result = op r0/r1".
3664 * This could be an ARM instruction or a function call.
3665 *
3666 * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3667 */
3668 /* unop vA, vB */
3669 mov r3, rINST, lsr #12 @ r3<- B
3670 ubfx r9, rINST, #8, #4 @ r9<- A
3671 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
3672 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3673 ldmia r3, {r0-r1} @ r0/r1<- vAA
3674 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3675 @ optional op; may set condition codes
3676 add r1, r1, #0x80000000 @ r0/r1<- op, r2-r3 changed
3677 GET_INST_OPCODE(ip) @ extract opcode from rINST
3678 stmia r9, {r0-r1} @ vAA<- r0/r1
3679 GOTO_OPCODE(ip) @ jump to next instruction
3680 /* 10-11 instructions */
3681
3682
3683
3684/* ------------------------------ */
3685 .balign 64
3686.L_OP_INT_TO_LONG: /* 0x81 */
3687/* File: armv6t2/OP_INT_TO_LONG.S */
3688/* File: armv6t2/unopWider.S */
3689 /*
3690 * Generic 32bit-to-64bit unary operation. Provide an "instr" line
3691 * that specifies an instruction that performs "result = op r0", where
3692 * "result" is a 64-bit quantity in r0/r1.
3693 *
3694 * For: int-to-long, int-to-double, float-to-long, float-to-double
3695 */
3696 /* unop vA, vB */
3697 mov r3, rINST, lsr #12 @ r3<- B
3698 ubfx r9, rINST, #8, #4 @ r9<- A
3699 GET_VREG(r0, r3) @ r0<- vB
3700 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3701 @ optional op; may set condition codes
3702 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3703 mov r1, r0, asr #31 @ r0<- op, r0-r3 changed
3704 GET_INST_OPCODE(ip) @ extract opcode from rINST
3705 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1
3706 GOTO_OPCODE(ip) @ jump to next instruction
3707 /* 9-10 instructions */
3708
3709
3710/* ------------------------------ */
3711 .balign 64
3712.L_OP_INT_TO_FLOAT: /* 0x82 */
3713/* File: arm-vfp/OP_INT_TO_FLOAT.S */
3714/* File: arm-vfp/funop.S */
3715 /*
3716 * Generic 32-bit unary floating-point operation. Provide an "instr"
3717 * line that specifies an instruction that performs "s1 = op s0".
3718 *
3719 * for: int-to-float, float-to-int
3720 */
3721 /* unop vA, vB */
3722 mov r3, rINST, lsr #12 @ r3<- B
3723 mov r9, rINST, lsr #8 @ r9<- A+
3724 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
3725 flds s0, [r3] @ s0<- vB
3726 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3727 and r9, r9, #15 @ r9<- A
3728 fsitos s1, s0 @ s1<- op
3729 GET_INST_OPCODE(ip) @ extract opcode from rINST
3730 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
3731 fsts s1, [r9] @ vA<- s1
3732 GOTO_OPCODE(ip) @ jump to next instruction
3733
3734
3735/* ------------------------------ */
3736 .balign 64
3737.L_OP_INT_TO_DOUBLE: /* 0x83 */
3738/* File: arm-vfp/OP_INT_TO_DOUBLE.S */
3739/* File: arm-vfp/funopWider.S */
3740 /*
3741 * Generic 32bit-to-64bit floating point unary operation. Provide an
3742 * "instr" line that specifies an instruction that performs "d0 = op s0".
3743 *
3744 * For: int-to-double, float-to-double
3745 */
3746 /* unop vA, vB */
3747 mov r3, rINST, lsr #12 @ r3<- B
3748 mov r9, rINST, lsr #8 @ r9<- A+
3749 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
3750 flds s0, [r3] @ s0<- vB
3751 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3752 and r9, r9, #15 @ r9<- A
3753 fsitod d0, s0 @ d0<- op
3754 GET_INST_OPCODE(ip) @ extract opcode from rINST
3755 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
3756 fstd d0, [r9] @ vA<- d0
3757 GOTO_OPCODE(ip) @ jump to next instruction
3758
3759
3760/* ------------------------------ */
3761 .balign 64
3762.L_OP_LONG_TO_INT: /* 0x84 */
3763/* File: armv5te/OP_LONG_TO_INT.S */
3764/* we ignore the high word, making this equivalent to a 32-bit reg move */
3765/* File: armv5te/OP_MOVE.S */
3766 /* for move, move-object, long-to-int */
3767 /* op vA, vB */
3768 mov r1, rINST, lsr #12 @ r1<- B from 15:12
3769 mov r0, rINST, lsr #8 @ r0<- A from 11:8
3770 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3771 GET_VREG(r2, r1) @ r2<- fp[B]
3772 and r0, r0, #15
3773 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
3774 SET_VREG(r2, r0) @ fp[A]<- r2
3775 GOTO_OPCODE(ip) @ execute next instruction
3776
3777
3778
3779/* ------------------------------ */
3780 .balign 64
3781.L_OP_LONG_TO_FLOAT: /* 0x85 */
3782/* File: armv6t2/OP_LONG_TO_FLOAT.S */
3783/* File: armv6t2/unopNarrower.S */
3784 /*
3785 * Generic 64bit-to-32bit unary operation. Provide an "instr" line
3786 * that specifies an instruction that performs "result = op r0/r1", where
3787 * "result" is a 32-bit quantity in r0.
3788 *
3789 * For: long-to-float, double-to-int, double-to-float
3790 *
3791 * (This would work for long-to-int, but that instruction is actually
3792 * an exact match for OP_MOVE.)
3793 */
3794 /* unop vA, vB */
3795 mov r3, rINST, lsr #12 @ r3<- B
3796 ubfx r9, rINST, #8, #4 @ r9<- A
3797 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
3798 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1
3799 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3800 @ optional op; may set condition codes
3801 bl __aeabi_l2f @ r0<- op, r0-r3 changed
3802 GET_INST_OPCODE(ip) @ extract opcode from rINST
3803 SET_VREG(r0, r9) @ vA<- r0
3804 GOTO_OPCODE(ip) @ jump to next instruction
3805 /* 9-10 instructions */
3806
3807
3808/* ------------------------------ */
3809 .balign 64
3810.L_OP_LONG_TO_DOUBLE: /* 0x86 */
3811/* File: armv6t2/OP_LONG_TO_DOUBLE.S */
3812/* File: armv6t2/unopWide.S */
3813 /*
3814 * Generic 64-bit unary operation. Provide an "instr" line that
3815 * specifies an instruction that performs "result = op r0/r1".
3816 * This could be an ARM instruction or a function call.
3817 *
3818 * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3819 */
3820 /* unop vA, vB */
3821 mov r3, rINST, lsr #12 @ r3<- B
3822 ubfx r9, rINST, #8, #4 @ r9<- A
3823 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
3824 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3825 ldmia r3, {r0-r1} @ r0/r1<- vAA
3826 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3827 @ optional op; may set condition codes
3828 bl __aeabi_l2d @ r0/r1<- op, r2-r3 changed
3829 GET_INST_OPCODE(ip) @ extract opcode from rINST
3830 stmia r9, {r0-r1} @ vAA<- r0/r1
3831 GOTO_OPCODE(ip) @ jump to next instruction
3832 /* 10-11 instructions */
3833
3834
3835
3836/* ------------------------------ */
3837 .balign 64
3838.L_OP_FLOAT_TO_INT: /* 0x87 */
3839/* File: arm-vfp/OP_FLOAT_TO_INT.S */
3840/* File: arm-vfp/funop.S */
3841 /*
3842 * Generic 32-bit unary floating-point operation. Provide an "instr"
3843 * line that specifies an instruction that performs "s1 = op s0".
3844 *
3845 * for: int-to-float, float-to-int
3846 */
3847 /* unop vA, vB */
3848 mov r3, rINST, lsr #12 @ r3<- B
3849 mov r9, rINST, lsr #8 @ r9<- A+
3850 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
3851 flds s0, [r3] @ s0<- vB
3852 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3853 and r9, r9, #15 @ r9<- A
3854 ftosizs s1, s0 @ s1<- op
3855 GET_INST_OPCODE(ip) @ extract opcode from rINST
3856 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
3857 fsts s1, [r9] @ vA<- s1
3858 GOTO_OPCODE(ip) @ jump to next instruction
3859
3860
3861/* ------------------------------ */
3862 .balign 64
3863.L_OP_FLOAT_TO_LONG: /* 0x88 */
3864/* File: armv6t2/OP_FLOAT_TO_LONG.S */
3865@include "armv6t2/unopWider.S" {"instr":"bl __aeabi_f2lz"}
3866/* File: armv6t2/unopWider.S */
3867 /*
3868 * Generic 32bit-to-64bit unary operation. Provide an "instr" line
3869 * that specifies an instruction that performs "result = op r0", where
3870 * "result" is a 64-bit quantity in r0/r1.
3871 *
3872 * For: int-to-long, int-to-double, float-to-long, float-to-double
3873 */
3874 /* unop vA, vB */
3875 mov r3, rINST, lsr #12 @ r3<- B
3876 ubfx r9, rINST, #8, #4 @ r9<- A
3877 GET_VREG(r0, r3) @ r0<- vB
3878 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3879 @ optional op; may set condition codes
3880 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3881 bl f2l_doconv @ r0<- op, r0-r3 changed
3882 GET_INST_OPCODE(ip) @ extract opcode from rINST
3883 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1
3884 GOTO_OPCODE(ip) @ jump to next instruction
3885 /* 9-10 instructions */
3886
3887
3888
3889/* ------------------------------ */
3890 .balign 64
3891.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
3892/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */
3893/* File: arm-vfp/funopWider.S */
3894 /*
3895 * Generic 32bit-to-64bit floating point unary operation. Provide an
3896 * "instr" line that specifies an instruction that performs "d0 = op s0".
3897 *
3898 * For: int-to-double, float-to-double
3899 */
3900 /* unop vA, vB */
3901 mov r3, rINST, lsr #12 @ r3<- B
3902 mov r9, rINST, lsr #8 @ r9<- A+
3903 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
3904 flds s0, [r3] @ s0<- vB
3905 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3906 and r9, r9, #15 @ r9<- A
3907 fcvtds d0, s0 @ d0<- op
3908 GET_INST_OPCODE(ip) @ extract opcode from rINST
3909 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
3910 fstd d0, [r9] @ vA<- d0
3911 GOTO_OPCODE(ip) @ jump to next instruction
3912
3913
3914/* ------------------------------ */
3915 .balign 64
3916.L_OP_DOUBLE_TO_INT: /* 0x8a */
3917/* File: arm-vfp/OP_DOUBLE_TO_INT.S */
3918/* File: arm-vfp/funopNarrower.S */
3919 /*
3920 * Generic 64bit-to-32bit unary floating point operation. Provide an
3921 * "instr" line that specifies an instruction that performs "s0 = op d0".
3922 *
3923 * For: double-to-int, double-to-float
3924 */
3925 /* unop vA, vB */
3926 mov r3, rINST, lsr #12 @ r3<- B
3927 mov r9, rINST, lsr #8 @ r9<- A+
3928 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
3929 fldd d0, [r3] @ d0<- vB
3930 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3931 and r9, r9, #15 @ r9<- A
3932 ftosizd s0, d0 @ s0<- op
3933 GET_INST_OPCODE(ip) @ extract opcode from rINST
3934 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
3935 fsts s0, [r9] @ vA<- s0
3936 GOTO_OPCODE(ip) @ jump to next instruction
3937
3938
3939/* ------------------------------ */
3940 .balign 64
3941.L_OP_DOUBLE_TO_LONG: /* 0x8b */
3942/* File: armv6t2/OP_DOUBLE_TO_LONG.S */
3943@include "armv6t2/unopWide.S" {"instr":"bl __aeabi_d2lz"}
3944/* File: armv6t2/unopWide.S */
3945 /*
3946 * Generic 64-bit unary operation. Provide an "instr" line that
3947 * specifies an instruction that performs "result = op r0/r1".
3948 * This could be an ARM instruction or a function call.
3949 *
3950 * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3951 */
3952 /* unop vA, vB */
3953 mov r3, rINST, lsr #12 @ r3<- B
3954 ubfx r9, rINST, #8, #4 @ r9<- A
3955 add r3, rFP, r3, lsl #2 @ r3<- &fp[B]
3956 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
3957 ldmia r3, {r0-r1} @ r0/r1<- vAA
3958 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3959 @ optional op; may set condition codes
3960 bl d2l_doconv @ r0/r1<- op, r2-r3 changed
3961 GET_INST_OPCODE(ip) @ extract opcode from rINST
3962 stmia r9, {r0-r1} @ vAA<- r0/r1
3963 GOTO_OPCODE(ip) @ jump to next instruction
3964 /* 10-11 instructions */
3965
3966
3967
3968
3969/* ------------------------------ */
3970 .balign 64
3971.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
3972/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */
3973/* File: arm-vfp/funopNarrower.S */
3974 /*
3975 * Generic 64bit-to-32bit unary floating point operation. Provide an
3976 * "instr" line that specifies an instruction that performs "s0 = op d0".
3977 *
3978 * For: double-to-int, double-to-float
3979 */
3980 /* unop vA, vB */
3981 mov r3, rINST, lsr #12 @ r3<- B
3982 mov r9, rINST, lsr #8 @ r9<- A+
3983 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
3984 fldd d0, [r3] @ d0<- vB
3985 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
3986 and r9, r9, #15 @ r9<- A
3987 fcvtsd s0, d0 @ s0<- op
3988 GET_INST_OPCODE(ip) @ extract opcode from rINST
3989 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
3990 fsts s0, [r9] @ vA<- s0
3991 GOTO_OPCODE(ip) @ jump to next instruction
3992
3993
3994/* ------------------------------ */
3995 .balign 64
3996.L_OP_INT_TO_BYTE: /* 0x8d */
3997/* File: armv6t2/OP_INT_TO_BYTE.S */
3998/* File: armv6t2/unop.S */
3999 /*
4000 * Generic 32-bit unary operation. Provide an "instr" line that
4001 * specifies an instruction that performs "result = op r0".
4002 * This could be an ARM instruction or a function call.
4003 *
4004 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4005 * int-to-byte, int-to-char, int-to-short
4006 */
4007 /* unop vA, vB */
4008 mov r3, rINST, lsr #12 @ r3<- B
4009 ubfx r9, rINST, #8, #4 @ r9<- A
4010 GET_VREG(r0, r3) @ r0<- vB
4011 @ optional op; may set condition codes
4012 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
4013 sxtb r0, r0 @ r0<- op, r0-r3 changed
4014 GET_INST_OPCODE(ip) @ extract opcode from rINST
4015 SET_VREG(r0, r9) @ vAA<- r0
4016 GOTO_OPCODE(ip) @ jump to next instruction
4017 /* 8-9 instructions */
4018
4019
4020/* ------------------------------ */
4021 .balign 64
4022.L_OP_INT_TO_CHAR: /* 0x8e */
4023/* File: armv6t2/OP_INT_TO_CHAR.S */
4024/* File: armv6t2/unop.S */
4025 /*
4026 * Generic 32-bit unary operation. Provide an "instr" line that
4027 * specifies an instruction that performs "result = op r0".
4028 * This could be an ARM instruction or a function call.
4029 *
4030 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4031 * int-to-byte, int-to-char, int-to-short
4032 */
4033 /* unop vA, vB */
4034 mov r3, rINST, lsr #12 @ r3<- B
4035 ubfx r9, rINST, #8, #4 @ r9<- A
4036 GET_VREG(r0, r3) @ r0<- vB
4037 @ optional op; may set condition codes
4038 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
4039 uxth r0, r0 @ r0<- op, r0-r3 changed
4040 GET_INST_OPCODE(ip) @ extract opcode from rINST
4041 SET_VREG(r0, r9) @ vAA<- r0
4042 GOTO_OPCODE(ip) @ jump to next instruction
4043 /* 8-9 instructions */
4044
4045
4046/* ------------------------------ */
4047 .balign 64
4048.L_OP_INT_TO_SHORT: /* 0x8f */
4049/* File: armv6t2/OP_INT_TO_SHORT.S */
4050/* File: armv6t2/unop.S */
4051 /*
4052 * Generic 32-bit unary operation. Provide an "instr" line that
4053 * specifies an instruction that performs "result = op r0".
4054 * This could be an ARM instruction or a function call.
4055 *
4056 * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4057 * int-to-byte, int-to-char, int-to-short
4058 */
4059 /* unop vA, vB */
4060 mov r3, rINST, lsr #12 @ r3<- B
4061 ubfx r9, rINST, #8, #4 @ r9<- A
4062 GET_VREG(r0, r3) @ r0<- vB
4063 @ optional op; may set condition codes
4064 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
4065 sxth r0, r0 @ r0<- op, r0-r3 changed
4066 GET_INST_OPCODE(ip) @ extract opcode from rINST
4067 SET_VREG(r0, r9) @ vAA<- r0
4068 GOTO_OPCODE(ip) @ jump to next instruction
4069 /* 8-9 instructions */
4070
4071
4072/* ------------------------------ */
4073 .balign 64
4074.L_OP_ADD_INT: /* 0x90 */
4075/* File: armv5te/OP_ADD_INT.S */
4076/* File: armv5te/binop.S */
4077 /*
4078 * Generic 32-bit binary operation. Provide an "instr" line that
4079 * specifies an instruction that performs "result = r0 op r1".
4080 * This could be an ARM instruction or a function call. (If the result
4081 * comes back in a register other than r0, you can override "result".)
4082 *
4083 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4084 * vCC (r1). Useful for integer division and modulus. Note that we
4085 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4086 * handles it correctly.
4087 *
4088 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4089 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4090 * mul-float, div-float, rem-float
4091 */
4092 /* binop vAA, vBB, vCC */
4093 FETCH(r0, 1) @ r0<- CCBB
4094 mov r9, rINST, lsr #8 @ r9<- AA
4095 mov r3, r0, lsr #8 @ r3<- CC
4096 and r2, r0, #255 @ r2<- BB
4097 GET_VREG(r1, r3) @ r1<- vCC
4098 GET_VREG(r0, r2) @ r0<- vBB
4099 .if 0
4100 cmp r1, #0 @ is second operand zero?
4101 beq common_errDivideByZero
4102 .endif
4103
4104 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4105 @ optional op; may set condition codes
4106 add r0, r0, r1 @ r0<- op, r0-r3 changed
4107 GET_INST_OPCODE(ip) @ extract opcode from rINST
4108 SET_VREG(r0, r9) @ vAA<- r0
4109 GOTO_OPCODE(ip) @ jump to next instruction
4110 /* 11-14 instructions */
4111
4112
4113
4114/* ------------------------------ */
4115 .balign 64
4116.L_OP_SUB_INT: /* 0x91 */
4117/* File: armv5te/OP_SUB_INT.S */
4118/* File: armv5te/binop.S */
4119 /*
4120 * Generic 32-bit binary operation. Provide an "instr" line that
4121 * specifies an instruction that performs "result = r0 op r1".
4122 * This could be an ARM instruction or a function call. (If the result
4123 * comes back in a register other than r0, you can override "result".)
4124 *
4125 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4126 * vCC (r1). Useful for integer division and modulus. Note that we
4127 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4128 * handles it correctly.
4129 *
4130 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4131 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4132 * mul-float, div-float, rem-float
4133 */
4134 /* binop vAA, vBB, vCC */
4135 FETCH(r0, 1) @ r0<- CCBB
4136 mov r9, rINST, lsr #8 @ r9<- AA
4137 mov r3, r0, lsr #8 @ r3<- CC
4138 and r2, r0, #255 @ r2<- BB
4139 GET_VREG(r1, r3) @ r1<- vCC
4140 GET_VREG(r0, r2) @ r0<- vBB
4141 .if 0
4142 cmp r1, #0 @ is second operand zero?
4143 beq common_errDivideByZero
4144 .endif
4145
4146 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4147 @ optional op; may set condition codes
4148 sub r0, r0, r1 @ r0<- op, r0-r3 changed
4149 GET_INST_OPCODE(ip) @ extract opcode from rINST
4150 SET_VREG(r0, r9) @ vAA<- r0
4151 GOTO_OPCODE(ip) @ jump to next instruction
4152 /* 11-14 instructions */
4153
4154
4155
4156/* ------------------------------ */
4157 .balign 64
4158.L_OP_MUL_INT: /* 0x92 */
4159/* File: armv5te/OP_MUL_INT.S */
4160/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
4161/* File: armv5te/binop.S */
4162 /*
4163 * Generic 32-bit binary operation. Provide an "instr" line that
4164 * specifies an instruction that performs "result = r0 op r1".
4165 * This could be an ARM instruction or a function call. (If the result
4166 * comes back in a register other than r0, you can override "result".)
4167 *
4168 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4169 * vCC (r1). Useful for integer division and modulus. Note that we
4170 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4171 * handles it correctly.
4172 *
4173 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4174 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4175 * mul-float, div-float, rem-float
4176 */
4177 /* binop vAA, vBB, vCC */
4178 FETCH(r0, 1) @ r0<- CCBB
4179 mov r9, rINST, lsr #8 @ r9<- AA
4180 mov r3, r0, lsr #8 @ r3<- CC
4181 and r2, r0, #255 @ r2<- BB
4182 GET_VREG(r1, r3) @ r1<- vCC
4183 GET_VREG(r0, r2) @ r0<- vBB
4184 .if 0
4185 cmp r1, #0 @ is second operand zero?
4186 beq common_errDivideByZero
4187 .endif
4188
4189 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4190 @ optional op; may set condition codes
4191 mul r0, r1, r0 @ r0<- op, r0-r3 changed
4192 GET_INST_OPCODE(ip) @ extract opcode from rINST
4193 SET_VREG(r0, r9) @ vAA<- r0
4194 GOTO_OPCODE(ip) @ jump to next instruction
4195 /* 11-14 instructions */
4196
4197
4198
4199/* ------------------------------ */
4200 .balign 64
4201.L_OP_DIV_INT: /* 0x93 */
4202/* File: armv5te/OP_DIV_INT.S */
4203/* File: armv5te/binop.S */
4204 /*
4205 * Generic 32-bit binary operation. Provide an "instr" line that
4206 * specifies an instruction that performs "result = r0 op r1".
4207 * This could be an ARM instruction or a function call. (If the result
4208 * comes back in a register other than r0, you can override "result".)
4209 *
4210 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4211 * vCC (r1). Useful for integer division and modulus. Note that we
4212 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4213 * handles it correctly.
4214 *
4215 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4216 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4217 * mul-float, div-float, rem-float
4218 */
4219 /* binop vAA, vBB, vCC */
4220 FETCH(r0, 1) @ r0<- CCBB
4221 mov r9, rINST, lsr #8 @ r9<- AA
4222 mov r3, r0, lsr #8 @ r3<- CC
4223 and r2, r0, #255 @ r2<- BB
4224 GET_VREG(r1, r3) @ r1<- vCC
4225 GET_VREG(r0, r2) @ r0<- vBB
4226 .if 1
4227 cmp r1, #0 @ is second operand zero?
4228 beq common_errDivideByZero
4229 .endif
4230
4231 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4232 @ optional op; may set condition codes
4233 bl __aeabi_idiv @ r0<- op, r0-r3 changed
4234 GET_INST_OPCODE(ip) @ extract opcode from rINST
4235 SET_VREG(r0, r9) @ vAA<- r0
4236 GOTO_OPCODE(ip) @ jump to next instruction
4237 /* 11-14 instructions */
4238
4239
4240
4241/* ------------------------------ */
4242 .balign 64
4243.L_OP_REM_INT: /* 0x94 */
4244/* File: armv5te/OP_REM_INT.S */
4245/* idivmod returns quotient in r0 and remainder in r1 */
4246/* File: armv5te/binop.S */
4247 /*
4248 * Generic 32-bit binary operation. Provide an "instr" line that
4249 * specifies an instruction that performs "result = r0 op r1".
4250 * This could be an ARM instruction or a function call. (If the result
4251 * comes back in a register other than r0, you can override "result".)
4252 *
4253 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4254 * vCC (r1). Useful for integer division and modulus. Note that we
4255 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4256 * handles it correctly.
4257 *
4258 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4259 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4260 * mul-float, div-float, rem-float
4261 */
4262 /* binop vAA, vBB, vCC */
4263 FETCH(r0, 1) @ r0<- CCBB
4264 mov r9, rINST, lsr #8 @ r9<- AA
4265 mov r3, r0, lsr #8 @ r3<- CC
4266 and r2, r0, #255 @ r2<- BB
4267 GET_VREG(r1, r3) @ r1<- vCC
4268 GET_VREG(r0, r2) @ r0<- vBB
4269 .if 1
4270 cmp r1, #0 @ is second operand zero?
4271 beq common_errDivideByZero
4272 .endif
4273
4274 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4275 @ optional op; may set condition codes
4276 bl __aeabi_idivmod @ r1<- op, r0-r3 changed
4277 GET_INST_OPCODE(ip) @ extract opcode from rINST
4278 SET_VREG(r1, r9) @ vAA<- r1
4279 GOTO_OPCODE(ip) @ jump to next instruction
4280 /* 11-14 instructions */
4281
4282
4283
4284/* ------------------------------ */
4285 .balign 64
4286.L_OP_AND_INT: /* 0x95 */
4287/* File: armv5te/OP_AND_INT.S */
4288/* File: armv5te/binop.S */
4289 /*
4290 * Generic 32-bit binary operation. Provide an "instr" line that
4291 * specifies an instruction that performs "result = r0 op r1".
4292 * This could be an ARM instruction or a function call. (If the result
4293 * comes back in a register other than r0, you can override "result".)
4294 *
4295 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4296 * vCC (r1). Useful for integer division and modulus. Note that we
4297 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4298 * handles it correctly.
4299 *
4300 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4301 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4302 * mul-float, div-float, rem-float
4303 */
4304 /* binop vAA, vBB, vCC */
4305 FETCH(r0, 1) @ r0<- CCBB
4306 mov r9, rINST, lsr #8 @ r9<- AA
4307 mov r3, r0, lsr #8 @ r3<- CC
4308 and r2, r0, #255 @ r2<- BB
4309 GET_VREG(r1, r3) @ r1<- vCC
4310 GET_VREG(r0, r2) @ r0<- vBB
4311 .if 0
4312 cmp r1, #0 @ is second operand zero?
4313 beq common_errDivideByZero
4314 .endif
4315
4316 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4317 @ optional op; may set condition codes
4318 and r0, r0, r1 @ r0<- op, r0-r3 changed
4319 GET_INST_OPCODE(ip) @ extract opcode from rINST
4320 SET_VREG(r0, r9) @ vAA<- r0
4321 GOTO_OPCODE(ip) @ jump to next instruction
4322 /* 11-14 instructions */
4323
4324
4325
4326/* ------------------------------ */
4327 .balign 64
4328.L_OP_OR_INT: /* 0x96 */
4329/* File: armv5te/OP_OR_INT.S */
4330/* File: armv5te/binop.S */
4331 /*
4332 * Generic 32-bit binary operation. Provide an "instr" line that
4333 * specifies an instruction that performs "result = r0 op r1".
4334 * This could be an ARM instruction or a function call. (If the result
4335 * comes back in a register other than r0, you can override "result".)
4336 *
4337 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4338 * vCC (r1). Useful for integer division and modulus. Note that we
4339 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4340 * handles it correctly.
4341 *
4342 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4343 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4344 * mul-float, div-float, rem-float
4345 */
4346 /* binop vAA, vBB, vCC */
4347 FETCH(r0, 1) @ r0<- CCBB
4348 mov r9, rINST, lsr #8 @ r9<- AA
4349 mov r3, r0, lsr #8 @ r3<- CC
4350 and r2, r0, #255 @ r2<- BB
4351 GET_VREG(r1, r3) @ r1<- vCC
4352 GET_VREG(r0, r2) @ r0<- vBB
4353 .if 0
4354 cmp r1, #0 @ is second operand zero?
4355 beq common_errDivideByZero
4356 .endif
4357
4358 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4359 @ optional op; may set condition codes
4360 orr r0, r0, r1 @ r0<- op, r0-r3 changed
4361 GET_INST_OPCODE(ip) @ extract opcode from rINST
4362 SET_VREG(r0, r9) @ vAA<- r0
4363 GOTO_OPCODE(ip) @ jump to next instruction
4364 /* 11-14 instructions */
4365
4366
4367
4368/* ------------------------------ */
4369 .balign 64
4370.L_OP_XOR_INT: /* 0x97 */
4371/* File: armv5te/OP_XOR_INT.S */
4372/* File: armv5te/binop.S */
4373 /*
4374 * Generic 32-bit binary operation. Provide an "instr" line that
4375 * specifies an instruction that performs "result = r0 op r1".
4376 * This could be an ARM instruction or a function call. (If the result
4377 * comes back in a register other than r0, you can override "result".)
4378 *
4379 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4380 * vCC (r1). Useful for integer division and modulus. Note that we
4381 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4382 * handles it correctly.
4383 *
4384 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4385 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4386 * mul-float, div-float, rem-float
4387 */
4388 /* binop vAA, vBB, vCC */
4389 FETCH(r0, 1) @ r0<- CCBB
4390 mov r9, rINST, lsr #8 @ r9<- AA
4391 mov r3, r0, lsr #8 @ r3<- CC
4392 and r2, r0, #255 @ r2<- BB
4393 GET_VREG(r1, r3) @ r1<- vCC
4394 GET_VREG(r0, r2) @ r0<- vBB
4395 .if 0
4396 cmp r1, #0 @ is second operand zero?
4397 beq common_errDivideByZero
4398 .endif
4399
4400 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4401 @ optional op; may set condition codes
4402 eor r0, r0, r1 @ r0<- op, r0-r3 changed
4403 GET_INST_OPCODE(ip) @ extract opcode from rINST
4404 SET_VREG(r0, r9) @ vAA<- r0
4405 GOTO_OPCODE(ip) @ jump to next instruction
4406 /* 11-14 instructions */
4407
4408
4409
4410/* ------------------------------ */
4411 .balign 64
4412.L_OP_SHL_INT: /* 0x98 */
4413/* File: armv5te/OP_SHL_INT.S */
4414/* File: armv5te/binop.S */
4415 /*
4416 * Generic 32-bit binary operation. Provide an "instr" line that
4417 * specifies an instruction that performs "result = r0 op r1".
4418 * This could be an ARM instruction or a function call. (If the result
4419 * comes back in a register other than r0, you can override "result".)
4420 *
4421 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4422 * vCC (r1). Useful for integer division and modulus. Note that we
4423 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4424 * handles it correctly.
4425 *
4426 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4427 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4428 * mul-float, div-float, rem-float
4429 */
4430 /* binop vAA, vBB, vCC */
4431 FETCH(r0, 1) @ r0<- CCBB
4432 mov r9, rINST, lsr #8 @ r9<- AA
4433 mov r3, r0, lsr #8 @ r3<- CC
4434 and r2, r0, #255 @ r2<- BB
4435 GET_VREG(r1, r3) @ r1<- vCC
4436 GET_VREG(r0, r2) @ r0<- vBB
4437 .if 0
4438 cmp r1, #0 @ is second operand zero?
4439 beq common_errDivideByZero
4440 .endif
4441
4442 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4443 and r1, r1, #31 @ optional op; may set condition codes
4444 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed
4445 GET_INST_OPCODE(ip) @ extract opcode from rINST
4446 SET_VREG(r0, r9) @ vAA<- r0
4447 GOTO_OPCODE(ip) @ jump to next instruction
4448 /* 11-14 instructions */
4449
4450
4451
4452/* ------------------------------ */
4453 .balign 64
4454.L_OP_SHR_INT: /* 0x99 */
4455/* File: armv5te/OP_SHR_INT.S */
4456/* File: armv5te/binop.S */
4457 /*
4458 * Generic 32-bit binary operation. Provide an "instr" line that
4459 * specifies an instruction that performs "result = r0 op r1".
4460 * This could be an ARM instruction or a function call. (If the result
4461 * comes back in a register other than r0, you can override "result".)
4462 *
4463 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4464 * vCC (r1). Useful for integer division and modulus. Note that we
4465 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4466 * handles it correctly.
4467 *
4468 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4469 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4470 * mul-float, div-float, rem-float
4471 */
4472 /* binop vAA, vBB, vCC */
4473 FETCH(r0, 1) @ r0<- CCBB
4474 mov r9, rINST, lsr #8 @ r9<- AA
4475 mov r3, r0, lsr #8 @ r3<- CC
4476 and r2, r0, #255 @ r2<- BB
4477 GET_VREG(r1, r3) @ r1<- vCC
4478 GET_VREG(r0, r2) @ r0<- vBB
4479 .if 0
4480 cmp r1, #0 @ is second operand zero?
4481 beq common_errDivideByZero
4482 .endif
4483
4484 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4485 and r1, r1, #31 @ optional op; may set condition codes
4486 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed
4487 GET_INST_OPCODE(ip) @ extract opcode from rINST
4488 SET_VREG(r0, r9) @ vAA<- r0
4489 GOTO_OPCODE(ip) @ jump to next instruction
4490 /* 11-14 instructions */
4491
4492
4493
4494/* ------------------------------ */
4495 .balign 64
4496.L_OP_USHR_INT: /* 0x9a */
4497/* File: armv5te/OP_USHR_INT.S */
4498/* File: armv5te/binop.S */
4499 /*
4500 * Generic 32-bit binary operation. Provide an "instr" line that
4501 * specifies an instruction that performs "result = r0 op r1".
4502 * This could be an ARM instruction or a function call. (If the result
4503 * comes back in a register other than r0, you can override "result".)
4504 *
4505 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4506 * vCC (r1). Useful for integer division and modulus. Note that we
4507 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4508 * handles it correctly.
4509 *
4510 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4511 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4512 * mul-float, div-float, rem-float
4513 */
4514 /* binop vAA, vBB, vCC */
4515 FETCH(r0, 1) @ r0<- CCBB
4516 mov r9, rINST, lsr #8 @ r9<- AA
4517 mov r3, r0, lsr #8 @ r3<- CC
4518 and r2, r0, #255 @ r2<- BB
4519 GET_VREG(r1, r3) @ r1<- vCC
4520 GET_VREG(r0, r2) @ r0<- vBB
4521 .if 0
4522 cmp r1, #0 @ is second operand zero?
4523 beq common_errDivideByZero
4524 .endif
4525
4526 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4527 and r1, r1, #31 @ optional op; may set condition codes
4528 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed
4529 GET_INST_OPCODE(ip) @ extract opcode from rINST
4530 SET_VREG(r0, r9) @ vAA<- r0
4531 GOTO_OPCODE(ip) @ jump to next instruction
4532 /* 11-14 instructions */
4533
4534
4535
4536/* ------------------------------ */
4537 .balign 64
4538.L_OP_ADD_LONG: /* 0x9b */
4539/* File: armv5te/OP_ADD_LONG.S */
4540/* File: armv5te/binopWide.S */
4541 /*
4542 * Generic 64-bit binary operation. Provide an "instr" line that
4543 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4544 * This could be an ARM instruction or a function call. (If the result
4545 * comes back in a register other than r0, you can override "result".)
4546 *
4547 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4548 * vCC (r1). Useful for integer division and modulus.
4549 *
4550 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4551 * xor-long, add-double, sub-double, mul-double, div-double,
4552 * rem-double
4553 *
4554 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4555 */
4556 /* binop vAA, vBB, vCC */
4557 FETCH(r0, 1) @ r0<- CCBB
4558 mov r9, rINST, lsr #8 @ r9<- AA
4559 and r2, r0, #255 @ r2<- BB
4560 mov r3, r0, lsr #8 @ r3<- CC
4561 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4562 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4563 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4564 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4565 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4566 .if 0
4567 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4568 beq common_errDivideByZero
4569 .endif
4570 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4571
4572 adds r0, r0, r2 @ optional op; may set condition codes
4573 adc r1, r1, r3 @ result<- op, r0-r3 changed
4574 GET_INST_OPCODE(ip) @ extract opcode from rINST
4575 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
4576 GOTO_OPCODE(ip) @ jump to next instruction
4577 /* 14-17 instructions */
4578
4579
4580
4581/* ------------------------------ */
4582 .balign 64
4583.L_OP_SUB_LONG: /* 0x9c */
4584/* File: armv5te/OP_SUB_LONG.S */
4585/* File: armv5te/binopWide.S */
4586 /*
4587 * Generic 64-bit binary operation. Provide an "instr" line that
4588 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4589 * This could be an ARM instruction or a function call. (If the result
4590 * comes back in a register other than r0, you can override "result".)
4591 *
4592 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4593 * vCC (r1). Useful for integer division and modulus.
4594 *
4595 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4596 * xor-long, add-double, sub-double, mul-double, div-double,
4597 * rem-double
4598 *
4599 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4600 */
4601 /* binop vAA, vBB, vCC */
4602 FETCH(r0, 1) @ r0<- CCBB
4603 mov r9, rINST, lsr #8 @ r9<- AA
4604 and r2, r0, #255 @ r2<- BB
4605 mov r3, r0, lsr #8 @ r3<- CC
4606 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4607 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4608 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4609 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4610 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4611 .if 0
4612 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4613 beq common_errDivideByZero
4614 .endif
4615 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4616
4617 subs r0, r0, r2 @ optional op; may set condition codes
4618 sbc r1, r1, r3 @ result<- op, r0-r3 changed
4619 GET_INST_OPCODE(ip) @ extract opcode from rINST
4620 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
4621 GOTO_OPCODE(ip) @ jump to next instruction
4622 /* 14-17 instructions */
4623
4624
4625
4626/* ------------------------------ */
4627 .balign 64
4628.L_OP_MUL_LONG: /* 0x9d */
4629/* File: armv5te/OP_MUL_LONG.S */
4630 /*
4631 * Signed 64-bit integer multiply.
4632 *
4633 * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
4634 * WX
4635 * x YZ
4636 * --------
4637 * ZW ZX
4638 * YW YX
4639 *
4640 * The low word of the result holds ZX, the high word holds
4641 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because
4642 * it doesn't fit in the low 64 bits.
4643 *
4644 * Unlike most ARM math operations, multiply instructions have
4645 * restrictions on using the same register more than once (Rd and Rm
4646 * cannot be the same).
4647 */
4648 /* mul-long vAA, vBB, vCC */
4649 FETCH(r0, 1) @ r0<- CCBB
4650 and r2, r0, #255 @ r2<- BB
4651 mov r3, r0, lsr #8 @ r3<- CC
4652 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4653 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4654 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4655 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4656 mul ip, r2, r1 @ ip<- ZxW
4657 umull r9, r10, r2, r0 @ r9/r10 <- ZxX
4658 mla r2, r0, r3, ip @ r2<- YxX + (ZxW)
4659 mov r0, rINST, lsr #8 @ r0<- AA
4660 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX))
4661 add r0, rFP, r0, lsl #2 @ r0<- &fp[AA]
4662 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4663 b .LOP_MUL_LONG_finish
4664
4665/* ------------------------------ */
4666 .balign 64
4667.L_OP_DIV_LONG: /* 0x9e */
4668/* File: armv5te/OP_DIV_LONG.S */
4669/* File: armv5te/binopWide.S */
4670 /*
4671 * Generic 64-bit binary operation. Provide an "instr" line that
4672 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4673 * This could be an ARM instruction or a function call. (If the result
4674 * comes back in a register other than r0, you can override "result".)
4675 *
4676 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4677 * vCC (r1). Useful for integer division and modulus.
4678 *
4679 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4680 * xor-long, add-double, sub-double, mul-double, div-double,
4681 * rem-double
4682 *
4683 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4684 */
4685 /* binop vAA, vBB, vCC */
4686 FETCH(r0, 1) @ r0<- CCBB
4687 mov r9, rINST, lsr #8 @ r9<- AA
4688 and r2, r0, #255 @ r2<- BB
4689 mov r3, r0, lsr #8 @ r3<- CC
4690 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4691 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4692 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4693 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4694 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4695 .if 1
4696 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4697 beq common_errDivideByZero
4698 .endif
4699 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4700
4701 @ optional op; may set condition codes
4702 bl __aeabi_ldivmod @ result<- op, r0-r3 changed
4703 GET_INST_OPCODE(ip) @ extract opcode from rINST
4704 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
4705 GOTO_OPCODE(ip) @ jump to next instruction
4706 /* 14-17 instructions */
4707
4708
4709
4710/* ------------------------------ */
4711 .balign 64
4712.L_OP_REM_LONG: /* 0x9f */
4713/* File: armv5te/OP_REM_LONG.S */
4714/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
4715/* File: armv5te/binopWide.S */
4716 /*
4717 * Generic 64-bit binary operation. Provide an "instr" line that
4718 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4719 * This could be an ARM instruction or a function call. (If the result
4720 * comes back in a register other than r0, you can override "result".)
4721 *
4722 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4723 * vCC (r1). Useful for integer division and modulus.
4724 *
4725 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4726 * xor-long, add-double, sub-double, mul-double, div-double,
4727 * rem-double
4728 *
4729 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4730 */
4731 /* binop vAA, vBB, vCC */
4732 FETCH(r0, 1) @ r0<- CCBB
4733 mov r9, rINST, lsr #8 @ r9<- AA
4734 and r2, r0, #255 @ r2<- BB
4735 mov r3, r0, lsr #8 @ r3<- CC
4736 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4737 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4738 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4739 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4740 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4741 .if 1
4742 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4743 beq common_errDivideByZero
4744 .endif
4745 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4746
4747 @ optional op; may set condition codes
4748 bl __aeabi_ldivmod @ result<- op, r0-r3 changed
4749 GET_INST_OPCODE(ip) @ extract opcode from rINST
4750 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3
4751 GOTO_OPCODE(ip) @ jump to next instruction
4752 /* 14-17 instructions */
4753
4754
4755
4756/* ------------------------------ */
4757 .balign 64
4758.L_OP_AND_LONG: /* 0xa0 */
4759/* File: armv5te/OP_AND_LONG.S */
4760/* File: armv5te/binopWide.S */
4761 /*
4762 * Generic 64-bit binary operation. Provide an "instr" line that
4763 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4764 * This could be an ARM instruction or a function call. (If the result
4765 * comes back in a register other than r0, you can override "result".)
4766 *
4767 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4768 * vCC (r1). Useful for integer division and modulus.
4769 *
4770 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4771 * xor-long, add-double, sub-double, mul-double, div-double,
4772 * rem-double
4773 *
4774 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4775 */
4776 /* binop vAA, vBB, vCC */
4777 FETCH(r0, 1) @ r0<- CCBB
4778 mov r9, rINST, lsr #8 @ r9<- AA
4779 and r2, r0, #255 @ r2<- BB
4780 mov r3, r0, lsr #8 @ r3<- CC
4781 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4782 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4783 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4784 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4785 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4786 .if 0
4787 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4788 beq common_errDivideByZero
4789 .endif
4790 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4791
4792 and r0, r0, r2 @ optional op; may set condition codes
4793 and r1, r1, r3 @ result<- op, r0-r3 changed
4794 GET_INST_OPCODE(ip) @ extract opcode from rINST
4795 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
4796 GOTO_OPCODE(ip) @ jump to next instruction
4797 /* 14-17 instructions */
4798
4799
4800
4801/* ------------------------------ */
4802 .balign 64
4803.L_OP_OR_LONG: /* 0xa1 */
4804/* File: armv5te/OP_OR_LONG.S */
4805/* File: armv5te/binopWide.S */
4806 /*
4807 * Generic 64-bit binary operation. Provide an "instr" line that
4808 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4809 * This could be an ARM instruction or a function call. (If the result
4810 * comes back in a register other than r0, you can override "result".)
4811 *
4812 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4813 * vCC (r1). Useful for integer division and modulus.
4814 *
4815 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4816 * xor-long, add-double, sub-double, mul-double, div-double,
4817 * rem-double
4818 *
4819 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4820 */
4821 /* binop vAA, vBB, vCC */
4822 FETCH(r0, 1) @ r0<- CCBB
4823 mov r9, rINST, lsr #8 @ r9<- AA
4824 and r2, r0, #255 @ r2<- BB
4825 mov r3, r0, lsr #8 @ r3<- CC
4826 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4827 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4828 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4829 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4830 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4831 .if 0
4832 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4833 beq common_errDivideByZero
4834 .endif
4835 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4836
4837 orr r0, r0, r2 @ optional op; may set condition codes
4838 orr r1, r1, r3 @ result<- op, r0-r3 changed
4839 GET_INST_OPCODE(ip) @ extract opcode from rINST
4840 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
4841 GOTO_OPCODE(ip) @ jump to next instruction
4842 /* 14-17 instructions */
4843
4844
4845
4846/* ------------------------------ */
4847 .balign 64
4848.L_OP_XOR_LONG: /* 0xa2 */
4849/* File: armv5te/OP_XOR_LONG.S */
4850/* File: armv5te/binopWide.S */
4851 /*
4852 * Generic 64-bit binary operation. Provide an "instr" line that
4853 * specifies an instruction that performs "result = r0-r1 op r2-r3".
4854 * This could be an ARM instruction or a function call. (If the result
4855 * comes back in a register other than r0, you can override "result".)
4856 *
4857 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4858 * vCC (r1). Useful for integer division and modulus.
4859 *
4860 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4861 * xor-long, add-double, sub-double, mul-double, div-double,
4862 * rem-double
4863 *
4864 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4865 */
4866 /* binop vAA, vBB, vCC */
4867 FETCH(r0, 1) @ r0<- CCBB
4868 mov r9, rINST, lsr #8 @ r9<- AA
4869 and r2, r0, #255 @ r2<- BB
4870 mov r3, r0, lsr #8 @ r3<- CC
4871 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4872 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
4873 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
4874 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
4875 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
4876 .if 0
4877 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
4878 beq common_errDivideByZero
4879 .endif
4880 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4881
4882 eor r0, r0, r2 @ optional op; may set condition codes
4883 eor r1, r1, r3 @ result<- op, r0-r3 changed
4884 GET_INST_OPCODE(ip) @ extract opcode from rINST
4885 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
4886 GOTO_OPCODE(ip) @ jump to next instruction
4887 /* 14-17 instructions */
4888
4889
4890
4891/* ------------------------------ */
4892 .balign 64
4893.L_OP_SHL_LONG: /* 0xa3 */
4894/* File: armv5te/OP_SHL_LONG.S */
4895 /*
4896 * Long integer shift. This is different from the generic 32/64-bit
4897 * binary operations because vAA/vBB are 64-bit but vCC (the shift
4898 * distance) is 32-bit. Also, Dalvik requires us to mask off the low
4899 * 6 bits of the shift distance.
4900 */
4901 /* shl-long vAA, vBB, vCC */
4902 FETCH(r0, 1) @ r0<- CCBB
4903 mov r9, rINST, lsr #8 @ r9<- AA
4904 and r3, r0, #255 @ r3<- BB
4905 mov r0, r0, lsr #8 @ r0<- CC
4906 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB]
4907 GET_VREG(r2, r0) @ r2<- vCC
4908 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1
4909 and r2, r2, #63 @ r2<- r2 & 0x3f
4910 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4911
4912 mov r1, r1, asl r2 @ r1<- r1 << r2
4913 rsb r3, r2, #32 @ r3<- 32 - r2
4914 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2))
4915 subs ip, r2, #32 @ ip<- r2 - 32
4916 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32)
4917 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4918 b .LOP_SHL_LONG_finish
4919
4920/* ------------------------------ */
4921 .balign 64
4922.L_OP_SHR_LONG: /* 0xa4 */
4923/* File: armv5te/OP_SHR_LONG.S */
4924 /*
4925 * Long integer shift. This is different from the generic 32/64-bit
4926 * binary operations because vAA/vBB are 64-bit but vCC (the shift
4927 * distance) is 32-bit. Also, Dalvik requires us to mask off the low
4928 * 6 bits of the shift distance.
4929 */
4930 /* shr-long vAA, vBB, vCC */
4931 FETCH(r0, 1) @ r0<- CCBB
4932 mov r9, rINST, lsr #8 @ r9<- AA
4933 and r3, r0, #255 @ r3<- BB
4934 mov r0, r0, lsr #8 @ r0<- CC
4935 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB]
4936 GET_VREG(r2, r0) @ r2<- vCC
4937 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1
4938 and r2, r2, #63 @ r0<- r0 & 0x3f
4939 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4940
4941 mov r0, r0, lsr r2 @ r0<- r2 >> r2
4942 rsb r3, r2, #32 @ r3<- 32 - r2
4943 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2))
4944 subs ip, r2, #32 @ ip<- r2 - 32
4945 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32)
4946 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4947 b .LOP_SHR_LONG_finish
4948
4949/* ------------------------------ */
4950 .balign 64
4951.L_OP_USHR_LONG: /* 0xa5 */
4952/* File: armv5te/OP_USHR_LONG.S */
4953 /*
4954 * Long integer shift. This is different from the generic 32/64-bit
4955 * binary operations because vAA/vBB are 64-bit but vCC (the shift
4956 * distance) is 32-bit. Also, Dalvik requires us to mask off the low
4957 * 6 bits of the shift distance.
4958 */
4959 /* ushr-long vAA, vBB, vCC */
4960 FETCH(r0, 1) @ r0<- CCBB
4961 mov r9, rINST, lsr #8 @ r9<- AA
4962 and r3, r0, #255 @ r3<- BB
4963 mov r0, r0, lsr #8 @ r0<- CC
4964 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB]
4965 GET_VREG(r2, r0) @ r2<- vCC
4966 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1
4967 and r2, r2, #63 @ r0<- r0 & 0x3f
4968 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
4969
4970 mov r0, r0, lsr r2 @ r0<- r2 >> r2
4971 rsb r3, r2, #32 @ r3<- 32 - r2
4972 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2))
4973 subs ip, r2, #32 @ ip<- r2 - 32
4974 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32)
4975 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
4976 b .LOP_USHR_LONG_finish
4977
4978/* ------------------------------ */
4979 .balign 64
4980.L_OP_ADD_FLOAT: /* 0xa6 */
4981/* File: arm-vfp/OP_ADD_FLOAT.S */
4982/* File: arm-vfp/fbinop.S */
4983 /*
4984 * Generic 32-bit floating-point operation. Provide an "instr" line that
4985 * specifies an instruction that performs "s2 = s0 op s1". Because we
4986 * use the "softfp" ABI, this must be an instruction, not a function call.
4987 *
4988 * For: add-float, sub-float, mul-float, div-float
4989 */
4990 /* floatop vAA, vBB, vCC */
4991 FETCH(r0, 1) @ r0<- CCBB
4992 mov r9, rINST, lsr #8 @ r9<- AA
4993 mov r3, r0, lsr #8 @ r3<- CC
4994 and r2, r0, #255 @ r2<- BB
4995 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC
4996 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB
4997 flds s1, [r3] @ s1<- vCC
4998 flds s0, [r2] @ s0<- vBB
4999
5000 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5001 fadds s2, s0, s1 @ s2<- op
5002 GET_INST_OPCODE(ip) @ extract opcode from rINST
5003 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA
5004 fsts s2, [r9] @ vAA<- s2
5005 GOTO_OPCODE(ip) @ jump to next instruction
5006
5007
5008/* ------------------------------ */
5009 .balign 64
5010.L_OP_SUB_FLOAT: /* 0xa7 */
5011/* File: arm-vfp/OP_SUB_FLOAT.S */
5012/* File: arm-vfp/fbinop.S */
5013 /*
5014 * Generic 32-bit floating-point operation. Provide an "instr" line that
5015 * specifies an instruction that performs "s2 = s0 op s1". Because we
5016 * use the "softfp" ABI, this must be an instruction, not a function call.
5017 *
5018 * For: add-float, sub-float, mul-float, div-float
5019 */
5020 /* floatop vAA, vBB, vCC */
5021 FETCH(r0, 1) @ r0<- CCBB
5022 mov r9, rINST, lsr #8 @ r9<- AA
5023 mov r3, r0, lsr #8 @ r3<- CC
5024 and r2, r0, #255 @ r2<- BB
5025 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC
5026 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB
5027 flds s1, [r3] @ s1<- vCC
5028 flds s0, [r2] @ s0<- vBB
5029
5030 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5031 fsubs s2, s0, s1 @ s2<- op
5032 GET_INST_OPCODE(ip) @ extract opcode from rINST
5033 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA
5034 fsts s2, [r9] @ vAA<- s2
5035 GOTO_OPCODE(ip) @ jump to next instruction
5036
5037
5038/* ------------------------------ */
5039 .balign 64
5040.L_OP_MUL_FLOAT: /* 0xa8 */
5041/* File: arm-vfp/OP_MUL_FLOAT.S */
5042/* File: arm-vfp/fbinop.S */
5043 /*
5044 * Generic 32-bit floating-point operation. Provide an "instr" line that
5045 * specifies an instruction that performs "s2 = s0 op s1". Because we
5046 * use the "softfp" ABI, this must be an instruction, not a function call.
5047 *
5048 * For: add-float, sub-float, mul-float, div-float
5049 */
5050 /* floatop vAA, vBB, vCC */
5051 FETCH(r0, 1) @ r0<- CCBB
5052 mov r9, rINST, lsr #8 @ r9<- AA
5053 mov r3, r0, lsr #8 @ r3<- CC
5054 and r2, r0, #255 @ r2<- BB
5055 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC
5056 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB
5057 flds s1, [r3] @ s1<- vCC
5058 flds s0, [r2] @ s0<- vBB
5059
5060 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5061 fmuls s2, s0, s1 @ s2<- op
5062 GET_INST_OPCODE(ip) @ extract opcode from rINST
5063 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA
5064 fsts s2, [r9] @ vAA<- s2
5065 GOTO_OPCODE(ip) @ jump to next instruction
5066
5067
5068/* ------------------------------ */
5069 .balign 64
5070.L_OP_DIV_FLOAT: /* 0xa9 */
5071/* File: arm-vfp/OP_DIV_FLOAT.S */
5072/* File: arm-vfp/fbinop.S */
5073 /*
5074 * Generic 32-bit floating-point operation. Provide an "instr" line that
5075 * specifies an instruction that performs "s2 = s0 op s1". Because we
5076 * use the "softfp" ABI, this must be an instruction, not a function call.
5077 *
5078 * For: add-float, sub-float, mul-float, div-float
5079 */
5080 /* floatop vAA, vBB, vCC */
5081 FETCH(r0, 1) @ r0<- CCBB
5082 mov r9, rINST, lsr #8 @ r9<- AA
5083 mov r3, r0, lsr #8 @ r3<- CC
5084 and r2, r0, #255 @ r2<- BB
5085 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC
5086 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB
5087 flds s1, [r3] @ s1<- vCC
5088 flds s0, [r2] @ s0<- vBB
5089
5090 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5091 fdivs s2, s0, s1 @ s2<- op
5092 GET_INST_OPCODE(ip) @ extract opcode from rINST
5093 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA
5094 fsts s2, [r9] @ vAA<- s2
5095 GOTO_OPCODE(ip) @ jump to next instruction
5096
5097
5098/* ------------------------------ */
5099 .balign 64
5100.L_OP_REM_FLOAT: /* 0xaa */
5101/* File: armv5te/OP_REM_FLOAT.S */
5102/* EABI doesn't define a float remainder function, but libm does */
5103/* File: armv5te/binop.S */
5104 /*
5105 * Generic 32-bit binary operation. Provide an "instr" line that
5106 * specifies an instruction that performs "result = r0 op r1".
5107 * This could be an ARM instruction or a function call. (If the result
5108 * comes back in a register other than r0, you can override "result".)
5109 *
5110 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5111 * vCC (r1). Useful for integer division and modulus. Note that we
5112 * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5113 * handles it correctly.
5114 *
5115 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5116 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5117 * mul-float, div-float, rem-float
5118 */
5119 /* binop vAA, vBB, vCC */
5120 FETCH(r0, 1) @ r0<- CCBB
5121 mov r9, rINST, lsr #8 @ r9<- AA
5122 mov r3, r0, lsr #8 @ r3<- CC
5123 and r2, r0, #255 @ r2<- BB
5124 GET_VREG(r1, r3) @ r1<- vCC
5125 GET_VREG(r0, r2) @ r0<- vBB
5126 .if 0
5127 cmp r1, #0 @ is second operand zero?
5128 beq common_errDivideByZero
5129 .endif
5130
5131 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5132 @ optional op; may set condition codes
5133 bl fmodf @ r0<- op, r0-r3 changed
5134 GET_INST_OPCODE(ip) @ extract opcode from rINST
5135 SET_VREG(r0, r9) @ vAA<- r0
5136 GOTO_OPCODE(ip) @ jump to next instruction
5137 /* 11-14 instructions */
5138
5139
5140
5141/* ------------------------------ */
5142 .balign 64
5143.L_OP_ADD_DOUBLE: /* 0xab */
5144/* File: arm-vfp/OP_ADD_DOUBLE.S */
5145/* File: arm-vfp/fbinopWide.S */
5146 /*
5147 * Generic 64-bit double-precision floating point binary operation.
5148 * Provide an "instr" line that specifies an instruction that performs
5149 * "d2 = d0 op d1".
5150 *
5151 * for: add-double, sub-double, mul-double, div-double
5152 */
5153 /* doubleop vAA, vBB, vCC */
5154 FETCH(r0, 1) @ r0<- CCBB
5155 mov r9, rINST, lsr #8 @ r9<- AA
5156 mov r3, r0, lsr #8 @ r3<- CC
5157 and r2, r0, #255 @ r2<- BB
5158 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC
5159 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB
5160 fldd d1, [r3] @ d1<- vCC
5161 fldd d0, [r2] @ d0<- vBB
5162
5163 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5164 faddd d2, d0, d1 @ s2<- op
5165 GET_INST_OPCODE(ip) @ extract opcode from rINST
5166 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA
5167 fstd d2, [r9] @ vAA<- d2
5168 GOTO_OPCODE(ip) @ jump to next instruction
5169
5170
5171/* ------------------------------ */
5172 .balign 64
5173.L_OP_SUB_DOUBLE: /* 0xac */
5174/* File: arm-vfp/OP_SUB_DOUBLE.S */
5175/* File: arm-vfp/fbinopWide.S */
5176 /*
5177 * Generic 64-bit double-precision floating point binary operation.
5178 * Provide an "instr" line that specifies an instruction that performs
5179 * "d2 = d0 op d1".
5180 *
5181 * for: add-double, sub-double, mul-double, div-double
5182 */
5183 /* doubleop vAA, vBB, vCC */
5184 FETCH(r0, 1) @ r0<- CCBB
5185 mov r9, rINST, lsr #8 @ r9<- AA
5186 mov r3, r0, lsr #8 @ r3<- CC
5187 and r2, r0, #255 @ r2<- BB
5188 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC
5189 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB
5190 fldd d1, [r3] @ d1<- vCC
5191 fldd d0, [r2] @ d0<- vBB
5192
5193 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5194 fsubd d2, d0, d1 @ s2<- op
5195 GET_INST_OPCODE(ip) @ extract opcode from rINST
5196 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA
5197 fstd d2, [r9] @ vAA<- d2
5198 GOTO_OPCODE(ip) @ jump to next instruction
5199
5200
5201/* ------------------------------ */
5202 .balign 64
5203.L_OP_MUL_DOUBLE: /* 0xad */
5204/* File: arm-vfp/OP_MUL_DOUBLE.S */
5205/* File: arm-vfp/fbinopWide.S */
5206 /*
5207 * Generic 64-bit double-precision floating point binary operation.
5208 * Provide an "instr" line that specifies an instruction that performs
5209 * "d2 = d0 op d1".
5210 *
5211 * for: add-double, sub-double, mul-double, div-double
5212 */
5213 /* doubleop vAA, vBB, vCC */
5214 FETCH(r0, 1) @ r0<- CCBB
5215 mov r9, rINST, lsr #8 @ r9<- AA
5216 mov r3, r0, lsr #8 @ r3<- CC
5217 and r2, r0, #255 @ r2<- BB
5218 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC
5219 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB
5220 fldd d1, [r3] @ d1<- vCC
5221 fldd d0, [r2] @ d0<- vBB
5222
5223 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5224 fmuld d2, d0, d1 @ s2<- op
5225 GET_INST_OPCODE(ip) @ extract opcode from rINST
5226 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA
5227 fstd d2, [r9] @ vAA<- d2
5228 GOTO_OPCODE(ip) @ jump to next instruction
5229
5230
5231/* ------------------------------ */
5232 .balign 64
5233.L_OP_DIV_DOUBLE: /* 0xae */
5234/* File: arm-vfp/OP_DIV_DOUBLE.S */
5235/* File: arm-vfp/fbinopWide.S */
5236 /*
5237 * Generic 64-bit double-precision floating point binary operation.
5238 * Provide an "instr" line that specifies an instruction that performs
5239 * "d2 = d0 op d1".
5240 *
5241 * for: add-double, sub-double, mul-double, div-double
5242 */
5243 /* doubleop vAA, vBB, vCC */
5244 FETCH(r0, 1) @ r0<- CCBB
5245 mov r9, rINST, lsr #8 @ r9<- AA
5246 mov r3, r0, lsr #8 @ r3<- CC
5247 and r2, r0, #255 @ r2<- BB
5248 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC
5249 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB
5250 fldd d1, [r3] @ d1<- vCC
5251 fldd d0, [r2] @ d0<- vBB
5252
5253 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5254 fdivd d2, d0, d1 @ s2<- op
5255 GET_INST_OPCODE(ip) @ extract opcode from rINST
5256 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA
5257 fstd d2, [r9] @ vAA<- d2
5258 GOTO_OPCODE(ip) @ jump to next instruction
5259
5260
5261/* ------------------------------ */
5262 .balign 64
5263.L_OP_REM_DOUBLE: /* 0xaf */
5264/* File: armv5te/OP_REM_DOUBLE.S */
5265/* EABI doesn't define a double remainder function, but libm does */
5266/* File: armv5te/binopWide.S */
5267 /*
5268 * Generic 64-bit binary operation. Provide an "instr" line that
5269 * specifies an instruction that performs "result = r0-r1 op r2-r3".
5270 * This could be an ARM instruction or a function call. (If the result
5271 * comes back in a register other than r0, you can override "result".)
5272 *
5273 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5274 * vCC (r1). Useful for integer division and modulus.
5275 *
5276 * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5277 * xor-long, add-double, sub-double, mul-double, div-double,
5278 * rem-double
5279 *
5280 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5281 */
5282 /* binop vAA, vBB, vCC */
5283 FETCH(r0, 1) @ r0<- CCBB
5284 mov r9, rINST, lsr #8 @ r9<- AA
5285 and r2, r0, #255 @ r2<- BB
5286 mov r3, r0, lsr #8 @ r3<- CC
5287 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
5288 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB]
5289 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC]
5290 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1
5291 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1
5292 .if 0
5293 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5294 beq common_errDivideByZero
5295 .endif
5296 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
5297
5298 @ optional op; may set condition codes
5299 bl fmod @ result<- op, r0-r3 changed
5300 GET_INST_OPCODE(ip) @ extract opcode from rINST
5301 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
5302 GOTO_OPCODE(ip) @ jump to next instruction
5303 /* 14-17 instructions */
5304
5305
5306
5307/* ------------------------------ */
5308 .balign 64
5309.L_OP_ADD_INT_2ADDR: /* 0xb0 */
5310/* File: armv6t2/OP_ADD_INT_2ADDR.S */
5311/* File: armv6t2/binop2addr.S */
5312 /*
5313 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5314 * that specifies an instruction that performs "result = r0 op r1".
5315 * This could be an ARM instruction or a function call. (If the result
5316 * comes back in a register other than r0, you can override "result".)
5317 *
5318 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5319 * vCC (r1). Useful for integer division and modulus.
5320 *
5321 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5322 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5323 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5324 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5325 */
5326 /* binop/2addr vA, vB */
5327 mov r3, rINST, lsr #12 @ r3<- B
5328 ubfx r9, rINST, #8, #4 @ r9<- A
5329 GET_VREG(r1, r3) @ r1<- vB
5330 GET_VREG(r0, r9) @ r0<- vA
5331 .if 0
5332 cmp r1, #0 @ is second operand zero?
5333 beq common_errDivideByZero
5334 .endif
5335 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5336
5337 @ optional op; may set condition codes
5338 add r0, r0, r1 @ r0<- op, r0-r3 changed
5339 GET_INST_OPCODE(ip) @ extract opcode from rINST
5340 SET_VREG(r0, r9) @ vAA<- r0
5341 GOTO_OPCODE(ip) @ jump to next instruction
5342 /* 10-13 instructions */
5343
5344
5345
5346/* ------------------------------ */
5347 .balign 64
5348.L_OP_SUB_INT_2ADDR: /* 0xb1 */
5349/* File: armv6t2/OP_SUB_INT_2ADDR.S */
5350/* File: armv6t2/binop2addr.S */
5351 /*
5352 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5353 * that specifies an instruction that performs "result = r0 op r1".
5354 * This could be an ARM instruction or a function call. (If the result
5355 * comes back in a register other than r0, you can override "result".)
5356 *
5357 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5358 * vCC (r1). Useful for integer division and modulus.
5359 *
5360 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5361 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5362 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5363 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5364 */
5365 /* binop/2addr vA, vB */
5366 mov r3, rINST, lsr #12 @ r3<- B
5367 ubfx r9, rINST, #8, #4 @ r9<- A
5368 GET_VREG(r1, r3) @ r1<- vB
5369 GET_VREG(r0, r9) @ r0<- vA
5370 .if 0
5371 cmp r1, #0 @ is second operand zero?
5372 beq common_errDivideByZero
5373 .endif
5374 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5375
5376 @ optional op; may set condition codes
5377 sub r0, r0, r1 @ r0<- op, r0-r3 changed
5378 GET_INST_OPCODE(ip) @ extract opcode from rINST
5379 SET_VREG(r0, r9) @ vAA<- r0
5380 GOTO_OPCODE(ip) @ jump to next instruction
5381 /* 10-13 instructions */
5382
5383
5384
5385/* ------------------------------ */
5386 .balign 64
5387.L_OP_MUL_INT_2ADDR: /* 0xb2 */
5388/* File: armv6t2/OP_MUL_INT_2ADDR.S */
5389/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
5390/* File: armv6t2/binop2addr.S */
5391 /*
5392 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5393 * that specifies an instruction that performs "result = r0 op r1".
5394 * This could be an ARM instruction or a function call. (If the result
5395 * comes back in a register other than r0, you can override "result".)
5396 *
5397 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5398 * vCC (r1). Useful for integer division and modulus.
5399 *
5400 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5401 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5402 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5403 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5404 */
5405 /* binop/2addr vA, vB */
5406 mov r3, rINST, lsr #12 @ r3<- B
5407 ubfx r9, rINST, #8, #4 @ r9<- A
5408 GET_VREG(r1, r3) @ r1<- vB
5409 GET_VREG(r0, r9) @ r0<- vA
5410 .if 0
5411 cmp r1, #0 @ is second operand zero?
5412 beq common_errDivideByZero
5413 .endif
5414 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5415
5416 @ optional op; may set condition codes
5417 mul r0, r1, r0 @ r0<- op, r0-r3 changed
5418 GET_INST_OPCODE(ip) @ extract opcode from rINST
5419 SET_VREG(r0, r9) @ vAA<- r0
5420 GOTO_OPCODE(ip) @ jump to next instruction
5421 /* 10-13 instructions */
5422
5423
5424
5425/* ------------------------------ */
5426 .balign 64
5427.L_OP_DIV_INT_2ADDR: /* 0xb3 */
5428/* File: armv6t2/OP_DIV_INT_2ADDR.S */
5429/* File: armv6t2/binop2addr.S */
5430 /*
5431 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5432 * that specifies an instruction that performs "result = r0 op r1".
5433 * This could be an ARM instruction or a function call. (If the result
5434 * comes back in a register other than r0, you can override "result".)
5435 *
5436 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5437 * vCC (r1). Useful for integer division and modulus.
5438 *
5439 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5440 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5441 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5442 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5443 */
5444 /* binop/2addr vA, vB */
5445 mov r3, rINST, lsr #12 @ r3<- B
5446 ubfx r9, rINST, #8, #4 @ r9<- A
5447 GET_VREG(r1, r3) @ r1<- vB
5448 GET_VREG(r0, r9) @ r0<- vA
5449 .if 1
5450 cmp r1, #0 @ is second operand zero?
5451 beq common_errDivideByZero
5452 .endif
5453 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5454
5455 @ optional op; may set condition codes
5456 bl __aeabi_idiv @ r0<- op, r0-r3 changed
5457 GET_INST_OPCODE(ip) @ extract opcode from rINST
5458 SET_VREG(r0, r9) @ vAA<- r0
5459 GOTO_OPCODE(ip) @ jump to next instruction
5460 /* 10-13 instructions */
5461
5462
5463
5464/* ------------------------------ */
5465 .balign 64
5466.L_OP_REM_INT_2ADDR: /* 0xb4 */
5467/* File: armv6t2/OP_REM_INT_2ADDR.S */
5468/* idivmod returns quotient in r0 and remainder in r1 */
5469/* File: armv6t2/binop2addr.S */
5470 /*
5471 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5472 * that specifies an instruction that performs "result = r0 op r1".
5473 * This could be an ARM instruction or a function call. (If the result
5474 * comes back in a register other than r0, you can override "result".)
5475 *
5476 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5477 * vCC (r1). Useful for integer division and modulus.
5478 *
5479 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5480 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5481 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5482 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5483 */
5484 /* binop/2addr vA, vB */
5485 mov r3, rINST, lsr #12 @ r3<- B
5486 ubfx r9, rINST, #8, #4 @ r9<- A
5487 GET_VREG(r1, r3) @ r1<- vB
5488 GET_VREG(r0, r9) @ r0<- vA
5489 .if 1
5490 cmp r1, #0 @ is second operand zero?
5491 beq common_errDivideByZero
5492 .endif
5493 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5494
5495 @ optional op; may set condition codes
5496 bl __aeabi_idivmod @ r1<- op, r0-r3 changed
5497 GET_INST_OPCODE(ip) @ extract opcode from rINST
5498 SET_VREG(r1, r9) @ vAA<- r1
5499 GOTO_OPCODE(ip) @ jump to next instruction
5500 /* 10-13 instructions */
5501
5502
5503
5504/* ------------------------------ */
5505 .balign 64
5506.L_OP_AND_INT_2ADDR: /* 0xb5 */
5507/* File: armv6t2/OP_AND_INT_2ADDR.S */
5508/* File: armv6t2/binop2addr.S */
5509 /*
5510 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5511 * that specifies an instruction that performs "result = r0 op r1".
5512 * This could be an ARM instruction or a function call. (If the result
5513 * comes back in a register other than r0, you can override "result".)
5514 *
5515 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5516 * vCC (r1). Useful for integer division and modulus.
5517 *
5518 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5519 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5520 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5521 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5522 */
5523 /* binop/2addr vA, vB */
5524 mov r3, rINST, lsr #12 @ r3<- B
5525 ubfx r9, rINST, #8, #4 @ r9<- A
5526 GET_VREG(r1, r3) @ r1<- vB
5527 GET_VREG(r0, r9) @ r0<- vA
5528 .if 0
5529 cmp r1, #0 @ is second operand zero?
5530 beq common_errDivideByZero
5531 .endif
5532 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5533
5534 @ optional op; may set condition codes
5535 and r0, r0, r1 @ r0<- op, r0-r3 changed
5536 GET_INST_OPCODE(ip) @ extract opcode from rINST
5537 SET_VREG(r0, r9) @ vAA<- r0
5538 GOTO_OPCODE(ip) @ jump to next instruction
5539 /* 10-13 instructions */
5540
5541
5542
5543/* ------------------------------ */
5544 .balign 64
5545.L_OP_OR_INT_2ADDR: /* 0xb6 */
5546/* File: armv6t2/OP_OR_INT_2ADDR.S */
5547/* File: armv6t2/binop2addr.S */
5548 /*
5549 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5550 * that specifies an instruction that performs "result = r0 op r1".
5551 * This could be an ARM instruction or a function call. (If the result
5552 * comes back in a register other than r0, you can override "result".)
5553 *
5554 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5555 * vCC (r1). Useful for integer division and modulus.
5556 *
5557 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5558 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5559 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5560 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5561 */
5562 /* binop/2addr vA, vB */
5563 mov r3, rINST, lsr #12 @ r3<- B
5564 ubfx r9, rINST, #8, #4 @ r9<- A
5565 GET_VREG(r1, r3) @ r1<- vB
5566 GET_VREG(r0, r9) @ r0<- vA
5567 .if 0
5568 cmp r1, #0 @ is second operand zero?
5569 beq common_errDivideByZero
5570 .endif
5571 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5572
5573 @ optional op; may set condition codes
5574 orr r0, r0, r1 @ r0<- op, r0-r3 changed
5575 GET_INST_OPCODE(ip) @ extract opcode from rINST
5576 SET_VREG(r0, r9) @ vAA<- r0
5577 GOTO_OPCODE(ip) @ jump to next instruction
5578 /* 10-13 instructions */
5579
5580
5581
5582/* ------------------------------ */
5583 .balign 64
5584.L_OP_XOR_INT_2ADDR: /* 0xb7 */
5585/* File: armv6t2/OP_XOR_INT_2ADDR.S */
5586/* File: armv6t2/binop2addr.S */
5587 /*
5588 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5589 * that specifies an instruction that performs "result = r0 op r1".
5590 * This could be an ARM instruction or a function call. (If the result
5591 * comes back in a register other than r0, you can override "result".)
5592 *
5593 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5594 * vCC (r1). Useful for integer division and modulus.
5595 *
5596 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5597 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5598 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5599 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5600 */
5601 /* binop/2addr vA, vB */
5602 mov r3, rINST, lsr #12 @ r3<- B
5603 ubfx r9, rINST, #8, #4 @ r9<- A
5604 GET_VREG(r1, r3) @ r1<- vB
5605 GET_VREG(r0, r9) @ r0<- vA
5606 .if 0
5607 cmp r1, #0 @ is second operand zero?
5608 beq common_errDivideByZero
5609 .endif
5610 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5611
5612 @ optional op; may set condition codes
5613 eor r0, r0, r1 @ r0<- op, r0-r3 changed
5614 GET_INST_OPCODE(ip) @ extract opcode from rINST
5615 SET_VREG(r0, r9) @ vAA<- r0
5616 GOTO_OPCODE(ip) @ jump to next instruction
5617 /* 10-13 instructions */
5618
5619
5620
5621/* ------------------------------ */
5622 .balign 64
5623.L_OP_SHL_INT_2ADDR: /* 0xb8 */
5624/* File: armv6t2/OP_SHL_INT_2ADDR.S */
5625/* File: armv6t2/binop2addr.S */
5626 /*
5627 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5628 * that specifies an instruction that performs "result = r0 op r1".
5629 * This could be an ARM instruction or a function call. (If the result
5630 * comes back in a register other than r0, you can override "result".)
5631 *
5632 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5633 * vCC (r1). Useful for integer division and modulus.
5634 *
5635 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5636 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5637 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5638 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5639 */
5640 /* binop/2addr vA, vB */
5641 mov r3, rINST, lsr #12 @ r3<- B
5642 ubfx r9, rINST, #8, #4 @ r9<- A
5643 GET_VREG(r1, r3) @ r1<- vB
5644 GET_VREG(r0, r9) @ r0<- vA
5645 .if 0
5646 cmp r1, #0 @ is second operand zero?
5647 beq common_errDivideByZero
5648 .endif
5649 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5650
5651 and r1, r1, #31 @ optional op; may set condition codes
5652 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed
5653 GET_INST_OPCODE(ip) @ extract opcode from rINST
5654 SET_VREG(r0, r9) @ vAA<- r0
5655 GOTO_OPCODE(ip) @ jump to next instruction
5656 /* 10-13 instructions */
5657
5658
5659
5660/* ------------------------------ */
5661 .balign 64
5662.L_OP_SHR_INT_2ADDR: /* 0xb9 */
5663/* File: armv6t2/OP_SHR_INT_2ADDR.S */
5664/* File: armv6t2/binop2addr.S */
5665 /*
5666 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5667 * that specifies an instruction that performs "result = r0 op r1".
5668 * This could be an ARM instruction or a function call. (If the result
5669 * comes back in a register other than r0, you can override "result".)
5670 *
5671 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5672 * vCC (r1). Useful for integer division and modulus.
5673 *
5674 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5675 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5676 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5677 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5678 */
5679 /* binop/2addr vA, vB */
5680 mov r3, rINST, lsr #12 @ r3<- B
5681 ubfx r9, rINST, #8, #4 @ r9<- A
5682 GET_VREG(r1, r3) @ r1<- vB
5683 GET_VREG(r0, r9) @ r0<- vA
5684 .if 0
5685 cmp r1, #0 @ is second operand zero?
5686 beq common_errDivideByZero
5687 .endif
5688 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5689
5690 and r1, r1, #31 @ optional op; may set condition codes
5691 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed
5692 GET_INST_OPCODE(ip) @ extract opcode from rINST
5693 SET_VREG(r0, r9) @ vAA<- r0
5694 GOTO_OPCODE(ip) @ jump to next instruction
5695 /* 10-13 instructions */
5696
5697
5698
5699/* ------------------------------ */
5700 .balign 64
5701.L_OP_USHR_INT_2ADDR: /* 0xba */
5702/* File: armv6t2/OP_USHR_INT_2ADDR.S */
5703/* File: armv6t2/binop2addr.S */
5704 /*
5705 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
5706 * that specifies an instruction that performs "result = r0 op r1".
5707 * This could be an ARM instruction or a function call. (If the result
5708 * comes back in a register other than r0, you can override "result".)
5709 *
5710 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5711 * vCC (r1). Useful for integer division and modulus.
5712 *
5713 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5714 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5715 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5716 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5717 */
5718 /* binop/2addr vA, vB */
5719 mov r3, rINST, lsr #12 @ r3<- B
5720 ubfx r9, rINST, #8, #4 @ r9<- A
5721 GET_VREG(r1, r3) @ r1<- vB
5722 GET_VREG(r0, r9) @ r0<- vA
5723 .if 0
5724 cmp r1, #0 @ is second operand zero?
5725 beq common_errDivideByZero
5726 .endif
5727 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5728
5729 and r1, r1, #31 @ optional op; may set condition codes
5730 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed
5731 GET_INST_OPCODE(ip) @ extract opcode from rINST
5732 SET_VREG(r0, r9) @ vAA<- r0
5733 GOTO_OPCODE(ip) @ jump to next instruction
5734 /* 10-13 instructions */
5735
5736
5737
5738/* ------------------------------ */
5739 .balign 64
5740.L_OP_ADD_LONG_2ADDR: /* 0xbb */
5741/* File: armv6t2/OP_ADD_LONG_2ADDR.S */
5742/* File: armv6t2/binopWide2addr.S */
5743 /*
5744 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
5745 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5746 * This could be an ARM instruction or a function call. (If the result
5747 * comes back in a register other than r0, you can override "result".)
5748 *
5749 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5750 * vCC (r1). Useful for integer division and modulus.
5751 *
5752 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5753 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5754 * sub-double/2addr, mul-double/2addr, div-double/2addr,
5755 * rem-double/2addr
5756 */
5757 /* binop/2addr vA, vB */
5758 mov r1, rINST, lsr #12 @ r1<- B
5759 ubfx r9, rINST, #8, #4 @ r9<- A
5760 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
5761 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
5762 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
5763 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
5764 .if 0
5765 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5766 beq common_errDivideByZero
5767 .endif
5768 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5769
5770 adds r0, r0, r2 @ optional op; may set condition codes
5771 adc r1, r1, r3 @ result<- op, r0-r3 changed
5772 GET_INST_OPCODE(ip) @ extract opcode from rINST
5773 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
5774 GOTO_OPCODE(ip) @ jump to next instruction
5775 /* 12-15 instructions */
5776
5777
5778
5779/* ------------------------------ */
5780 .balign 64
5781.L_OP_SUB_LONG_2ADDR: /* 0xbc */
5782/* File: armv6t2/OP_SUB_LONG_2ADDR.S */
5783/* File: armv6t2/binopWide2addr.S */
5784 /*
5785 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
5786 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5787 * This could be an ARM instruction or a function call. (If the result
5788 * comes back in a register other than r0, you can override "result".)
5789 *
5790 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5791 * vCC (r1). Useful for integer division and modulus.
5792 *
5793 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5794 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5795 * sub-double/2addr, mul-double/2addr, div-double/2addr,
5796 * rem-double/2addr
5797 */
5798 /* binop/2addr vA, vB */
5799 mov r1, rINST, lsr #12 @ r1<- B
5800 ubfx r9, rINST, #8, #4 @ r9<- A
5801 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
5802 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
5803 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
5804 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
5805 .if 0
5806 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5807 beq common_errDivideByZero
5808 .endif
5809 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5810
5811 subs r0, r0, r2 @ optional op; may set condition codes
5812 sbc r1, r1, r3 @ result<- op, r0-r3 changed
5813 GET_INST_OPCODE(ip) @ extract opcode from rINST
5814 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
5815 GOTO_OPCODE(ip) @ jump to next instruction
5816 /* 12-15 instructions */
5817
5818
5819
5820/* ------------------------------ */
5821 .balign 64
5822.L_OP_MUL_LONG_2ADDR: /* 0xbd */
5823/* File: armv6t2/OP_MUL_LONG_2ADDR.S */
5824 /*
5825 * Signed 64-bit integer multiply, "/2addr" version.
5826 *
5827 * See OP_MUL_LONG for an explanation.
5828 *
5829 * We get a little tight on registers, so to avoid looking up &fp[A]
5830 * again we stuff it into rINST.
5831 */
5832 /* mul-long/2addr vA, vB */
5833 mov r1, rINST, lsr #12 @ r1<- B
5834 ubfx r9, rINST, #8, #4 @ r9<- A
5835 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
5836 add rINST, rFP, r9, lsl #2 @ rINST<- &fp[A]
5837 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
5838 ldmia rINST, {r0-r1} @ r0/r1<- vAA/vAA+1
5839 mul ip, r2, r1 @ ip<- ZxW
5840 umull r9, r10, r2, r0 @ r9/r10 <- ZxX
5841 mla r2, r0, r3, ip @ r2<- YxX + (ZxW)
5842 mov r0, rINST @ r0<- &fp[A] (free up rINST)
5843 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5844 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX))
5845 GET_INST_OPCODE(ip) @ extract opcode from rINST
5846 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10
5847 GOTO_OPCODE(ip) @ jump to next instruction
5848
5849
5850/* ------------------------------ */
5851 .balign 64
5852.L_OP_DIV_LONG_2ADDR: /* 0xbe */
5853/* File: armv6t2/OP_DIV_LONG_2ADDR.S */
5854/* File: armv6t2/binopWide2addr.S */
5855 /*
5856 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
5857 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5858 * This could be an ARM instruction or a function call. (If the result
5859 * comes back in a register other than r0, you can override "result".)
5860 *
5861 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5862 * vCC (r1). Useful for integer division and modulus.
5863 *
5864 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5865 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5866 * sub-double/2addr, mul-double/2addr, div-double/2addr,
5867 * rem-double/2addr
5868 */
5869 /* binop/2addr vA, vB */
5870 mov r1, rINST, lsr #12 @ r1<- B
5871 ubfx r9, rINST, #8, #4 @ r9<- A
5872 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
5873 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
5874 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
5875 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
5876 .if 1
5877 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5878 beq common_errDivideByZero
5879 .endif
5880 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5881
5882 @ optional op; may set condition codes
5883 bl __aeabi_ldivmod @ result<- op, r0-r3 changed
5884 GET_INST_OPCODE(ip) @ extract opcode from rINST
5885 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
5886 GOTO_OPCODE(ip) @ jump to next instruction
5887 /* 12-15 instructions */
5888
5889
5890
5891/* ------------------------------ */
5892 .balign 64
5893.L_OP_REM_LONG_2ADDR: /* 0xbf */
5894/* File: armv6t2/OP_REM_LONG_2ADDR.S */
5895/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
5896/* File: armv6t2/binopWide2addr.S */
5897 /*
5898 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
5899 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5900 * This could be an ARM instruction or a function call. (If the result
5901 * comes back in a register other than r0, you can override "result".)
5902 *
5903 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5904 * vCC (r1). Useful for integer division and modulus.
5905 *
5906 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5907 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5908 * sub-double/2addr, mul-double/2addr, div-double/2addr,
5909 * rem-double/2addr
5910 */
5911 /* binop/2addr vA, vB */
5912 mov r1, rINST, lsr #12 @ r1<- B
5913 ubfx r9, rINST, #8, #4 @ r9<- A
5914 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
5915 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
5916 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
5917 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
5918 .if 1
5919 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5920 beq common_errDivideByZero
5921 .endif
5922 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5923
5924 @ optional op; may set condition codes
5925 bl __aeabi_ldivmod @ result<- op, r0-r3 changed
5926 GET_INST_OPCODE(ip) @ extract opcode from rINST
5927 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3
5928 GOTO_OPCODE(ip) @ jump to next instruction
5929 /* 12-15 instructions */
5930
5931
5932
5933/* ------------------------------ */
5934 .balign 64
5935.L_OP_AND_LONG_2ADDR: /* 0xc0 */
5936/* File: armv6t2/OP_AND_LONG_2ADDR.S */
5937/* File: armv6t2/binopWide2addr.S */
5938 /*
5939 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
5940 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5941 * This could be an ARM instruction or a function call. (If the result
5942 * comes back in a register other than r0, you can override "result".)
5943 *
5944 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5945 * vCC (r1). Useful for integer division and modulus.
5946 *
5947 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5948 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5949 * sub-double/2addr, mul-double/2addr, div-double/2addr,
5950 * rem-double/2addr
5951 */
5952 /* binop/2addr vA, vB */
5953 mov r1, rINST, lsr #12 @ r1<- B
5954 ubfx r9, rINST, #8, #4 @ r9<- A
5955 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
5956 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
5957 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
5958 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
5959 .if 0
5960 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
5961 beq common_errDivideByZero
5962 .endif
5963 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
5964
5965 and r0, r0, r2 @ optional op; may set condition codes
5966 and r1, r1, r3 @ result<- op, r0-r3 changed
5967 GET_INST_OPCODE(ip) @ extract opcode from rINST
5968 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
5969 GOTO_OPCODE(ip) @ jump to next instruction
5970 /* 12-15 instructions */
5971
5972
5973
5974/* ------------------------------ */
5975 .balign 64
5976.L_OP_OR_LONG_2ADDR: /* 0xc1 */
5977/* File: armv6t2/OP_OR_LONG_2ADDR.S */
5978/* File: armv6t2/binopWide2addr.S */
5979 /*
5980 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
5981 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5982 * This could be an ARM instruction or a function call. (If the result
5983 * comes back in a register other than r0, you can override "result".)
5984 *
5985 * If "chkzero" is set to 1, we perform a divide-by-zero check on
5986 * vCC (r1). Useful for integer division and modulus.
5987 *
5988 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5989 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5990 * sub-double/2addr, mul-double/2addr, div-double/2addr,
5991 * rem-double/2addr
5992 */
5993 /* binop/2addr vA, vB */
5994 mov r1, rINST, lsr #12 @ r1<- B
5995 ubfx r9, rINST, #8, #4 @ r9<- A
5996 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
5997 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
5998 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
5999 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6000 .if 0
6001 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
6002 beq common_errDivideByZero
6003 .endif
6004 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6005
6006 orr r0, r0, r2 @ optional op; may set condition codes
6007 orr r1, r1, r3 @ result<- op, r0-r3 changed
6008 GET_INST_OPCODE(ip) @ extract opcode from rINST
6009 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
6010 GOTO_OPCODE(ip) @ jump to next instruction
6011 /* 12-15 instructions */
6012
6013
6014
6015/* ------------------------------ */
6016 .balign 64
6017.L_OP_XOR_LONG_2ADDR: /* 0xc2 */
6018/* File: armv6t2/OP_XOR_LONG_2ADDR.S */
6019/* File: armv6t2/binopWide2addr.S */
6020 /*
6021 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
6022 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6023 * This could be an ARM instruction or a function call. (If the result
6024 * comes back in a register other than r0, you can override "result".)
6025 *
6026 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6027 * vCC (r1). Useful for integer division and modulus.
6028 *
6029 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6030 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6031 * sub-double/2addr, mul-double/2addr, div-double/2addr,
6032 * rem-double/2addr
6033 */
6034 /* binop/2addr vA, vB */
6035 mov r1, rINST, lsr #12 @ r1<- B
6036 ubfx r9, rINST, #8, #4 @ r9<- A
6037 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
6038 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6039 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
6040 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6041 .if 0
6042 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
6043 beq common_errDivideByZero
6044 .endif
6045 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6046
6047 eor r0, r0, r2 @ optional op; may set condition codes
6048 eor r1, r1, r3 @ result<- op, r0-r3 changed
6049 GET_INST_OPCODE(ip) @ extract opcode from rINST
6050 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
6051 GOTO_OPCODE(ip) @ jump to next instruction
6052 /* 12-15 instructions */
6053
6054
6055
6056/* ------------------------------ */
6057 .balign 64
6058.L_OP_SHL_LONG_2ADDR: /* 0xc3 */
6059/* File: armv6t2/OP_SHL_LONG_2ADDR.S */
6060 /*
6061 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is
6062 * 32-bit shift distance.
6063 */
6064 /* shl-long/2addr vA, vB */
6065 mov r3, rINST, lsr #12 @ r3<- B
6066 ubfx r9, rINST, #8, #4 @ r9<- A
6067 GET_VREG(r2, r3) @ r2<- vB
6068 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6069 and r2, r2, #63 @ r2<- r2 & 0x3f
6070 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6071
6072 mov r1, r1, asl r2 @ r1<- r1 << r2
6073 rsb r3, r2, #32 @ r3<- 32 - r2
6074 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2))
6075 subs ip, r2, #32 @ ip<- r2 - 32
6076 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6077 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32)
6078 mov r0, r0, asl r2 @ r0<- r0 << r2
6079 b .LOP_SHL_LONG_2ADDR_finish
6080
6081/* ------------------------------ */
6082 .balign 64
6083.L_OP_SHR_LONG_2ADDR: /* 0xc4 */
6084/* File: armv6t2/OP_SHR_LONG_2ADDR.S */
6085 /*
6086 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is
6087 * 32-bit shift distance.
6088 */
6089 /* shr-long/2addr vA, vB */
6090 mov r3, rINST, lsr #12 @ r3<- B
6091 ubfx r9, rINST, #8, #4 @ r9<- A
6092 GET_VREG(r2, r3) @ r2<- vB
6093 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6094 and r2, r2, #63 @ r2<- r2 & 0x3f
6095 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6096
6097 mov r0, r0, lsr r2 @ r0<- r2 >> r2
6098 rsb r3, r2, #32 @ r3<- 32 - r2
6099 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2))
6100 subs ip, r2, #32 @ ip<- r2 - 32
6101 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6102 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32)
6103 mov r1, r1, asr r2 @ r1<- r1 >> r2
6104 b .LOP_SHR_LONG_2ADDR_finish
6105
6106/* ------------------------------ */
6107 .balign 64
6108.L_OP_USHR_LONG_2ADDR: /* 0xc5 */
6109/* File: armv6t2/OP_USHR_LONG_2ADDR.S */
6110 /*
6111 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is
6112 * 32-bit shift distance.
6113 */
6114 /* ushr-long/2addr vA, vB */
6115 mov r3, rINST, lsr #12 @ r3<- B
6116 ubfx r9, rINST, #8, #4 @ r9<- A
6117 GET_VREG(r2, r3) @ r2<- vB
6118 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6119 and r2, r2, #63 @ r2<- r2 & 0x3f
6120 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6121
6122 mov r0, r0, lsr r2 @ r0<- r2 >> r2
6123 rsb r3, r2, #32 @ r3<- 32 - r2
6124 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2))
6125 subs ip, r2, #32 @ ip<- r2 - 32
6126 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6127 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32)
6128 mov r1, r1, lsr r2 @ r1<- r1 >>> r2
6129 b .LOP_USHR_LONG_2ADDR_finish
6130
6131/* ------------------------------ */
6132 .balign 64
6133.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
6134/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */
6135/* File: arm-vfp/fbinop2addr.S */
6136 /*
6137 * Generic 32-bit floating point "/2addr" binary operation. Provide
6138 * an "instr" line that specifies an instruction that performs
6139 * "s2 = s0 op s1".
6140 *
6141 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6142 */
6143 /* binop/2addr vA, vB */
6144 mov r3, rINST, lsr #12 @ r3<- B
6145 mov r9, rINST, lsr #8 @ r9<- A+
6146 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
6147 and r9, r9, #15 @ r9<- A
6148 flds s1, [r3] @ s1<- vB
6149 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
6150 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6151 flds s0, [r9] @ s0<- vA
6152
6153 fadds s2, s0, s1 @ s2<- op
6154 GET_INST_OPCODE(ip) @ extract opcode from rINST
6155 fsts s2, [r9] @ vAA<- s2
6156 GOTO_OPCODE(ip) @ jump to next instruction
6157
6158
6159/* ------------------------------ */
6160 .balign 64
6161.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
6162/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */
6163/* File: arm-vfp/fbinop2addr.S */
6164 /*
6165 * Generic 32-bit floating point "/2addr" binary operation. Provide
6166 * an "instr" line that specifies an instruction that performs
6167 * "s2 = s0 op s1".
6168 *
6169 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6170 */
6171 /* binop/2addr vA, vB */
6172 mov r3, rINST, lsr #12 @ r3<- B
6173 mov r9, rINST, lsr #8 @ r9<- A+
6174 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
6175 and r9, r9, #15 @ r9<- A
6176 flds s1, [r3] @ s1<- vB
6177 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
6178 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6179 flds s0, [r9] @ s0<- vA
6180
6181 fsubs s2, s0, s1 @ s2<- op
6182 GET_INST_OPCODE(ip) @ extract opcode from rINST
6183 fsts s2, [r9] @ vAA<- s2
6184 GOTO_OPCODE(ip) @ jump to next instruction
6185
6186
6187/* ------------------------------ */
6188 .balign 64
6189.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
6190/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */
6191/* File: arm-vfp/fbinop2addr.S */
6192 /*
6193 * Generic 32-bit floating point "/2addr" binary operation. Provide
6194 * an "instr" line that specifies an instruction that performs
6195 * "s2 = s0 op s1".
6196 *
6197 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6198 */
6199 /* binop/2addr vA, vB */
6200 mov r3, rINST, lsr #12 @ r3<- B
6201 mov r9, rINST, lsr #8 @ r9<- A+
6202 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
6203 and r9, r9, #15 @ r9<- A
6204 flds s1, [r3] @ s1<- vB
6205 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
6206 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6207 flds s0, [r9] @ s0<- vA
6208
6209 fmuls s2, s0, s1 @ s2<- op
6210 GET_INST_OPCODE(ip) @ extract opcode from rINST
6211 fsts s2, [r9] @ vAA<- s2
6212 GOTO_OPCODE(ip) @ jump to next instruction
6213
6214
6215/* ------------------------------ */
6216 .balign 64
6217.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
6218/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */
6219/* File: arm-vfp/fbinop2addr.S */
6220 /*
6221 * Generic 32-bit floating point "/2addr" binary operation. Provide
6222 * an "instr" line that specifies an instruction that performs
6223 * "s2 = s0 op s1".
6224 *
6225 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6226 */
6227 /* binop/2addr vA, vB */
6228 mov r3, rINST, lsr #12 @ r3<- B
6229 mov r9, rINST, lsr #8 @ r9<- A+
6230 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
6231 and r9, r9, #15 @ r9<- A
6232 flds s1, [r3] @ s1<- vB
6233 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
6234 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6235 flds s0, [r9] @ s0<- vA
6236
6237 fdivs s2, s0, s1 @ s2<- op
6238 GET_INST_OPCODE(ip) @ extract opcode from rINST
6239 fsts s2, [r9] @ vAA<- s2
6240 GOTO_OPCODE(ip) @ jump to next instruction
6241
6242
6243/* ------------------------------ */
6244 .balign 64
6245.L_OP_REM_FLOAT_2ADDR: /* 0xca */
6246/* File: armv6t2/OP_REM_FLOAT_2ADDR.S */
6247/* EABI doesn't define a float remainder function, but libm does */
6248/* File: armv6t2/binop2addr.S */
6249 /*
6250 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
6251 * that specifies an instruction that performs "result = r0 op r1".
6252 * This could be an ARM instruction or a function call. (If the result
6253 * comes back in a register other than r0, you can override "result".)
6254 *
6255 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6256 * vCC (r1). Useful for integer division and modulus.
6257 *
6258 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6259 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6260 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6261 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6262 */
6263 /* binop/2addr vA, vB */
6264 mov r3, rINST, lsr #12 @ r3<- B
6265 ubfx r9, rINST, #8, #4 @ r9<- A
6266 GET_VREG(r1, r3) @ r1<- vB
6267 GET_VREG(r0, r9) @ r0<- vA
6268 .if 0
6269 cmp r1, #0 @ is second operand zero?
6270 beq common_errDivideByZero
6271 .endif
6272 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6273
6274 @ optional op; may set condition codes
6275 bl fmodf @ r0<- op, r0-r3 changed
6276 GET_INST_OPCODE(ip) @ extract opcode from rINST
6277 SET_VREG(r0, r9) @ vAA<- r0
6278 GOTO_OPCODE(ip) @ jump to next instruction
6279 /* 10-13 instructions */
6280
6281
6282
6283/* ------------------------------ */
6284 .balign 64
6285.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
6286/* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */
6287/* File: arm-vfp/fbinopWide2addr.S */
6288 /*
6289 * Generic 64-bit floating point "/2addr" binary operation. Provide
6290 * an "instr" line that specifies an instruction that performs
6291 * "d2 = d0 op d1".
6292 *
6293 * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6294 * div-double/2addr
6295 */
6296 /* binop/2addr vA, vB */
6297 mov r3, rINST, lsr #12 @ r3<- B
6298 mov r9, rINST, lsr #8 @ r9<- A+
6299 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
6300 and r9, r9, #15 @ r9<- A
6301 fldd d1, [r3] @ d1<- vB
6302 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
6303 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6304 fldd d0, [r9] @ d0<- vA
6305
6306 faddd d2, d0, d1 @ d2<- op
6307 GET_INST_OPCODE(ip) @ extract opcode from rINST
6308 fstd d2, [r9] @ vAA<- d2
6309 GOTO_OPCODE(ip) @ jump to next instruction
6310
6311
6312/* ------------------------------ */
6313 .balign 64
6314.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
6315/* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */
6316/* File: arm-vfp/fbinopWide2addr.S */
6317 /*
6318 * Generic 64-bit floating point "/2addr" binary operation. Provide
6319 * an "instr" line that specifies an instruction that performs
6320 * "d2 = d0 op d1".
6321 *
6322 * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6323 * div-double/2addr
6324 */
6325 /* binop/2addr vA, vB */
6326 mov r3, rINST, lsr #12 @ r3<- B
6327 mov r9, rINST, lsr #8 @ r9<- A+
6328 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
6329 and r9, r9, #15 @ r9<- A
6330 fldd d1, [r3] @ d1<- vB
6331 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
6332 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6333 fldd d0, [r9] @ d0<- vA
6334
6335 fsubd d2, d0, d1 @ d2<- op
6336 GET_INST_OPCODE(ip) @ extract opcode from rINST
6337 fstd d2, [r9] @ vAA<- d2
6338 GOTO_OPCODE(ip) @ jump to next instruction
6339
6340
6341/* ------------------------------ */
6342 .balign 64
6343.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
6344/* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */
6345/* File: arm-vfp/fbinopWide2addr.S */
6346 /*
6347 * Generic 64-bit floating point "/2addr" binary operation. Provide
6348 * an "instr" line that specifies an instruction that performs
6349 * "d2 = d0 op d1".
6350 *
6351 * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6352 * div-double/2addr
6353 */
6354 /* binop/2addr vA, vB */
6355 mov r3, rINST, lsr #12 @ r3<- B
6356 mov r9, rINST, lsr #8 @ r9<- A+
6357 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
6358 and r9, r9, #15 @ r9<- A
6359 fldd d1, [r3] @ d1<- vB
6360 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
6361 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6362 fldd d0, [r9] @ d0<- vA
6363
6364 fmuld d2, d0, d1 @ d2<- op
6365 GET_INST_OPCODE(ip) @ extract opcode from rINST
6366 fstd d2, [r9] @ vAA<- d2
6367 GOTO_OPCODE(ip) @ jump to next instruction
6368
6369
6370/* ------------------------------ */
6371 .balign 64
6372.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
6373/* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */
6374/* File: arm-vfp/fbinopWide2addr.S */
6375 /*
6376 * Generic 64-bit floating point "/2addr" binary operation. Provide
6377 * an "instr" line that specifies an instruction that performs
6378 * "d2 = d0 op d1".
6379 *
6380 * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6381 * div-double/2addr
6382 */
6383 /* binop/2addr vA, vB */
6384 mov r3, rINST, lsr #12 @ r3<- B
6385 mov r9, rINST, lsr #8 @ r9<- A+
6386 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB
6387 and r9, r9, #15 @ r9<- A
6388 fldd d1, [r3] @ d1<- vB
6389 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA
6390 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6391 fldd d0, [r9] @ d0<- vA
6392
6393 fdivd d2, d0, d1 @ d2<- op
6394 GET_INST_OPCODE(ip) @ extract opcode from rINST
6395 fstd d2, [r9] @ vAA<- d2
6396 GOTO_OPCODE(ip) @ jump to next instruction
6397
6398
6399/* ------------------------------ */
6400 .balign 64
6401.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
6402/* File: armv6t2/OP_REM_DOUBLE_2ADDR.S */
6403/* EABI doesn't define a double remainder function, but libm does */
6404/* File: armv6t2/binopWide2addr.S */
6405 /*
6406 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
6407 * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6408 * This could be an ARM instruction or a function call. (If the result
6409 * comes back in a register other than r0, you can override "result".)
6410 *
6411 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6412 * vCC (r1). Useful for integer division and modulus.
6413 *
6414 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6415 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6416 * sub-double/2addr, mul-double/2addr, div-double/2addr,
6417 * rem-double/2addr
6418 */
6419 /* binop/2addr vA, vB */
6420 mov r1, rINST, lsr #12 @ r1<- B
6421 ubfx r9, rINST, #8, #4 @ r9<- A
6422 add r1, rFP, r1, lsl #2 @ r1<- &fp[B]
6423 add r9, rFP, r9, lsl #2 @ r9<- &fp[A]
6424 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1
6425 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
6426 .if 0
6427 orrs ip, r2, r3 @ second arg (r2-r3) is zero?
6428 beq common_errDivideByZero
6429 .endif
6430 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST
6431
6432 @ optional op; may set condition codes
6433 bl fmod @ result<- op, r0-r3 changed
6434 GET_INST_OPCODE(ip) @ extract opcode from rINST
6435 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1
6436 GOTO_OPCODE(ip) @ jump to next instruction
6437 /* 12-15 instructions */
6438
6439
6440
6441/* ------------------------------ */
6442 .balign 64
6443.L_OP_ADD_INT_LIT16: /* 0xd0 */
6444/* File: armv6t2/OP_ADD_INT_LIT16.S */
6445/* File: armv6t2/binopLit16.S */
6446 /*
6447 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6448 * that specifies an instruction that performs "result = r0 op r1".
6449 * This could be an ARM instruction or a function call. (If the result
6450 * comes back in a register other than r0, you can override "result".)
6451 *
6452 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6453 * vCC (r1). Useful for integer division and modulus.
6454 *
6455 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6456 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6457 */
6458 /* binop/lit16 vA, vB, #+CCCC */
6459 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6460 mov r2, rINST, lsr #12 @ r2<- B
6461 ubfx r9, rINST, #8, #4 @ r9<- A
6462 GET_VREG(r0, r2) @ r0<- vB
6463 .if 0
6464 cmp r1, #0 @ is second operand zero?
6465 beq common_errDivideByZero
6466 .endif
6467 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6468
6469 add r0, r0, r1 @ r0<- op, r0-r3 changed
6470 GET_INST_OPCODE(ip) @ extract opcode from rINST
6471 SET_VREG(r0, r9) @ vAA<- r0
6472 GOTO_OPCODE(ip) @ jump to next instruction
6473 /* 10-13 instructions */
6474
6475
6476
6477/* ------------------------------ */
6478 .balign 64
6479.L_OP_RSUB_INT: /* 0xd1 */
6480/* File: armv6t2/OP_RSUB_INT.S */
6481/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
6482/* File: armv6t2/binopLit16.S */
6483 /*
6484 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6485 * that specifies an instruction that performs "result = r0 op r1".
6486 * This could be an ARM instruction or a function call. (If the result
6487 * comes back in a register other than r0, you can override "result".)
6488 *
6489 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6490 * vCC (r1). Useful for integer division and modulus.
6491 *
6492 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6493 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6494 */
6495 /* binop/lit16 vA, vB, #+CCCC */
6496 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6497 mov r2, rINST, lsr #12 @ r2<- B
6498 ubfx r9, rINST, #8, #4 @ r9<- A
6499 GET_VREG(r0, r2) @ r0<- vB
6500 .if 0
6501 cmp r1, #0 @ is second operand zero?
6502 beq common_errDivideByZero
6503 .endif
6504 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6505
6506 rsb r0, r0, r1 @ r0<- op, r0-r3 changed
6507 GET_INST_OPCODE(ip) @ extract opcode from rINST
6508 SET_VREG(r0, r9) @ vAA<- r0
6509 GOTO_OPCODE(ip) @ jump to next instruction
6510 /* 10-13 instructions */
6511
6512
6513
6514/* ------------------------------ */
6515 .balign 64
6516.L_OP_MUL_INT_LIT16: /* 0xd2 */
6517/* File: armv6t2/OP_MUL_INT_LIT16.S */
6518/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6519/* File: armv6t2/binopLit16.S */
6520 /*
6521 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6522 * that specifies an instruction that performs "result = r0 op r1".
6523 * This could be an ARM instruction or a function call. (If the result
6524 * comes back in a register other than r0, you can override "result".)
6525 *
6526 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6527 * vCC (r1). Useful for integer division and modulus.
6528 *
6529 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6530 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6531 */
6532 /* binop/lit16 vA, vB, #+CCCC */
6533 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6534 mov r2, rINST, lsr #12 @ r2<- B
6535 ubfx r9, rINST, #8, #4 @ r9<- A
6536 GET_VREG(r0, r2) @ r0<- vB
6537 .if 0
6538 cmp r1, #0 @ is second operand zero?
6539 beq common_errDivideByZero
6540 .endif
6541 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6542
6543 mul r0, r1, r0 @ r0<- op, r0-r3 changed
6544 GET_INST_OPCODE(ip) @ extract opcode from rINST
6545 SET_VREG(r0, r9) @ vAA<- r0
6546 GOTO_OPCODE(ip) @ jump to next instruction
6547 /* 10-13 instructions */
6548
6549
6550
6551/* ------------------------------ */
6552 .balign 64
6553.L_OP_DIV_INT_LIT16: /* 0xd3 */
6554/* File: armv6t2/OP_DIV_INT_LIT16.S */
6555/* File: armv6t2/binopLit16.S */
6556 /*
6557 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6558 * that specifies an instruction that performs "result = r0 op r1".
6559 * This could be an ARM instruction or a function call. (If the result
6560 * comes back in a register other than r0, you can override "result".)
6561 *
6562 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6563 * vCC (r1). Useful for integer division and modulus.
6564 *
6565 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6566 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6567 */
6568 /* binop/lit16 vA, vB, #+CCCC */
6569 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6570 mov r2, rINST, lsr #12 @ r2<- B
6571 ubfx r9, rINST, #8, #4 @ r9<- A
6572 GET_VREG(r0, r2) @ r0<- vB
6573 .if 1
6574 cmp r1, #0 @ is second operand zero?
6575 beq common_errDivideByZero
6576 .endif
6577 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6578
6579 bl __aeabi_idiv @ r0<- op, r0-r3 changed
6580 GET_INST_OPCODE(ip) @ extract opcode from rINST
6581 SET_VREG(r0, r9) @ vAA<- r0
6582 GOTO_OPCODE(ip) @ jump to next instruction
6583 /* 10-13 instructions */
6584
6585
6586
6587/* ------------------------------ */
6588 .balign 64
6589.L_OP_REM_INT_LIT16: /* 0xd4 */
6590/* File: armv6t2/OP_REM_INT_LIT16.S */
6591/* idivmod returns quotient in r0 and remainder in r1 */
6592/* File: armv6t2/binopLit16.S */
6593 /*
6594 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6595 * that specifies an instruction that performs "result = r0 op r1".
6596 * This could be an ARM instruction or a function call. (If the result
6597 * comes back in a register other than r0, you can override "result".)
6598 *
6599 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6600 * vCC (r1). Useful for integer division and modulus.
6601 *
6602 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6603 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6604 */
6605 /* binop/lit16 vA, vB, #+CCCC */
6606 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6607 mov r2, rINST, lsr #12 @ r2<- B
6608 ubfx r9, rINST, #8, #4 @ r9<- A
6609 GET_VREG(r0, r2) @ r0<- vB
6610 .if 1
6611 cmp r1, #0 @ is second operand zero?
6612 beq common_errDivideByZero
6613 .endif
6614 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6615
6616 bl __aeabi_idivmod @ r1<- op, r0-r3 changed
6617 GET_INST_OPCODE(ip) @ extract opcode from rINST
6618 SET_VREG(r1, r9) @ vAA<- r1
6619 GOTO_OPCODE(ip) @ jump to next instruction
6620 /* 10-13 instructions */
6621
6622
6623
6624/* ------------------------------ */
6625 .balign 64
6626.L_OP_AND_INT_LIT16: /* 0xd5 */
6627/* File: armv6t2/OP_AND_INT_LIT16.S */
6628/* File: armv6t2/binopLit16.S */
6629 /*
6630 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6631 * that specifies an instruction that performs "result = r0 op r1".
6632 * This could be an ARM instruction or a function call. (If the result
6633 * comes back in a register other than r0, you can override "result".)
6634 *
6635 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6636 * vCC (r1). Useful for integer division and modulus.
6637 *
6638 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6639 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6640 */
6641 /* binop/lit16 vA, vB, #+CCCC */
6642 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6643 mov r2, rINST, lsr #12 @ r2<- B
6644 ubfx r9, rINST, #8, #4 @ r9<- A
6645 GET_VREG(r0, r2) @ r0<- vB
6646 .if 0
6647 cmp r1, #0 @ is second operand zero?
6648 beq common_errDivideByZero
6649 .endif
6650 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6651
6652 and r0, r0, r1 @ r0<- op, r0-r3 changed
6653 GET_INST_OPCODE(ip) @ extract opcode from rINST
6654 SET_VREG(r0, r9) @ vAA<- r0
6655 GOTO_OPCODE(ip) @ jump to next instruction
6656 /* 10-13 instructions */
6657
6658
6659
6660/* ------------------------------ */
6661 .balign 64
6662.L_OP_OR_INT_LIT16: /* 0xd6 */
6663/* File: armv6t2/OP_OR_INT_LIT16.S */
6664/* File: armv6t2/binopLit16.S */
6665 /*
6666 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6667 * that specifies an instruction that performs "result = r0 op r1".
6668 * This could be an ARM instruction or a function call. (If the result
6669 * comes back in a register other than r0, you can override "result".)
6670 *
6671 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6672 * vCC (r1). Useful for integer division and modulus.
6673 *
6674 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6675 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6676 */
6677 /* binop/lit16 vA, vB, #+CCCC */
6678 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6679 mov r2, rINST, lsr #12 @ r2<- B
6680 ubfx r9, rINST, #8, #4 @ r9<- A
6681 GET_VREG(r0, r2) @ r0<- vB
6682 .if 0
6683 cmp r1, #0 @ is second operand zero?
6684 beq common_errDivideByZero
6685 .endif
6686 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6687
6688 orr r0, r0, r1 @ r0<- op, r0-r3 changed
6689 GET_INST_OPCODE(ip) @ extract opcode from rINST
6690 SET_VREG(r0, r9) @ vAA<- r0
6691 GOTO_OPCODE(ip) @ jump to next instruction
6692 /* 10-13 instructions */
6693
6694
6695
6696/* ------------------------------ */
6697 .balign 64
6698.L_OP_XOR_INT_LIT16: /* 0xd7 */
6699/* File: armv6t2/OP_XOR_INT_LIT16.S */
6700/* File: armv6t2/binopLit16.S */
6701 /*
6702 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
6703 * that specifies an instruction that performs "result = r0 op r1".
6704 * This could be an ARM instruction or a function call. (If the result
6705 * comes back in a register other than r0, you can override "result".)
6706 *
6707 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6708 * vCC (r1). Useful for integer division and modulus.
6709 *
6710 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6711 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6712 */
6713 /* binop/lit16 vA, vB, #+CCCC */
6714 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended)
6715 mov r2, rINST, lsr #12 @ r2<- B
6716 ubfx r9, rINST, #8, #4 @ r9<- A
6717 GET_VREG(r0, r2) @ r0<- vB
6718 .if 0
6719 cmp r1, #0 @ is second operand zero?
6720 beq common_errDivideByZero
6721 .endif
6722 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6723
6724 eor r0, r0, r1 @ r0<- op, r0-r3 changed
6725 GET_INST_OPCODE(ip) @ extract opcode from rINST
6726 SET_VREG(r0, r9) @ vAA<- r0
6727 GOTO_OPCODE(ip) @ jump to next instruction
6728 /* 10-13 instructions */
6729
6730
6731
6732/* ------------------------------ */
6733 .balign 64
6734.L_OP_ADD_INT_LIT8: /* 0xd8 */
6735/* File: armv5te/OP_ADD_INT_LIT8.S */
6736/* File: armv5te/binopLit8.S */
6737 /*
6738 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
6739 * that specifies an instruction that performs "result = r0 op r1".
6740 * This could be an ARM instruction or a function call. (If the result
6741 * comes back in a register other than r0, you can override "result".)
6742 *
6743 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6744 * vCC (r1). Useful for integer division and modulus.
6745 *
6746 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6747 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6748 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
6749 */
6750 /* binop/lit8 vAA, vBB, #+CC */
6751 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
6752 mov r9, rINST, lsr #8 @ r9<- AA
6753 and r2, r3, #255 @ r2<- BB
6754 GET_VREG(r0, r2) @ r0<- vBB
6755 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
6756 .if 0
6757 @cmp r1, #0 @ is second operand zero?
6758 beq common_errDivideByZero
6759 .endif
6760 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6761
6762 @ optional op; may set condition codes
6763 add r0, r0, r1 @ r0<- op, r0-r3 changed
6764 GET_INST_OPCODE(ip) @ extract opcode from rINST
6765 SET_VREG(r0, r9) @ vAA<- r0
6766 GOTO_OPCODE(ip) @ jump to next instruction
6767 /* 10-12 instructions */
6768
6769
6770
6771/* ------------------------------ */
6772 .balign 64
6773.L_OP_RSUB_INT_LIT8: /* 0xd9 */
6774/* File: armv5te/OP_RSUB_INT_LIT8.S */
6775/* File: armv5te/binopLit8.S */
6776 /*
6777 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
6778 * that specifies an instruction that performs "result = r0 op r1".
6779 * This could be an ARM instruction or a function call. (If the result
6780 * comes back in a register other than r0, you can override "result".)
6781 *
6782 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6783 * vCC (r1). Useful for integer division and modulus.
6784 *
6785 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6786 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6787 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
6788 */
6789 /* binop/lit8 vAA, vBB, #+CC */
6790 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
6791 mov r9, rINST, lsr #8 @ r9<- AA
6792 and r2, r3, #255 @ r2<- BB
6793 GET_VREG(r0, r2) @ r0<- vBB
6794 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
6795 .if 0
6796 @cmp r1, #0 @ is second operand zero?
6797 beq common_errDivideByZero
6798 .endif
6799 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6800
6801 @ optional op; may set condition codes
6802 rsb r0, r0, r1 @ r0<- op, r0-r3 changed
6803 GET_INST_OPCODE(ip) @ extract opcode from rINST
6804 SET_VREG(r0, r9) @ vAA<- r0
6805 GOTO_OPCODE(ip) @ jump to next instruction
6806 /* 10-12 instructions */
6807
6808
6809
6810/* ------------------------------ */
6811 .balign 64
6812.L_OP_MUL_INT_LIT8: /* 0xda */
6813/* File: armv5te/OP_MUL_INT_LIT8.S */
6814/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6815/* File: armv5te/binopLit8.S */
6816 /*
6817 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
6818 * that specifies an instruction that performs "result = r0 op r1".
6819 * This could be an ARM instruction or a function call. (If the result
6820 * comes back in a register other than r0, you can override "result".)
6821 *
6822 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6823 * vCC (r1). Useful for integer division and modulus.
6824 *
6825 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6826 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6827 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
6828 */
6829 /* binop/lit8 vAA, vBB, #+CC */
6830 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
6831 mov r9, rINST, lsr #8 @ r9<- AA
6832 and r2, r3, #255 @ r2<- BB
6833 GET_VREG(r0, r2) @ r0<- vBB
6834 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
6835 .if 0
6836 @cmp r1, #0 @ is second operand zero?
6837 beq common_errDivideByZero
6838 .endif
6839 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6840
6841 @ optional op; may set condition codes
6842 mul r0, r1, r0 @ r0<- op, r0-r3 changed
6843 GET_INST_OPCODE(ip) @ extract opcode from rINST
6844 SET_VREG(r0, r9) @ vAA<- r0
6845 GOTO_OPCODE(ip) @ jump to next instruction
6846 /* 10-12 instructions */
6847
6848
6849
6850/* ------------------------------ */
6851 .balign 64
6852.L_OP_DIV_INT_LIT8: /* 0xdb */
6853/* File: armv5te/OP_DIV_INT_LIT8.S */
6854/* File: armv5te/binopLit8.S */
6855 /*
6856 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
6857 * that specifies an instruction that performs "result = r0 op r1".
6858 * This could be an ARM instruction or a function call. (If the result
6859 * comes back in a register other than r0, you can override "result".)
6860 *
6861 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6862 * vCC (r1). Useful for integer division and modulus.
6863 *
6864 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6865 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6866 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
6867 */
6868 /* binop/lit8 vAA, vBB, #+CC */
6869 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
6870 mov r9, rINST, lsr #8 @ r9<- AA
6871 and r2, r3, #255 @ r2<- BB
6872 GET_VREG(r0, r2) @ r0<- vBB
6873 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
6874 .if 1
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 @ optional op; may set condition codes
6881 bl __aeabi_idiv @ r0<- op, r0-r3 changed
6882 GET_INST_OPCODE(ip) @ extract opcode from rINST
6883 SET_VREG(r0, r9) @ vAA<- r0
6884 GOTO_OPCODE(ip) @ jump to next instruction
6885 /* 10-12 instructions */
6886
6887
6888
6889/* ------------------------------ */
6890 .balign 64
6891.L_OP_REM_INT_LIT8: /* 0xdc */
6892/* File: armv5te/OP_REM_INT_LIT8.S */
6893/* idivmod returns quotient in r0 and remainder in r1 */
6894/* File: armv5te/binopLit8.S */
6895 /*
6896 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
6897 * that specifies an instruction that performs "result = r0 op r1".
6898 * This could be an ARM instruction or a function call. (If the result
6899 * comes back in a register other than r0, you can override "result".)
6900 *
6901 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6902 * vCC (r1). Useful for integer division and modulus.
6903 *
6904 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6905 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6906 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
6907 */
6908 /* binop/lit8 vAA, vBB, #+CC */
6909 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
6910 mov r9, rINST, lsr #8 @ r9<- AA
6911 and r2, r3, #255 @ r2<- BB
6912 GET_VREG(r0, r2) @ r0<- vBB
6913 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
6914 .if 1
6915 @cmp r1, #0 @ is second operand zero?
6916 beq common_errDivideByZero
6917 .endif
6918 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6919
6920 @ optional op; may set condition codes
6921 bl __aeabi_idivmod @ r1<- op, r0-r3 changed
6922 GET_INST_OPCODE(ip) @ extract opcode from rINST
6923 SET_VREG(r1, r9) @ vAA<- r1
6924 GOTO_OPCODE(ip) @ jump to next instruction
6925 /* 10-12 instructions */
6926
6927
6928
6929/* ------------------------------ */
6930 .balign 64
6931.L_OP_AND_INT_LIT8: /* 0xdd */
6932/* File: armv5te/OP_AND_INT_LIT8.S */
6933/* File: armv5te/binopLit8.S */
6934 /*
6935 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
6936 * that specifies an instruction that performs "result = r0 op r1".
6937 * This could be an ARM instruction or a function call. (If the result
6938 * comes back in a register other than r0, you can override "result".)
6939 *
6940 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6941 * vCC (r1). Useful for integer division and modulus.
6942 *
6943 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6944 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6945 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
6946 */
6947 /* binop/lit8 vAA, vBB, #+CC */
6948 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
6949 mov r9, rINST, lsr #8 @ r9<- AA
6950 and r2, r3, #255 @ r2<- BB
6951 GET_VREG(r0, r2) @ r0<- vBB
6952 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
6953 .if 0
6954 @cmp r1, #0 @ is second operand zero?
6955 beq common_errDivideByZero
6956 .endif
6957 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6958
6959 @ optional op; may set condition codes
6960 and r0, r0, r1 @ r0<- op, r0-r3 changed
6961 GET_INST_OPCODE(ip) @ extract opcode from rINST
6962 SET_VREG(r0, r9) @ vAA<- r0
6963 GOTO_OPCODE(ip) @ jump to next instruction
6964 /* 10-12 instructions */
6965
6966
6967
6968/* ------------------------------ */
6969 .balign 64
6970.L_OP_OR_INT_LIT8: /* 0xde */
6971/* File: armv5te/OP_OR_INT_LIT8.S */
6972/* File: armv5te/binopLit8.S */
6973 /*
6974 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
6975 * that specifies an instruction that performs "result = r0 op r1".
6976 * This could be an ARM instruction or a function call. (If the result
6977 * comes back in a register other than r0, you can override "result".)
6978 *
6979 * If "chkzero" is set to 1, we perform a divide-by-zero check on
6980 * vCC (r1). Useful for integer division and modulus.
6981 *
6982 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6983 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6984 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
6985 */
6986 /* binop/lit8 vAA, vBB, #+CC */
6987 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
6988 mov r9, rINST, lsr #8 @ r9<- AA
6989 and r2, r3, #255 @ r2<- BB
6990 GET_VREG(r0, r2) @ r0<- vBB
6991 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
6992 .if 0
6993 @cmp r1, #0 @ is second operand zero?
6994 beq common_errDivideByZero
6995 .endif
6996 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
6997
6998 @ optional op; may set condition codes
6999 orr r0, r0, r1 @ r0<- op, r0-r3 changed
7000 GET_INST_OPCODE(ip) @ extract opcode from rINST
7001 SET_VREG(r0, r9) @ vAA<- r0
7002 GOTO_OPCODE(ip) @ jump to next instruction
7003 /* 10-12 instructions */
7004
7005
7006
7007/* ------------------------------ */
7008 .balign 64
7009.L_OP_XOR_INT_LIT8: /* 0xdf */
7010/* File: armv5te/OP_XOR_INT_LIT8.S */
7011/* File: armv5te/binopLit8.S */
7012 /*
7013 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7014 * that specifies an instruction that performs "result = r0 op r1".
7015 * This could be an ARM instruction or a function call. (If the result
7016 * comes back in a register other than r0, you can override "result".)
7017 *
7018 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7019 * vCC (r1). Useful for integer division and modulus.
7020 *
7021 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7022 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7023 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7024 */
7025 /* binop/lit8 vAA, vBB, #+CC */
7026 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7027 mov r9, rINST, lsr #8 @ r9<- AA
7028 and r2, r3, #255 @ r2<- BB
7029 GET_VREG(r0, r2) @ r0<- vBB
7030 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7031 .if 0
7032 @cmp r1, #0 @ is second operand zero?
7033 beq common_errDivideByZero
7034 .endif
7035 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7036
7037 @ optional op; may set condition codes
7038 eor r0, r0, r1 @ r0<- op, r0-r3 changed
7039 GET_INST_OPCODE(ip) @ extract opcode from rINST
7040 SET_VREG(r0, r9) @ vAA<- r0
7041 GOTO_OPCODE(ip) @ jump to next instruction
7042 /* 10-12 instructions */
7043
7044
7045
7046/* ------------------------------ */
7047 .balign 64
7048.L_OP_SHL_INT_LIT8: /* 0xe0 */
7049/* File: armv5te/OP_SHL_INT_LIT8.S */
7050/* File: armv5te/binopLit8.S */
7051 /*
7052 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7053 * that specifies an instruction that performs "result = r0 op r1".
7054 * This could be an ARM instruction or a function call. (If the result
7055 * comes back in a register other than r0, you can override "result".)
7056 *
7057 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7058 * vCC (r1). Useful for integer division and modulus.
7059 *
7060 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7061 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7062 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7063 */
7064 /* binop/lit8 vAA, vBB, #+CC */
7065 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7066 mov r9, rINST, lsr #8 @ r9<- AA
7067 and r2, r3, #255 @ r2<- BB
7068 GET_VREG(r0, r2) @ r0<- vBB
7069 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7070 .if 0
7071 @cmp r1, #0 @ is second operand zero?
7072 beq common_errDivideByZero
7073 .endif
7074 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7075
7076 and r1, r1, #31 @ optional op; may set condition codes
7077 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed
7078 GET_INST_OPCODE(ip) @ extract opcode from rINST
7079 SET_VREG(r0, r9) @ vAA<- r0
7080 GOTO_OPCODE(ip) @ jump to next instruction
7081 /* 10-12 instructions */
7082
7083
7084
7085/* ------------------------------ */
7086 .balign 64
7087.L_OP_SHR_INT_LIT8: /* 0xe1 */
7088/* File: armv5te/OP_SHR_INT_LIT8.S */
7089/* File: armv5te/binopLit8.S */
7090 /*
7091 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7092 * that specifies an instruction that performs "result = r0 op r1".
7093 * This could be an ARM instruction or a function call. (If the result
7094 * comes back in a register other than r0, you can override "result".)
7095 *
7096 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7097 * vCC (r1). Useful for integer division and modulus.
7098 *
7099 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7100 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7101 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7102 */
7103 /* binop/lit8 vAA, vBB, #+CC */
7104 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7105 mov r9, rINST, lsr #8 @ r9<- AA
7106 and r2, r3, #255 @ r2<- BB
7107 GET_VREG(r0, r2) @ r0<- vBB
7108 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7109 .if 0
7110 @cmp r1, #0 @ is second operand zero?
7111 beq common_errDivideByZero
7112 .endif
7113 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7114
7115 and r1, r1, #31 @ optional op; may set condition codes
7116 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed
7117 GET_INST_OPCODE(ip) @ extract opcode from rINST
7118 SET_VREG(r0, r9) @ vAA<- r0
7119 GOTO_OPCODE(ip) @ jump to next instruction
7120 /* 10-12 instructions */
7121
7122
7123
7124/* ------------------------------ */
7125 .balign 64
7126.L_OP_USHR_INT_LIT8: /* 0xe2 */
7127/* File: armv5te/OP_USHR_INT_LIT8.S */
7128/* File: armv5te/binopLit8.S */
7129 /*
7130 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
7131 * that specifies an instruction that performs "result = r0 op r1".
7132 * This could be an ARM instruction or a function call. (If the result
7133 * comes back in a register other than r0, you can override "result".)
7134 *
7135 * If "chkzero" is set to 1, we perform a divide-by-zero check on
7136 * vCC (r1). Useful for integer division and modulus.
7137 *
7138 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7139 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7140 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
7141 */
7142 /* binop/lit8 vAA, vBB, #+CC */
7143 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC)
7144 mov r9, rINST, lsr #8 @ r9<- AA
7145 and r2, r3, #255 @ r2<- BB
7146 GET_VREG(r0, r2) @ r0<- vBB
7147 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended)
7148 .if 0
7149 @cmp r1, #0 @ is second operand zero?
7150 beq common_errDivideByZero
7151 .endif
7152 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7153
7154 and r1, r1, #31 @ optional op; may set condition codes
7155 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed
7156 GET_INST_OPCODE(ip) @ extract opcode from rINST
7157 SET_VREG(r0, r9) @ vAA<- r0
7158 GOTO_OPCODE(ip) @ jump to next instruction
7159 /* 10-12 instructions */
7160
7161
7162
7163/* ------------------------------ */
7164 .balign 64
7165.L_OP_UNUSED_E3: /* 0xe3 */
7166/* File: armv5te/OP_UNUSED_E3.S */
7167/* File: armv5te/unused.S */
7168 bl common_abort
7169
7170
7171
7172/* ------------------------------ */
7173 .balign 64
7174.L_OP_UNUSED_E4: /* 0xe4 */
7175/* File: armv5te/OP_UNUSED_E4.S */
7176/* File: armv5te/unused.S */
7177 bl common_abort
7178
7179
7180
7181/* ------------------------------ */
7182 .balign 64
7183.L_OP_UNUSED_E5: /* 0xe5 */
7184/* File: armv5te/OP_UNUSED_E5.S */
7185/* File: armv5te/unused.S */
7186 bl common_abort
7187
7188
7189
7190/* ------------------------------ */
7191 .balign 64
7192.L_OP_UNUSED_E6: /* 0xe6 */
7193/* File: armv5te/OP_UNUSED_E6.S */
7194/* File: armv5te/unused.S */
7195 bl common_abort
7196
7197
7198
7199/* ------------------------------ */
7200 .balign 64
7201.L_OP_UNUSED_E7: /* 0xe7 */
7202/* File: armv5te/OP_UNUSED_E7.S */
7203/* File: armv5te/unused.S */
7204 bl common_abort
7205
7206
7207
7208/* ------------------------------ */
7209 .balign 64
Andy McFadden53878242010-03-05 07:24:27 -08007210.L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */
7211/* File: armv5te/OP_IGET_WIDE_VOLATILE.S */
7212/* File: armv5te/OP_IGET_WIDE.S */
7213 /*
7214 * Wide 32-bit instance field get.
7215 */
7216 /* iget-wide vA, vB, field@CCCC */
7217 mov r0, rINST, lsr #12 @ r0<- B
7218 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
7219 FETCH(r1, 1) @ r1<- field ref CCCC
7220 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
7221 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
7222 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
7223 cmp r0, #0 @ is resolved entry null?
7224 bne .LOP_IGET_WIDE_VOLATILE_finish @ no, already resolved
72258: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
7226 EXPORT_PC() @ resolve() could throw
7227 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
7228 bl dvmResolveInstField @ r0<- resolved InstField ptr
7229 cmp r0, #0
7230 bne .LOP_IGET_WIDE_VOLATILE_finish
7231 b common_exceptionThrown
Andy McFaddena5069fb2009-06-19 15:20:12 -07007232
7233
7234/* ------------------------------ */
7235 .balign 64
Andy McFadden53878242010-03-05 07:24:27 -08007236.L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */
7237/* File: armv5te/OP_IPUT_WIDE_VOLATILE.S */
7238/* File: armv5te/OP_IPUT_WIDE.S */
7239 /* iput-wide vA, vB, field@CCCC */
7240 mov r0, rINST, lsr #12 @ r0<- B
7241 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
7242 FETCH(r1, 1) @ r1<- field ref CCCC
7243 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
7244 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
7245 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
7246 cmp r0, #0 @ is resolved entry null?
7247 bne .LOP_IPUT_WIDE_VOLATILE_finish @ no, already resolved
72488: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
7249 EXPORT_PC() @ resolve() could throw
7250 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
7251 bl dvmResolveInstField @ r0<- resolved InstField ptr
7252 cmp r0, #0 @ success?
7253 bne .LOP_IPUT_WIDE_VOLATILE_finish @ yes, finish up
7254 b common_exceptionThrown
Andy McFaddena5069fb2009-06-19 15:20:12 -07007255
7256
7257/* ------------------------------ */
7258 .balign 64
Andy McFadden53878242010-03-05 07:24:27 -08007259.L_OP_SGET_WIDE_VOLATILE: /* 0xea */
7260/* File: armv5te/OP_SGET_WIDE_VOLATILE.S */
7261/* File: armv5te/OP_SGET_WIDE.S */
7262 /*
7263 * 64-bit SGET handler.
7264 */
7265 /* sget-wide vAA, field@BBBB */
7266 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
7267 FETCH(r1, 1) @ r1<- field ref BBBB
7268 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7269 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
7270 cmp r0, #0 @ is resolved entry null?
7271 beq .LOP_SGET_WIDE_VOLATILE_resolve @ yes, do resolve
7272.LOP_SGET_WIDE_VOLATILE_finish:
Andy McFadden861b3382010-03-05 15:58:31 -08007273 mov r9, rINST, lsr #8 @ r9<- AA
7274 .if 1
7275 add r0, r0, #offStaticField_value @ r0<- pointer to data
7276 bl android_quasiatomic_read_64 @ r0/r1<- contents of field
7277 .else
7278 ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
7279 .endif
7280 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
Andy McFadden53878242010-03-05 07:24:27 -08007281 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
Andy McFadden861b3382010-03-05 15:58:31 -08007282 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
Andy McFadden53878242010-03-05 07:24:27 -08007283 GET_INST_OPCODE(ip) @ extract opcode from rINST
7284 GOTO_OPCODE(ip) @ jump to next instruction
Andy McFaddena5069fb2009-06-19 15:20:12 -07007285
7286
7287/* ------------------------------ */
7288 .balign 64
Andy McFadden53878242010-03-05 07:24:27 -08007289.L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */
7290/* File: armv5te/OP_SPUT_WIDE_VOLATILE.S */
7291/* File: armv5te/OP_SPUT_WIDE.S */
7292 /*
7293 * 64-bit SPUT handler.
7294 */
7295 /* sput-wide vAA, field@BBBB */
Andy McFadden861b3382010-03-05 15:58:31 -08007296 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex
Andy McFadden53878242010-03-05 07:24:27 -08007297 FETCH(r1, 1) @ r1<- field ref BBBB
Andy McFadden861b3382010-03-05 15:58:31 -08007298 ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
Andy McFadden53878242010-03-05 07:24:27 -08007299 mov r9, rINST, lsr #8 @ r9<- AA
Andy McFadden861b3382010-03-05 15:58:31 -08007300 ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr
Andy McFadden53878242010-03-05 07:24:27 -08007301 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
Andy McFadden861b3382010-03-05 15:58:31 -08007302 cmp r2, #0 @ is resolved entry null?
Andy McFadden53878242010-03-05 07:24:27 -08007303 beq .LOP_SPUT_WIDE_VOLATILE_resolve @ yes, do resolve
Andy McFadden861b3382010-03-05 15:58:31 -08007304.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9
Andy McFadden53878242010-03-05 07:24:27 -08007305 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
Andy McFadden861b3382010-03-05 15:58:31 -08007306 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
7307 GET_INST_OPCODE(r10) @ extract opcode from rINST
7308 .if 1
7309 add r2, r2, #offStaticField_value @ r2<- pointer to data
7310 bl android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
7311 .else
7312 strd r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
7313 .endif
7314 GOTO_OPCODE(r10) @ jump to next instruction
Andy McFaddena5069fb2009-06-19 15:20:12 -07007315
7316
7317/* ------------------------------ */
7318 .balign 64
Andy McFadden96516932009-10-28 17:39:02 -07007319.L_OP_BREAKPOINT: /* 0xec */
7320/* File: armv5te/OP_BREAKPOINT.S */
Andy McFaddena5069fb2009-06-19 15:20:12 -07007321/* File: armv5te/unused.S */
7322 bl common_abort
7323
7324
7325
7326/* ------------------------------ */
7327 .balign 64
7328.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
7329/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
7330 /*
7331 * Handle a throw-verification-error instruction. This throws an
7332 * exception for an error discovered during verification. The
7333 * exception is indicated by AA, with some detail provided by BBBB.
7334 */
7335 /* op AA, ref@BBBB */
7336 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7337 FETCH(r2, 1) @ r2<- BBBB
7338 EXPORT_PC() @ export the PC
7339 mov r1, rINST, lsr #8 @ r1<- AA
7340 bl dvmThrowVerificationError @ always throws
7341 b common_exceptionThrown @ handle exception
7342
7343
7344/* ------------------------------ */
7345 .balign 64
7346.L_OP_EXECUTE_INLINE: /* 0xee */
7347/* File: armv5te/OP_EXECUTE_INLINE.S */
7348 /*
7349 * Execute a "native inline" instruction.
7350 *
Andy McFaddenb0a05412009-11-19 10:23:41 -08007351 * We need to call an InlineOp4Func:
7352 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
Andy McFaddena5069fb2009-06-19 15:20:12 -07007353 *
Andy McFaddenb0a05412009-11-19 10:23:41 -08007354 * The first four args are in r0-r3, pointer to return value storage
7355 * is on the stack. The function's return value is a flag that tells
7356 * us if an exception was thrown.
Andy McFaddena5069fb2009-06-19 15:20:12 -07007357 */
7358 /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
7359 FETCH(r10, 1) @ r10<- BBBB
7360 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval
7361 EXPORT_PC() @ can throw
Andy McFaddenb0a05412009-11-19 10:23:41 -08007362 sub sp, sp, #8 @ make room for arg, +64 bit align
Andy McFaddena5069fb2009-06-19 15:20:12 -07007363 mov r0, rINST, lsr #12 @ r0<- B
7364 str r1, [sp] @ push &glue->retval
7365 bl .LOP_EXECUTE_INLINE_continue @ make call; will return after
7366 add sp, sp, #8 @ pop stack
7367 cmp r0, #0 @ test boolean result of inline
7368 beq common_exceptionThrown @ returned false, handle exception
7369 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
7370 GET_INST_OPCODE(ip) @ extract opcode from rINST
7371 GOTO_OPCODE(ip) @ jump to next instruction
7372
7373/* ------------------------------ */
7374 .balign 64
Andy McFaddenb0a05412009-11-19 10:23:41 -08007375.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */
7376/* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */
7377 /*
7378 * Execute a "native inline" instruction, using "/range" semantics.
7379 * Same idea as execute-inline, but we get the args differently.
7380 *
7381 * We need to call an InlineOp4Func:
7382 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7383 *
7384 * The first four args are in r0-r3, pointer to return value storage
7385 * is on the stack. The function's return value is a flag that tells
7386 * us if an exception was thrown.
7387 */
7388 /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */
7389 FETCH(r10, 1) @ r10<- BBBB
7390 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval
7391 EXPORT_PC() @ can throw
7392 sub sp, sp, #8 @ make room for arg, +64 bit align
7393 mov r0, rINST, lsr #8 @ r0<- AA
7394 str r1, [sp] @ push &glue->retval
7395 bl .LOP_EXECUTE_INLINE_RANGE_continue @ make call; will return after
7396 add sp, sp, #8 @ pop stack
7397 cmp r0, #0 @ test boolean result of inline
7398 beq common_exceptionThrown @ returned false, handle exception
7399 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
7400 GET_INST_OPCODE(ip) @ extract opcode from rINST
7401 GOTO_OPCODE(ip) @ jump to next instruction
Andy McFaddena5069fb2009-06-19 15:20:12 -07007402
7403/* ------------------------------ */
7404 .balign 64
7405.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
7406/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
7407 /*
7408 * invoke-direct-empty is a no-op in a "standard" interpreter.
7409 */
7410 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST
7411 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
7412 GOTO_OPCODE(ip) @ execute it
7413
7414/* ------------------------------ */
7415 .balign 64
7416.L_OP_UNUSED_F1: /* 0xf1 */
7417/* File: armv5te/OP_UNUSED_F1.S */
7418/* File: armv5te/unused.S */
7419 bl common_abort
7420
7421
7422
7423/* ------------------------------ */
7424 .balign 64
7425.L_OP_IGET_QUICK: /* 0xf2 */
7426/* File: armv6t2/OP_IGET_QUICK.S */
7427 /* For: iget-quick, iget-object-quick */
7428 /* op vA, vB, offset@CCCC */
7429 mov r2, rINST, lsr #12 @ r2<- B
7430 FETCH(r1, 1) @ r1<- field byte offset
7431 GET_VREG(r3, r2) @ r3<- object we're operating on
7432 ubfx r2, rINST, #8, #4 @ r2<- A
7433 cmp r3, #0 @ check object for null
7434 beq common_errNullObject @ object was null
7435 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits)
7436 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7437 GET_INST_OPCODE(ip) @ extract opcode from rINST
7438 SET_VREG(r0, r2) @ fp[A]<- r0
7439 GOTO_OPCODE(ip) @ jump to next instruction
7440
7441
7442/* ------------------------------ */
7443 .balign 64
7444.L_OP_IGET_WIDE_QUICK: /* 0xf3 */
7445/* File: armv6t2/OP_IGET_WIDE_QUICK.S */
7446 /* iget-wide-quick vA, vB, offset@CCCC */
7447 mov r2, rINST, lsr #12 @ r2<- B
7448 FETCH(r1, 1) @ r1<- field byte offset
7449 GET_VREG(r3, r2) @ r3<- object we're operating on
7450 ubfx r2, rINST, #8, #4 @ r2<- A
7451 cmp r3, #0 @ check object for null
7452 beq common_errNullObject @ object was null
7453 ldrd r0, [r3, r1] @ r0<- obj.field (64 bits, aligned)
7454 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7455 add r3, rFP, r2, lsl #2 @ r3<- &fp[A]
7456 GET_INST_OPCODE(ip) @ extract opcode from rINST
7457 stmia r3, {r0-r1} @ fp[A]<- r0/r1
7458 GOTO_OPCODE(ip) @ jump to next instruction
7459
7460
7461/* ------------------------------ */
7462 .balign 64
7463.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
7464/* File: armv5te/OP_IGET_OBJECT_QUICK.S */
7465/* File: armv5te/OP_IGET_QUICK.S */
7466 /* For: iget-quick, iget-object-quick */
7467 /* op vA, vB, offset@CCCC */
7468 mov r2, rINST, lsr #12 @ r2<- B
7469 GET_VREG(r3, r2) @ r3<- object we're operating on
7470 FETCH(r1, 1) @ r1<- field byte offset
7471 cmp r3, #0 @ check object for null
7472 mov r2, rINST, lsr #8 @ r2<- A(+)
7473 beq common_errNullObject @ object was null
7474 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits)
7475 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7476 and r2, r2, #15
7477 GET_INST_OPCODE(ip) @ extract opcode from rINST
7478 SET_VREG(r0, r2) @ fp[A]<- r0
7479 GOTO_OPCODE(ip) @ jump to next instruction
7480
7481
7482
7483/* ------------------------------ */
7484 .balign 64
7485.L_OP_IPUT_QUICK: /* 0xf5 */
7486/* File: armv6t2/OP_IPUT_QUICK.S */
7487 /* For: iput-quick, iput-object-quick */
7488 /* op vA, vB, offset@CCCC */
7489 mov r2, rINST, lsr #12 @ r2<- B
7490 FETCH(r1, 1) @ r1<- field byte offset
7491 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer
7492 ubfx r2, rINST, #8, #4 @ r2<- A
7493 cmp r3, #0 @ check object for null
7494 beq common_errNullObject @ object was null
7495 GET_VREG(r0, r2) @ r0<- fp[A]
7496 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7497 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0
7498 GET_INST_OPCODE(ip) @ extract opcode from rINST
7499 GOTO_OPCODE(ip) @ jump to next instruction
7500
7501
7502/* ------------------------------ */
7503 .balign 64
7504.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
7505/* File: armv6t2/OP_IPUT_WIDE_QUICK.S */
7506 /* iput-wide-quick vA, vB, offset@CCCC */
7507 mov r1, rINST, lsr #12 @ r1<- B
7508 ubfx r0, rINST, #8, #4 @ r0<- A
7509 GET_VREG(r2, r1) @ r2<- fp[B], the object pointer
7510 add r3, rFP, r0, lsl #2 @ r3<- &fp[A]
7511 cmp r2, #0 @ check object for null
7512 ldmia r3, {r0-r1} @ r0/r1<- fp[A]
7513 beq common_errNullObject @ object was null
7514 FETCH(r3, 1) @ r3<- field byte offset
7515 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7516 strd r0, [r2, r3] @ obj.field (64 bits, aligned)<- r0/r1
7517 GET_INST_OPCODE(ip) @ extract opcode from rINST
7518 GOTO_OPCODE(ip) @ jump to next instruction
7519
7520
7521/* ------------------------------ */
7522 .balign 64
7523.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
7524/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
7525/* File: armv5te/OP_IPUT_QUICK.S */
7526 /* For: iput-quick, iput-object-quick */
7527 /* op vA, vB, offset@CCCC */
7528 mov r2, rINST, lsr #12 @ r2<- B
7529 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer
7530 FETCH(r1, 1) @ r1<- field byte offset
7531 cmp r3, #0 @ check object for null
7532 mov r2, rINST, lsr #8 @ r2<- A(+)
7533 beq common_errNullObject @ object was null
7534 and r2, r2, #15
7535 GET_VREG(r0, r2) @ r0<- fp[A]
7536 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7537 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0
7538 GET_INST_OPCODE(ip) @ extract opcode from rINST
7539 GOTO_OPCODE(ip) @ jump to next instruction
7540
7541
7542
7543/* ------------------------------ */
7544 .balign 64
7545.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
7546/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7547 /*
7548 * Handle an optimized virtual method call.
7549 *
7550 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7551 */
7552 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7553 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7554 FETCH(r3, 2) @ r3<- FEDC or CCCC
7555 FETCH(r1, 1) @ r1<- BBBB
7556 .if (!0)
7557 and r3, r3, #15 @ r3<- C (or stays CCCC)
7558 .endif
7559 GET_VREG(r2, r3) @ r2<- vC ("this" ptr)
7560 cmp r2, #0 @ is "this" null?
7561 beq common_errNullObject @ null "this", throw exception
7562 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz
7563 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable
7564 EXPORT_PC() @ invoke must export
7565 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB]
7566 bl common_invokeMethodNoRange @ continue on
7567
7568/* ------------------------------ */
7569 .balign 64
7570.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
7571/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
7572/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7573 /*
7574 * Handle an optimized virtual method call.
7575 *
7576 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7577 */
7578 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7579 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7580 FETCH(r3, 2) @ r3<- FEDC or CCCC
7581 FETCH(r1, 1) @ r1<- BBBB
7582 .if (!1)
7583 and r3, r3, #15 @ r3<- C (or stays CCCC)
7584 .endif
7585 GET_VREG(r2, r3) @ r2<- vC ("this" ptr)
7586 cmp r2, #0 @ is "this" null?
7587 beq common_errNullObject @ null "this", throw exception
7588 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz
7589 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable
7590 EXPORT_PC() @ invoke must export
7591 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB]
7592 bl common_invokeMethodRange @ continue on
7593
7594
7595/* ------------------------------ */
7596 .balign 64
7597.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
7598/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7599 /*
7600 * Handle an optimized "super" method call.
7601 *
7602 * for: [opt] invoke-super-quick, invoke-super-quick/range
7603 */
7604 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7605 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7606 FETCH(r10, 2) @ r10<- GFED or CCCC
7607 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
7608 .if (!0)
7609 and r10, r10, #15 @ r10<- D (or stays CCCC)
7610 .endif
7611 FETCH(r1, 1) @ r1<- BBBB
7612 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz
7613 EXPORT_PC() @ must export for invoke
7614 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super
7615 GET_VREG(r3, r10) @ r3<- "this"
7616 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable
7617 cmp r3, #0 @ null "this" ref?
7618 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB]
7619 beq common_errNullObject @ "this" is null, throw exception
7620 bl common_invokeMethodNoRange @ continue on
7621
7622
7623/* ------------------------------ */
7624 .balign 64
7625.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
7626/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
7627/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7628 /*
7629 * Handle an optimized "super" method call.
7630 *
7631 * for: [opt] invoke-super-quick, invoke-super-quick/range
7632 */
7633 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7634 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7635 FETCH(r10, 2) @ r10<- GFED or CCCC
7636 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
7637 .if (!1)
7638 and r10, r10, #15 @ r10<- D (or stays CCCC)
7639 .endif
7640 FETCH(r1, 1) @ r1<- BBBB
7641 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz
7642 EXPORT_PC() @ must export for invoke
7643 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super
7644 GET_VREG(r3, r10) @ r3<- "this"
7645 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable
7646 cmp r3, #0 @ null "this" ref?
7647 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB]
7648 beq common_errNullObject @ "this" is null, throw exception
7649 bl common_invokeMethodRange @ continue on
7650
7651
7652
7653/* ------------------------------ */
7654 .balign 64
7655.L_OP_UNUSED_FC: /* 0xfc */
7656/* File: armv5te/OP_UNUSED_FC.S */
7657/* File: armv5te/unused.S */
7658 bl common_abort
7659
7660
7661
7662/* ------------------------------ */
7663 .balign 64
7664.L_OP_UNUSED_FD: /* 0xfd */
7665/* File: armv5te/OP_UNUSED_FD.S */
7666/* File: armv5te/unused.S */
7667 bl common_abort
7668
7669
7670
7671/* ------------------------------ */
7672 .balign 64
7673.L_OP_UNUSED_FE: /* 0xfe */
7674/* File: armv5te/OP_UNUSED_FE.S */
7675/* File: armv5te/unused.S */
7676 bl common_abort
7677
7678
7679
7680/* ------------------------------ */
7681 .balign 64
7682.L_OP_UNUSED_FF: /* 0xff */
7683/* File: armv5te/OP_UNUSED_FF.S */
7684/* File: armv5te/unused.S */
7685 bl common_abort
7686
7687
7688
7689
7690 .balign 64
7691 .size dvmAsmInstructionStart, .-dvmAsmInstructionStart
7692 .global dvmAsmInstructionEnd
7693dvmAsmInstructionEnd:
7694
7695/*
7696 * ===========================================================================
7697 * Sister implementations
7698 * ===========================================================================
7699 */
7700 .global dvmAsmSisterStart
7701 .type dvmAsmSisterStart, %function
7702 .text
7703 .balign 4
7704dvmAsmSisterStart:
7705
7706/* continuation for OP_CONST_STRING */
7707
7708 /*
7709 * Continuation if the String has not yet been resolved.
7710 * r1: BBBB (String ref)
7711 * r9: target register
7712 */
7713.LOP_CONST_STRING_resolve:
7714 EXPORT_PC()
7715 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7716 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz
7717 bl dvmResolveString @ r0<- String reference
7718 cmp r0, #0 @ failed?
7719 beq common_exceptionThrown @ yup, handle the exception
7720 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7721 GET_INST_OPCODE(ip) @ extract opcode from rINST
7722 SET_VREG(r0, r9) @ vAA<- r0
7723 GOTO_OPCODE(ip) @ jump to next instruction
7724
7725
7726/* continuation for OP_CONST_STRING_JUMBO */
7727
7728 /*
7729 * Continuation if the String has not yet been resolved.
7730 * r1: BBBBBBBB (String ref)
7731 * r9: target register
7732 */
7733.LOP_CONST_STRING_JUMBO_resolve:
7734 EXPORT_PC()
7735 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7736 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz
7737 bl dvmResolveString @ r0<- String reference
7738 cmp r0, #0 @ failed?
7739 beq common_exceptionThrown @ yup, handle the exception
7740 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
7741 GET_INST_OPCODE(ip) @ extract opcode from rINST
7742 SET_VREG(r0, r9) @ vAA<- r0
7743 GOTO_OPCODE(ip) @ jump to next instruction
7744
7745
7746/* continuation for OP_CONST_CLASS */
7747
7748 /*
7749 * Continuation if the Class has not yet been resolved.
7750 * r1: BBBB (Class ref)
7751 * r9: target register
7752 */
7753.LOP_CONST_CLASS_resolve:
7754 EXPORT_PC()
7755 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7756 mov r2, #1 @ r2<- true
7757 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz
7758 bl dvmResolveClass @ r0<- Class reference
7759 cmp r0, #0 @ failed?
7760 beq common_exceptionThrown @ yup, handle the exception
7761 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7762 GET_INST_OPCODE(ip) @ extract opcode from rINST
7763 SET_VREG(r0, r9) @ vAA<- r0
7764 GOTO_OPCODE(ip) @ jump to next instruction
7765
7766
7767/* continuation for OP_CHECK_CAST */
7768
7769 /*
7770 * Trivial test failed, need to perform full check. This is common.
7771 * r0 holds obj->clazz
7772 * r1 holds class resolved from BBBB
7773 * r9 holds object
7774 */
7775.LOP_CHECK_CAST_fullcheck:
7776 bl dvmInstanceofNonTrivial @ r0<- boolean result
7777 cmp r0, #0 @ failed?
7778 bne .LOP_CHECK_CAST_okay @ no, success
7779
7780 @ A cast has failed. We need to throw a ClassCastException with the
7781 @ class of the object that failed to be cast.
7782 EXPORT_PC() @ about to throw
7783 ldr r3, [r9, #offObject_clazz] @ r3<- obj->clazz
7784 ldr r0, .LstrClassCastExceptionPtr
7785 ldr r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor
7786 bl dvmThrowExceptionWithClassMessage
7787 b common_exceptionThrown
7788
7789 /*
7790 * Resolution required. This is the least-likely path.
7791 *
7792 * r2 holds BBBB
7793 * r9 holds object
7794 */
7795.LOP_CHECK_CAST_resolve:
7796 EXPORT_PC() @ resolve() could throw
7797 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7798 mov r1, r2 @ r1<- BBBB
7799 mov r2, #0 @ r2<- false
7800 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
7801 bl dvmResolveClass @ r0<- resolved ClassObject ptr
7802 cmp r0, #0 @ got null?
7803 beq common_exceptionThrown @ yes, handle exception
7804 mov r1, r0 @ r1<- class resolved from BBB
7805 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz
7806 b .LOP_CHECK_CAST_resolved @ pick up where we left off
7807
7808.LstrClassCastExceptionPtr:
7809 .word .LstrClassCastException
7810
7811
7812/* continuation for OP_INSTANCE_OF */
7813
7814 /*
7815 * Trivial test failed, need to perform full check. This is common.
7816 * r0 holds obj->clazz
7817 * r1 holds class resolved from BBBB
7818 * r9 holds A
7819 */
7820.LOP_INSTANCE_OF_fullcheck:
7821 bl dvmInstanceofNonTrivial @ r0<- boolean result
7822 @ fall through to OP_INSTANCE_OF_store
7823
7824 /*
7825 * r0 holds boolean result
7826 * r9 holds A
7827 */
7828.LOP_INSTANCE_OF_store:
7829 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7830 SET_VREG(r0, r9) @ vA<- r0
7831 GET_INST_OPCODE(ip) @ extract opcode from rINST
7832 GOTO_OPCODE(ip) @ jump to next instruction
7833
7834 /*
7835 * Trivial test succeeded, save and bail.
7836 * r9 holds A
7837 */
7838.LOP_INSTANCE_OF_trivial:
7839 mov r0, #1 @ indicate success
7840 @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
7841 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7842 SET_VREG(r0, r9) @ vA<- r0
7843 GET_INST_OPCODE(ip) @ extract opcode from rINST
7844 GOTO_OPCODE(ip) @ jump to next instruction
7845
7846 /*
7847 * Resolution required. This is the least-likely path.
7848 *
7849 * r3 holds BBBB
7850 * r9 holds A
7851 */
7852.LOP_INSTANCE_OF_resolve:
7853 EXPORT_PC() @ resolve() could throw
7854 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7855 mov r1, r3 @ r1<- BBBB
7856 mov r2, #1 @ r2<- true
7857 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz
7858 bl dvmResolveClass @ r0<- resolved ClassObject ptr
7859 cmp r0, #0 @ got null?
7860 beq common_exceptionThrown @ yes, handle exception
7861 mov r1, r0 @ r1<- class resolved from BBB
7862 mov r3, rINST, lsr #12 @ r3<- B
7863 GET_VREG(r0, r3) @ r0<- vB (object)
7864 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz
7865 b .LOP_INSTANCE_OF_resolved @ pick up where we left off
7866
7867
7868/* continuation for OP_NEW_INSTANCE */
7869
7870 .balign 32 @ minimize cache lines
7871.LOP_NEW_INSTANCE_finish: @ r0=new object
7872 mov r3, rINST, lsr #8 @ r3<- AA
7873 cmp r0, #0 @ failed?
7874 beq common_exceptionThrown @ yes, handle the exception
7875 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7876 GET_INST_OPCODE(ip) @ extract opcode from rINST
7877 SET_VREG(r0, r3) @ vAA<- r0
7878 GOTO_OPCODE(ip) @ jump to next instruction
7879
7880 /*
7881 * Class initialization required.
7882 *
7883 * r0 holds class object
7884 */
7885.LOP_NEW_INSTANCE_needinit:
7886 mov r9, r0 @ save r0
7887 bl dvmInitClass @ initialize class
7888 cmp r0, #0 @ check boolean result
7889 mov r0, r9 @ restore r0
7890 bne .LOP_NEW_INSTANCE_initialized @ success, continue
7891 b common_exceptionThrown @ failed, deal with init exception
7892
7893 /*
7894 * Resolution required. This is the least-likely path.
7895 *
7896 * r1 holds BBBB
7897 */
7898.LOP_NEW_INSTANCE_resolve:
7899 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7900 mov r2, #0 @ r2<- false
7901 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
7902 bl dvmResolveClass @ r0<- resolved ClassObject ptr
7903 cmp r0, #0 @ got null?
7904 bne .LOP_NEW_INSTANCE_resolved @ no, continue
7905 b common_exceptionThrown @ yes, handle exception
7906
7907.LstrInstantiationErrorPtr:
7908 .word .LstrInstantiationError
7909
7910
7911/* continuation for OP_NEW_ARRAY */
7912
7913
7914 /*
7915 * Resolve class. (This is an uncommon case.)
7916 *
7917 * r1 holds array length
7918 * r2 holds class ref CCCC
7919 */
7920.LOP_NEW_ARRAY_resolve:
7921 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7922 mov r9, r1 @ r9<- length (save)
7923 mov r1, r2 @ r1<- CCCC
7924 mov r2, #0 @ r2<- false
7925 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
7926 bl dvmResolveClass @ r0<- call(clazz, ref)
7927 cmp r0, #0 @ got null?
7928 mov r1, r9 @ r1<- length (restore)
7929 beq common_exceptionThrown @ yes, handle exception
7930 @ fall through to OP_NEW_ARRAY_finish
7931
7932 /*
7933 * Finish allocation.
7934 *
7935 * r0 holds class
7936 * r1 holds array length
7937 */
7938.LOP_NEW_ARRAY_finish:
7939 mov r2, #ALLOC_DONT_TRACK @ don't track in local refs table
7940 bl dvmAllocArrayByClass @ r0<- call(clazz, length, flags)
7941 cmp r0, #0 @ failed?
7942 mov r2, rINST, lsr #8 @ r2<- A+
7943 beq common_exceptionThrown @ yes, handle the exception
7944 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
7945 and r2, r2, #15 @ r2<- A
7946 GET_INST_OPCODE(ip) @ extract opcode from rINST
7947 SET_VREG(r0, r2) @ vA<- r0
7948 GOTO_OPCODE(ip) @ jump to next instruction
7949
7950
7951/* continuation for OP_FILLED_NEW_ARRAY */
7952
7953 /*
7954 * On entry:
7955 * r0 holds array class
7956 * r10 holds AA or BA
7957 */
7958.LOP_FILLED_NEW_ARRAY_continue:
7959 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
7960 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags
7961 ldrb r3, [r3, #1] @ r3<- descriptor[1]
7962 .if 0
7963 mov r1, r10 @ r1<- AA (length)
7964 .else
7965 mov r1, r10, lsr #4 @ r1<- B (length)
7966 .endif
7967 cmp r3, #'I' @ array of ints?
7968 cmpne r3, #'L' @ array of objects?
7969 cmpne r3, #'[' @ array of arrays?
7970 mov r9, r1 @ save length in r9
7971 bne .LOP_FILLED_NEW_ARRAY_notimpl @ no, not handled yet
7972 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags)
7973 cmp r0, #0 @ null return?
7974 beq common_exceptionThrown @ alloc failed, handle exception
7975
7976 FETCH(r1, 2) @ r1<- FEDC or CCCC
7977 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array
7978 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents
7979 subs r9, r9, #1 @ length--, check for neg
7980 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST
7981 bmi 2f @ was zero, bail
7982
7983 @ copy values from registers into the array
7984 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
7985 .if 0
7986 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC]
79871: ldr r3, [r2], #4 @ r3<- *r2++
7988 subs r9, r9, #1 @ count--
7989 str r3, [r0], #4 @ *contents++ = vX
7990 bpl 1b
7991 @ continue at 2
7992 .else
7993 cmp r9, #4 @ length was initially 5?
7994 and r2, r10, #15 @ r2<- A
7995 bne 1f @ <= 4 args, branch
7996 GET_VREG(r3, r2) @ r3<- vA
7997 sub r9, r9, #1 @ count--
7998 str r3, [r0, #16] @ contents[4] = vA
79991: and r2, r1, #15 @ r2<- F/E/D/C
8000 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC
8001 mov r1, r1, lsr #4 @ r1<- next reg in low 4
8002 subs r9, r9, #1 @ count--
8003 str r3, [r0], #4 @ *contents++ = vX
8004 bpl 1b
8005 @ continue at 2
8006 .endif
8007
80082:
8009 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
8010 GOTO_OPCODE(ip) @ execute it
8011
8012 /*
8013 * Throw an exception indicating that we have not implemented this
8014 * mode of filled-new-array.
8015 */
8016.LOP_FILLED_NEW_ARRAY_notimpl:
8017 ldr r0, .L_strInternalError
8018 ldr r1, .L_strFilledNewArrayNotImpl
8019 bl dvmThrowException
8020 b common_exceptionThrown
8021
8022 .if (!0) @ define in one or the other, not both
8023.L_strFilledNewArrayNotImpl:
8024 .word .LstrFilledNewArrayNotImpl
8025.L_strInternalError:
8026 .word .LstrInternalError
8027 .endif
8028
8029
8030/* continuation for OP_FILLED_NEW_ARRAY_RANGE */
8031
8032 /*
8033 * On entry:
8034 * r0 holds array class
8035 * r10 holds AA or BA
8036 */
8037.LOP_FILLED_NEW_ARRAY_RANGE_continue:
8038 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8039 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags
8040 ldrb r3, [r3, #1] @ r3<- descriptor[1]
8041 .if 1
8042 mov r1, r10 @ r1<- AA (length)
8043 .else
8044 mov r1, r10, lsr #4 @ r1<- B (length)
8045 .endif
8046 cmp r3, #'I' @ array of ints?
8047 cmpne r3, #'L' @ array of objects?
8048 cmpne r3, #'[' @ array of arrays?
8049 mov r9, r1 @ save length in r9
8050 bne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl @ no, not handled yet
8051 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags)
8052 cmp r0, #0 @ null return?
8053 beq common_exceptionThrown @ alloc failed, handle exception
8054
8055 FETCH(r1, 2) @ r1<- FEDC or CCCC
8056 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array
8057 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8058 subs r9, r9, #1 @ length--, check for neg
8059 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST
8060 bmi 2f @ was zero, bail
8061
8062 @ copy values from registers into the array
8063 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8064 .if 1
8065 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC]
80661: ldr r3, [r2], #4 @ r3<- *r2++
8067 subs r9, r9, #1 @ count--
8068 str r3, [r0], #4 @ *contents++ = vX
8069 bpl 1b
8070 @ continue at 2
8071 .else
8072 cmp r9, #4 @ length was initially 5?
8073 and r2, r10, #15 @ r2<- A
8074 bne 1f @ <= 4 args, branch
8075 GET_VREG(r3, r2) @ r3<- vA
8076 sub r9, r9, #1 @ count--
8077 str r3, [r0, #16] @ contents[4] = vA
80781: and r2, r1, #15 @ r2<- F/E/D/C
8079 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC
8080 mov r1, r1, lsr #4 @ r1<- next reg in low 4
8081 subs r9, r9, #1 @ count--
8082 str r3, [r0], #4 @ *contents++ = vX
8083 bpl 1b
8084 @ continue at 2
8085 .endif
8086
80872:
8088 GET_INST_OPCODE(ip) @ ip<- opcode from rINST
8089 GOTO_OPCODE(ip) @ execute it
8090
8091 /*
8092 * Throw an exception indicating that we have not implemented this
8093 * mode of filled-new-array.
8094 */
8095.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
8096 ldr r0, .L_strInternalError
8097 ldr r1, .L_strFilledNewArrayNotImpl
8098 bl dvmThrowException
8099 b common_exceptionThrown
8100
8101 .if (!1) @ define in one or the other, not both
8102.L_strFilledNewArrayNotImpl:
8103 .word .LstrFilledNewArrayNotImpl
8104.L_strInternalError:
8105 .word .LstrInternalError
8106 .endif
8107
8108
8109/* continuation for OP_CMPL_FLOAT */
8110.LOP_CMPL_FLOAT_finish:
8111 SET_VREG(r0, r9) @ vAA<- r0
8112 GOTO_OPCODE(ip) @ jump to next instruction
8113
8114
8115/* continuation for OP_CMPG_FLOAT */
8116.LOP_CMPG_FLOAT_finish:
8117 SET_VREG(r0, r9) @ vAA<- r0
8118 GOTO_OPCODE(ip) @ jump to next instruction
8119
8120
8121/* continuation for OP_CMPL_DOUBLE */
8122.LOP_CMPL_DOUBLE_finish:
8123 SET_VREG(r0, r9) @ vAA<- r0
8124 GOTO_OPCODE(ip) @ jump to next instruction
8125
8126
8127/* continuation for OP_CMPG_DOUBLE */
8128.LOP_CMPG_DOUBLE_finish:
8129 SET_VREG(r0, r9) @ vAA<- r0
8130 GOTO_OPCODE(ip) @ jump to next instruction
8131
8132
8133/* continuation for OP_CMP_LONG */
8134
8135.LOP_CMP_LONG_less:
8136 mvn r1, #0 @ r1<- -1
8137 @ Want to cond code the next mov so we can avoid branch, but don't see it;
8138 @ instead, we just replicate the tail end.
8139 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8140 SET_VREG(r1, r9) @ vAA<- r1
8141 GET_INST_OPCODE(ip) @ extract opcode from rINST
8142 GOTO_OPCODE(ip) @ jump to next instruction
8143
8144.LOP_CMP_LONG_greater:
8145 mov r1, #1 @ r1<- 1
8146 @ fall through to _finish
8147
8148.LOP_CMP_LONG_finish:
8149 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8150 SET_VREG(r1, r9) @ vAA<- r1
8151 GET_INST_OPCODE(ip) @ extract opcode from rINST
8152 GOTO_OPCODE(ip) @ jump to next instruction
8153
8154
8155/* continuation for OP_AGET_WIDE */
8156
8157.LOP_AGET_WIDE_finish:
8158 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8159 ldrd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC]
8160 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
8161 GET_INST_OPCODE(ip) @ extract opcode from rINST
8162 stmia r9, {r2-r3} @ vAA/vAA+1<- r2/r3
8163 GOTO_OPCODE(ip) @ jump to next instruction
8164
8165
8166/* continuation for OP_APUT_WIDE */
8167
8168.LOP_APUT_WIDE_finish:
8169 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8170 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1
8171 GET_INST_OPCODE(ip) @ extract opcode from rINST
8172 strd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC]
8173 GOTO_OPCODE(ip) @ jump to next instruction
8174
8175
8176/* continuation for OP_APUT_OBJECT */
8177 /*
8178 * On entry:
8179 * r1 = vBB (arrayObj)
8180 * r9 = vAA (obj)
8181 * r10 = offset into array (vBB + vCC * width)
8182 */
8183.LOP_APUT_OBJECT_finish:
8184 cmp r9, #0 @ storing null reference?
8185 beq .LOP_APUT_OBJECT_skip_check @ yes, skip type checks
8186 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz
8187 ldr r1, [r1, #offObject_clazz] @ r1<- arrayObj->clazz
8188 bl dvmCanPutArrayElement @ test object type vs. array type
8189 cmp r0, #0 @ okay?
8190 beq common_errArrayStore @ no
8191.LOP_APUT_OBJECT_skip_check:
8192 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8193 GET_INST_OPCODE(ip) @ extract opcode from rINST
8194 str r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
8195 GOTO_OPCODE(ip) @ jump to next instruction
8196
8197
8198/* continuation for OP_IGET */
8199
8200 /*
8201 * Currently:
8202 * r0 holds resolved field
8203 * r9 holds object
8204 */
8205.LOP_IGET_finish:
8206 @bl common_squeak0
8207 cmp r9, #0 @ check object for null
8208 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8209 beq common_errNullObject @ object was null
8210 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits)
8211 ubfx r2, rINST, #8, #4 @ r2<- A
8212 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8213 GET_INST_OPCODE(ip) @ extract opcode from rINST
8214 SET_VREG(r0, r2) @ fp[A]<- r0
8215 GOTO_OPCODE(ip) @ jump to next instruction
8216
8217
8218/* continuation for OP_IGET_WIDE */
8219
8220 /*
8221 * Currently:
8222 * r0 holds resolved field
8223 * r9 holds object
8224 */
8225.LOP_IGET_WIDE_finish:
8226 cmp r9, #0 @ check object for null
8227 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8228 beq common_errNullObject @ object was null
8229 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok)
8230 ubfx r2, rINST, #8, #4 @ r2<- A
8231 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8232 add r3, rFP, r2, lsl #2 @ r3<- &fp[A]
8233 GET_INST_OPCODE(ip) @ extract opcode from rINST
8234 stmia r3, {r0-r1} @ fp[A]<- r0/r1
8235 GOTO_OPCODE(ip) @ jump to next instruction
8236
8237
8238/* continuation for OP_IGET_OBJECT */
8239
8240 /*
8241 * Currently:
8242 * r0 holds resolved field
8243 * r9 holds object
8244 */
8245.LOP_IGET_OBJECT_finish:
8246 @bl common_squeak0
8247 cmp r9, #0 @ check object for null
8248 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8249 beq common_errNullObject @ object was null
8250 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits)
8251 mov r2, rINST, lsr #8 @ r2<- A+
8252 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8253 and r2, r2, #15 @ r2<- A
8254 GET_INST_OPCODE(ip) @ extract opcode from rINST
8255 SET_VREG(r0, r2) @ fp[A]<- r0
8256 GOTO_OPCODE(ip) @ jump to next instruction
8257
8258
8259/* continuation for OP_IGET_BOOLEAN */
8260
8261 /*
8262 * Currently:
8263 * r0 holds resolved field
8264 * r9 holds object
8265 */
8266.LOP_IGET_BOOLEAN_finish:
8267 @bl common_squeak1
8268 cmp r9, #0 @ check object for null
8269 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8270 beq common_errNullObject @ object was null
8271 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits)
8272 mov r2, rINST, lsr #8 @ r2<- A+
8273 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8274 and r2, r2, #15 @ r2<- A
8275 GET_INST_OPCODE(ip) @ extract opcode from rINST
8276 SET_VREG(r0, r2) @ fp[A]<- r0
8277 GOTO_OPCODE(ip) @ jump to next instruction
8278
8279
8280/* continuation for OP_IGET_BYTE */
8281
8282 /*
8283 * Currently:
8284 * r0 holds resolved field
8285 * r9 holds object
8286 */
8287.LOP_IGET_BYTE_finish:
8288 @bl common_squeak2
8289 cmp r9, #0 @ check object for null
8290 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8291 beq common_errNullObject @ object was null
8292 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits)
8293 mov r2, rINST, lsr #8 @ r2<- A+
8294 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8295 and r2, r2, #15 @ r2<- A
8296 GET_INST_OPCODE(ip) @ extract opcode from rINST
8297 SET_VREG(r0, r2) @ fp[A]<- r0
8298 GOTO_OPCODE(ip) @ jump to next instruction
8299
8300
8301/* continuation for OP_IGET_CHAR */
8302
8303 /*
8304 * Currently:
8305 * r0 holds resolved field
8306 * r9 holds object
8307 */
8308.LOP_IGET_CHAR_finish:
8309 @bl common_squeak3
8310 cmp r9, #0 @ check object for null
8311 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8312 beq common_errNullObject @ object was null
8313 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits)
8314 mov r2, rINST, lsr #8 @ r2<- A+
8315 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8316 and r2, r2, #15 @ r2<- A
8317 GET_INST_OPCODE(ip) @ extract opcode from rINST
8318 SET_VREG(r0, r2) @ fp[A]<- r0
8319 GOTO_OPCODE(ip) @ jump to next instruction
8320
8321
8322/* continuation for OP_IGET_SHORT */
8323
8324 /*
8325 * Currently:
8326 * r0 holds resolved field
8327 * r9 holds object
8328 */
8329.LOP_IGET_SHORT_finish:
8330 @bl common_squeak4
8331 cmp r9, #0 @ check object for null
8332 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8333 beq common_errNullObject @ object was null
8334 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits)
8335 mov r2, rINST, lsr #8 @ r2<- A+
8336 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8337 and r2, r2, #15 @ r2<- A
8338 GET_INST_OPCODE(ip) @ extract opcode from rINST
8339 SET_VREG(r0, r2) @ fp[A]<- r0
8340 GOTO_OPCODE(ip) @ jump to next instruction
8341
8342
8343/* continuation for OP_IPUT */
8344
8345 /*
8346 * Currently:
8347 * r0 holds resolved field
8348 * r9 holds object
8349 */
8350.LOP_IPUT_finish:
8351 @bl common_squeak0
8352 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8353 ubfx r1, rINST, #8, #4 @ r1<- A
8354 cmp r9, #0 @ check object for null
8355 GET_VREG(r0, r1) @ r0<- fp[A]
8356 beq common_errNullObject @ object was null
8357 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8358 GET_INST_OPCODE(ip) @ extract opcode from rINST
8359 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0
8360 GOTO_OPCODE(ip) @ jump to next instruction
8361
8362
8363/* continuation for OP_IPUT_WIDE */
8364
8365 /*
8366 * Currently:
8367 * r0 holds resolved field
8368 * r9 holds object
8369 */
8370.LOP_IPUT_WIDE_finish:
8371 ubfx r2, rINST, #8, #4 @ r2<- A
8372 cmp r9, #0 @ check object for null
8373 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8374 add r2, rFP, r2, lsl #2 @ r3<- &fp[A]
8375 beq common_errNullObject @ object was null
8376 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8377 ldmia r2, {r0-r1} @ r0/r1<- fp[A]
8378 GET_INST_OPCODE(ip) @ extract opcode from rINST
8379 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0
8380 GOTO_OPCODE(ip) @ jump to next instruction
8381
8382
8383/* continuation for OP_IPUT_OBJECT */
8384
8385 /*
8386 * Currently:
8387 * r0 holds resolved field
8388 * r9 holds object
8389 */
8390.LOP_IPUT_OBJECT_finish:
8391 @bl common_squeak0
8392 mov r1, rINST, lsr #8 @ r1<- A+
8393 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8394 and r1, r1, #15 @ r1<- A
8395 cmp r9, #0 @ check object for null
8396 GET_VREG(r0, r1) @ r0<- fp[A]
8397 beq common_errNullObject @ object was null
8398 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8399 GET_INST_OPCODE(ip) @ extract opcode from rINST
8400 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0
8401 GOTO_OPCODE(ip) @ jump to next instruction
8402
8403
8404/* continuation for OP_IPUT_BOOLEAN */
8405
8406 /*
8407 * Currently:
8408 * r0 holds resolved field
8409 * r9 holds object
8410 */
8411.LOP_IPUT_BOOLEAN_finish:
8412 @bl common_squeak1
8413 mov r1, rINST, lsr #8 @ r1<- A+
8414 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8415 and r1, r1, #15 @ r1<- A
8416 cmp r9, #0 @ check object for null
8417 GET_VREG(r0, r1) @ r0<- fp[A]
8418 beq common_errNullObject @ object was null
8419 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8420 GET_INST_OPCODE(ip) @ extract opcode from rINST
8421 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0
8422 GOTO_OPCODE(ip) @ jump to next instruction
8423
8424
8425/* continuation for OP_IPUT_BYTE */
8426
8427 /*
8428 * Currently:
8429 * r0 holds resolved field
8430 * r9 holds object
8431 */
8432.LOP_IPUT_BYTE_finish:
8433 @bl common_squeak2
8434 mov r1, rINST, lsr #8 @ r1<- A+
8435 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8436 and r1, r1, #15 @ r1<- A
8437 cmp r9, #0 @ check object for null
8438 GET_VREG(r0, r1) @ r0<- fp[A]
8439 beq common_errNullObject @ object was null
8440 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8441 GET_INST_OPCODE(ip) @ extract opcode from rINST
8442 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0
8443 GOTO_OPCODE(ip) @ jump to next instruction
8444
8445
8446/* continuation for OP_IPUT_CHAR */
8447
8448 /*
8449 * Currently:
8450 * r0 holds resolved field
8451 * r9 holds object
8452 */
8453.LOP_IPUT_CHAR_finish:
8454 @bl common_squeak3
8455 mov r1, rINST, lsr #8 @ r1<- A+
8456 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8457 and r1, r1, #15 @ r1<- A
8458 cmp r9, #0 @ check object for null
8459 GET_VREG(r0, r1) @ r0<- fp[A]
8460 beq common_errNullObject @ object was null
8461 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8462 GET_INST_OPCODE(ip) @ extract opcode from rINST
8463 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0
8464 GOTO_OPCODE(ip) @ jump to next instruction
8465
8466
8467/* continuation for OP_IPUT_SHORT */
8468
8469 /*
8470 * Currently:
8471 * r0 holds resolved field
8472 * r9 holds object
8473 */
8474.LOP_IPUT_SHORT_finish:
8475 @bl common_squeak4
8476 mov r1, rINST, lsr #8 @ r1<- A+
8477 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
8478 and r1, r1, #15 @ r1<- A
8479 cmp r9, #0 @ check object for null
8480 GET_VREG(r0, r1) @ r0<- fp[A]
8481 beq common_errNullObject @ object was null
8482 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
8483 GET_INST_OPCODE(ip) @ extract opcode from rINST
8484 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0
8485 GOTO_OPCODE(ip) @ jump to next instruction
8486
8487
8488/* continuation for OP_SGET */
8489
8490 /*
8491 * Continuation if the field has not yet been resolved.
8492 * r1: BBBB field ref
8493 */
8494.LOP_SGET_resolve:
8495 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8496 EXPORT_PC() @ resolve() could throw, so export now
8497 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8498 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8499 cmp r0, #0 @ success?
8500 bne .LOP_SGET_finish @ yes, finish
8501 b common_exceptionThrown @ no, handle exception
8502
8503
8504/* continuation for OP_SGET_WIDE */
8505
8506 /*
8507 * Continuation if the field has not yet been resolved.
8508 * r1: BBBB field ref
Andy McFadden861b3382010-03-05 15:58:31 -08008509 *
8510 * Returns StaticField pointer in r0.
Andy McFaddena5069fb2009-06-19 15:20:12 -07008511 */
8512.LOP_SGET_WIDE_resolve:
8513 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8514 EXPORT_PC() @ resolve() could throw, so export now
8515 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8516 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8517 cmp r0, #0 @ success?
8518 bne .LOP_SGET_WIDE_finish @ yes, finish
8519 b common_exceptionThrown @ no, handle exception
8520
8521
8522/* continuation for OP_SGET_OBJECT */
8523
8524 /*
8525 * Continuation if the field has not yet been resolved.
8526 * r1: BBBB field ref
8527 */
8528.LOP_SGET_OBJECT_resolve:
8529 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8530 EXPORT_PC() @ resolve() could throw, so export now
8531 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8532 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8533 cmp r0, #0 @ success?
8534 bne .LOP_SGET_OBJECT_finish @ yes, finish
8535 b common_exceptionThrown @ no, handle exception
8536
8537
8538/* continuation for OP_SGET_BOOLEAN */
8539
8540 /*
8541 * Continuation if the field has not yet been resolved.
8542 * r1: BBBB field ref
8543 */
8544.LOP_SGET_BOOLEAN_resolve:
8545 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8546 EXPORT_PC() @ resolve() could throw, so export now
8547 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8548 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8549 cmp r0, #0 @ success?
8550 bne .LOP_SGET_BOOLEAN_finish @ yes, finish
8551 b common_exceptionThrown @ no, handle exception
8552
8553
8554/* continuation for OP_SGET_BYTE */
8555
8556 /*
8557 * Continuation if the field has not yet been resolved.
8558 * r1: BBBB field ref
8559 */
8560.LOP_SGET_BYTE_resolve:
8561 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8562 EXPORT_PC() @ resolve() could throw, so export now
8563 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8564 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8565 cmp r0, #0 @ success?
8566 bne .LOP_SGET_BYTE_finish @ yes, finish
8567 b common_exceptionThrown @ no, handle exception
8568
8569
8570/* continuation for OP_SGET_CHAR */
8571
8572 /*
8573 * Continuation if the field has not yet been resolved.
8574 * r1: BBBB field ref
8575 */
8576.LOP_SGET_CHAR_resolve:
8577 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8578 EXPORT_PC() @ resolve() could throw, so export now
8579 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8580 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8581 cmp r0, #0 @ success?
8582 bne .LOP_SGET_CHAR_finish @ yes, finish
8583 b common_exceptionThrown @ no, handle exception
8584
8585
8586/* continuation for OP_SGET_SHORT */
8587
8588 /*
8589 * Continuation if the field has not yet been resolved.
8590 * r1: BBBB field ref
8591 */
8592.LOP_SGET_SHORT_resolve:
8593 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8594 EXPORT_PC() @ resolve() could throw, so export now
8595 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8596 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8597 cmp r0, #0 @ success?
8598 bne .LOP_SGET_SHORT_finish @ yes, finish
8599 b common_exceptionThrown @ no, handle exception
8600
8601
8602/* continuation for OP_SPUT */
8603
8604 /*
8605 * Continuation if the field has not yet been resolved.
8606 * r1: BBBB field ref
8607 */
8608.LOP_SPUT_resolve:
8609 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8610 EXPORT_PC() @ resolve() could throw, so export now
8611 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8612 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8613 cmp r0, #0 @ success?
8614 bne .LOP_SPUT_finish @ yes, finish
8615 b common_exceptionThrown @ no, handle exception
8616
8617
8618/* continuation for OP_SPUT_WIDE */
8619
8620 /*
8621 * Continuation if the field has not yet been resolved.
8622 * r1: BBBB field ref
8623 * r9: &fp[AA]
Andy McFadden861b3382010-03-05 15:58:31 -08008624 *
8625 * Returns StaticField pointer in r2.
Andy McFaddena5069fb2009-06-19 15:20:12 -07008626 */
8627.LOP_SPUT_WIDE_resolve:
8628 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8629 EXPORT_PC() @ resolve() could throw, so export now
8630 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8631 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8632 cmp r0, #0 @ success?
Andy McFadden861b3382010-03-05 15:58:31 -08008633 mov r2, r0 @ copy to r2
Andy McFaddena5069fb2009-06-19 15:20:12 -07008634 bne .LOP_SPUT_WIDE_finish @ yes, finish
8635 b common_exceptionThrown @ no, handle exception
8636
8637
8638/* continuation for OP_SPUT_OBJECT */
8639
8640 /*
8641 * Continuation if the field has not yet been resolved.
8642 * r1: BBBB field ref
8643 */
8644.LOP_SPUT_OBJECT_resolve:
8645 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8646 EXPORT_PC() @ resolve() could throw, so export now
8647 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8648 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8649 cmp r0, #0 @ success?
8650 bne .LOP_SPUT_OBJECT_finish @ yes, finish
8651 b common_exceptionThrown @ no, handle exception
8652
8653
8654/* continuation for OP_SPUT_BOOLEAN */
8655
8656 /*
8657 * Continuation if the field has not yet been resolved.
8658 * r1: BBBB field ref
8659 */
8660.LOP_SPUT_BOOLEAN_resolve:
8661 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8662 EXPORT_PC() @ resolve() could throw, so export now
8663 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8664 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8665 cmp r0, #0 @ success?
8666 bne .LOP_SPUT_BOOLEAN_finish @ yes, finish
8667 b common_exceptionThrown @ no, handle exception
8668
8669
8670/* continuation for OP_SPUT_BYTE */
8671
8672 /*
8673 * Continuation if the field has not yet been resolved.
8674 * r1: BBBB field ref
8675 */
8676.LOP_SPUT_BYTE_resolve:
8677 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8678 EXPORT_PC() @ resolve() could throw, so export now
8679 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8680 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8681 cmp r0, #0 @ success?
8682 bne .LOP_SPUT_BYTE_finish @ yes, finish
8683 b common_exceptionThrown @ no, handle exception
8684
8685
8686/* continuation for OP_SPUT_CHAR */
8687
8688 /*
8689 * Continuation if the field has not yet been resolved.
8690 * r1: BBBB field ref
8691 */
8692.LOP_SPUT_CHAR_resolve:
8693 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8694 EXPORT_PC() @ resolve() could throw, so export now
8695 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8696 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8697 cmp r0, #0 @ success?
8698 bne .LOP_SPUT_CHAR_finish @ yes, finish
8699 b common_exceptionThrown @ no, handle exception
8700
8701
8702/* continuation for OP_SPUT_SHORT */
8703
8704 /*
8705 * Continuation if the field has not yet been resolved.
8706 * r1: BBBB field ref
8707 */
8708.LOP_SPUT_SHORT_resolve:
8709 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
8710 EXPORT_PC() @ resolve() could throw, so export now
8711 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
8712 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
8713 cmp r0, #0 @ success?
8714 bne .LOP_SPUT_SHORT_finish @ yes, finish
8715 b common_exceptionThrown @ no, handle exception
8716
8717
8718/* continuation for OP_INVOKE_VIRTUAL */
8719
8720 /*
8721 * At this point:
8722 * r0 = resolved base method
8723 * r10 = C or CCCC (index of first arg, which is the "this" ptr)
8724 */
8725.LOP_INVOKE_VIRTUAL_continue:
8726 GET_VREG(r1, r10) @ r1<- "this" ptr
8727 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex
8728 cmp r1, #0 @ is "this" null?
8729 beq common_errNullObject @ null "this", throw exception
8730 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz
8731 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable
8732 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex]
8733 bl common_invokeMethodNoRange @ continue on
8734
8735
8736/* continuation for OP_INVOKE_SUPER */
8737
8738 /*
8739 * At this point:
8740 * r0 = resolved base method
8741 * r9 = method->clazz
8742 */
8743.LOP_INVOKE_SUPER_continue:
8744 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super
8745 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex
8746 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount
8747 EXPORT_PC() @ must export for invoke
8748 cmp r2, r3 @ compare (methodIndex, vtableCount)
8749 bcs .LOP_INVOKE_SUPER_nsm @ method not present in superclass
8750 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable
8751 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex]
8752 bl common_invokeMethodNoRange @ continue on
8753
8754.LOP_INVOKE_SUPER_resolve:
8755 mov r0, r9 @ r0<- method->clazz
8756 mov r2, #METHOD_VIRTUAL @ resolver method type
8757 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
8758 cmp r0, #0 @ got null?
8759 bne .LOP_INVOKE_SUPER_continue @ no, continue
8760 b common_exceptionThrown @ yes, handle exception
8761
8762 /*
8763 * Throw a NoSuchMethodError with the method name as the message.
8764 * r0 = resolved base method
8765 */
8766.LOP_INVOKE_SUPER_nsm:
8767 ldr r1, [r0, #offMethod_name] @ r1<- method name
8768 b common_errNoSuchMethod
8769
8770
8771/* continuation for OP_INVOKE_DIRECT */
8772
8773 /*
8774 * On entry:
8775 * r1 = reference (BBBB or CCCC)
8776 * r10 = "this" register
8777 */
8778.LOP_INVOKE_DIRECT_resolve:
8779 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8780 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
8781 mov r2, #METHOD_DIRECT @ resolver method type
8782 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
8783 cmp r0, #0 @ got null?
8784 GET_VREG(r2, r10) @ r2<- "this" ptr (reload)
8785 bne .LOP_INVOKE_DIRECT_finish @ no, continue
8786 b common_exceptionThrown @ yes, handle exception
8787
8788
8789/* continuation for OP_INVOKE_VIRTUAL_RANGE */
8790
8791 /*
8792 * At this point:
8793 * r0 = resolved base method
8794 * r10 = C or CCCC (index of first arg, which is the "this" ptr)
8795 */
8796.LOP_INVOKE_VIRTUAL_RANGE_continue:
8797 GET_VREG(r1, r10) @ r1<- "this" ptr
8798 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex
8799 cmp r1, #0 @ is "this" null?
8800 beq common_errNullObject @ null "this", throw exception
8801 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz
8802 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable
8803 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex]
8804 bl common_invokeMethodRange @ continue on
8805
8806
8807/* continuation for OP_INVOKE_SUPER_RANGE */
8808
8809 /*
8810 * At this point:
8811 * r0 = resolved base method
8812 * r9 = method->clazz
8813 */
8814.LOP_INVOKE_SUPER_RANGE_continue:
8815 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super
8816 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex
8817 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount
8818 EXPORT_PC() @ must export for invoke
8819 cmp r2, r3 @ compare (methodIndex, vtableCount)
8820 bcs .LOP_INVOKE_SUPER_RANGE_nsm @ method not present in superclass
8821 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable
8822 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex]
8823 bl common_invokeMethodRange @ continue on
8824
8825.LOP_INVOKE_SUPER_RANGE_resolve:
8826 mov r0, r9 @ r0<- method->clazz
8827 mov r2, #METHOD_VIRTUAL @ resolver method type
8828 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
8829 cmp r0, #0 @ got null?
8830 bne .LOP_INVOKE_SUPER_RANGE_continue @ no, continue
8831 b common_exceptionThrown @ yes, handle exception
8832
8833 /*
8834 * Throw a NoSuchMethodError with the method name as the message.
8835 * r0 = resolved base method
8836 */
8837.LOP_INVOKE_SUPER_RANGE_nsm:
8838 ldr r1, [r0, #offMethod_name] @ r1<- method name
8839 b common_errNoSuchMethod
8840
8841
8842/* continuation for OP_INVOKE_DIRECT_RANGE */
8843
8844 /*
8845 * On entry:
8846 * r1 = reference (BBBB or CCCC)
8847 * r10 = "this" register
8848 */
8849.LOP_INVOKE_DIRECT_RANGE_resolve:
8850 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8851 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz
8852 mov r2, #METHOD_DIRECT @ resolver method type
8853 bl dvmResolveMethod @ r0<- call(clazz, ref, flags)
8854 cmp r0, #0 @ got null?
8855 GET_VREG(r2, r10) @ r2<- "this" ptr (reload)
8856 bne .LOP_INVOKE_DIRECT_RANGE_finish @ no, continue
8857 b common_exceptionThrown @ yes, handle exception
8858
8859
8860/* continuation for OP_FLOAT_TO_LONG */
8861/*
8862 * Convert the float in r0 to a long in r0/r1.
8863 *
8864 * We have to clip values to long min/max per the specification. The
8865 * expected common case is a "reasonable" value that converts directly
8866 * to modest integer. The EABI convert function isn't doing this for us.
8867 */
8868f2l_doconv:
8869 stmfd sp!, {r4, lr}
8870 mov r1, #0x5f000000 @ (float)maxlong
8871 mov r4, r0
8872 bl __aeabi_fcmpge @ is arg >= maxlong?
8873 cmp r0, #0 @ nonzero == yes
8874 mvnne r0, #0 @ return maxlong (7fffffff)
8875 mvnne r1, #0x80000000
8876 ldmnefd sp!, {r4, pc}
8877
8878 mov r0, r4 @ recover arg
8879 mov r1, #0xdf000000 @ (float)minlong
8880 bl __aeabi_fcmple @ is arg <= minlong?
8881 cmp r0, #0 @ nonzero == yes
8882 movne r0, #0 @ return minlong (80000000)
8883 movne r1, #0x80000000
8884 ldmnefd sp!, {r4, pc}
8885
8886 mov r0, r4 @ recover arg
8887 mov r1, r4
8888 bl __aeabi_fcmpeq @ is arg == self?
8889 cmp r0, #0 @ zero == no
8890 moveq r1, #0 @ return zero for NaN
8891 ldmeqfd sp!, {r4, pc}
8892
8893 mov r0, r4 @ recover arg
8894 bl __aeabi_f2lz @ convert float to long
8895 ldmfd sp!, {r4, pc}
8896
8897
8898/* continuation for OP_DOUBLE_TO_LONG */
8899/*
8900 * Convert the double in r0/r1 to a long in r0/r1.
8901 *
8902 * We have to clip values to long min/max per the specification. The
8903 * expected common case is a "reasonable" value that converts directly
8904 * to modest integer. The EABI convert function isn't doing this for us.
8905 */
8906d2l_doconv:
8907 stmfd sp!, {r4, r5, lr} @ save regs
Andy McFadden5162c5f2009-06-19 16:52:19 -07008908 mov r3, #0x43000000 @ maxlong, as a double (high word)
8909 add r3, #0x00e00000 @ 0x43e00000
8910 mov r2, #0 @ maxlong, as a double (low word)
Andy McFaddena5069fb2009-06-19 15:20:12 -07008911 sub sp, sp, #4 @ align for EABI
Andy McFadden5162c5f2009-06-19 16:52:19 -07008912 mov r4, r0 @ save a copy of r0
Andy McFaddena5069fb2009-06-19 15:20:12 -07008913 mov r5, r1 @ and r1
8914 bl __aeabi_dcmpge @ is arg >= maxlong?
8915 cmp r0, #0 @ nonzero == yes
8916 mvnne r0, #0 @ return maxlong (7fffffffffffffff)
8917 mvnne r1, #0x80000000
8918 bne 1f
8919
8920 mov r0, r4 @ recover arg
8921 mov r1, r5
Andy McFadden5162c5f2009-06-19 16:52:19 -07008922 mov r3, #0xc3000000 @ minlong, as a double (high word)
8923 add r3, #0x00e00000 @ 0xc3e00000
8924 mov r2, #0 @ minlong, as a double (low word)
Andy McFaddena5069fb2009-06-19 15:20:12 -07008925 bl __aeabi_dcmple @ is arg <= minlong?
8926 cmp r0, #0 @ nonzero == yes
8927 movne r0, #0 @ return minlong (8000000000000000)
8928 movne r1, #0x80000000
8929 bne 1f
8930
8931 mov r0, r4 @ recover arg
8932 mov r1, r5
8933 mov r2, r4 @ compare against self
8934 mov r3, r5
8935 bl __aeabi_dcmpeq @ is arg == self?
8936 cmp r0, #0 @ zero == no
8937 moveq r1, #0 @ return zero for NaN
8938 beq 1f
8939
8940 mov r0, r4 @ recover arg
8941 mov r1, r5
8942 bl __aeabi_d2lz @ convert double to long
8943
89441:
8945 add sp, sp, #4
8946 ldmfd sp!, {r4, r5, pc}
8947
Andy McFaddena5069fb2009-06-19 15:20:12 -07008948
8949/* continuation for OP_MUL_LONG */
8950
8951.LOP_MUL_LONG_finish:
8952 GET_INST_OPCODE(ip) @ extract opcode from rINST
8953 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10
8954 GOTO_OPCODE(ip) @ jump to next instruction
8955
8956
8957/* continuation for OP_SHL_LONG */
8958
8959.LOP_SHL_LONG_finish:
8960 mov r0, r0, asl r2 @ r0<- r0 << r2
8961 GET_INST_OPCODE(ip) @ extract opcode from rINST
8962 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
8963 GOTO_OPCODE(ip) @ jump to next instruction
8964
8965
8966/* continuation for OP_SHR_LONG */
8967
8968.LOP_SHR_LONG_finish:
8969 mov r1, r1, asr r2 @ r1<- r1 >> r2
8970 GET_INST_OPCODE(ip) @ extract opcode from rINST
8971 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
8972 GOTO_OPCODE(ip) @ jump to next instruction
8973
8974
8975/* continuation for OP_USHR_LONG */
8976
8977.LOP_USHR_LONG_finish:
8978 mov r1, r1, lsr r2 @ r1<- r1 >>> r2
8979 GET_INST_OPCODE(ip) @ extract opcode from rINST
8980 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
8981 GOTO_OPCODE(ip) @ jump to next instruction
8982
8983
8984/* continuation for OP_SHL_LONG_2ADDR */
8985
8986.LOP_SHL_LONG_2ADDR_finish:
8987 GET_INST_OPCODE(ip) @ extract opcode from rINST
8988 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
8989 GOTO_OPCODE(ip) @ jump to next instruction
8990
8991
8992/* continuation for OP_SHR_LONG_2ADDR */
8993
8994.LOP_SHR_LONG_2ADDR_finish:
8995 GET_INST_OPCODE(ip) @ extract opcode from rINST
8996 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
8997 GOTO_OPCODE(ip) @ jump to next instruction
8998
8999
9000/* continuation for OP_USHR_LONG_2ADDR */
9001
9002.LOP_USHR_LONG_2ADDR_finish:
9003 GET_INST_OPCODE(ip) @ extract opcode from rINST
9004 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
9005 GOTO_OPCODE(ip) @ jump to next instruction
9006
9007
Andy McFadden53878242010-03-05 07:24:27 -08009008/* continuation for OP_IGET_WIDE_VOLATILE */
9009
9010 /*
9011 * Currently:
9012 * r0 holds resolved field
9013 * r9 holds object
9014 */
9015.LOP_IGET_WIDE_VOLATILE_finish:
9016 cmp r9, #0 @ check object for null
9017 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
9018 beq common_errNullObject @ object was null
Andy McFadden861b3382010-03-05 15:58:31 -08009019 .if 1
9020 add r0, r9, r3 @ r0<- address of field
9021 bl android_quasiatomic_read_64 @ r0/r1<- contents of field
9022 .else
Andy McFadden53878242010-03-05 07:24:27 -08009023 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok)
Andy McFadden861b3382010-03-05 15:58:31 -08009024 .endif
9025 mov r2, rINST, lsr #8 @ r2<- A+
Andy McFadden53878242010-03-05 07:24:27 -08009026 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
Andy McFadden861b3382010-03-05 15:58:31 -08009027 and r2, r2, #15 @ r2<- A
Andy McFadden53878242010-03-05 07:24:27 -08009028 add r3, rFP, r2, lsl #2 @ r3<- &fp[A]
9029 GET_INST_OPCODE(ip) @ extract opcode from rINST
9030 stmia r3, {r0-r1} @ fp[A]<- r0/r1
9031 GOTO_OPCODE(ip) @ jump to next instruction
9032
9033
9034/* continuation for OP_IPUT_WIDE_VOLATILE */
9035
9036 /*
9037 * Currently:
9038 * r0 holds resolved field
9039 * r9 holds object
9040 */
9041.LOP_IPUT_WIDE_VOLATILE_finish:
9042 mov r2, rINST, lsr #8 @ r2<- A+
9043 cmp r9, #0 @ check object for null
9044 and r2, r2, #15 @ r2<- A
9045 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
9046 add r2, rFP, r2, lsl #2 @ r3<- &fp[A]
9047 beq common_errNullObject @ object was null
9048 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
9049 ldmia r2, {r0-r1} @ r0/r1<- fp[A]
Andy McFadden861b3382010-03-05 15:58:31 -08009050 GET_INST_OPCODE(r10) @ extract opcode from rINST
9051 .if 1
9052 add r2, r9, r3 @ r2<- target address
9053 bl android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
9054 .else
9055 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0/r1
9056 .endif
9057 GOTO_OPCODE(r10) @ jump to next instruction
Andy McFadden53878242010-03-05 07:24:27 -08009058
9059
9060/* continuation for OP_SGET_WIDE_VOLATILE */
9061
9062 /*
9063 * Continuation if the field has not yet been resolved.
9064 * r1: BBBB field ref
Andy McFadden861b3382010-03-05 15:58:31 -08009065 *
9066 * Returns StaticField pointer in r0.
Andy McFadden53878242010-03-05 07:24:27 -08009067 */
9068.LOP_SGET_WIDE_VOLATILE_resolve:
9069 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
9070 EXPORT_PC() @ resolve() could throw, so export now
9071 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
9072 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
9073 cmp r0, #0 @ success?
9074 bne .LOP_SGET_WIDE_VOLATILE_finish @ yes, finish
9075 b common_exceptionThrown @ no, handle exception
9076
9077
9078/* continuation for OP_SPUT_WIDE_VOLATILE */
9079
9080 /*
9081 * Continuation if the field has not yet been resolved.
9082 * r1: BBBB field ref
9083 * r9: &fp[AA]
Andy McFadden861b3382010-03-05 15:58:31 -08009084 *
9085 * Returns StaticField pointer in r2.
Andy McFadden53878242010-03-05 07:24:27 -08009086 */
9087.LOP_SPUT_WIDE_VOLATILE_resolve:
9088 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
9089 EXPORT_PC() @ resolve() could throw, so export now
9090 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
9091 bl dvmResolveStaticField @ r0<- resolved StaticField ptr
9092 cmp r0, #0 @ success?
Andy McFadden861b3382010-03-05 15:58:31 -08009093 mov r2, r0 @ copy to r2
Andy McFadden53878242010-03-05 07:24:27 -08009094 bne .LOP_SPUT_WIDE_VOLATILE_finish @ yes, finish
9095 b common_exceptionThrown @ no, handle exception
9096
9097
Andy McFaddena5069fb2009-06-19 15:20:12 -07009098/* continuation for OP_EXECUTE_INLINE */
9099
9100 /*
9101 * Extract args, call function.
9102 * r0 = #of args (0-4)
9103 * r10 = call index
9104 * lr = return addr, above [DO NOT bl out of here w/o preserving LR]
9105 *
9106 * Other ideas:
9107 * - Use a jump table from the main piece to jump directly into the
9108 * AND/LDR pairs. Costs a data load, saves a branch.
9109 * - Have five separate pieces that do the loading, so we can work the
9110 * interleave a little better. Increases code size.
9111 */
9112.LOP_EXECUTE_INLINE_continue:
9113 rsb r0, r0, #4 @ r0<- 4-r0
9114 FETCH(r9, 2) @ r9<- FEDC
9115 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each
9116 bl common_abort @ (skipped due to ARM prefetch)
91174: and ip, r9, #0xf000 @ isolate F
9118 ldr r3, [rFP, ip, lsr #10] @ r3<- vF (shift right 12, left 2)
91193: and ip, r9, #0x0f00 @ isolate E
9120 ldr r2, [rFP, ip, lsr #6] @ r2<- vE
91212: and ip, r9, #0x00f0 @ isolate D
9122 ldr r1, [rFP, ip, lsr #2] @ r1<- vD
91231: and ip, r9, #0x000f @ isolate C
9124 ldr r0, [rFP, ip, lsl #2] @ r0<- vC
91250:
9126 ldr r9, .LOP_EXECUTE_INLINE_table @ table of InlineOperation
9127 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry
9128 @ (not reached)
9129
9130.LOP_EXECUTE_INLINE_table:
9131 .word gDvmInlineOpsTable
9132
9133
Andy McFaddenb0a05412009-11-19 10:23:41 -08009134/* continuation for OP_EXECUTE_INLINE_RANGE */
9135
9136 /*
9137 * Extract args, call function.
9138 * r0 = #of args (0-4)
9139 * r10 = call index
9140 * lr = return addr, above [DO NOT bl out of here w/o preserving LR]
9141 */
9142.LOP_EXECUTE_INLINE_RANGE_continue:
9143 rsb r0, r0, #4 @ r0<- 4-r0
9144 FETCH(r9, 2) @ r9<- CCCC
9145 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each
9146 bl common_abort @ (skipped due to ARM prefetch)
91474: add ip, r9, #3 @ base+3
9148 GET_VREG(r3, ip) @ r3<- vBase[3]
91493: add ip, r9, #2 @ base+2
9150 GET_VREG(r2, ip) @ r2<- vBase[2]
91512: add ip, r9, #1 @ base+1
9152 GET_VREG(r1, ip) @ r1<- vBase[1]
91531: add ip, r9, #0 @ (nop)
9154 GET_VREG(r0, ip) @ r0<- vBase[0]
91550:
9156 ldr r9, .LOP_EXECUTE_INLINE_RANGE_table @ table of InlineOperation
9157 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry
9158 @ (not reached)
9159
9160.LOP_EXECUTE_INLINE_RANGE_table:
9161 .word gDvmInlineOpsTable
9162
9163
Andy McFaddena5069fb2009-06-19 15:20:12 -07009164 .size dvmAsmSisterStart, .-dvmAsmSisterStart
9165 .global dvmAsmSisterEnd
9166dvmAsmSisterEnd:
9167
9168/* File: armv5te/footer.S */
9169
9170/*
9171 * ===========================================================================
9172 * Common subroutines and data
9173 * ===========================================================================
9174 */
9175
9176
9177
9178 .text
9179 .align 2
9180
9181#if defined(WITH_JIT)
Jeff Hao97319a82009-08-12 16:57:15 -07009182#if defined(WITH_SELF_VERIFICATION)
9183 .global dvmJitToInterpPunt
9184dvmJitToInterpPunt:
Ben Chengd5adae12010-03-26 17:45:28 -07009185 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
Jeff Hao97319a82009-08-12 16:57:15 -07009186 mov r2,#kSVSPunt @ r2<- interpreter entry point
Ben Chengd5adae12010-03-26 17:45:28 -07009187 mov r3, #0
9188 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9189 b jitSVShadowRunEnd @ doesn't return
Jeff Hao97319a82009-08-12 16:57:15 -07009190
9191 .global dvmJitToInterpSingleStep
9192dvmJitToInterpSingleStep:
Ben Chengd5adae12010-03-26 17:45:28 -07009193 str lr,[rGLUE,#offGlue_jitResumeNPC]
9194 str r1,[rGLUE,#offGlue_jitResumeDPC]
Jeff Hao97319a82009-08-12 16:57:15 -07009195 mov r2,#kSVSSingleStep @ r2<- interpreter entry point
Ben Chengd5adae12010-03-26 17:45:28 -07009196 b jitSVShadowRunEnd @ doesn't return
Jeff Hao97319a82009-08-12 16:57:15 -07009197
Ben Cheng40094c12010-02-24 20:58:44 -08009198 .global dvmJitToInterpTraceSelectNoChain
9199dvmJitToInterpTraceSelectNoChain:
Ben Chengd5adae12010-03-26 17:45:28 -07009200 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
Ben Cheng40094c12010-02-24 20:58:44 -08009201 mov r0,rPC @ pass our target PC
9202 mov r2,#kSVSTraceSelectNoChain @ r2<- interpreter entry point
Ben Chengd5adae12010-03-26 17:45:28 -07009203 mov r3, #0
9204 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9205 b jitSVShadowRunEnd @ doesn't return
Ben Cheng40094c12010-02-24 20:58:44 -08009206
9207 .global dvmJitToInterpTraceSelect
9208dvmJitToInterpTraceSelect:
Ben Chengd5adae12010-03-26 17:45:28 -07009209 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
Bill Buzbee9a8c75a2009-11-08 14:31:20 -08009210 ldr r0,[lr, #-1] @ pass our target PC
Jeff Hao97319a82009-08-12 16:57:15 -07009211 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point
Ben Chengd5adae12010-03-26 17:45:28 -07009212 mov r3, #0
9213 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9214 b jitSVShadowRunEnd @ doesn't return
Jeff Hao97319a82009-08-12 16:57:15 -07009215
Ben Cheng40094c12010-02-24 20:58:44 -08009216 .global dvmJitToInterpBackwardBranch
9217dvmJitToInterpBackwardBranch:
Ben Chengd5adae12010-03-26 17:45:28 -07009218 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
Bill Buzbee9a8c75a2009-11-08 14:31:20 -08009219 ldr r0,[lr, #-1] @ pass our target PC
Jeff Hao97319a82009-08-12 16:57:15 -07009220 mov r2,#kSVSBackwardBranch @ r2<- interpreter entry point
Ben Chengd5adae12010-03-26 17:45:28 -07009221 mov r3, #0
9222 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9223 b jitSVShadowRunEnd @ doesn't return
Jeff Hao97319a82009-08-12 16:57:15 -07009224
9225 .global dvmJitToInterpNormal
9226dvmJitToInterpNormal:
Ben Chengd5adae12010-03-26 17:45:28 -07009227 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
Bill Buzbee9a8c75a2009-11-08 14:31:20 -08009228 ldr r0,[lr, #-1] @ pass our target PC
Jeff Hao97319a82009-08-12 16:57:15 -07009229 mov r2,#kSVSNormal @ r2<- interpreter entry point
Ben Chengd5adae12010-03-26 17:45:28 -07009230 mov r3, #0
9231 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9232 b jitSVShadowRunEnd @ doesn't return
Jeff Hao97319a82009-08-12 16:57:15 -07009233
9234 .global dvmJitToInterpNoChain
9235dvmJitToInterpNoChain:
Ben Chengd5adae12010-03-26 17:45:28 -07009236 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
Jeff Hao97319a82009-08-12 16:57:15 -07009237 mov r0,rPC @ pass our target PC
9238 mov r2,#kSVSNoChain @ r2<- interpreter entry point
Ben Chengd5adae12010-03-26 17:45:28 -07009239 mov r3, #0
9240 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9241 b jitSVShadowRunEnd @ doesn't return
Jeff Hao97319a82009-08-12 16:57:15 -07009242#else
Andy McFaddena5069fb2009-06-19 15:20:12 -07009243/*
9244 * Return from the translation cache to the interpreter when the compiler is
9245 * having issues translating/executing a Dalvik instruction. We have to skip
9246 * the code cache lookup otherwise it is possible to indefinitely bouce
9247 * between the interpreter and the code cache if the instruction that fails
9248 * to be compiled happens to be at a trace start.
9249 */
9250 .global dvmJitToInterpPunt
9251dvmJitToInterpPunt:
Ben Cheng7a0bcd02010-01-22 16:45:45 -08009252 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
Andy McFaddena5069fb2009-06-19 15:20:12 -07009253 mov rPC, r0
Ben Cheng86717f72010-03-05 15:27:21 -08009254#ifdef JIT_STATS
Andy McFaddena5069fb2009-06-19 15:20:12 -07009255 mov r0,lr
9256 bl dvmBumpPunt;
9257#endif
9258 EXPORT_PC()
Ben Cheng7a0bcd02010-01-22 16:45:45 -08009259 mov r0, #0
9260 str r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land
Andy McFaddena5069fb2009-06-19 15:20:12 -07009261 adrl rIBASE, dvmAsmInstructionStart
9262 FETCH_INST()
9263 GET_INST_OPCODE(ip)
9264 GOTO_OPCODE(ip)
9265
9266/*
9267 * Return to the interpreter to handle a single instruction.
9268 * On entry:
9269 * r0 <= PC
9270 * r1 <= PC of resume instruction
9271 * lr <= resume point in translation
9272 */
9273 .global dvmJitToInterpSingleStep
9274dvmJitToInterpSingleStep:
Ben Chengd5adae12010-03-26 17:45:28 -07009275 str lr,[rGLUE,#offGlue_jitResumeNPC]
9276 str r1,[rGLUE,#offGlue_jitResumeDPC]
Andy McFaddena5069fb2009-06-19 15:20:12 -07009277 mov r1,#kInterpEntryInstr
9278 @ enum is 4 byte in aapcs-EABI
9279 str r1, [rGLUE, #offGlue_entryPoint]
9280 mov rPC,r0
9281 EXPORT_PC()
Ben Cheng7a0bcd02010-01-22 16:45:45 -08009282
Andy McFaddena5069fb2009-06-19 15:20:12 -07009283 adrl rIBASE, dvmAsmInstructionStart
9284 mov r2,#kJitSingleStep @ Ask for single step and then revert
9285 str r2,[rGLUE,#offGlue_jitState]
9286 mov r1,#1 @ set changeInterp to bail to debug interp
9287 b common_gotoBail
9288
Ben Cheng40094c12010-02-24 20:58:44 -08009289/*
9290 * Return from the translation cache and immediately request
9291 * a translation for the exit target. Commonly used for callees.
9292 */
9293 .global dvmJitToInterpTraceSelectNoChain
9294dvmJitToInterpTraceSelectNoChain:
Ben Cheng86717f72010-03-05 15:27:21 -08009295#ifdef JIT_STATS
Ben Cheng40094c12010-02-24 20:58:44 -08009296 bl dvmBumpNoChain
9297#endif
9298 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
9299 mov r0,rPC
9300 bl dvmJitGetCodeAddr @ Is there a translation?
9301 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9302 mov r1, rPC @ arg1 of translation may need this
9303 mov lr, #0 @ in case target is HANDLER_INTERPRET
9304 cmp r0,#0
9305 bxne r0 @ continue native execution if so
9306 b 2f
Andy McFaddena5069fb2009-06-19 15:20:12 -07009307
9308/*
9309 * Return from the translation cache and immediately request
9310 * a translation for the exit target. Commonly used following
9311 * invokes.
9312 */
Ben Cheng40094c12010-02-24 20:58:44 -08009313 .global dvmJitToInterpTraceSelect
9314dvmJitToInterpTraceSelect:
Bill Buzbee9a8c75a2009-11-08 14:31:20 -08009315 ldr rPC,[lr, #-1] @ get our target PC
Ben Cheng7a0bcd02010-01-22 16:45:45 -08009316 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
Bill Buzbee9a8c75a2009-11-08 14:31:20 -08009317 add rINST,lr,#-5 @ save start of chain branch
Andy McFaddena5069fb2009-06-19 15:20:12 -07009318 mov r0,rPC
Ben Cheng7a0bcd02010-01-22 16:45:45 -08009319 bl dvmJitGetCodeAddr @ Is there a translation?
9320 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
Andy McFaddena5069fb2009-06-19 15:20:12 -07009321 cmp r0,#0
9322 beq 2f
9323 mov r1,rINST
9324 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr)
Bill Buzbee9a8c75a2009-11-08 14:31:20 -08009325 mov r1, rPC @ arg1 of translation may need this
9326 mov lr, #0 @ in case target is HANDLER_INTERPRET
Andy McFaddena5069fb2009-06-19 15:20:12 -07009327 cmp r0,#0 @ successful chain?
9328 bxne r0 @ continue native execution
9329 b toInterpreter @ didn't chain - resume with interpreter
9330
9331/* No translation, so request one if profiling isn't disabled*/
93322:
9333 adrl rIBASE, dvmAsmInstructionStart
9334 GET_JIT_PROF_TABLE(r0)
9335 FETCH_INST()
9336 cmp r0, #0
Ben Cheng40094c12010-02-24 20:58:44 -08009337 movne r2,#kJitTSelectRequestHot @ ask for trace selection
Andy McFaddena5069fb2009-06-19 15:20:12 -07009338 bne common_selectTrace
9339 GET_INST_OPCODE(ip)
9340 GOTO_OPCODE(ip)
9341
9342/*
9343 * Return from the translation cache to the interpreter.
9344 * The return was done with a BLX from thumb mode, and
9345 * the following 32-bit word contains the target rPC value.
9346 * Note that lr (r14) will have its low-order bit set to denote
9347 * its thumb-mode origin.
9348 *
9349 * We'll need to stash our lr origin away, recover the new
9350 * target and then check to see if there is a translation available
9351 * for our new target. If so, we do a translation chain and
9352 * go back to native execution. Otherwise, it's back to the
9353 * interpreter (after treating this entry as a potential
9354 * trace start).
9355 */
9356 .global dvmJitToInterpNormal
9357dvmJitToInterpNormal:
Bill Buzbee9a8c75a2009-11-08 14:31:20 -08009358 ldr rPC,[lr, #-1] @ get our target PC
Ben Cheng7a0bcd02010-01-22 16:45:45 -08009359 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
Bill Buzbee9a8c75a2009-11-08 14:31:20 -08009360 add rINST,lr,#-5 @ save start of chain branch
Ben Cheng86717f72010-03-05 15:27:21 -08009361#ifdef JIT_STATS
Andy McFaddena5069fb2009-06-19 15:20:12 -07009362 bl dvmBumpNormal
9363#endif
9364 mov r0,rPC
9365 bl dvmJitGetCodeAddr @ Is there a translation?
Ben Cheng7a0bcd02010-01-22 16:45:45 -08009366 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
Andy McFaddena5069fb2009-06-19 15:20:12 -07009367 cmp r0,#0
9368 beq toInterpreter @ go if not, otherwise do chain
9369 mov r1,rINST
9370 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr)
Bill Buzbee9a8c75a2009-11-08 14:31:20 -08009371 mov r1, rPC @ arg1 of translation may need this
9372 mov lr, #0 @ in case target is HANDLER_INTERPRET
Andy McFaddena5069fb2009-06-19 15:20:12 -07009373 cmp r0,#0 @ successful chain?
9374 bxne r0 @ continue native execution
9375 b toInterpreter @ didn't chain - resume with interpreter
9376
9377/*
9378 * Return from the translation cache to the interpreter to do method invocation.
9379 * Check if translation exists for the callee, but don't chain to it.
9380 */
9381 .global dvmJitToInterpNoChain
9382dvmJitToInterpNoChain:
Ben Cheng86717f72010-03-05 15:27:21 -08009383#ifdef JIT_STATS
Andy McFaddena5069fb2009-06-19 15:20:12 -07009384 bl dvmBumpNoChain
9385#endif
Ben Cheng7a0bcd02010-01-22 16:45:45 -08009386 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
Andy McFaddena5069fb2009-06-19 15:20:12 -07009387 mov r0,rPC
9388 bl dvmJitGetCodeAddr @ Is there a translation?
Ben Cheng7a0bcd02010-01-22 16:45:45 -08009389 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
Bill Buzbee9a8c75a2009-11-08 14:31:20 -08009390 mov r1, rPC @ arg1 of translation may need this
9391 mov lr, #0 @ in case target is HANDLER_INTERPRET
Andy McFaddena5069fb2009-06-19 15:20:12 -07009392 cmp r0,#0
9393 bxne r0 @ continue native execution if so
Jeff Hao97319a82009-08-12 16:57:15 -07009394#endif
Andy McFaddena5069fb2009-06-19 15:20:12 -07009395
9396/*
9397 * No translation, restore interpreter regs and start interpreting.
9398 * rGLUE & rFP were preserved in the translated code, and rPC has
9399 * already been restored by the time we get here. We'll need to set
9400 * up rIBASE & rINST, and load the address of the JitTable into r0.
9401 */
9402toInterpreter:
9403 EXPORT_PC()
9404 adrl rIBASE, dvmAsmInstructionStart
9405 FETCH_INST()
9406 GET_JIT_PROF_TABLE(r0)
9407 @ NOTE: intended fallthrough
9408/*
9409 * Common code to update potential trace start counter, and initiate
9410 * a trace-build if appropriate. On entry, rPC should point to the
9411 * next instruction to execute, and rINST should be already loaded with
9412 * the next opcode word, and r0 holds a pointer to the jit profile
9413 * table (pJitProfTable).
9414 */
9415common_testUpdateProfile:
9416 cmp r0,#0
9417 GET_INST_OPCODE(ip)
9418 GOTO_OPCODE_IFEQ(ip) @ if not profiling, fallthrough otherwise */
9419
9420common_updateProfile:
9421 eor r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
Ben Cheng7b133ef2010-02-04 16:15:59 -08009422 lsl r3,r3,#(32 - JIT_PROF_SIZE_LOG_2) @ shift out excess bits
9423 ldrb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter
Andy McFaddena5069fb2009-06-19 15:20:12 -07009424 GET_INST_OPCODE(ip)
9425 subs r1,r1,#1 @ decrement counter
Ben Cheng7b133ef2010-02-04 16:15:59 -08009426 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it
Andy McFaddena5069fb2009-06-19 15:20:12 -07009427 GOTO_OPCODE_IFNE(ip) @ if not threshold, fallthrough otherwise */
9428
9429/*
9430 * Here, we switch to the debug interpreter to request
9431 * trace selection. First, though, check to see if there
9432 * is already a native translation in place (and, if so,
9433 * jump to it now).
9434 */
Bill Buzbeed7269912009-11-10 14:31:32 -08009435 GET_JIT_THRESHOLD(r1)
Ben Cheng7a0bcd02010-01-22 16:45:45 -08009436 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
Ben Cheng7b133ef2010-02-04 16:15:59 -08009437 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter
Andy McFaddena5069fb2009-06-19 15:20:12 -07009438 EXPORT_PC()
9439 mov r0,rPC
9440 bl dvmJitGetCodeAddr @ r0<- dvmJitGetCodeAddr(rPC)
Ben Cheng7a0bcd02010-01-22 16:45:45 -08009441 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9442 mov r1, rPC @ arg1 of translation may need this
9443 mov lr, #0 @ in case target is HANDLER_INTERPRET
Andy McFaddena5069fb2009-06-19 15:20:12 -07009444 cmp r0,#0
Jeff Hao97319a82009-08-12 16:57:15 -07009445#if !defined(WITH_SELF_VERIFICATION)
Andy McFaddena5069fb2009-06-19 15:20:12 -07009446 bxne r0 @ jump to the translation
Ben Cheng40094c12010-02-24 20:58:44 -08009447 mov r2,#kJitTSelectRequest @ ask for trace selection
9448 @ fall-through to common_selectTrace
Jeff Hao97319a82009-08-12 16:57:15 -07009449#else
Ben Cheng40094c12010-02-24 20:58:44 -08009450 moveq r2,#kJitTSelectRequest @ ask for trace selection
Bill Buzbee9a8c75a2009-11-08 14:31:20 -08009451 beq common_selectTrace
9452 /*
9453 * At this point, we have a target translation. However, if
9454 * that translation is actually the interpret-only pseudo-translation
9455 * we want to treat it the same as no translation.
9456 */
Ben Chengd5adae12010-03-26 17:45:28 -07009457 mov r10, r0 @ save target
Bill Buzbee9a8c75a2009-11-08 14:31:20 -08009458 bl dvmCompilerGetInterpretTemplate
Ben Chengd5adae12010-03-26 17:45:28 -07009459 cmp r0, r10 @ special case?
9460 bne jitSVShadowRunStart @ set up self verification shadow space
Bill Buzbee9a8c75a2009-11-08 14:31:20 -08009461 GET_INST_OPCODE(ip)
9462 GOTO_OPCODE(ip)
9463 /* no return */
Jeff Hao97319a82009-08-12 16:57:15 -07009464#endif
Bill Buzbee9a8c75a2009-11-08 14:31:20 -08009465
Ben Cheng40094c12010-02-24 20:58:44 -08009466/*
9467 * On entry:
9468 * r2 is jit state, e.g. kJitTSelectRequest or kJitTSelectRequestHot
9469 */
Andy McFaddena5069fb2009-06-19 15:20:12 -07009470common_selectTrace:
Andy McFaddena5069fb2009-06-19 15:20:12 -07009471 str r2,[rGLUE,#offGlue_jitState]
Ben Cheng9c147b82009-10-07 16:41:46 -07009472 mov r2,#kInterpEntryInstr @ normal entry reason
9473 str r2,[rGLUE,#offGlue_entryPoint]
Andy McFaddena5069fb2009-06-19 15:20:12 -07009474 mov r1,#1 @ set changeInterp
9475 b common_gotoBail
9476
Jeff Hao97319a82009-08-12 16:57:15 -07009477#if defined(WITH_SELF_VERIFICATION)
9478/*
9479 * Save PC and registers to shadow memory for self verification mode
9480 * before jumping to native translation.
Ben Chengd5adae12010-03-26 17:45:28 -07009481 * On entry:
9482 * rPC, rFP, rGLUE: the values that they should contain
9483 * r10: the address of the target translation.
Jeff Hao97319a82009-08-12 16:57:15 -07009484 */
Ben Chengd5adae12010-03-26 17:45:28 -07009485jitSVShadowRunStart:
Jeff Hao97319a82009-08-12 16:57:15 -07009486 mov r0,rPC @ r0<- program counter
9487 mov r1,rFP @ r1<- frame pointer
9488 mov r2,rGLUE @ r2<- InterpState pointer
Bill Buzbee9a8c75a2009-11-08 14:31:20 -08009489 mov r3,r10 @ r3<- target translation
Jeff Hao97319a82009-08-12 16:57:15 -07009490 bl dvmSelfVerificationSaveState @ save registers to shadow space
Ben Chengccd6c012009-10-15 14:52:45 -07009491 ldr rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
9492 add rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
9493 bx r10 @ jump to the translation
Jeff Hao97319a82009-08-12 16:57:15 -07009494
9495/*
9496 * Restore PC, registers, and interpState to original values
9497 * before jumping back to the interpreter.
9498 */
Ben Chengd5adae12010-03-26 17:45:28 -07009499jitSVShadowRunEnd:
Jeff Hao97319a82009-08-12 16:57:15 -07009500 mov r1,rFP @ pass ending fp
9501 bl dvmSelfVerificationRestoreState @ restore pc and fp values
Ben Chengccd6c012009-10-15 14:52:45 -07009502 ldr rPC,[r0,#offShadowSpace_startPC] @ restore PC
9503 ldr rFP,[r0,#offShadowSpace_fp] @ restore FP
9504 ldr rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
9505 ldr r1,[r0,#offShadowSpace_svState] @ get self verification state
Jeff Hao97319a82009-08-12 16:57:15 -07009506 cmp r1,#0 @ check for punt condition
9507 beq 1f
9508 mov r2,#kJitSelfVerification @ ask for self verification
9509 str r2,[rGLUE,#offGlue_jitState]
Ben Cheng30f1f462009-10-12 13:46:55 -07009510 mov r2,#kInterpEntryInstr @ normal entry reason
9511 str r2,[rGLUE,#offGlue_entryPoint]
Jeff Hao97319a82009-08-12 16:57:15 -07009512 mov r1,#1 @ set changeInterp
9513 b common_gotoBail
9514
95151: @ exit to interpreter without check
9516 EXPORT_PC()
9517 adrl rIBASE, dvmAsmInstructionStart
9518 FETCH_INST()
9519 GET_INST_OPCODE(ip)
9520 GOTO_OPCODE(ip)
9521#endif
9522
Andy McFaddena5069fb2009-06-19 15:20:12 -07009523#endif
9524
9525/*
9526 * Common code when a backward branch is taken.
9527 *
9528 * On entry:
9529 * r9 is PC adjustment *in bytes*
9530 */
9531common_backwardBranch:
9532 mov r0, #kInterpEntryInstr
9533 bl common_periodicChecks
9534#if defined(WITH_JIT)
9535 GET_JIT_PROF_TABLE(r0)
9536 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
9537 cmp r0,#0
9538 bne common_updateProfile
9539 GET_INST_OPCODE(ip)
9540 GOTO_OPCODE(ip)
9541#else
9542 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST
9543 GET_INST_OPCODE(ip) @ extract opcode from rINST
9544 GOTO_OPCODE(ip) @ jump to next instruction
9545#endif
9546
9547
9548/*
9549 * Need to see if the thread needs to be suspended or debugger/profiler
9550 * activity has begun.
9551 *
9552 * TODO: if JDWP isn't running, zero out pDebuggerActive pointer so we don't
9553 * have to do the second ldr.
9554 *
9555 * TODO: reduce this so we're just checking a single location.
9556 *
9557 * On entry:
9558 * r0 is reentry type, e.g. kInterpEntryInstr
9559 * r9 is trampoline PC adjustment *in bytes*
9560 */
9561common_periodicChecks:
9562 ldr r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
9563
Ben Cheng9c147b82009-10-07 16:41:46 -07009564 @ speculatively store r0 before it is clobbered by dvmCheckSuspendPending
9565 str r0, [rGLUE, #offGlue_entryPoint]
9566
Andy McFaddena5069fb2009-06-19 15:20:12 -07009567#if defined(WITH_DEBUGGER)
9568 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive
9569#endif
9570#if defined(WITH_PROFILER)
9571 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers
9572#endif
9573
9574 ldr r3, [r3] @ r3<- suspendCount (int)
9575
9576#if defined(WITH_DEBUGGER)
9577 ldrb r1, [r1] @ r1<- debuggerActive (boolean)
9578#endif
9579#if defined (WITH_PROFILER)
9580 ldr r2, [r2] @ r2<- activeProfilers (int)
9581#endif
9582
9583 cmp r3, #0 @ suspend pending?
9584 bne 2f @ yes, do full suspension check
9585
9586#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
9587# if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
9588 orrs r1, r1, r2 @ r1<- r1 | r2
9589 cmp r1, #0 @ debugger attached or profiler started?
9590# elif defined(WITH_DEBUGGER)
9591 cmp r1, #0 @ debugger attached?
9592# elif defined(WITH_PROFILER)
9593 cmp r2, #0 @ profiler started?
9594# endif
9595 bne 3f @ debugger/profiler, switch interp
9596#endif
9597
9598 bx lr @ nothing to do, return
9599
96002: @ check suspend
Bill Buzbee964a7b02010-01-28 12:54:19 -08009601#if defined(WITH_JIT)
9602 /*
9603 * Refresh the Jit's cached copy of profile table pointer. This pointer
9604 * doubles as the Jit's on/off switch.
9605 */
Ben Chengd5adae12010-03-26 17:45:28 -07009606 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ r3<-&gDvmJit.pJitProfTable
Bill Buzbee964a7b02010-01-28 12:54:19 -08009607 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
Ben Chengd5adae12010-03-26 17:45:28 -07009608 ldr r3, [r3] @ r3 <- pJitProfTable
Bill Buzbee964a7b02010-01-28 12:54:19 -08009609 EXPORT_PC() @ need for precise GC
9610 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch
9611#else
Andy McFaddena5069fb2009-06-19 15:20:12 -07009612 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self
9613 EXPORT_PC() @ need for precise GC
Bill Buzbee964a7b02010-01-28 12:54:19 -08009614#endif
Andy McFaddena5069fb2009-06-19 15:20:12 -07009615 b dvmCheckSuspendPending @ suspend if necessary, then return
9616
96173: @ debugger/profiler enabled, bail out
9618 add rPC, rPC, r9 @ update rPC
Andy McFaddena5069fb2009-06-19 15:20:12 -07009619 mov r1, #1 @ "want switch" = true
9620 b common_gotoBail
9621
9622
9623/*
9624 * The equivalent of "goto bail", this calls through the "bail handler".
9625 *
9626 * State registers will be saved to the "glue" area before bailing.
9627 *
9628 * On entry:
9629 * r1 is "bool changeInterp", indicating if we want to switch to the
9630 * other interpreter or just bail all the way out
9631 */
9632common_gotoBail:
9633 SAVE_PC_FP_TO_GLUE() @ export state to "glue"
9634 mov r0, rGLUE @ r0<- glue ptr
9635 b dvmMterpStdBail @ call(glue, changeInterp)
9636
9637 @add r1, r1, #1 @ using (boolean+1)
9638 @add r0, rGLUE, #offGlue_jmpBuf @ r0<- &glue->jmpBuf
9639 @bl _longjmp @ does not return
9640 @bl common_abort
9641
9642
9643/*
9644 * Common code for method invocation with range.
9645 *
9646 * On entry:
9647 * r0 is "Method* methodToCall", the method we're trying to call
9648 */
9649common_invokeMethodRange:
9650.LinvokeNewRange:
9651 @ prepare to copy args to "outs" area of current frame
9652 movs r2, rINST, lsr #8 @ r2<- AA (arg count) -- test for zero
9653 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area
9654 beq .LinvokeArgsDone @ if no args, skip the rest
9655 FETCH(r1, 2) @ r1<- CCCC
9656
9657 @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
9658 @ (very few methods have > 10 args; could unroll for common cases)
9659 add r3, rFP, r1, lsl #2 @ r3<- &fp[CCCC]
9660 sub r10, r10, r2, lsl #2 @ r10<- "outs" area, for call args
9661 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize
96621: ldr r1, [r3], #4 @ val = *fp++
9663 subs r2, r2, #1 @ count--
9664 str r1, [r10], #4 @ *outs++ = val
9665 bne 1b @ ...while count != 0
9666 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize
9667 b .LinvokeArgsDone
9668
9669/*
9670 * Common code for method invocation without range.
9671 *
9672 * On entry:
9673 * r0 is "Method* methodToCall", the method we're trying to call
9674 */
9675common_invokeMethodNoRange:
9676.LinvokeNewNoRange:
9677 @ prepare to copy args to "outs" area of current frame
9678 movs r2, rINST, lsr #12 @ r2<- B (arg count) -- test for zero
9679 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area
9680 FETCH(r1, 2) @ r1<- GFED (load here to hide latency)
9681 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize
9682 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize
9683 beq .LinvokeArgsDone
9684
9685 @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
9686.LinvokeNonRange:
9687 rsb r2, r2, #5 @ r2<- 5-r2
9688 add pc, pc, r2, lsl #4 @ computed goto, 4 instrs each
9689 bl common_abort @ (skipped due to ARM prefetch)
96905: and ip, rINST, #0x0f00 @ isolate A
9691 ldr r2, [rFP, ip, lsr #6] @ r2<- vA (shift right 8, left 2)
9692 mov r0, r0 @ nop
9693 str r2, [r10, #-4]! @ *--outs = vA
96944: and ip, r1, #0xf000 @ isolate G
9695 ldr r2, [rFP, ip, lsr #10] @ r2<- vG (shift right 12, left 2)
9696 mov r0, r0 @ nop
9697 str r2, [r10, #-4]! @ *--outs = vG
96983: and ip, r1, #0x0f00 @ isolate F
9699 ldr r2, [rFP, ip, lsr #6] @ r2<- vF
9700 mov r0, r0 @ nop
9701 str r2, [r10, #-4]! @ *--outs = vF
97022: and ip, r1, #0x00f0 @ isolate E
9703 ldr r2, [rFP, ip, lsr #2] @ r2<- vE
9704 mov r0, r0 @ nop
9705 str r2, [r10, #-4]! @ *--outs = vE
97061: and ip, r1, #0x000f @ isolate D
9707 ldr r2, [rFP, ip, lsl #2] @ r2<- vD
9708 mov r0, r0 @ nop
9709 str r2, [r10, #-4]! @ *--outs = vD
97100: @ fall through to .LinvokeArgsDone
9711
9712.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
9713 ldr r2, [r0, #offMethod_insns] @ r2<- method->insns
9714 ldr rINST, [r0, #offMethod_clazz] @ rINST<- method->clazz
9715 @ find space for the new stack frame, check for overflow
9716 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area
9717 sub r1, r1, r9, lsl #2 @ r1<- newFp (old savearea - regsSize)
9718 SAVEAREA_FROM_FP(r10, r1) @ r10<- newSaveArea
9719@ bl common_dumpRegs
9720 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd
9721 sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize)
9722 cmp r3, r9 @ bottom < interpStackEnd?
9723 ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
Andy McFadden7a44e4e2010-04-28 15:46:16 -07009724 blo .LstackOverflow @ yes, this frame will overflow stack
Andy McFaddena5069fb2009-06-19 15:20:12 -07009725
9726 @ set up newSaveArea
9727#ifdef EASY_GDB
9728 SAVEAREA_FROM_FP(ip, rFP) @ ip<- stack save area
9729 str ip, [r10, #offStackSaveArea_prevSave]
9730#endif
9731 str rFP, [r10, #offStackSaveArea_prevFrame]
9732 str rPC, [r10, #offStackSaveArea_savedPc]
9733#if defined(WITH_JIT)
9734 mov r9, #0
9735 str r9, [r10, #offStackSaveArea_returnAddr]
9736#endif
9737 str r0, [r10, #offStackSaveArea_method]
9738 tst r3, #ACC_NATIVE
9739 bne .LinvokeNative
9740
9741 /*
9742 stmfd sp!, {r0-r3}
9743 bl common_printNewline
9744 mov r0, rFP
9745 mov r1, #0
9746 bl dvmDumpFp
9747 ldmfd sp!, {r0-r3}
9748 stmfd sp!, {r0-r3}
9749 mov r0, r1
9750 mov r1, r10
9751 bl dvmDumpFp
9752 bl common_printNewline
9753 ldmfd sp!, {r0-r3}
9754 */
9755
9756 ldrh r9, [r2] @ r9 <- load INST from new PC
9757 ldr r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
9758 mov rPC, r2 @ publish new rPC
9759 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self
9760
9761 @ Update "glue" values for the new method
9762 @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
9763 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall
9764 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
9765#if defined(WITH_JIT)
9766 GET_JIT_PROF_TABLE(r0)
9767 mov rFP, r1 @ fp = newFp
9768 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9
9769 mov rINST, r9 @ publish new rINST
9770 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp
9771 cmp r0,#0
9772 bne common_updateProfile
9773 GOTO_OPCODE(ip) @ jump to next instruction
9774#else
9775 mov rFP, r1 @ fp = newFp
9776 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9
9777 mov rINST, r9 @ publish new rINST
9778 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp
9779 GOTO_OPCODE(ip) @ jump to next instruction
9780#endif
9781
9782.LinvokeNative:
9783 @ Prep for the native call
9784 @ r0=methodToCall, r1=newFp, r10=newSaveArea
9785 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
Andy McFaddend5ab7262009-08-25 07:19:34 -07009786 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
Andy McFaddena5069fb2009-06-19 15:20:12 -07009787 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp
Andy McFaddend5ab7262009-08-25 07:19:34 -07009788 str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
Andy McFaddena5069fb2009-06-19 15:20:12 -07009789 mov r9, r3 @ r9<- glue->self (preserve)
9790
9791 mov r2, r0 @ r2<- methodToCall
9792 mov r0, r1 @ r0<- newFp (points to args)
9793 add r1, rGLUE, #offGlue_retval @ r1<- &retval
9794
9795#ifdef ASSIST_DEBUGGER
9796 /* insert fake function header to help gdb find the stack frame */
9797 b .Lskip
9798 .type dalvik_mterp, %function
9799dalvik_mterp:
9800 .fnstart
9801 MTERP_ENTRY1
9802 MTERP_ENTRY2
9803.Lskip:
9804#endif
9805
9806 @mov lr, pc @ set return addr
9807 @ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
9808 LDR_PC_LR "[r2, #offMethod_nativeFunc]"
9809
Bill Buzbee964a7b02010-01-28 12:54:19 -08009810#if defined(WITH_JIT)
9811 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status
9812#endif
9813
Andy McFaddena5069fb2009-06-19 15:20:12 -07009814 @ native return; r9=self, r10=newSaveArea
9815 @ equivalent to dvmPopJniLocals
Andy McFaddend5ab7262009-08-25 07:19:34 -07009816 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
Andy McFaddena5069fb2009-06-19 15:20:12 -07009817 ldr r1, [r9, #offThread_exception] @ check for exception
Bill Buzbee964a7b02010-01-28 12:54:19 -08009818#if defined(WITH_JIT)
9819 ldr r3, [r3] @ r3 <- gDvmJit.pProfTable
9820#endif
Andy McFaddena5069fb2009-06-19 15:20:12 -07009821 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp
9822 cmp r1, #0 @ null?
Andy McFaddend5ab7262009-08-25 07:19:34 -07009823 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
Bill Buzbee964a7b02010-01-28 12:54:19 -08009824#if defined(WITH_JIT)
9825 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch
9826#endif
Andy McFaddena5069fb2009-06-19 15:20:12 -07009827 bne common_exceptionThrown @ no, handle exception
9828
9829 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
9830 GET_INST_OPCODE(ip) @ extract opcode from rINST
9831 GOTO_OPCODE(ip) @ jump to next instruction
9832
Andy McFadden6ed1a0f2009-09-10 15:34:19 -07009833.LstackOverflow: @ r0=methodToCall
9834 mov r1, r0 @ r1<- methodToCall
Andy McFaddena5069fb2009-06-19 15:20:12 -07009835 ldr r0, [rGLUE, #offGlue_self] @ r0<- self
9836 bl dvmHandleStackOverflow
9837 b common_exceptionThrown
9838#ifdef ASSIST_DEBUGGER
9839 .fnend
9840#endif
9841
9842
9843 /*
9844 * Common code for method invocation, calling through "glue code".
9845 *
9846 * TODO: now that we have range and non-range invoke handlers, this
9847 * needs to be split into two. Maybe just create entry points
9848 * that set r9 and jump here?
9849 *
9850 * On entry:
9851 * r0 is "Method* methodToCall", the method we're trying to call
9852 * r9 is "bool methodCallRange", indicating if this is a /range variant
9853 */
9854 .if 0
9855.LinvokeOld:
9856 sub sp, sp, #8 @ space for args + pad
9857 FETCH(ip, 2) @ ip<- FEDC or CCCC
9858 mov r2, r0 @ A2<- methodToCall
9859 mov r0, rGLUE @ A0<- glue
9860 SAVE_PC_FP_TO_GLUE() @ export state to "glue"
9861 mov r1, r9 @ A1<- methodCallRange
9862 mov r3, rINST, lsr #8 @ A3<- AA
9863 str ip, [sp, #0] @ A4<- ip
9864 bl dvmMterp_invokeMethod @ call the C invokeMethod
9865 add sp, sp, #8 @ remove arg area
9866 b common_resumeAfterGlueCall @ continue to next instruction
9867 .endif
9868
9869
9870
9871/*
9872 * Common code for handling a return instruction.
9873 *
9874 * This does not return.
9875 */
9876common_returnFromMethod:
9877.LreturnNew:
9878 mov r0, #kInterpEntryReturn
9879 mov r9, #0
9880 bl common_periodicChecks
9881
9882 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old)
9883 ldr rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
9884 ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
9885 ldr r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
9886 @ r2<- method we're returning to
9887 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
9888 cmp r2, #0 @ is this a break frame?
9889 ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz
9890 mov r1, #0 @ "want switch" = false
9891 beq common_gotoBail @ break frame, bail out completely
9892
9893 PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
9894 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
9895 ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex
9896 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp
9897#if defined(WITH_JIT)
Ben Cheng7a0bcd02010-01-22 16:45:45 -08009898 ldr r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr
Andy McFaddena5069fb2009-06-19 15:20:12 -07009899 GET_JIT_PROF_TABLE(r0)
9900 mov rPC, r9 @ publish new rPC
9901 str r1, [rGLUE, #offGlue_methodClassDex]
Ben Cheng7a0bcd02010-01-22 16:45:45 -08009902 str r10, [r3, #offThread_inJitCodeCache] @ may return to JIT'ed land
9903 cmp r10, #0 @ caller is compiled code
9904 blxne r10
Andy McFaddena5069fb2009-06-19 15:20:12 -07009905 GET_INST_OPCODE(ip) @ extract opcode from rINST
9906 cmp r0,#0
9907 bne common_updateProfile
9908 GOTO_OPCODE(ip) @ jump to next instruction
9909#else
9910 GET_INST_OPCODE(ip) @ extract opcode from rINST
9911 mov rPC, r9 @ publish new rPC
9912 str r1, [rGLUE, #offGlue_methodClassDex]
9913 GOTO_OPCODE(ip) @ jump to next instruction
9914#endif
9915
9916 /*
9917 * Return handling, calls through "glue code".
9918 */
9919 .if 0
9920.LreturnOld:
9921 SAVE_PC_FP_TO_GLUE() @ export state
9922 mov r0, rGLUE @ arg to function
9923 bl dvmMterp_returnFromMethod
9924 b common_resumeAfterGlueCall
9925 .endif
9926
9927
9928/*
9929 * Somebody has thrown an exception. Handle it.
9930 *
9931 * If the exception processing code returns to us (instead of falling
9932 * out of the interpreter), continue with whatever the next instruction
9933 * now happens to be.
9934 *
9935 * This does not return.
9936 */
9937 .global dvmMterpCommonExceptionThrown
9938dvmMterpCommonExceptionThrown:
9939common_exceptionThrown:
9940.LexceptionNew:
9941 mov r0, #kInterpEntryThrow
9942 mov r9, #0
9943 bl common_periodicChecks
9944
Andy McFaddena5069fb2009-06-19 15:20:12 -07009945 ldr r10, [rGLUE, #offGlue_self] @ r10<- glue->self
9946 ldr r9, [r10, #offThread_exception] @ r9<- self->exception
9947 mov r1, r10 @ r1<- self
9948 mov r0, r9 @ r0<- exception
9949 bl dvmAddTrackedAlloc @ don't let the exception be GCed
9950 mov r3, #0 @ r3<- NULL
9951 str r3, [r10, #offThread_exception] @ self->exception = NULL
9952
9953 /* set up args and a local for "&fp" */
9954 /* (str sp, [sp, #-4]! would be perfect here, but is discouraged) */
9955 str rFP, [sp, #-4]! @ *--sp = fp
9956 mov ip, sp @ ip<- &fp
9957 mov r3, #0 @ r3<- false
9958 str ip, [sp, #-4]! @ *--sp = &fp
9959 ldr r1, [rGLUE, #offGlue_method] @ r1<- glue->method
9960 mov r0, r10 @ r0<- self
9961 ldr r1, [r1, #offMethod_insns] @ r1<- method->insns
9962 mov r2, r9 @ r2<- exception
9963 sub r1, rPC, r1 @ r1<- pc - method->insns
9964 mov r1, r1, asr #1 @ r1<- offset in code units
9965
9966 /* call, r0 gets catchRelPc (a code-unit offset) */
9967 bl dvmFindCatchBlock @ call(self, relPc, exc, scan?, &fp)
9968
9969 /* fix earlier stack overflow if necessary; may trash rFP */
9970 ldrb r1, [r10, #offThread_stackOverflowed]
9971 cmp r1, #0 @ did we overflow earlier?
9972 beq 1f @ no, skip ahead
9973 mov rFP, r0 @ save relPc result in rFP
9974 mov r0, r10 @ r0<- self
Andy McFadden4fbba1f2010-02-03 07:21:14 -08009975 mov r1, r9 @ r1<- exception
Andy McFaddena5069fb2009-06-19 15:20:12 -07009976 bl dvmCleanupStackOverflow @ call(self)
9977 mov r0, rFP @ restore result
99781:
9979
9980 /* update frame pointer and check result from dvmFindCatchBlock */
9981 ldr rFP, [sp, #4] @ retrieve the updated rFP
9982 cmp r0, #0 @ is catchRelPc < 0?
9983 add sp, sp, #8 @ restore stack
9984 bmi .LnotCaughtLocally
9985
9986 /* adjust locals to match self->curFrame and updated PC */
9987 SAVEAREA_FROM_FP(r1, rFP) @ r1<- new save area
9988 ldr r1, [r1, #offStackSaveArea_method] @ r1<- new method
9989 str r1, [rGLUE, #offGlue_method] @ glue->method = new method
9990 ldr r2, [r1, #offMethod_clazz] @ r2<- method->clazz
9991 ldr r3, [r1, #offMethod_insns] @ r3<- method->insns
9992 ldr r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
9993 add rPC, r3, r0, asl #1 @ rPC<- method->insns + catchRelPc
9994 str r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
9995
9996 /* release the tracked alloc on the exception */
9997 mov r0, r9 @ r0<- exception
9998 mov r1, r10 @ r1<- self
9999 bl dvmReleaseTrackedAlloc @ release the exception
10000
10001 /* restore the exception if the handler wants it */
10002 FETCH_INST() @ load rINST from rPC
10003 GET_INST_OPCODE(ip) @ extract opcode from rINST
10004 cmp ip, #OP_MOVE_EXCEPTION @ is it "move-exception"?
10005 streq r9, [r10, #offThread_exception] @ yes, restore the exception
10006 GOTO_OPCODE(ip) @ jump to next instruction
10007
10008.LnotCaughtLocally: @ r9=exception, r10=self
10009 /* fix stack overflow if necessary */
10010 ldrb r1, [r10, #offThread_stackOverflowed]
10011 cmp r1, #0 @ did we overflow earlier?
10012 movne r0, r10 @ if yes: r0<- self
Andy McFadden4fbba1f2010-02-03 07:21:14 -080010013 movne r1, r9 @ if yes: r1<- exception
Andy McFaddena5069fb2009-06-19 15:20:12 -070010014 blne dvmCleanupStackOverflow @ if yes: call(self)
10015
10016 @ may want to show "not caught locally" debug messages here
10017#if DVM_SHOW_EXCEPTION >= 2
10018 /* call __android_log_print(prio, tag, format, ...) */
10019 /* "Exception %s from %s:%d not caught locally" */
10020 @ dvmLineNumFromPC(method, pc - method->insns)
10021 ldr r0, [rGLUE, #offGlue_method]
10022 ldr r1, [r0, #offMethod_insns]
10023 sub r1, rPC, r1
10024 asr r1, r1, #1
10025 bl dvmLineNumFromPC
10026 str r0, [sp, #-4]!
10027 @ dvmGetMethodSourceFile(method)
10028 ldr r0, [rGLUE, #offGlue_method]
10029 bl dvmGetMethodSourceFile
10030 str r0, [sp, #-4]!
10031 @ exception->clazz->descriptor
10032 ldr r3, [r9, #offObject_clazz]
10033 ldr r3, [r3, #offClassObject_descriptor]
10034 @
10035 ldr r2, strExceptionNotCaughtLocally
10036 ldr r1, strLogTag
10037 mov r0, #3 @ LOG_DEBUG
10038 bl __android_log_print
10039#endif
10040 str r9, [r10, #offThread_exception] @ restore exception
10041 mov r0, r9 @ r0<- exception
10042 mov r1, r10 @ r1<- self
10043 bl dvmReleaseTrackedAlloc @ release the exception
10044 mov r1, #0 @ "want switch" = false
10045 b common_gotoBail @ bail out
10046
10047
10048 /*
10049 * Exception handling, calls through "glue code".
10050 */
10051 .if 0
10052.LexceptionOld:
10053 SAVE_PC_FP_TO_GLUE() @ export state
10054 mov r0, rGLUE @ arg to function
10055 bl dvmMterp_exceptionThrown
10056 b common_resumeAfterGlueCall
10057 .endif
10058
10059
10060/*
10061 * After returning from a "glued" function, pull out the updated
10062 * values and start executing at the next instruction.
10063 */
10064common_resumeAfterGlueCall:
10065 LOAD_PC_FP_FROM_GLUE() @ pull rPC and rFP out of glue
10066 FETCH_INST() @ load rINST from rPC
10067 GET_INST_OPCODE(ip) @ extract opcode from rINST
10068 GOTO_OPCODE(ip) @ jump to next instruction
10069
10070/*
10071 * Invalid array index.
10072 */
10073common_errArrayIndex:
10074 EXPORT_PC()
10075 ldr r0, strArrayIndexException
10076 mov r1, #0
10077 bl dvmThrowException
10078 b common_exceptionThrown
10079
10080/*
10081 * Invalid array value.
10082 */
10083common_errArrayStore:
10084 EXPORT_PC()
10085 ldr r0, strArrayStoreException
10086 mov r1, #0
10087 bl dvmThrowException
10088 b common_exceptionThrown
10089
10090/*
10091 * Integer divide or mod by zero.
10092 */
10093common_errDivideByZero:
10094 EXPORT_PC()
10095 ldr r0, strArithmeticException
10096 ldr r1, strDivideByZero
10097 bl dvmThrowException
10098 b common_exceptionThrown
10099
10100/*
10101 * Attempt to allocate an array with a negative size.
10102 */
10103common_errNegativeArraySize:
10104 EXPORT_PC()
10105 ldr r0, strNegativeArraySizeException
10106 mov r1, #0
10107 bl dvmThrowException
10108 b common_exceptionThrown
10109
10110/*
10111 * Invocation of a non-existent method.
10112 */
10113common_errNoSuchMethod:
10114 EXPORT_PC()
10115 ldr r0, strNoSuchMethodError
10116 mov r1, #0
10117 bl dvmThrowException
10118 b common_exceptionThrown
10119
10120/*
10121 * We encountered a null object when we weren't expecting one. We
10122 * export the PC, throw a NullPointerException, and goto the exception
10123 * processing code.
10124 */
10125common_errNullObject:
10126 EXPORT_PC()
10127 ldr r0, strNullPointerException
10128 mov r1, #0
10129 bl dvmThrowException
10130 b common_exceptionThrown
10131
10132/*
10133 * For debugging, cause an immediate fault. The source address will
10134 * be in lr (use a bl instruction to jump here).
10135 */
10136common_abort:
10137 ldr pc, .LdeadFood
10138.LdeadFood:
10139 .word 0xdeadf00d
10140
10141/*
10142 * Spit out a "we were here", preserving all registers. (The attempt
10143 * to save ip won't work, but we need to save an even number of
10144 * registers for EABI 64-bit stack alignment.)
10145 */
10146 .macro SQUEAK num
10147common_squeak\num:
10148 stmfd sp!, {r0, r1, r2, r3, ip, lr}
10149 ldr r0, strSqueak
10150 mov r1, #\num
10151 bl printf
10152 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
10153 bx lr
10154 .endm
10155
10156 SQUEAK 0
10157 SQUEAK 1
10158 SQUEAK 2
10159 SQUEAK 3
10160 SQUEAK 4
10161 SQUEAK 5
10162
10163/*
10164 * Spit out the number in r0, preserving registers.
10165 */
10166common_printNum:
10167 stmfd sp!, {r0, r1, r2, r3, ip, lr}
10168 mov r1, r0
10169 ldr r0, strSqueak
10170 bl printf
10171 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
10172 bx lr
10173
10174/*
10175 * Print a newline, preserving registers.
10176 */
10177common_printNewline:
10178 stmfd sp!, {r0, r1, r2, r3, ip, lr}
10179 ldr r0, strNewline
10180 bl printf
10181 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
10182 bx lr
10183
10184 /*
10185 * Print the 32-bit quantity in r0 as a hex value, preserving registers.
10186 */
10187common_printHex:
10188 stmfd sp!, {r0, r1, r2, r3, ip, lr}
10189 mov r1, r0
10190 ldr r0, strPrintHex
10191 bl printf
10192 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
10193 bx lr
10194
10195/*
10196 * Print the 64-bit quantity in r0-r1, preserving registers.
10197 */
10198common_printLong:
10199 stmfd sp!, {r0, r1, r2, r3, ip, lr}
10200 mov r3, r1
10201 mov r2, r0
10202 ldr r0, strPrintLong
10203 bl printf
10204 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
10205 bx lr
10206
10207/*
10208 * Print full method info. Pass the Method* in r0. Preserves regs.
10209 */
10210common_printMethod:
10211 stmfd sp!, {r0, r1, r2, r3, ip, lr}
10212 bl dvmMterpPrintMethod
10213 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
10214 bx lr
10215
10216/*
10217 * Call a C helper function that dumps regs and possibly some
10218 * additional info. Requires the C function to be compiled in.
10219 */
10220 .if 0
10221common_dumpRegs:
10222 stmfd sp!, {r0, r1, r2, r3, ip, lr}
10223 bl dvmMterpDumpArmRegs
10224 ldmfd sp!, {r0, r1, r2, r3, ip, lr}
10225 bx lr
10226 .endif
10227
10228#if 0
10229/*
10230 * Experiment on VFP mode.
10231 *
10232 * uint32_t setFPSCR(uint32_t val, uint32_t mask)
10233 *
10234 * Updates the bits specified by "mask", setting them to the values in "val".
10235 */
10236setFPSCR:
10237 and r0, r0, r1 @ make sure no stray bits are set
10238 fmrx r2, fpscr @ get VFP reg
10239 mvn r1, r1 @ bit-invert mask
10240 and r2, r2, r1 @ clear masked bits
10241 orr r2, r2, r0 @ set specified bits
10242 fmxr fpscr, r2 @ set VFP reg
10243 mov r0, r2 @ return new value
10244 bx lr
10245
10246 .align 2
10247 .global dvmConfigureFP
10248 .type dvmConfigureFP, %function
10249dvmConfigureFP:
10250 stmfd sp!, {ip, lr}
10251 /* 0x03000000 sets DN/FZ */
10252 /* 0x00009f00 clears the six exception enable flags */
10253 bl common_squeak0
10254 mov r0, #0x03000000 @ r0<- 0x03000000
10255 add r1, r0, #0x9f00 @ r1<- 0x03009f00
10256 bl setFPSCR
10257 ldmfd sp!, {ip, pc}
10258#endif
10259
10260
10261/*
10262 * String references, must be close to the code that uses them.
10263 */
10264 .align 2
10265strArithmeticException:
10266 .word .LstrArithmeticException
10267strArrayIndexException:
10268 .word .LstrArrayIndexException
10269strArrayStoreException:
10270 .word .LstrArrayStoreException
10271strDivideByZero:
10272 .word .LstrDivideByZero
10273strNegativeArraySizeException:
10274 .word .LstrNegativeArraySizeException
10275strNoSuchMethodError:
10276 .word .LstrNoSuchMethodError
10277strNullPointerException:
10278 .word .LstrNullPointerException
10279
10280strLogTag:
10281 .word .LstrLogTag
10282strExceptionNotCaughtLocally:
10283 .word .LstrExceptionNotCaughtLocally
10284
10285strNewline:
10286 .word .LstrNewline
10287strSqueak:
10288 .word .LstrSqueak
10289strPrintHex:
10290 .word .LstrPrintHex
10291strPrintLong:
10292 .word .LstrPrintLong
10293
10294/*
10295 * Zero-terminated ASCII string data.
10296 *
10297 * On ARM we have two choices: do like gcc does, and LDR from a .word
10298 * with the address, or use an ADR pseudo-op to get the address
10299 * directly. ADR saves 4 bytes and an indirection, but it's using a
10300 * PC-relative addressing mode and hence has a limited range, which
10301 * makes it not work well with mergeable string sections.
10302 */
10303 .section .rodata.str1.4,"aMS",%progbits,1
10304
10305.LstrBadEntryPoint:
10306 .asciz "Bad entry point %d\n"
10307.LstrArithmeticException:
10308 .asciz "Ljava/lang/ArithmeticException;"
10309.LstrArrayIndexException:
10310 .asciz "Ljava/lang/ArrayIndexOutOfBoundsException;"
10311.LstrArrayStoreException:
10312 .asciz "Ljava/lang/ArrayStoreException;"
10313.LstrClassCastException:
10314 .asciz "Ljava/lang/ClassCastException;"
10315.LstrDivideByZero:
10316 .asciz "divide by zero"
10317.LstrFilledNewArrayNotImpl:
10318 .asciz "filled-new-array only implemented for objects and 'int'"
10319.LstrInternalError:
10320 .asciz "Ljava/lang/InternalError;"
10321.LstrInstantiationError:
10322 .asciz "Ljava/lang/InstantiationError;"
10323.LstrNegativeArraySizeException:
10324 .asciz "Ljava/lang/NegativeArraySizeException;"
10325.LstrNoSuchMethodError:
10326 .asciz "Ljava/lang/NoSuchMethodError;"
10327.LstrNullPointerException:
10328 .asciz "Ljava/lang/NullPointerException;"
10329
10330.LstrLogTag:
10331 .asciz "mterp"
10332.LstrExceptionNotCaughtLocally:
10333 .asciz "Exception %s from %s:%d not caught locally\n"
10334
10335.LstrNewline:
10336 .asciz "\n"
10337.LstrSqueak:
10338 .asciz "<%d>"
10339.LstrPrintHex:
10340 .asciz "<0x%x>"
10341.LstrPrintLong:
10342 .asciz "<%lld>"
10343
10344