xref: /aosp_15_r20/art/runtime/interpreter/mterp/riscv64/main.S (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker%def header():
2*795d594fSAndroid Build Coastguard Worker/*
3*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2023 The Android Open Source Project
4*795d594fSAndroid Build Coastguard Worker *
5*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
6*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
7*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
8*795d594fSAndroid Build Coastguard Worker *
9*795d594fSAndroid Build Coastguard Worker *      http://www.apache.org/licenses/LICENSE-2.0
10*795d594fSAndroid Build Coastguard Worker *
11*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
12*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
13*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
15*795d594fSAndroid Build Coastguard Worker * limitations under the License.
16*795d594fSAndroid Build Coastguard Worker */
17*795d594fSAndroid Build Coastguard Worker
18*795d594fSAndroid Build Coastguard Worker/*
19*795d594fSAndroid Build Coastguard Worker * This is a #include, not a %include, because we want the C pre-processor
20*795d594fSAndroid Build Coastguard Worker * to expand the macros into assembler assignment statements.
21*795d594fSAndroid Build Coastguard Worker */
22*795d594fSAndroid Build Coastguard Worker#include "asm_support.h"
23*795d594fSAndroid Build Coastguard Worker#include "arch/riscv64/asm_support_riscv64.S"
24*795d594fSAndroid Build Coastguard Worker
25*795d594fSAndroid Build Coastguard Worker/**
26*795d594fSAndroid Build Coastguard Worker * RISC-V 64 ABI general notes
27*795d594fSAndroid Build Coastguard Worker *
28*795d594fSAndroid Build Coastguard Worker * References
29*795d594fSAndroid Build Coastguard Worker * - https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-cc.adoc
30*795d594fSAndroid Build Coastguard Worker * - runtime/arch/riscv64/registers_riscv64.h
31*795d594fSAndroid Build Coastguard Worker *
32*795d594fSAndroid Build Coastguard Worker * 32 general purposes registers
33*795d594fSAndroid Build Coastguard Worker * - fixed purpose: zero, ra, sp, gp, tp, s1
34*795d594fSAndroid Build Coastguard Worker *     gp/scs: shadow call stack - do not clobber!
35*795d594fSAndroid Build Coastguard Worker *     s1/tr: ART thread register - do not clobber!
36*795d594fSAndroid Build Coastguard Worker * - temporaries: t0-t6
37*795d594fSAndroid Build Coastguard Worker * - arguments: a0-a7
38*795d594fSAndroid Build Coastguard Worker * - callee saved: ra, s0/fp, s2-s11
39*795d594fSAndroid Build Coastguard Worker *     s0 is flexible, available to use as a frame pointer if needed.
40*795d594fSAndroid Build Coastguard Worker *
41*795d594fSAndroid Build Coastguard Worker * 32 floating point registers
42*795d594fSAndroid Build Coastguard Worker * - temporaries: ft0-ft11
43*795d594fSAndroid Build Coastguard Worker * - arguments: fa0-fa7
44*795d594fSAndroid Build Coastguard Worker * - callee saved: fs0-fs11
45*795d594fSAndroid Build Coastguard Worker */
46*795d594fSAndroid Build Coastguard Worker
47*795d594fSAndroid Build Coastguard Worker// Android references
48*795d594fSAndroid Build Coastguard Worker//   Bytecodes: https://source.android.com/docs/core/runtime/dalvik-bytecode
49*795d594fSAndroid Build Coastguard Worker//   Instruction formats: https://source.android.com/docs/core/runtime/instruction-formats
50*795d594fSAndroid Build Coastguard Worker//   Shorty: https://source.android.com/docs/core/runtime/dex-format#shortydescriptor
51*795d594fSAndroid Build Coastguard Worker
52*795d594fSAndroid Build Coastguard Worker// Fixed register usages in Nterp.
53*795d594fSAndroid Build Coastguard Worker//    nickname  ABI    reg   purpose
54*795d594fSAndroid Build Coastguard Worker#define xSELF    s1  // x9,   Thread* self pointer
55*795d594fSAndroid Build Coastguard Worker#define xFP      s2  // x18,  interpreted frame pointer: to access locals and args
56*795d594fSAndroid Build Coastguard Worker#define xPC      s3  // x19,  interpreted program counter: to fetch instructions
57*795d594fSAndroid Build Coastguard Worker#define xINST    s4  // x20,  first 16-bit code unit of current instruction
58*795d594fSAndroid Build Coastguard Worker#define xIBASE   s5  // x21,  interpreted instruction base pointer: for computed goto
59*795d594fSAndroid Build Coastguard Worker#define xREFS    s6  // x22,  base of object references of dex registers
60*795d594fSAndroid Build Coastguard Worker
61*795d594fSAndroid Build Coastguard Worker// DWARF registers reference
62*795d594fSAndroid Build Coastguard Worker// https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-dwarf.adoc
63*795d594fSAndroid Build Coastguard Worker#define CFI_TMP  10  // DWARF register number for       a0/x10
64*795d594fSAndroid Build Coastguard Worker#define CFI_DEX  19  // DWARF register number for xPC  /s3/x19
65*795d594fSAndroid Build Coastguard Worker#define CFI_REFS 22  // DWARF register number for xREFS/s6/x22
66*795d594fSAndroid Build Coastguard Worker
67*795d594fSAndroid Build Coastguard Worker// Synchronization
68*795d594fSAndroid Build Coastguard Worker// This code follows the RISC-V atomics ABI specification [1].
69*795d594fSAndroid Build Coastguard Worker//
70*795d594fSAndroid Build Coastguard Worker// Object publication.
71*795d594fSAndroid Build Coastguard Worker// new-instance and new-array operations must first perform a `fence w,w` "constructor fence" to
72*795d594fSAndroid Build Coastguard Worker// ensure their new object references are correctly published with a subsequent SET_VREG_OBJECT.
73*795d594fSAndroid Build Coastguard Worker//
74*795d594fSAndroid Build Coastguard Worker// Volatile load/store.
75*795d594fSAndroid Build Coastguard Worker// A volatile load is implemented as: fence rw,rw ; load ; fence r,rw.
76*795d594fSAndroid Build Coastguard Worker// A 32-bit or 64-bit volatile store is implemented as: amoswap.{w,d}.rl
77*795d594fSAndroid Build Coastguard Worker// A volatile store for a narrower type is implemented as: fence rw,w ; store ; fence rw,rw
78*795d594fSAndroid Build Coastguard Worker//
79*795d594fSAndroid Build Coastguard Worker// [1] https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-atomic.adoc
80*795d594fSAndroid Build Coastguard Worker
81*795d594fSAndroid Build Coastguard Worker// An assembly entry for nterp.
82*795d594fSAndroid Build Coastguard Worker.macro OAT_ENTRY name
83*795d594fSAndroid Build Coastguard Worker    .type \name, @function
84*795d594fSAndroid Build Coastguard Worker    .hidden \name
85*795d594fSAndroid Build Coastguard Worker    .global \name
86*795d594fSAndroid Build Coastguard Worker    .balign 16
87*795d594fSAndroid Build Coastguard Worker\name:
88*795d594fSAndroid Build Coastguard Worker.endm
89*795d594fSAndroid Build Coastguard Worker
90*795d594fSAndroid Build Coastguard Worker.macro SIZE name
91*795d594fSAndroid Build Coastguard Worker    .size \name, .-\name
92*795d594fSAndroid Build Coastguard Worker.endm
93*795d594fSAndroid Build Coastguard Worker
94*795d594fSAndroid Build Coastguard Worker// Similar to ENTRY but without the CFI directives.
95*795d594fSAndroid Build Coastguard Worker.macro NAME_START name
96*795d594fSAndroid Build Coastguard Worker    .type \name, @function
97*795d594fSAndroid Build Coastguard Worker    .hidden \name  // Hide this as a global symbol, so we do not incur plt calls.
98*795d594fSAndroid Build Coastguard Worker    .global \name
99*795d594fSAndroid Build Coastguard Worker    /* Cache alignment for function entry */
100*795d594fSAndroid Build Coastguard Worker    .balign 16
101*795d594fSAndroid Build Coastguard Worker\name:
102*795d594fSAndroid Build Coastguard Worker.endm
103*795d594fSAndroid Build Coastguard Worker
104*795d594fSAndroid Build Coastguard Worker.macro NAME_END name
105*795d594fSAndroid Build Coastguard Worker  SIZE \name
106*795d594fSAndroid Build Coastguard Worker.endm
107*795d594fSAndroid Build Coastguard Worker
108*795d594fSAndroid Build Coastguard Worker// Macro for defining entrypoints into runtime. We don't need to save registers (we're not holding
109*795d594fSAndroid Build Coastguard Worker// references there), but there is no kDontSave runtime method. So just use the kSaveRefsOnly
110*795d594fSAndroid Build Coastguard Worker// runtime method.
111*795d594fSAndroid Build Coastguard Worker.macro NTERP_TRAMPOLINE name, helper
112*795d594fSAndroid Build Coastguard WorkerENTRY \name
113*795d594fSAndroid Build Coastguard Worker    SETUP_SAVE_REFS_ONLY_FRAME
114*795d594fSAndroid Build Coastguard Worker    call \helper
115*795d594fSAndroid Build Coastguard Worker    RESTORE_SAVE_REFS_ONLY_FRAME
116*795d594fSAndroid Build Coastguard Worker    ld t0, THREAD_EXCEPTION_OFFSET(xSELF)
117*795d594fSAndroid Build Coastguard Worker    bnez t0, nterp_deliver_pending_exception
118*795d594fSAndroid Build Coastguard Worker    ret
119*795d594fSAndroid Build Coastguard WorkerEND \name
120*795d594fSAndroid Build Coastguard Worker.endm
121*795d594fSAndroid Build Coastguard Worker
122*795d594fSAndroid Build Coastguard Worker// Unpack code items from dex format.
123*795d594fSAndroid Build Coastguard Worker// Input: \code_item
124*795d594fSAndroid Build Coastguard Worker// Output:
125*795d594fSAndroid Build Coastguard Worker//   - \regs: register count
126*795d594fSAndroid Build Coastguard Worker//   - \outs: out count
127*795d594fSAndroid Build Coastguard Worker//   - \ins: in count. If set to register "zero" (x0), load is skipped.
128*795d594fSAndroid Build Coastguard Worker//   - \code_item: holds instruction array on exit
129*795d594fSAndroid Build Coastguard Worker.macro FETCH_CODE_ITEM_INFO code_item, regs, outs, ins
130*795d594fSAndroid Build Coastguard Worker    // Unpack values from regular dex format.
131*795d594fSAndroid Build Coastguard Worker    lhu \regs, CODE_ITEM_REGISTERS_SIZE_OFFSET(\code_item)
132*795d594fSAndroid Build Coastguard Worker    lhu \outs, CODE_ITEM_OUTS_SIZE_OFFSET(\code_item)
133*795d594fSAndroid Build Coastguard Worker    .ifnc \ins, zero
134*795d594fSAndroid Build Coastguard Worker      lhu \ins, CODE_ITEM_INS_SIZE_OFFSET(\code_item)
135*795d594fSAndroid Build Coastguard Worker    .endif
136*795d594fSAndroid Build Coastguard Worker    addi \code_item, \code_item, CODE_ITEM_INSNS_OFFSET
137*795d594fSAndroid Build Coastguard Worker.endm
138*795d594fSAndroid Build Coastguard Worker
139*795d594fSAndroid Build Coastguard Worker.macro EXPORT_PC
140*795d594fSAndroid Build Coastguard Worker    sd xPC, -16(xREFS)
141*795d594fSAndroid Build Coastguard Worker.endm
142*795d594fSAndroid Build Coastguard Worker
143*795d594fSAndroid Build Coastguard Worker.macro TEST_IF_MARKING reg, label
144*795d594fSAndroid Build Coastguard Worker    lb \reg, THREAD_IS_GC_MARKING_OFFSET(xSELF)
145*795d594fSAndroid Build Coastguard Worker    bnez \reg, \label
146*795d594fSAndroid Build Coastguard Worker.endm
147*795d594fSAndroid Build Coastguard Worker
148*795d594fSAndroid Build Coastguard Worker.macro DO_SUSPEND_CHECK continue
149*795d594fSAndroid Build Coastguard Worker    lwu t0, THREAD_FLAGS_OFFSET(xSELF)
150*795d594fSAndroid Build Coastguard Worker    andi t0, t0, THREAD_SUSPEND_OR_CHECKPOINT_REQUEST
151*795d594fSAndroid Build Coastguard Worker    beqz t0, \continue
152*795d594fSAndroid Build Coastguard Worker    EXPORT_PC
153*795d594fSAndroid Build Coastguard Worker    call art_quick_test_suspend
154*795d594fSAndroid Build Coastguard Worker.endm
155*795d594fSAndroid Build Coastguard Worker
156*795d594fSAndroid Build Coastguard Worker// Fetch one or more half-word units from an offset past the current PC.
157*795d594fSAndroid Build Coastguard Worker// The offset is specified in 16-bit code units.
158*795d594fSAndroid Build Coastguard Worker//
159*795d594fSAndroid Build Coastguard Worker// A \width flag allows reading 32 bits (2 units) or 64 bits (4 units) from the offset.
160*795d594fSAndroid Build Coastguard Worker// The RISC-V ISA supports unaligned accesses for these wider loads.
161*795d594fSAndroid Build Coastguard Worker//
162*795d594fSAndroid Build Coastguard Worker// If \width=8, \byte={0,1} indexes into the code unit at the offset.
163*795d594fSAndroid Build Coastguard Worker//
164*795d594fSAndroid Build Coastguard Worker// Default behavior loads one code unit with unsigned zext.
165*795d594fSAndroid Build Coastguard Worker// The \signed flag is for signed sext, for shorter loads.
166*795d594fSAndroid Build Coastguard Worker//
167*795d594fSAndroid Build Coastguard Worker// Does not advance xPC.
168*795d594fSAndroid Build Coastguard Worker.macro FETCH reg, count, signed=0, width=16, byte=0
169*795d594fSAndroid Build Coastguard Worker    .if \width == 8
170*795d594fSAndroid Build Coastguard Worker      .if \signed
171*795d594fSAndroid Build Coastguard Worker        lb  \reg, (\count*2 + \byte)(xPC)
172*795d594fSAndroid Build Coastguard Worker      .else
173*795d594fSAndroid Build Coastguard Worker        lbu \reg, (\count*2 + \byte)(xPC)
174*795d594fSAndroid Build Coastguard Worker      .endif
175*795d594fSAndroid Build Coastguard Worker    .elseif \width == 16
176*795d594fSAndroid Build Coastguard Worker      .if \signed
177*795d594fSAndroid Build Coastguard Worker        lh  \reg, (\count*2)(xPC)
178*795d594fSAndroid Build Coastguard Worker      .else
179*795d594fSAndroid Build Coastguard Worker        lhu \reg, (\count*2)(xPC)
180*795d594fSAndroid Build Coastguard Worker      .endif
181*795d594fSAndroid Build Coastguard Worker    .elseif \width == 32
182*795d594fSAndroid Build Coastguard Worker      .if \signed
183*795d594fSAndroid Build Coastguard Worker        lw  \reg, (\count*2)(xPC)
184*795d594fSAndroid Build Coastguard Worker      .else
185*795d594fSAndroid Build Coastguard Worker        lwu \reg, (\count*2)(xPC)
186*795d594fSAndroid Build Coastguard Worker      .endif
187*795d594fSAndroid Build Coastguard Worker    .elseif \width == 64
188*795d594fSAndroid Build Coastguard Worker      ld  \reg, (\count*2)(xPC)
189*795d594fSAndroid Build Coastguard Worker    .else
190*795d594fSAndroid Build Coastguard Worker      unimp  // impossible
191*795d594fSAndroid Build Coastguard Worker    .endif
192*795d594fSAndroid Build Coastguard Worker.endm
193*795d594fSAndroid Build Coastguard Worker
194*795d594fSAndroid Build Coastguard Worker// Fetch the next instruction, from xPC into xINST.
195*795d594fSAndroid Build Coastguard Worker// Does not advance xPC.
196*795d594fSAndroid Build Coastguard Worker.macro FETCH_INST
197*795d594fSAndroid Build Coastguard Worker    lhu xINST, (xPC)  // zero in upper 48 bits
198*795d594fSAndroid Build Coastguard Worker.endm
199*795d594fSAndroid Build Coastguard Worker
200*795d594fSAndroid Build Coastguard Worker// Fetch the next instruction, from xPC into xINST. Advance xPC by \count units, each 2 bytes.
201*795d594fSAndroid Build Coastguard Worker//
202*795d594fSAndroid Build Coastguard Worker// Immediates have a 12-bit offset range from xPC. Thus, \count can range from -1024 to 1023.
203*795d594fSAndroid Build Coastguard Worker//
204*795d594fSAndroid Build Coastguard Worker// Note: Must be placed AFTER anything that can throw an exception, or the exception catch may miss.
205*795d594fSAndroid Build Coastguard Worker// Thus, this macro must be placed after EXPORT_PC.
206*795d594fSAndroid Build Coastguard Worker.macro FETCH_ADVANCE_INST count
207*795d594fSAndroid Build Coastguard Worker    lhu xINST, (\count*2)(xPC)  // zero in upper 48 bits
208*795d594fSAndroid Build Coastguard Worker    addi xPC, xPC, (\count*2)
209*795d594fSAndroid Build Coastguard Worker.endm
210*795d594fSAndroid Build Coastguard Worker
211*795d594fSAndroid Build Coastguard Worker// Clobbers: \reg
212*795d594fSAndroid Build Coastguard Worker.macro GET_INST_OPCODE reg
213*795d594fSAndroid Build Coastguard Worker    and \reg, xINST, 0xFF
214*795d594fSAndroid Build Coastguard Worker.endm
215*795d594fSAndroid Build Coastguard Worker
216*795d594fSAndroid Build Coastguard Worker// Clobbers: \reg
217*795d594fSAndroid Build Coastguard Worker.macro GOTO_OPCODE reg
218*795d594fSAndroid Build Coastguard Worker    slliw \reg, \reg, ${handler_size_bits}
219*795d594fSAndroid Build Coastguard Worker    add \reg, xIBASE, \reg
220*795d594fSAndroid Build Coastguard Worker    jr \reg
221*795d594fSAndroid Build Coastguard Worker.endm
222*795d594fSAndroid Build Coastguard Worker
223*795d594fSAndroid Build Coastguard Worker.macro FETCH_FROM_THREAD_CACHE reg, miss_label, z0, z1
224*795d594fSAndroid Build Coastguard Worker    // See art::InterpreterCache::IndexOf() for computing index of key within cache array.
225*795d594fSAndroid Build Coastguard Worker    // Entry address:
226*795d594fSAndroid Build Coastguard Worker    //   xSELF + OFFSET + ((xPC>>2 & xFF) << 4)
227*795d594fSAndroid Build Coastguard Worker    // = xSELF + OFFSET + ((xPC & xFF<<2) << 2)
228*795d594fSAndroid Build Coastguard Worker    // = xSELF + ((OFFSET>>2 + (xPC & xFF<<2)) << 2)
229*795d594fSAndroid Build Coastguard Worker    // => ANDI, ADD, SH2ADD
230*795d594fSAndroid Build Coastguard Worker#if (THREAD_INTERPRETER_CACHE_SIZE_LOG2 != 8)
231*795d594fSAndroid Build Coastguard Worker#error Expected interpreter cache array size = 256 elements
232*795d594fSAndroid Build Coastguard Worker#endif
233*795d594fSAndroid Build Coastguard Worker#if (THREAD_INTERPRETER_CACHE_SIZE_SHIFT != 2)
234*795d594fSAndroid Build Coastguard Worker#error Expected interpreter cache entry size = 16 bytes
235*795d594fSAndroid Build Coastguard Worker#endif
236*795d594fSAndroid Build Coastguard Worker#if ((THREAD_INTERPRETER_CACHE_OFFSET & 0x3) != 0)
237*795d594fSAndroid Build Coastguard Worker#error Expected interpreter cache offset to be 4-byte aligned
238*795d594fSAndroid Build Coastguard Worker#endif
239*795d594fSAndroid Build Coastguard Worker    andi \z0, xPC, 0xFF << 2
240*795d594fSAndroid Build Coastguard Worker    addi \z0, \z0, THREAD_INTERPRETER_CACHE_OFFSET >> 2
241*795d594fSAndroid Build Coastguard Worker    sh2add \z0, \z0, xSELF  // z0 := entry's address
242*795d594fSAndroid Build Coastguard Worker    ld \z1, (\z0)           // z1 := dex PC
243*795d594fSAndroid Build Coastguard Worker    bne xPC, \z1, \miss_label
244*795d594fSAndroid Build Coastguard Worker    ld \reg, 8(\z0)         // value: depends on context; see call site
245*795d594fSAndroid Build Coastguard Worker.endm
246*795d594fSAndroid Build Coastguard Worker
247*795d594fSAndroid Build Coastguard Worker// Inputs:
248*795d594fSAndroid Build Coastguard Worker//   - a0
249*795d594fSAndroid Build Coastguard Worker//   - xSELF
250*795d594fSAndroid Build Coastguard Worker// Clobbers: t0
251*795d594fSAndroid Build Coastguard Worker.macro CHECK_AND_UPDATE_SHARED_MEMORY_METHOD if_hot, if_not_hot
252*795d594fSAndroid Build Coastguard Worker    // TODO(solanes): Figure out if there's a way to load t0 only once.
253*795d594fSAndroid Build Coastguard Worker    lwu t0, ART_METHOD_ACCESS_FLAGS_OFFSET(a0)
254*795d594fSAndroid Build Coastguard Worker    BRANCH_IF_BIT_CLEAR t0, t0, ART_METHOD_IS_MEMORY_SHARED_FLAG_BIT, \if_hot
255*795d594fSAndroid Build Coastguard Worker    lwu t0, ART_METHOD_ACCESS_FLAGS_OFFSET(a0)
256*795d594fSAndroid Build Coastguard Worker    // Intrinsics are always in the boot image and considered hot.
257*795d594fSAndroid Build Coastguard Worker    BRANCH_IF_BIT_SET t0, t0, ART_METHOD_IS_INTRINSIC_FLAG_BIT, \if_hot
258*795d594fSAndroid Build Coastguard Worker    lwu t0, THREAD_SHARED_METHOD_HOTNESS_OFFSET(xSELF)  // t0 := hotness
259*795d594fSAndroid Build Coastguard Worker    beqz t0, \if_hot
260*795d594fSAndroid Build Coastguard Worker
261*795d594fSAndroid Build Coastguard Worker    addi t0, t0, -1  // increase hotness
262*795d594fSAndroid Build Coastguard Worker    sw t0,  THREAD_SHARED_METHOD_HOTNESS_OFFSET(xSELF)
263*795d594fSAndroid Build Coastguard Worker    j \if_not_hot
264*795d594fSAndroid Build Coastguard Worker.endm
265*795d594fSAndroid Build Coastguard Worker
266*795d594fSAndroid Build Coastguard Worker// Update xPC by \units code units. On back edges, perform hotness and suspend.
267*795d594fSAndroid Build Coastguard Worker.macro BRANCH units
268*795d594fSAndroid Build Coastguard Worker    sh1add xPC, \units, xPC
269*795d594fSAndroid Build Coastguard Worker    blez \units, 2f  // If branch is <= 0, increase hotness and do a suspend check.
270*795d594fSAndroid Build Coastguard Worker1:
271*795d594fSAndroid Build Coastguard Worker    FETCH_INST
272*795d594fSAndroid Build Coastguard Worker    GET_INST_OPCODE t0
273*795d594fSAndroid Build Coastguard Worker    GOTO_OPCODE t0
274*795d594fSAndroid Build Coastguard Worker2:
275*795d594fSAndroid Build Coastguard Worker    ld a0, (sp)
276*795d594fSAndroid Build Coastguard Worker    lhu t0, ART_METHOD_HOTNESS_COUNT_OFFSET(a0)  // t0 := hotness
277*795d594fSAndroid Build Coastguard Worker#if (NTERP_HOTNESS_VALUE != 0)
278*795d594fSAndroid Build Coastguard Worker#error Expected 0 for hotness value
279*795d594fSAndroid Build Coastguard Worker#endif
280*795d594fSAndroid Build Coastguard Worker    // If the counter is at zero (hot), handle it in the runtime.
281*795d594fSAndroid Build Coastguard Worker    beqz t0, 3f
282*795d594fSAndroid Build Coastguard Worker    addi t0, t0, -1  // increase hotness
283*795d594fSAndroid Build Coastguard Worker    sh t0, ART_METHOD_HOTNESS_COUNT_OFFSET(a0)
284*795d594fSAndroid Build Coastguard Worker    DO_SUSPEND_CHECK continue=1b
285*795d594fSAndroid Build Coastguard Worker    j 1b
286*795d594fSAndroid Build Coastguard Worker3:
287*795d594fSAndroid Build Coastguard Worker    tail NterpHandleHotnessOverflow  // arg a0 (ArtMethod*)
288*795d594fSAndroid Build Coastguard Worker.endm
289*795d594fSAndroid Build Coastguard Worker
290*795d594fSAndroid Build Coastguard Worker// Increase method hotness before starting the method.
291*795d594fSAndroid Build Coastguard Worker// Hardcoded:
292*795d594fSAndroid Build Coastguard Worker// - a0: ArtMethod*
293*795d594fSAndroid Build Coastguard Worker// Clobbers: t0
294*795d594fSAndroid Build Coastguard Worker.macro START_EXECUTING_INSTRUCTIONS
295*795d594fSAndroid Build Coastguard Worker    ld a0, (sp)
296*795d594fSAndroid Build Coastguard Worker    lhu t0, ART_METHOD_HOTNESS_COUNT_OFFSET(a0)  // t0 := hotness
297*795d594fSAndroid Build Coastguard Worker#if (NTERP_HOTNESS_VALUE != 0)
298*795d594fSAndroid Build Coastguard Worker#error Expected 0 for hotness value
299*795d594fSAndroid Build Coastguard Worker#endif
300*795d594fSAndroid Build Coastguard Worker    // If the counter is at zero (hot), handle it in the runtime.
301*795d594fSAndroid Build Coastguard Worker    beqz t0, 3f
302*795d594fSAndroid Build Coastguard Worker    addi t0, t0, -1  // increase hotness
303*795d594fSAndroid Build Coastguard Worker    sh t0, ART_METHOD_HOTNESS_COUNT_OFFSET(a0)
304*795d594fSAndroid Build Coastguard Worker1:
305*795d594fSAndroid Build Coastguard Worker    DO_SUSPEND_CHECK continue=2f
306*795d594fSAndroid Build Coastguard Worker2:
307*795d594fSAndroid Build Coastguard Worker    FETCH_INST
308*795d594fSAndroid Build Coastguard Worker    GET_INST_OPCODE t0
309*795d594fSAndroid Build Coastguard Worker    GOTO_OPCODE t0
310*795d594fSAndroid Build Coastguard Worker3:
311*795d594fSAndroid Build Coastguard Worker    CHECK_AND_UPDATE_SHARED_MEMORY_METHOD if_hot=4f, if_not_hot=1b
312*795d594fSAndroid Build Coastguard Worker4:
313*795d594fSAndroid Build Coastguard Worker    mv a1, zero  // dex_pc_ptr=nullptr
314*795d594fSAndroid Build Coastguard Worker    mv a2, zero  // vergs=nullptr
315*795d594fSAndroid Build Coastguard Worker    call nterp_hot_method
316*795d594fSAndroid Build Coastguard Worker    j 2b
317*795d594fSAndroid Build Coastguard Worker.endm
318*795d594fSAndroid Build Coastguard Worker
319*795d594fSAndroid Build Coastguard Worker// 64 bit read
320*795d594fSAndroid Build Coastguard Worker// Clobbers: \reg
321*795d594fSAndroid Build Coastguard Worker// Safe if \reg == \vreg.
322*795d594fSAndroid Build Coastguard Worker.macro GET_VREG_WIDE reg, vreg
323*795d594fSAndroid Build Coastguard Worker    sh2add \reg, \vreg, xFP  // vreg addr in register array
324*795d594fSAndroid Build Coastguard Worker    ld \reg, (\reg)          // reg := fp[vreg](lo) | fp[vreg+1](hi)
325*795d594fSAndroid Build Coastguard Worker.endm
326*795d594fSAndroid Build Coastguard Worker
327*795d594fSAndroid Build Coastguard Worker// 64 bit write
328*795d594fSAndroid Build Coastguard Worker// Clobbers: z0
329*795d594fSAndroid Build Coastguard Worker.macro SET_VREG_WIDE reg, vreg, z0
330*795d594fSAndroid Build Coastguard Worker    sh2add \z0, \vreg, xFP    // vreg addr in register array
331*795d594fSAndroid Build Coastguard Worker    sd \reg, (\z0)            // fp[vreg] := reg(lo) ; fp[vreg+1] := reg(hi)
332*795d594fSAndroid Build Coastguard Worker    sh2add \z0, \vreg, xREFS  // vreg addr in reference array
333*795d594fSAndroid Build Coastguard Worker    sd zero, (\z0)            // refs[vreg] := null ; refs[vreg+1] := null
334*795d594fSAndroid Build Coastguard Worker.endm
335*795d594fSAndroid Build Coastguard Worker
336*795d594fSAndroid Build Coastguard Worker// Object read
337*795d594fSAndroid Build Coastguard Worker// Clobbers: \reg
338*795d594fSAndroid Build Coastguard Worker// Safe if \reg == \vreg.
339*795d594fSAndroid Build Coastguard Worker.macro GET_VREG_OBJECT reg, vreg
340*795d594fSAndroid Build Coastguard Worker    sh2add \reg, \vreg, xREFS  // vreg addr in reference array
341*795d594fSAndroid Build Coastguard Worker    lwu \reg, (\reg)           // reg := refs[vreg]
342*795d594fSAndroid Build Coastguard Worker.endm
343*795d594fSAndroid Build Coastguard Worker
344*795d594fSAndroid Build Coastguard Worker// Object write
345*795d594fSAndroid Build Coastguard Worker// Clobbers: z0
346*795d594fSAndroid Build Coastguard Worker.macro SET_VREG_OBJECT reg, vreg, z0
347*795d594fSAndroid Build Coastguard Worker    sh2add \z0, \vreg, xFP    // vreg addr in register array
348*795d594fSAndroid Build Coastguard Worker    sw \reg, (\z0)            // fp[vreg] := reg
349*795d594fSAndroid Build Coastguard Worker    sh2add \z0, \vreg, xREFS  // vreg addr in reference array
350*795d594fSAndroid Build Coastguard Worker    sw \reg, (\z0)            // refs[vreg] := reg
351*795d594fSAndroid Build Coastguard Worker.endm
352*795d594fSAndroid Build Coastguard Worker
353*795d594fSAndroid Build Coastguard Worker// Floating-point 64 bit read
354*795d594fSAndroid Build Coastguard Worker// Clobbers: \reg, \vreg
355*795d594fSAndroid Build Coastguard Worker.macro GET_VREG_DOUBLE reg, vreg
356*795d594fSAndroid Build Coastguard Worker    sh2add \vreg, \vreg, xFP  // vreg addr in register array
357*795d594fSAndroid Build Coastguard Worker    fld \reg, (\vreg)         // reg := fp[vreg](lo) | fp[vreg+1](hi)
358*795d594fSAndroid Build Coastguard Worker.endm
359*795d594fSAndroid Build Coastguard Worker
360*795d594fSAndroid Build Coastguard Worker// Floating-point 64 bit write
361*795d594fSAndroid Build Coastguard Worker// Clobbers: \reg, z0
362*795d594fSAndroid Build Coastguard Worker.macro SET_VREG_DOUBLE reg, vreg, z0
363*795d594fSAndroid Build Coastguard Worker    sh2add \z0, \vreg, xFP    // vreg addr in register array
364*795d594fSAndroid Build Coastguard Worker    fsd \reg, (\z0)           // fp[vreg] := reg(lo) ; fp[vreg+1] := reg(hi)
365*795d594fSAndroid Build Coastguard Worker    sh2add \z0, \vreg, xREFS  // vreg addr in reference array
366*795d594fSAndroid Build Coastguard Worker    sd zero, (\z0)            // refs[vreg] := null ; refs[vreg+1] := null
367*795d594fSAndroid Build Coastguard Worker.endm
368*795d594fSAndroid Build Coastguard Worker
369*795d594fSAndroid Build Coastguard Worker// Put "%def" definitions after ".macro" definitions for proper expansion. %def is greedy.
370*795d594fSAndroid Build Coastguard Worker
371*795d594fSAndroid Build Coastguard Worker// Typed read, defaults to 32-bit read
372*795d594fSAndroid Build Coastguard Worker// Note: An object ref requires LWU, or LW;ZEXT.W.
373*795d594fSAndroid Build Coastguard Worker// Clobbers: \reg
374*795d594fSAndroid Build Coastguard Worker// Safe if \reg == \vreg.
375*795d594fSAndroid Build Coastguard Worker%def get_vreg(reg, vreg, width=32, is_wide=False, is_unsigned=False):
376*795d594fSAndroid Build Coastguard Worker%  if is_wide or width == 64:
377*795d594fSAndroid Build Coastguard Worker     GET_VREG_WIDE $reg, $vreg
378*795d594fSAndroid Build Coastguard Worker%  elif is_unsigned:
379*795d594fSAndroid Build Coastguard Worker     sh2add $reg, $vreg, xFP  // vreg addr in register array
380*795d594fSAndroid Build Coastguard Worker     lwu $reg, ($reg)         // reg := fp[vreg], zext
381*795d594fSAndroid Build Coastguard Worker%  else:
382*795d594fSAndroid Build Coastguard Worker     sh2add $reg, $vreg, xFP  // vreg addr in register array
383*795d594fSAndroid Build Coastguard Worker     lw $reg, ($reg)          // reg := fp[vreg]
384*795d594fSAndroid Build Coastguard Worker%#:
385*795d594fSAndroid Build Coastguard Worker
386*795d594fSAndroid Build Coastguard Worker// Typed write, defaults to 32-bit write.
387*795d594fSAndroid Build Coastguard Worker// Note: Incorrect for an object ref; it requires 2nd SW into xREFS.
388*795d594fSAndroid Build Coastguard Worker// Clobbers: z0
389*795d594fSAndroid Build Coastguard Worker%def set_vreg(reg, vreg, z0, width=32, is_wide=False):
390*795d594fSAndroid Build Coastguard Worker%  if is_wide or width == 64:
391*795d594fSAndroid Build Coastguard Worker     SET_VREG_WIDE $reg, $vreg, $z0
392*795d594fSAndroid Build Coastguard Worker%  else:
393*795d594fSAndroid Build Coastguard Worker     sh2add $z0, $vreg, xFP    // vreg addr in register array
394*795d594fSAndroid Build Coastguard Worker     sw $reg, ($z0)            // fp[vreg] := reg
395*795d594fSAndroid Build Coastguard Worker     sh2add $z0, $vreg, xREFS  // vreg addr in reference array
396*795d594fSAndroid Build Coastguard Worker     sw zero, ($z0)            // refs[vreg] := null
397*795d594fSAndroid Build Coastguard Worker%#:
398*795d594fSAndroid Build Coastguard Worker
399*795d594fSAndroid Build Coastguard Worker// Floating-point read, defaults to 32-bit read.
400*795d594fSAndroid Build Coastguard Worker// Clobbers: reg, vreg
401*795d594fSAndroid Build Coastguard Worker%def get_vreg_float(reg, vreg, is_double=False):
402*795d594fSAndroid Build Coastguard Worker%  if is_double:
403*795d594fSAndroid Build Coastguard Worker     GET_VREG_DOUBLE $reg, $vreg
404*795d594fSAndroid Build Coastguard Worker%  else:
405*795d594fSAndroid Build Coastguard Worker     sh2add $vreg, $vreg, xFP  // vreg addr in register array
406*795d594fSAndroid Build Coastguard Worker     flw $reg, ($vreg)         // reg := fp[vreg]
407*795d594fSAndroid Build Coastguard Worker%#:
408*795d594fSAndroid Build Coastguard Worker
409*795d594fSAndroid Build Coastguard Worker// Floating-point write, defaults to 32-bit write.
410*795d594fSAndroid Build Coastguard Worker// Clobbers: reg, z0
411*795d594fSAndroid Build Coastguard Worker%def set_vreg_float(reg, vreg, z0, is_double=False):
412*795d594fSAndroid Build Coastguard Worker%  if is_double:
413*795d594fSAndroid Build Coastguard Worker     SET_VREG_DOUBLE $reg, $vreg, $z0
414*795d594fSAndroid Build Coastguard Worker%  else:
415*795d594fSAndroid Build Coastguard Worker     sh2add $z0, $vreg, xFP    // vreg addr in register array
416*795d594fSAndroid Build Coastguard Worker     fsw $reg, ($z0)           // fp[vreg] := reg
417*795d594fSAndroid Build Coastguard Worker     sh2add $z0, $vreg, xREFS  // vreg addr in reference array
418*795d594fSAndroid Build Coastguard Worker     sw zero, ($z0)            // refs[vreg] := null
419*795d594fSAndroid Build Coastguard Worker%#:
420*795d594fSAndroid Build Coastguard Worker
421*795d594fSAndroid Build Coastguard Worker%def entry():
422*795d594fSAndroid Build Coastguard Worker/*
423*795d594fSAndroid Build Coastguard Worker * ArtMethod entry point.
424*795d594fSAndroid Build Coastguard Worker *
425*795d594fSAndroid Build Coastguard Worker * On entry:
426*795d594fSAndroid Build Coastguard Worker *  a0     ArtMethod* callee
427*795d594fSAndroid Build Coastguard Worker *  a1-a7  method parameters
428*795d594fSAndroid Build Coastguard Worker */
429*795d594fSAndroid Build Coastguard WorkerOAT_ENTRY ExecuteNterpWithClinitImpl
430*795d594fSAndroid Build Coastguard Worker#if MIRROR_CLASS_STATUS_SHIFT < 12
431*795d594fSAndroid Build Coastguard Worker#error mirror class status bits cannot use LUI load technique
432*795d594fSAndroid Build Coastguard Worker#endif
433*795d594fSAndroid Build Coastguard Worker    .cfi_startproc
434*795d594fSAndroid Build Coastguard Worker    // For simplicity, we don't do a read barrier here, but instead rely
435*795d594fSAndroid Build Coastguard Worker    // on art_quick_resolution_trampoline to always have a suspend point before
436*795d594fSAndroid Build Coastguard Worker    // calling back here.
437*795d594fSAndroid Build Coastguard Worker    lwu t0, ART_METHOD_DECLARING_CLASS_OFFSET(a0)
438*795d594fSAndroid Build Coastguard Worker    lw t1, MIRROR_CLASS_STATUS_OFFSET(t0)  // t1 := status word, sext
439*795d594fSAndroid Build Coastguard Worker    lui t2, MIRROR_CLASS_STATUS_VISIBLY_INITIALIZED << (MIRROR_CLASS_STATUS_SHIFT - 12)
440*795d594fSAndroid Build Coastguard Worker    // The unsigned comparison works in tandem with the 64-bit sign-extension of
441*795d594fSAndroid Build Coastguard Worker    // the status bits at the top of the 32-bit word. The order of the status
442*795d594fSAndroid Build Coastguard Worker    // constants (sign extended from LUI) is unchanged with unsigned comparison.
443*795d594fSAndroid Build Coastguard Worker    bgeu t1, t2, ExecuteNterpImpl
444*795d594fSAndroid Build Coastguard Worker    lui t2, MIRROR_CLASS_STATUS_INITIALIZED << (MIRROR_CLASS_STATUS_SHIFT - 12)
445*795d594fSAndroid Build Coastguard Worker    bltu t1, t2, .Linitializing_check
446*795d594fSAndroid Build Coastguard Worker    fence w, w
447*795d594fSAndroid Build Coastguard Worker    j ExecuteNterpImpl
448*795d594fSAndroid Build Coastguard Worker.Linitializing_check:
449*795d594fSAndroid Build Coastguard Worker    lui t2, MIRROR_CLASS_STATUS_INITIALIZING << (MIRROR_CLASS_STATUS_SHIFT - 12)
450*795d594fSAndroid Build Coastguard Worker    bltu t1, t2, .Lresolution_trampoline
451*795d594fSAndroid Build Coastguard Worker    lwu t1, MIRROR_CLASS_CLINIT_THREAD_ID_OFFSET(t0)
452*795d594fSAndroid Build Coastguard Worker    lwu t0, THREAD_TID_OFFSET(xSELF)
453*795d594fSAndroid Build Coastguard Worker    beq t0, t1, ExecuteNterpImpl
454*795d594fSAndroid Build Coastguard Worker.Lresolution_trampoline:
455*795d594fSAndroid Build Coastguard Worker    tail art_quick_resolution_trampoline
456*795d594fSAndroid Build Coastguard Worker    .cfi_endproc
457*795d594fSAndroid Build Coastguard Worker    .type EndExecuteNterpWithClinitImpl, @function
458*795d594fSAndroid Build Coastguard Worker    .hidden EndExecuteNterpWithClinitImpl
459*795d594fSAndroid Build Coastguard Worker    .global EndExecuteNterpWithClinitImpl
460*795d594fSAndroid Build Coastguard WorkerEndExecuteNterpWithClinitImpl:
461*795d594fSAndroid Build Coastguard Worker
462*795d594fSAndroid Build Coastguard WorkerOAT_ENTRY ExecuteNterpImpl
463*795d594fSAndroid Build Coastguard Worker   .cfi_startproc
464*795d594fSAndroid Build Coastguard Worker%  setup_nterp_frame(cfi_refs="CFI_REFS", refs="xREFS", fp="xFP", pc="xPC", regs="s7", ins="s8", spills_sp="s9", z0="t0", z1="t1", z2="t2", z3="t3", uniq="entry")
465*795d594fSAndroid Build Coastguard Worker                            // xREFS := callee refs array
466*795d594fSAndroid Build Coastguard Worker                            // xFP   := callee fp array
467*795d594fSAndroid Build Coastguard Worker                            // xPC   := callee dex array
468*795d594fSAndroid Build Coastguard Worker                            // s7    := refs/fp vreg count
469*795d594fSAndroid Build Coastguard Worker                            // s8    := ins count
470*795d594fSAndroid Build Coastguard Worker                            // s9    := post-spills pre-frame sp
471*795d594fSAndroid Build Coastguard Worker                            // sp    := post-frame sp
472*795d594fSAndroid Build Coastguard Worker   CFI_DEFINE_DEX_PC_WITH_OFFSET(/*tmpReg*/CFI_TMP, /*dexReg*/CFI_DEX, /*dexOffset*/0)
473*795d594fSAndroid Build Coastguard Worker
474*795d594fSAndroid Build Coastguard Worker   // Fast path: zero args.
475*795d594fSAndroid Build Coastguard Worker   beqz s8, .Lentry_go
476*795d594fSAndroid Build Coastguard Worker
477*795d594fSAndroid Build Coastguard Worker   sub s7, s7, s8           // s7 := a1 index in fp/refs
478*795d594fSAndroid Build Coastguard Worker   lwu s10, ART_METHOD_ACCESS_FLAGS_OFFSET(a0)
479*795d594fSAndroid Build Coastguard Worker                            // s10 := method flags
480*795d594fSAndroid Build Coastguard Worker
481*795d594fSAndroid Build Coastguard Worker   // Fast path: all reference args.
482*795d594fSAndroid Build Coastguard Worker   sh2add t0, s7, xFP       // t0 := &xFP[a1]
483*795d594fSAndroid Build Coastguard Worker   sh2add t1, s7, xREFS     // t1 := &xREFS[a1]
484*795d594fSAndroid Build Coastguard Worker   BRANCH_IF_BIT_CLEAR t2, s10, ART_METHOD_NTERP_ENTRY_POINT_FAST_PATH_FLAG_BIT, .Lentry_a1
485*795d594fSAndroid Build Coastguard Worker%  setup_ref_args_and_go(fp="t0", refs="t1", refs_end="xFP", spills_sp="s9", z0="t2", z1="t3", done=".Lentry_go")
486*795d594fSAndroid Build Coastguard Worker
487*795d594fSAndroid Build Coastguard Worker   // Fast path: instance with zero args.
488*795d594fSAndroid Build Coastguard Worker.Lentry_a1:
489*795d594fSAndroid Build Coastguard Worker   bexti s10, s10, ART_METHOD_IS_STATIC_FLAG_BIT
490*795d594fSAndroid Build Coastguard Worker                            // s10 := 1 if static, 0 if instance
491*795d594fSAndroid Build Coastguard Worker   bnez s10, .Lentry_shorty
492*795d594fSAndroid Build Coastguard Worker   sw a1, (t0)
493*795d594fSAndroid Build Coastguard Worker   sw a1, (t1)
494*795d594fSAndroid Build Coastguard Worker   li t2, 1
495*795d594fSAndroid Build Coastguard Worker   beq s8, t2, .Lentry_go
496*795d594fSAndroid Build Coastguard Worker
497*795d594fSAndroid Build Coastguard Worker   // Slow path: runtime call to obtain shorty, full setup from managed ABI.
498*795d594fSAndroid Build Coastguard Worker.Lentry_shorty:
499*795d594fSAndroid Build Coastguard Worker   SPILL_ALL_ARGUMENTS
500*795d594fSAndroid Build Coastguard Worker   // TODO: Better way to get shorty
501*795d594fSAndroid Build Coastguard Worker   call NterpGetShorty      // arg a0
502*795d594fSAndroid Build Coastguard Worker   mv s11, a0               // s11 := shorty
503*795d594fSAndroid Build Coastguard Worker   RESTORE_ALL_ARGUMENTS
504*795d594fSAndroid Build Coastguard Worker
505*795d594fSAndroid Build Coastguard Worker   // temporaries are trashed, recompute some values
506*795d594fSAndroid Build Coastguard Worker   sh2add t0, s7, xFP       // t0 := &xFP[a1]
507*795d594fSAndroid Build Coastguard Worker   sh2add t1, s7, xREFS     // t1 := &xREFS[a1]
508*795d594fSAndroid Build Coastguard Worker   addi t2, s11, 1          // t2 := shorty arg (skip return type)
509*795d594fSAndroid Build Coastguard Worker   xori s10, s10, 1         // s10 := 0 if static, 1 if instance
510*795d594fSAndroid Build Coastguard Worker   slliw t3, s10, 2         // t3 := (static) 0, (instance) 4: fp/refs/outs byte offset
511*795d594fSAndroid Build Coastguard Worker   // constant setup for gpr/fpr shorty comparisons
512*795d594fSAndroid Build Coastguard Worker   li s0, 'D'               // s0 := double char (unused fp)
513*795d594fSAndroid Build Coastguard Worker   li s4, 'F'               // s4 := float char (unused xINST)
514*795d594fSAndroid Build Coastguard Worker   li s5, 'J'               // s5 := long char (unused xIBASE)
515*795d594fSAndroid Build Coastguard Worker   li s8, 'L'               // s8 := ref char (unused ins count)
516*795d594fSAndroid Build Coastguard Worker   bnez s10, .Lentry_args   // instance a1 already stored into callee's xFP and xREFS
517*795d594fSAndroid Build Coastguard Worker
518*795d594fSAndroid Build Coastguard Worker%  store_gpr_to_vreg(gpr="a1", offset="t3", shorty="t2", fp="t0", refs="t1", z0="t4", z1="t5", D="s0", F="s4", J="s5", L="s8", next=".Lentry_fargs")
519*795d594fSAndroid Build Coastguard Worker
520*795d594fSAndroid Build Coastguard Worker.Lentry_args:
521*795d594fSAndroid Build Coastguard Worker   // linear scan through shorty: extract non-float args
522*795d594fSAndroid Build Coastguard Worker%  store_gpr_to_vreg(gpr="a2", offset="t3", shorty="t2", fp="t0", refs="t1", z0="t4", z1="t5", D="s0", F="s4", J="s5", L="s8", next=".Lentry_fargs")
523*795d594fSAndroid Build Coastguard Worker%  store_gpr_to_vreg(gpr="a3", offset="t3", shorty="t2", fp="t0", refs="t1", z0="t4", z1="t5", D="s0", F="s4", J="s5", L="s8", next=".Lentry_fargs")
524*795d594fSAndroid Build Coastguard Worker%  store_gpr_to_vreg(gpr="a4", offset="t3", shorty="t2", fp="t0", refs="t1", z0="t4", z1="t5", D="s0", F="s4", J="s5", L="s8", next=".Lentry_fargs")
525*795d594fSAndroid Build Coastguard Worker%  store_gpr_to_vreg(gpr="a5", offset="t3", shorty="t2", fp="t0", refs="t1", z0="t4", z1="t5", D="s0", F="s4", J="s5", L="s8", next=".Lentry_fargs")
526*795d594fSAndroid Build Coastguard Worker%  store_gpr_to_vreg(gpr="a6", offset="t3", shorty="t2", fp="t0", refs="t1", z0="t4", z1="t5", D="s0", F="s4", J="s5", L="s8", next=".Lentry_fargs")
527*795d594fSAndroid Build Coastguard Worker%  store_gpr_to_vreg(gpr="a7", offset="t3", shorty="t2", fp="t0", refs="t1", z0="t4", z1="t5", D="s0", F="s4", J="s5", L="s8", next=".Lentry_fargs")
528*795d594fSAndroid Build Coastguard Worker   // We drained arg registers, so continue from caller stack's out array. Unlike the reference-only
529*795d594fSAndroid Build Coastguard Worker   // fast-path, the continuation offset in the out array can vary, depending on the presence of
530*795d594fSAndroid Build Coastguard Worker   // 64-bit values in the arg registers. \offset tracks this value as a byte offset.
531*795d594fSAndroid Build Coastguard Worker   addi t5, s9, (NTERP_SIZE_SAVE_CALLEE_SAVES + 8)
532*795d594fSAndroid Build Coastguard Worker                            // t5 := (caller) outs array base address
533*795d594fSAndroid Build Coastguard Worker   add t4, t3, t0           // t4 := (callee) &FP[next]
534*795d594fSAndroid Build Coastguard Worker   add t1, t3, t1           // t1 := (callee) &REFS[next]
535*795d594fSAndroid Build Coastguard Worker   add t3, t3, t5           // t3 := (caller) &OUTS[next]
536*795d594fSAndroid Build Coastguard Worker%  store_outs_to_vregs(outs="t3", shorty="t2", fp="t4", refs="t1", z0="t5", z1="t6", D="s0", F="s4", J="s5", L="s8", next=".Lentry_fargs")
537*795d594fSAndroid Build Coastguard Worker                            // t0 = &xFP[a1], unclobbered
538*795d594fSAndroid Build Coastguard Worker.Lentry_fargs:
539*795d594fSAndroid Build Coastguard Worker   addi t1, s11, 1          // t1 := shorty arg (skip return type)
540*795d594fSAndroid Build Coastguard Worker   slliw t2, s10, 2         // t2 := starting byte offset for fp/outs, static and instance
541*795d594fSAndroid Build Coastguard Worker   // linear scan through shorty: extract float args
542*795d594fSAndroid Build Coastguard Worker%  store_fpr_to_vreg(fpr="fa0", offset="t2", shorty="t1", fp="t0", z0="t3", z1="t4", D="s0", F="s4", J="s5", next=".Lentry_go")
543*795d594fSAndroid Build Coastguard Worker%  store_fpr_to_vreg(fpr="fa1", offset="t2", shorty="t1", fp="t0", z0="t3", z1="t4", D="s0", F="s4", J="s5", next=".Lentry_go")
544*795d594fSAndroid Build Coastguard Worker%  store_fpr_to_vreg(fpr="fa2", offset="t2", shorty="t1", fp="t0", z0="t3", z1="t4", D="s0", F="s4", J="s5", next=".Lentry_go")
545*795d594fSAndroid Build Coastguard Worker%  store_fpr_to_vreg(fpr="fa3", offset="t2", shorty="t1", fp="t0", z0="t3", z1="t4", D="s0", F="s4", J="s5", next=".Lentry_go")
546*795d594fSAndroid Build Coastguard Worker%  store_fpr_to_vreg(fpr="fa4", offset="t2", shorty="t1", fp="t0", z0="t3", z1="t4", D="s0", F="s4", J="s5", next=".Lentry_go")
547*795d594fSAndroid Build Coastguard Worker%  store_fpr_to_vreg(fpr="fa5", offset="t2", shorty="t1", fp="t0", z0="t3", z1="t4", D="s0", F="s4", J="s5", next=".Lentry_go")
548*795d594fSAndroid Build Coastguard Worker%  store_fpr_to_vreg(fpr="fa6", offset="t2", shorty="t1", fp="t0", z0="t3", z1="t4", D="s0", F="s4", J="s5", next=".Lentry_go")
549*795d594fSAndroid Build Coastguard Worker%  store_fpr_to_vreg(fpr="fa7", offset="t2", shorty="t1", fp="t0", z0="t3", z1="t4", D="s0", F="s4", J="s5", next=".Lentry_go")
550*795d594fSAndroid Build Coastguard Worker   addi t3, s9, (NTERP_SIZE_SAVE_CALLEE_SAVES + 8)
551*795d594fSAndroid Build Coastguard Worker                            // t3 := (caller) outs array base address
552*795d594fSAndroid Build Coastguard Worker   add t0, t2, t0           // t0 := (callee) &FP[next]
553*795d594fSAndroid Build Coastguard Worker   add t2, t2, t3           // t2 := (caller) &OUTS[next]
554*795d594fSAndroid Build Coastguard Worker%  store_float_outs_to_vregs(outs="t2", shorty="t1", fp="t0", z0="t3", D="s0", F="s4", J="s5", next=".Lentry_go")
555*795d594fSAndroid Build Coastguard Worker
556*795d594fSAndroid Build Coastguard Worker.Lentry_go:
557*795d594fSAndroid Build Coastguard Worker    la xIBASE, artNterpAsmInstructionStart
558*795d594fSAndroid Build Coastguard Worker    START_EXECUTING_INSTRUCTIONS
559*795d594fSAndroid Build Coastguard Worker    // NOTE: no fallthrough
560*795d594fSAndroid Build Coastguard Worker    // cfi info continues, and covers the whole nterp implementation.
561*795d594fSAndroid Build Coastguard Worker    SIZE ExecuteNterpImpl
562*795d594fSAndroid Build Coastguard Worker
563*795d594fSAndroid Build Coastguard Worker%def footer():
564*795d594fSAndroid Build Coastguard Worker/*
565*795d594fSAndroid Build Coastguard Worker * ===========================================================================
566*795d594fSAndroid Build Coastguard Worker *  Common subroutines and data
567*795d594fSAndroid Build Coastguard Worker * ===========================================================================
568*795d594fSAndroid Build Coastguard Worker */
569*795d594fSAndroid Build Coastguard Worker
570*795d594fSAndroid Build Coastguard Worker    .text
571*795d594fSAndroid Build Coastguard Worker    .align  2
572*795d594fSAndroid Build Coastguard Worker
573*795d594fSAndroid Build Coastguard Worker
574*795d594fSAndroid Build Coastguard Worker// Enclose all code below in a symbol (which gets printed in backtraces).
575*795d594fSAndroid Build Coastguard WorkerNAME_START nterp_helper
576*795d594fSAndroid Build Coastguard Worker
577*795d594fSAndroid Build Coastguard Workercommon_errArrayIndex:
578*795d594fSAndroid Build Coastguard Worker    EXPORT_PC
579*795d594fSAndroid Build Coastguard Worker    // CALL preserves RA for stack walking.
580*795d594fSAndroid Build Coastguard Worker    call art_quick_throw_array_bounds  // args a0 (index), a1 (length)
581*795d594fSAndroid Build Coastguard Worker
582*795d594fSAndroid Build Coastguard Workercommon_errDivideByZero:
583*795d594fSAndroid Build Coastguard Worker    EXPORT_PC
584*795d594fSAndroid Build Coastguard Worker    // CALL preserves RA for stack walking.
585*795d594fSAndroid Build Coastguard Worker    call art_quick_throw_div_zero
586*795d594fSAndroid Build Coastguard Worker
587*795d594fSAndroid Build Coastguard Workercommon_errNullObject:
588*795d594fSAndroid Build Coastguard Worker    EXPORT_PC
589*795d594fSAndroid Build Coastguard Worker    // CALL preserves RA for stack walking.
590*795d594fSAndroid Build Coastguard Worker    call art_quick_throw_null_pointer_exception
591*795d594fSAndroid Build Coastguard Worker
592*795d594fSAndroid Build Coastguard WorkerNterpInvokeVirtual:
593*795d594fSAndroid Build Coastguard Worker%  nterp_invoke_virtual()
594*795d594fSAndroid Build Coastguard WorkerNterpInvokeSuper:
595*795d594fSAndroid Build Coastguard Worker%  nterp_invoke_super()
596*795d594fSAndroid Build Coastguard WorkerNterpInvokeDirect:
597*795d594fSAndroid Build Coastguard Worker%  nterp_invoke_direct()
598*795d594fSAndroid Build Coastguard WorkerNterpInvokeStringInit:
599*795d594fSAndroid Build Coastguard Worker%  nterp_invoke_string_init()
600*795d594fSAndroid Build Coastguard WorkerNterpInvokeStatic:
601*795d594fSAndroid Build Coastguard Worker%  nterp_invoke_static()
602*795d594fSAndroid Build Coastguard WorkerNterpInvokeInterface:
603*795d594fSAndroid Build Coastguard Worker%  nterp_invoke_interface()
604*795d594fSAndroid Build Coastguard WorkerNterpInvokePolymorphic:
605*795d594fSAndroid Build Coastguard Worker%  nterp_invoke_polymorphic()
606*795d594fSAndroid Build Coastguard WorkerNterpInvokeCustom:
607*795d594fSAndroid Build Coastguard Worker%  nterp_invoke_custom()
608*795d594fSAndroid Build Coastguard WorkerNterpInvokeVirtualRange:
609*795d594fSAndroid Build Coastguard Worker%  nterp_invoke_virtual_range()
610*795d594fSAndroid Build Coastguard WorkerNterpInvokeSuperRange:
611*795d594fSAndroid Build Coastguard Worker%  nterp_invoke_super_range()
612*795d594fSAndroid Build Coastguard WorkerNterpInvokeDirectRange:
613*795d594fSAndroid Build Coastguard Worker%  nterp_invoke_direct_range()
614*795d594fSAndroid Build Coastguard WorkerNterpInvokeStringInitRange:
615*795d594fSAndroid Build Coastguard Worker%  nterp_invoke_string_init_range()
616*795d594fSAndroid Build Coastguard WorkerNterpInvokeStaticRange:
617*795d594fSAndroid Build Coastguard Worker%  nterp_invoke_static_range()
618*795d594fSAndroid Build Coastguard WorkerNterpInvokeInterfaceRange:
619*795d594fSAndroid Build Coastguard Worker%  nterp_invoke_interface_range()
620*795d594fSAndroid Build Coastguard WorkerNterpInvokePolymorphicRange:
621*795d594fSAndroid Build Coastguard Worker%  nterp_invoke_polymorphic_range()
622*795d594fSAndroid Build Coastguard WorkerNterpInvokeCustomRange:
623*795d594fSAndroid Build Coastguard Worker%  nterp_invoke_custom_range()
624*795d594fSAndroid Build Coastguard Worker
625*795d594fSAndroid Build Coastguard Worker// Arg a0: ArtMethod*
626*795d594fSAndroid Build Coastguard WorkerNterpHandleHotnessOverflow:
627*795d594fSAndroid Build Coastguard Worker   CHECK_AND_UPDATE_SHARED_MEMORY_METHOD if_hot=.Lhotspill_hot, if_not_hot=.Lhotspill_suspend
628*795d594fSAndroid Build Coastguard Worker.Lhotspill_hot:
629*795d594fSAndroid Build Coastguard Worker   mv a1, xPC
630*795d594fSAndroid Build Coastguard Worker   mv a2, xFP
631*795d594fSAndroid Build Coastguard Worker   call nterp_hot_method  // args a0, a1, a2
632*795d594fSAndroid Build Coastguard Worker   bnez a0, .Lhotspill_osr
633*795d594fSAndroid Build Coastguard Worker.Lhotspill_advance:
634*795d594fSAndroid Build Coastguard Worker   FETCH_INST
635*795d594fSAndroid Build Coastguard Worker   GET_INST_OPCODE t0
636*795d594fSAndroid Build Coastguard Worker   GOTO_OPCODE t0
637*795d594fSAndroid Build Coastguard Worker.Lhotspill_osr:
638*795d594fSAndroid Build Coastguard Worker   // a0 = OsrData*
639*795d594fSAndroid Build Coastguard Worker   // Drop most of the current nterp frame, but keep the callee-saves.
640*795d594fSAndroid Build Coastguard Worker   // The nterp callee-saves (count and layout) match the OSR frame's callee-saves.
641*795d594fSAndroid Build Coastguard Worker   ld sp, -8(xREFS)  // caller's interpreted frame pointer
642*795d594fSAndroid Build Coastguard Worker   .cfi_def_cfa sp, NTERP_SIZE_SAVE_CALLEE_SAVES
643*795d594fSAndroid Build Coastguard Worker   lwu t0, OSR_DATA_FRAME_SIZE(a0)
644*795d594fSAndroid Build Coastguard Worker   addi t0, t0, -NTERP_SIZE_SAVE_CALLEE_SAVES  // t0 := osr frame - callee saves, in bytes
645*795d594fSAndroid Build Coastguard Worker   mv s7, sp         // Remember CFA in a callee-save register.
646*795d594fSAndroid Build Coastguard Worker   .cfi_def_cfa_register s7
647*795d594fSAndroid Build Coastguard Worker   sub sp, sp, t0    // OSR size guaranteed to be stack aligned (16 bytes).
648*795d594fSAndroid Build Coastguard Worker
649*795d594fSAndroid Build Coastguard Worker   addi t1, a0, OSR_DATA_MEMORY  // t1 := read start
650*795d594fSAndroid Build Coastguard Worker   add t1, t1, t0                // t1 := read end (exclusive)
651*795d594fSAndroid Build Coastguard Worker   mv t2, s7                     // t2 := write end (exclusive)
652*795d594fSAndroid Build Coastguard Worker   // t0 >= 8 (OSR places ArtMethod* at bottom of frame), so loop will terminate.
653*795d594fSAndroid Build Coastguard Worker.Lhotspill_osr_copy_loop:
654*795d594fSAndroid Build Coastguard Worker   addi t1, t1, -8
655*795d594fSAndroid Build Coastguard Worker   ld t3, (t1)
656*795d594fSAndroid Build Coastguard Worker   addi t2, t2, -8
657*795d594fSAndroid Build Coastguard Worker   sd t3, (t2)
658*795d594fSAndroid Build Coastguard Worker   bne t2, sp, .Lhotspill_osr_copy_loop
659*795d594fSAndroid Build Coastguard Worker
660*795d594fSAndroid Build Coastguard Worker   ld s8, OSR_DATA_NATIVE_PC(a0)  // s8 := native PC; jump after free
661*795d594fSAndroid Build Coastguard Worker   call free  // arg a0; release OsrData*
662*795d594fSAndroid Build Coastguard Worker   jr s8      // Jump to the compiled code.
663*795d594fSAndroid Build Coastguard Worker.Lhotspill_suspend:
664*795d594fSAndroid Build Coastguard Worker   DO_SUSPEND_CHECK continue=.Lhotspill_advance
665*795d594fSAndroid Build Coastguard Worker   j .Lhotspill_advance
666*795d594fSAndroid Build Coastguard Worker
667*795d594fSAndroid Build Coastguard Worker// This is the logical end of ExecuteNterpImpl, where the frame info applies.
668*795d594fSAndroid Build Coastguard Worker.cfi_endproc
669*795d594fSAndroid Build Coastguard Worker
670*795d594fSAndroid Build Coastguard WorkerNterpToNterpInstance:
671*795d594fSAndroid Build Coastguard Worker%  nterp_to_nterp_instance()
672*795d594fSAndroid Build Coastguard WorkerNterpToNterpStringInit:
673*795d594fSAndroid Build Coastguard Worker%  nterp_to_nterp_string_init()
674*795d594fSAndroid Build Coastguard WorkerNterpToNterpStatic:
675*795d594fSAndroid Build Coastguard Worker%  nterp_to_nterp_static()
676*795d594fSAndroid Build Coastguard WorkerNterpToNterpInstanceRange:
677*795d594fSAndroid Build Coastguard Worker%  nterp_to_nterp_instance_range()
678*795d594fSAndroid Build Coastguard WorkerNterpToNterpStringInitRange:
679*795d594fSAndroid Build Coastguard Worker%  nterp_to_nterp_string_init_range()
680*795d594fSAndroid Build Coastguard WorkerNterpToNterpStaticRange:
681*795d594fSAndroid Build Coastguard Worker%  nterp_to_nterp_static_range()
682*795d594fSAndroid Build Coastguard Worker
683*795d594fSAndroid Build Coastguard WorkerNAME_END nterp_helper
684*795d594fSAndroid Build Coastguard Worker
685*795d594fSAndroid Build Coastguard Worker// EndExecuteNterpImpl includes the methods after .cfi_endproc, as we want the runtime to see them
686*795d594fSAndroid Build Coastguard Worker// as part of the Nterp PCs. This label marks the end of PCs contained by the OatQuickMethodHeader
687*795d594fSAndroid Build Coastguard Worker// created for the interpreter entry point.
688*795d594fSAndroid Build Coastguard Worker    .type EndExecuteNterpImpl, @function
689*795d594fSAndroid Build Coastguard Worker    .hidden EndExecuteNterpImpl
690*795d594fSAndroid Build Coastguard Worker    .global EndExecuteNterpImpl
691*795d594fSAndroid Build Coastguard WorkerEndExecuteNterpImpl:
692*795d594fSAndroid Build Coastguard Worker
693*795d594fSAndroid Build Coastguard Worker// Entrypoints into runtime.
694*795d594fSAndroid Build Coastguard WorkerNTERP_TRAMPOLINE nterp_allocate_object, NterpAllocateObject
695*795d594fSAndroid Build Coastguard WorkerNTERP_TRAMPOLINE nterp_filled_new_array, NterpFilledNewArray
696*795d594fSAndroid Build Coastguard WorkerNTERP_TRAMPOLINE nterp_filled_new_array_range, NterpFilledNewArrayRange
697*795d594fSAndroid Build Coastguard WorkerNTERP_TRAMPOLINE nterp_get_class, NterpGetClass
698*795d594fSAndroid Build Coastguard WorkerNTERP_TRAMPOLINE nterp_get_instance_field_offset, NterpGetInstanceFieldOffset
699*795d594fSAndroid Build Coastguard WorkerNTERP_TRAMPOLINE nterp_get_method, NterpGetMethod
700*795d594fSAndroid Build Coastguard WorkerNTERP_TRAMPOLINE nterp_get_static_field, NterpGetStaticField
701*795d594fSAndroid Build Coastguard WorkerNTERP_TRAMPOLINE nterp_hot_method, NterpHotMethod
702*795d594fSAndroid Build Coastguard WorkerNTERP_TRAMPOLINE nterp_load_object, NterpLoadObject
703*795d594fSAndroid Build Coastguard Worker
704*795d594fSAndroid Build Coastguard WorkerENTRY nterp_deliver_pending_exception
705*795d594fSAndroid Build Coastguard Worker    DELIVER_PENDING_EXCEPTION
706*795d594fSAndroid Build Coastguard WorkerEND nterp_deliver_pending_exception
707*795d594fSAndroid Build Coastguard Worker
708*795d594fSAndroid Build Coastguard Worker// gen_mterp.py will inline the following definitions
709*795d594fSAndroid Build Coastguard Worker// within [ExecuteNterpImpl, EndExecuteNterpImpl).
710*795d594fSAndroid Build Coastguard Worker%def instruction_start():
711*795d594fSAndroid Build Coastguard Worker    .type artNterpAsmInstructionStart, @function
712*795d594fSAndroid Build Coastguard Worker    .hidden artNterpAsmInstructionStart
713*795d594fSAndroid Build Coastguard Worker    .global artNterpAsmInstructionStart
714*795d594fSAndroid Build Coastguard WorkerartNterpAsmInstructionStart = .L_op_nop
715*795d594fSAndroid Build Coastguard Worker    .text
716*795d594fSAndroid Build Coastguard Worker
717*795d594fSAndroid Build Coastguard Worker%def instruction_end():
718*795d594fSAndroid Build Coastguard Worker    .type artNterpAsmInstructionEnd, @function
719*795d594fSAndroid Build Coastguard Worker    .hidden artNterpAsmInstructionEnd
720*795d594fSAndroid Build Coastguard Worker    .global artNterpAsmInstructionEnd
721*795d594fSAndroid Build Coastguard WorkerartNterpAsmInstructionEnd:
722*795d594fSAndroid Build Coastguard Worker    // artNterpAsmInstructionEnd is used as landing pad for exception handling.
723*795d594fSAndroid Build Coastguard Worker    // xPC (S3) for the exception handler was set just prior to the long jump coming here.
724*795d594fSAndroid Build Coastguard Worker    FETCH_INST
725*795d594fSAndroid Build Coastguard Worker    GET_INST_OPCODE t0
726*795d594fSAndroid Build Coastguard Worker    GOTO_OPCODE t0
727*795d594fSAndroid Build Coastguard Worker
728*795d594fSAndroid Build Coastguard Worker%def opcode_pre():
729*795d594fSAndroid Build Coastguard Worker%   pass
730*795d594fSAndroid Build Coastguard Worker%def opcode_name_prefix():
731*795d594fSAndroid Build Coastguard Worker%   return "nterp_"
732*795d594fSAndroid Build Coastguard Worker%def opcode_start():
733*795d594fSAndroid Build Coastguard Worker    NAME_START nterp_${opcode}
734*795d594fSAndroid Build Coastguard Worker%def opcode_end():
735*795d594fSAndroid Build Coastguard Worker    NAME_END nterp_${opcode}
736*795d594fSAndroid Build Coastguard Worker%def opcode_slow_path_start(name):
737*795d594fSAndroid Build Coastguard Worker    NAME_START ${name}
738*795d594fSAndroid Build Coastguard Worker%def opcode_slow_path_end(name):
739*795d594fSAndroid Build Coastguard Worker    NAME_END ${name}
740