1 /* 2 * Copyright (C) 2011 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 #include "calling_convention_mips.h" 18 19 #include "base/logging.h" 20 #include "handle_scope-inl.h" 21 #include "utils/mips/managed_register_mips.h" 22 23 namespace art { 24 namespace mips { 25 26 // 27 // JNI calling convention constants. 28 // 29 30 // Up to how many float-like (float, double) args can be enregistered in floating-point registers. 31 // The rest of the args must go in integer registers or on the stack. 32 constexpr size_t kMaxFloatOrDoubleRegisterArguments = 2u; 33 // Up to how many integer-like (pointers, objects, longs, int, short, bool, etc) args can be 34 // enregistered. The rest of the args must go on the stack. 35 constexpr size_t kMaxIntLikeRegisterArguments = 4u; 36 37 static const Register kJniCoreArgumentRegisters[] = { A0, A1, A2, A3 }; 38 static const FRegister kJniFArgumentRegisters[] = { F12, F14 }; 39 static const DRegister kJniDArgumentRegisters[] = { D6, D7 }; 40 41 // 42 // Managed calling convention constants. 43 // 44 45 static const Register kManagedCoreArgumentRegisters[] = { A0, A1, A2, A3, T0, T1 }; 46 static const FRegister kManagedFArgumentRegisters[] = { F8, F10, F12, F14, F16, F18 }; 47 static const DRegister kManagedDArgumentRegisters[] = { D4, D5, D6, D7, D8, D9 }; 48 49 static constexpr ManagedRegister kCalleeSaveRegisters[] = { 50 // Core registers. 51 MipsManagedRegister::FromCoreRegister(S2), 52 MipsManagedRegister::FromCoreRegister(S3), 53 MipsManagedRegister::FromCoreRegister(S4), 54 MipsManagedRegister::FromCoreRegister(S5), 55 MipsManagedRegister::FromCoreRegister(S6), 56 MipsManagedRegister::FromCoreRegister(S7), 57 MipsManagedRegister::FromCoreRegister(FP), 58 // No hard float callee saves. 59 }; 60 61 static constexpr uint32_t CalculateCoreCalleeSpillMask() { 62 // RA is a special callee save which is not reported by CalleeSaveRegisters(). 63 uint32_t result = 1 << RA; 64 for (auto&& r : kCalleeSaveRegisters) { 65 if (r.AsMips().IsCoreRegister()) { 66 result |= (1 << r.AsMips().AsCoreRegister()); 67 } 68 } 69 return result; 70 } 71 72 static constexpr uint32_t kCoreCalleeSpillMask = CalculateCoreCalleeSpillMask(); 73 static constexpr uint32_t kFpCalleeSpillMask = 0u; 74 75 // Calling convention 76 ManagedRegister MipsManagedRuntimeCallingConvention::InterproceduralScratchRegister() { 77 return MipsManagedRegister::FromCoreRegister(T9); 78 } 79 80 ManagedRegister MipsJniCallingConvention::InterproceduralScratchRegister() { 81 return MipsManagedRegister::FromCoreRegister(T9); 82 } 83 84 static ManagedRegister ReturnRegisterForShorty(const char* shorty) { 85 if (shorty[0] == 'F') { 86 return MipsManagedRegister::FromFRegister(F0); 87 } else if (shorty[0] == 'D') { 88 return MipsManagedRegister::FromDRegister(D0); 89 } else if (shorty[0] == 'J') { 90 return MipsManagedRegister::FromRegisterPair(V0_V1); 91 } else if (shorty[0] == 'V') { 92 return MipsManagedRegister::NoRegister(); 93 } else { 94 return MipsManagedRegister::FromCoreRegister(V0); 95 } 96 } 97 98 ManagedRegister MipsManagedRuntimeCallingConvention::ReturnRegister() { 99 return ReturnRegisterForShorty(GetShorty()); 100 } 101 102 ManagedRegister MipsJniCallingConvention::ReturnRegister() { 103 return ReturnRegisterForShorty(GetShorty()); 104 } 105 106 ManagedRegister MipsJniCallingConvention::IntReturnRegister() { 107 return MipsManagedRegister::FromCoreRegister(V0); 108 } 109 110 // Managed runtime calling convention 111 112 ManagedRegister MipsManagedRuntimeCallingConvention::MethodRegister() { 113 return MipsManagedRegister::FromCoreRegister(A0); 114 } 115 116 bool MipsManagedRuntimeCallingConvention::IsCurrentParamInRegister() { 117 return false; // Everything moved to stack on entry. 118 } 119 120 bool MipsManagedRuntimeCallingConvention::IsCurrentParamOnStack() { 121 return true; 122 } 123 124 ManagedRegister MipsManagedRuntimeCallingConvention::CurrentParamRegister() { 125 LOG(FATAL) << "Should not reach here"; 126 return ManagedRegister::NoRegister(); 127 } 128 129 FrameOffset MipsManagedRuntimeCallingConvention::CurrentParamStackOffset() { 130 CHECK(IsCurrentParamOnStack()); 131 FrameOffset result = 132 FrameOffset(displacement_.Int32Value() + // displacement 133 kFramePointerSize + // Method* 134 (itr_slots_ * kFramePointerSize)); // offset into in args 135 return result; 136 } 137 138 const ManagedRegisterEntrySpills& MipsManagedRuntimeCallingConvention::EntrySpills() { 139 // We spill the argument registers on MIPS to free them up for scratch use, we then assume 140 // all arguments are on the stack. 141 if ((entry_spills_.size() == 0) && (NumArgs() > 0)) { 142 uint32_t gpr_index = 1; // Skip A0, it is used for ArtMethod*. 143 uint32_t fpr_index = 0; 144 145 for (ResetIterator(FrameOffset(0)); HasNext(); Next()) { 146 if (IsCurrentParamAFloatOrDouble()) { 147 if (IsCurrentParamADouble()) { 148 if (fpr_index < arraysize(kManagedDArgumentRegisters)) { 149 entry_spills_.push_back( 150 MipsManagedRegister::FromDRegister(kManagedDArgumentRegisters[fpr_index++])); 151 } else { 152 entry_spills_.push_back(ManagedRegister::NoRegister(), 8); 153 } 154 } else { 155 if (fpr_index < arraysize(kManagedFArgumentRegisters)) { 156 entry_spills_.push_back( 157 MipsManagedRegister::FromFRegister(kManagedFArgumentRegisters[fpr_index++])); 158 } else { 159 entry_spills_.push_back(ManagedRegister::NoRegister(), 4); 160 } 161 } 162 } else { 163 if (IsCurrentParamALong() && !IsCurrentParamAReference()) { 164 if (gpr_index == 1 || gpr_index == 3) { 165 // Don't use A1-A2(A3-T0) as a register pair, move to A2-A3(T0-T1) instead. 166 gpr_index++; 167 } 168 if (gpr_index < arraysize(kManagedCoreArgumentRegisters) - 1) { 169 entry_spills_.push_back( 170 MipsManagedRegister::FromCoreRegister(kManagedCoreArgumentRegisters[gpr_index++])); 171 } else if (gpr_index == arraysize(kManagedCoreArgumentRegisters) - 1) { 172 gpr_index++; 173 entry_spills_.push_back(ManagedRegister::NoRegister(), 4); 174 } else { 175 entry_spills_.push_back(ManagedRegister::NoRegister(), 4); 176 } 177 } 178 179 if (gpr_index < arraysize(kManagedCoreArgumentRegisters)) { 180 entry_spills_.push_back( 181 MipsManagedRegister::FromCoreRegister(kManagedCoreArgumentRegisters[gpr_index++])); 182 } else { 183 entry_spills_.push_back(ManagedRegister::NoRegister(), 4); 184 } 185 } 186 } 187 } 188 return entry_spills_; 189 } 190 191 // JNI calling convention 192 193 MipsJniCallingConvention::MipsJniCallingConvention(bool is_static, 194 bool is_synchronized, 195 bool is_critical_native, 196 const char* shorty) 197 : JniCallingConvention(is_static, 198 is_synchronized, 199 is_critical_native, 200 shorty, 201 kMipsPointerSize) { 202 // SYSTEM V - Application Binary Interface (MIPS RISC Processor): 203 // Data Representation - Fundamental Types (3-4) specifies fundamental alignments for each type. 204 // "Each member is assigned to the lowest available offset with the appropriate alignment. This 205 // may require internal padding, depending on the previous member." 206 // 207 // All of our stack arguments are usually 4-byte aligned, however longs and doubles must be 8 208 // bytes aligned. Add padding to maintain 8-byte alignment invariant. 209 // 210 // Compute padding to ensure longs and doubles are not split in o32. 211 size_t padding = 0; 212 size_t cur_arg, cur_reg; 213 if (LIKELY(HasExtraArgumentsForJni())) { 214 // Ignore the 'this' jobject or jclass for static methods and the JNIEnv. 215 // We start at the aligned register A2. 216 // 217 // Ignore the first 2 parameters because they are guaranteed to be aligned. 218 cur_arg = NumImplicitArgs(); // Skip the "this" argument. 219 cur_reg = 2; // Skip {A0=JNIEnv, A1=jobject} / {A0=JNIEnv, A1=jclass} parameters (start at A2). 220 } else { 221 // Check every parameter. 222 cur_arg = 0; 223 cur_reg = 0; 224 } 225 226 // Shift across a logical register mapping that looks like: 227 // 228 // | A0 | A1 | A2 | A3 | SP+16 | SP+20 | SP+24 | ... | SP+n | SP+n+4 | 229 // 230 // or some of variants with floating-point registers (F12 and F14), for example 231 // 232 // | F12 | F14 | A3 | SP+16 | SP+20 | SP+24 | ... | SP+n | SP+n+4 | 233 // 234 // (where SP is the stack pointer at the start of called function). 235 // 236 // Any time there would normally be a long/double in an odd logical register, 237 // we have to push out the rest of the mappings by 4 bytes to maintain an 8-byte alignment. 238 // 239 // This works for both physical register pairs {A0, A1}, {A2, A3}, 240 // floating-point registers F12, F14 and for when the value is on the stack. 241 // 242 // For example: 243 // (a) long would normally go into A1, but we shift it into A2 244 // | INT | (PAD) | LONG | 245 // | A0 | A1 | A2 | A3 | 246 // 247 // (b) long would normally go into A3, but we shift it into SP 248 // | INT | INT | INT | (PAD) | LONG | 249 // | A0 | A1 | A2 | A3 | SP+16 SP+20 | 250 // 251 // where INT is any <=4 byte arg, and LONG is any 8-byte arg. 252 for (; cur_arg < NumArgs(); cur_arg++) { 253 if (IsParamALongOrDouble(cur_arg)) { 254 if ((cur_reg & 1) != 0) { 255 padding += 4; 256 cur_reg++; // Additional bump to ensure alignment. 257 } 258 cur_reg += 2; // Bump the iterator twice for every long argument. 259 } else { 260 cur_reg++; // Bump the iterator for every argument. 261 } 262 } 263 if (cur_reg < kMaxIntLikeRegisterArguments) { 264 // As a special case when, as a result of shifting (or not) there are no arguments on the stack, 265 // we actually have 0 stack padding. 266 // 267 // For example with @CriticalNative and: 268 // (int, long) -> shifts the long but doesn't need to pad the stack 269 // 270 // shift 271 // \/ 272 // | INT | (PAD) | LONG | (EMPTY) ... 273 // | r0 | r1 | r2 | r3 | SP ... 274 // /\ 275 // no stack padding 276 padding_ = 0; 277 } else { 278 padding_ = padding; 279 } 280 281 // Argument Passing (3-17): 282 // "When the first argument is integral, the remaining arguments are passed in the integer 283 // registers." 284 // 285 // "The rules that determine which arguments go into registers and which ones must be passed on 286 // the stack are most easily explained by considering the list of arguments as a structure, 287 // aligned according to normal structure rules. Mapping of this structure into the combination of 288 // stack and registers is as follows: up to two leading floating-point arguments can be passed in 289 // $f12 and $f14; everything else with a structure offset greater than or equal to 16 is passed on 290 // the stack. The remainder of the arguments are passed in $4..$7 based on their structure offset. 291 // Holes left in the structure for alignment are unused, whether in registers or in the stack." 292 // 293 // For example with @CriticalNative and: 294 // (a) first argument is not floating-point, so all go into integer registers 295 // | INT | FLOAT | DOUBLE | 296 // | A0 | A1 | A2 | A3 | 297 // (b) first argument is floating-point, but 2nd is integer 298 // | FLOAT | INT | DOUBLE | 299 // | F12 | A1 | A2 | A3 | 300 // (c) first two arguments are floating-point (float, double) 301 // | FLOAT | (PAD) | DOUBLE | INT | 302 // | F12 | | F14 | SP+16 | 303 // (d) first two arguments are floating-point (double, float) 304 // | DOUBLE | FLOAT | INT | 305 // | F12 | F14 | A3 | 306 // (e) first three arguments are floating-point, but just first two will go into fp registers 307 // | DOUBLE | FLOAT | FLOAT | 308 // | F12 | F14 | A3 | 309 // 310 // Find out if the first argument is a floating-point. In that case, floating-point registers will 311 // be used for up to two leading floating-point arguments. Otherwise, all arguments will be passed 312 // using integer registers. 313 use_fp_arg_registers_ = false; 314 if (is_critical_native) { 315 if (NumArgs() > 0) { 316 if (IsParamAFloatOrDouble(0)) { 317 use_fp_arg_registers_ = true; 318 } 319 } 320 } 321 } 322 323 uint32_t MipsJniCallingConvention::CoreSpillMask() const { 324 return kCoreCalleeSpillMask; 325 } 326 327 uint32_t MipsJniCallingConvention::FpSpillMask() const { 328 return kFpCalleeSpillMask; 329 } 330 331 ManagedRegister MipsJniCallingConvention::ReturnScratchRegister() const { 332 return MipsManagedRegister::FromCoreRegister(AT); 333 } 334 335 size_t MipsJniCallingConvention::FrameSize() { 336 // ArtMethod*, RA and callee save area size, local reference segment state. 337 const size_t method_ptr_size = static_cast<size_t>(kMipsPointerSize); 338 const size_t ra_return_addr_size = kFramePointerSize; 339 const size_t callee_save_area_size = CalleeSaveRegisters().size() * kFramePointerSize; 340 341 size_t frame_data_size = method_ptr_size + ra_return_addr_size + callee_save_area_size; 342 343 if (LIKELY(HasLocalReferenceSegmentState())) { 344 // Local reference segment state. 345 frame_data_size += kFramePointerSize; 346 } 347 348 // References plus 2 words for HandleScope header. 349 const size_t handle_scope_size = HandleScope::SizeOf(kMipsPointerSize, ReferenceCount()); 350 351 size_t total_size = frame_data_size; 352 if (LIKELY(HasHandleScope())) { 353 // HandleScope is sometimes excluded. 354 total_size += handle_scope_size; // Handle scope size. 355 } 356 357 // Plus return value spill area size. 358 total_size += SizeOfReturnValue(); 359 360 return RoundUp(total_size, kStackAlignment); 361 } 362 363 size_t MipsJniCallingConvention::OutArgSize() { 364 // Argument Passing (3-17): 365 // "Despite the fact that some or all of the arguments to a function are passed in registers, 366 // always allocate space on the stack for all arguments. This stack space should be a structure 367 // large enough to contain all the arguments, aligned according to normal structure rules (after 368 // promotion and structure return pointer insertion). The locations within the stack frame used 369 // for arguments are called the home locations." 370 // 371 // Allocate 16 bytes for home locations + space needed for stack arguments. 372 return RoundUp( 373 (kMaxIntLikeRegisterArguments + NumberOfOutgoingStackArgs()) * kFramePointerSize + padding_, 374 kStackAlignment); 375 } 376 377 ArrayRef<const ManagedRegister> MipsJniCallingConvention::CalleeSaveRegisters() const { 378 return ArrayRef<const ManagedRegister>(kCalleeSaveRegisters); 379 } 380 381 // JniCallingConvention ABI follows o32 where longs and doubles must occur 382 // in even register numbers and stack slots. 383 void MipsJniCallingConvention::Next() { 384 JniCallingConvention::Next(); 385 386 if (LIKELY(HasNext())) { // Avoid CHECK failure for IsCurrentParam 387 // Ensure slot is 8-byte aligned for longs/doubles (o32). 388 if (IsCurrentParamALongOrDouble() && ((itr_slots_ & 0x1u) != 0)) { 389 // itr_slots_ needs to be an even number, according to o32. 390 itr_slots_++; 391 } 392 } 393 } 394 395 bool MipsJniCallingConvention::IsCurrentParamInRegister() { 396 // Argument Passing (3-17): 397 // "The rules that determine which arguments go into registers and which ones must be passed on 398 // the stack are most easily explained by considering the list of arguments as a structure, 399 // aligned according to normal structure rules. Mapping of this structure into the combination of 400 // stack and registers is as follows: up to two leading floating-point arguments can be passed in 401 // $f12 and $f14; everything else with a structure offset greater than or equal to 16 is passed on 402 // the stack. The remainder of the arguments are passed in $4..$7 based on their structure offset. 403 // Holes left in the structure for alignment are unused, whether in registers or in the stack." 404 // 405 // Even when floating-point registers are used, there can be up to 4 arguments passed in 406 // registers. 407 return itr_slots_ < kMaxIntLikeRegisterArguments; 408 } 409 410 bool MipsJniCallingConvention::IsCurrentParamOnStack() { 411 return !IsCurrentParamInRegister(); 412 } 413 414 ManagedRegister MipsJniCallingConvention::CurrentParamRegister() { 415 CHECK_LT(itr_slots_, kMaxIntLikeRegisterArguments); 416 // Up to two leading floating-point arguments can be passed in floating-point registers. 417 if (use_fp_arg_registers_ && (itr_args_ < kMaxFloatOrDoubleRegisterArguments)) { 418 if (IsCurrentParamAFloatOrDouble()) { 419 if (IsCurrentParamADouble()) { 420 return MipsManagedRegister::FromDRegister(kJniDArgumentRegisters[itr_args_]); 421 } else { 422 return MipsManagedRegister::FromFRegister(kJniFArgumentRegisters[itr_args_]); 423 } 424 } 425 } 426 // All other arguments (including other floating-point arguments) will be passed in integer 427 // registers. 428 if (IsCurrentParamALongOrDouble()) { 429 if (itr_slots_ == 0u) { 430 return MipsManagedRegister::FromRegisterPair(A0_A1); 431 } else { 432 CHECK_EQ(itr_slots_, 2u); 433 return MipsManagedRegister::FromRegisterPair(A2_A3); 434 } 435 } else { 436 return MipsManagedRegister::FromCoreRegister(kJniCoreArgumentRegisters[itr_slots_]); 437 } 438 } 439 440 FrameOffset MipsJniCallingConvention::CurrentParamStackOffset() { 441 CHECK_GE(itr_slots_, kMaxIntLikeRegisterArguments); 442 size_t offset = displacement_.Int32Value() - OutArgSize() + (itr_slots_ * kFramePointerSize); 443 CHECK_LT(offset, OutArgSize()); 444 return FrameOffset(offset); 445 } 446 447 size_t MipsJniCallingConvention::NumberOfOutgoingStackArgs() { 448 size_t static_args = HasSelfClass() ? 1 : 0; // Count jclass. 449 // Regular argument parameters and this. 450 size_t param_args = NumArgs() + NumLongOrDoubleArgs(); // Twice count 8-byte args. 451 // Count JNIEnv* less arguments in registers. 452 size_t internal_args = (HasJniEnv() ? 1 : 0); 453 size_t total_args = static_args + param_args + internal_args; 454 455 return total_args - std::min(kMaxIntLikeRegisterArguments, static_cast<size_t>(total_args)); 456 } 457 458 } // namespace mips 459 } // namespace art 460