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