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