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_COMPILER_UTILS_MIPS64_ASSEMBLER_MIPS64_H_ 18 #define ART_COMPILER_UTILS_MIPS64_ASSEMBLER_MIPS64_H_ 19 20 #include <deque> 21 #include <utility> 22 #include <vector> 23 24 #include "arch/mips64/instruction_set_features_mips64.h" 25 #include "base/arena_containers.h" 26 #include "base/enums.h" 27 #include "base/macros.h" 28 #include "base/stl_util_identity.h" 29 #include "constants_mips64.h" 30 #include "globals.h" 31 #include "managed_register_mips64.h" 32 #include "offsets.h" 33 #include "utils/assembler.h" 34 #include "utils/jni_macro_assembler.h" 35 #include "utils/label.h" 36 37 namespace art { 38 namespace mips64 { 39 40 enum LoadConst64Path { 41 kLoadConst64PathZero = 0x0, 42 kLoadConst64PathOri = 0x1, 43 kLoadConst64PathDaddiu = 0x2, 44 kLoadConst64PathLui = 0x4, 45 kLoadConst64PathLuiOri = 0x8, 46 kLoadConst64PathOriDahi = 0x10, 47 kLoadConst64PathOriDati = 0x20, 48 kLoadConst64PathLuiDahi = 0x40, 49 kLoadConst64PathLuiDati = 0x80, 50 kLoadConst64PathDaddiuDsrlX = 0x100, 51 kLoadConst64PathOriDsllX = 0x200, 52 kLoadConst64PathDaddiuDsllX = 0x400, 53 kLoadConst64PathLuiOriDsllX = 0x800, 54 kLoadConst64PathOriDsllXOri = 0x1000, 55 kLoadConst64PathDaddiuDsllXOri = 0x2000, 56 kLoadConst64PathDaddiuDahi = 0x4000, 57 kLoadConst64PathDaddiuDati = 0x8000, 58 kLoadConst64PathDinsu1 = 0x10000, 59 kLoadConst64PathDinsu2 = 0x20000, 60 kLoadConst64PathCatchAll = 0x40000, 61 kLoadConst64PathAllPaths = 0x7ffff, 62 }; 63 64 template <typename Asm> 65 void TemplateLoadConst32(Asm* a, GpuRegister rd, int32_t value) { 66 if (IsUint<16>(value)) { 67 // Use OR with (unsigned) immediate to encode 16b unsigned int. 68 a->Ori(rd, ZERO, value); 69 } else if (IsInt<16>(value)) { 70 // Use ADD with (signed) immediate to encode 16b signed int. 71 a->Addiu(rd, ZERO, value); 72 } else { 73 // Set 16 most significant bits of value. The "lui" instruction 74 // also clears the 16 least significant bits to zero. 75 a->Lui(rd, value >> 16); 76 if (value & 0xFFFF) { 77 // If the 16 least significant bits are non-zero, set them 78 // here. 79 a->Ori(rd, rd, value); 80 } 81 } 82 } 83 84 static inline int InstrCountForLoadReplicatedConst32(int64_t value) { 85 int32_t x = Low32Bits(value); 86 int32_t y = High32Bits(value); 87 88 if (x == y) { 89 return (IsUint<16>(x) || IsInt<16>(x) || ((x & 0xFFFF) == 0 && IsInt<16>(value >> 16))) ? 2 : 3; 90 } 91 92 return INT_MAX; 93 } 94 95 template <typename Asm, typename Rtype, typename Vtype> 96 void TemplateLoadConst64(Asm* a, Rtype rd, Vtype value) { 97 int bit31 = (value & UINT64_C(0x80000000)) != 0; 98 int rep32_count = InstrCountForLoadReplicatedConst32(value); 99 100 // Loads with 1 instruction. 101 if (IsUint<16>(value)) { 102 // 64-bit value can be loaded as an unsigned 16-bit number. 103 a->RecordLoadConst64Path(kLoadConst64PathOri); 104 a->Ori(rd, ZERO, value); 105 } else if (IsInt<16>(value)) { 106 // 64-bit value can be loaded as an signed 16-bit number. 107 a->RecordLoadConst64Path(kLoadConst64PathDaddiu); 108 a->Daddiu(rd, ZERO, value); 109 } else if ((value & 0xFFFF) == 0 && IsInt<16>(value >> 16)) { 110 // 64-bit value can be loaded as an signed 32-bit number which has all 111 // of its 16 least significant bits set to zero. 112 a->RecordLoadConst64Path(kLoadConst64PathLui); 113 a->Lui(rd, value >> 16); 114 } else if (IsInt<32>(value)) { 115 // Loads with 2 instructions. 116 // 64-bit value can be loaded as an signed 32-bit number which has some 117 // or all of its 16 least significant bits set to one. 118 a->RecordLoadConst64Path(kLoadConst64PathLuiOri); 119 a->Lui(rd, value >> 16); 120 a->Ori(rd, rd, value); 121 } else if ((value & 0xFFFF0000) == 0 && IsInt<16>(value >> 32)) { 122 // 64-bit value which consists of an unsigned 16-bit value in its 123 // least significant 32-bits, and a signed 16-bit value in its 124 // most significant 32-bits. 125 a->RecordLoadConst64Path(kLoadConst64PathOriDahi); 126 a->Ori(rd, ZERO, value); 127 a->Dahi(rd, value >> 32); 128 } else if ((value & UINT64_C(0xFFFFFFFF0000)) == 0) { 129 // 64-bit value which consists of an unsigned 16-bit value in its 130 // least significant 48-bits, and a signed 16-bit value in its 131 // most significant 16-bits. 132 a->RecordLoadConst64Path(kLoadConst64PathOriDati); 133 a->Ori(rd, ZERO, value); 134 a->Dati(rd, value >> 48); 135 } else if ((value & 0xFFFF) == 0 && 136 (-32768 - bit31) <= (value >> 32) && (value >> 32) <= (32767 - bit31)) { 137 // 16 LSBs (Least Significant Bits) all set to zero. 138 // 48 MSBs (Most Significant Bits) hold a signed 32-bit value. 139 a->RecordLoadConst64Path(kLoadConst64PathLuiDahi); 140 a->Lui(rd, value >> 16); 141 a->Dahi(rd, (value >> 32) + bit31); 142 } else if ((value & 0xFFFF) == 0 && ((value >> 31) & 0x1FFFF) == ((0x20000 - bit31) & 0x1FFFF)) { 143 // 16 LSBs all set to zero. 144 // 48 MSBs hold a signed value which can't be represented by signed 145 // 32-bit number, and the middle 16 bits are all zero, or all one. 146 a->RecordLoadConst64Path(kLoadConst64PathLuiDati); 147 a->Lui(rd, value >> 16); 148 a->Dati(rd, (value >> 48) + bit31); 149 } else if (IsInt<16>(static_cast<int32_t>(value)) && 150 (-32768 - bit31) <= (value >> 32) && (value >> 32) <= (32767 - bit31)) { 151 // 32 LSBs contain an unsigned 16-bit number. 152 // 32 MSBs contain a signed 16-bit number. 153 a->RecordLoadConst64Path(kLoadConst64PathDaddiuDahi); 154 a->Daddiu(rd, ZERO, value); 155 a->Dahi(rd, (value >> 32) + bit31); 156 } else if (IsInt<16>(static_cast<int32_t>(value)) && 157 ((value >> 31) & 0x1FFFF) == ((0x20000 - bit31) & 0x1FFFF)) { 158 // 48 LSBs contain an unsigned 16-bit number. 159 // 16 MSBs contain a signed 16-bit number. 160 a->RecordLoadConst64Path(kLoadConst64PathDaddiuDati); 161 a->Daddiu(rd, ZERO, value); 162 a->Dati(rd, (value >> 48) + bit31); 163 } else if (IsPowerOfTwo(value + UINT64_C(1))) { 164 // 64-bit values which have their "n" MSBs set to one, and their 165 // "64-n" LSBs set to zero. "n" must meet the restrictions 0 < n < 64. 166 int shift_cnt = 64 - CTZ(value + UINT64_C(1)); 167 a->RecordLoadConst64Path(kLoadConst64PathDaddiuDsrlX); 168 a->Daddiu(rd, ZERO, -1); 169 if (shift_cnt < 32) { 170 a->Dsrl(rd, rd, shift_cnt); 171 } else { 172 a->Dsrl32(rd, rd, shift_cnt & 31); 173 } 174 } else { 175 int shift_cnt = CTZ(value); 176 int64_t tmp = value >> shift_cnt; 177 a->RecordLoadConst64Path(kLoadConst64PathOriDsllX); 178 if (IsUint<16>(tmp)) { 179 // Value can be computed by loading a 16-bit unsigned value, and 180 // then shifting left. 181 a->Ori(rd, ZERO, tmp); 182 if (shift_cnt < 32) { 183 a->Dsll(rd, rd, shift_cnt); 184 } else { 185 a->Dsll32(rd, rd, shift_cnt & 31); 186 } 187 } else if (IsInt<16>(tmp)) { 188 // Value can be computed by loading a 16-bit signed value, and 189 // then shifting left. 190 a->RecordLoadConst64Path(kLoadConst64PathDaddiuDsllX); 191 a->Daddiu(rd, ZERO, tmp); 192 if (shift_cnt < 32) { 193 a->Dsll(rd, rd, shift_cnt); 194 } else { 195 a->Dsll32(rd, rd, shift_cnt & 31); 196 } 197 } else if (rep32_count < 3) { 198 // Value being loaded has 32 LSBs equal to the 32 MSBs, and the 199 // value loaded into the 32 LSBs can be loaded with a single 200 // MIPS instruction. 201 a->LoadConst32(rd, value); 202 a->Dinsu(rd, rd, 32, 32); 203 a->RecordLoadConst64Path(kLoadConst64PathDinsu1); 204 } else if (IsInt<32>(tmp)) { 205 // Loads with 3 instructions. 206 // Value can be computed by loading a 32-bit signed value, and 207 // then shifting left. 208 a->RecordLoadConst64Path(kLoadConst64PathLuiOriDsllX); 209 a->Lui(rd, tmp >> 16); 210 a->Ori(rd, rd, tmp); 211 if (shift_cnt < 32) { 212 a->Dsll(rd, rd, shift_cnt); 213 } else { 214 a->Dsll32(rd, rd, shift_cnt & 31); 215 } 216 } else { 217 shift_cnt = 16 + CTZ(value >> 16); 218 tmp = value >> shift_cnt; 219 if (IsUint<16>(tmp)) { 220 // Value can be computed by loading a 16-bit unsigned value, 221 // shifting left, and "or"ing in another 16-bit unsigned value. 222 a->RecordLoadConst64Path(kLoadConst64PathOriDsllXOri); 223 a->Ori(rd, ZERO, tmp); 224 if (shift_cnt < 32) { 225 a->Dsll(rd, rd, shift_cnt); 226 } else { 227 a->Dsll32(rd, rd, shift_cnt & 31); 228 } 229 a->Ori(rd, rd, value); 230 } else if (IsInt<16>(tmp)) { 231 // Value can be computed by loading a 16-bit signed value, 232 // shifting left, and "or"ing in a 16-bit unsigned value. 233 a->RecordLoadConst64Path(kLoadConst64PathDaddiuDsllXOri); 234 a->Daddiu(rd, ZERO, tmp); 235 if (shift_cnt < 32) { 236 a->Dsll(rd, rd, shift_cnt); 237 } else { 238 a->Dsll32(rd, rd, shift_cnt & 31); 239 } 240 a->Ori(rd, rd, value); 241 } else if (rep32_count < 4) { 242 // Value being loaded has 32 LSBs equal to the 32 MSBs, and the 243 // value in the 32 LSBs requires 2 MIPS instructions to load. 244 a->LoadConst32(rd, value); 245 a->Dinsu(rd, rd, 32, 32); 246 a->RecordLoadConst64Path(kLoadConst64PathDinsu2); 247 } else { 248 // Loads with 3-4 instructions. 249 // Catch-all case to get any other 64-bit values which aren't 250 // handled by special cases above. 251 uint64_t tmp2 = value; 252 a->RecordLoadConst64Path(kLoadConst64PathCatchAll); 253 a->LoadConst32(rd, value); 254 if (bit31) { 255 tmp2 += UINT64_C(0x100000000); 256 } 257 if (((tmp2 >> 32) & 0xFFFF) != 0) { 258 a->Dahi(rd, tmp2 >> 32); 259 } 260 if (tmp2 & UINT64_C(0x800000000000)) { 261 tmp2 += UINT64_C(0x1000000000000); 262 } 263 if ((tmp2 >> 48) != 0) { 264 a->Dati(rd, tmp2 >> 48); 265 } 266 } 267 } 268 } 269 } 270 271 static constexpr size_t kMips64HalfwordSize = 2; 272 static constexpr size_t kMips64WordSize = 4; 273 static constexpr size_t kMips64DoublewordSize = 8; 274 275 enum LoadOperandType { 276 kLoadSignedByte, 277 kLoadUnsignedByte, 278 kLoadSignedHalfword, 279 kLoadUnsignedHalfword, 280 kLoadWord, 281 kLoadUnsignedWord, 282 kLoadDoubleword, 283 kLoadQuadword 284 }; 285 286 enum StoreOperandType { 287 kStoreByte, 288 kStoreHalfword, 289 kStoreWord, 290 kStoreDoubleword, 291 kStoreQuadword 292 }; 293 294 // Used to test the values returned by ClassS/ClassD. 295 enum FPClassMaskType { 296 kSignalingNaN = 0x001, 297 kQuietNaN = 0x002, 298 kNegativeInfinity = 0x004, 299 kNegativeNormal = 0x008, 300 kNegativeSubnormal = 0x010, 301 kNegativeZero = 0x020, 302 kPositiveInfinity = 0x040, 303 kPositiveNormal = 0x080, 304 kPositiveSubnormal = 0x100, 305 kPositiveZero = 0x200, 306 }; 307 308 class Mips64Label : public Label { 309 public: 310 Mips64Label() : prev_branch_id_plus_one_(0) {} 311 312 Mips64Label(Mips64Label&& src) 313 : Label(std::move(src)), prev_branch_id_plus_one_(src.prev_branch_id_plus_one_) {} 314 315 private: 316 uint32_t prev_branch_id_plus_one_; // To get distance from preceding branch, if any. 317 318 friend class Mips64Assembler; 319 DISALLOW_COPY_AND_ASSIGN(Mips64Label); 320 }; 321 322 // Assembler literal is a value embedded in code, retrieved using a PC-relative load. 323 class Literal { 324 public: 325 static constexpr size_t kMaxSize = 8; 326 327 Literal(uint32_t size, const uint8_t* data) 328 : label_(), size_(size) { 329 DCHECK_LE(size, Literal::kMaxSize); 330 memcpy(data_, data, size); 331 } 332 333 template <typename T> 334 T GetValue() const { 335 DCHECK_EQ(size_, sizeof(T)); 336 T value; 337 memcpy(&value, data_, sizeof(T)); 338 return value; 339 } 340 341 uint32_t GetSize() const { 342 return size_; 343 } 344 345 const uint8_t* GetData() const { 346 return data_; 347 } 348 349 Mips64Label* GetLabel() { 350 return &label_; 351 } 352 353 const Mips64Label* GetLabel() const { 354 return &label_; 355 } 356 357 private: 358 Mips64Label label_; 359 const uint32_t size_; 360 uint8_t data_[kMaxSize]; 361 362 DISALLOW_COPY_AND_ASSIGN(Literal); 363 }; 364 365 // Jump table: table of labels emitted after the code and before the literals. Similar to literals. 366 class JumpTable { 367 public: 368 explicit JumpTable(std::vector<Mips64Label*>&& labels) 369 : label_(), labels_(std::move(labels)) { 370 } 371 372 size_t GetSize() const { 373 return labels_.size() * sizeof(uint32_t); 374 } 375 376 const std::vector<Mips64Label*>& GetData() const { 377 return labels_; 378 } 379 380 Mips64Label* GetLabel() { 381 return &label_; 382 } 383 384 const Mips64Label* GetLabel() const { 385 return &label_; 386 } 387 388 private: 389 Mips64Label label_; 390 std::vector<Mips64Label*> labels_; 391 392 DISALLOW_COPY_AND_ASSIGN(JumpTable); 393 }; 394 395 // Slowpath entered when Thread::Current()->_exception is non-null. 396 class Mips64ExceptionSlowPath { 397 public: 398 explicit Mips64ExceptionSlowPath(Mips64ManagedRegister scratch, size_t stack_adjust) 399 : scratch_(scratch), stack_adjust_(stack_adjust) {} 400 401 Mips64ExceptionSlowPath(Mips64ExceptionSlowPath&& src) 402 : scratch_(src.scratch_), 403 stack_adjust_(src.stack_adjust_), 404 exception_entry_(std::move(src.exception_entry_)) {} 405 406 private: 407 Mips64Label* Entry() { return &exception_entry_; } 408 const Mips64ManagedRegister scratch_; 409 const size_t stack_adjust_; 410 Mips64Label exception_entry_; 411 412 friend class Mips64Assembler; 413 DISALLOW_COPY_AND_ASSIGN(Mips64ExceptionSlowPath); 414 }; 415 416 class Mips64Assembler FINAL : public Assembler, public JNIMacroAssembler<PointerSize::k64> { 417 public: 418 using JNIBase = JNIMacroAssembler<PointerSize::k64>; 419 420 explicit Mips64Assembler(ArenaAllocator* arena, 421 const Mips64InstructionSetFeatures* instruction_set_features = nullptr) 422 : Assembler(arena), 423 overwriting_(false), 424 overwrite_location_(0), 425 literals_(arena->Adapter(kArenaAllocAssembler)), 426 long_literals_(arena->Adapter(kArenaAllocAssembler)), 427 jump_tables_(arena->Adapter(kArenaAllocAssembler)), 428 last_position_adjustment_(0), 429 last_old_position_(0), 430 last_branch_id_(0), 431 has_msa_(instruction_set_features != nullptr ? instruction_set_features->HasMsa() : false) { 432 cfi().DelayEmittingAdvancePCs(); 433 } 434 435 virtual ~Mips64Assembler() { 436 for (auto& branch : branches_) { 437 CHECK(branch.IsResolved()); 438 } 439 } 440 441 size_t CodeSize() const OVERRIDE { return Assembler::CodeSize(); } 442 DebugFrameOpCodeWriterForAssembler& cfi() { return Assembler::cfi(); } 443 444 // Emit Machine Instructions. 445 void Addu(GpuRegister rd, GpuRegister rs, GpuRegister rt); 446 void Addiu(GpuRegister rt, GpuRegister rs, uint16_t imm16); 447 void Daddu(GpuRegister rd, GpuRegister rs, GpuRegister rt); // MIPS64 448 void Daddiu(GpuRegister rt, GpuRegister rs, uint16_t imm16); // MIPS64 449 void Subu(GpuRegister rd, GpuRegister rs, GpuRegister rt); 450 void Dsubu(GpuRegister rd, GpuRegister rs, GpuRegister rt); // MIPS64 451 452 void MulR6(GpuRegister rd, GpuRegister rs, GpuRegister rt); 453 void MuhR6(GpuRegister rd, GpuRegister rs, GpuRegister rt); 454 void DivR6(GpuRegister rd, GpuRegister rs, GpuRegister rt); 455 void ModR6(GpuRegister rd, GpuRegister rs, GpuRegister rt); 456 void DivuR6(GpuRegister rd, GpuRegister rs, GpuRegister rt); 457 void ModuR6(GpuRegister rd, GpuRegister rs, GpuRegister rt); 458 void Dmul(GpuRegister rd, GpuRegister rs, GpuRegister rt); // MIPS64 459 void Dmuh(GpuRegister rd, GpuRegister rs, GpuRegister rt); // MIPS64 460 void Ddiv(GpuRegister rd, GpuRegister rs, GpuRegister rt); // MIPS64 461 void Dmod(GpuRegister rd, GpuRegister rs, GpuRegister rt); // MIPS64 462 void Ddivu(GpuRegister rd, GpuRegister rs, GpuRegister rt); // MIPS64 463 void Dmodu(GpuRegister rd, GpuRegister rs, GpuRegister rt); // MIPS64 464 465 void And(GpuRegister rd, GpuRegister rs, GpuRegister rt); 466 void Andi(GpuRegister rt, GpuRegister rs, uint16_t imm16); 467 void Or(GpuRegister rd, GpuRegister rs, GpuRegister rt); 468 void Ori(GpuRegister rt, GpuRegister rs, uint16_t imm16); 469 void Xor(GpuRegister rd, GpuRegister rs, GpuRegister rt); 470 void Xori(GpuRegister rt, GpuRegister rs, uint16_t imm16); 471 void Nor(GpuRegister rd, GpuRegister rs, GpuRegister rt); 472 473 void Bitswap(GpuRegister rd, GpuRegister rt); 474 void Dbitswap(GpuRegister rd, GpuRegister rt); // MIPS64 475 void Seb(GpuRegister rd, GpuRegister rt); 476 void Seh(GpuRegister rd, GpuRegister rt); 477 void Dsbh(GpuRegister rd, GpuRegister rt); // MIPS64 478 void Dshd(GpuRegister rd, GpuRegister rt); // MIPS64 479 void Dext(GpuRegister rs, GpuRegister rt, int pos, int size); // MIPS64 480 void Dinsu(GpuRegister rt, GpuRegister rs, int pos, int size); // MIPS64 481 void Lsa(GpuRegister rd, GpuRegister rs, GpuRegister rt, int saPlusOne); 482 void Dlsa(GpuRegister rd, GpuRegister rs, GpuRegister rt, int saPlusOne); // MIPS64 483 void Wsbh(GpuRegister rd, GpuRegister rt); 484 void Sc(GpuRegister rt, GpuRegister base, int16_t imm9 = 0); 485 void Scd(GpuRegister rt, GpuRegister base, int16_t imm9 = 0); // MIPS64 486 void Ll(GpuRegister rt, GpuRegister base, int16_t imm9 = 0); 487 void Lld(GpuRegister rt, GpuRegister base, int16_t imm9 = 0); // MIPS64 488 489 void Sll(GpuRegister rd, GpuRegister rt, int shamt); 490 void Srl(GpuRegister rd, GpuRegister rt, int shamt); 491 void Rotr(GpuRegister rd, GpuRegister rt, int shamt); 492 void Sra(GpuRegister rd, GpuRegister rt, int shamt); 493 void Sllv(GpuRegister rd, GpuRegister rt, GpuRegister rs); 494 void Srlv(GpuRegister rd, GpuRegister rt, GpuRegister rs); 495 void Rotrv(GpuRegister rd, GpuRegister rt, GpuRegister rs); 496 void Srav(GpuRegister rd, GpuRegister rt, GpuRegister rs); 497 void Dsll(GpuRegister rd, GpuRegister rt, int shamt); // MIPS64 498 void Dsrl(GpuRegister rd, GpuRegister rt, int shamt); // MIPS64 499 void Drotr(GpuRegister rd, GpuRegister rt, int shamt); // MIPS64 500 void Dsra(GpuRegister rd, GpuRegister rt, int shamt); // MIPS64 501 void Dsll32(GpuRegister rd, GpuRegister rt, int shamt); // MIPS64 502 void Dsrl32(GpuRegister rd, GpuRegister rt, int shamt); // MIPS64 503 void Drotr32(GpuRegister rd, GpuRegister rt, int shamt); // MIPS64 504 void Dsra32(GpuRegister rd, GpuRegister rt, int shamt); // MIPS64 505 void Dsllv(GpuRegister rd, GpuRegister rt, GpuRegister rs); // MIPS64 506 void Dsrlv(GpuRegister rd, GpuRegister rt, GpuRegister rs); // MIPS64 507 void Drotrv(GpuRegister rd, GpuRegister rt, GpuRegister rs); // MIPS64 508 void Dsrav(GpuRegister rd, GpuRegister rt, GpuRegister rs); // MIPS64 509 510 void Lb(GpuRegister rt, GpuRegister rs, uint16_t imm16); 511 void Lh(GpuRegister rt, GpuRegister rs, uint16_t imm16); 512 void Lw(GpuRegister rt, GpuRegister rs, uint16_t imm16); 513 void Ld(GpuRegister rt, GpuRegister rs, uint16_t imm16); // MIPS64 514 void Lbu(GpuRegister rt, GpuRegister rs, uint16_t imm16); 515 void Lhu(GpuRegister rt, GpuRegister rs, uint16_t imm16); 516 void Lwu(GpuRegister rt, GpuRegister rs, uint16_t imm16); // MIPS64 517 void Lwpc(GpuRegister rs, uint32_t imm19); 518 void Lwupc(GpuRegister rs, uint32_t imm19); // MIPS64 519 void Ldpc(GpuRegister rs, uint32_t imm18); // MIPS64 520 void Lui(GpuRegister rt, uint16_t imm16); 521 void Aui(GpuRegister rt, GpuRegister rs, uint16_t imm16); 522 void Daui(GpuRegister rt, GpuRegister rs, uint16_t imm16); // MIPS64 523 void Dahi(GpuRegister rs, uint16_t imm16); // MIPS64 524 void Dati(GpuRegister rs, uint16_t imm16); // MIPS64 525 void Sync(uint32_t stype); 526 527 void Sb(GpuRegister rt, GpuRegister rs, uint16_t imm16); 528 void Sh(GpuRegister rt, GpuRegister rs, uint16_t imm16); 529 void Sw(GpuRegister rt, GpuRegister rs, uint16_t imm16); 530 void Sd(GpuRegister rt, GpuRegister rs, uint16_t imm16); // MIPS64 531 532 void Slt(GpuRegister rd, GpuRegister rs, GpuRegister rt); 533 void Sltu(GpuRegister rd, GpuRegister rs, GpuRegister rt); 534 void Slti(GpuRegister rt, GpuRegister rs, uint16_t imm16); 535 void Sltiu(GpuRegister rt, GpuRegister rs, uint16_t imm16); 536 void Seleqz(GpuRegister rd, GpuRegister rs, GpuRegister rt); 537 void Selnez(GpuRegister rd, GpuRegister rs, GpuRegister rt); 538 void Clz(GpuRegister rd, GpuRegister rs); 539 void Clo(GpuRegister rd, GpuRegister rs); 540 void Dclz(GpuRegister rd, GpuRegister rs); // MIPS64 541 void Dclo(GpuRegister rd, GpuRegister rs); // MIPS64 542 543 void Jalr(GpuRegister rd, GpuRegister rs); 544 void Jalr(GpuRegister rs); 545 void Jr(GpuRegister rs); 546 void Auipc(GpuRegister rs, uint16_t imm16); 547 void Addiupc(GpuRegister rs, uint32_t imm19); 548 void Bc(uint32_t imm26); 549 void Balc(uint32_t imm26); 550 void Jic(GpuRegister rt, uint16_t imm16); 551 void Jialc(GpuRegister rt, uint16_t imm16); 552 void Bltc(GpuRegister rs, GpuRegister rt, uint16_t imm16); 553 void Bltzc(GpuRegister rt, uint16_t imm16); 554 void Bgtzc(GpuRegister rt, uint16_t imm16); 555 void Bgec(GpuRegister rs, GpuRegister rt, uint16_t imm16); 556 void Bgezc(GpuRegister rt, uint16_t imm16); 557 void Blezc(GpuRegister rt, uint16_t imm16); 558 void Bltuc(GpuRegister rs, GpuRegister rt, uint16_t imm16); 559 void Bgeuc(GpuRegister rs, GpuRegister rt, uint16_t imm16); 560 void Beqc(GpuRegister rs, GpuRegister rt, uint16_t imm16); 561 void Bnec(GpuRegister rs, GpuRegister rt, uint16_t imm16); 562 void Beqzc(GpuRegister rs, uint32_t imm21); 563 void Bnezc(GpuRegister rs, uint32_t imm21); 564 void Bc1eqz(FpuRegister ft, uint16_t imm16); 565 void Bc1nez(FpuRegister ft, uint16_t imm16); 566 567 void AddS(FpuRegister fd, FpuRegister fs, FpuRegister ft); 568 void SubS(FpuRegister fd, FpuRegister fs, FpuRegister ft); 569 void MulS(FpuRegister fd, FpuRegister fs, FpuRegister ft); 570 void DivS(FpuRegister fd, FpuRegister fs, FpuRegister ft); 571 void AddD(FpuRegister fd, FpuRegister fs, FpuRegister ft); 572 void SubD(FpuRegister fd, FpuRegister fs, FpuRegister ft); 573 void MulD(FpuRegister fd, FpuRegister fs, FpuRegister ft); 574 void DivD(FpuRegister fd, FpuRegister fs, FpuRegister ft); 575 void SqrtS(FpuRegister fd, FpuRegister fs); 576 void SqrtD(FpuRegister fd, FpuRegister fs); 577 void AbsS(FpuRegister fd, FpuRegister fs); 578 void AbsD(FpuRegister fd, FpuRegister fs); 579 void MovS(FpuRegister fd, FpuRegister fs); 580 void MovD(FpuRegister fd, FpuRegister fs); 581 void NegS(FpuRegister fd, FpuRegister fs); 582 void NegD(FpuRegister fd, FpuRegister fs); 583 void RoundLS(FpuRegister fd, FpuRegister fs); 584 void RoundLD(FpuRegister fd, FpuRegister fs); 585 void RoundWS(FpuRegister fd, FpuRegister fs); 586 void RoundWD(FpuRegister fd, FpuRegister fs); 587 void TruncLS(FpuRegister fd, FpuRegister fs); 588 void TruncLD(FpuRegister fd, FpuRegister fs); 589 void TruncWS(FpuRegister fd, FpuRegister fs); 590 void TruncWD(FpuRegister fd, FpuRegister fs); 591 void CeilLS(FpuRegister fd, FpuRegister fs); 592 void CeilLD(FpuRegister fd, FpuRegister fs); 593 void CeilWS(FpuRegister fd, FpuRegister fs); 594 void CeilWD(FpuRegister fd, FpuRegister fs); 595 void FloorLS(FpuRegister fd, FpuRegister fs); 596 void FloorLD(FpuRegister fd, FpuRegister fs); 597 void FloorWS(FpuRegister fd, FpuRegister fs); 598 void FloorWD(FpuRegister fd, FpuRegister fs); 599 void SelS(FpuRegister fd, FpuRegister fs, FpuRegister ft); 600 void SelD(FpuRegister fd, FpuRegister fs, FpuRegister ft); 601 void RintS(FpuRegister fd, FpuRegister fs); 602 void RintD(FpuRegister fd, FpuRegister fs); 603 void ClassS(FpuRegister fd, FpuRegister fs); 604 void ClassD(FpuRegister fd, FpuRegister fs); 605 void MinS(FpuRegister fd, FpuRegister fs, FpuRegister ft); 606 void MinD(FpuRegister fd, FpuRegister fs, FpuRegister ft); 607 void MaxS(FpuRegister fd, FpuRegister fs, FpuRegister ft); 608 void MaxD(FpuRegister fd, FpuRegister fs, FpuRegister ft); 609 void CmpUnS(FpuRegister fd, FpuRegister fs, FpuRegister ft); 610 void CmpEqS(FpuRegister fd, FpuRegister fs, FpuRegister ft); 611 void CmpUeqS(FpuRegister fd, FpuRegister fs, FpuRegister ft); 612 void CmpLtS(FpuRegister fd, FpuRegister fs, FpuRegister ft); 613 void CmpUltS(FpuRegister fd, FpuRegister fs, FpuRegister ft); 614 void CmpLeS(FpuRegister fd, FpuRegister fs, FpuRegister ft); 615 void CmpUleS(FpuRegister fd, FpuRegister fs, FpuRegister ft); 616 void CmpOrS(FpuRegister fd, FpuRegister fs, FpuRegister ft); 617 void CmpUneS(FpuRegister fd, FpuRegister fs, FpuRegister ft); 618 void CmpNeS(FpuRegister fd, FpuRegister fs, FpuRegister ft); 619 void CmpUnD(FpuRegister fd, FpuRegister fs, FpuRegister ft); 620 void CmpEqD(FpuRegister fd, FpuRegister fs, FpuRegister ft); 621 void CmpUeqD(FpuRegister fd, FpuRegister fs, FpuRegister ft); 622 void CmpLtD(FpuRegister fd, FpuRegister fs, FpuRegister ft); 623 void CmpUltD(FpuRegister fd, FpuRegister fs, FpuRegister ft); 624 void CmpLeD(FpuRegister fd, FpuRegister fs, FpuRegister ft); 625 void CmpUleD(FpuRegister fd, FpuRegister fs, FpuRegister ft); 626 void CmpOrD(FpuRegister fd, FpuRegister fs, FpuRegister ft); 627 void CmpUneD(FpuRegister fd, FpuRegister fs, FpuRegister ft); 628 void CmpNeD(FpuRegister fd, FpuRegister fs, FpuRegister ft); 629 630 void Cvtsw(FpuRegister fd, FpuRegister fs); 631 void Cvtdw(FpuRegister fd, FpuRegister fs); 632 void Cvtsd(FpuRegister fd, FpuRegister fs); 633 void Cvtds(FpuRegister fd, FpuRegister fs); 634 void Cvtsl(FpuRegister fd, FpuRegister fs); 635 void Cvtdl(FpuRegister fd, FpuRegister fs); 636 637 void Mfc1(GpuRegister rt, FpuRegister fs); 638 void Mfhc1(GpuRegister rt, FpuRegister fs); 639 void Mtc1(GpuRegister rt, FpuRegister fs); 640 void Mthc1(GpuRegister rt, FpuRegister fs); 641 void Dmfc1(GpuRegister rt, FpuRegister fs); // MIPS64 642 void Dmtc1(GpuRegister rt, FpuRegister fs); // MIPS64 643 void Lwc1(FpuRegister ft, GpuRegister rs, uint16_t imm16); 644 void Ldc1(FpuRegister ft, GpuRegister rs, uint16_t imm16); 645 void Swc1(FpuRegister ft, GpuRegister rs, uint16_t imm16); 646 void Sdc1(FpuRegister ft, GpuRegister rs, uint16_t imm16); 647 648 void Break(); 649 void Nop(); 650 void Move(GpuRegister rd, GpuRegister rs); 651 void Clear(GpuRegister rd); 652 void Not(GpuRegister rd, GpuRegister rs); 653 654 // MSA instructions. 655 void AndV(VectorRegister wd, VectorRegister ws, VectorRegister wt); 656 void OrV(VectorRegister wd, VectorRegister ws, VectorRegister wt); 657 void NorV(VectorRegister wd, VectorRegister ws, VectorRegister wt); 658 void XorV(VectorRegister wd, VectorRegister ws, VectorRegister wt); 659 660 void AddvB(VectorRegister wd, VectorRegister ws, VectorRegister wt); 661 void AddvH(VectorRegister wd, VectorRegister ws, VectorRegister wt); 662 void AddvW(VectorRegister wd, VectorRegister ws, VectorRegister wt); 663 void AddvD(VectorRegister wd, VectorRegister ws, VectorRegister wt); 664 void SubvB(VectorRegister wd, VectorRegister ws, VectorRegister wt); 665 void SubvH(VectorRegister wd, VectorRegister ws, VectorRegister wt); 666 void SubvW(VectorRegister wd, VectorRegister ws, VectorRegister wt); 667 void SubvD(VectorRegister wd, VectorRegister ws, VectorRegister wt); 668 void MulvB(VectorRegister wd, VectorRegister ws, VectorRegister wt); 669 void MulvH(VectorRegister wd, VectorRegister ws, VectorRegister wt); 670 void MulvW(VectorRegister wd, VectorRegister ws, VectorRegister wt); 671 void MulvD(VectorRegister wd, VectorRegister ws, VectorRegister wt); 672 void Div_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt); 673 void Div_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt); 674 void Div_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt); 675 void Div_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt); 676 void Div_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt); 677 void Div_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt); 678 void Div_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt); 679 void Div_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt); 680 void Mod_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt); 681 void Mod_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt); 682 void Mod_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt); 683 void Mod_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt); 684 void Mod_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt); 685 void Mod_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt); 686 void Mod_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt); 687 void Mod_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt); 688 void Add_aB(VectorRegister wd, VectorRegister ws, VectorRegister wt); 689 void Add_aH(VectorRegister wd, VectorRegister ws, VectorRegister wt); 690 void Add_aW(VectorRegister wd, VectorRegister ws, VectorRegister wt); 691 void Add_aD(VectorRegister wd, VectorRegister ws, VectorRegister wt); 692 void Ave_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt); 693 void Ave_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt); 694 void Ave_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt); 695 void Ave_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt); 696 void Ave_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt); 697 void Ave_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt); 698 void Ave_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt); 699 void Ave_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt); 700 void Aver_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt); 701 void Aver_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt); 702 void Aver_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt); 703 void Aver_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt); 704 void Aver_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt); 705 void Aver_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt); 706 void Aver_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt); 707 void Aver_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt); 708 void Max_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt); 709 void Max_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt); 710 void Max_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt); 711 void Max_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt); 712 void Max_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt); 713 void Max_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt); 714 void Max_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt); 715 void Max_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt); 716 void Min_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt); 717 void Min_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt); 718 void Min_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt); 719 void Min_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt); 720 void Min_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt); 721 void Min_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt); 722 void Min_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt); 723 void Min_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt); 724 725 void FaddW(VectorRegister wd, VectorRegister ws, VectorRegister wt); 726 void FaddD(VectorRegister wd, VectorRegister ws, VectorRegister wt); 727 void FsubW(VectorRegister wd, VectorRegister ws, VectorRegister wt); 728 void FsubD(VectorRegister wd, VectorRegister ws, VectorRegister wt); 729 void FmulW(VectorRegister wd, VectorRegister ws, VectorRegister wt); 730 void FmulD(VectorRegister wd, VectorRegister ws, VectorRegister wt); 731 void FdivW(VectorRegister wd, VectorRegister ws, VectorRegister wt); 732 void FdivD(VectorRegister wd, VectorRegister ws, VectorRegister wt); 733 void FmaxW(VectorRegister wd, VectorRegister ws, VectorRegister wt); 734 void FmaxD(VectorRegister wd, VectorRegister ws, VectorRegister wt); 735 void FminW(VectorRegister wd, VectorRegister ws, VectorRegister wt); 736 void FminD(VectorRegister wd, VectorRegister ws, VectorRegister wt); 737 738 void Ffint_sW(VectorRegister wd, VectorRegister ws); 739 void Ffint_sD(VectorRegister wd, VectorRegister ws); 740 void Ftint_sW(VectorRegister wd, VectorRegister ws); 741 void Ftint_sD(VectorRegister wd, VectorRegister ws); 742 743 void SllB(VectorRegister wd, VectorRegister ws, VectorRegister wt); 744 void SllH(VectorRegister wd, VectorRegister ws, VectorRegister wt); 745 void SllW(VectorRegister wd, VectorRegister ws, VectorRegister wt); 746 void SllD(VectorRegister wd, VectorRegister ws, VectorRegister wt); 747 void SraB(VectorRegister wd, VectorRegister ws, VectorRegister wt); 748 void SraH(VectorRegister wd, VectorRegister ws, VectorRegister wt); 749 void SraW(VectorRegister wd, VectorRegister ws, VectorRegister wt); 750 void SraD(VectorRegister wd, VectorRegister ws, VectorRegister wt); 751 void SrlB(VectorRegister wd, VectorRegister ws, VectorRegister wt); 752 void SrlH(VectorRegister wd, VectorRegister ws, VectorRegister wt); 753 void SrlW(VectorRegister wd, VectorRegister ws, VectorRegister wt); 754 void SrlD(VectorRegister wd, VectorRegister ws, VectorRegister wt); 755 756 // Immediate shift instructions, where shamtN denotes shift amount (must be between 0 and 2^N-1). 757 void SlliB(VectorRegister wd, VectorRegister ws, int shamt3); 758 void SlliH(VectorRegister wd, VectorRegister ws, int shamt4); 759 void SlliW(VectorRegister wd, VectorRegister ws, int shamt5); 760 void SlliD(VectorRegister wd, VectorRegister ws, int shamt6); 761 void SraiB(VectorRegister wd, VectorRegister ws, int shamt3); 762 void SraiH(VectorRegister wd, VectorRegister ws, int shamt4); 763 void SraiW(VectorRegister wd, VectorRegister ws, int shamt5); 764 void SraiD(VectorRegister wd, VectorRegister ws, int shamt6); 765 void SrliB(VectorRegister wd, VectorRegister ws, int shamt3); 766 void SrliH(VectorRegister wd, VectorRegister ws, int shamt4); 767 void SrliW(VectorRegister wd, VectorRegister ws, int shamt5); 768 void SrliD(VectorRegister wd, VectorRegister ws, int shamt6); 769 770 void MoveV(VectorRegister wd, VectorRegister ws); 771 void SplatiB(VectorRegister wd, VectorRegister ws, int n4); 772 void SplatiH(VectorRegister wd, VectorRegister ws, int n3); 773 void SplatiW(VectorRegister wd, VectorRegister ws, int n2); 774 void SplatiD(VectorRegister wd, VectorRegister ws, int n1); 775 void FillB(VectorRegister wd, GpuRegister rs); 776 void FillH(VectorRegister wd, GpuRegister rs); 777 void FillW(VectorRegister wd, GpuRegister rs); 778 void FillD(VectorRegister wd, GpuRegister rs); 779 780 void LdiB(VectorRegister wd, int imm8); 781 void LdiH(VectorRegister wd, int imm10); 782 void LdiW(VectorRegister wd, int imm10); 783 void LdiD(VectorRegister wd, int imm10); 784 void LdB(VectorRegister wd, GpuRegister rs, int offset); 785 void LdH(VectorRegister wd, GpuRegister rs, int offset); 786 void LdW(VectorRegister wd, GpuRegister rs, int offset); 787 void LdD(VectorRegister wd, GpuRegister rs, int offset); 788 void StB(VectorRegister wd, GpuRegister rs, int offset); 789 void StH(VectorRegister wd, GpuRegister rs, int offset); 790 void StW(VectorRegister wd, GpuRegister rs, int offset); 791 void StD(VectorRegister wd, GpuRegister rs, int offset); 792 793 void IlvrB(VectorRegister wd, VectorRegister ws, VectorRegister wt); 794 void IlvrH(VectorRegister wd, VectorRegister ws, VectorRegister wt); 795 void IlvrW(VectorRegister wd, VectorRegister ws, VectorRegister wt); 796 void IlvrD(VectorRegister wd, VectorRegister ws, VectorRegister wt); 797 798 // Helper for replicating floating point value in all destination elements. 799 void ReplicateFPToVectorRegister(VectorRegister dst, FpuRegister src, bool is_double); 800 801 // Higher level composite instructions. 802 int InstrCountForLoadReplicatedConst32(int64_t); 803 void LoadConst32(GpuRegister rd, int32_t value); 804 void LoadConst64(GpuRegister rd, int64_t value); // MIPS64 805 806 // This function is only used for testing purposes. 807 void RecordLoadConst64Path(int value); 808 809 void Addiu32(GpuRegister rt, GpuRegister rs, int32_t value); 810 void Daddiu64(GpuRegister rt, GpuRegister rs, int64_t value, GpuRegister rtmp = AT); // MIPS64 811 812 // 813 // Heap poisoning. 814 // 815 816 // Poison a heap reference contained in `src` and store it in `dst`. 817 void PoisonHeapReference(GpuRegister dst, GpuRegister src) { 818 // dst = -src. 819 // Negate the 32-bit ref. 820 Dsubu(dst, ZERO, src); 821 // And constrain it to 32 bits (zero-extend into bits 32 through 63) as on Arm64 and x86/64. 822 Dext(dst, dst, 0, 32); 823 } 824 // Poison a heap reference contained in `reg`. 825 void PoisonHeapReference(GpuRegister reg) { 826 // reg = -reg. 827 PoisonHeapReference(reg, reg); 828 } 829 // Unpoison a heap reference contained in `reg`. 830 void UnpoisonHeapReference(GpuRegister reg) { 831 // reg = -reg. 832 // Negate the 32-bit ref. 833 Dsubu(reg, ZERO, reg); 834 // And constrain it to 32 bits (zero-extend into bits 32 through 63) as on Arm64 and x86/64. 835 Dext(reg, reg, 0, 32); 836 } 837 // Poison a heap reference contained in `reg` if heap poisoning is enabled. 838 void MaybePoisonHeapReference(GpuRegister reg) { 839 if (kPoisonHeapReferences) { 840 PoisonHeapReference(reg); 841 } 842 } 843 // Unpoison a heap reference contained in `reg` if heap poisoning is enabled. 844 void MaybeUnpoisonHeapReference(GpuRegister reg) { 845 if (kPoisonHeapReferences) { 846 UnpoisonHeapReference(reg); 847 } 848 } 849 850 void Bind(Label* label) OVERRIDE { 851 Bind(down_cast<Mips64Label*>(label)); 852 } 853 void Jump(Label* label ATTRIBUTE_UNUSED) OVERRIDE { 854 UNIMPLEMENTED(FATAL) << "Do not use Jump for MIPS64"; 855 } 856 857 void Bind(Mips64Label* label); 858 859 // Don't warn about a different virtual Bind/Jump in the base class. 860 using JNIBase::Bind; 861 using JNIBase::Jump; 862 863 // Create a new label that can be used with Jump/Bind calls. 864 std::unique_ptr<JNIMacroLabel> CreateLabel() OVERRIDE { 865 LOG(FATAL) << "Not implemented on MIPS64"; 866 UNREACHABLE(); 867 } 868 // Emit an unconditional jump to the label. 869 void Jump(JNIMacroLabel* label ATTRIBUTE_UNUSED) OVERRIDE { 870 LOG(FATAL) << "Not implemented on MIPS64"; 871 UNREACHABLE(); 872 } 873 // Emit a conditional jump to the label by applying a unary condition test to the register. 874 void Jump(JNIMacroLabel* label ATTRIBUTE_UNUSED, 875 JNIMacroUnaryCondition cond ATTRIBUTE_UNUSED, 876 ManagedRegister test ATTRIBUTE_UNUSED) OVERRIDE { 877 LOG(FATAL) << "Not implemented on MIPS64"; 878 UNREACHABLE(); 879 } 880 881 // Code at this offset will serve as the target for the Jump call. 882 void Bind(JNIMacroLabel* label ATTRIBUTE_UNUSED) OVERRIDE { 883 LOG(FATAL) << "Not implemented on MIPS64"; 884 UNREACHABLE(); 885 } 886 887 // Create a new literal with a given value. 888 // NOTE: Force the template parameter to be explicitly specified. 889 template <typename T> 890 Literal* NewLiteral(typename Identity<T>::type value) { 891 static_assert(std::is_integral<T>::value, "T must be an integral type."); 892 return NewLiteral(sizeof(value), reinterpret_cast<const uint8_t*>(&value)); 893 } 894 895 // Load label address using PC-relative loads. To be used with data labels in the literal / 896 // jump table area only and not with regular code labels. 897 void LoadLabelAddress(GpuRegister dest_reg, Mips64Label* label); 898 899 // Create a new literal with the given data. 900 Literal* NewLiteral(size_t size, const uint8_t* data); 901 902 // Load literal using PC-relative loads. 903 void LoadLiteral(GpuRegister dest_reg, LoadOperandType load_type, Literal* literal); 904 905 // Create a jump table for the given labels that will be emitted when finalizing. 906 // When the table is emitted, offsets will be relative to the location of the table. 907 // The table location is determined by the location of its label (the label precedes 908 // the table data) and should be loaded using LoadLabelAddress(). 909 JumpTable* CreateJumpTable(std::vector<Mips64Label*>&& labels); 910 911 void Bc(Mips64Label* label); 912 void Balc(Mips64Label* label); 913 void Bltc(GpuRegister rs, GpuRegister rt, Mips64Label* label); 914 void Bltzc(GpuRegister rt, Mips64Label* label); 915 void Bgtzc(GpuRegister rt, Mips64Label* label); 916 void Bgec(GpuRegister rs, GpuRegister rt, Mips64Label* label); 917 void Bgezc(GpuRegister rt, Mips64Label* label); 918 void Blezc(GpuRegister rt, Mips64Label* label); 919 void Bltuc(GpuRegister rs, GpuRegister rt, Mips64Label* label); 920 void Bgeuc(GpuRegister rs, GpuRegister rt, Mips64Label* label); 921 void Beqc(GpuRegister rs, GpuRegister rt, Mips64Label* label); 922 void Bnec(GpuRegister rs, GpuRegister rt, Mips64Label* label); 923 void Beqzc(GpuRegister rs, Mips64Label* label); 924 void Bnezc(GpuRegister rs, Mips64Label* label); 925 void Bc1eqz(FpuRegister ft, Mips64Label* label); 926 void Bc1nez(FpuRegister ft, Mips64Label* label); 927 928 void EmitLoad(ManagedRegister m_dst, GpuRegister src_register, int32_t src_offset, size_t size); 929 void AdjustBaseAndOffset(GpuRegister& base, int32_t& offset, bool is_doubleword); 930 // If element_size_shift is negative at entry, its value will be calculated based on the offset. 931 void AdjustBaseOffsetAndElementSizeShift(GpuRegister& base, 932 int32_t& offset, 933 int& element_size_shift); 934 935 private: 936 // This will be used as an argument for loads/stores 937 // when there is no need for implicit null checks. 938 struct NoImplicitNullChecker { 939 void operator()() const {} 940 }; 941 942 public: 943 template <typename ImplicitNullChecker = NoImplicitNullChecker> 944 void StoreConstToOffset(StoreOperandType type, 945 int64_t value, 946 GpuRegister base, 947 int32_t offset, 948 GpuRegister temp, 949 ImplicitNullChecker null_checker = NoImplicitNullChecker()) { 950 // We permit `base` and `temp` to coincide (however, we check that neither is AT), 951 // in which case the `base` register may be overwritten in the process. 952 CHECK_NE(temp, AT); // Must not use AT as temp, so as not to overwrite the adjusted base. 953 AdjustBaseAndOffset(base, offset, /* is_doubleword */ (type == kStoreDoubleword)); 954 GpuRegister reg; 955 // If the adjustment left `base` unchanged and equal to `temp`, we can't use `temp` 956 // to load and hold the value but we can use AT instead as AT hasn't been used yet. 957 // Otherwise, `temp` can be used for the value. And if `temp` is the same as the 958 // original `base` (that is, `base` prior to the adjustment), the original `base` 959 // register will be overwritten. 960 if (base == temp) { 961 temp = AT; 962 } 963 964 if (type == kStoreDoubleword && IsAligned<kMips64DoublewordSize>(offset)) { 965 if (value == 0) { 966 reg = ZERO; 967 } else { 968 reg = temp; 969 LoadConst64(reg, value); 970 } 971 Sd(reg, base, offset); 972 null_checker(); 973 } else { 974 uint32_t low = Low32Bits(value); 975 uint32_t high = High32Bits(value); 976 if (low == 0) { 977 reg = ZERO; 978 } else { 979 reg = temp; 980 LoadConst32(reg, low); 981 } 982 switch (type) { 983 case kStoreByte: 984 Sb(reg, base, offset); 985 break; 986 case kStoreHalfword: 987 Sh(reg, base, offset); 988 break; 989 case kStoreWord: 990 Sw(reg, base, offset); 991 break; 992 case kStoreDoubleword: 993 // not aligned to kMips64DoublewordSize 994 CHECK_ALIGNED(offset, kMips64WordSize); 995 Sw(reg, base, offset); 996 null_checker(); 997 if (high == 0) { 998 reg = ZERO; 999 } else { 1000 reg = temp; 1001 if (high != low) { 1002 LoadConst32(reg, high); 1003 } 1004 } 1005 Sw(reg, base, offset + kMips64WordSize); 1006 break; 1007 default: 1008 LOG(FATAL) << "UNREACHABLE"; 1009 } 1010 if (type != kStoreDoubleword) { 1011 null_checker(); 1012 } 1013 } 1014 } 1015 1016 template <typename ImplicitNullChecker = NoImplicitNullChecker> 1017 void LoadFromOffset(LoadOperandType type, 1018 GpuRegister reg, 1019 GpuRegister base, 1020 int32_t offset, 1021 ImplicitNullChecker null_checker = NoImplicitNullChecker()) { 1022 AdjustBaseAndOffset(base, offset, /* is_doubleword */ (type == kLoadDoubleword)); 1023 1024 switch (type) { 1025 case kLoadSignedByte: 1026 Lb(reg, base, offset); 1027 break; 1028 case kLoadUnsignedByte: 1029 Lbu(reg, base, offset); 1030 break; 1031 case kLoadSignedHalfword: 1032 Lh(reg, base, offset); 1033 break; 1034 case kLoadUnsignedHalfword: 1035 Lhu(reg, base, offset); 1036 break; 1037 case kLoadWord: 1038 CHECK_ALIGNED(offset, kMips64WordSize); 1039 Lw(reg, base, offset); 1040 break; 1041 case kLoadUnsignedWord: 1042 CHECK_ALIGNED(offset, kMips64WordSize); 1043 Lwu(reg, base, offset); 1044 break; 1045 case kLoadDoubleword: 1046 if (!IsAligned<kMips64DoublewordSize>(offset)) { 1047 CHECK_ALIGNED(offset, kMips64WordSize); 1048 Lwu(reg, base, offset); 1049 null_checker(); 1050 Lwu(TMP2, base, offset + kMips64WordSize); 1051 Dinsu(reg, TMP2, 32, 32); 1052 } else { 1053 Ld(reg, base, offset); 1054 null_checker(); 1055 } 1056 break; 1057 default: 1058 LOG(FATAL) << "UNREACHABLE"; 1059 } 1060 if (type != kLoadDoubleword) { 1061 null_checker(); 1062 } 1063 } 1064 1065 template <typename ImplicitNullChecker = NoImplicitNullChecker> 1066 void LoadFpuFromOffset(LoadOperandType type, 1067 FpuRegister reg, 1068 GpuRegister base, 1069 int32_t offset, 1070 ImplicitNullChecker null_checker = NoImplicitNullChecker()) { 1071 int element_size_shift = -1; 1072 if (type != kLoadQuadword) { 1073 AdjustBaseAndOffset(base, offset, /* is_doubleword */ (type == kLoadDoubleword)); 1074 } else { 1075 AdjustBaseOffsetAndElementSizeShift(base, offset, element_size_shift); 1076 } 1077 1078 switch (type) { 1079 case kLoadWord: 1080 CHECK_ALIGNED(offset, kMips64WordSize); 1081 Lwc1(reg, base, offset); 1082 null_checker(); 1083 break; 1084 case kLoadDoubleword: 1085 if (!IsAligned<kMips64DoublewordSize>(offset)) { 1086 CHECK_ALIGNED(offset, kMips64WordSize); 1087 Lwc1(reg, base, offset); 1088 null_checker(); 1089 Lw(TMP2, base, offset + kMips64WordSize); 1090 Mthc1(TMP2, reg); 1091 } else { 1092 Ldc1(reg, base, offset); 1093 null_checker(); 1094 } 1095 break; 1096 case kLoadQuadword: 1097 switch (element_size_shift) { 1098 case TIMES_1: LdB(static_cast<VectorRegister>(reg), base, offset); break; 1099 case TIMES_2: LdH(static_cast<VectorRegister>(reg), base, offset); break; 1100 case TIMES_4: LdW(static_cast<VectorRegister>(reg), base, offset); break; 1101 case TIMES_8: LdD(static_cast<VectorRegister>(reg), base, offset); break; 1102 default: 1103 LOG(FATAL) << "UNREACHABLE"; 1104 } 1105 null_checker(); 1106 break; 1107 default: 1108 LOG(FATAL) << "UNREACHABLE"; 1109 } 1110 } 1111 1112 template <typename ImplicitNullChecker = NoImplicitNullChecker> 1113 void StoreToOffset(StoreOperandType type, 1114 GpuRegister reg, 1115 GpuRegister base, 1116 int32_t offset, 1117 ImplicitNullChecker null_checker = NoImplicitNullChecker()) { 1118 // Must not use AT as `reg`, so as not to overwrite the value being stored 1119 // with the adjusted `base`. 1120 CHECK_NE(reg, AT); 1121 AdjustBaseAndOffset(base, offset, /* is_doubleword */ (type == kStoreDoubleword)); 1122 1123 switch (type) { 1124 case kStoreByte: 1125 Sb(reg, base, offset); 1126 break; 1127 case kStoreHalfword: 1128 Sh(reg, base, offset); 1129 break; 1130 case kStoreWord: 1131 CHECK_ALIGNED(offset, kMips64WordSize); 1132 Sw(reg, base, offset); 1133 break; 1134 case kStoreDoubleword: 1135 if (!IsAligned<kMips64DoublewordSize>(offset)) { 1136 CHECK_ALIGNED(offset, kMips64WordSize); 1137 Sw(reg, base, offset); 1138 null_checker(); 1139 Dsrl32(TMP2, reg, 0); 1140 Sw(TMP2, base, offset + kMips64WordSize); 1141 } else { 1142 Sd(reg, base, offset); 1143 null_checker(); 1144 } 1145 break; 1146 default: 1147 LOG(FATAL) << "UNREACHABLE"; 1148 } 1149 if (type != kStoreDoubleword) { 1150 null_checker(); 1151 } 1152 } 1153 1154 template <typename ImplicitNullChecker = NoImplicitNullChecker> 1155 void StoreFpuToOffset(StoreOperandType type, 1156 FpuRegister reg, 1157 GpuRegister base, 1158 int32_t offset, 1159 ImplicitNullChecker null_checker = NoImplicitNullChecker()) { 1160 int element_size_shift = -1; 1161 if (type != kStoreQuadword) { 1162 AdjustBaseAndOffset(base, offset, /* is_doubleword */ (type == kStoreDoubleword)); 1163 } else { 1164 AdjustBaseOffsetAndElementSizeShift(base, offset, element_size_shift); 1165 } 1166 1167 switch (type) { 1168 case kStoreWord: 1169 CHECK_ALIGNED(offset, kMips64WordSize); 1170 Swc1(reg, base, offset); 1171 null_checker(); 1172 break; 1173 case kStoreDoubleword: 1174 if (!IsAligned<kMips64DoublewordSize>(offset)) { 1175 CHECK_ALIGNED(offset, kMips64WordSize); 1176 Mfhc1(TMP2, reg); 1177 Swc1(reg, base, offset); 1178 null_checker(); 1179 Sw(TMP2, base, offset + kMips64WordSize); 1180 } else { 1181 Sdc1(reg, base, offset); 1182 null_checker(); 1183 } 1184 break; 1185 case kStoreQuadword: 1186 switch (element_size_shift) { 1187 case TIMES_1: StB(static_cast<VectorRegister>(reg), base, offset); break; 1188 case TIMES_2: StH(static_cast<VectorRegister>(reg), base, offset); break; 1189 case TIMES_4: StW(static_cast<VectorRegister>(reg), base, offset); break; 1190 case TIMES_8: StD(static_cast<VectorRegister>(reg), base, offset); break; 1191 default: 1192 LOG(FATAL) << "UNREACHABLE"; 1193 } 1194 null_checker(); 1195 break; 1196 default: 1197 LOG(FATAL) << "UNREACHABLE"; 1198 } 1199 } 1200 1201 void LoadFromOffset(LoadOperandType type, GpuRegister reg, GpuRegister base, int32_t offset); 1202 void LoadFpuFromOffset(LoadOperandType type, FpuRegister reg, GpuRegister base, int32_t offset); 1203 void StoreToOffset(StoreOperandType type, GpuRegister reg, GpuRegister base, int32_t offset); 1204 void StoreFpuToOffset(StoreOperandType type, FpuRegister reg, GpuRegister base, int32_t offset); 1205 1206 // Emit data (e.g. encoded instruction or immediate) to the instruction stream. 1207 void Emit(uint32_t value); 1208 1209 // 1210 // Overridden common assembler high-level functionality. 1211 // 1212 1213 // Emit code that will create an activation on the stack. 1214 void BuildFrame(size_t frame_size, 1215 ManagedRegister method_reg, 1216 ArrayRef<const ManagedRegister> callee_save_regs, 1217 const ManagedRegisterEntrySpills& entry_spills) OVERRIDE; 1218 1219 // Emit code that will remove an activation from the stack. 1220 void RemoveFrame(size_t frame_size, ArrayRef<const ManagedRegister> callee_save_regs) OVERRIDE; 1221 1222 void IncreaseFrameSize(size_t adjust) OVERRIDE; 1223 void DecreaseFrameSize(size_t adjust) OVERRIDE; 1224 1225 // Store routines. 1226 void Store(FrameOffset offs, ManagedRegister msrc, size_t size) OVERRIDE; 1227 void StoreRef(FrameOffset dest, ManagedRegister msrc) OVERRIDE; 1228 void StoreRawPtr(FrameOffset dest, ManagedRegister msrc) OVERRIDE; 1229 1230 void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister mscratch) OVERRIDE; 1231 1232 void StoreStackOffsetToThread(ThreadOffset64 thr_offs, 1233 FrameOffset fr_offs, 1234 ManagedRegister mscratch) OVERRIDE; 1235 1236 void StoreStackPointerToThread(ThreadOffset64 thr_offs) OVERRIDE; 1237 1238 void StoreSpanning(FrameOffset dest, ManagedRegister msrc, FrameOffset in_off, 1239 ManagedRegister mscratch) OVERRIDE; 1240 1241 // Load routines. 1242 void Load(ManagedRegister mdest, FrameOffset src, size_t size) OVERRIDE; 1243 1244 void LoadFromThread(ManagedRegister mdest, ThreadOffset64 src, size_t size) OVERRIDE; 1245 1246 void LoadRef(ManagedRegister dest, FrameOffset src) OVERRIDE; 1247 1248 void LoadRef(ManagedRegister mdest, ManagedRegister base, MemberOffset offs, 1249 bool unpoison_reference) OVERRIDE; 1250 1251 void LoadRawPtr(ManagedRegister mdest, ManagedRegister base, Offset offs) OVERRIDE; 1252 1253 void LoadRawPtrFromThread(ManagedRegister mdest, ThreadOffset64 offs) OVERRIDE; 1254 1255 // Copying routines. 1256 void Move(ManagedRegister mdest, ManagedRegister msrc, size_t size) OVERRIDE; 1257 1258 void CopyRawPtrFromThread(FrameOffset fr_offs, 1259 ThreadOffset64 thr_offs, 1260 ManagedRegister mscratch) OVERRIDE; 1261 1262 void CopyRawPtrToThread(ThreadOffset64 thr_offs, 1263 FrameOffset fr_offs, 1264 ManagedRegister mscratch) OVERRIDE; 1265 1266 void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister mscratch) OVERRIDE; 1267 1268 void Copy(FrameOffset dest, FrameOffset src, ManagedRegister mscratch, size_t size) OVERRIDE; 1269 1270 void Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset, ManagedRegister mscratch, 1271 size_t size) OVERRIDE; 1272 1273 void Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src, 1274 ManagedRegister mscratch, size_t size) OVERRIDE; 1275 1276 void Copy(FrameOffset dest, FrameOffset src_base, Offset src_offset, ManagedRegister mscratch, 1277 size_t size) OVERRIDE; 1278 1279 void Copy(ManagedRegister dest, Offset dest_offset, ManagedRegister src, Offset src_offset, 1280 ManagedRegister mscratch, size_t size) OVERRIDE; 1281 1282 void Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset, 1283 ManagedRegister mscratch, size_t size) OVERRIDE; 1284 1285 void MemoryBarrier(ManagedRegister) OVERRIDE; 1286 1287 // Sign extension. 1288 void SignExtend(ManagedRegister mreg, size_t size) OVERRIDE; 1289 1290 // Zero extension. 1291 void ZeroExtend(ManagedRegister mreg, size_t size) OVERRIDE; 1292 1293 // Exploit fast access in managed code to Thread::Current(). 1294 void GetCurrentThread(ManagedRegister tr) OVERRIDE; 1295 void GetCurrentThread(FrameOffset dest_offset, ManagedRegister mscratch) OVERRIDE; 1296 1297 // Set up out_reg to hold a Object** into the handle scope, or to be null if the 1298 // value is null and null_allowed. in_reg holds a possibly stale reference 1299 // that can be used to avoid loading the handle scope entry to see if the value is 1300 // null. 1301 void CreateHandleScopeEntry(ManagedRegister out_reg, FrameOffset handlescope_offset, 1302 ManagedRegister in_reg, bool null_allowed) OVERRIDE; 1303 1304 // Set up out_off to hold a Object** into the handle scope, or to be null if the 1305 // value is null and null_allowed. 1306 void CreateHandleScopeEntry(FrameOffset out_off, FrameOffset handlescope_offset, ManagedRegister 1307 mscratch, bool null_allowed) OVERRIDE; 1308 1309 // src holds a handle scope entry (Object**) load this into dst. 1310 void LoadReferenceFromHandleScope(ManagedRegister dst, ManagedRegister src) OVERRIDE; 1311 1312 // Heap::VerifyObject on src. In some cases (such as a reference to this) we 1313 // know that src may not be null. 1314 void VerifyObject(ManagedRegister src, bool could_be_null) OVERRIDE; 1315 void VerifyObject(FrameOffset src, bool could_be_null) OVERRIDE; 1316 1317 // Call to address held at [base+offset]. 1318 void Call(ManagedRegister base, Offset offset, ManagedRegister mscratch) OVERRIDE; 1319 void Call(FrameOffset base, Offset offset, ManagedRegister mscratch) OVERRIDE; 1320 void CallFromThread(ThreadOffset64 offset, ManagedRegister mscratch) OVERRIDE; 1321 1322 // Generate code to check if Thread::Current()->exception_ is non-null 1323 // and branch to a ExceptionSlowPath if it is. 1324 void ExceptionPoll(ManagedRegister mscratch, size_t stack_adjust) OVERRIDE; 1325 1326 // Emit slow paths queued during assembly and promote short branches to long if needed. 1327 void FinalizeCode() OVERRIDE; 1328 1329 // Emit branches and finalize all instructions. 1330 void FinalizeInstructions(const MemoryRegion& region); 1331 1332 // Returns the (always-)current location of a label (can be used in class CodeGeneratorMIPS64, 1333 // must be used instead of Mips64Label::GetPosition()). 1334 uint32_t GetLabelLocation(const Mips64Label* label) const; 1335 1336 // Get the final position of a label after local fixup based on the old position 1337 // recorded before FinalizeCode(). 1338 uint32_t GetAdjustedPosition(uint32_t old_position); 1339 1340 // Note that PC-relative literal loads are handled as pseudo branches because they need very 1341 // similar relocation and may similarly expand in size to accomodate for larger offsets relative 1342 // to PC. 1343 enum BranchCondition { 1344 kCondLT, 1345 kCondGE, 1346 kCondLE, 1347 kCondGT, 1348 kCondLTZ, 1349 kCondGEZ, 1350 kCondLEZ, 1351 kCondGTZ, 1352 kCondEQ, 1353 kCondNE, 1354 kCondEQZ, 1355 kCondNEZ, 1356 kCondLTU, 1357 kCondGEU, 1358 kCondF, // Floating-point predicate false. 1359 kCondT, // Floating-point predicate true. 1360 kUncond, 1361 }; 1362 friend std::ostream& operator<<(std::ostream& os, const BranchCondition& rhs); 1363 1364 private: 1365 class Branch { 1366 public: 1367 enum Type { 1368 // Short branches. 1369 kUncondBranch, 1370 kCondBranch, 1371 kCall, 1372 // Near label. 1373 kLabel, 1374 // Near literals. 1375 kLiteral, 1376 kLiteralUnsigned, 1377 kLiteralLong, 1378 // Long branches. 1379 kLongUncondBranch, 1380 kLongCondBranch, 1381 kLongCall, 1382 // Far label. 1383 kFarLabel, 1384 // Far literals. 1385 kFarLiteral, 1386 kFarLiteralUnsigned, 1387 kFarLiteralLong, 1388 }; 1389 1390 // Bit sizes of offsets defined as enums to minimize chance of typos. 1391 enum OffsetBits { 1392 kOffset16 = 16, 1393 kOffset18 = 18, 1394 kOffset21 = 21, 1395 kOffset23 = 23, 1396 kOffset28 = 28, 1397 kOffset32 = 32, 1398 }; 1399 1400 static constexpr uint32_t kUnresolved = 0xffffffff; // Unresolved target_ 1401 static constexpr int32_t kMaxBranchLength = 32; 1402 static constexpr int32_t kMaxBranchSize = kMaxBranchLength * sizeof(uint32_t); 1403 1404 struct BranchInfo { 1405 // Branch length as a number of 4-byte-long instructions. 1406 uint32_t length; 1407 // Ordinal number (0-based) of the first (or the only) instruction that contains the branch's 1408 // PC-relative offset (or its most significant 16-bit half, which goes first). 1409 uint32_t instr_offset; 1410 // Different MIPS instructions with PC-relative offsets apply said offsets to slightly 1411 // different origins, e.g. to PC or PC+4. Encode the origin distance (as a number of 4-byte 1412 // instructions) from the instruction containing the offset. 1413 uint32_t pc_org; 1414 // How large (in bits) a PC-relative offset can be for a given type of branch (kCondBranch is 1415 // an exception: use kOffset23 for beqzc/bnezc). 1416 OffsetBits offset_size; 1417 // Some MIPS instructions with PC-relative offsets shift the offset by 2. Encode the shift 1418 // count. 1419 int offset_shift; 1420 }; 1421 static const BranchInfo branch_info_[/* Type */]; 1422 1423 // Unconditional branch or call. 1424 Branch(uint32_t location, uint32_t target, bool is_call); 1425 // Conditional branch. 1426 Branch(uint32_t location, 1427 uint32_t target, 1428 BranchCondition condition, 1429 GpuRegister lhs_reg, 1430 GpuRegister rhs_reg); 1431 // Label address (in literal area) or literal. 1432 Branch(uint32_t location, GpuRegister dest_reg, Type label_or_literal_type); 1433 1434 // Some conditional branches with lhs = rhs are effectively NOPs, while some 1435 // others are effectively unconditional. MIPSR6 conditional branches require lhs != rhs. 1436 // So, we need a way to identify such branches in order to emit no instructions for them 1437 // or change them to unconditional. 1438 static bool IsNop(BranchCondition condition, GpuRegister lhs, GpuRegister rhs); 1439 static bool IsUncond(BranchCondition condition, GpuRegister lhs, GpuRegister rhs); 1440 1441 static BranchCondition OppositeCondition(BranchCondition cond); 1442 1443 Type GetType() const; 1444 BranchCondition GetCondition() const; 1445 GpuRegister GetLeftRegister() const; 1446 GpuRegister GetRightRegister() const; 1447 uint32_t GetTarget() const; 1448 uint32_t GetLocation() const; 1449 uint32_t GetOldLocation() const; 1450 uint32_t GetLength() const; 1451 uint32_t GetOldLength() const; 1452 uint32_t GetSize() const; 1453 uint32_t GetOldSize() const; 1454 uint32_t GetEndLocation() const; 1455 uint32_t GetOldEndLocation() const; 1456 bool IsLong() const; 1457 bool IsResolved() const; 1458 1459 // Returns the bit size of the signed offset that the branch instruction can handle. 1460 OffsetBits GetOffsetSize() const; 1461 1462 // Calculates the distance between two byte locations in the assembler buffer and 1463 // returns the number of bits needed to represent the distance as a signed integer. 1464 // 1465 // Branch instructions have signed offsets of 16, 19 (addiupc), 21 (beqzc/bnezc), 1466 // and 26 (bc) bits, which are additionally shifted left 2 positions at run time. 1467 // 1468 // Composite branches (made of several instructions) with longer reach have 32-bit 1469 // offsets encoded as 2 16-bit "halves" in two instructions (high half goes first). 1470 // The composite branches cover the range of PC + ~+/-2GB. The range is not end-to-end, 1471 // however. Consider the following implementation of a long unconditional branch, for 1472 // example: 1473 // 1474 // auipc at, offset_31_16 // at = pc + sign_extend(offset_31_16) << 16 1475 // jic at, offset_15_0 // pc = at + sign_extend(offset_15_0) 1476 // 1477 // Both of the above instructions take 16-bit signed offsets as immediate operands. 1478 // When bit 15 of offset_15_0 is 1, it effectively causes subtraction of 0x10000 1479 // due to sign extension. This must be compensated for by incrementing offset_31_16 1480 // by 1. offset_31_16 can only be incremented by 1 if it's not 0x7FFF. If it is 1481 // 0x7FFF, adding 1 will overflow the positive offset into the negative range. 1482 // Therefore, the long branch range is something like from PC - 0x80000000 to 1483 // PC + 0x7FFF7FFF, IOW, shorter by 32KB on one side. 1484 // 1485 // The returned values are therefore: 18, 21, 23, 28 and 32. There's also a special 1486 // case with the addiu instruction and a 16 bit offset. 1487 static OffsetBits GetOffsetSizeNeeded(uint32_t location, uint32_t target); 1488 1489 // Resolve a branch when the target is known. 1490 void Resolve(uint32_t target); 1491 1492 // Relocate a branch by a given delta if needed due to expansion of this or another 1493 // branch at a given location by this delta (just changes location_ and target_). 1494 void Relocate(uint32_t expand_location, uint32_t delta); 1495 1496 // If the branch is short, changes its type to long. 1497 void PromoteToLong(); 1498 1499 // If necessary, updates the type by promoting a short branch to a long branch 1500 // based on the branch location and target. Returns the amount (in bytes) by 1501 // which the branch size has increased. 1502 // max_short_distance caps the maximum distance between location_ and target_ 1503 // that is allowed for short branches. This is for debugging/testing purposes. 1504 // max_short_distance = 0 forces all short branches to become long. 1505 // Use the implicit default argument when not debugging/testing. 1506 uint32_t PromoteIfNeeded(uint32_t max_short_distance = std::numeric_limits<uint32_t>::max()); 1507 1508 // Returns the location of the instruction(s) containing the offset. 1509 uint32_t GetOffsetLocation() const; 1510 1511 // Calculates and returns the offset ready for encoding in the branch instruction(s). 1512 uint32_t GetOffset() const; 1513 1514 private: 1515 // Completes branch construction by determining and recording its type. 1516 void InitializeType(Type initial_type); 1517 // Helper for the above. 1518 void InitShortOrLong(OffsetBits ofs_size, Type short_type, Type long_type); 1519 1520 uint32_t old_location_; // Offset into assembler buffer in bytes. 1521 uint32_t location_; // Offset into assembler buffer in bytes. 1522 uint32_t target_; // Offset into assembler buffer in bytes. 1523 1524 GpuRegister lhs_reg_; // Left-hand side register in conditional branches or 1525 // destination register in literals. 1526 GpuRegister rhs_reg_; // Right-hand side register in conditional branches. 1527 BranchCondition condition_; // Condition for conditional branches. 1528 1529 Type type_; // Current type of the branch. 1530 Type old_type_; // Initial type of the branch. 1531 }; 1532 friend std::ostream& operator<<(std::ostream& os, const Branch::Type& rhs); 1533 friend std::ostream& operator<<(std::ostream& os, const Branch::OffsetBits& rhs); 1534 1535 void EmitR(int opcode, GpuRegister rs, GpuRegister rt, GpuRegister rd, int shamt, int funct); 1536 void EmitRsd(int opcode, GpuRegister rs, GpuRegister rd, int shamt, int funct); 1537 void EmitRtd(int opcode, GpuRegister rt, GpuRegister rd, int shamt, int funct); 1538 void EmitI(int opcode, GpuRegister rs, GpuRegister rt, uint16_t imm); 1539 void EmitI21(int opcode, GpuRegister rs, uint32_t imm21); 1540 void EmitI26(int opcode, uint32_t imm26); 1541 void EmitFR(int opcode, int fmt, FpuRegister ft, FpuRegister fs, FpuRegister fd, int funct); 1542 void EmitFI(int opcode, int fmt, FpuRegister rt, uint16_t imm); 1543 void EmitBcondc(BranchCondition cond, GpuRegister rs, GpuRegister rt, uint32_t imm16_21); 1544 void EmitMsa3R(int operation, 1545 int df, 1546 VectorRegister wt, 1547 VectorRegister ws, 1548 VectorRegister wd, 1549 int minor_opcode); 1550 void EmitMsaBIT(int operation, int df_m, VectorRegister ws, VectorRegister wd, int minor_opcode); 1551 void EmitMsaELM(int operation, int df_n, VectorRegister ws, VectorRegister wd, int minor_opcode); 1552 void EmitMsaMI10(int s10, GpuRegister rs, VectorRegister wd, int minor_opcode, int df); 1553 void EmitMsaI10(int operation, int df, int i10, VectorRegister wd, int minor_opcode); 1554 void EmitMsa2R(int operation, int df, VectorRegister ws, VectorRegister wd, int minor_opcode); 1555 void EmitMsa2RF(int operation, int df, VectorRegister ws, VectorRegister wd, int minor_opcode); 1556 1557 void Buncond(Mips64Label* label); 1558 void Bcond(Mips64Label* label, 1559 BranchCondition condition, 1560 GpuRegister lhs, 1561 GpuRegister rhs = ZERO); 1562 void Call(Mips64Label* label); 1563 void FinalizeLabeledBranch(Mips64Label* label); 1564 1565 Branch* GetBranch(uint32_t branch_id); 1566 const Branch* GetBranch(uint32_t branch_id) const; 1567 1568 void EmitLiterals(); 1569 void ReserveJumpTableSpace(); 1570 void EmitJumpTables(); 1571 void PromoteBranches(); 1572 void EmitBranch(Branch* branch); 1573 void EmitBranches(); 1574 void PatchCFI(); 1575 1576 // Emits exception block. 1577 void EmitExceptionPoll(Mips64ExceptionSlowPath* exception); 1578 1579 bool HasMsa() const { 1580 return has_msa_; 1581 } 1582 1583 // List of exception blocks to generate at the end of the code cache. 1584 std::vector<Mips64ExceptionSlowPath> exception_blocks_; 1585 1586 std::vector<Branch> branches_; 1587 1588 // Whether appending instructions at the end of the buffer or overwriting the existing ones. 1589 bool overwriting_; 1590 // The current overwrite location. 1591 uint32_t overwrite_location_; 1592 1593 // Use std::deque<> for literal labels to allow insertions at the end 1594 // without invalidating pointers and references to existing elements. 1595 ArenaDeque<Literal> literals_; 1596 ArenaDeque<Literal> long_literals_; // 64-bit literals separated for alignment reasons. 1597 1598 // Jump table list. 1599 ArenaDeque<JumpTable> jump_tables_; 1600 1601 // Data for AdjustedPosition(), see the description there. 1602 uint32_t last_position_adjustment_; 1603 uint32_t last_old_position_; 1604 uint32_t last_branch_id_; 1605 1606 const bool has_msa_; 1607 1608 DISALLOW_COPY_AND_ASSIGN(Mips64Assembler); 1609 }; 1610 1611 } // namespace mips64 1612 } // namespace art 1613 1614 #endif // ART_COMPILER_UTILS_MIPS64_ASSEMBLER_MIPS64_H_ 1615