xref: /aosp_15_r20/art/runtime/interpreter/mterp/armng/main.S (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
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 for nterp.
245.macro OAT_ENTRY name
246    .arm
247    .type \name, #function
248    .hidden \name
249    .global \name
250    .balign 16
251\name:
252.endm
253
254.macro SIZE name
255    .size \name, .-\name
256.endm
257
258.macro NAME_START name
259    .arm
260    .type \name, #function
261    .hidden \name  // Hide this as a global symbol, so we do not incur plt calls.
262    .global \name
263    /* Cache alignment for function entry */
264    .balign 16
265\name:
266.endm
267
268.macro NAME_END name
269  SIZE \name
270.endm
271
272// Macro for defining entrypoints into runtime. We don't need to save registers
273// (we're not holding references there), but there is no
274// kDontSave runtime method. So just use the kSaveRefsOnly runtime method.
275.macro NTERP_TRAMPOLINE name, helper
276ENTRY \name
277  SETUP_SAVE_REFS_ONLY_FRAME ip
278  bl \helper
279  RESTORE_SAVE_REFS_ONLY_FRAME
280  REFRESH_MARKING_REGISTER
281  ldr ip, [rSELF, #THREAD_EXCEPTION_OFFSET]  @ Get exception field.
282  cmp ip, #0
283  bne nterp_deliver_pending_exception
284  bx lr
285END \name
286.endm
287
288.macro CLEAR_STATIC_VOLATILE_MARKER reg
289  and \reg, \reg, #-2
290.endm
291
292.macro CLEAR_INSTANCE_VOLATILE_MARKER reg
293  rsb \reg, \reg, #0
294.endm
295
296.macro EXPORT_PC
297    str    rPC, [rREFS, #-8]
298.endm
299
300.macro BRANCH
301    add rPC, rPC, rINST, lsl #1
302    // Update method counter and do a suspend check if the branch is negative or zero.
303    cmp rINST, #0
304    ble 2f
3051:
306    FETCH_INST                          // load rINST
307    GET_INST_OPCODE ip                  // extract opcode from rINST
308    GOTO_OPCODE ip                      // jump to next instruction
3092:
310    ldr r0, [sp]
311    ldrh r2, [r0, #ART_METHOD_HOTNESS_COUNT_OFFSET]
312    cmp r2, #NTERP_HOTNESS_VALUE
313    beq NterpHandleHotnessOverflow
314    add r2, r2, #-1
315    strh r2, [r0, #ART_METHOD_HOTNESS_COUNT_OFFSET]
316    DO_SUSPEND_CHECK continue_label=1b
317    b 1b
318.endm
319
320.macro TEST_IF_MARKING label
321    cmp rMR, #0
322    bne \label
323.endm
324
325// Expects:
326// - ip and lr to be available.
327// Outputs:
328// - \registers contains the dex registers size
329// - \outs contains the outs size
330// - if load_ins is 1, \ins contains the ins
331// - \code_item is replaced with a pointer to the instructions
332.macro FETCH_CODE_ITEM_INFO code_item, registers, outs, ins, load_ins
333    // Fetch dex register size.
334    ldrh \registers, [\code_item, #CODE_ITEM_REGISTERS_SIZE_OFFSET]
335    // Fetch outs size.
336    ldrh \outs, [\code_item, #CODE_ITEM_OUTS_SIZE_OFFSET]
337    .if \load_ins
338    ldrh \ins, [\code_item, #CODE_ITEM_INS_SIZE_OFFSET]
339    .endif
340    add \code_item, \code_item, #CODE_ITEM_INSNS_OFFSET
341.endm
342
343// Setup the stack to start executing the method. Expects:
344// - r0 to contain the ArtMethod
345// - \code_item to already contain the code item
346// - rINST, ip, lr to be available
347//
348// Outputs
349// - rINST contains the dex registers size
350// - ip contains the old stack pointer.
351// - \code_item is replaced with a pointer to the instructions
352// - if load_ins is 1, r4 contains the ins
353//
354.macro SETUP_STACK_FRAME code_item, refs, fp, cfi_refs, load_ins
355    FETCH_CODE_ITEM_INFO \code_item, rINST, \refs, r4, \load_ins
356
357    // Compute required frame size: ((2 * rINST) + \refs) * 4 + 12
358    // 12 is for saving the previous frame, pc, and method being executed.
359    add ip, \refs, rINST, lsl #1
360
361    // Compute new stack pointer in lr
362    sub lr, sp, #12
363    sub lr, lr, ip, lsl #2
364    // Alignment
365    and lr, lr, #-16
366
367    // Set reference and dex registers.
368    add \refs, lr, \refs, lsl #2
369    add \refs, \refs, #12
370    add \fp, \refs, rINST, lsl #2
371
372    // Now setup the stack pointer.
373    mov ip, sp
374    .cfi_def_cfa_register ip
375    mov sp, lr
376    str ip, [\refs, #-4]
377    CFI_DEF_CFA_BREG_PLUS_UCONST \cfi_refs, -4, CALLEE_SAVES_SIZE
378
379    // Save the ArtMethod, and use r0 as a temporary.
380    str r0, [sp]
381
382    // Put nulls in reference frame.
383    cmp rINST, #0
384    beq 2f
385    mov lr, \refs
386    mov r0, #0
3871:
388    str r0, [lr], #4
389    str r0, [lr], #4  // May clear vreg[0].
390    cmp lr, \fp
391    blo 1b
3922:
393    ldr r0, [sp]  // Reload the ArtMethod, expected by the callers.
394.endm
395
396// Increase method hotness and do suspend check before starting executing the method.
397.macro START_EXECUTING_INSTRUCTIONS
398    ldr r0, [sp]
399    ldrh r2, [r0, #ART_METHOD_HOTNESS_COUNT_OFFSET]
400    cmp r2, #NTERP_HOTNESS_VALUE
401    beq 3f
402    add r2, r2, #-1
403    strh r2, [r0, #ART_METHOD_HOTNESS_COUNT_OFFSET]
4041:
405    DO_SUSPEND_CHECK continue_label=2f
4062:
407    FETCH_INST
408    GET_INST_OPCODE ip
409    GOTO_OPCODE ip
4103:
411    CHECK_AND_UPDATE_SHARED_MEMORY_METHOD if_hot=4f, if_not_hot=1b
4124:
413    mov r1, #0
414    mov r2, rFP
415    bl nterp_hot_method
416    b 2b
417.endm
418
419.macro SPILL_ALL_CALLEE_SAVES
420    SPILL_ALL_CALLEE_SAVE_GPRS                    @ 9 words (36 bytes) of callee saves.
421    vpush {s16-s31}                               @ 16 words (64 bytes) of floats.
422    .cfi_adjust_cfa_offset 64
423.endm
424
425.macro RESTORE_ALL_CALLEE_SAVES lr_to_pc=0
426    vpop {s16-s31}
427    .cfi_adjust_cfa_offset -64
428    pop {r4-r7}
429    .cfi_adjust_cfa_offset -16
430    .cfi_restore r4
431    .cfi_restore r5
432    .cfi_restore r6
433    .cfi_restore r7
434    // Don't restore r8, the marking register gets updated when coming back from runtime.
435    add sp, sp, #4
436    .cfi_adjust_cfa_offset -4
437    .if \lr_to_pc
438    pop {r9-r11, pc}  @ 9 words of callee saves and args.
439    .cfi_adjust_cfa_offset -16
440    .else
441    pop {r9-r11, lr}  @ 9 words of callee saves and args.
442    .cfi_adjust_cfa_offset -16
443    .cfi_restore r9
444    .cfi_restore r10
445    .cfi_restore r11
446    .cfi_restore lr
447    .endif
448.endm
449
450// Helper to setup the stack after doing a nterp to nterp call. This will setup:
451// - rNEW_FP: the new pointer to dex registers
452// - rNEW_REFS: the new pointer to references
453// - rPC: the new PC pointer to execute
454// - r2: value in instruction to decode the number of arguments.
455// - r3: first dex register for range invokes, up to 4 arguments for non-range invokes.
456// - r4: top of dex register array
457//
458// The method expects:
459// - r0 to contain the ArtMethod
460// - r4 to contain the code item
461.macro SETUP_STACK_FOR_INVOKE
462   // We do the same stack overflow check as the compiler. See CanMethodUseNterp
463   // in how we limit the maximum nterp frame size.
464   sub ip, sp, #STACK_OVERFLOW_RESERVED_BYTES
465   ldr ip, [ip]
466
467   // Spill all callee saves to have a consistent stack frame whether we
468   // are called by compiled code or nterp.
469   SPILL_ALL_CALLEE_SAVES
470
471   // Setup the frame.
472   SETUP_STACK_FRAME r4, rNEW_REFS, rNEW_FP, CFI_NEW_REFS, load_ins=0
473
474   // Fetch instruction information before replacing rPC.
475   FETCH_B r2, 0, 1
476   FETCH r3, 2
477
478   // Set the dex pc pointer.
479   mov rPC, r4
480
481   // Make r4 point to the top of the dex register array.
482   add r4, rNEW_FP, rINST, lsl #2
483
484   CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0)
485.endm
486
487// Setup arguments based on a non-range nterp to nterp call, and start executing
488// the method. We expect:
489// - rNEW_FP: the new pointer to dex registers
490// - rPC: the new PC pointer to execute
491// - r2: number of arguments (bits 4-7), 5th argument if any (bits 0-3)
492// - r3: up to four dex register arguments
493// - r4: top of dex register array
494// - r1: receiver if non-static.
495//
496// Uses r0 and rINST as temporaries.
497.macro SETUP_NON_RANGE_ARGUMENTS_AND_EXECUTE is_static=0, is_string_init=0
498   // /* op vA, vB, {vC...vG} */
499   .if \is_static
500   asrs   r0, r2, #4
501   beq    6f
502   .else
503   asr    r0, r2, #4
504   .endif
505   mov rINST, #-4
506   cmp r0, #2
507   blt 1f
508   beq 2f
509   cmp r0, #4
510   blt 3f
511   beq 4f
512
513  // We use a decrementing rINST to store references relative
514  // to rNEW_FP and dex registers relative to r4
515  //
516  // TODO: We could set up rINST as the number of registers (this can be an additional output from
517  // SETUP_STACK_FOR_INVOKE) and then just decrement it by one before copying each arg.
518  // Maybe even introduce macros NEW_VREG_ADDRESS/NEW_VREG_REF_ADDRESS.
5195:
520   and         r2, r2, #15
521   GET_VREG_OBJECT r0, r2
522   str         r0, [rNEW_FP, rINST]
523   GET_VREG    r0, r2
524   str         r0, [r4, rINST]
525   sub         rINST, rINST, #4
5264:
527   asr         r2, r3, #12
528   GET_VREG_OBJECT r0, r2
529   str         r0, [rNEW_FP, rINST]
530   GET_VREG    r0, r2
531   str         r0, [r4, rINST]
532   sub         rINST, rINST, #4
5333:
534   ubfx        r2, r3, #8, #4
535   GET_VREG_OBJECT r0, r2
536   str         r0, [rNEW_FP, rINST]
537   GET_VREG    r0, r2
538   str         r0, [r4, rINST]
539   sub         rINST, rINST, #4
5402:
541   ubfx        r2, r3, #4, #4
542   GET_VREG_OBJECT r0, r2
543   str         r0, [rNEW_FP, rINST]
544   GET_VREG    r0, r2
545   str         r0, [r4, rINST]
546   .if !\is_string_init
547   sub         rINST, rINST, #4
548   .endif
5491:
550   .if \is_string_init
551   // Ignore the first argument
552   .elseif \is_static
553   and         r2, r3, #0xf
554   GET_VREG_OBJECT r0, r2
555   str         r0, [rNEW_FP, rINST]
556   GET_VREG    r0, r2
557   str         r0, [r4, rINST]
558   .else
559   str         r1, [rNEW_FP, rINST]
560   str         r1, [r4, rINST]
561   .endif
562
5636:
564   // Start executing the method.
565   mov rFP, rNEW_FP
566   mov rREFS, rNEW_REFS
567   CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -4, CALLEE_SAVES_SIZE
568   // r8 was used for setting up the frame, restore it now.
569   REFRESH_MARKING_REGISTER
570   // Branch to the main handler, which will reload rIBASE,
571   // that was used for setting up the frame.
572   b .Lexecute_instructions
573.endm
574
575// Setup arguments based on a range nterp to nterp call, and start executing
576// the method.
577// - rNEW_FP: the new pointer to dex registers
578// - rNEW_REFS: the new pointer to references
579// - rPC: the new PC pointer to execute
580// - r2: number of arguments
581// - r3: first dex register
582// - r4: top of dex register array
583// - r1: receiver if non-static.
584//
585// Expects r0 to be available.
586.macro SETUP_RANGE_ARGUMENTS_AND_EXECUTE is_static=0, is_string_init=0
587   mov r0, #-4
588   .if \is_string_init
589   // Ignore the first argument
590   sub r2, r2, #1
591   add r3, r3, #1
592   .elseif !\is_static
593   sub r2, r2, #1
594   add r3, r3, #1
595   .endif
596
597   cmp r2, #0
598   beq 2f
599   add rREFS, rREFS, r3, lsl #2  // pointer to first argument in reference array
600   add rREFS, rREFS, r2, lsl #2    // pointer to last argument in reference array
601   add rFP, rFP, r3, lsl #2     // pointer to first argument in register array
602   add rFP, rFP, r2, lsl #2      // pointer to last argument in register array
6031:
604   ldr  r3, [rREFS, #-4]!
605   str  r3, [rNEW_FP, r0]
606   subs r2, r2, 1
607   ldr  r3, [rFP, #-4]!
608   str  r3, [r4, r0]
609   sub r0, r0, 4
610   bne 1b
6112:
612   .if \is_string_init
613   // Ignore first argument
614   .elseif !\is_static
615   str r1, [rNEW_FP, r0]
616   str r1, [r4, r0]
617   .endif
618   mov rFP, rNEW_FP
619   mov rREFS, rNEW_REFS
620   CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -4, CALLEE_SAVES_SIZE
621   // r8 was used for setting up the frame, restore it now.
622   REFRESH_MARKING_REGISTER
623   // Branch to the main handler, which will reload rIBASE,
624   // that was used for setting up the frame.
625   b .Lexecute_instructions
626.endm
627
628.macro GET_SHORTY dest, is_interface, is_polymorphic, is_custom
629   push {r0-r3}
630   .if \is_polymorphic
631   ldr r0, [sp, #16]
632   mov r1, rPC
633   bl NterpGetShortyFromInvokePolymorphic
634   .elseif \is_custom
635   ldr r0, [sp, #16]
636   mov r1, rPC
637   bl NterpGetShortyFromInvokeCustom
638   .elseif \is_interface
639   ldr r0, [sp, #16]
640   FETCH r1, 1
641   bl NterpGetShortyFromMethodId
642   .else
643   bl NterpGetShorty
644   .endif
645   mov \dest, r0
646   pop {r0-r3}
647.endm
648
649// Input:  r0 contains the ArtMethod
650// Output: r4 contains the code item
651.macro GET_CODE_ITEM
652   ldr r4, [r0, #ART_METHOD_DATA_OFFSET_32]
653.endm
654
655.macro DO_ENTRY_POINT_CHECK call_compiled_code, name
656   // On entry, the method is r0, the instance is r1
657   ldr r2, .Lfetch_nterp_\name
658.Lfetch_location_\name:
659   // Note that this won't work for thumb.
660   sub r2, pc, r2
661   ldr r3, [r0, #ART_METHOD_QUICK_CODE_OFFSET_32]
662   cmp r2, r3
663   bne  \call_compiled_code
664.endm
665
666// Expects ip and lr to be available.
667.macro UPDATE_REGISTERS_FOR_STRING_INIT old_value, new_value
668   mov ip, #0
6691:
670   GET_VREG_OBJECT lr, ip
671   cmp lr, \old_value
672   bne 2f
673   SET_VREG_OBJECT \new_value, ip
6742:
675   add ip, ip, #1
676   add lr, rREFS, ip, lsl #2
677   cmp lr, rFP
678   bne 1b
679.endm
680
681// Puts the next floating point argument into the expected register,
682// fetching values based on a non-range invoke.
683// Uses ip and lr.
684.macro LOOP_OVER_SHORTY_LOADING_FPS dreg, sreg, inst, shorty, arg_index, finished, if_double
6851: // LOOP
686    ldrb ip, [\shorty], #1          // Load next character in shorty, and increment.
687    cmp ip, #0
688    beq \finished                   // if (ip == '\0') goto finished
689    cmp ip, #68                    // if (ip == 'D') goto FOUND_DOUBLE
690    beq 2f
691    cmp ip, #70                    // if (ip == 'F') goto FOUND_FLOAT
692    beq 3f
693    lsr \inst, \inst, #4
694    add \arg_index, \arg_index, #1
695    //  Handle extra argument in arg array taken by a long.
696    cmp ip, #74                   // if (ip != 'J') goto LOOP
697    bne 1b
698    lsr \inst, \inst, #4
699    add \arg_index, \arg_index, #1
700    b 1b                        // goto LOOP
7012:  // FOUND_DOUBLE
702    and ip, \inst, #0xf
703    GET_VREG ip, ip
704    lsr \inst, \inst, #4
705    add \arg_index, \arg_index, #1
706    cmp \arg_index, #4
707    beq 5f
708    and lr, \inst, #0xf
709    lsr \inst, \inst, #4
710    add \arg_index, \arg_index, #1
711    b 6f
7125:
713    FETCH_B lr, 0, 1
714    and lr, lr, #0xf
7156:
716    GET_VREG lr, lr
717    vmov \dreg, ip, lr
718    b \if_double
7193:  // FOUND_FLOAT
720    cmp \arg_index, #4
721    beq 7f
722    and ip, \inst, #0xf
723    lsr \inst, \inst, #4
724    add \arg_index, \arg_index, #1
725    b 8f
7267:
727    FETCH_B ip, 0, 1
728    and ip, ip, #0xf
7298:
730    GET_VREG_FLOAT \sreg, ip
731.endm
732
733// Puts the next int/long/object argument in the expected register,
734// fetching values based on a non-range invoke.
735// Uses ip.
736.macro LOOP_OVER_SHORTY_LOADING_GPRS gpr_reg, inst, shorty, arg_index, finished, if_long, is_r3
7371: // LOOP
738    ldrb ip, [\shorty], #1         // Load next character in shorty, and increment.
739    cmp ip, #0
740    beq \finished                   // if (ip == '\0') goto finished
741    cmp ip, #74                    // if (ip == 'J') goto FOUND_LONG
742    beq 2f
743    cmp ip, #70                    // if (ip == 'F') goto SKIP_FLOAT
744    beq 3f
745    cmp ip, #68                    // if (ip == 'D') goto SKIP_DOUBLE
746    beq 4f
747    cmp \arg_index, #4
748    beq 7f
749    and ip, \inst, #0xf
750    lsr \inst, \inst, #4
751    add \arg_index, \arg_index, #1
752    b 8f
7537:
754    FETCH_B ip, 0, 1
755    and ip, ip, #0xf
7568:
757    GET_VREG \gpr_reg, ip
758    b 5f
7592:  // FOUND_LONG
760    .if \is_r3
761    // Put back shorty and exit
762    sub \shorty, \shorty, #1
763    b 5f
764    .endif
765    and ip, \inst, #0xf
766    GET_VREG ip, ip
767    // The only one possible for non-range long is r2-r3
768    mov r2, ip
769    lsr \inst, \inst, #4
770    add \arg_index, \arg_index, #1
771    cmp \arg_index, #4
772    beq 9f
773    and ip, \inst, #0xf
774    lsr \inst, \inst, #4
775    b 10f
7769:
777    FETCH_B ip, 0, 1
778    and ip, ip, #0xf
77910:
780    GET_VREG ip, ip
781    // The only one possible for non-range long is r2-r3
782    mov r3, ip
783    add \arg_index, \arg_index, #1
784    b \if_long
7853:  // SKIP_FLOAT
786    lsr \inst, \inst, #4
787    add \arg_index, \arg_index, #1
788    b 1b
7894:  // SKIP_DOUBLE
790    lsr \inst, \inst, #8
791    add \arg_index, \arg_index, #2
792    b 1b
7935:
794.endm
795
796// Puts the next int/long/object argument in the expected stack slot,
797// fetching values based on a non-range invoke.
798// Uses ip as temporary.
799.macro LOOP_OVER_SHORTY_LOADING_INTs shorty, inst, arg_index, finished, is_string_init
8001: // LOOP
801    ldrb ip, [\shorty], #1         // Load next character in shorty, and increment.
802    cmp ip, #0
803    beq \finished                  // if (ip == '\0') goto finished
804    cmp ip, #74                    // if (ip == 'J') goto FOUND_LONG
805    beq 2f
806    cmp ip, #70                    // if (ip == 'F') goto SKIP_FLOAT
807    beq 3f
808    cmp ip, #68                    // if (ip == 'D') goto SKIP_DOUBLE
809    beq 4f
810    .if \is_string_init
811    cmp \arg_index, #4
812    .else
813    cmp \arg_index, #(4+1)         // +1 for ArtMethod
814    .endif
815    beq 7f
816    and ip, \inst, #0xf
817    lsr \inst, \inst, #4
818    b 8f
8197:
820    FETCH_B ip, 0, 1
821    and ip, ip, #0xf
8228:
823    GET_VREG ip, ip
824    str ip, [sp, \arg_index, lsl #2]
825    add \arg_index, \arg_index, #1
826    b 1b
8272:  // FOUND_LONG
828    and ip, \inst, #0xf
829    GET_VREG ip, ip
830    str ip, [sp, \arg_index, lsl #2]
831    lsr \inst, \inst, #4
832    add \arg_index, \arg_index, #1
833    .if \is_string_init
834    cmp \arg_index, #4
835    .else
836    cmp \arg_index, #(4+1)         // +1 for ArtMethod
837    .endif
838    beq 9f
839    and ip, \inst, #0xf
840    lsr \inst, \inst, #4
841    b 10f
8429:
843    FETCH_B ip, 0, 1
844    and ip, ip, #0xf
84510:
846    GET_VREG ip, ip
847    str ip, [sp, \arg_index, lsl #2]
848    add \arg_index, \arg_index, #1
849    b 1b
8503:  // SKIP_FLOAT
851    lsr \inst, \inst, #4
852    add \arg_index, \arg_index, #1
853    b 1b
8544:  // SKIP_DOUBLE
855    lsr \inst, \inst, #8
856    add \arg_index, \arg_index, #2
857    b 1b
858.endm
859
860.macro SETUP_RETURN_VALUE shorty
861   ldrb ip, [\shorty]
862   cmp ip, #68       // Test if result type char == 'D'.
863   beq 1f
864   cmp ip, #70       // Test if result type char == 'F'.
865   bne 2f
866   vmov r0, s0
867   b 2f
8681:
869   vmov r0, r1, d0
8702:
871.endm
872
873.macro GET_SHORTY_SLOW_PATH dest, is_interface
874   // Save all registers that can hold arguments in the fast path.
875   vpush {s0}
876   push {r0-r2}
877   .if \is_interface
878   ldr r0, [sp, #16]
879   FETCH r1, 1
880   bl NterpGetShortyFromMethodId
881   .else
882   bl NterpGetShorty
883   .endif
884   mov \dest, r0
885   pop {r0-r2}
886   vpop {s0}
887.endm
888
889.macro COMMON_INVOKE_NON_RANGE is_static=0, is_interface=0, suffix="", is_string_init=0, is_polymorphic=0, is_custom=0
890   .if \is_polymorphic
891   // We always go to compiled code for polymorphic calls.
892   .elseif \is_custom
893   // We always go to compiled code for custom calls.
894   .else
895     DO_ENTRY_POINT_CHECK .Lcall_compiled_code_\suffix, \suffix
896     GET_CODE_ITEM
897     .if \is_string_init
898     bl nterp_to_nterp_string_init_non_range
899     .elseif \is_static
900     bl nterp_to_nterp_static_non_range
901     .else
902     bl nterp_to_nterp_instance_non_range
903     .endif
904     b .Ldone_return_\suffix
905.Lfetch_nterp_\suffix:
906    .word   (.Lfetch_location_\suffix+8) - ExecuteNterpImpl
907   .endif
908
909.Lcall_compiled_code_\suffix:
910   .if \is_polymorphic
911   // No fast path for polymorphic calls.
912   .elseif \is_custom
913   // No fast path for custom calls.
914   .elseif \is_string_init
915   // No fast path for string.init.
916   .else
917     ldr ip, [r0, #ART_METHOD_ACCESS_FLAGS_OFFSET]
918     tst ip, #ART_METHOD_NTERP_INVOKE_FAST_PATH_FLAG
919     beq .Lfast_path_with_few_args_\suffix
920     FETCH_B rINST, 0, 1
921     .if \is_static
922     asrs lr, rINST, #4
923     beq .Linvoke_fast_path_\suffix
924     .else
925     asr lr, rINST, #4
926     cmp lr, #1
927     beq .Linvoke_fast_path_\suffix
928     .endif
929     FETCH ip, 2
930     cmp lr, #2
931     .if \is_static
932     blt .Lone_arg_fast_path_\suffix
933     .endif
934     beq .Ltwo_args_fast_path_\suffix
935     cmp lr, #4
936     blt .Lthree_args_fast_path_\suffix
937     beq .Lfour_args_fast_path_\suffix
938     and         rINST, rINST, #15
939     GET_VREG    rINST, rINST
940     str         rINST, [sp, #(4 + 4 * 4)]
941.Lfour_args_fast_path_\suffix:
942     asr         rINST, ip, #12
943     GET_VREG    rINST, rINST
944     str         rINST, [sp, #(4 + 3 * 4)]
945.Lthree_args_fast_path_\suffix:
946     ubfx        rINST, ip, #8, #4
947     GET_VREG    r3, rINST
948.Ltwo_args_fast_path_\suffix:
949     ubfx        rINST, ip, #4, #4
950     GET_VREG    r2, rINST
951.Lone_arg_fast_path_\suffix:
952     .if \is_static
953     and         rINST, ip, #0xf
954     GET_VREG    r1, rINST
955     .else
956     // First argument already in r1.
957     .endif
958.Linvoke_fast_path_\suffix:
959     .if \is_interface
960     // Setup hidden argument.
961     mov ip, r4
962     .endif
963     ldr lr, [r0, #ART_METHOD_QUICK_CODE_OFFSET_32]
964     blx lr
965     FETCH_ADVANCE_INST 3
966     GET_INST_OPCODE ip
967     GOTO_OPCODE ip
968
969.Lfast_path_with_few_args_\suffix:
970     // Fast path when we have zero or one argument (modulo 'this'). If there
971     // is one argument, we can put it in both floating point and core register.
972     FETCH_B r2, 0, 1
973     asr r2, r2, #4  // number of arguments
974     .if \is_static
975     cmp r2, #1
976     blt .Linvoke_with_few_args_\suffix
977     bne .Lget_shorty_\suffix
978     FETCH r2, 2
979     and r2, r2, #0xf  // dex register of first argument
980     GET_VREG r1, r2
981     vmov s0, r1
982     .else
983     cmp r2, #2
984     blt .Linvoke_with_few_args_\suffix
985     bne .Lget_shorty_\suffix
986     FETCH r2, 2
987     ubfx r2, r2, #4, #4  // dex register of second argument
988     GET_VREG r2, r2
989     vmov s0, r2
990     .endif
991.Linvoke_with_few_args_\suffix:
992     // Check if the next instruction is move-result or move-result-wide.
993     // If it is, we fetch the shorty and jump to the regular invocation.
994     FETCH r3, 3
995     and r3, r3, #0xfe
996     cmp r3, #0x0a
997     beq .Lget_shorty_and_invoke_\suffix
998     .if \is_interface
999     // Setup hidden argument.
1000     mov ip, r4
1001     .endif
1002     ldr lr, [r0, #ART_METHOD_QUICK_CODE_OFFSET_32]
1003     blx lr
1004     FETCH_ADVANCE_INST 3
1005     GET_INST_OPCODE ip
1006     GOTO_OPCODE ip
1007.Lget_shorty_and_invoke_\suffix:
1008     .if \is_interface
1009     // Save hidden argument.
1010     vmov s16, r4
1011     .endif
1012     GET_SHORTY_SLOW_PATH rINST, \is_interface
1013     b .Lgpr_setup_finished_\suffix
1014   .endif
1015
1016.Lget_shorty_\suffix:
1017   .if \is_interface
1018   // Save hidden argument.
1019   vmov s16, r4
1020   .endif
1021   GET_SHORTY rINST, \is_interface, \is_polymorphic, \is_custom
1022   // From this point:
1023   // - rINST contains shorty (in callee-save to switch over return value after call).
1024   // - r0 contains method
1025   // - r1 contains 'this' pointer for instance method.
1026   // We need three registers.
1027   add r3, rINST, #1  // shorty + 1  ; ie skip return arg character
1028   FETCH r2, 2 // arguments
1029   .if \is_string_init
1030   lsr r2, r2, #4
1031   mov r4, #1       // ignore first argument
1032   .elseif \is_static
1033   mov r4, #0      // arg_index
1034   .else
1035   lsr r2, r2, #4
1036   mov r4, #1       // ignore first argument
1037   .endif
1038   LOOP_OVER_SHORTY_LOADING_FPS d0, s0, r2, r3, r4, .Lxmm_setup_finished_\suffix, .Ld1_s2_\suffix
1039.Ld1_s1_\suffix:
1040   LOOP_OVER_SHORTY_LOADING_FPS d1, s1, r2, r3, r4, .Lxmm_setup_finished_\suffix, .Ld2_s1_\suffix
1041.Ld1_s2_\suffix:
1042   LOOP_OVER_SHORTY_LOADING_FPS d1, s2, r2, r3, r4, .Lxmm_setup_finished_\suffix, .Ls4_\suffix
1043.Ld2_s3_\suffix:
1044   LOOP_OVER_SHORTY_LOADING_FPS d2, s3, r2, r3, r4, .Lxmm_setup_finished_\suffix, .Lxmm_setup_finished_\suffix
1045   b .Ls4_\suffix
1046.Ld2_s1_\suffix:
1047   LOOP_OVER_SHORTY_LOADING_FPS d2, s1, r2, r3, r4, .Lxmm_setup_finished_\suffix, .Lxmm_setup_finished_\suffix
1048.Ls4_\suffix:
1049   // If we arrive here, we can only have a float.
1050   LOOP_OVER_SHORTY_LOADING_FPS d2, s4, r2, r3, r4, .Lxmm_setup_finished_\suffix, .Lxmm_setup_finished_\suffix
1051.Lxmm_setup_finished_\suffix:
1052   add r4, rINST, #1  // shorty + 1  ; ie skip return arg character
1053   FETCH r8, 2 // arguments
1054   .if \is_string_init
1055   lsr r8, r8, #4
1056   mov lr, #1       // ignore first argument
1057   LOOP_OVER_SHORTY_LOADING_GPRS r1, r8, r4, lr, .Lgpr_setup_finished_\suffix, .Lif_long_\suffix, is_r3=0
1058   .elseif \is_static
1059   mov lr, #0      // arg_index
1060   LOOP_OVER_SHORTY_LOADING_GPRS r1, r8, r4, lr, .Lgpr_setup_finished_\suffix, .Lif_long_\suffix, is_r3=0
1061   .else
1062   lsr r8, r8, #4
1063   mov lr, #1       // ignore first argument
1064   .endif
1065   LOOP_OVER_SHORTY_LOADING_GPRS r2, r8, r4, lr, .Lgpr_setup_finished_\suffix, .Lif_long_\suffix, is_r3=0
1066   LOOP_OVER_SHORTY_LOADING_GPRS r3, r8, r4, lr, .Lgpr_setup_finished_\suffix, .Lif_long_\suffix, is_r3=1
1067.Lif_long_\suffix:
1068   // Store in the outs array (stored above the ArtMethod in the stack). We only do this for non-string-init
1069   // calls as the index is already adjusted above.
1070   .if !\is_string_init
1071   add lr, lr, #1
1072   .endif
1073   LOOP_OVER_SHORTY_LOADING_INTs r4, r8, lr, .Lgpr_setup_finished_\suffix, \is_string_init
1074.Lgpr_setup_finished_\suffix:
1075   REFRESH_MARKING_REGISTER // r8 was used when setting parameters, restore it.
1076   .if \is_polymorphic
1077   bl art_quick_invoke_polymorphic
1078   .elseif \is_custom
1079   bl art_quick_invoke_custom
1080   .else
1081      .if \is_interface
1082      // Setup hidden argument.
1083      vmov ip, s16
1084      .endif
1085      ldr lr, [r0, #ART_METHOD_QUICK_CODE_OFFSET_32]
1086      blx lr
1087   .endif
1088   SETUP_RETURN_VALUE rINST
1089.Ldone_return_\suffix:
1090   /* resume execution of caller */
1091   .if \is_string_init
1092   FETCH ip, 2 // arguments
1093   and ip, ip, #0xf
1094   GET_VREG r1, ip
1095   UPDATE_REGISTERS_FOR_STRING_INIT r1, r0
1096   .endif
1097
1098   .if \is_polymorphic
1099   FETCH_ADVANCE_INST 4
1100   .else
1101   FETCH_ADVANCE_INST 3
1102   .endif
1103   GET_INST_OPCODE ip
1104   GOTO_OPCODE ip
1105.endm
1106
1107// Puts the next int/long/object argument in the expected register,
1108// fetching values based on a range invoke.
1109// Uses ip as temporary.
1110.macro LOOP_RANGE_OVER_SHORTY_LOADING_GPRS reg32, shorty, arg_index, stack_index, finished, if_long, is_r3
11111: // LOOP
1112    ldrb ip, [\shorty], #1         // Load next character in shorty, and increment.
1113    cmp ip, #0
1114    beq \finished                  // if (ip == '\0') goto finished
1115    cmp ip, #74                    // if (ip == 'J') goto FOUND_LONG
1116    beq 2f
1117    cmp ip, #70                    // if (ip == 'F') goto SKIP_FLOAT
1118    beq 3f
1119    cmp ip, #68                    // if (ip == 'D') goto SKIP_DOUBLE
1120    beq 4f
1121    GET_VREG \reg32, \arg_index
1122    add \arg_index, \arg_index, #1
1123    add \stack_index, \stack_index, #1
1124    b 5f
11252:  // FOUND_LONG
1126    .if \is_r3
1127    // Put back shorty and jump to \if_long
1128    sub \shorty, \shorty, #1
1129    .else
1130    GET_VREG r2, \arg_index
1131    add \arg_index, \arg_index, #1
1132    add \stack_index, \stack_index, #1
1133    GET_VREG r3, \arg_index
1134    add \arg_index, \arg_index, #1
1135    add \stack_index, \stack_index, #1
1136    .endif
1137    b \if_long
11383:  // SKIP_FLOAT
1139    add \arg_index, \arg_index, #1
1140    add \stack_index, \stack_index, #1
1141    b 1b
11424:  // SKIP_DOUBLE
1143    add \arg_index, \arg_index, #2
1144    add \stack_index, \stack_index, #2
1145    b 1b
11465:
1147.endm
1148
1149// Puts the next int/long/object argument in the expected stack slot,
1150// fetching values based on a range invoke.
1151// Uses ip as temporary.
1152.macro LOOP_RANGE_OVER_INTs shorty, arg_index, stack_index, finished
11531: // LOOP
1154    ldrb ip, [\shorty], #1         // Load next character in shorty, and increment.
1155    cmp ip, #0
1156    beq \finished                     // if (ip == '\0') goto finished
1157    cmp ip, #74                    // if (ip == 'J') goto FOUND_LONG
1158    beq 2f
1159    cmp ip, #70                    // if (ip == 'F') goto SKIP_FLOAT
1160    beq 3f
1161    cmp ip, #68                    // if (ip == 'D') goto SKIP_DOUBLE
1162    beq 4f
1163    GET_VREG ip, \arg_index
1164    str ip, [sp, \stack_index, lsl #2]
1165    add \arg_index, \arg_index, #1
1166    add \stack_index, \stack_index, #1
1167    b 1b
11682:  // FOUND_LONG
1169    GET_VREG ip, \arg_index
1170    str ip, [sp, \stack_index, lsl #2]
1171    add \arg_index, \arg_index, #1
1172    add \stack_index, \stack_index, #1
1173    GET_VREG ip, \arg_index
1174    str ip, [sp, \stack_index, lsl #2]
1175    add \arg_index, \arg_index, #1
1176    add \stack_index, \stack_index, #1
1177    b 1b
11783:  // SKIP_FLOAT
1179    add \arg_index, \arg_index, #1
1180    add \stack_index, \stack_index, #1
1181    b 1b
11824:  // SKIP_DOUBLE
1183    add \arg_index, \arg_index, #2
1184    add \stack_index, \stack_index, #2
1185    b 1b
1186.endm
1187
1188.macro COMMON_INVOKE_RANGE is_static=0, is_interface=0, suffix="", is_string_init=0, is_polymorphic=0, is_custom=0
1189   .if \is_polymorphic
1190   // We always go to compiled code for polymorphic calls.
1191   .elseif \is_custom
1192   // We always go to compiled code for custom calls.
1193   .else
1194     DO_ENTRY_POINT_CHECK .Lcall_compiled_code_range_\suffix, range_\suffix
1195     GET_CODE_ITEM
1196     .if \is_string_init
1197     bl nterp_to_nterp_string_init_range
1198     .elseif \is_static
1199     bl nterp_to_nterp_static_range
1200     .else
1201     bl nterp_to_nterp_instance_range
1202     .endif
1203     b .Ldone_return_range_\suffix
1204.Lfetch_nterp_range_\suffix:
1205    .word   (.Lfetch_location_range_\suffix+8) - ExecuteNterpImpl
1206   .endif
1207
1208.Lcall_compiled_code_range_\suffix:
1209   .if \is_polymorphic
1210   // No fast path for polymorphic calls.
1211   .elseif \is_custom
1212   // No fast path for custom calls.
1213   .elseif \is_string_init
1214   // No fast path for string.init.
1215   .else
1216     ldr ip, [r0, #ART_METHOD_ACCESS_FLAGS_OFFSET]
1217     tst ip, #ART_METHOD_NTERP_INVOKE_FAST_PATH_FLAG
1218     beq .Lfast_path_with_few_args_range_\suffix
1219     FETCH_B ip, 0, 1  // Number of arguments
1220     .if \is_static
1221     cmp ip, #0
1222     .else
1223     cmp ip, #1
1224     .endif
1225     beq .Linvoke_fast_path_range_\suffix
1226     FETCH lr, 2  // dex register of first argument
1227     add lr, rFP, lr, lsl #2  // location of first dex register value.
1228     .if \is_static
1229     cmp ip, #2
1230     blt .Lone_arg_fast_path_range_\suffix
1231     beq .Ltwo_args_fast_path_range_\suffix
1232     cmp ip, #3
1233     .else
1234     cmp ip, #3
1235     blt .Ltwo_args_fast_path_range_\suffix
1236     .endif
1237     beq .Lthree_args_fast_path_range_\suffix
1238     add rINST, sp, #4  // Add space for the ArtMethod
1239
1240.Lloop_over_fast_path_range_\suffix:
1241     sub ip, ip, #1
1242     ldr r3, [lr, ip, lsl #2]
1243     str r3, [rINST, ip, lsl #2]
1244     cmp ip, #3
1245     bne .Lloop_over_fast_path_range_\suffix
1246
1247.Lthree_args_fast_path_range_\suffix:
1248     ldr r3, [lr, #8]
1249.Ltwo_args_fast_path_range_\suffix:
1250     ldr r2, [lr, #4]
1251.Lone_arg_fast_path_range_\suffix:
1252     .if \is_static
1253     ldr r1, [lr, #0]
1254     .else
1255     // First argument already in r1.
1256     .endif
1257.Linvoke_fast_path_range_\suffix:
1258     .if \is_interface
1259     // Setup hidden argument.
1260     mov ip, r4
1261     .endif
1262     ldr lr, [r0, #ART_METHOD_QUICK_CODE_OFFSET_32]
1263     blx lr
1264     FETCH_ADVANCE_INST 3
1265     GET_INST_OPCODE ip
1266     GOTO_OPCODE ip
1267
1268.Lfast_path_with_few_args_range_\suffix:
1269     // Fast path when we have zero or one argument (modulo 'this'). If there
1270     // is one argument, we can put it in both floating point and core register.
1271     FETCH_B r2, 0, 1 // number of arguments
1272     .if \is_static
1273     cmp r2, #1
1274     blt .Linvoke_with_few_args_range_\suffix
1275     bne .Lget_shorty_range_\suffix
1276     FETCH r3, 2  // dex register of first argument
1277     GET_VREG r1, r3
1278     vmov s0, r1
1279     .else
1280     cmp r2, #2
1281     blt .Linvoke_with_few_args_range_\suffix
1282     bne .Lget_shorty_range_\suffix
1283     FETCH r3, 2  // dex register of first argument
1284     add r3, r3, #1  // Add 1 for next argument
1285     GET_VREG r2, r3
1286     vmov s0, r2
1287     .endif
1288.Linvoke_with_few_args_range_\suffix:
1289     // Check if the next instruction is move-result or move-result-wide.
1290     // If it is, we fetch the shorty and jump to the regular invocation.
1291     FETCH r3, 3
1292     and r3, r3, #0xfe
1293     cmp r3, #0x0a
1294     beq .Lget_shorty_and_invoke_range_\suffix
1295     .if \is_interface
1296     // Setup hidden argument.
1297     mov ip, r4
1298     .endif
1299     ldr lr, [r0, #ART_METHOD_QUICK_CODE_OFFSET_32]
1300     blx lr
1301     FETCH_ADVANCE_INST 3
1302     GET_INST_OPCODE ip
1303     GOTO_OPCODE ip
1304.Lget_shorty_and_invoke_range_\suffix:
1305     .if \is_interface
1306     // Save hidden argument.
1307     vmov s16, r4
1308     .endif
1309     GET_SHORTY_SLOW_PATH rINST, \is_interface
1310     b .Lgpr_setup_finished_range_\suffix
1311   .endif
1312
1313.Lget_shorty_range_\suffix:
1314   .if \is_interface
1315   // Save hidden argument.
1316   vmov s16, r4
1317   .endif
1318   GET_SHORTY rINST, \is_interface, \is_polymorphic, \is_custom
1319   // From this point:
1320   // - rINST contains shorty (in callee-save to switch over return value after call).
1321   // - r0 contains method
1322   // - r1 contains 'this' pointer for instance method.
1323   //
1324   // Save r0 and r1 before calling NterpSetupArm32Fprs.
1325   push {r0, r1}
1326   add r0, rINST, #1  // shorty + 1  ; ie skip return arg character
1327   FETCH r1, 2 // arguments
1328   .if \is_string_init
1329   add r1, r1, #1  // arg start index
1330   mov r2, #1       // index in stack
1331   .elseif \is_static
1332   mov r2, #0       // index in stack
1333   .else
1334   add r1, r1, #1  // arg start index
1335   mov r2, #1       // index in stack
1336   .endif
1337   vpush {s0-s15}
1338   mov r3, sp
1339   // Pass the stack address for arguments, +16 for fprs, +2 for saved registers,
1340   // +1 for ArtMethod.
1341   add lr, sp, #((16 + 2 + 1) * 4)
1342   push {rFP, lr}
1343   bl NterpSetupArm32Fprs
1344   add sp, sp, #8
1345   vpop {s0-s15}
1346   pop {r0, r1}
1347.Lxmm_setup_finished_range_\suffix:
1348   add r8, rINST, #1  // shorty + 1  ; ie skip return arg character
1349   FETCH lr, 2 // arguments
1350   .if \is_string_init
1351   add lr, lr, #1  // arg start index
1352   mov r4, #0      // index in stack
1353   LOOP_RANGE_OVER_SHORTY_LOADING_GPRS r1, r8, lr, r4, .Lgpr_setup_finished_range_\suffix, .Lif_long_range_\suffix, is_r3=0
1354   .elseif \is_static
1355   mov r4, #0      // index in stack
1356   LOOP_RANGE_OVER_SHORTY_LOADING_GPRS r1, r8, lr, r4, .Lgpr_setup_finished_range_\suffix, .Lif_long_range_\suffix, is_r3=0
1357   .else
1358   add lr, lr, #1  // arg start index
1359   mov r4, #1       // index in stack
1360   .endif
1361   LOOP_RANGE_OVER_SHORTY_LOADING_GPRS r2, r8, lr, r4, .Lgpr_setup_finished_range_\suffix, .Lif_long_range_\suffix, is_r3=0
1362   LOOP_RANGE_OVER_SHORTY_LOADING_GPRS r3, r8, lr, r4, .Lgpr_setup_finished_range_\suffix, .Lif_long_range_\suffix, is_r3=1
1363.Lif_long_range_\suffix:
1364   // Add 1 word for the ArtMethod stored before the outs.
1365   add r4, r4, #1
1366   LOOP_RANGE_OVER_INTs r8, lr, r4, .Lgpr_setup_finished_range_\suffix
1367.Lgpr_setup_finished_range_\suffix:
1368   REFRESH_MARKING_REGISTER // r8 was used when setting parameters, restore it.
1369   .if \is_polymorphic
1370   bl art_quick_invoke_polymorphic
1371   .elseif \is_custom
1372   bl art_quick_invoke_custom
1373   .else
1374      .if \is_interface
1375      // Setup hidden argument.
1376      vmov ip, s16
1377      .endif
1378      ldr lr, [r0, #ART_METHOD_QUICK_CODE_OFFSET_32]
1379      blx lr
1380   .endif
1381   SETUP_RETURN_VALUE rINST
1382.Ldone_return_range_\suffix:
1383   /* resume execution of caller */
1384   .if \is_string_init
1385   FETCH ip, 2 // arguments
1386   GET_VREG r1, ip
1387   UPDATE_REGISTERS_FOR_STRING_INIT r1, r0
1388   .endif
1389
1390   .if \is_polymorphic
1391    FETCH_ADVANCE_INST 4
1392   .else
1393   FETCH_ADVANCE_INST 3
1394   .endif
1395   GET_INST_OPCODE ip
1396   GOTO_OPCODE ip
1397.endm
1398
1399.macro POISON_HEAP_REF_IF_OBJECT is_object, rRef
1400   .if \is_object
1401   POISON_HEAP_REF \rRef
1402   .endif
1403.endm
1404
1405.macro WRITE_BARRIER_IF_OBJECT is_object, value, holder, label, tmp
1406   .if \is_object
1407   // In T32, we would use `SMART_CBZ \value, \label`
1408   cmp     \value, #0
1409   beq     \label
1410   ldr     ip, [rSELF, #THREAD_CARD_TABLE_OFFSET]
1411   lsr     \tmp, \holder, #CARD_TABLE_CARD_SHIFT
1412   strb    ip, [ip, \tmp]
1413\label:
1414   .endif
1415.endm
1416
1417.macro LDREXD_STREXD_LOOP addr, load1, load2, store1, store2, tmp, label
1418\label:
1419   ldrexd  \load1, \load2, [\addr]
1420   strexd  \tmp, \store1, \store2, [\addr]
1421   cmp     \tmp, #0
1422   bne     \label
1423.endm
1424
1425.macro ATOMIC_LOAD64 addr, load1, load2, tmp, label
1426   LDREXD_STREXD_LOOP \addr, \load1, \load2, \load1, \load2, \tmp, \label
1427.endm
1428
1429.macro ATOMIC_STORE64 addr, store1, store2, tmp1, tmp2, label
1430   LDREXD_STREXD_LOOP \addr, \tmp1, \tmp2, \store1, \store2, \tmp1, \label
1431.endm
1432
1433// Puts the next int/long/object parameter passed in physical register
1434// in the expected dex register array entry, and in case of object in the
1435// expected reference array entry.
1436// Uses ip as temporary.
1437.macro LOOP_OVER_SHORTY_STORING_GPRS gpr_32, shorty, arg_offset, regs, refs, finished, if_long, is_r3
14381: // LOOP
1439    ldrb ip, [\shorty], #1       // Load next character in shorty, and increment.
1440    cmp ip, #0
1441    beq \finished            // if (ip == '\0') goto finished
1442    cmp ip, #74                  // if (ip == 'J') goto FOUND_LONG
1443    beq 2f
1444    cmp ip, #70                  // if (ip == 'F') goto SKIP_FLOAT
1445    beq 3f
1446    cmp ip, #68                  // if (ip == 'D') goto SKIP_DOUBLE
1447    beq 4f
1448    str \gpr_32, [\regs, \arg_offset]
1449    cmp ip, #76                  // if (ip != 'L') goto NOT_REFERENCE
1450    bne 6f
1451    str \gpr_32, [\refs, \arg_offset]
14526:  // NOT_REFERENCE
1453    add \arg_offset, \arg_offset, #4
1454    b 5f
14552:  // FOUND_LONG
1456    .if \is_r3
1457    // Put back shorty and jump to \if_long
1458    sub \shorty, \shorty, #1
1459    .else
1460    // A long can only be in r2, r3
1461    str r2, [\regs, \arg_offset]
1462    add \arg_offset, \arg_offset, #4
1463    str r3, [\regs, \arg_offset]
1464    add \arg_offset, \arg_offset, #4
1465    .endif
1466    b \if_long
14673:  // SKIP_FLOAT
1468    add \arg_offset, \arg_offset, #4
1469    b 1b
14704:  // SKIP_DOUBLE
1471    add \arg_offset, \arg_offset, #8
1472    b 1b
14735:
1474.endm
1475
1476// Puts the next int/long/object parameter passed in stack
1477// in the expected dex register array entry, and in case of object in the
1478// expected reference array entry.
1479.macro LOOP_OVER_INTs shorty, arg_offset, regs, refs, stack_ptr, tmp1, tmp2, finished
14801: // LOOP
1481    ldrb \tmp1, [\shorty], #1       // Load next character in shorty, and increment.
1482    cmp \tmp1, #0
1483    beq \finished                   // if (\tmp1 == '\0') goto finished
1484    cmp \tmp1, #74                  // if (\tmp1 == 'J') goto FOUND_LONG
1485    beq 2f
1486    cmp \tmp1, #70                  // if (\tmp1 == 'F') goto SKIP_FLOAT
1487    beq 3f
1488    cmp \tmp1, #68                  // if (\tmp1 == 'D') goto SKIP_DOUBLE
1489    beq 4f
1490    add \tmp2, \stack_ptr, \arg_offset
1491    ldr \tmp2, [\tmp2,  #OFFSET_TO_FIRST_ARGUMENT_IN_STACK]
1492    str \tmp2, [\regs, \arg_offset]
1493    cmp \tmp1, #76                  // if (\tmp1 != 'L') goto loop
1494    bne 3f
1495    str \tmp2, [\refs, \arg_offset]
1496    add \arg_offset, \arg_offset, #4
1497    b 1b
14982:  // FOUND_LONG
1499    add \tmp1, \stack_ptr, \arg_offset
1500    ldr \tmp1, [\tmp1,  #OFFSET_TO_FIRST_ARGUMENT_IN_STACK]
1501    str \tmp1, [\regs, \arg_offset]
1502    add \arg_offset, \arg_offset, #4
1503    add \tmp1, \stack_ptr, \arg_offset
1504    ldr \tmp1, [\tmp1,  #OFFSET_TO_FIRST_ARGUMENT_IN_STACK]
1505    str \tmp1, [\regs, \arg_offset]
1506    add \arg_offset, \arg_offset, #4
1507    b 1b
15083:  // SKIP_FLOAT
1509    add \arg_offset, \arg_offset, #4
1510    b 1b
15114:  // SKIP_DOUBLE
1512    add \arg_offset, \arg_offset, #8
1513    b 1b
1514.endm
1515
1516.macro SETUP_REFERENCE_PARAMETER_IN_GPR gpr32, regs, refs, ins, arg_offset, finished
1517    str \gpr32, [\regs, \arg_offset]
1518    subs \ins, \ins, #1
1519    str \gpr32, [\refs, \arg_offset]
1520    add \arg_offset, \arg_offset, #4
1521    beq \finished
1522.endm
1523
1524.macro SETUP_REFERENCE_PARAMETERS_IN_STACK regs, refs, ins, stack_ptr, arg_offset
15251:
1526    ldr ip, [\stack_ptr, \arg_offset]
1527    subs \ins, \ins, #1
1528    str ip, [\regs, \arg_offset]
1529    str ip, [\refs, \arg_offset]
1530    add \arg_offset, \arg_offset, #4
1531    bne 1b
1532.endm
1533
1534.macro DO_SUSPEND_CHECK continue_label
1535    // Otherwise, do a suspend check.
1536    ldr ip, [rSELF, #THREAD_FLAGS_OFFSET]
1537    tst ip, #THREAD_SUSPEND_OR_CHECKPOINT_REQUEST
1538    beq \continue_label
1539    EXPORT_PC
1540    bl    art_quick_test_suspend
1541.endm
1542
1543.macro CHECK_AND_UPDATE_SHARED_MEMORY_METHOD if_hot, if_not_hot
1544    ldr ip, [r0, #ART_METHOD_ACCESS_FLAGS_OFFSET]
1545    tst ip, #ART_METHOD_IS_MEMORY_SHARED_FLAG
1546    beq \if_hot
1547    // Intrinsics are always in the boot image and considered hot.
1548    tst ip, #ART_METHOD_IS_INTRINSIC_FLAG
1549    bne \if_hot
1550    ldr ip, [rSELF, #THREAD_SHARED_METHOD_HOTNESS_OFFSET]
1551    cmp ip, #0
1552    beq \if_hot
1553    add ip, ip, #-1
1554    str ip, [rSELF, #THREAD_SHARED_METHOD_HOTNESS_OFFSET]
1555    b \if_not_hot
1556.endm
1557
1558
1559%def entry():
1560/*
1561 * ArtMethod entry point.
1562 *
1563 * On entry:
1564 *  r0   ArtMethod* callee
1565 *  rest  method parameters
1566 */
1567
1568OAT_ENTRY ExecuteNterpWithClinitImpl
1569    .cfi_startproc
1570    // For simplicity, we don't do a read barrier here, but instead rely
1571    // on art_quick_resolution_trampoline to always have a suspend point before
1572    // calling back here.
1573    ldr r4, [r0, ART_METHOD_DECLARING_CLASS_OFFSET]
1574    ldr ip, [r4, MIRROR_CLASS_STATUS_OFFSET]
1575    cmp ip, #MIRROR_CLASS_STATUS_VISIBLY_INITIALIZED_SHIFTED
1576    bcs ExecuteNterpImpl
1577    cmp ip, #MIRROR_CLASS_STATUS_INITIALIZED_SHIFTED
1578    blo .Linitializing_check
1579    dmb ish
1580    b ExecuteNterpImpl
1581.Linitializing_check:
1582    cmp ip, #MIRROR_CLASS_STATUS_INITIALIZING_SHIFTED
1583    blo art_quick_resolution_trampoline
1584    ldr r4, [r4, #MIRROR_CLASS_CLINIT_THREAD_ID_OFFSET]
1585    ldr ip, [rSELF, #THREAD_TID_OFFSET]
1586    cmp r4, ip
1587    beq ExecuteNterpImpl
1588    b art_quick_resolution_trampoline
1589    .cfi_endproc
1590    .type EndExecuteNterpWithClinitImpl, #function
1591    .hidden EndExecuteNterpWithClinitImpl
1592    .global EndExecuteNterpWithClinitImpl
1593EndExecuteNterpWithClinitImpl:
1594
1595OAT_ENTRY ExecuteNterpImpl
1596    .cfi_startproc
1597    sub ip, sp, #STACK_OVERFLOW_RESERVED_BYTES
1598    ldr ip, [ip]
1599    /* Spill callee save regs */
1600    SPILL_ALL_CALLEE_SAVES
1601
1602    ldr rPC, [r0, #ART_METHOD_DATA_OFFSET_32]
1603
1604    // Setup the stack for executing the method.
1605    SETUP_STACK_FRAME rPC, rREFS, rFP, CFI_REFS, load_ins=1
1606
1607    // Setup the parameters
1608    cmp r4, #0
1609    beq .Lxmm_setup_finished
1610
1611    sub rINST, rINST, r4
1612    ldr r8, [r0, #ART_METHOD_ACCESS_FLAGS_OFFSET]
1613    lsl rINST, rINST, #2 // rINST is now the offset for inputs into the registers array.
1614    mov rIBASE, ip // rIBASE contains the old stack pointer
1615
1616    tst r8, #ART_METHOD_NTERP_ENTRY_POINT_FAST_PATH_FLAG
1617    beq .Lsetup_slow_path
1618    // Setup pointer to inputs in FP and pointer to inputs in REFS
1619    add lr, rFP, rINST
1620    add r8, rREFS, rINST
1621    mov r0, #0
1622    SETUP_REFERENCE_PARAMETER_IN_GPR r1, lr, r8, r4, r0, .Lxmm_setup_finished
1623    SETUP_REFERENCE_PARAMETER_IN_GPR r2, lr, r8, r4, r0, .Lxmm_setup_finished
1624    SETUP_REFERENCE_PARAMETER_IN_GPR r3, lr, r8, r4, r0, .Lxmm_setup_finished
1625    add rIBASE, rIBASE, #OFFSET_TO_FIRST_ARGUMENT_IN_STACK
1626    SETUP_REFERENCE_PARAMETERS_IN_STACK lr, r8, r4, rIBASE, r0
1627    b .Lxmm_setup_finished
1628
1629.Lsetup_slow_path:
1630    // If the method is not static and there is one argument ('this'), we don't need to fetch the
1631    // shorty.
1632    tst r8, #ART_METHOD_IS_STATIC_FLAG
1633    bne .Lsetup_with_shorty
1634    str r1, [rFP, rINST]
1635    str r1, [rREFS, rINST]
1636    cmp r4, #1
1637    beq .Lxmm_setup_finished
1638
1639.Lsetup_with_shorty:
1640    // Save arguments that were passed before calling into the runtime.
1641    // No need to save r0 (ArtMethod) as we're not using it later in this code.
1642    // Save r4 for stack aligment.
1643    // TODO: Get shorty in a better way and remove below
1644    push {r1-r4}
1645    vpush {s0-s15}
1646    bl NterpGetShorty
1647    vpop {s0-s15}
1648    pop {r1-r4}
1649
1650    mov ip, r8
1651    add r8, rREFS, rINST
1652    add r7, rFP, rINST
1653    mov r4, #0
1654    // Setup shorty, pointer to inputs in FP and pointer to inputs in REFS
1655    add lr, r0, #1  // shorty + 1  ; ie skip return arg character
1656    tst ip, #ART_METHOD_IS_STATIC_FLAG
1657    bne .Lhandle_static_method
1658    add r7, r7, #4
1659    add r8, r8, #4
1660    add rIBASE, rIBASE, #4
1661    b .Lcontinue_setup_gprs
1662.Lhandle_static_method:
1663    LOOP_OVER_SHORTY_STORING_GPRS r1, lr, r4, r7, r8, .Lgpr_setup_finished, .Lif_long, is_r3=0
1664.Lcontinue_setup_gprs:
1665    LOOP_OVER_SHORTY_STORING_GPRS r2, lr, r4, r7, r8, .Lgpr_setup_finished, .Lif_long, is_r3=0
1666    LOOP_OVER_SHORTY_STORING_GPRS r3, lr, r4, r7, r8, .Lgpr_setup_finished, .Lif_long, is_r3=1
1667.Lif_long:
1668    LOOP_OVER_INTs lr, r4, r7, r8, rIBASE, ip, r1, .Lgpr_setup_finished
1669.Lgpr_setup_finished:
1670    add r0, r0, #1  // shorty + 1  ; ie skip return arg character
1671    mov r1, r7
1672    add r2, rIBASE, #OFFSET_TO_FIRST_ARGUMENT_IN_STACK
1673    vpush {s0-s15}
1674    mov r3, sp
1675    bl NterpStoreArm32Fprs
1676    add sp, sp, #(16 * 4)
1677.Lxmm_setup_finished:
1678    CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0)
1679    // r8 was used for setting up the frame, restore it now.
1680    REFRESH_MARKING_REGISTER
1681.Lexecute_instructions:
1682    // Set rIBASE
1683    adr rIBASE, artNterpAsmInstructionStart
1684    /* start executing the instruction at rPC */
1685    START_EXECUTING_INSTRUCTIONS
1686    /* NOTE: no fallthrough */
1687    // cfi info continues, and covers the whole nterp implementation.
1688    SIZE ExecuteNterpImpl
1689
1690%def opcode_pre():
1691
1692%def fetch_from_thread_cache(dest_reg, miss_label):
1693   // Fetch some information from the thread cache.
1694   // Uses ip and lr as temporaries.
1695   add      ip, rSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
1696   ubfx     lr, rPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
1697   add      ip, ip, lr, lsl #3             // entry address within the cache
1698   // In T32, we would use `ldrd ip, \dest_reg, [ip]`
1699   ldr      ${dest_reg}, [ip, #4]          // value (offset)
1700   ldr      ip, [ip]                       // entry key (pc)
1701   cmp      ip, rPC
1702   bne      ${miss_label}
1703
1704%def footer():
1705/*
1706 * ===========================================================================
1707 *  Common subroutines and data
1708 * ===========================================================================
1709 */
1710
1711    .text
1712    .align  2
1713
1714// Enclose all code below in a symbol (which gets printed in backtraces).
1715NAME_START nterp_helper
1716
1717// Note: mterp also uses the common_* names below for helpers, but that's OK
1718// as the assembler compiled each interpreter separately.
1719common_errDivideByZero:
1720    EXPORT_PC
1721    bl art_quick_throw_div_zero
1722
1723// Expect index in r1, length in r3
1724common_errArrayIndex:
1725    EXPORT_PC
1726    mov r0, r1
1727    mov r1, r3
1728    bl art_quick_throw_array_bounds
1729
1730common_errNullObject:
1731    EXPORT_PC
1732    bl art_quick_throw_null_pointer_exception
1733
1734NterpCommonInvokeStatic:
1735    COMMON_INVOKE_NON_RANGE is_static=1, suffix="invokeStatic"
1736
1737NterpCommonInvokeStaticRange:
1738    COMMON_INVOKE_RANGE is_static=1, suffix="invokeStatic"
1739
1740NterpCommonInvokeInstance:
1741    COMMON_INVOKE_NON_RANGE suffix="invokeInstance"
1742
1743NterpCommonInvokeInstanceRange:
1744    COMMON_INVOKE_RANGE suffix="invokeInstance"
1745
1746NterpCommonInvokeInterface:
1747    COMMON_INVOKE_NON_RANGE is_interface=1, suffix="invokeInterface"
1748
1749NterpCommonInvokeInterfaceRange:
1750    COMMON_INVOKE_RANGE is_interface=1, suffix="invokeInterface"
1751
1752NterpCommonInvokePolymorphic:
1753    COMMON_INVOKE_NON_RANGE is_polymorphic=1, suffix="invokePolymorphic"
1754
1755NterpCommonInvokePolymorphicRange:
1756    COMMON_INVOKE_RANGE is_polymorphic=1, suffix="invokePolymorphic"
1757
1758NterpCommonInvokeCustom:
1759    COMMON_INVOKE_NON_RANGE is_static=1, is_custom=1, suffix="invokeCustom"
1760
1761NterpCommonInvokeCustomRange:
1762    COMMON_INVOKE_RANGE is_static=1, is_custom=1, suffix="invokeCustom"
1763
1764NterpHandleStringInit:
1765   COMMON_INVOKE_NON_RANGE is_string_init=1, suffix="stringInit"
1766
1767NterpHandleStringInitRange:
1768   COMMON_INVOKE_RANGE is_string_init=1, suffix="stringInit"
1769
1770
1771NterpHandleHotnessOverflow:
1772    CHECK_AND_UPDATE_SHARED_MEMORY_METHOD if_hot=1f, if_not_hot=5f
17731:
1774    mov r1, rPC
1775    mov r2, rFP
1776    bl nterp_hot_method
1777    cmp r0, #0
1778    bne 3f
17792:
1780    FETCH_INST                          // load rINST
1781    GET_INST_OPCODE ip                  // extract opcode from rINST
1782    GOTO_OPCODE ip                      // jump to next instruction
17833:
1784    // Drop the current frame.
1785    ldr ip, [rREFS, #-4]
1786    mov sp, ip
1787    .cfi_def_cfa sp, CALLEE_SAVES_SIZE
1788
1789    // The transition frame of type SaveAllCalleeSaves saves r4, r8, and r9,
1790    // but not managed ABI. So we need to restore callee-saves of the nterp frame,
1791    // and save managed ABI callee saves, which will be restored by the callee upon
1792    // return.
1793
1794    RESTORE_ALL_CALLEE_SAVES
1795    push {r5-r7, r10-r11, lr}
1796   .cfi_adjust_cfa_offset 24
1797   .cfi_rel_offset r5, 0
1798   .cfi_rel_offset r6, 4
1799   .cfi_rel_offset r7, 8
1800   .cfi_rel_offset r10, 12
1801   .cfi_rel_offset r11, 16
1802   .cfi_rel_offset lr, 20
1803    vpush {s16-s31}
1804    .cfi_adjust_cfa_offset 64
1805
1806    // Setup the new frame
1807    ldr r1, [r0, #OSR_DATA_FRAME_SIZE]
1808    // Given stack size contains all callee saved registers, remove them.
1809    sub r1, r1, #(CALLEE_SAVES_SIZE - 12)
1810
1811    // We know r1 cannot be 0, as it at least contains the ArtMethod.
1812
1813    // Remember CFA in a callee-save register.
1814    mov rINST, sp
1815    .cfi_def_cfa_register rINST
1816
1817    sub sp, sp, r1
1818
1819    add r2, r0, #OSR_DATA_MEMORY
18204:
1821    sub r1, r1, #4
1822    ldr ip, [r2, r1]
1823    str ip, [sp, r1]
1824    cmp r1, #0
1825    bne 4b
1826
1827    // Fetch the native PC to jump to and save it in a callee-save register.
1828    ldr rFP, [r0, #OSR_DATA_NATIVE_PC]
1829
1830    // Free the memory holding OSR Data.
1831    bl free
1832
1833    // Jump to the compiled code.
1834    bx rFP
18355:
1836    DO_SUSPEND_CHECK continue_label=2b
1837    b 2b
1838
1839// This is the logical end of ExecuteNterpImpl, where the frame info applies.
1840// EndExecuteNterpImpl includes the methods below as we want the runtime to
1841// see them as part of the Nterp PCs.
1842.cfi_endproc
1843
1844nterp_to_nterp_static_non_range:
1845    .cfi_startproc
1846    SETUP_STACK_FOR_INVOKE
1847    SETUP_NON_RANGE_ARGUMENTS_AND_EXECUTE is_static=1, is_string_init=0
1848    .cfi_endproc
1849
1850nterp_to_nterp_string_init_non_range:
1851    .cfi_startproc
1852    SETUP_STACK_FOR_INVOKE
1853    SETUP_NON_RANGE_ARGUMENTS_AND_EXECUTE is_static=0, is_string_init=1
1854    .cfi_endproc
1855
1856nterp_to_nterp_instance_non_range:
1857    .cfi_startproc
1858    SETUP_STACK_FOR_INVOKE
1859    SETUP_NON_RANGE_ARGUMENTS_AND_EXECUTE is_static=0, is_string_init=0
1860    .cfi_endproc
1861
1862nterp_to_nterp_static_range:
1863    .cfi_startproc
1864    SETUP_STACK_FOR_INVOKE
1865    SETUP_RANGE_ARGUMENTS_AND_EXECUTE is_static=1, is_string_init=0
1866    .cfi_endproc
1867
1868nterp_to_nterp_string_init_range:
1869    .cfi_startproc
1870    SETUP_STACK_FOR_INVOKE
1871    SETUP_RANGE_ARGUMENTS_AND_EXECUTE is_static=0, is_string_init=1
1872    .cfi_endproc
1873
1874nterp_to_nterp_instance_range:
1875    .cfi_startproc
1876    SETUP_STACK_FOR_INVOKE
1877    SETUP_RANGE_ARGUMENTS_AND_EXECUTE is_static=0, is_string_init=0
1878    .cfi_endproc
1879
1880NAME_END nterp_helper
1881
1882// This is the end of PCs contained by the OatQuickMethodHeader created for the interpreter
1883// entry point.
1884    .type EndExecuteNterpImpl, #function
1885    .hidden EndExecuteNterpImpl
1886    .global EndExecuteNterpImpl
1887EndExecuteNterpImpl:
1888
1889/*
1890 * Convert the double in r0/r1 to a long in r0/r1.
1891 *
1892 * We have to clip values to long min/max per the specification.  The
1893 * expected common case is a "reasonable" value that converts directly
1894 * to modest integer.  The EABI convert function isn't doing this for us.
1895 */
1896ENTRY nterp_d2l_doconv
1897    ubfx    r2, r1, #20, #11            @ grab the exponent
1898    movw    r3, #0x43e
1899    cmp     r2, r3                      @ MINLONG < x > MAXLONG?
1900    bhs     d2l_special_cases
1901    b       __aeabi_d2lz                @ tail call to convert double to long
1902d2l_special_cases:
1903    movw    r3, #0x7ff
1904    cmp     r2, r3
1905    beq     d2l_maybeNaN                @ NaN?
1906d2l_notNaN:
1907    adds    r1, r1, r1                  @ sign bit to carry
1908    mov     r0, #0xffffffff             @ assume maxlong for lsw
1909    mov     r1, #0x7fffffff             @ assume maxlong for msw
1910    adc     r0, r0, #0
1911    adc     r1, r1, #0                  @ convert maxlong to minlong if exp negative
1912    bx      lr                          @ return
1913d2l_maybeNaN:
1914    orrs    r3, r0, r1, lsl #12
1915    beq     d2l_notNaN                  @ if fraction is non-zero, it's a NaN
1916    mov     r0, #0
1917    mov     r1, #0
1918    bx      lr                          @ return 0 for NaN
1919END nterp_d2l_doconv
1920
1921/*
1922 * Convert the float in r0 to a long in r0/r1.
1923 *
1924 * We have to clip values to long min/max per the specification.  The
1925 * expected common case is a "reasonable" value that converts directly
1926 * to modest integer.  The EABI convert function isn't doing this for us.
1927 */
1928ENTRY nterp_f2l_doconv
1929    ubfx    r2, r0, #23, #8             @ grab the exponent
1930    cmp     r2, #0xbe                   @ MININT < x > MAXINT?
1931    bhs     f2l_special_cases
1932    b       __aeabi_f2lz                @ tail call to convert float to long
1933f2l_special_cases:
1934    cmp     r2, #0xff                   @ NaN or infinity?
1935    beq     f2l_maybeNaN
1936f2l_notNaN:
1937    adds    r0, r0, r0                  @ sign bit to carry
1938    mov     r0, #0xffffffff             @ assume maxlong for lsw
1939    mov     r1, #0x7fffffff             @ assume maxlong for msw
1940    adc     r0, r0, #0
1941    adc     r1, r1, #0                  @ convert maxlong to minlong if exp negative
1942    bx      lr                          @ return
1943f2l_maybeNaN:
1944    lsls    r3, r0, #9
1945    beq     f2l_notNaN                  @ if fraction is non-zero, it's a NaN
1946    mov     r0, #0
1947    mov     r1, #0
1948    bx      lr                          @ return 0 for NaN
1949END nterp_f2l_doconv
1950
1951// Entrypoints into runtime.
1952NTERP_TRAMPOLINE nterp_get_static_field, NterpGetStaticField
1953NTERP_TRAMPOLINE nterp_get_instance_field_offset, NterpGetInstanceFieldOffset
1954NTERP_TRAMPOLINE nterp_filled_new_array, NterpFilledNewArray
1955NTERP_TRAMPOLINE nterp_filled_new_array_range, NterpFilledNewArrayRange
1956NTERP_TRAMPOLINE nterp_get_class, NterpGetClass
1957NTERP_TRAMPOLINE nterp_allocate_object, NterpAllocateObject
1958NTERP_TRAMPOLINE nterp_get_method, NterpGetMethod
1959NTERP_TRAMPOLINE nterp_hot_method, NterpHotMethod
1960NTERP_TRAMPOLINE nterp_load_object, NterpLoadObject
1961
1962ENTRY nterp_deliver_pending_exception
1963    DELIVER_PENDING_EXCEPTION
1964END nterp_deliver_pending_exception
1965
1966// gen_mterp.py will inline the following definitions
1967// within [ExecuteNterpImpl, EndExecuteNterpImpl).
1968%def instruction_end():
1969
1970    .type artNterpAsmInstructionEnd, #function
1971    .hidden artNterpAsmInstructionEnd
1972    .global artNterpAsmInstructionEnd
1973artNterpAsmInstructionEnd:
1974    // artNterpAsmInstructionEnd is used as landing pad for exception handling.
1975    FETCH_INST
1976    GET_INST_OPCODE ip
1977    GOTO_OPCODE ip
1978
1979%def instruction_start():
1980
1981    .type artNterpAsmInstructionStart, #function
1982    .hidden artNterpAsmInstructionStart
1983    .global artNterpAsmInstructionStart
1984artNterpAsmInstructionStart = .L_op_nop
1985    .text
1986
1987%def opcode_name_prefix():
1988%   return "nterp_"
1989%def opcode_start():
1990    NAME_START nterp_${opcode}
1991    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
1992    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -4, CALLEE_SAVES_SIZE
1993%def opcode_end():
1994    NAME_END nterp_${opcode}
1995    // Advance to the end of this handler. Causes error if we are past that point.
1996    .org nterp_${opcode} + NTERP_HANDLER_SIZE  // ${opcode} handler is too big!
1997%def opcode_slow_path_start(name):
1998    NAME_START ${name}
1999%def opcode_slow_path_end(name):
2000    NAME_END ${name}
2001