1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ART_RUNTIME_ARCH_RISCV64_CALLEE_SAVE_FRAME_RISCV64_H_ 18 #define ART_RUNTIME_ARCH_RISCV64_CALLEE_SAVE_FRAME_RISCV64_H_ 19 20 #include "arch/instruction_set.h" 21 #include "base/bit_utils.h" 22 #include "base/callee_save_type.h" 23 #include "base/enums.h" 24 #include "quick/quick_method_frame_info.h" 25 #include "registers_riscv64.h" 26 #include "runtime_globals.h" 27 28 namespace art { 29 namespace riscv64 { 30 31 static constexpr uint32_t kRiscv64CalleeSaveAlwaysSpills = 32 (1 << art::riscv64::RA); // Return address 33 // Callee-saved registers except for SP and S1 (SP is callee-saved according to RISC-V spec, but 34 // it cannot contain object reference, and S1(TR) is excluded as the ART thread register). 35 static constexpr uint32_t kRiscv64CalleeSaveRefSpills = 36 (1 << art::riscv64::S0) | (1 << art::riscv64::S2) | (1 << art::riscv64::S3) | 37 (1 << art::riscv64::S4) | (1 << art::riscv64::S5) | (1 << art::riscv64::S6) | 38 (1 << art::riscv64::S7) | (1 << art::riscv64::S8) | (1 << art::riscv64::S9) | 39 (1 << art::riscv64::S10) | (1 << art::riscv64::S11); 40 // Stack pointer SP is excluded (although it is callee-saved by calling convention) because it is 41 // restored by the code logic and not from a stack frame. 42 static constexpr uint32_t kRiscv64CalleeSaveAllSpills = 0; 43 // Argument registers except X10/A0 (which contains method pointer). 44 static constexpr uint32_t kRiscv64CalleeSaveArgSpills = 45 (1 << art::riscv64::A1) | (1 << art::riscv64::A2) | (1 << art::riscv64::A3) | 46 (1 << art::riscv64::A4) | (1 << art::riscv64::A5) | (1 << art::riscv64::A6) | 47 (1 << art::riscv64::A7); 48 // All registers except SP, immutable Zero, unallocatable TP and GP, and the ART thread register TR. 49 static constexpr uint32_t kRiscv64CalleeSaveEverythingSpills = 50 (1 << art::riscv64::T0) | (1 << art::riscv64::T1) | (1 << art::riscv64::T2) | 51 (1 << art::riscv64::T3) | (1 << art::riscv64::T4) | (1 << art::riscv64::T5) | 52 (1 << art::riscv64::T6) | (1 << art::riscv64::A0) | (1 << art::riscv64::A1) | 53 (1 << art::riscv64::A2) | (1 << art::riscv64::A3) | (1 << art::riscv64::A4) | 54 (1 << art::riscv64::A5) | (1 << art::riscv64::A6) | (1 << art::riscv64::A7); 55 56 // No references in floating-point registers. 57 static constexpr uint32_t kRiscv64CalleeSaveFpSpills = 0; 58 // Floating-point argument registers FA0 - FA7. 59 static constexpr uint32_t kRiscv64CalleeSaveFpArgSpills = 60 (1 << art::riscv64::FA0) | (1 << art::riscv64::FA1) | (1 << art::riscv64::FA2) | 61 (1 << art::riscv64::FA3) | (1 << art::riscv64::FA4) | (1 << art::riscv64::FA5) | 62 (1 << art::riscv64::FA6) | (1 << art::riscv64::FA7); 63 // Floating-point callee-saved registers FS0 - FS11. 64 static constexpr uint32_t kRiscv64CalleeSaveFpAllSpills = 65 (1 << art::riscv64::FS0) | (1 << art::riscv64::FS1) | (1 << art::riscv64::FS2) | 66 (1 << art::riscv64::FS3) | (1 << art::riscv64::FS4) | (1 << art::riscv64::FS5) | 67 (1 << art::riscv64::FS6) | (1 << art::riscv64::FS7) | (1 << art::riscv64::FS8) | 68 (1 << art::riscv64::FS9) | (1 << art::riscv64::FS10) | (1 << art::riscv64::FS11); 69 // All floating-point registers. 70 static constexpr uint32_t kRiscv64CalleeSaveFpEverythingSpills = 71 (1 << art::riscv64::FT0) | (1 << art::riscv64::FT1) | (1 << art::riscv64::FT2) | 72 (1 << art::riscv64::FT3) | (1 << art::riscv64::FT4) | (1 << art::riscv64::FT5) | 73 (1 << art::riscv64::FT6) | (1 << art::riscv64::FT7) | (1 << art::riscv64::FT8) | 74 (1 << art::riscv64::FT9) | (1 << art::riscv64::FT10) | (1 << art::riscv64::FT11) | 75 (1 << art::riscv64::FS0) | (1 << art::riscv64::FS1) | (1 << art::riscv64::FS2) | 76 (1 << art::riscv64::FS3) | (1 << art::riscv64::FS4) | (1 << art::riscv64::FS5) | 77 (1 << art::riscv64::FS6) | (1 << art::riscv64::FS7) | (1 << art::riscv64::FS8) | 78 (1 << art::riscv64::FS9) | (1 << art::riscv64::FS10) | (1 << art::riscv64::FS11) | 79 (1 << art::riscv64::FA0) | (1 << art::riscv64::FA1) | (1 << art::riscv64::FA2) | 80 (1 << art::riscv64::FA3) | (1 << art::riscv64::FA4) | (1 << art::riscv64::FA5) | 81 (1 << art::riscv64::FA6) | (1 << art::riscv64::FA7); 82 83 class Riscv64CalleeSaveFrame { 84 public: GetCoreSpills(CalleeSaveType type)85 static constexpr uint32_t GetCoreSpills(CalleeSaveType type) { 86 type = GetCanonicalCalleeSaveType(type); 87 return kRiscv64CalleeSaveAlwaysSpills | kRiscv64CalleeSaveRefSpills | 88 (type == CalleeSaveType::kSaveRefsAndArgs ? kRiscv64CalleeSaveArgSpills : 0) | 89 (type == CalleeSaveType::kSaveAllCalleeSaves ? kRiscv64CalleeSaveAllSpills : 0) | 90 (type == CalleeSaveType::kSaveEverything ? kRiscv64CalleeSaveEverythingSpills : 0); 91 } 92 GetFpSpills(CalleeSaveType type)93 static constexpr uint32_t GetFpSpills(CalleeSaveType type) { 94 type = GetCanonicalCalleeSaveType(type); 95 return kRiscv64CalleeSaveFpSpills | 96 (type == CalleeSaveType::kSaveRefsAndArgs ? kRiscv64CalleeSaveFpArgSpills : 0) | 97 (type == CalleeSaveType::kSaveAllCalleeSaves ? kRiscv64CalleeSaveFpAllSpills : 0) | 98 (type == CalleeSaveType::kSaveEverything ? kRiscv64CalleeSaveFpEverythingSpills : 0); 99 } 100 GetFrameSize(CalleeSaveType type)101 static constexpr uint32_t GetFrameSize(CalleeSaveType type) { 102 type = GetCanonicalCalleeSaveType(type); 103 return RoundUp((POPCOUNT(GetCoreSpills(type)) /* gprs */ + 104 POPCOUNT(GetFpSpills(type)) /* fprs */ + 1 /* Method* */) * 105 static_cast<size_t>(kRiscv64PointerSize), 106 kStackAlignment); 107 } 108 GetMethodFrameInfo(CalleeSaveType type)109 static constexpr QuickMethodFrameInfo GetMethodFrameInfo(CalleeSaveType type) { 110 type = GetCanonicalCalleeSaveType(type); 111 return QuickMethodFrameInfo(GetFrameSize(type), GetCoreSpills(type), GetFpSpills(type)); 112 } 113 GetFpr1Offset(CalleeSaveType type)114 static constexpr size_t GetFpr1Offset(CalleeSaveType type) { 115 type = GetCanonicalCalleeSaveType(type); 116 return GetFrameSize(type) - (POPCOUNT(GetCoreSpills(type)) + POPCOUNT(GetFpSpills(type))) * 117 static_cast<size_t>(kRiscv64PointerSize); 118 } 119 GetGpr1Offset(CalleeSaveType type)120 static constexpr size_t GetGpr1Offset(CalleeSaveType type) { 121 type = GetCanonicalCalleeSaveType(type); 122 return GetFrameSize(type) - 123 POPCOUNT(GetCoreSpills(type)) * static_cast<size_t>(kRiscv64PointerSize); 124 } 125 GetReturnPcOffset(CalleeSaveType type)126 static constexpr size_t GetReturnPcOffset(CalleeSaveType type) { 127 type = GetCanonicalCalleeSaveType(type); 128 return GetFrameSize(type) - static_cast<size_t>(kRiscv64PointerSize); 129 } 130 }; 131 132 // Assembly entrypoints rely on these constants. 133 static_assert(Riscv64CalleeSaveFrame::GetFrameSize(CalleeSaveType::kSaveRefsAndArgs) == 224); 134 static_assert(Riscv64CalleeSaveFrame::GetFrameSize(CalleeSaveType::kSaveAllCalleeSaves) == 208); 135 static_assert(Riscv64CalleeSaveFrame::GetFrameSize(CalleeSaveType::kSaveEverything) == 480); 136 137 } // namespace riscv64 138 } // namespace art 139 140 #endif // ART_RUNTIME_ARCH_RISCV64_CALLEE_SAVE_FRAME_RISCV64_H_ 141