1%def header():
2/*
3 * Copyright (C) 2020 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18/*
19 * This is a #include, not a %include, because we want the C pre-processor
20 * to expand the macros into assembler assignment statements.
21 */
22#include "asm_support.h"
23#include "arch/arm/asm_support_arm.S"
24
25/**
26 * ARM EABI general notes:
27 *
28 * r0-r3 hold first 4 args to a method; they are not preserved across method calls
29 * r4-r8 are available for general use
30 * r9 is given special treatment in some situations, but not for us
31 * r10 (sl) seems to be generally available
32 * r11 (fp) is used by gcc (unless -fomit-frame-pointer is set)
33 * r12 (ip) is scratch -- not preserved across method calls
34 * r13 (sp) should be managed carefully in case a signal arrives
35 * r14 (lr) must be preserved
36 * r15 (pc) can be tinkered with directly
37 *
38 * r0 holds returns of <= 4 bytes
39 * r0-r1 hold returns of 8 bytes, low word in r0
40 *
41 * Callee must save/restore r4+ (except r12) if it modifies them.  If VFP
42 * is present, registers s16-s31 (a/k/a d8-d15, a/k/a q4-q7) must be preserved,
43 * s0-s15 (d0-d7, q0-a3) do not need to be.
44 *
45 * Stack is "full descending".  Only the arguments that don't fit in the first 4
46 * registers are placed on the stack.  "sp" points at the first stacked argument
47 * (i.e. the 5th arg).
48 *
49 * Native ABI uses soft-float, single-precision results are in r0,
50 * double-precision results in r0-r1.
51 *
52 * In the EABI, "sp" must be 64-bit aligned on entry to a function, and any
53 * 64-bit quantities (long long, double) must be 64-bit aligned.
54 *
55 * Nterp notes:
56 *
57 * The following registers have fixed assignments:
58 *
59 *   reg nick      purpose
60 *   r5  rFP       interpreted frame pointer, used for accessing locals and args
61 *   r6  rREFS     base of object references of dex registers
62 *   r7  rINST     first 16-bit code unit of current instruction
63 *   r8  rMR       marking register
64 *   r9  rSELF     self (Thread) pointer
65 *   r10 rIBASE    interpreted instruction base pointer, used for computed goto
66 *   r11 rPC       interpreted program counter, used for fetching instructions
67 *
68 *   r4, ip, and lr can be used as temporary
69 *
70 * Note that r4 is a callee-save register in ARM EABI, but not in managed code.
71 *
72 */
73
74/* single-purpose registers, given names for clarity */
75#define CFI_DEX  11 // DWARF register number of the register holding dex-pc (rPC).
76#define CFI_TMP  0  // DWARF register number of the first argument register (r0).
77#define CFI_REFS 6
78#define rFP      r5
79#define rREFS    r6
80#define rINST    r7
81#define rSELF    r9
82#define rIBASE   r10
83#define rPC      r11
84
85// To avoid putting ifdefs arond the use of rMR, make sure it's defined.
86// IsNterpSupported returns false for configurations that don't have rMR (typically CMS).
87#ifndef rMR
88#define rMR r8
89#endif
90
91// Temporary registers while setting up a frame.
92#define rNEW_FP   r8
93#define rNEW_REFS r10
94#define CFI_NEW_REFS 10
95
96#define CALLEE_SAVES_SIZE (9 * 4 + 16 * 4)
97
98// +4 for the ArtMethod of the caller.
99#define OFFSET_TO_FIRST_ARGUMENT_IN_STACK (CALLEE_SAVES_SIZE + 4)
100
101/*
102 * Fetch the next instruction from rPC into rINST.  Does not advance rPC.
103 */
104.macro FETCH_INST
105    ldrh    rINST, [rPC]
106.endm
107
108/*
109 * Fetch the next instruction from the specified offset.  Advances rPC
110 * to point to the next instruction.  "count" is in 16-bit code units.
111 *
112 * Because of the limited size of immediate constants on ARM, this is only
113 * suitable for small forward movements (i.e. don't try to implement "goto"
114 * with this).
115 *
116 * This must come AFTER anything that can throw an exception, or the
117 * exception catch may miss.  (This also implies that it must come after
118 * EXPORT_PC.)
119 */
120.macro FETCH_ADVANCE_INST count
121    ldrh    rINST, [rPC, #((\count)*2)]!
122.endm
123
124/*
125 * Similar to FETCH_ADVANCE_INST, but does not update xPC.  Used to load
126 * rINST ahead of possible exception point.  Be sure to manually advance xPC
127 * later.
128 */
129.macro PREFETCH_INST count
130    ldrh    rINST, [rPC, #((\count)*2)]
131.endm
132
133/* Advance xPC by some number of code units. */
134.macro ADVANCE count
135  add  rPC, #((\count)*2)
136.endm
137
138/*
139 * Fetch the next instruction from an offset specified by "reg" and advance xPC.
140 * xPC to point to the next instruction.  "reg" must specify the distance
141 * in bytes, *not* 16-bit code units, and may be a signed value.
142 */
143.macro FETCH_ADVANCE_INST_RB reg
144    ldrh    rINST, [rPC, \reg]!
145.endm
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 xPC.
150 *
151 * The "_S" variant works the same but treats the value as signed.
152 */
153.macro FETCH reg, count
154    ldrh    \reg, [rPC, #((\count)*2)]
155.endm
156
157.macro FETCH_S reg, count
158    ldrsh   \reg, [rPC, #((\count)*2)]
159.endm
160
161/*
162 * Fetch one byte from an offset past the current PC.  Pass in the same
163 * "count" as you would for FETCH, and an additional 0/1 indicating which
164 * byte of the halfword you want (lo/hi).
165 */
166.macro FETCH_B reg, count, byte
167    ldrb     \reg, [rPC, #((\count)*2+(\byte))]
168.endm
169
170/*
171 * Put the instruction's opcode field into the specified register.
172 */
173.macro GET_INST_OPCODE reg
174    and     \reg, rINST, #255
175.endm
176
177/*
178 * Begin executing the opcode in _reg.  Clobbers reg
179 */
180
181.macro GOTO_OPCODE reg
182    add     pc, rIBASE, \reg, lsl #${handler_size_bits}
183.endm
184
185/*
186 * Get/set value from a Dalvik register.
187 */
188.macro GET_VREG reg, vreg
189    ldr     \reg, [rFP, \vreg, lsl #2]
190.endm
191.macro GET_VREG_OBJECT reg, vreg
192    ldr     \reg, [rREFS, \vreg, lsl #2]
193.endm
194.macro SET_VREG reg, vreg
195    str     \reg, [rFP, \vreg, lsl #2]
196    mov     \reg, #0
197    str     \reg, [rREFS, \vreg, lsl #2]
198.endm
199.macro SET_VREG_OBJECT reg, vreg
200    str     \reg, [rFP, \vreg, lsl #2]
201    str     \reg, [rREFS, \vreg, lsl #2]
202.endm
203.macro SET_VREG_FLOAT reg, vreg, tmpreg
204    add     \tmpreg, rFP, \vreg, lsl #2
205    vstr    \reg, [\tmpreg]
206    mov     \tmpreg, #0
207    str     \tmpreg, [rREFS, \vreg, lsl #2]
208.endm
209.macro GET_VREG_WIDE_BY_ADDR reg0, reg1, addr
210    ldmia \addr, {\reg0, \reg1}
211.endm
212.macro SET_VREG_WIDE_BY_ADDR reg0, reg1, addr
213    stmia \addr, {\reg0, \reg1}
214.endm
215.macro GET_VREG_FLOAT sreg, vreg
216    ldr  \vreg, [rFP, \vreg, lsl #2]
217    vmov \sreg, \vreg
218.endm
219.macro GET_VREG_FLOAT_BY_ADDR reg, addr
220    vldr \reg, [\addr]
221.endm
222.macro SET_VREG_FLOAT_BY_ADDR reg, addr
223    vstr \reg, [\addr]
224.endm
225.macro GET_VREG_DOUBLE_BY_ADDR reg, addr
226    vldr \reg, [\addr]
227.endm
228.macro SET_VREG_DOUBLE_BY_ADDR reg, addr
229    vstr \reg, [\addr]
230.endm
231.macro SET_VREG_SHADOW reg, vreg
232    str     \reg, [rREFS, \vreg, lsl #2]
233.endm
234.macro CLEAR_SHADOW_PAIR vreg, tmp1, tmp2
235    mov     \tmp1, #0
236    add     \tmp2, \vreg, #1
237    SET_VREG_SHADOW \tmp1, \vreg
238    SET_VREG_SHADOW \tmp1, \tmp2
239.endm
240.macro VREG_INDEX_TO_ADDR reg, vreg
241    add     \reg, rFP, \vreg, lsl #2
242.endm
243
244// An assembly entry that has a OatQuickMethodHeader prefix.
245.macro OAT_ENTRY name, end
246    .arm
247    .type \name, #function
248    .hidden \name
249    .global \name
250    .balign 16
251    // Padding of 3 * 8 bytes to get 16 bytes alignment of code entry.
252    .long 0
253    .long 0
254    .long 0
255    // OatQuickMethodHeader. Note that the top two bits must be clear.
256    .long (\end - \name)
257\name:
258.endm
259
260.macro SIZE name
261    .size \name, .-\name
262.endm
263
264.macro NAME_START name
265    .arm
266    .type \name, #function
267    .hidden \name  // Hide this as a global symbol, so we do not incur plt calls.
268    .global \name
269    /* Cache alignment for function entry */
270    .balign 16
271\name:
272.endm
273
274.macro NAME_END name
275  SIZE \name
276.endm
277
278// Macro for defining entrypoints into runtime. We don't need to save registers
279// (we're not holding references there), but there is no
280// kDontSave runtime method. So just use the kSaveRefsOnly runtime method.
281.macro NTERP_TRAMPOLINE name, helper
282ENTRY \name
283  SETUP_SAVE_REFS_ONLY_FRAME ip
284  bl \helper
285  RESTORE_SAVE_REFS_ONLY_FRAME
286  REFRESH_MARKING_REGISTER
287  RETURN_OR_DELIVER_PENDING_EXCEPTION
288END \name
289.endm
290
291.macro CLEAR_STATIC_VOLATILE_MARKER reg
292  and \reg, \reg, #-2
293.endm
294
295.macro CLEAR_INSTANCE_VOLATILE_MARKER reg
296  rsb \reg, \reg, #0
297.endm
298
299.macro EXPORT_PC
300    str    rPC, [rREFS, #-8]
301.endm
302
303.macro BRANCH
304    // Update method counter and do a suspend check if the branch is negative.
305    cmp rINST, #0
306    blt 2f
3071:
308    add r2, rINST, rINST                // r2<- byte offset
309    FETCH_ADVANCE_INST_RB r2            // update xPC, load rINST
310    GET_INST_OPCODE ip                  // extract opcode from rINST
311    GOTO_OPCODE ip                      // jump to next instruction
3122:
313    ldr r0, [sp]
314    ldrh r2, [r0, #ART_METHOD_HOTNESS_COUNT_OFFSET]
315    add r2, r2, #1
316    ubfx r2, r2, #0, #NTERP_HOTNESS_BITS
317    strh r2, [r0, #ART_METHOD_HOTNESS_COUNT_OFFSET]
318    // If the counter overflows, handle this in the runtime.
319    cmp r2, #0
320    beq NterpHandleHotnessOverflow
321    // Otherwise, do a suspend check.
322    ldr r0, [rSELF, #THREAD_FLAGS_OFFSET]
323    ands r0, r0, #THREAD_SUSPEND_OR_CHECKPOINT_REQUEST
324    beq 1b
325    EXPORT_PC
326    bl    art_quick_test_suspend
327    b 1b
328.endm
329
330// Expects:
331// - ip and lr to be available.
332// Outputs:
333// - \registers contains the dex registers size
334// - \outs contains the outs size
335// - if load_ins is 1, \ins contains the ins
336// - \code_item is replaced with a pointer to the instructions
337.macro FETCH_CODE_ITEM_INFO code_item, registers, outs, ins, load_ins
338    tst \code_item, #1
339    beq 5f
340    bic \code_item, \code_item, #1 // Remove the extra bit that marks it's a compact dex file
341    ldrh lr, [\code_item, #COMPACT_CODE_ITEM_FIELDS_OFFSET]
342    ubfx \registers, lr, #COMPACT_CODE_ITEM_REGISTERS_SIZE_SHIFT, #4
343    ubfx \outs, lr, #COMPACT_CODE_ITEM_OUTS_SIZE_SHIFT, #4
344    .if \load_ins
345    ubfx \ins, lr, #COMPACT_CODE_ITEM_INS_SIZE_SHIFT, #4
346    .else
347    ubfx ip, lr, #COMPACT_CODE_ITEM_INS_SIZE_SHIFT, #4
348    add \registers, \registers, ip
349    .endif
350
351    ldrh lr, [\code_item, #COMPACT_CODE_ITEM_FLAGS_OFFSET]
352    tst lr, #COMPACT_CODE_ITEM_REGISTERS_INS_OUTS_FLAGS
353    beq 4f
354    mov ip, \code_item
355    tst lr, #COMPACT_CODE_ITEM_INSNS_FLAG
356    beq 1f
357    sub ip, ip, #4
3581:
359    tst lr, #COMPACT_CODE_ITEM_REGISTERS_FLAG
360    beq 2f
361    ldrh lr, [ip, #-2]!
362    add \registers, \registers, lr
363    ldrh lr, [\code_item, #COMPACT_CODE_ITEM_FLAGS_OFFSET]
3642:
365    tst lr, #COMPACT_CODE_ITEM_INS_FLAG
366    beq 3f
367    ldrh lr, [ip, #-2]!
368    .if \load_ins
369    add \ins, \ins, lr
370    .else
371    add \registers, \registers, lr
372    .endif
373    ldrh lr, [\code_item, #COMPACT_CODE_ITEM_FLAGS_OFFSET]
3743:
375    tst lr, #COMPACT_CODE_ITEM_OUTS_FLAG
376    beq 4f
377    ldrh lr, [ip, #-2]!
378    add \outs, \outs, lr
3794:
380    .if \load_ins
381    add \registers, \registers, \ins
382    .endif
383    add \code_item, \code_item, #COMPACT_CODE_ITEM_INSNS_OFFSET
384    b 6f
3855:
386    // Fetch dex register size.
387    ldrh \registers, [\code_item, #CODE_ITEM_REGISTERS_SIZE_OFFSET]
388    // Fetch outs size.
389    ldrh \outs, [\code_item, #CODE_ITEM_OUTS_SIZE_OFFSET]
390    .if \load_ins
391    ldrh \ins, [\code_item, #CODE_ITEM_INS_SIZE_OFFSET]
392    .endif
393    add \code_item, \code_item, #CODE_ITEM_INSNS_OFFSET
3946:
395.endm
396
397// Setup the stack to start executing the method. Expects:
398// - r0 to contain the ArtMethod
399// - \code_item to already contain the code item
400// - rINST, ip, lr to be available
401//
402// Outputs
403// - rINST contains the dex registers size
404// - ip contains the old stack pointer.
405// - \code_item is replaced with a pointer to the instructions
406// - if load_ins is 1, r4 contains the ins
407//
408.macro SETUP_STACK_FRAME code_item, refs, fp, cfi_refs, load_ins
409    FETCH_CODE_ITEM_INFO \code_item, rINST, \refs, r4, \load_ins
410
411    // Compute required frame size: ((2 * rINST) + \refs) * 4 + 12
412    // 12 is for saving the previous frame, pc, and method being executed.
413    add ip, \refs, rINST, lsl #1
414
415    // Compute new stack pointer in lr
416    sub lr, sp, #12
417    sub lr, lr, ip, lsl #2
418    // Alignment
419    and lr, lr, #-16
420
421    // Set reference and dex registers.
422    add \refs, lr, \refs, lsl #2
423    add \refs, \refs, #12
424    add \fp, \refs, rINST, lsl #2
425
426    // Now setup the stack pointer.
427    mov ip, sp
428    .cfi_def_cfa_register ip
429    mov sp, lr
430    str ip, [\refs, #-4]
431    CFI_DEF_CFA_BREG_PLUS_UCONST \cfi_refs, -4, CALLEE_SAVES_SIZE
432
433    // Save the ArtMethod, and use r0 as a temporary.
434    str r0, [sp]
435
436    // Put nulls in reference frame.
437    cmp rINST, #0
438    beq 2f
439    mov lr, \refs
440    mov r0, #0
4411:
442    str r0, [lr], #4
443    str r0, [lr], #4  // May clear vreg[0].
444    cmp lr, \fp
445    blo 1b
4462:
447    ldr r0, [sp]  // Reload the ArtMethod, expected by the callers.
448.endm
449
450// Increase method hotness and do suspend check before starting executing the method.
451.macro START_EXECUTING_INSTRUCTIONS
452    ldr r0, [sp]
453    ldrh r2, [r0, #ART_METHOD_HOTNESS_COUNT_OFFSET]
454    add r2, r2, #1
455    ubfx r2, r2, #0, #NTERP_HOTNESS_BITS
456    strh r2, [r0, #ART_METHOD_HOTNESS_COUNT_OFFSET]
457    // If the counter overflows, handle this in the runtime.
458    cmp r2, #0
459    beq 2f
460    ldr r0, [rSELF, #THREAD_FLAGS_OFFSET]
461    tst r0, #THREAD_SUSPEND_OR_CHECKPOINT_REQUEST
462    bne 3f
4631:
464    FETCH_INST
465    GET_INST_OPCODE ip
466    GOTO_OPCODE ip
4672:
468    mov r1, #0
469    mov r2, rFP
470    bl nterp_hot_method
471    b 1b
4723:
473    EXPORT_PC
474    bl art_quick_test_suspend
475    b 1b
476.endm
477
478.macro SPILL_ALL_CALLEE_SAVES
479    SPILL_ALL_CALLEE_SAVE_GPRS                    @ 9 words (36 bytes) of callee saves.
480    vpush {s16-s31}                               @ 16 words (64 bytes) of floats.
481    .cfi_adjust_cfa_offset 64
482.endm
483
484.macro RESTORE_ALL_CALLEE_SAVES lr_to_pc=0
485    vpop {s16-s31}
486    .cfi_adjust_cfa_offset -64
487    pop {r4-r7}
488    .cfi_adjust_cfa_offset -16
489    .cfi_restore r4
490    .cfi_restore r5
491    .cfi_restore r6
492    .cfi_restore r7
493    // Don't restore r8, the marking register gets updated when coming back from runtime.
494    add sp, sp, #4
495    .cfi_adjust_cfa_offset -4
496    .if \lr_to_pc
497    pop {r9-r11, pc}  @ 9 words of callee saves and args.
498    .else
499    pop {r9-r11, lr}  @ 9 words of callee saves and args.
500    .cfi_adjust_cfa_offset -16
501    .cfi_restore r9
502    .cfi_restore r10
503    .cfi_restore r11
504    .cfi_restore lr
505    .endif
506.endm
507
508// Helper to setup the stack after doing a nterp to nterp call. This will setup:
509// - rNEW_FP: the new pointer to dex registers
510// - rNEW_REFS: the new pointer to references
511// - rPC: the new PC pointer to execute
512// - r2: value in instruction to decode the number of arguments.
513// - r3: first dex register for range invokes, up to 4 arguments for non-range invokes.
514// - r4: top of dex register array
515//
516// The method expects:
517// - r0 to contain the ArtMethod
518// - r4 to contain the code item
519.macro SETUP_STACK_FOR_INVOKE
520   // We do the same stack overflow check as the compiler. See CanMethodUseNterp
521   // in how we limit the maximum nterp frame size.
522   sub ip, sp, #STACK_OVERFLOW_RESERVED_BYTES
523   ldr ip, [ip]
524
525   // Spill all callee saves to have a consistent stack frame whether we
526   // are called by compiled code or nterp.
527   SPILL_ALL_CALLEE_SAVES
528
529   // Setup the frame.
530   SETUP_STACK_FRAME r4, rNEW_REFS, rNEW_FP, CFI_NEW_REFS, load_ins=0
531
532   // Fetch instruction information before replacing rPC.
533   FETCH_B r2, 0, 1
534   FETCH r3, 2
535
536   // Set the dex pc pointer.
537   mov rPC, r4
538
539   // Make r4 point to the top of the dex register array.
540   add r4, rNEW_FP, rINST, lsl #2
541
542   CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0)
543.endm
544
545// Setup arguments based on a non-range nterp to nterp call, and start executing
546// the method. We expect:
547// - rNEW_FP: the new pointer to dex registers
548// - rPC: the new PC pointer to execute
549// - r2: number of arguments (bits 4-7), 5th argument if any (bits 0-3)
550// - r3: up to four dex register arguments
551// - r4: top of dex register array
552// - r1: receiver if non-static.
553//
554// Uses r0 and rINST as temporaries.
555.macro SETUP_NON_RANGE_ARGUMENTS_AND_EXECUTE is_static=0, is_string_init=0
556   // /* op vA, vB, {vC...vG} */
557   .if \is_static
558   asrs   r0, r2, #4
559   beq    6f
560   .else
561   asr    r0, r2, #4
562   .endif
563   mov rINST, #-4
564   cmp r0, #2
565   blt 1f
566   beq 2f
567   cmp r0, #4
568   blt 3f
569   beq 4f
570
571  // We use a decrementing rINST to store references relative
572  // to rNEW_FP and dex registers relative to r4
573  //
574  // TODO: We could set up rINST as the number of registers (this can be an additional output from
575  // SETUP_STACK_FOR_INVOKE) and then just decrement it by one before copying each arg.
576  // Maybe even introduce macros NEW_VREG_ADDRESS/NEW_VREG_REF_ADDRESS.
5775:
578   and         r2, r2, #15
579   GET_VREG_OBJECT r0, r2
580   str         r0, [rNEW_FP, rINST]
581   GET_VREG    r0, r2
582   str         r0, [r4, rINST]
583   sub         rINST, rINST, #4
5844:
585   asr         r2, r3, #12
586   GET_VREG_OBJECT r0, r2
587   str         r0, [rNEW_FP, rINST]
588   GET_VREG    r0, r2
589   str         r0, [r4, rINST]
590   sub         rINST, rINST, #4
5913:
592   ubfx        r2, r3, #8, #4
593   GET_VREG_OBJECT r0, r2
594   str         r0, [rNEW_FP, rINST]
595   GET_VREG    r0, r2
596   str         r0, [r4, rINST]
597   sub         rINST, rINST, #4
5982:
599   ubfx        r2, r3, #4, #4
600   GET_VREG_OBJECT r0, r2
601   str         r0, [rNEW_FP, rINST]
602   GET_VREG    r0, r2
603   str         r0, [r4, rINST]
604   .if !\is_string_init
605   sub         rINST, rINST, #4
606   .endif
6071:
608   .if \is_string_init
609   // Ignore the first argument
610   .elseif \is_static
611   and         r2, r3, #0xf
612   GET_VREG_OBJECT r0, r2
613   str         r0, [rNEW_FP, rINST]
614   GET_VREG    r0, r2
615   str         r0, [r4, rINST]
616   .else
617   str         r1, [rNEW_FP, rINST]
618   str         r1, [r4, rINST]
619   .endif
620
6216:
622   // Start executing the method.
623   mov rFP, rNEW_FP
624   mov rREFS, rNEW_REFS
625   CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -4, CALLEE_SAVES_SIZE
626   // r8 was used for setting up the frame, restore it now.
627   REFRESH_MARKING_REGISTER
628   // Branch to the main handler, which will reload rIBASE,
629   // that was used for setting up the frame.
630   b .Lexecute_instructions
631.endm
632
633// Setup arguments based on a range nterp to nterp call, and start executing
634// the method.
635// - rNEW_FP: the new pointer to dex registers
636// - rNEW_REFS: the new pointer to references
637// - rPC: the new PC pointer to execute
638// - r2: number of arguments
639// - r3: first dex register
640// - r4: top of dex register array
641// - r1: receiver if non-static.
642//
643// Expects r0 to be available.
644.macro SETUP_RANGE_ARGUMENTS_AND_EXECUTE is_static=0, is_string_init=0
645   mov r0, #-4
646   .if \is_string_init
647   // Ignore the first argument
648   sub r2, r2, #1
649   add r3, r3, #1
650   .elseif !\is_static
651   sub r2, r2, #1
652   add r3, r3, #1
653   .endif
654
655   cmp r2, #0
656   beq 2f
657   add rREFS, rREFS, r3, lsl #2  // pointer to first argument in reference array
658   add rREFS, rREFS, r2, lsl #2    // pointer to last argument in reference array
659   add rFP, rFP, r3, lsl #2     // pointer to first argument in register array
660   add rFP, rFP, r2, lsl #2      // pointer to last argument in register array
6611:
662   ldr  r3, [rREFS, #-4]!
663   str  r3, [rNEW_FP, r0]
664   subs r2, r2, 1
665   ldr  r3, [rFP, #-4]!
666   str  r3, [r4, r0]
667   sub r0, r0, 4
668   bne 1b
6692:
670   .if \is_string_init
671   // Ignore first argument
672   .elseif !\is_static
673   str r1, [rNEW_FP, r0]
674   str r1, [r4, r0]
675   .endif
676   mov rFP, rNEW_FP
677   mov rREFS, rNEW_REFS
678   CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -4, CALLEE_SAVES_SIZE
679   // r8 was used for setting up the frame, restore it now.
680   REFRESH_MARKING_REGISTER
681   // Branch to the main handler, which will reload rIBASE,
682   // that was used for setting up the frame.
683   b .Lexecute_instructions
684.endm
685
686.macro GET_SHORTY dest, is_interface, is_polymorphic, is_custom
687   push {r0-r3}
688   .if \is_polymorphic
689   ldr r0, [sp, #16]
690   mov r1, rPC
691   bl NterpGetShortyFromInvokePolymorphic
692   .elseif \is_custom
693   ldr r0, [sp, #16]
694   mov r1, rPC
695   bl NterpGetShortyFromInvokeCustom
696   .elseif \is_interface
697   ldr r0, [sp, #16]
698   FETCH r1, 1
699   bl NterpGetShortyFromMethodId
700   .else
701   bl NterpGetShorty
702   .endif
703   mov \dest, r0
704   pop {r0-r3}
705.endm
706
707// Input:  r0 contains the ArtMethod
708// Output: r4 contains the code item
709.macro GET_CODE_ITEM
710   ldr r4, [r0, #ART_METHOD_DATA_OFFSET_32]
711.endm
712
713.macro DO_ENTRY_POINT_CHECK call_compiled_code, name
714   // On entry, the method is r0, the instance is r1
715   ldr r2, .Lfetch_nterp_\name
716.Lfetch_location_\name:
717   // Note that this won't work for thumb.
718   sub r2, pc, r2
719   ldr r3, [r0, #ART_METHOD_QUICK_CODE_OFFSET_32]
720   cmp r2, r3
721   bne  \call_compiled_code
722.endm
723
724// Expects ip and lr to be available.
725.macro UPDATE_REGISTERS_FOR_STRING_INIT old_value, new_value
726   mov ip, #0
7271:
728   GET_VREG_OBJECT lr, ip
729   cmp lr, \old_value
730   bne 2f
731   SET_VREG_OBJECT \new_value, ip
7322:
733   add ip, ip, #1
734   add lr, rREFS, ip, lsl #2
735   cmp lr, rFP
736   bne 1b
737.endm
738
739// Puts the next floating point argument into the expected register,
740// fetching values based on a non-range invoke.
741// Uses ip and lr.
742.macro LOOP_OVER_SHORTY_LOADING_FPS dreg, sreg, inst, shorty, arg_index, finished, if_double
7431: // LOOP
744    ldrb ip, [\shorty], #1          // Load next character in shorty, and increment.
745    cmp ip, #0
746    beq \finished                   // if (ip == '\0') goto finished
747    cmp ip, #68                    // if (ip == 'D') goto FOUND_DOUBLE
748    beq 2f
749    cmp ip, #70                    // if (ip == 'F') goto FOUND_FLOAT
750    beq 3f
751    lsr \inst, \inst, #4
752    add \arg_index, \arg_index, #1
753    //  Handle extra argument in arg array taken by a long.
754    cmp ip, #74                   // if (ip != 'J') goto LOOP
755    bne 1b
756    lsr \inst, \inst, #4
757    add \arg_index, \arg_index, #1
758    b 1b                        // goto LOOP
7592:  // FOUND_DOUBLE
760    and ip, \inst, #0xf
761    GET_VREG ip, ip
762    lsr \inst, \inst, #4
763    add \arg_index, \arg_index, #1
764    cmp \arg_index, #4
765    beq 5f
766    and lr, \inst, #0xf
767    lsr \inst, \inst, #4
768    add \arg_index, \arg_index, #1
769    b 6f
7705:
771    FETCH_B lr, 0, 1
772    and lr, lr, #0xf
7736:
774    GET_VREG lr, lr
775    vmov \dreg, ip, lr
776    b \if_double
7773:  // FOUND_FLOAT
778    cmp \arg_index, #4
779    beq 7f
780    and ip, \inst, #0xf
781    lsr \inst, \inst, #4
782    add \arg_index, \arg_index, #1
783    b 8f
7847:
785    FETCH_B ip, 0, 1
786    and ip, ip, #0xf
7878:
788    GET_VREG_FLOAT \sreg, ip
789.endm
790
791// Puts the next int/long/object argument in the expected register,
792// fetching values based on a non-range invoke.
793// Uses ip.
794.macro LOOP_OVER_SHORTY_LOADING_GPRS gpr_reg, inst, shorty, arg_index, finished, if_long, is_r3
7951: // LOOP
796    ldrb ip, [\shorty], #1         // Load next character in shorty, and increment.
797    cmp ip, #0
798    beq \finished                   // if (ip == '\0') goto finished
799    cmp ip, #74                    // if (ip == 'J') goto FOUND_LONG
800    beq 2f
801    cmp ip, #70                    // if (ip == 'F') goto SKIP_FLOAT
802    beq 3f
803    cmp ip, #68                    // if (ip == 'D') goto SKIP_DOUBLE
804    beq 4f
805    cmp \arg_index, #4
806    beq 7f
807    and ip, \inst, #0xf
808    lsr \inst, \inst, #4
809    add \arg_index, \arg_index, #1
810    b 8f
8117:
812    FETCH_B ip, 0, 1
813    and ip, ip, #0xf
8148:
815    GET_VREG \gpr_reg, ip
816    b 5f
8172:  // FOUND_LONG
818    .if \is_r3
819    // Put back shorty and exit
820    sub \shorty, \shorty, #1
821    b 5f
822    .endif
823    and ip, \inst, #0xf
824    GET_VREG ip, ip
825    // The only one possible for non-range long is r2-r3
826    mov r2, ip
827    lsr \inst, \inst, #4
828    add \arg_index, \arg_index, #1
829    cmp \arg_index, #4
830    beq 9f
831    and ip, \inst, #0xf
832    lsr \inst, \inst, #4
833    b 10f
8349:
835    FETCH_B ip, 0, 1
836    and ip, ip, #0xf
83710:
838    GET_VREG ip, ip
839    // The only one possible for non-range long is r2-r3
840    mov r3, ip
841    add \arg_index, \arg_index, #1
842    b \if_long
8433:  // SKIP_FLOAT
844    lsr \inst, \inst, #4
845    add \arg_index, \arg_index, #1
846    b 1b
8474:  // SKIP_DOUBLE
848    lsr \inst, \inst, #8
849    add \arg_index, \arg_index, #2
850    b 1b
8515:
852.endm
853
854// Puts the next int/long/object argument in the expected stack slot,
855// fetching values based on a non-range invoke.
856// Uses ip as temporary.
857.macro LOOP_OVER_SHORTY_LOADING_INTs shorty, inst, arg_index, finished, is_string_init
8581: // LOOP
859    ldrb ip, [\shorty], #1         // Load next character in shorty, and increment.
860    cmp ip, #0
861    beq \finished                  // if (ip == '\0') goto finished
862    cmp ip, #74                    // if (ip == 'J') goto FOUND_LONG
863    beq 2f
864    cmp ip, #70                    // if (ip == 'F') goto SKIP_FLOAT
865    beq 3f
866    cmp ip, #68                    // if (ip == 'D') goto SKIP_DOUBLE
867    beq 4f
868    .if \is_string_init
869    cmp \arg_index, #4
870    .else
871    cmp \arg_index, #(4+1)         // +1 for ArtMethod
872    .endif
873    beq 7f
874    and ip, \inst, #0xf
875    lsr \inst, \inst, #4
876    b 8f
8777:
878    FETCH_B ip, 0, 1
879    and ip, ip, #0xf
8808:
881    GET_VREG ip, ip
882    str ip, [sp, \arg_index, lsl #2]
883    add \arg_index, \arg_index, #1
884    b 1b
8852:  // FOUND_LONG
886    and ip, \inst, #0xf
887    GET_VREG ip, ip
888    str ip, [sp, \arg_index, lsl #2]
889    lsr \inst, \inst, #4
890    add \arg_index, \arg_index, #1
891    .if \is_string_init
892    cmp \arg_index, #4
893    .else
894    cmp \arg_index, #(4+1)         // +1 for ArtMethod
895    .endif
896    beq 9f
897    and ip, \inst, #0xf
898    lsr \inst, \inst, #4
899    b 10f
9009:
901    FETCH_B ip, 0, 1
902    and ip, ip, #0xf
90310:
904    GET_VREG ip, ip
905    str ip, [sp, \arg_index, lsl #2]
906    add \arg_index, \arg_index, #1
907    b 1b
9083:  // SKIP_FLOAT
909    lsr \inst, \inst, #4
910    add \arg_index, \arg_index, #1
911    b 1b
9124:  // SKIP_DOUBLE
913    lsr \inst, \inst, #8
914    add \arg_index, \arg_index, #2
915    b 1b
916.endm
917
918.macro SETUP_RETURN_VALUE shorty
919   ldrb ip, [\shorty]
920   cmp ip, #68       // Test if result type char == 'D'.
921   beq 1f
922   cmp ip, #70       // Test if result type char == 'F'.
923   bne 2f
924   vmov r0, s0
925   b 2f
9261:
927   vmov r0, r1, d0
9282:
929.endm
930
931.macro GET_SHORTY_SLOW_PATH dest, is_interface
932   // Save all registers that can hold arguments in the fast path.
933   vpush {s0}
934   push {r0-r2}
935   .if \is_interface
936   ldr r0, [sp, #16]
937   FETCH r1, 1
938   bl NterpGetShortyFromMethodId
939   .else
940   bl NterpGetShorty
941   .endif
942   mov \dest, r0
943   pop {r0-r2}
944   vpop {s0}
945.endm
946
947.macro COMMON_INVOKE_NON_RANGE is_static=0, is_interface=0, suffix="", is_string_init=0, is_polymorphic=0, is_custom=0
948   .if \is_polymorphic
949   // We always go to compiled code for polymorphic calls.
950   .elseif \is_custom
951   // We always go to compiled code for custom calls.
952   .else
953     DO_ENTRY_POINT_CHECK .Lcall_compiled_code_\suffix, \suffix
954     GET_CODE_ITEM
955     .if \is_string_init
956     bl nterp_to_nterp_string_init_non_range
957     .elseif \is_static
958     bl nterp_to_nterp_static_non_range
959     .else
960     bl nterp_to_nterp_instance_non_range
961     .endif
962     b .Ldone_return_\suffix
963.Lfetch_nterp_\suffix:
964    .word   (.Lfetch_location_\suffix+8) - ExecuteNterpImpl
965   .endif
966
967.Lcall_compiled_code_\suffix:
968   .if \is_polymorphic
969   // No fast path for polymorphic calls.
970   .elseif \is_custom
971   // No fast path for custom calls.
972   .elseif \is_string_init
973   // No fast path for string.init.
974   .else
975     ldr ip, [r0, #ART_METHOD_ACCESS_FLAGS_OFFSET]
976     tst ip, #ART_METHOD_NTERP_INVOKE_FAST_PATH_FLAG
977     beq .Lfast_path_with_few_args_\suffix
978     FETCH_B rINST, 0, 1
979     .if \is_static
980     asrs lr, rINST, #4
981     beq .Linvoke_fast_path_\suffix
982     .else
983     asr lr, rINST, #4
984     cmp lr, #1
985     beq .Linvoke_fast_path_\suffix
986     .endif
987     FETCH ip, 2
988     cmp lr, #2
989     .if \is_static
990     blt .Lone_arg_fast_path_\suffix
991     .endif
992     beq .Ltwo_args_fast_path_\suffix
993     cmp lr, #4
994     blt .Lthree_args_fast_path_\suffix
995     beq .Lfour_args_fast_path_\suffix
996     and         rINST, rINST, #15
997     GET_VREG    rINST, rINST
998     str         rINST, [sp, #(4 + 4 * 4)]
999.Lfour_args_fast_path_\suffix:
1000     asr         rINST, ip, #12
1001     GET_VREG    rINST, rINST
1002     str         rINST, [sp, #(4 + 3 * 4)]
1003.Lthree_args_fast_path_\suffix:
1004     ubfx        rINST, ip, #8, #4
1005     GET_VREG    r3, rINST
1006.Ltwo_args_fast_path_\suffix:
1007     ubfx        rINST, ip, #4, #4
1008     GET_VREG    r2, rINST
1009.Lone_arg_fast_path_\suffix:
1010     .if \is_static
1011     and         rINST, ip, #0xf
1012     GET_VREG    r1, rINST
1013     .else
1014     // First argument already in r1.
1015     .endif
1016.Linvoke_fast_path_\suffix:
1017     .if \is_interface
1018     // Setup hidden argument.
1019     mov ip, r4
1020     .endif
1021     ldr lr, [r0, #ART_METHOD_QUICK_CODE_OFFSET_32]
1022     blx lr
1023     FETCH_ADVANCE_INST 3
1024     GET_INST_OPCODE ip
1025     GOTO_OPCODE ip
1026
1027.Lfast_path_with_few_args_\suffix:
1028     // Fast path when we have zero or one argument (modulo 'this'). If there
1029     // is one argument, we can put it in both floating point and core register.
1030     FETCH_B r2, 0, 1
1031     asr r2, r2, #4  // number of arguments
1032     .if \is_static
1033     cmp r2, #1
1034     blt .Linvoke_with_few_args_\suffix
1035     bne .Lget_shorty_\suffix
1036     FETCH r2, 2
1037     and r2, r2, #0xf  // dex register of first argument
1038     GET_VREG r1, r2
1039     vmov s0, r1
1040     .else
1041     cmp r2, #2
1042     blt .Linvoke_with_few_args_\suffix
1043     bne .Lget_shorty_\suffix
1044     FETCH r2, 2
1045     ubfx r2, r2, #4, #4  // dex register of second argument
1046     GET_VREG r2, r2
1047     vmov s0, r2
1048     .endif
1049.Linvoke_with_few_args_\suffix:
1050     // Check if the next instruction is move-result or move-result-wide.
1051     // If it is, we fetch the shorty and jump to the regular invocation.
1052     FETCH r3, 3
1053     and r3, r3, #0xfe
1054     cmp r3, #0x0a
1055     beq .Lget_shorty_and_invoke_\suffix
1056     .if \is_interface
1057     // Setup hidden argument.
1058     mov ip, r4
1059     .endif
1060     ldr lr, [r0, #ART_METHOD_QUICK_CODE_OFFSET_32]
1061     blx lr
1062     FETCH_ADVANCE_INST 3
1063     GET_INST_OPCODE ip
1064     GOTO_OPCODE ip
1065.Lget_shorty_and_invoke_\suffix:
1066     .if \is_interface
1067     // Save hidden argument.
1068     vmov s16, r4
1069     .endif
1070     GET_SHORTY_SLOW_PATH rINST, \is_interface
1071     b .Lgpr_setup_finished_\suffix
1072   .endif
1073
1074.Lget_shorty_\suffix:
1075   .if \is_interface
1076   // Save hidden argument.
1077   vmov s16, r4
1078   .endif
1079   GET_SHORTY rINST, \is_interface, \is_polymorphic, \is_custom
1080   // From this point:
1081   // - rINST contains shorty (in callee-save to switch over return value after call).
1082   // - r0 contains method
1083   // - r1 contains 'this' pointer for instance method.
1084   // We need three registers.
1085   add r3, rINST, #1  // shorty + 1  ; ie skip return arg character
1086   FETCH r2, 2 // arguments
1087   .if \is_string_init
1088   lsr r2, r2, #4
1089   mov r4, #1       // ignore first argument
1090   .elseif \is_static
1091   mov r4, #0      // arg_index
1092   .else
1093   lsr r2, r2, #4
1094   mov r4, #1       // ignore first argument
1095   .endif
1096   LOOP_OVER_SHORTY_LOADING_FPS d0, s0, r2, r3, r4, .Lxmm_setup_finished_\suffix, .Ld1_s2_\suffix
1097.Ld1_s1_\suffix:
1098   LOOP_OVER_SHORTY_LOADING_FPS d1, s1, r2, r3, r4, .Lxmm_setup_finished_\suffix, .Ld2_s1_\suffix
1099.Ld1_s2_\suffix:
1100   LOOP_OVER_SHORTY_LOADING_FPS d1, s2, r2, r3, r4, .Lxmm_setup_finished_\suffix, .Ls4_\suffix
1101.Ld2_s3_\suffix:
1102   LOOP_OVER_SHORTY_LOADING_FPS d2, s3, r2, r3, r4, .Lxmm_setup_finished_\suffix, .Lxmm_setup_finished_\suffix
1103   b .Ls4_\suffix
1104.Ld2_s1_\suffix:
1105   LOOP_OVER_SHORTY_LOADING_FPS d2, s1, r2, r3, r4, .Lxmm_setup_finished_\suffix, .Lxmm_setup_finished_\suffix
1106.Ls4_\suffix:
1107   // If we arrive here, we can only have a float.
1108   LOOP_OVER_SHORTY_LOADING_FPS d2, s4, r2, r3, r4, .Lxmm_setup_finished_\suffix, .Lxmm_setup_finished_\suffix
1109.Lxmm_setup_finished_\suffix:
1110   add r4, rINST, #1  // shorty + 1  ; ie skip return arg character
1111   FETCH r8, 2 // arguments
1112   .if \is_string_init
1113   lsr r8, r8, #4
1114   mov lr, #1       // ignore first argument
1115   LOOP_OVER_SHORTY_LOADING_GPRS r1, r8, r4, lr, .Lgpr_setup_finished_\suffix, .Lif_long_\suffix, is_r3=0
1116   .elseif \is_static
1117   mov lr, #0      // arg_index
1118   LOOP_OVER_SHORTY_LOADING_GPRS r1, r8, r4, lr, .Lgpr_setup_finished_\suffix, .Lif_long_\suffix, is_r3=0
1119   .else
1120   lsr r8, r8, #4
1121   mov lr, #1       // ignore first argument
1122   .endif
1123   LOOP_OVER_SHORTY_LOADING_GPRS r2, r8, r4, lr, .Lgpr_setup_finished_\suffix, .Lif_long_\suffix, is_r3=0
1124   LOOP_OVER_SHORTY_LOADING_GPRS r3, r8, r4, lr, .Lgpr_setup_finished_\suffix, .Lif_long_\suffix, is_r3=1
1125.Lif_long_\suffix:
1126   // Store in the outs array (stored above the ArtMethod in the stack). We only do this for non-string-init
1127   // calls as the index is already adjusted above.
1128   .if !\is_string_init
1129   add lr, lr, #1
1130   .endif
1131   LOOP_OVER_SHORTY_LOADING_INTs r4, r8, lr, .Lgpr_setup_finished_\suffix, \is_string_init
1132.Lgpr_setup_finished_\suffix:
1133   REFRESH_MARKING_REGISTER // r8 was used when setting parameters, restore it.
1134   .if \is_polymorphic
1135   bl art_quick_invoke_polymorphic
1136   .elseif \is_custom
1137   bl art_quick_invoke_custom
1138   .else
1139      .if \is_interface
1140      // Setup hidden argument.
1141      vmov ip, s16
1142      .endif
1143      ldr lr, [r0, #ART_METHOD_QUICK_CODE_OFFSET_32]
1144      blx lr
1145   .endif
1146   SETUP_RETURN_VALUE rINST
1147.Ldone_return_\suffix:
1148   /* resume execution of caller */
1149   .if \is_string_init
1150   FETCH ip, 2 // arguments
1151   and ip, ip, #0xf
1152   GET_VREG r1, ip
1153   UPDATE_REGISTERS_FOR_STRING_INIT r1, r0
1154   .endif
1155
1156   .if \is_polymorphic
1157   FETCH_ADVANCE_INST 4
1158   .else
1159   FETCH_ADVANCE_INST 3
1160   .endif
1161   GET_INST_OPCODE ip
1162   GOTO_OPCODE ip
1163.endm
1164
1165// Puts the next int/long/object argument in the expected register,
1166// fetching values based on a range invoke.
1167// Uses ip as temporary.
1168.macro LOOP_RANGE_OVER_SHORTY_LOADING_GPRS reg32, shorty, arg_index, stack_index, finished, if_long, is_r3
11691: // LOOP
1170    ldrb ip, [\shorty], #1         // Load next character in shorty, and increment.
1171    cmp ip, #0
1172    beq \finished                  // if (ip == '\0') goto finished
1173    cmp ip, #74                    // if (ip == 'J') goto FOUND_LONG
1174    beq 2f
1175    cmp ip, #70                    // if (ip == 'F') goto SKIP_FLOAT
1176    beq 3f
1177    cmp ip, #68                    // if (ip == 'D') goto SKIP_DOUBLE
1178    beq 4f
1179    GET_VREG \reg32, \arg_index
1180    add \arg_index, \arg_index, #1
1181    add \stack_index, \stack_index, #1
1182    b 5f
11832:  // FOUND_LONG
1184    .if \is_r3
1185    // Put back shorty and jump to \if_long
1186    sub \shorty, \shorty, #1
1187    .else
1188    GET_VREG r2, \arg_index
1189    add \arg_index, \arg_index, #1
1190    add \stack_index, \stack_index, #1
1191    GET_VREG r3, \arg_index
1192    add \arg_index, \arg_index, #1
1193    add \stack_index, \stack_index, #1
1194    .endif
1195    b \if_long
11963:  // SKIP_FLOAT
1197    add \arg_index, \arg_index, #1
1198    add \stack_index, \stack_index, #1
1199    b 1b
12004:  // SKIP_DOUBLE
1201    add \arg_index, \arg_index, #2
1202    add \stack_index, \stack_index, #2
1203    b 1b
12045:
1205.endm
1206
1207// Puts the next int/long/object argument in the expected stack slot,
1208// fetching values based on a range invoke.
1209// Uses ip as temporary.
1210.macro LOOP_RANGE_OVER_INTs shorty, arg_index, stack_index, finished
12111: // LOOP
1212    ldrb ip, [\shorty], #1         // Load next character in shorty, and increment.
1213    cmp ip, #0
1214    beq \finished                     // if (ip == '\0') goto finished
1215    cmp ip, #74                    // if (ip == 'J') goto FOUND_LONG
1216    beq 2f
1217    cmp ip, #70                    // if (ip == 'F') goto SKIP_FLOAT
1218    beq 3f
1219    cmp ip, #68                    // if (ip == 'D') goto SKIP_DOUBLE
1220    beq 4f
1221    GET_VREG ip, \arg_index
1222    str ip, [sp, \stack_index, lsl #2]
1223    add \arg_index, \arg_index, #1
1224    add \stack_index, \stack_index, #1
1225    b 1b
12262:  // FOUND_LONG
1227    GET_VREG ip, \arg_index
1228    str ip, [sp, \stack_index, lsl #2]
1229    add \arg_index, \arg_index, #1
1230    add \stack_index, \stack_index, #1
1231    GET_VREG ip, \arg_index
1232    str ip, [sp, \stack_index, lsl #2]
1233    add \arg_index, \arg_index, #1
1234    add \stack_index, \stack_index, #1
1235    b 1b
12363:  // SKIP_FLOAT
1237    add \arg_index, \arg_index, #1
1238    add \stack_index, \stack_index, #1
1239    b 1b
12404:  // SKIP_DOUBLE
1241    add \arg_index, \arg_index, #2
1242    add \stack_index, \stack_index, #2
1243    b 1b
1244.endm
1245
1246.macro COMMON_INVOKE_RANGE is_static=0, is_interface=0, suffix="", is_string_init=0, is_polymorphic=0, is_custom=0
1247   .if \is_polymorphic
1248   // We always go to compiled code for polymorphic calls.
1249   .elseif \is_custom
1250   // We always go to compiled code for custom calls.
1251   .else
1252     DO_ENTRY_POINT_CHECK .Lcall_compiled_code_range_\suffix, range_\suffix
1253     GET_CODE_ITEM
1254     .if \is_string_init
1255     bl nterp_to_nterp_string_init_range
1256     .elseif \is_static
1257     bl nterp_to_nterp_static_range
1258     .else
1259     bl nterp_to_nterp_instance_range
1260     .endif
1261     b .Ldone_return_range_\suffix
1262.Lfetch_nterp_range_\suffix:
1263    .word   (.Lfetch_location_range_\suffix+8) - ExecuteNterpImpl
1264   .endif
1265
1266.Lcall_compiled_code_range_\suffix:
1267   .if \is_polymorphic
1268   // No fast path for polymorphic calls.
1269   .elseif \is_custom
1270   // No fast path for custom calls.
1271   .elseif \is_string_init
1272   // No fast path for string.init.
1273   .else
1274     ldr ip, [r0, #ART_METHOD_ACCESS_FLAGS_OFFSET]
1275     tst ip, #ART_METHOD_NTERP_INVOKE_FAST_PATH_FLAG
1276     beq .Lfast_path_with_few_args_range_\suffix
1277     FETCH_B ip, 0, 1  // Number of arguments
1278     .if \is_static
1279     cmp ip, #0
1280     .else
1281     cmp ip, #1
1282     .endif
1283     beq .Linvoke_fast_path_range_\suffix
1284     FETCH lr, 2  // dex register of first argument
1285     add lr, rFP, lr, lsl #2  // location of first dex register value.
1286     .if \is_static
1287     cmp ip, #2
1288     blt .Lone_arg_fast_path_range_\suffix
1289     beq .Ltwo_args_fast_path_range_\suffix
1290     cmp ip, #3
1291     .else
1292     cmp ip, #3
1293     blt .Ltwo_args_fast_path_range_\suffix
1294     .endif
1295     beq .Lthree_args_fast_path_range_\suffix
1296     add rINST, sp, #4  // Add space for the ArtMethod
1297
1298.Lloop_over_fast_path_range_\suffix:
1299     sub ip, ip, #1
1300     ldr r3, [lr, ip, lsl #2]
1301     str r3, [rINST, ip, lsl #2]
1302     cmp ip, #3
1303     bne .Lloop_over_fast_path_range_\suffix
1304
1305.Lthree_args_fast_path_range_\suffix:
1306     ldr r3, [lr, #8]
1307.Ltwo_args_fast_path_range_\suffix:
1308     ldr r2, [lr, #4]
1309.Lone_arg_fast_path_range_\suffix:
1310     .if \is_static
1311     ldr r1, [lr, #0]
1312     .else
1313     // First argument already in r1.
1314     .endif
1315.Linvoke_fast_path_range_\suffix:
1316     .if \is_interface
1317     // Setup hidden argument.
1318     mov ip, r4
1319     .endif
1320     ldr lr, [r0, #ART_METHOD_QUICK_CODE_OFFSET_32]
1321     blx lr
1322     FETCH_ADVANCE_INST 3
1323     GET_INST_OPCODE ip
1324     GOTO_OPCODE ip
1325
1326.Lfast_path_with_few_args_range_\suffix:
1327     // Fast path when we have zero or one argument (modulo 'this'). If there
1328     // is one argument, we can put it in both floating point and core register.
1329     FETCH_B r2, 0, 1 // number of arguments
1330     .if \is_static
1331     cmp r2, #1
1332     blt .Linvoke_with_few_args_range_\suffix
1333     bne .Lget_shorty_range_\suffix
1334     FETCH r3, 2  // dex register of first argument
1335     GET_VREG r1, r3
1336     vmov s0, r1
1337     .else
1338     cmp r2, #2
1339     blt .Linvoke_with_few_args_range_\suffix
1340     bne .Lget_shorty_range_\suffix
1341     FETCH r3, 2  // dex register of first argument
1342     add r3, r3, #1  // Add 1 for next argument
1343     GET_VREG r2, r3
1344     vmov s0, r2
1345     .endif
1346.Linvoke_with_few_args_range_\suffix:
1347     // Check if the next instruction is move-result or move-result-wide.
1348     // If it is, we fetch the shorty and jump to the regular invocation.
1349     FETCH r3, 3
1350     and r3, r3, #0xfe
1351     cmp r3, #0x0a
1352     beq .Lget_shorty_and_invoke_range_\suffix
1353     .if \is_interface
1354     // Setup hidden argument.
1355     mov ip, r4
1356     .endif
1357     ldr lr, [r0, #ART_METHOD_QUICK_CODE_OFFSET_32]
1358     blx lr
1359     FETCH_ADVANCE_INST 3
1360     GET_INST_OPCODE ip
1361     GOTO_OPCODE ip
1362.Lget_shorty_and_invoke_range_\suffix:
1363     .if \is_interface
1364     // Save hidden argument.
1365     vmov s16, r4
1366     .endif
1367     GET_SHORTY_SLOW_PATH rINST, \is_interface
1368     b .Lgpr_setup_finished_range_\suffix
1369   .endif
1370
1371.Lget_shorty_range_\suffix:
1372   .if \is_interface
1373   // Save hidden argument.
1374   vmov s16, r4
1375   .endif
1376   GET_SHORTY rINST, \is_interface, \is_polymorphic, \is_custom
1377   // From this point:
1378   // - rINST contains shorty (in callee-save to switch over return value after call).
1379   // - r0 contains method
1380   // - r1 contains 'this' pointer for instance method.
1381   //
1382   // Save r0 and r1 before calling NterpSetupArm32Fprs.
1383   push {r0, r1}
1384   add r0, rINST, #1  // shorty + 1  ; ie skip return arg character
1385   FETCH r1, 2 // arguments
1386   .if \is_string_init
1387   add r1, r1, #1  // arg start index
1388   mov r2, #1       // index in stack
1389   .elseif \is_static
1390   mov r2, #0       // index in stack
1391   .else
1392   add r1, r1, #1  // arg start index
1393   mov r2, #1       // index in stack
1394   .endif
1395   vpush {s0-s15}
1396   mov r3, sp
1397   // Pass the stack address for arguments, +16 for fprs, +2 for saved registers,
1398   // +1 for ArtMethod.
1399   add lr, sp, #((16 + 2 + 1) * 4)
1400   push {rFP, lr}
1401   bl NterpSetupArm32Fprs
1402   add sp, sp, #8
1403   vpop {s0-s15}
1404   pop {r0, r1}
1405.Lxmm_setup_finished_range_\suffix:
1406   add r8, rINST, #1  // shorty + 1  ; ie skip return arg character
1407   FETCH lr, 2 // arguments
1408   .if \is_string_init
1409   add lr, lr, #1  // arg start index
1410   mov r4, #0      // index in stack
1411   LOOP_RANGE_OVER_SHORTY_LOADING_GPRS r1, r8, lr, r4, .Lgpr_setup_finished_range_\suffix, .Lif_long_range_\suffix, is_r3=0
1412   .elseif \is_static
1413   mov r4, #0      // index in stack
1414   LOOP_RANGE_OVER_SHORTY_LOADING_GPRS r1, r8, lr, r4, .Lgpr_setup_finished_range_\suffix, .Lif_long_range_\suffix, is_r3=0
1415   .else
1416   add lr, lr, #1  // arg start index
1417   mov r4, #1       // index in stack
1418   .endif
1419   LOOP_RANGE_OVER_SHORTY_LOADING_GPRS r2, r8, lr, r4, .Lgpr_setup_finished_range_\suffix, .Lif_long_range_\suffix, is_r3=0
1420   LOOP_RANGE_OVER_SHORTY_LOADING_GPRS r3, r8, lr, r4, .Lgpr_setup_finished_range_\suffix, .Lif_long_range_\suffix, is_r3=1
1421.Lif_long_range_\suffix:
1422   // Add 1 word for the ArtMethod stored before the outs.
1423   add r4, r4, #1
1424   LOOP_RANGE_OVER_INTs r8, lr, r4, .Lgpr_setup_finished_range_\suffix
1425.Lgpr_setup_finished_range_\suffix:
1426   REFRESH_MARKING_REGISTER // r8 was used when setting parameters, restore it.
1427   .if \is_polymorphic
1428   bl art_quick_invoke_polymorphic
1429   .elseif \is_custom
1430   bl art_quick_invoke_custom
1431   .else
1432      .if \is_interface
1433      // Setup hidden argument.
1434      vmov ip, s16
1435      .endif
1436      ldr lr, [r0, #ART_METHOD_QUICK_CODE_OFFSET_32]
1437      blx lr
1438   .endif
1439   SETUP_RETURN_VALUE rINST
1440.Ldone_return_range_\suffix:
1441   /* resume execution of caller */
1442   .if \is_string_init
1443   FETCH ip, 2 // arguments
1444   GET_VREG r1, ip
1445   UPDATE_REGISTERS_FOR_STRING_INIT r1, r0
1446   .endif
1447
1448   .if \is_polymorphic
1449    FETCH_ADVANCE_INST 4
1450   .else
1451   FETCH_ADVANCE_INST 3
1452   .endif
1453   GET_INST_OPCODE ip
1454   GOTO_OPCODE ip
1455.endm
1456
1457.macro WRITE_BARRIER_IF_OBJECT is_object, value, holder, label, tmp
1458   .if \is_object
1459   // In T32, we would use `SMART_CBZ \value, \label`
1460   cmp     \value, #0
1461   beq     \label
1462   ldr     ip, [rSELF, #THREAD_CARD_TABLE_OFFSET]
1463   lsr     \tmp, \holder, #CARD_TABLE_CARD_SHIFT
1464   strb    ip, [ip, \tmp]
1465\label:
1466   .endif
1467.endm
1468
1469.macro LDREXD_STREXD_LOOP addr, load1, load2, store1, store2, tmp, label
1470\label:
1471   ldrexd  \load1, \load2, [\addr]
1472   strexd  \tmp, \store1, \store2, [\addr]
1473   cmp     \tmp, #0
1474   bne     \label
1475.endm
1476
1477.macro ATOMIC_LOAD64 addr, load1, load2, tmp, label
1478   LDREXD_STREXD_LOOP \addr, \load1, \load2, \load1, \load2, \tmp, \label
1479.endm
1480
1481.macro ATOMIC_STORE64 addr, store1, store2, tmp1, tmp2, label
1482   LDREXD_STREXD_LOOP \addr, \tmp1, \tmp2, \store1, \store2, \tmp1, \label
1483.endm
1484
1485// Fetch some information from the thread cache.
1486// Uses ip and lr as temporaries.
1487.macro FETCH_FROM_THREAD_CACHE dest_reg, slow_path
1488   add      ip, rSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
1489   ubfx     lr, rPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
1490   add      ip, ip, lr, lsl #3             // entry address within the cache
1491   // In T32, we would use `ldrd ip, \dest_reg, [ip]`
1492   ldr      \dest_reg, [ip, #4]            // value (offset)
1493   ldr      ip, [ip]                       // entry key (pc)
1494   cmp      ip, rPC
1495   bne \slow_path
1496.endm
1497
1498// Puts the next int/long/object parameter passed in physical register
1499// in the expected dex register array entry, and in case of object in the
1500// expected reference array entry.
1501// Uses ip as temporary.
1502.macro LOOP_OVER_SHORTY_STORING_GPRS gpr_32, shorty, arg_offset, regs, refs, finished, if_long, is_r3
15031: // LOOP
1504    ldrb ip, [\shorty], #1       // Load next character in shorty, and increment.
1505    cmp ip, #0
1506    beq \finished            // if (ip == '\0') goto finished
1507    cmp ip, #74                  // if (ip == 'J') goto FOUND_LONG
1508    beq 2f
1509    cmp ip, #70                  // if (ip == 'F') goto SKIP_FLOAT
1510    beq 3f
1511    cmp ip, #68                  // if (ip == 'D') goto SKIP_DOUBLE
1512    beq 4f
1513    str \gpr_32, [\regs, \arg_offset]
1514    cmp ip, #76                  // if (ip != 'L') goto NOT_REFERENCE
1515    bne 6f
1516    str \gpr_32, [\refs, \arg_offset]
15176:  // NOT_REFERENCE
1518    add \arg_offset, \arg_offset, #4
1519    b 5f
15202:  // FOUND_LONG
1521    .if \is_r3
1522    // Put back shorty and jump to \if_long
1523    sub \shorty, \shorty, #1
1524    .else
1525    // A long can only be in r2, r3
1526    str r2, [\regs, \arg_offset]
1527    add \arg_offset, \arg_offset, #4
1528    str r3, [\regs, \arg_offset]
1529    add \arg_offset, \arg_offset, #4
1530    .endif
1531    b \if_long
15323:  // SKIP_FLOAT
1533    add \arg_offset, \arg_offset, #4
1534    b 1b
15354:  // SKIP_DOUBLE
1536    add \arg_offset, \arg_offset, #8
1537    b 1b
15385:
1539.endm
1540
1541// Puts the next int/long/object parameter passed in stack
1542// in the expected dex register array entry, and in case of object in the
1543// expected reference array entry.
1544.macro LOOP_OVER_INTs shorty, arg_offset, regs, refs, stack_ptr, tmp1, tmp2, finished
15451: // LOOP
1546    ldrb \tmp1, [\shorty], #1       // Load next character in shorty, and increment.
1547    cmp \tmp1, #0
1548    beq \finished                   // if (\tmp1 == '\0') goto finished
1549    cmp \tmp1, #74                  // if (\tmp1 == 'J') goto FOUND_LONG
1550    beq 2f
1551    cmp \tmp1, #70                  // if (\tmp1 == 'F') goto SKIP_FLOAT
1552    beq 3f
1553    cmp \tmp1, #68                  // if (\tmp1 == 'D') goto SKIP_DOUBLE
1554    beq 4f
1555    add \tmp2, \stack_ptr, \arg_offset
1556    ldr \tmp2, [\tmp2,  #OFFSET_TO_FIRST_ARGUMENT_IN_STACK]
1557    str \tmp2, [\regs, \arg_offset]
1558    cmp \tmp1, #76                  // if (\tmp1 != 'L') goto loop
1559    bne 3f
1560    str \tmp2, [\refs, \arg_offset]
1561    add \arg_offset, \arg_offset, #4
1562    b 1b
15632:  // FOUND_LONG
1564    add \tmp1, \stack_ptr, \arg_offset
1565    ldr \tmp1, [\tmp1,  #OFFSET_TO_FIRST_ARGUMENT_IN_STACK]
1566    str \tmp1, [\regs, \arg_offset]
1567    add \arg_offset, \arg_offset, #4
1568    add \tmp1, \stack_ptr, \arg_offset
1569    ldr \tmp1, [\tmp1,  #OFFSET_TO_FIRST_ARGUMENT_IN_STACK]
1570    str \tmp1, [\regs, \arg_offset]
1571    add \arg_offset, \arg_offset, #4
1572    b 1b
15733:  // SKIP_FLOAT
1574    add \arg_offset, \arg_offset, #4
1575    b 1b
15764:  // SKIP_DOUBLE
1577    add \arg_offset, \arg_offset, #8
1578    b 1b
1579.endm
1580
1581.macro SETUP_REFERENCE_PARAMETER_IN_GPR gpr32, regs, refs, ins, arg_offset, finished
1582    str \gpr32, [\regs, \arg_offset]
1583    subs \ins, \ins, #1
1584    str \gpr32, [\refs, \arg_offset]
1585    add \arg_offset, \arg_offset, #4
1586    beq \finished
1587.endm
1588
1589.macro SETUP_REFERENCE_PARAMETERS_IN_STACK regs, refs, ins, stack_ptr, arg_offset
15901:
1591    ldr ip, [\stack_ptr, \arg_offset]
1592    subs \ins, \ins, #1
1593    str ip, [\regs, \arg_offset]
1594    str ip, [\refs, \arg_offset]
1595    add \arg_offset, \arg_offset, #4
1596    bne 1b
1597.endm
1598
1599%def entry():
1600/*
1601 * ArtMethod entry point.
1602 *
1603 * On entry:
1604 *  r0   ArtMethod* callee
1605 *  rest  method parameters
1606 */
1607
1608OAT_ENTRY ExecuteNterpImpl, EndExecuteNterpImpl
1609    .cfi_startproc
1610    sub ip, sp, #STACK_OVERFLOW_RESERVED_BYTES
1611    ldr ip, [ip]
1612    /* Spill callee save regs */
1613    SPILL_ALL_CALLEE_SAVES
1614
1615    ldr rPC, [r0, #ART_METHOD_DATA_OFFSET_32]
1616
1617    // Setup the stack for executing the method.
1618    SETUP_STACK_FRAME rPC, rREFS, rFP, CFI_REFS, load_ins=1
1619
1620    // Setup the parameters
1621    cmp r4, #0
1622    beq .Lxmm_setup_finished
1623
1624    sub rINST, rINST, r4
1625    ldr r8, [r0, #ART_METHOD_ACCESS_FLAGS_OFFSET]
1626    lsl rINST, rINST, #2 // rINST is now the offset for inputs into the registers array.
1627    mov rIBASE, ip // rIBASE contains the old stack pointer
1628
1629    tst r8, #ART_METHOD_NTERP_ENTRY_POINT_FAST_PATH_FLAG
1630    beq .Lsetup_slow_path
1631    // Setup pointer to inputs in FP and pointer to inputs in REFS
1632    add lr, rFP, rINST
1633    add r8, rREFS, rINST
1634    mov r0, #0
1635    SETUP_REFERENCE_PARAMETER_IN_GPR r1, lr, r8, r4, r0, .Lxmm_setup_finished
1636    SETUP_REFERENCE_PARAMETER_IN_GPR r2, lr, r8, r4, r0, .Lxmm_setup_finished
1637    SETUP_REFERENCE_PARAMETER_IN_GPR r3, lr, r8, r4, r0, .Lxmm_setup_finished
1638    add rIBASE, rIBASE, #OFFSET_TO_FIRST_ARGUMENT_IN_STACK
1639    SETUP_REFERENCE_PARAMETERS_IN_STACK lr, r8, r4, rIBASE, r0
1640    b .Lxmm_setup_finished
1641
1642.Lsetup_slow_path:
1643    // If the method is not static and there is one argument ('this'), we don't need to fetch the
1644    // shorty.
1645    tst r8, #ART_METHOD_IS_STATIC_FLAG
1646    bne .Lsetup_with_shorty
1647    str r1, [rFP, rINST]
1648    str r1, [rREFS, rINST]
1649    cmp r4, #1
1650    beq .Lxmm_setup_finished
1651
1652.Lsetup_with_shorty:
1653    // Save arguments that were passed before calling into the runtime.
1654    // No need to save r0 (ArtMethod) as we're not using it later in this code.
1655    // Save r4 for stack aligment.
1656    // TODO: Get shorty in a better way and remove below
1657    push {r1-r4}
1658    vpush {s0-s15}
1659    bl NterpGetShorty
1660    vpop {s0-s15}
1661    pop {r1-r4}
1662
1663    mov ip, r8
1664    add r8, rREFS, rINST
1665    add r7, rFP, rINST
1666    mov r4, #0
1667    // Setup shorty, pointer to inputs in FP and pointer to inputs in REFS
1668    add lr, r0, #1  // shorty + 1  ; ie skip return arg character
1669    tst ip, #ART_METHOD_IS_STATIC_FLAG
1670    bne .Lhandle_static_method
1671    add r7, r7, #4
1672    add r8, r8, #4
1673    add rIBASE, rIBASE, #4
1674    b .Lcontinue_setup_gprs
1675.Lhandle_static_method:
1676    LOOP_OVER_SHORTY_STORING_GPRS r1, lr, r4, r7, r8, .Lgpr_setup_finished, .Lif_long, is_r3=0
1677.Lcontinue_setup_gprs:
1678    LOOP_OVER_SHORTY_STORING_GPRS r2, lr, r4, r7, r8, .Lgpr_setup_finished, .Lif_long, is_r3=0
1679    LOOP_OVER_SHORTY_STORING_GPRS r3, lr, r4, r7, r8, .Lgpr_setup_finished, .Lif_long, is_r3=1
1680.Lif_long:
1681    LOOP_OVER_INTs lr, r4, r7, r8, rIBASE, ip, r1, .Lgpr_setup_finished
1682.Lgpr_setup_finished:
1683    add r0, r0, #1  // shorty + 1  ; ie skip return arg character
1684    mov r1, r7
1685    add r2, rIBASE, #OFFSET_TO_FIRST_ARGUMENT_IN_STACK
1686    vpush {s0-s15}
1687    mov r3, sp
1688    bl NterpStoreArm32Fprs
1689    add sp, sp, #(16 * 4)
1690.Lxmm_setup_finished:
1691    CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0)
1692    // r8 was used for setting up the frame, restore it now.
1693    REFRESH_MARKING_REGISTER
1694.Lexecute_instructions:
1695    // Set rIBASE
1696    adr rIBASE, artNterpAsmInstructionStart
1697    /* start executing the instruction at rPC */
1698    START_EXECUTING_INSTRUCTIONS
1699    /* NOTE: no fallthrough */
1700    // cfi info continues, and covers the whole nterp implementation.
1701    SIZE ExecuteNterpImpl
1702
1703%def opcode_pre():
1704
1705%def helpers():
1706
1707%def footer():
1708/*
1709 * ===========================================================================
1710 *  Common subroutines and data
1711 * ===========================================================================
1712 */
1713
1714    .text
1715    .align  2
1716
1717// Enclose all code below in a symbol (which gets printed in backtraces).
1718NAME_START nterp_helper
1719
1720// Note: mterp also uses the common_* names below for helpers, but that's OK
1721// as the assembler compiled each interpreter separately.
1722common_errDivideByZero:
1723    EXPORT_PC
1724    bl art_quick_throw_div_zero
1725
1726// Expect index in r1, length in r3
1727common_errArrayIndex:
1728    EXPORT_PC
1729    mov r0, r1
1730    mov r1, r3
1731    bl art_quick_throw_array_bounds
1732
1733common_errNullObject:
1734    EXPORT_PC
1735    bl art_quick_throw_null_pointer_exception
1736
1737NterpCommonInvokeStatic:
1738    COMMON_INVOKE_NON_RANGE is_static=1, suffix="invokeStatic"
1739
1740NterpCommonInvokeStaticRange:
1741    COMMON_INVOKE_RANGE is_static=1, suffix="invokeStatic"
1742
1743NterpCommonInvokeInstance:
1744    COMMON_INVOKE_NON_RANGE suffix="invokeInstance"
1745
1746NterpCommonInvokeInstanceRange:
1747    COMMON_INVOKE_RANGE suffix="invokeInstance"
1748
1749NterpCommonInvokeInterface:
1750    COMMON_INVOKE_NON_RANGE is_interface=1, suffix="invokeInterface"
1751
1752NterpCommonInvokeInterfaceRange:
1753    COMMON_INVOKE_RANGE is_interface=1, suffix="invokeInterface"
1754
1755NterpCommonInvokePolymorphic:
1756    COMMON_INVOKE_NON_RANGE is_polymorphic=1, suffix="invokePolymorphic"
1757
1758NterpCommonInvokePolymorphicRange:
1759    COMMON_INVOKE_RANGE is_polymorphic=1, suffix="invokePolymorphic"
1760
1761NterpCommonInvokeCustom:
1762    COMMON_INVOKE_NON_RANGE is_static=1, is_custom=1, suffix="invokeCustom"
1763
1764NterpCommonInvokeCustomRange:
1765    COMMON_INVOKE_RANGE is_static=1, is_custom=1, suffix="invokeCustom"
1766
1767NterpHandleStringInit:
1768   COMMON_INVOKE_NON_RANGE is_string_init=1, suffix="stringInit"
1769
1770NterpHandleStringInitRange:
1771   COMMON_INVOKE_RANGE is_string_init=1, suffix="stringInit"
1772
1773NterpNewArray:
1774   /* new-array vA, vB, class@CCCC */
1775   EXPORT_PC
1776   // Fast-path which gets the class from thread-local cache.
1777   FETCH_FROM_THREAD_CACHE r0, 2f
1778   cmp rMR, #0
1779   bne 3f
17801:
1781   lsr     r1, rINST, #12              // r1<- B
1782   GET_VREG r1, r1                     // r1<- vB (array length)
1783   ldr lr, [rSELF, #THREAD_ALLOC_ARRAY_ENTRYPOINT_OFFSET]
1784   blx lr
1785   ubfx    r1, rINST, #8, #4           // r1<- A
1786   SET_VREG_OBJECT r0, r1
1787   FETCH_ADVANCE_INST 2
1788   GET_INST_OPCODE ip
1789   GOTO_OPCODE ip
17902:
1791   mov r0, rSELF
1792   ldr r1, [sp]
1793   mov r2, rPC
1794   bl nterp_get_class_or_allocate_object
1795   b 1b
17963:
1797   bl art_quick_read_barrier_mark_reg00
1798   b 1b
1799
1800
1801NterpHandleHotnessOverflow:
1802    add r1, rPC, rINST, lsl #1
1803    mov r2, rFP
1804    bl nterp_hot_method
1805    cmp r0, #0
1806    bne 1f
1807    add r2, rINST, rINST                // w2<- byte offset
1808    FETCH_ADVANCE_INST_RB r2            // update rPC, load rINST
1809    GET_INST_OPCODE ip                  // extract opcode from rINST
1810    GOTO_OPCODE ip                      // jump to next instruction
18111:
1812    // Drop the current frame.
1813    ldr ip, [rREFS, #-4]
1814    mov sp, ip
1815    .cfi_def_cfa sp, CALLEE_SAVES_SIZE
1816
1817    // The transition frame of type SaveAllCalleeSaves saves r4, r8, and r9,
1818    // but not managed ABI. So we need to restore callee-saves of the nterp frame,
1819    // and save managed ABI callee saves, which will be restored by the callee upon
1820    // return.
1821
1822    RESTORE_ALL_CALLEE_SAVES
1823    push {r5-r7, r10-r11, lr}
1824   .cfi_adjust_cfa_offset 24
1825   .cfi_rel_offset r5, 0
1826   .cfi_rel_offset r6, 4
1827   .cfi_rel_offset r7, 8
1828   .cfi_rel_offset r10, 12
1829   .cfi_rel_offset r11, 16
1830   .cfi_rel_offset lr, 20
1831    vpush {s16-s31}
1832    .cfi_adjust_cfa_offset 64
1833
1834    // Setup the new frame
1835    ldr r1, [r0, #OSR_DATA_FRAME_SIZE]
1836    // Given stack size contains all callee saved registers, remove them.
1837    sub r1, r1, #(CALLEE_SAVES_SIZE - 12)
1838
1839    // We know r1 cannot be 0, as it at least contains the ArtMethod.
1840
1841    // Remember CFA in a callee-save register.
1842    mov rINST, sp
1843    .cfi_def_cfa_register rINST
1844
1845    sub sp, sp, r1
1846
1847    add r2, r0, #OSR_DATA_MEMORY
18482:
1849    sub r1, r1, #4
1850    ldr ip, [r2, r1]
1851    str ip, [sp, r1]
1852    cmp r1, #0
1853    bne 2b
1854
1855    // Fetch the native PC to jump to and save it in a callee-save register.
1856    ldr rFP, [r0, #OSR_DATA_NATIVE_PC]
1857
1858    // Free the memory holding OSR Data.
1859    bl free
1860
1861    // Jump to the compiled code.
1862    bx rFP
1863// This is the logical end of ExecuteNterpImpl, where the frame info applies.
1864// EndExecuteNterpImpl includes the methods below as we want the runtime to
1865// see them as part of the Nterp PCs.
1866.cfi_endproc
1867
1868nterp_to_nterp_static_non_range:
1869    .cfi_startproc
1870    SETUP_STACK_FOR_INVOKE
1871    SETUP_NON_RANGE_ARGUMENTS_AND_EXECUTE is_static=1, is_string_init=0
1872    .cfi_endproc
1873
1874nterp_to_nterp_string_init_non_range:
1875    .cfi_startproc
1876    SETUP_STACK_FOR_INVOKE
1877    SETUP_NON_RANGE_ARGUMENTS_AND_EXECUTE is_static=0, is_string_init=1
1878    .cfi_endproc
1879
1880nterp_to_nterp_instance_non_range:
1881    .cfi_startproc
1882    SETUP_STACK_FOR_INVOKE
1883    SETUP_NON_RANGE_ARGUMENTS_AND_EXECUTE is_static=0, is_string_init=0
1884    .cfi_endproc
1885
1886nterp_to_nterp_static_range:
1887    .cfi_startproc
1888    SETUP_STACK_FOR_INVOKE
1889    SETUP_RANGE_ARGUMENTS_AND_EXECUTE is_static=1, is_string_init=0
1890    .cfi_endproc
1891
1892nterp_to_nterp_string_init_range:
1893    .cfi_startproc
1894    SETUP_STACK_FOR_INVOKE
1895    SETUP_RANGE_ARGUMENTS_AND_EXECUTE is_static=0, is_string_init=1
1896    .cfi_endproc
1897
1898nterp_to_nterp_instance_range:
1899    .cfi_startproc
1900    SETUP_STACK_FOR_INVOKE
1901    SETUP_RANGE_ARGUMENTS_AND_EXECUTE is_static=0, is_string_init=0
1902    .cfi_endproc
1903
1904NAME_END nterp_helper
1905
1906// This is the end of PCs contained by the OatQuickMethodHeader created for the interpreter
1907// entry point.
1908    .type EndExecuteNterpImpl, #function
1909    .hidden EndExecuteNterpImpl
1910    .global EndExecuteNterpImpl
1911EndExecuteNterpImpl:
1912
1913/*
1914 * Convert the double in r0/r1 to a long in r0/r1.
1915 *
1916 * We have to clip values to long min/max per the specification.  The
1917 * expected common case is a "reasonable" value that converts directly
1918 * to modest integer.  The EABI convert function isn't doing this for us.
1919 */
1920nterp_d2l_doconv:
1921    ubfx    r2, r1, #20, #11            @ grab the exponent
1922    movw    r3, #0x43e
1923    cmp     r2, r3                      @ MINLONG < x > MAXLONG?
1924    bhs     d2l_special_cases
1925    b       __aeabi_d2lz                @ tail call to convert double to long
1926d2l_special_cases:
1927    movw    r3, #0x7ff
1928    cmp     r2, r3
1929    beq     d2l_maybeNaN                @ NaN?
1930d2l_notNaN:
1931    adds    r1, r1, r1                  @ sign bit to carry
1932    mov     r0, #0xffffffff             @ assume maxlong for lsw
1933    mov     r1, #0x7fffffff             @ assume maxlong for msw
1934    adc     r0, r0, #0
1935    adc     r1, r1, #0                  @ convert maxlong to minlong if exp negative
1936    bx      lr                          @ return
1937d2l_maybeNaN:
1938    orrs    r3, r0, r1, lsl #12
1939    beq     d2l_notNaN                  @ if fraction is non-zero, it's a NaN
1940    mov     r0, #0
1941    mov     r1, #0
1942    bx      lr                          @ return 0 for NaN
1943
1944/*
1945 * Convert the float in r0 to a long in r0/r1.
1946 *
1947 * We have to clip values to long min/max per the specification.  The
1948 * expected common case is a "reasonable" value that converts directly
1949 * to modest integer.  The EABI convert function isn't doing this for us.
1950 */
1951nterp_f2l_doconv:
1952    ubfx    r2, r0, #23, #8             @ grab the exponent
1953    cmp     r2, #0xbe                   @ MININT < x > MAXINT?
1954    bhs     f2l_special_cases
1955    b       __aeabi_f2lz                @ tail call to convert float to long
1956f2l_special_cases:
1957    cmp     r2, #0xff                   @ NaN or infinity?
1958    beq     f2l_maybeNaN
1959f2l_notNaN:
1960    adds    r0, r0, r0                  @ sign bit to carry
1961    mov     r0, #0xffffffff             @ assume maxlong for lsw
1962    mov     r1, #0x7fffffff             @ assume maxlong for msw
1963    adc     r0, r0, #0
1964    adc     r1, r1, #0                  @ convert maxlong to minlong if exp negative
1965    bx      lr                          @ return
1966f2l_maybeNaN:
1967    lsls    r3, r0, #9
1968    beq     f2l_notNaN                  @ if fraction is non-zero, it's a NaN
1969    mov     r0, #0
1970    mov     r1, #0
1971    bx      lr                          @ return 0 for NaN
1972
1973// Entrypoints into runtime.
1974NTERP_TRAMPOLINE nterp_get_static_field, NterpGetStaticField
1975NTERP_TRAMPOLINE nterp_get_instance_field_offset, NterpGetInstanceFieldOffset
1976NTERP_TRAMPOLINE nterp_filled_new_array, NterpFilledNewArray
1977NTERP_TRAMPOLINE nterp_filled_new_array_range, NterpFilledNewArrayRange
1978NTERP_TRAMPOLINE nterp_get_class_or_allocate_object, NterpGetClassOrAllocateObject
1979NTERP_TRAMPOLINE nterp_get_method, NterpGetMethod
1980NTERP_TRAMPOLINE nterp_hot_method, NterpHotMethod
1981NTERP_TRAMPOLINE nterp_load_object, NterpLoadObject
1982
1983// gen_mterp.py will inline the following definitions
1984// within [ExecuteNterpImpl, EndExecuteNterpImpl).
1985%def instruction_end():
1986
1987    .type artNterpAsmInstructionEnd, #object
1988    .hidden artNterpAsmInstructionEnd
1989    .global artNterpAsmInstructionEnd
1990artNterpAsmInstructionEnd:
1991    // artNterpAsmInstructionEnd is used as landing pad for exception handling.
1992    FETCH_INST
1993    GET_INST_OPCODE ip
1994    GOTO_OPCODE ip
1995
1996%def instruction_start():
1997
1998    .type artNterpAsmInstructionStart, #object
1999    .hidden artNterpAsmInstructionStart
2000    .global artNterpAsmInstructionStart
2001artNterpAsmInstructionStart = .L_op_nop
2002    .text
2003
2004%def default_helper_prefix():
2005%  return "nterp_"
2006
2007%def opcode_start():
2008    NAME_START nterp_${opcode}
2009%def opcode_end():
2010    NAME_END nterp_${opcode}
2011%def helper_start(name):
2012    NAME_START ${name}
2013%def helper_end(name):
2014    NAME_END ${name}
2015