1 /*
2  * Copyright (C) 2014 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_MIPS_CALLEE_SAVE_FRAME_MIPS_H_
18 #define ART_RUNTIME_ARCH_MIPS_CALLEE_SAVE_FRAME_MIPS_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_mips.h"
26 #include "runtime_globals.h"
27 
28 namespace art {
29 namespace mips {
30 
31 static constexpr uint32_t kMipsCalleeSaveAlwaysSpills =
32     (1u << art::mips::RA);
33 static constexpr uint32_t kMipsCalleeSaveRefSpills =
34     (1 << art::mips::S2) | (1 << art::mips::S3) | (1 << art::mips::S4) | (1 << art::mips::S5) |
35     (1 << art::mips::S6) | (1 << art::mips::S7) | (1 << art::mips::GP) | (1 << art::mips::FP);
36 static constexpr uint32_t kMipsCalleeSaveArgSpills =
37     (1 << art::mips::A1) | (1 << art::mips::A2) | (1 << art::mips::A3) | (1 << art::mips::T0) |
38     (1 << art::mips::T1);
39 // We want to save all floating point register pairs at addresses
40 // which are multiples of 8 so that we can eliminate use of the
41 // SDu/LDu macros by using sdc1/ldc1 to store/load floating
42 // register values using a single instruction. Because integer
43 // registers are stored at the top of the frame, to achieve having
44 // the floating point register pairs aligned on multiples of 8 the
45 // number of integer registers saved must be even. Previously, the
46 // only case in which we saved floating point registers beneath an
47 // odd number of integer registers was when "type" is
48 // CalleeSaveType::kSaveAllCalleeSaves. (There are other cases in
49 // which an odd number of integer registers are saved but those
50 // cases don't save any floating point registers. If no floating
51 // point registers are saved we don't care if the number of integer
52 // registers saved is odd or even). To save an even number of
53 // integer registers in this particular case we add the ZERO
54 // register to the list of registers which get saved.
55 static constexpr uint32_t kMipsCalleeSaveAllSpills =
56     (1 << art::mips::ZERO) | (1 << art::mips::S0) | (1 << art::mips::S1);
57 static constexpr uint32_t kMipsCalleeSaveEverythingSpills =
58     (1 << art::mips::AT) | (1 << art::mips::V0) | (1 << art::mips::V1) |
59     (1 << art::mips::A0) | (1 << art::mips::A1) | (1 << art::mips::A2) | (1 << art::mips::A3) |
60     (1 << art::mips::T0) | (1 << art::mips::T1) | (1 << art::mips::T2) | (1 << art::mips::T3) |
61     (1 << art::mips::T4) | (1 << art::mips::T5) | (1 << art::mips::T6) | (1 << art::mips::T7) |
62     (1 << art::mips::S0) | (1 << art::mips::S1) | (1 << art::mips::T8) | (1 << art::mips::T9);
63 
64 static constexpr uint32_t kMipsCalleeSaveFpAlwaysSpills = 0;
65 static constexpr uint32_t kMipsCalleeSaveFpRefSpills = 0;
66 static constexpr uint32_t kMipsCalleeSaveFpArgSpills =
67     (1 << art::mips::F8) | (1 << art::mips::F9) | (1 << art::mips::F10) | (1 << art::mips::F11) |
68     (1 << art::mips::F12) | (1 << art::mips::F13) | (1 << art::mips::F14) | (1 << art::mips::F15) |
69     (1 << art::mips::F16) | (1 << art::mips::F17) | (1 << art::mips::F18) | (1 << art::mips::F19);
70 static constexpr uint32_t kMipsCalleeSaveAllFPSpills =
71     (1 << art::mips::F20) | (1 << art::mips::F21) | (1 << art::mips::F22) | (1 << art::mips::F23) |
72     (1 << art::mips::F24) | (1 << art::mips::F25) | (1 << art::mips::F26) | (1 << art::mips::F27) |
73     (1 << art::mips::F28) | (1 << art::mips::F29) | (1 << art::mips::F30) | (1u << art::mips::F31);
74 static constexpr uint32_t kMipsCalleeSaveFpEverythingSpills =
75     (1 << art::mips::F0) | (1 << art::mips::F1) | (1 << art::mips::F2) | (1 << art::mips::F3) |
76     (1 << art::mips::F4) | (1 << art::mips::F5) | (1 << art::mips::F6) | (1 << art::mips::F7) |
77     (1 << art::mips::F8) | (1 << art::mips::F9) | (1 << art::mips::F10) | (1 << art::mips::F11) |
78     (1 << art::mips::F12) | (1 << art::mips::F13) | (1 << art::mips::F14) | (1 << art::mips::F15) |
79     (1 << art::mips::F16) | (1 << art::mips::F17) | (1 << art::mips::F18) | (1 << art::mips::F19) |
80     (1 << art::mips::F20) | (1 << art::mips::F21) | (1 << art::mips::F22) | (1 << art::mips::F23) |
81     (1 << art::mips::F24) | (1 << art::mips::F25) | (1 << art::mips::F26) | (1 << art::mips::F27) |
82     (1 << art::mips::F28) | (1 << art::mips::F29) | (1 << art::mips::F30) | (1u << art::mips::F31);
83 
84 class MipsCalleeSaveFrame {
85  public:
GetCoreSpills(CalleeSaveType type)86   static constexpr uint32_t GetCoreSpills(CalleeSaveType type) {
87     type = GetCanonicalCalleeSaveType(type);
88     return kMipsCalleeSaveAlwaysSpills | kMipsCalleeSaveRefSpills |
89         (type == CalleeSaveType::kSaveRefsAndArgs ? kMipsCalleeSaveArgSpills : 0) |
90         (type == CalleeSaveType::kSaveAllCalleeSaves ? kMipsCalleeSaveAllSpills : 0) |
91         (type == CalleeSaveType::kSaveEverything ? kMipsCalleeSaveEverythingSpills : 0);
92   }
93 
GetFpSpills(CalleeSaveType type)94   static constexpr uint32_t GetFpSpills(CalleeSaveType type) {
95     type = GetCanonicalCalleeSaveType(type);
96     return kMipsCalleeSaveFpAlwaysSpills | kMipsCalleeSaveFpRefSpills |
97         (type == CalleeSaveType::kSaveRefsAndArgs ? kMipsCalleeSaveFpArgSpills : 0) |
98         (type == CalleeSaveType::kSaveAllCalleeSaves ? kMipsCalleeSaveAllFPSpills : 0) |
99         (type == CalleeSaveType::kSaveEverything ? kMipsCalleeSaveFpEverythingSpills : 0);
100   }
101 
GetFrameSize(CalleeSaveType type)102   static constexpr uint32_t GetFrameSize(CalleeSaveType type) {
103     type = GetCanonicalCalleeSaveType(type);
104     return RoundUp((POPCOUNT(GetCoreSpills(type)) /* gprs */ +
105                     POPCOUNT(GetFpSpills(type))   /* fprs */ +
106                     1 /* Method* */) * static_cast<size_t>(kMipsPointerSize), 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) -
117            (POPCOUNT(GetCoreSpills(type)) +
118             POPCOUNT(GetFpSpills(type))) * static_cast<size_t>(kMipsPointerSize);
119   }
120 
GetGpr1Offset(CalleeSaveType type)121   static constexpr size_t GetGpr1Offset(CalleeSaveType type) {
122     type = GetCanonicalCalleeSaveType(type);
123     return GetFrameSize(type) -
124            POPCOUNT(GetCoreSpills(type)) * static_cast<size_t>(kMipsPointerSize);
125   }
126 
GetReturnPcOffset(CalleeSaveType type)127   static constexpr size_t GetReturnPcOffset(CalleeSaveType type) {
128     type = GetCanonicalCalleeSaveType(type);
129     return GetFrameSize(type) - static_cast<size_t>(kMipsPointerSize);
130   }
131 };
132 
133 }  // namespace mips
134 }  // namespace art
135 
136 #endif  // ART_RUNTIME_ARCH_MIPS_CALLEE_SAVE_FRAME_MIPS_H_
137