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