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 "assembler_arm.h" 18 19#include <algorithm> 20 21#include "base/bit_utils.h" 22#include "base/logging.h" 23#include "entrypoints/quick/quick_entrypoints.h" 24#include "offsets.h" 25#include "thread.h" 26 27namespace art { 28namespace arm { 29 30const char* kRegisterNames[] = { 31 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", 32 "fp", "ip", "sp", "lr", "pc" 33}; 34 35const char* kConditionNames[] = { 36 "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC", "HI", "LS", "GE", "LT", "GT", 37 "LE", "AL", 38}; 39 40std::ostream& operator<<(std::ostream& os, const Register& rhs) { 41 if (rhs >= R0 && rhs <= PC) { 42 os << kRegisterNames[rhs]; 43 } else { 44 os << "Register[" << static_cast<int>(rhs) << "]"; 45 } 46 return os; 47} 48 49 50std::ostream& operator<<(std::ostream& os, const SRegister& rhs) { 51 if (rhs >= S0 && rhs < kNumberOfSRegisters) { 52 os << "s" << static_cast<int>(rhs); 53 } else { 54 os << "SRegister[" << static_cast<int>(rhs) << "]"; 55 } 56 return os; 57} 58 59 60std::ostream& operator<<(std::ostream& os, const DRegister& rhs) { 61 if (rhs >= D0 && rhs < kNumberOfDRegisters) { 62 os << "d" << static_cast<int>(rhs); 63 } else { 64 os << "DRegister[" << static_cast<int>(rhs) << "]"; 65 } 66 return os; 67} 68 69std::ostream& operator<<(std::ostream& os, const Condition& rhs) { 70 if (rhs >= EQ && rhs <= AL) { 71 os << kConditionNames[rhs]; 72 } else { 73 os << "Condition[" << static_cast<int>(rhs) << "]"; 74 } 75 return os; 76} 77 78ShifterOperand::ShifterOperand(uint32_t immed) 79 : type_(kImmediate), rm_(kNoRegister), rs_(kNoRegister), 80 is_rotate_(false), is_shift_(false), shift_(kNoShift), rotate_(0), immed_(immed) { 81 CHECK(immed < (1u << 12) || ArmAssembler::ModifiedImmediate(immed) != kInvalidModifiedImmediate); 82} 83 84 85uint32_t ShifterOperand::encodingArm() const { 86 CHECK(is_valid()); 87 switch (type_) { 88 case kImmediate: 89 if (is_rotate_) { 90 return (rotate_ << kRotateShift) | (immed_ << kImmed8Shift); 91 } else { 92 return immed_; 93 } 94 case kRegister: 95 if (is_shift_) { 96 uint32_t shift_type; 97 switch (shift_) { 98 case arm::Shift::ROR: 99 shift_type = static_cast<uint32_t>(shift_); 100 CHECK_NE(immed_, 0U); 101 break; 102 case arm::Shift::RRX: 103 shift_type = static_cast<uint32_t>(arm::Shift::ROR); // Same encoding as ROR. 104 CHECK_EQ(immed_, 0U); 105 break; 106 default: 107 shift_type = static_cast<uint32_t>(shift_); 108 } 109 // Shifted immediate or register. 110 if (rs_ == kNoRegister) { 111 // Immediate shift. 112 return immed_ << kShiftImmShift | 113 shift_type << kShiftShift | 114 static_cast<uint32_t>(rm_); 115 } else { 116 // Register shift. 117 return static_cast<uint32_t>(rs_) << kShiftRegisterShift | 118 shift_type << kShiftShift | (1 << 4) | 119 static_cast<uint32_t>(rm_); 120 } 121 } else { 122 // Simple register 123 return static_cast<uint32_t>(rm_); 124 } 125 default: 126 // Can't get here. 127 LOG(FATAL) << "Invalid shifter operand for ARM"; 128 return 0; 129 } 130} 131 132uint32_t ShifterOperand::encodingThumb() const { 133 switch (type_) { 134 case kImmediate: 135 return immed_; 136 case kRegister: 137 if (is_shift_) { 138 // Shifted immediate or register. 139 if (rs_ == kNoRegister) { 140 // Immediate shift. 141 if (shift_ == RRX) { 142 DCHECK_EQ(immed_, 0u); 143 // RRX is encoded as an ROR with imm 0. 144 return ROR << 4 | static_cast<uint32_t>(rm_); 145 } else { 146 DCHECK((1 <= immed_ && immed_ <= 31) || 147 (immed_ == 0u && shift_ == LSL) || 148 (immed_ == 32u && (shift_ == ASR || shift_ == LSR))); 149 uint32_t imm3 = (immed_ >> 2) & 7 /* 0b111*/; 150 uint32_t imm2 = immed_ & 3U /* 0b11 */; 151 152 return imm3 << 12 | imm2 << 6 | shift_ << 4 | 153 static_cast<uint32_t>(rm_); 154 } 155 } else { 156 LOG(FATAL) << "No register-shifted register instruction available in thumb"; 157 return 0; 158 } 159 } else { 160 // Simple register 161 return static_cast<uint32_t>(rm_); 162 } 163 default: 164 // Can't get here. 165 LOG(FATAL) << "Invalid shifter operand for thumb"; 166 UNREACHABLE(); 167 } 168} 169 170uint32_t Address::encodingArm() const { 171 CHECK(IsAbsoluteUint<12>(offset_)); 172 uint32_t encoding; 173 if (is_immed_offset_) { 174 if (offset_ < 0) { 175 encoding = (am_ ^ (1 << kUShift)) | -offset_; // Flip U to adjust sign. 176 } else { 177 encoding = am_ | offset_; 178 } 179 } else { 180 uint32_t shift = shift_; 181 if (shift == RRX) { 182 CHECK_EQ(offset_, 0); 183 shift = ROR; 184 } 185 encoding = am_ | static_cast<uint32_t>(rm_) | shift << 5 | offset_ << 7 | B25; 186 } 187 encoding |= static_cast<uint32_t>(rn_) << kRnShift; 188 return encoding; 189} 190 191 192uint32_t Address::encodingThumb(bool is_32bit) const { 193 uint32_t encoding = 0; 194 if (is_immed_offset_) { 195 encoding = static_cast<uint32_t>(rn_) << 16; 196 // Check for the T3/T4 encoding. 197 // PUW must Offset for T3 198 // Convert ARM PU0W to PUW 199 // The Mode is in ARM encoding format which is: 200 // |P|U|0|W| 201 // we need this in thumb2 mode: 202 // |P|U|W| 203 204 uint32_t am = am_; 205 int32_t offset = offset_; 206 if (offset < 0) { 207 am ^= 1 << kUShift; 208 offset = -offset; 209 } 210 if (offset_ < 0 || (offset >= 0 && offset < 256 && 211 am_ != Mode::Offset)) { 212 // T4 encoding. 213 uint32_t PUW = am >> 21; // Move down to bottom of word. 214 PUW = (PUW >> 1) | (PUW & 1); // Bits 3, 2 and 0. 215 // If P is 0 then W must be 1 (Different from ARM). 216 if ((PUW & 4U /* 0b100 */) == 0) { 217 PUW |= 1U /* 0b1 */; 218 } 219 encoding |= B11 | PUW << 8 | offset; 220 } else { 221 // T3 encoding (also sets op1 to 0b01). 222 encoding |= B23 | offset_; 223 } 224 } else { 225 // Register offset, possibly shifted. 226 // Need to choose between encoding T1 (16 bit) or T2. 227 // Only Offset mode is supported. Shift must be LSL and the count 228 // is only 2 bits. 229 CHECK_EQ(shift_, LSL); 230 CHECK_LE(offset_, 4); 231 CHECK_EQ(am_, Offset); 232 bool is_t2 = is_32bit; 233 if (ArmAssembler::IsHighRegister(rn_) || ArmAssembler::IsHighRegister(rm_)) { 234 is_t2 = true; 235 } else if (offset_ != 0) { 236 is_t2 = true; 237 } 238 if (is_t2) { 239 encoding = static_cast<uint32_t>(rn_) << 16 | static_cast<uint32_t>(rm_) | 240 offset_ << 4; 241 } else { 242 encoding = static_cast<uint32_t>(rn_) << 3 | static_cast<uint32_t>(rm_) << 6; 243 } 244 } 245 return encoding; 246} 247 248// This is very like the ARM encoding except the offset is 10 bits. 249uint32_t Address::encodingThumbLdrdStrd() const { 250 DCHECK(IsImmediate()); 251 uint32_t encoding; 252 uint32_t am = am_; 253 // If P is 0 then W must be 1 (Different from ARM). 254 uint32_t PU1W = am_ >> 21; // Move down to bottom of word. 255 if ((PU1W & 8U /* 0b1000 */) == 0) { 256 am |= 1 << 21; // Set W bit. 257 } 258 if (offset_ < 0) { 259 int32_t off = -offset_; 260 CHECK_LT(off, 1024); 261 CHECK_ALIGNED(off, 4); 262 encoding = (am ^ (1 << kUShift)) | off >> 2; // Flip U to adjust sign. 263 } else { 264 CHECK_LT(offset_, 1024); 265 CHECK_ALIGNED(offset_, 4); 266 encoding = am | offset_ >> 2; 267 } 268 encoding |= static_cast<uint32_t>(rn_) << 16; 269 return encoding; 270} 271 272// Encoding for ARM addressing mode 3. 273uint32_t Address::encoding3() const { 274 const uint32_t offset_mask = (1 << 12) - 1; 275 uint32_t encoding = encodingArm(); 276 uint32_t offset = encoding & offset_mask; 277 CHECK_LT(offset, 256u); 278 return (encoding & ~offset_mask) | ((offset & 0xf0) << 4) | (offset & 0xf); 279} 280 281// Encoding for vfp load/store addressing. 282uint32_t Address::vencoding() const { 283 CHECK(IsAbsoluteUint<10>(offset_)); // In the range -1020 to +1020. 284 CHECK_ALIGNED(offset_, 2); // Multiple of 4. 285 286 const uint32_t offset_mask = (1 << 12) - 1; 287 uint32_t encoding = encodingArm(); 288 uint32_t offset = encoding & offset_mask; 289 CHECK((am_ == Offset) || (am_ == NegOffset)); 290 uint32_t vencoding_value = (encoding & (0xf << kRnShift)) | (offset >> 2); 291 if (am_ == Offset) { 292 vencoding_value |= 1 << 23; 293 } 294 return vencoding_value; 295} 296 297 298bool Address::CanHoldLoadOffsetArm(LoadOperandType type, int offset) { 299 switch (type) { 300 case kLoadSignedByte: 301 case kLoadSignedHalfword: 302 case kLoadUnsignedHalfword: 303 case kLoadWordPair: 304 return IsAbsoluteUint<8>(offset); // Addressing mode 3. 305 case kLoadUnsignedByte: 306 case kLoadWord: 307 return IsAbsoluteUint<12>(offset); // Addressing mode 2. 308 case kLoadSWord: 309 case kLoadDWord: 310 return IsAbsoluteUint<10>(offset); // VFP addressing mode. 311 default: 312 LOG(FATAL) << "UNREACHABLE"; 313 UNREACHABLE(); 314 } 315} 316 317 318bool Address::CanHoldStoreOffsetArm(StoreOperandType type, int offset) { 319 switch (type) { 320 case kStoreHalfword: 321 case kStoreWordPair: 322 return IsAbsoluteUint<8>(offset); // Addressing mode 3. 323 case kStoreByte: 324 case kStoreWord: 325 return IsAbsoluteUint<12>(offset); // Addressing mode 2. 326 case kStoreSWord: 327 case kStoreDWord: 328 return IsAbsoluteUint<10>(offset); // VFP addressing mode. 329 default: 330 LOG(FATAL) << "UNREACHABLE"; 331 UNREACHABLE(); 332 } 333} 334 335bool Address::CanHoldLoadOffsetThumb(LoadOperandType type, int offset) { 336 switch (type) { 337 case kLoadSignedByte: 338 case kLoadSignedHalfword: 339 case kLoadUnsignedHalfword: 340 case kLoadUnsignedByte: 341 case kLoadWord: 342 return IsAbsoluteUint<12>(offset); 343 case kLoadSWord: 344 case kLoadDWord: 345 return IsAbsoluteUint<10>(offset) && (offset & 3) == 0; // VFP addressing mode. 346 case kLoadWordPair: 347 return IsAbsoluteUint<10>(offset) && (offset & 3) == 0; 348 default: 349 LOG(FATAL) << "UNREACHABLE"; 350 UNREACHABLE(); 351 } 352} 353 354 355bool Address::CanHoldStoreOffsetThumb(StoreOperandType type, int offset) { 356 switch (type) { 357 case kStoreHalfword: 358 case kStoreByte: 359 case kStoreWord: 360 return IsAbsoluteUint<12>(offset); 361 case kStoreSWord: 362 case kStoreDWord: 363 return IsAbsoluteUint<10>(offset) && (offset & 3) == 0; // VFP addressing mode. 364 case kStoreWordPair: 365 return IsAbsoluteUint<10>(offset) && (offset & 3) == 0; 366 default: 367 LOG(FATAL) << "UNREACHABLE"; 368 UNREACHABLE(); 369 } 370} 371 372void ArmAssembler::Pad(uint32_t bytes) { 373 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 374 for (uint32_t i = 0; i < bytes; ++i) { 375 buffer_.Emit<uint8_t>(0); 376 } 377} 378 379static int LeadingZeros(uint32_t val) { 380 uint32_t alt; 381 int32_t n; 382 int32_t count; 383 384 count = 16; 385 n = 32; 386 do { 387 alt = val >> count; 388 if (alt != 0) { 389 n = n - count; 390 val = alt; 391 } 392 count >>= 1; 393 } while (count); 394 return n - val; 395} 396 397 398uint32_t ArmAssembler::ModifiedImmediate(uint32_t value) { 399 int32_t z_leading; 400 int32_t z_trailing; 401 uint32_t b0 = value & 0xff; 402 403 /* Note: case of value==0 must use 0:000:0:0000000 encoding */ 404 if (value <= 0xFF) 405 return b0; // 0:000:a:bcdefgh. 406 if (value == ((b0 << 16) | b0)) 407 return (0x1 << 12) | b0; /* 0:001:a:bcdefgh */ 408 if (value == ((b0 << 24) | (b0 << 16) | (b0 << 8) | b0)) 409 return (0x3 << 12) | b0; /* 0:011:a:bcdefgh */ 410 b0 = (value >> 8) & 0xff; 411 if (value == ((b0 << 24) | (b0 << 8))) 412 return (0x2 << 12) | b0; /* 0:010:a:bcdefgh */ 413 /* Can we do it with rotation? */ 414 z_leading = LeadingZeros(value); 415 z_trailing = 32 - LeadingZeros(~value & (value - 1)); 416 /* A run of eight or fewer active bits? */ 417 if ((z_leading + z_trailing) < 24) 418 return kInvalidModifiedImmediate; /* No - bail */ 419 /* left-justify the constant, discarding msb (known to be 1) */ 420 value <<= z_leading + 1; 421 /* Create bcdefgh */ 422 value >>= 25; 423 424 /* Put it all together */ 425 uint32_t v = 8 + z_leading; 426 427 uint32_t i = (v & 16U /* 0b10000 */) >> 4; 428 uint32_t imm3 = (v >> 1) & 7U /* 0b111 */; 429 uint32_t a = v & 1; 430 return value | i << 26 | imm3 << 12 | a << 7; 431} 432 433void ArmAssembler::FinalizeTrackedLabels() { 434 if (!tracked_labels_.empty()) { 435 // This array should be sorted, as assembly is generated in linearized order. It isn't 436 // technically required, but GetAdjustedPosition() used in AdjustLabelPosition() can take 437 // advantage of it. So ensure that it's actually the case. 438 DCHECK(std::is_sorted( 439 tracked_labels_.begin(), 440 tracked_labels_.end(), 441 [](const Label* lhs, const Label* rhs) { return lhs->Position() < rhs->Position(); })); 442 443 Label* last_label = nullptr; // Track duplicates, we must not adjust twice. 444 for (Label* label : tracked_labels_) { 445 DCHECK_NE(label, last_label); 446 AdjustLabelPosition(label); 447 last_label = label; 448 } 449 } 450} 451 452} // namespace arm 453} // namespace art 454