1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "assembler_mips.h" 18 19 #include "base/bit_utils.h" 20 #include "base/casts.h" 21 #include "entrypoints/quick/quick_entrypoints.h" 22 #include "entrypoints/quick/quick_entrypoints_enum.h" 23 #include "memory_region.h" 24 #include "thread.h" 25 26 namespace art { 27 namespace mips { 28 29 static_assert(static_cast<size_t>(kMipsPointerSize) == kMipsWordSize, 30 "Unexpected Mips pointer size."); 31 static_assert(kMipsPointerSize == PointerSize::k32, "Unexpected Mips pointer size."); 32 33 34 std::ostream& operator<<(std::ostream& os, const DRegister& rhs) { 35 if (rhs >= D0 && rhs < kNumberOfDRegisters) { 36 os << "d" << static_cast<int>(rhs); 37 } else { 38 os << "DRegister[" << static_cast<int>(rhs) << "]"; 39 } 40 return os; 41 } 42 43 MipsAssembler::DelaySlot::DelaySlot() 44 : instruction_(0), 45 gpr_outs_mask_(0), 46 gpr_ins_mask_(0), 47 fpr_outs_mask_(0), 48 fpr_ins_mask_(0), 49 cc_outs_mask_(0), 50 cc_ins_mask_(0) {} 51 52 void MipsAssembler::DsFsmInstr(uint32_t instruction, 53 uint32_t gpr_outs_mask, 54 uint32_t gpr_ins_mask, 55 uint32_t fpr_outs_mask, 56 uint32_t fpr_ins_mask, 57 uint32_t cc_outs_mask, 58 uint32_t cc_ins_mask) { 59 if (!reordering_) { 60 CHECK_EQ(ds_fsm_state_, kExpectingLabel); 61 CHECK_EQ(delay_slot_.instruction_, 0u); 62 return; 63 } 64 switch (ds_fsm_state_) { 65 case kExpectingLabel: 66 break; 67 case kExpectingInstruction: 68 CHECK_EQ(ds_fsm_target_pc_ + sizeof(uint32_t), buffer_.Size()); 69 // If the last instruction is not suitable for delay slots, drop 70 // the PC of the label preceding it so that no unconditional branch 71 // uses this instruction to fill its delay slot. 72 if (instruction == 0) { 73 DsFsmDropLabel(); // Sets ds_fsm_state_ = kExpectingLabel. 74 } else { 75 // Otherwise wait for another instruction or label before we can 76 // commit the label PC. The label PC will be dropped if instead 77 // of another instruction or label there's a call from the code 78 // generator to CodePosition() to record the buffer size. 79 // Instructions after which the buffer size is recorded cannot 80 // be moved into delay slots or anywhere else because they may 81 // trigger signals and the signal handlers expect these signals 82 // to be coming from the instructions immediately preceding the 83 // recorded buffer locations. 84 ds_fsm_state_ = kExpectingCommit; 85 } 86 break; 87 case kExpectingCommit: 88 CHECK_EQ(ds_fsm_target_pc_ + 2 * sizeof(uint32_t), buffer_.Size()); 89 DsFsmCommitLabel(); // Sets ds_fsm_state_ = kExpectingLabel. 90 break; 91 } 92 delay_slot_.instruction_ = instruction; 93 delay_slot_.gpr_outs_mask_ = gpr_outs_mask & ~1u; // Ignore register ZERO. 94 delay_slot_.gpr_ins_mask_ = gpr_ins_mask & ~1u; // Ignore register ZERO. 95 delay_slot_.fpr_outs_mask_ = fpr_outs_mask; 96 delay_slot_.fpr_ins_mask_ = fpr_ins_mask; 97 delay_slot_.cc_outs_mask_ = cc_outs_mask; 98 delay_slot_.cc_ins_mask_ = cc_ins_mask; 99 } 100 101 void MipsAssembler::DsFsmLabel() { 102 if (!reordering_) { 103 CHECK_EQ(ds_fsm_state_, kExpectingLabel); 104 CHECK_EQ(delay_slot_.instruction_, 0u); 105 return; 106 } 107 switch (ds_fsm_state_) { 108 case kExpectingLabel: 109 ds_fsm_target_pc_ = buffer_.Size(); 110 ds_fsm_state_ = kExpectingInstruction; 111 break; 112 case kExpectingInstruction: 113 // Allow consecutive labels. 114 CHECK_EQ(ds_fsm_target_pc_, buffer_.Size()); 115 break; 116 case kExpectingCommit: 117 CHECK_EQ(ds_fsm_target_pc_ + sizeof(uint32_t), buffer_.Size()); 118 DsFsmCommitLabel(); 119 ds_fsm_target_pc_ = buffer_.Size(); 120 ds_fsm_state_ = kExpectingInstruction; 121 break; 122 } 123 // We cannot move instructions into delay slots across labels. 124 delay_slot_.instruction_ = 0; 125 } 126 127 void MipsAssembler::DsFsmCommitLabel() { 128 if (ds_fsm_state_ == kExpectingCommit) { 129 ds_fsm_target_pcs_.emplace_back(ds_fsm_target_pc_); 130 } 131 ds_fsm_state_ = kExpectingLabel; 132 } 133 134 void MipsAssembler::DsFsmDropLabel() { 135 ds_fsm_state_ = kExpectingLabel; 136 } 137 138 bool MipsAssembler::SetReorder(bool enable) { 139 bool last_state = reordering_; 140 if (last_state != enable) { 141 DsFsmCommitLabel(); 142 DsFsmInstrNop(0); 143 } 144 reordering_ = enable; 145 return last_state; 146 } 147 148 size_t MipsAssembler::CodePosition() { 149 // The last instruction cannot be used in a delay slot, do not commit 150 // the label before it (if any) and clear the delay slot. 151 DsFsmDropLabel(); 152 DsFsmInstrNop(0); 153 size_t size = buffer_.Size(); 154 // In theory we can get the following sequence: 155 // label1: 156 // instr 157 // label2: # label1 gets committed when label2 is seen 158 // CodePosition() call 159 // and we need to uncommit label1. 160 if (ds_fsm_target_pcs_.size() != 0 && ds_fsm_target_pcs_.back() + sizeof(uint32_t) == size) { 161 ds_fsm_target_pcs_.pop_back(); 162 } 163 return size; 164 } 165 166 void MipsAssembler::DsFsmInstrNop(uint32_t instruction ATTRIBUTE_UNUSED) { 167 DsFsmInstr(0, 0, 0, 0, 0, 0, 0); 168 } 169 170 void MipsAssembler::DsFsmInstrRrr(uint32_t instruction, Register out, Register in1, Register in2) { 171 DsFsmInstr(instruction, (1u << out), (1u << in1) | (1u << in2), 0, 0, 0, 0); 172 } 173 174 void MipsAssembler::DsFsmInstrRrrr(uint32_t instruction, 175 Register in1_out, 176 Register in2, 177 Register in3) { 178 DsFsmInstr(instruction, (1u << in1_out), (1u << in1_out) | (1u << in2) | (1u << in3), 0, 0, 0, 0); 179 } 180 181 void MipsAssembler::DsFsmInstrFff(uint32_t instruction, 182 FRegister out, 183 FRegister in1, 184 FRegister in2) { 185 DsFsmInstr(instruction, 0, 0, (1u << out), (1u << in1) | (1u << in2), 0, 0); 186 } 187 188 void MipsAssembler::DsFsmInstrFfff(uint32_t instruction, 189 FRegister in1_out, 190 FRegister in2, 191 FRegister in3) { 192 DsFsmInstr(instruction, 0, 0, (1u << in1_out), (1u << in1_out) | (1u << in2) | (1u << in3), 0, 0); 193 } 194 195 void MipsAssembler::DsFsmInstrFffr(uint32_t instruction, 196 FRegister in1_out, 197 FRegister in2, 198 Register in3) { 199 DsFsmInstr(instruction, 0, (1u << in3), (1u << in1_out), (1u << in1_out) | (1u << in2), 0, 0); 200 } 201 202 void MipsAssembler::DsFsmInstrRf(uint32_t instruction, Register out, FRegister in) { 203 DsFsmInstr(instruction, (1u << out), 0, 0, (1u << in), 0, 0); 204 } 205 206 void MipsAssembler::DsFsmInstrFr(uint32_t instruction, FRegister out, Register in) { 207 DsFsmInstr(instruction, 0, (1u << in), (1u << out), 0, 0, 0); 208 } 209 210 void MipsAssembler::DsFsmInstrFR(uint32_t instruction, FRegister in1, Register in2) { 211 DsFsmInstr(instruction, 0, (1u << in2), 0, (1u << in1), 0, 0); 212 } 213 214 void MipsAssembler::DsFsmInstrCff(uint32_t instruction, int cc_out, FRegister in1, FRegister in2) { 215 DsFsmInstr(instruction, 0, 0, 0, (1u << in1) | (1u << in2), (1 << cc_out), 0); 216 } 217 218 void MipsAssembler::DsFsmInstrRrrc(uint32_t instruction, 219 Register in1_out, 220 Register in2, 221 int cc_in) { 222 DsFsmInstr(instruction, (1u << in1_out), (1u << in1_out) | (1u << in2), 0, 0, 0, (1 << cc_in)); 223 } 224 225 void MipsAssembler::DsFsmInstrFffc(uint32_t instruction, 226 FRegister in1_out, 227 FRegister in2, 228 int cc_in) { 229 DsFsmInstr(instruction, 0, 0, (1u << in1_out), (1u << in1_out) | (1u << in2), 0, (1 << cc_in)); 230 } 231 232 void MipsAssembler::FinalizeCode() { 233 for (auto& exception_block : exception_blocks_) { 234 EmitExceptionPoll(&exception_block); 235 } 236 // Commit the last branch target label (if any) and disable instruction reordering. 237 DsFsmCommitLabel(); 238 SetReorder(false); 239 EmitLiterals(); 240 ReserveJumpTableSpace(); 241 PromoteBranches(); 242 } 243 244 void MipsAssembler::FinalizeInstructions(const MemoryRegion& region) { 245 size_t number_of_delayed_adjust_pcs = cfi().NumberOfDelayedAdvancePCs(); 246 EmitBranches(); 247 EmitJumpTables(); 248 Assembler::FinalizeInstructions(region); 249 PatchCFI(number_of_delayed_adjust_pcs); 250 } 251 252 void MipsAssembler::PatchCFI(size_t number_of_delayed_adjust_pcs) { 253 if (cfi().NumberOfDelayedAdvancePCs() == 0u) { 254 DCHECK_EQ(number_of_delayed_adjust_pcs, 0u); 255 return; 256 } 257 258 typedef DebugFrameOpCodeWriterForAssembler::DelayedAdvancePC DelayedAdvancePC; 259 const auto data = cfi().ReleaseStreamAndPrepareForDelayedAdvancePC(); 260 const std::vector<uint8_t>& old_stream = data.first; 261 const std::vector<DelayedAdvancePC>& advances = data.second; 262 263 // PCs recorded before EmitBranches() need to be adjusted. 264 // PCs recorded during EmitBranches() are already adjusted. 265 // Both ranges are separately sorted but they may overlap. 266 if (kIsDebugBuild) { 267 auto cmp = [](const DelayedAdvancePC& lhs, const DelayedAdvancePC& rhs) { 268 return lhs.pc < rhs.pc; 269 }; 270 CHECK(std::is_sorted(advances.begin(), advances.begin() + number_of_delayed_adjust_pcs, cmp)); 271 CHECK(std::is_sorted(advances.begin() + number_of_delayed_adjust_pcs, advances.end(), cmp)); 272 } 273 274 // Append initial CFI data if any. 275 size_t size = advances.size(); 276 DCHECK_NE(size, 0u); 277 cfi().AppendRawData(old_stream, 0u, advances[0].stream_pos); 278 // Emit PC adjustments interleaved with the old CFI stream. 279 size_t adjust_pos = 0u; 280 size_t late_emit_pos = number_of_delayed_adjust_pcs; 281 while (adjust_pos != number_of_delayed_adjust_pcs || late_emit_pos != size) { 282 size_t adjusted_pc = (adjust_pos != number_of_delayed_adjust_pcs) 283 ? GetAdjustedPosition(advances[adjust_pos].pc) 284 : static_cast<size_t>(-1); 285 size_t late_emit_pc = (late_emit_pos != size) 286 ? advances[late_emit_pos].pc 287 : static_cast<size_t>(-1); 288 size_t advance_pc = std::min(adjusted_pc, late_emit_pc); 289 DCHECK_NE(advance_pc, static_cast<size_t>(-1)); 290 size_t entry = (adjusted_pc <= late_emit_pc) ? adjust_pos : late_emit_pos; 291 if (adjusted_pc <= late_emit_pc) { 292 ++adjust_pos; 293 } else { 294 ++late_emit_pos; 295 } 296 cfi().AdvancePC(advance_pc); 297 size_t end_pos = (entry + 1u == size) ? old_stream.size() : advances[entry + 1u].stream_pos; 298 cfi().AppendRawData(old_stream, advances[entry].stream_pos, end_pos); 299 } 300 } 301 302 void MipsAssembler::EmitBranches() { 303 CHECK(!overwriting_); 304 CHECK(!reordering_); 305 // Now that everything has its final position in the buffer (the branches have 306 // been promoted), adjust the target label PCs. 307 for (size_t cnt = ds_fsm_target_pcs_.size(), i = 0; i < cnt; i++) { 308 ds_fsm_target_pcs_[i] = GetAdjustedPosition(ds_fsm_target_pcs_[i]); 309 } 310 // Switch from appending instructions at the end of the buffer to overwriting 311 // existing instructions (branch placeholders) in the buffer. 312 overwriting_ = true; 313 for (auto& branch : branches_) { 314 EmitBranch(&branch); 315 } 316 overwriting_ = false; 317 } 318 319 void MipsAssembler::Emit(uint32_t value) { 320 if (overwriting_) { 321 // Branches to labels are emitted into their placeholders here. 322 buffer_.Store<uint32_t>(overwrite_location_, value); 323 overwrite_location_ += sizeof(uint32_t); 324 } else { 325 // Other instructions are simply appended at the end here. 326 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 327 buffer_.Emit<uint32_t>(value); 328 } 329 } 330 331 uint32_t MipsAssembler::EmitR(int opcode, 332 Register rs, 333 Register rt, 334 Register rd, 335 int shamt, 336 int funct) { 337 CHECK_NE(rs, kNoRegister); 338 CHECK_NE(rt, kNoRegister); 339 CHECK_NE(rd, kNoRegister); 340 uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift | 341 static_cast<uint32_t>(rs) << kRsShift | 342 static_cast<uint32_t>(rt) << kRtShift | 343 static_cast<uint32_t>(rd) << kRdShift | 344 shamt << kShamtShift | 345 funct; 346 Emit(encoding); 347 return encoding; 348 } 349 350 uint32_t MipsAssembler::EmitI(int opcode, Register rs, Register rt, uint16_t imm) { 351 CHECK_NE(rs, kNoRegister); 352 CHECK_NE(rt, kNoRegister); 353 uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift | 354 static_cast<uint32_t>(rs) << kRsShift | 355 static_cast<uint32_t>(rt) << kRtShift | 356 imm; 357 Emit(encoding); 358 return encoding; 359 } 360 361 uint32_t MipsAssembler::EmitI21(int opcode, Register rs, uint32_t imm21) { 362 CHECK_NE(rs, kNoRegister); 363 CHECK(IsUint<21>(imm21)) << imm21; 364 uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift | 365 static_cast<uint32_t>(rs) << kRsShift | 366 imm21; 367 Emit(encoding); 368 return encoding; 369 } 370 371 uint32_t MipsAssembler::EmitI26(int opcode, uint32_t imm26) { 372 CHECK(IsUint<26>(imm26)) << imm26; 373 uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift | imm26; 374 Emit(encoding); 375 return encoding; 376 } 377 378 uint32_t MipsAssembler::EmitFR(int opcode, 379 int fmt, 380 FRegister ft, 381 FRegister fs, 382 FRegister fd, 383 int funct) { 384 CHECK_NE(ft, kNoFRegister); 385 CHECK_NE(fs, kNoFRegister); 386 CHECK_NE(fd, kNoFRegister); 387 uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift | 388 fmt << kFmtShift | 389 static_cast<uint32_t>(ft) << kFtShift | 390 static_cast<uint32_t>(fs) << kFsShift | 391 static_cast<uint32_t>(fd) << kFdShift | 392 funct; 393 Emit(encoding); 394 return encoding; 395 } 396 397 uint32_t MipsAssembler::EmitFI(int opcode, int fmt, FRegister ft, uint16_t imm) { 398 CHECK_NE(ft, kNoFRegister); 399 uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift | 400 fmt << kFmtShift | 401 static_cast<uint32_t>(ft) << kFtShift | 402 imm; 403 Emit(encoding); 404 return encoding; 405 } 406 407 uint32_t MipsAssembler::EmitMsa3R(int operation, 408 int df, 409 VectorRegister wt, 410 VectorRegister ws, 411 VectorRegister wd, 412 int minor_opcode) { 413 CHECK_NE(wt, kNoVectorRegister); 414 CHECK_NE(ws, kNoVectorRegister); 415 CHECK_NE(wd, kNoVectorRegister); 416 uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift | 417 operation << kMsaOperationShift | 418 df << kDfShift | 419 static_cast<uint32_t>(wt) << kWtShift | 420 static_cast<uint32_t>(ws) << kWsShift | 421 static_cast<uint32_t>(wd) << kWdShift | 422 minor_opcode; 423 Emit(encoding); 424 return encoding; 425 } 426 427 uint32_t MipsAssembler::EmitMsaBIT(int operation, 428 int df_m, 429 VectorRegister ws, 430 VectorRegister wd, 431 int minor_opcode) { 432 CHECK_NE(ws, kNoVectorRegister); 433 CHECK_NE(wd, kNoVectorRegister); 434 uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift | 435 operation << kMsaOperationShift | 436 df_m << kDfMShift | 437 static_cast<uint32_t>(ws) << kWsShift | 438 static_cast<uint32_t>(wd) << kWdShift | 439 minor_opcode; 440 Emit(encoding); 441 return encoding; 442 } 443 444 uint32_t MipsAssembler::EmitMsaELM(int operation, 445 int df_n, 446 VectorRegister ws, 447 VectorRegister wd, 448 int minor_opcode) { 449 CHECK_NE(ws, kNoVectorRegister); 450 CHECK_NE(wd, kNoVectorRegister); 451 uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift | 452 operation << kMsaELMOperationShift | 453 df_n << kDfNShift | 454 static_cast<uint32_t>(ws) << kWsShift | 455 static_cast<uint32_t>(wd) << kWdShift | 456 minor_opcode; 457 Emit(encoding); 458 return encoding; 459 } 460 461 uint32_t MipsAssembler::EmitMsaMI10(int s10, 462 Register rs, 463 VectorRegister wd, 464 int minor_opcode, 465 int df) { 466 CHECK_NE(rs, kNoRegister); 467 CHECK_NE(wd, kNoVectorRegister); 468 CHECK(IsUint<10>(s10)) << s10; 469 uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift | 470 s10 << kS10Shift | 471 static_cast<uint32_t>(rs) << kWsShift | 472 static_cast<uint32_t>(wd) << kWdShift | 473 minor_opcode << kS10MinorShift | 474 df; 475 Emit(encoding); 476 return encoding; 477 } 478 479 uint32_t MipsAssembler::EmitMsaI10(int operation, 480 int df, 481 int i10, 482 VectorRegister wd, 483 int minor_opcode) { 484 CHECK_NE(wd, kNoVectorRegister); 485 CHECK(IsUint<10>(i10)) << i10; 486 uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift | 487 operation << kMsaOperationShift | 488 df << kDfShift | 489 i10 << kI10Shift | 490 static_cast<uint32_t>(wd) << kWdShift | 491 minor_opcode; 492 Emit(encoding); 493 return encoding; 494 } 495 496 uint32_t MipsAssembler::EmitMsa2R(int operation, 497 int df, 498 VectorRegister ws, 499 VectorRegister wd, 500 int minor_opcode) { 501 CHECK_NE(ws, kNoVectorRegister); 502 CHECK_NE(wd, kNoVectorRegister); 503 uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift | 504 operation << kMsa2ROperationShift | 505 df << kDf2RShift | 506 static_cast<uint32_t>(ws) << kWsShift | 507 static_cast<uint32_t>(wd) << kWdShift | 508 minor_opcode; 509 Emit(encoding); 510 return encoding; 511 } 512 513 uint32_t MipsAssembler::EmitMsa2RF(int operation, 514 int df, 515 VectorRegister ws, 516 VectorRegister wd, 517 int minor_opcode) { 518 CHECK_NE(ws, kNoVectorRegister); 519 CHECK_NE(wd, kNoVectorRegister); 520 uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift | 521 operation << kMsa2RFOperationShift | 522 df << kDf2RShift | 523 static_cast<uint32_t>(ws) << kWsShift | 524 static_cast<uint32_t>(wd) << kWdShift | 525 minor_opcode; 526 Emit(encoding); 527 return encoding; 528 } 529 530 void MipsAssembler::Addu(Register rd, Register rs, Register rt) { 531 DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x21), rd, rs, rt); 532 } 533 534 void MipsAssembler::Addiu(Register rt, Register rs, uint16_t imm16) { 535 DsFsmInstrRrr(EmitI(0x9, rs, rt, imm16), rt, rs, rs); 536 } 537 538 void MipsAssembler::Subu(Register rd, Register rs, Register rt) { 539 DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x23), rd, rs, rt); 540 } 541 542 void MipsAssembler::MultR2(Register rs, Register rt) { 543 CHECK(!IsR6()); 544 DsFsmInstrRrr(EmitR(0, rs, rt, static_cast<Register>(0), 0, 0x18), ZERO, rs, rt); 545 } 546 547 void MipsAssembler::MultuR2(Register rs, Register rt) { 548 CHECK(!IsR6()); 549 DsFsmInstrRrr(EmitR(0, rs, rt, static_cast<Register>(0), 0, 0x19), ZERO, rs, rt); 550 } 551 552 void MipsAssembler::DivR2(Register rs, Register rt) { 553 CHECK(!IsR6()); 554 DsFsmInstrRrr(EmitR(0, rs, rt, static_cast<Register>(0), 0, 0x1a), ZERO, rs, rt); 555 } 556 557 void MipsAssembler::DivuR2(Register rs, Register rt) { 558 CHECK(!IsR6()); 559 DsFsmInstrRrr(EmitR(0, rs, rt, static_cast<Register>(0), 0, 0x1b), ZERO, rs, rt); 560 } 561 562 void MipsAssembler::MulR2(Register rd, Register rs, Register rt) { 563 CHECK(!IsR6()); 564 DsFsmInstrRrr(EmitR(0x1c, rs, rt, rd, 0, 2), rd, rs, rt); 565 } 566 567 void MipsAssembler::DivR2(Register rd, Register rs, Register rt) { 568 CHECK(!IsR6()); 569 DivR2(rs, rt); 570 Mflo(rd); 571 } 572 573 void MipsAssembler::ModR2(Register rd, Register rs, Register rt) { 574 CHECK(!IsR6()); 575 DivR2(rs, rt); 576 Mfhi(rd); 577 } 578 579 void MipsAssembler::DivuR2(Register rd, Register rs, Register rt) { 580 CHECK(!IsR6()); 581 DivuR2(rs, rt); 582 Mflo(rd); 583 } 584 585 void MipsAssembler::ModuR2(Register rd, Register rs, Register rt) { 586 CHECK(!IsR6()); 587 DivuR2(rs, rt); 588 Mfhi(rd); 589 } 590 591 void MipsAssembler::MulR6(Register rd, Register rs, Register rt) { 592 CHECK(IsR6()); 593 DsFsmInstrRrr(EmitR(0, rs, rt, rd, 2, 0x18), rd, rs, rt); 594 } 595 596 void MipsAssembler::MuhR6(Register rd, Register rs, Register rt) { 597 CHECK(IsR6()); 598 DsFsmInstrRrr(EmitR(0, rs, rt, rd, 3, 0x18), rd, rs, rt); 599 } 600 601 void MipsAssembler::MuhuR6(Register rd, Register rs, Register rt) { 602 CHECK(IsR6()); 603 DsFsmInstrRrr(EmitR(0, rs, rt, rd, 3, 0x19), rd, rs, rt); 604 } 605 606 void MipsAssembler::DivR6(Register rd, Register rs, Register rt) { 607 CHECK(IsR6()); 608 DsFsmInstrRrr(EmitR(0, rs, rt, rd, 2, 0x1a), rd, rs, rt); 609 } 610 611 void MipsAssembler::ModR6(Register rd, Register rs, Register rt) { 612 CHECK(IsR6()); 613 DsFsmInstrRrr(EmitR(0, rs, rt, rd, 3, 0x1a), rd, rs, rt); 614 } 615 616 void MipsAssembler::DivuR6(Register rd, Register rs, Register rt) { 617 CHECK(IsR6()); 618 DsFsmInstrRrr(EmitR(0, rs, rt, rd, 2, 0x1b), rd, rs, rt); 619 } 620 621 void MipsAssembler::ModuR6(Register rd, Register rs, Register rt) { 622 CHECK(IsR6()); 623 DsFsmInstrRrr(EmitR(0, rs, rt, rd, 3, 0x1b), rd, rs, rt); 624 } 625 626 void MipsAssembler::And(Register rd, Register rs, Register rt) { 627 DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x24), rd, rs, rt); 628 } 629 630 void MipsAssembler::Andi(Register rt, Register rs, uint16_t imm16) { 631 DsFsmInstrRrr(EmitI(0xc, rs, rt, imm16), rt, rs, rs); 632 } 633 634 void MipsAssembler::Or(Register rd, Register rs, Register rt) { 635 DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x25), rd, rs, rt); 636 } 637 638 void MipsAssembler::Ori(Register rt, Register rs, uint16_t imm16) { 639 DsFsmInstrRrr(EmitI(0xd, rs, rt, imm16), rt, rs, rs); 640 } 641 642 void MipsAssembler::Xor(Register rd, Register rs, Register rt) { 643 DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x26), rd, rs, rt); 644 } 645 646 void MipsAssembler::Xori(Register rt, Register rs, uint16_t imm16) { 647 DsFsmInstrRrr(EmitI(0xe, rs, rt, imm16), rt, rs, rs); 648 } 649 650 void MipsAssembler::Nor(Register rd, Register rs, Register rt) { 651 DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x27), rd, rs, rt); 652 } 653 654 void MipsAssembler::Movz(Register rd, Register rs, Register rt) { 655 CHECK(!IsR6()); 656 DsFsmInstrRrrr(EmitR(0, rs, rt, rd, 0, 0x0A), rd, rs, rt); 657 } 658 659 void MipsAssembler::Movn(Register rd, Register rs, Register rt) { 660 CHECK(!IsR6()); 661 DsFsmInstrRrrr(EmitR(0, rs, rt, rd, 0, 0x0B), rd, rs, rt); 662 } 663 664 void MipsAssembler::Seleqz(Register rd, Register rs, Register rt) { 665 CHECK(IsR6()); 666 DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x35), rd, rs, rt); 667 } 668 669 void MipsAssembler::Selnez(Register rd, Register rs, Register rt) { 670 CHECK(IsR6()); 671 DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x37), rd, rs, rt); 672 } 673 674 void MipsAssembler::ClzR6(Register rd, Register rs) { 675 CHECK(IsR6()); 676 DsFsmInstrRrr(EmitR(0, rs, static_cast<Register>(0), rd, 0x01, 0x10), rd, rs, rs); 677 } 678 679 void MipsAssembler::ClzR2(Register rd, Register rs) { 680 CHECK(!IsR6()); 681 DsFsmInstrRrr(EmitR(0x1C, rs, rd, rd, 0, 0x20), rd, rs, rs); 682 } 683 684 void MipsAssembler::CloR6(Register rd, Register rs) { 685 CHECK(IsR6()); 686 DsFsmInstrRrr(EmitR(0, rs, static_cast<Register>(0), rd, 0x01, 0x11), rd, rs, rs); 687 } 688 689 void MipsAssembler::CloR2(Register rd, Register rs) { 690 CHECK(!IsR6()); 691 DsFsmInstrRrr(EmitR(0x1C, rs, rd, rd, 0, 0x21), rd, rs, rs); 692 } 693 694 void MipsAssembler::Seb(Register rd, Register rt) { 695 DsFsmInstrRrr(EmitR(0x1f, static_cast<Register>(0), rt, rd, 0x10, 0x20), rd, rt, rt); 696 } 697 698 void MipsAssembler::Seh(Register rd, Register rt) { 699 DsFsmInstrRrr(EmitR(0x1f, static_cast<Register>(0), rt, rd, 0x18, 0x20), rd, rt, rt); 700 } 701 702 void MipsAssembler::Wsbh(Register rd, Register rt) { 703 DsFsmInstrRrr(EmitR(0x1f, static_cast<Register>(0), rt, rd, 2, 0x20), rd, rt, rt); 704 } 705 706 void MipsAssembler::Bitswap(Register rd, Register rt) { 707 CHECK(IsR6()); 708 DsFsmInstrRrr(EmitR(0x1f, static_cast<Register>(0), rt, rd, 0x0, 0x20), rd, rt, rt); 709 } 710 711 void MipsAssembler::Sll(Register rd, Register rt, int shamt) { 712 CHECK(IsUint<5>(shamt)) << shamt; 713 DsFsmInstrRrr(EmitR(0, static_cast<Register>(0), rt, rd, shamt, 0x00), rd, rt, rt); 714 } 715 716 void MipsAssembler::Srl(Register rd, Register rt, int shamt) { 717 CHECK(IsUint<5>(shamt)) << shamt; 718 DsFsmInstrRrr(EmitR(0, static_cast<Register>(0), rt, rd, shamt, 0x02), rd, rt, rt); 719 } 720 721 void MipsAssembler::Rotr(Register rd, Register rt, int shamt) { 722 CHECK(IsUint<5>(shamt)) << shamt; 723 DsFsmInstrRrr(EmitR(0, static_cast<Register>(1), rt, rd, shamt, 0x02), rd, rt, rt); 724 } 725 726 void MipsAssembler::Sra(Register rd, Register rt, int shamt) { 727 CHECK(IsUint<5>(shamt)) << shamt; 728 DsFsmInstrRrr(EmitR(0, static_cast<Register>(0), rt, rd, shamt, 0x03), rd, rt, rt); 729 } 730 731 void MipsAssembler::Sllv(Register rd, Register rt, Register rs) { 732 DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x04), rd, rs, rt); 733 } 734 735 void MipsAssembler::Srlv(Register rd, Register rt, Register rs) { 736 DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x06), rd, rs, rt); 737 } 738 739 void MipsAssembler::Rotrv(Register rd, Register rt, Register rs) { 740 DsFsmInstrRrr(EmitR(0, rs, rt, rd, 1, 0x06), rd, rs, rt); 741 } 742 743 void MipsAssembler::Srav(Register rd, Register rt, Register rs) { 744 DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x07), rd, rs, rt); 745 } 746 747 void MipsAssembler::Ext(Register rd, Register rt, int pos, int size) { 748 CHECK(IsUint<5>(pos)) << pos; 749 CHECK(0 < size && size <= 32) << size; 750 CHECK(0 < pos + size && pos + size <= 32) << pos << " + " << size; 751 DsFsmInstrRrr(EmitR(0x1f, rt, rd, static_cast<Register>(size - 1), pos, 0x00), rd, rt, rt); 752 } 753 754 void MipsAssembler::Ins(Register rd, Register rt, int pos, int size) { 755 CHECK(IsUint<5>(pos)) << pos; 756 CHECK(0 < size && size <= 32) << size; 757 CHECK(0 < pos + size && pos + size <= 32) << pos << " + " << size; 758 DsFsmInstrRrr(EmitR(0x1f, rt, rd, static_cast<Register>(pos + size - 1), pos, 0x04), rd, rd, rt); 759 } 760 761 void MipsAssembler::Lsa(Register rd, Register rs, Register rt, int saPlusOne) { 762 CHECK(IsR6() || HasMsa()); 763 CHECK(1 <= saPlusOne && saPlusOne <= 4) << saPlusOne; 764 int sa = saPlusOne - 1; 765 DsFsmInstrRrr(EmitR(0x0, rs, rt, rd, sa, 0x05), rd, rs, rt); 766 } 767 768 void MipsAssembler::ShiftAndAdd(Register dst, 769 Register src_idx, 770 Register src_base, 771 int shamt, 772 Register tmp) { 773 CHECK(0 <= shamt && shamt <= 4) << shamt; 774 CHECK_NE(src_base, tmp); 775 if (shamt == TIMES_1) { 776 // Catch the special case where the shift amount is zero (0). 777 Addu(dst, src_base, src_idx); 778 } else if (IsR6() || HasMsa()) { 779 Lsa(dst, src_idx, src_base, shamt); 780 } else { 781 Sll(tmp, src_idx, shamt); 782 Addu(dst, src_base, tmp); 783 } 784 } 785 786 void MipsAssembler::Lb(Register rt, Register rs, uint16_t imm16) { 787 DsFsmInstrRrr(EmitI(0x20, rs, rt, imm16), rt, rs, rs); 788 } 789 790 void MipsAssembler::Lh(Register rt, Register rs, uint16_t imm16) { 791 DsFsmInstrRrr(EmitI(0x21, rs, rt, imm16), rt, rs, rs); 792 } 793 794 void MipsAssembler::Lw(Register rt, Register rs, uint16_t imm16) { 795 DsFsmInstrRrr(EmitI(0x23, rs, rt, imm16), rt, rs, rs); 796 } 797 798 void MipsAssembler::Lwl(Register rt, Register rs, uint16_t imm16) { 799 CHECK(!IsR6()); 800 DsFsmInstrRrr(EmitI(0x22, rs, rt, imm16), rt, rt, rs); 801 } 802 803 void MipsAssembler::Lwr(Register rt, Register rs, uint16_t imm16) { 804 CHECK(!IsR6()); 805 DsFsmInstrRrr(EmitI(0x26, rs, rt, imm16), rt, rt, rs); 806 } 807 808 void MipsAssembler::Lbu(Register rt, Register rs, uint16_t imm16) { 809 DsFsmInstrRrr(EmitI(0x24, rs, rt, imm16), rt, rs, rs); 810 } 811 812 void MipsAssembler::Lhu(Register rt, Register rs, uint16_t imm16) { 813 DsFsmInstrRrr(EmitI(0x25, rs, rt, imm16), rt, rs, rs); 814 } 815 816 void MipsAssembler::Lwpc(Register rs, uint32_t imm19) { 817 CHECK(IsR6()); 818 CHECK(IsUint<19>(imm19)) << imm19; 819 DsFsmInstrNop(EmitI21(0x3B, rs, (0x01 << 19) | imm19)); 820 } 821 822 void MipsAssembler::Lui(Register rt, uint16_t imm16) { 823 DsFsmInstrRrr(EmitI(0xf, static_cast<Register>(0), rt, imm16), rt, ZERO, ZERO); 824 } 825 826 void MipsAssembler::Aui(Register rt, Register rs, uint16_t imm16) { 827 CHECK(IsR6()); 828 DsFsmInstrRrr(EmitI(0xf, rs, rt, imm16), rt, rt, rs); 829 } 830 831 void MipsAssembler::Sync(uint32_t stype) { 832 DsFsmInstrNop(EmitR(0, ZERO, ZERO, ZERO, stype & 0x1f, 0xf)); 833 } 834 835 void MipsAssembler::Mfhi(Register rd) { 836 CHECK(!IsR6()); 837 DsFsmInstrRrr(EmitR(0, ZERO, ZERO, rd, 0, 0x10), rd, ZERO, ZERO); 838 } 839 840 void MipsAssembler::Mflo(Register rd) { 841 CHECK(!IsR6()); 842 DsFsmInstrRrr(EmitR(0, ZERO, ZERO, rd, 0, 0x12), rd, ZERO, ZERO); 843 } 844 845 void MipsAssembler::Sb(Register rt, Register rs, uint16_t imm16) { 846 DsFsmInstrRrr(EmitI(0x28, rs, rt, imm16), ZERO, rt, rs); 847 } 848 849 void MipsAssembler::Sh(Register rt, Register rs, uint16_t imm16) { 850 DsFsmInstrRrr(EmitI(0x29, rs, rt, imm16), ZERO, rt, rs); 851 } 852 853 void MipsAssembler::Sw(Register rt, Register rs, uint16_t imm16) { 854 DsFsmInstrRrr(EmitI(0x2b, rs, rt, imm16), ZERO, rt, rs); 855 } 856 857 void MipsAssembler::Swl(Register rt, Register rs, uint16_t imm16) { 858 CHECK(!IsR6()); 859 DsFsmInstrRrr(EmitI(0x2a, rs, rt, imm16), ZERO, rt, rs); 860 } 861 862 void MipsAssembler::Swr(Register rt, Register rs, uint16_t imm16) { 863 CHECK(!IsR6()); 864 DsFsmInstrRrr(EmitI(0x2e, rs, rt, imm16), ZERO, rt, rs); 865 } 866 867 void MipsAssembler::LlR2(Register rt, Register base, int16_t imm16) { 868 CHECK(!IsR6()); 869 DsFsmInstrRrr(EmitI(0x30, base, rt, imm16), rt, base, base); 870 } 871 872 void MipsAssembler::ScR2(Register rt, Register base, int16_t imm16) { 873 CHECK(!IsR6()); 874 DsFsmInstrRrr(EmitI(0x38, base, rt, imm16), rt, rt, base); 875 } 876 877 void MipsAssembler::LlR6(Register rt, Register base, int16_t imm9) { 878 CHECK(IsR6()); 879 CHECK(IsInt<9>(imm9)); 880 DsFsmInstrRrr(EmitI(0x1f, base, rt, ((imm9 & 0x1ff) << 7) | 0x36), rt, base, base); 881 } 882 883 void MipsAssembler::ScR6(Register rt, Register base, int16_t imm9) { 884 CHECK(IsR6()); 885 CHECK(IsInt<9>(imm9)); 886 DsFsmInstrRrr(EmitI(0x1f, base, rt, ((imm9 & 0x1ff) << 7) | 0x26), rt, rt, base); 887 } 888 889 void MipsAssembler::Slt(Register rd, Register rs, Register rt) { 890 DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x2a), rd, rs, rt); 891 } 892 893 void MipsAssembler::Sltu(Register rd, Register rs, Register rt) { 894 DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x2b), rd, rs, rt); 895 } 896 897 void MipsAssembler::Slti(Register rt, Register rs, uint16_t imm16) { 898 DsFsmInstrRrr(EmitI(0xa, rs, rt, imm16), rt, rs, rs); 899 } 900 901 void MipsAssembler::Sltiu(Register rt, Register rs, uint16_t imm16) { 902 DsFsmInstrRrr(EmitI(0xb, rs, rt, imm16), rt, rs, rs); 903 } 904 905 void MipsAssembler::B(uint16_t imm16) { 906 DsFsmInstrNop(EmitI(0x4, static_cast<Register>(0), static_cast<Register>(0), imm16)); 907 } 908 909 void MipsAssembler::Bal(uint16_t imm16) { 910 DsFsmInstrNop(EmitI(0x1, static_cast<Register>(0), static_cast<Register>(0x11), imm16)); 911 } 912 913 void MipsAssembler::Beq(Register rs, Register rt, uint16_t imm16) { 914 DsFsmInstrNop(EmitI(0x4, rs, rt, imm16)); 915 } 916 917 void MipsAssembler::Bne(Register rs, Register rt, uint16_t imm16) { 918 DsFsmInstrNop(EmitI(0x5, rs, rt, imm16)); 919 } 920 921 void MipsAssembler::Beqz(Register rt, uint16_t imm16) { 922 Beq(ZERO, rt, imm16); 923 } 924 925 void MipsAssembler::Bnez(Register rt, uint16_t imm16) { 926 Bne(ZERO, rt, imm16); 927 } 928 929 void MipsAssembler::Bltz(Register rt, uint16_t imm16) { 930 DsFsmInstrNop(EmitI(0x1, rt, static_cast<Register>(0), imm16)); 931 } 932 933 void MipsAssembler::Bgez(Register rt, uint16_t imm16) { 934 DsFsmInstrNop(EmitI(0x1, rt, static_cast<Register>(0x1), imm16)); 935 } 936 937 void MipsAssembler::Blez(Register rt, uint16_t imm16) { 938 DsFsmInstrNop(EmitI(0x6, rt, static_cast<Register>(0), imm16)); 939 } 940 941 void MipsAssembler::Bgtz(Register rt, uint16_t imm16) { 942 DsFsmInstrNop(EmitI(0x7, rt, static_cast<Register>(0), imm16)); 943 } 944 945 void MipsAssembler::Bc1f(uint16_t imm16) { 946 Bc1f(0, imm16); 947 } 948 949 void MipsAssembler::Bc1f(int cc, uint16_t imm16) { 950 CHECK(!IsR6()); 951 CHECK(IsUint<3>(cc)) << cc; 952 DsFsmInstrNop(EmitI(0x11, static_cast<Register>(0x8), static_cast<Register>(cc << 2), imm16)); 953 } 954 955 void MipsAssembler::Bc1t(uint16_t imm16) { 956 Bc1t(0, imm16); 957 } 958 959 void MipsAssembler::Bc1t(int cc, uint16_t imm16) { 960 CHECK(!IsR6()); 961 CHECK(IsUint<3>(cc)) << cc; 962 DsFsmInstrNop(EmitI(0x11, 963 static_cast<Register>(0x8), 964 static_cast<Register>((cc << 2) | 1), 965 imm16)); 966 } 967 968 void MipsAssembler::J(uint32_t addr26) { 969 DsFsmInstrNop(EmitI26(0x2, addr26)); 970 } 971 972 void MipsAssembler::Jal(uint32_t addr26) { 973 DsFsmInstrNop(EmitI26(0x3, addr26)); 974 } 975 976 void MipsAssembler::Jalr(Register rd, Register rs) { 977 uint32_t last_instruction = delay_slot_.instruction_; 978 bool exchange = (last_instruction != 0 && 979 (delay_slot_.gpr_outs_mask_ & (1u << rs)) == 0 && 980 ((delay_slot_.gpr_ins_mask_ | delay_slot_.gpr_outs_mask_) & (1u << rd)) == 0); 981 if (exchange) { 982 // The last instruction cannot be used in a different delay slot, 983 // do not commit the label before it (if any). 984 DsFsmDropLabel(); 985 } 986 DsFsmInstrNop(EmitR(0, rs, static_cast<Register>(0), rd, 0, 0x09)); 987 if (exchange) { 988 // Exchange the last two instructions in the assembler buffer. 989 size_t size = buffer_.Size(); 990 CHECK_GE(size, 2 * sizeof(uint32_t)); 991 size_t pos1 = size - 2 * sizeof(uint32_t); 992 size_t pos2 = size - sizeof(uint32_t); 993 uint32_t instr1 = buffer_.Load<uint32_t>(pos1); 994 uint32_t instr2 = buffer_.Load<uint32_t>(pos2); 995 CHECK_EQ(instr1, last_instruction); 996 buffer_.Store<uint32_t>(pos1, instr2); 997 buffer_.Store<uint32_t>(pos2, instr1); 998 } else if (reordering_) { 999 Nop(); 1000 } 1001 } 1002 1003 void MipsAssembler::Jalr(Register rs) { 1004 Jalr(RA, rs); 1005 } 1006 1007 void MipsAssembler::Jr(Register rs) { 1008 Jalr(ZERO, rs); 1009 } 1010 1011 void MipsAssembler::Nal() { 1012 DsFsmInstrNop(EmitI(0x1, static_cast<Register>(0), static_cast<Register>(0x10), 0)); 1013 } 1014 1015 void MipsAssembler::Auipc(Register rs, uint16_t imm16) { 1016 CHECK(IsR6()); 1017 DsFsmInstrNop(EmitI(0x3B, rs, static_cast<Register>(0x1E), imm16)); 1018 } 1019 1020 void MipsAssembler::Addiupc(Register rs, uint32_t imm19) { 1021 CHECK(IsR6()); 1022 CHECK(IsUint<19>(imm19)) << imm19; 1023 DsFsmInstrNop(EmitI21(0x3B, rs, imm19)); 1024 } 1025 1026 void MipsAssembler::Bc(uint32_t imm26) { 1027 CHECK(IsR6()); 1028 DsFsmInstrNop(EmitI26(0x32, imm26)); 1029 } 1030 1031 void MipsAssembler::Balc(uint32_t imm26) { 1032 CHECK(IsR6()); 1033 DsFsmInstrNop(EmitI26(0x3A, imm26)); 1034 } 1035 1036 void MipsAssembler::Jic(Register rt, uint16_t imm16) { 1037 CHECK(IsR6()); 1038 DsFsmInstrNop(EmitI(0x36, static_cast<Register>(0), rt, imm16)); 1039 } 1040 1041 void MipsAssembler::Jialc(Register rt, uint16_t imm16) { 1042 CHECK(IsR6()); 1043 DsFsmInstrNop(EmitI(0x3E, static_cast<Register>(0), rt, imm16)); 1044 } 1045 1046 void MipsAssembler::Bltc(Register rs, Register rt, uint16_t imm16) { 1047 CHECK(IsR6()); 1048 CHECK_NE(rs, ZERO); 1049 CHECK_NE(rt, ZERO); 1050 CHECK_NE(rs, rt); 1051 DsFsmInstrNop(EmitI(0x17, rs, rt, imm16)); 1052 } 1053 1054 void MipsAssembler::Bltzc(Register rt, uint16_t imm16) { 1055 CHECK(IsR6()); 1056 CHECK_NE(rt, ZERO); 1057 DsFsmInstrNop(EmitI(0x17, rt, rt, imm16)); 1058 } 1059 1060 void MipsAssembler::Bgtzc(Register rt, uint16_t imm16) { 1061 CHECK(IsR6()); 1062 CHECK_NE(rt, ZERO); 1063 DsFsmInstrNop(EmitI(0x17, static_cast<Register>(0), rt, imm16)); 1064 } 1065 1066 void MipsAssembler::Bgec(Register rs, Register rt, uint16_t imm16) { 1067 CHECK(IsR6()); 1068 CHECK_NE(rs, ZERO); 1069 CHECK_NE(rt, ZERO); 1070 CHECK_NE(rs, rt); 1071 DsFsmInstrNop(EmitI(0x16, rs, rt, imm16)); 1072 } 1073 1074 void MipsAssembler::Bgezc(Register rt, uint16_t imm16) { 1075 CHECK(IsR6()); 1076 CHECK_NE(rt, ZERO); 1077 DsFsmInstrNop(EmitI(0x16, rt, rt, imm16)); 1078 } 1079 1080 void MipsAssembler::Blezc(Register rt, uint16_t imm16) { 1081 CHECK(IsR6()); 1082 CHECK_NE(rt, ZERO); 1083 DsFsmInstrNop(EmitI(0x16, static_cast<Register>(0), rt, imm16)); 1084 } 1085 1086 void MipsAssembler::Bltuc(Register rs, Register rt, uint16_t imm16) { 1087 CHECK(IsR6()); 1088 CHECK_NE(rs, ZERO); 1089 CHECK_NE(rt, ZERO); 1090 CHECK_NE(rs, rt); 1091 DsFsmInstrNop(EmitI(0x7, rs, rt, imm16)); 1092 } 1093 1094 void MipsAssembler::Bgeuc(Register rs, Register rt, uint16_t imm16) { 1095 CHECK(IsR6()); 1096 CHECK_NE(rs, ZERO); 1097 CHECK_NE(rt, ZERO); 1098 CHECK_NE(rs, rt); 1099 DsFsmInstrNop(EmitI(0x6, rs, rt, imm16)); 1100 } 1101 1102 void MipsAssembler::Beqc(Register rs, Register rt, uint16_t imm16) { 1103 CHECK(IsR6()); 1104 CHECK_NE(rs, ZERO); 1105 CHECK_NE(rt, ZERO); 1106 CHECK_NE(rs, rt); 1107 DsFsmInstrNop(EmitI(0x8, std::min(rs, rt), std::max(rs, rt), imm16)); 1108 } 1109 1110 void MipsAssembler::Bnec(Register rs, Register rt, uint16_t imm16) { 1111 CHECK(IsR6()); 1112 CHECK_NE(rs, ZERO); 1113 CHECK_NE(rt, ZERO); 1114 CHECK_NE(rs, rt); 1115 DsFsmInstrNop(EmitI(0x18, std::min(rs, rt), std::max(rs, rt), imm16)); 1116 } 1117 1118 void MipsAssembler::Beqzc(Register rs, uint32_t imm21) { 1119 CHECK(IsR6()); 1120 CHECK_NE(rs, ZERO); 1121 DsFsmInstrNop(EmitI21(0x36, rs, imm21)); 1122 } 1123 1124 void MipsAssembler::Bnezc(Register rs, uint32_t imm21) { 1125 CHECK(IsR6()); 1126 CHECK_NE(rs, ZERO); 1127 DsFsmInstrNop(EmitI21(0x3E, rs, imm21)); 1128 } 1129 1130 void MipsAssembler::Bc1eqz(FRegister ft, uint16_t imm16) { 1131 CHECK(IsR6()); 1132 DsFsmInstrNop(EmitFI(0x11, 0x9, ft, imm16)); 1133 } 1134 1135 void MipsAssembler::Bc1nez(FRegister ft, uint16_t imm16) { 1136 CHECK(IsR6()); 1137 DsFsmInstrNop(EmitFI(0x11, 0xD, ft, imm16)); 1138 } 1139 1140 void MipsAssembler::EmitBcondR2(BranchCondition cond, Register rs, Register rt, uint16_t imm16) { 1141 switch (cond) { 1142 case kCondLTZ: 1143 CHECK_EQ(rt, ZERO); 1144 Bltz(rs, imm16); 1145 break; 1146 case kCondGEZ: 1147 CHECK_EQ(rt, ZERO); 1148 Bgez(rs, imm16); 1149 break; 1150 case kCondLEZ: 1151 CHECK_EQ(rt, ZERO); 1152 Blez(rs, imm16); 1153 break; 1154 case kCondGTZ: 1155 CHECK_EQ(rt, ZERO); 1156 Bgtz(rs, imm16); 1157 break; 1158 case kCondEQ: 1159 Beq(rs, rt, imm16); 1160 break; 1161 case kCondNE: 1162 Bne(rs, rt, imm16); 1163 break; 1164 case kCondEQZ: 1165 CHECK_EQ(rt, ZERO); 1166 Beqz(rs, imm16); 1167 break; 1168 case kCondNEZ: 1169 CHECK_EQ(rt, ZERO); 1170 Bnez(rs, imm16); 1171 break; 1172 case kCondF: 1173 CHECK_EQ(rt, ZERO); 1174 Bc1f(static_cast<int>(rs), imm16); 1175 break; 1176 case kCondT: 1177 CHECK_EQ(rt, ZERO); 1178 Bc1t(static_cast<int>(rs), imm16); 1179 break; 1180 case kCondLT: 1181 case kCondGE: 1182 case kCondLE: 1183 case kCondGT: 1184 case kCondLTU: 1185 case kCondGEU: 1186 case kUncond: 1187 // We don't support synthetic R2 branches (preceded with slt[u]) at this level 1188 // (R2 doesn't have branches to compare 2 registers using <, <=, >=, >). 1189 LOG(FATAL) << "Unexpected branch condition " << cond; 1190 UNREACHABLE(); 1191 } 1192 } 1193 1194 void MipsAssembler::EmitBcondR6(BranchCondition cond, Register rs, Register rt, uint32_t imm16_21) { 1195 switch (cond) { 1196 case kCondLT: 1197 Bltc(rs, rt, imm16_21); 1198 break; 1199 case kCondGE: 1200 Bgec(rs, rt, imm16_21); 1201 break; 1202 case kCondLE: 1203 Bgec(rt, rs, imm16_21); 1204 break; 1205 case kCondGT: 1206 Bltc(rt, rs, imm16_21); 1207 break; 1208 case kCondLTZ: 1209 CHECK_EQ(rt, ZERO); 1210 Bltzc(rs, imm16_21); 1211 break; 1212 case kCondGEZ: 1213 CHECK_EQ(rt, ZERO); 1214 Bgezc(rs, imm16_21); 1215 break; 1216 case kCondLEZ: 1217 CHECK_EQ(rt, ZERO); 1218 Blezc(rs, imm16_21); 1219 break; 1220 case kCondGTZ: 1221 CHECK_EQ(rt, ZERO); 1222 Bgtzc(rs, imm16_21); 1223 break; 1224 case kCondEQ: 1225 Beqc(rs, rt, imm16_21); 1226 break; 1227 case kCondNE: 1228 Bnec(rs, rt, imm16_21); 1229 break; 1230 case kCondEQZ: 1231 CHECK_EQ(rt, ZERO); 1232 Beqzc(rs, imm16_21); 1233 break; 1234 case kCondNEZ: 1235 CHECK_EQ(rt, ZERO); 1236 Bnezc(rs, imm16_21); 1237 break; 1238 case kCondLTU: 1239 Bltuc(rs, rt, imm16_21); 1240 break; 1241 case kCondGEU: 1242 Bgeuc(rs, rt, imm16_21); 1243 break; 1244 case kCondF: 1245 CHECK_EQ(rt, ZERO); 1246 Bc1eqz(static_cast<FRegister>(rs), imm16_21); 1247 break; 1248 case kCondT: 1249 CHECK_EQ(rt, ZERO); 1250 Bc1nez(static_cast<FRegister>(rs), imm16_21); 1251 break; 1252 case kUncond: 1253 LOG(FATAL) << "Unexpected branch condition " << cond; 1254 UNREACHABLE(); 1255 } 1256 } 1257 1258 void MipsAssembler::AddS(FRegister fd, FRegister fs, FRegister ft) { 1259 DsFsmInstrFff(EmitFR(0x11, 0x10, ft, fs, fd, 0x0), fd, fs, ft); 1260 } 1261 1262 void MipsAssembler::SubS(FRegister fd, FRegister fs, FRegister ft) { 1263 DsFsmInstrFff(EmitFR(0x11, 0x10, ft, fs, fd, 0x1), fd, fs, ft); 1264 } 1265 1266 void MipsAssembler::MulS(FRegister fd, FRegister fs, FRegister ft) { 1267 DsFsmInstrFff(EmitFR(0x11, 0x10, ft, fs, fd, 0x2), fd, fs, ft); 1268 } 1269 1270 void MipsAssembler::DivS(FRegister fd, FRegister fs, FRegister ft) { 1271 DsFsmInstrFff(EmitFR(0x11, 0x10, ft, fs, fd, 0x3), fd, fs, ft); 1272 } 1273 1274 void MipsAssembler::AddD(FRegister fd, FRegister fs, FRegister ft) { 1275 DsFsmInstrFff(EmitFR(0x11, 0x11, ft, fs, fd, 0x0), fd, fs, ft); 1276 } 1277 1278 void MipsAssembler::SubD(FRegister fd, FRegister fs, FRegister ft) { 1279 DsFsmInstrFff(EmitFR(0x11, 0x11, ft, fs, fd, 0x1), fd, fs, ft); 1280 } 1281 1282 void MipsAssembler::MulD(FRegister fd, FRegister fs, FRegister ft) { 1283 DsFsmInstrFff(EmitFR(0x11, 0x11, ft, fs, fd, 0x2), fd, fs, ft); 1284 } 1285 1286 void MipsAssembler::DivD(FRegister fd, FRegister fs, FRegister ft) { 1287 DsFsmInstrFff(EmitFR(0x11, 0x11, ft, fs, fd, 0x3), fd, fs, ft); 1288 } 1289 1290 void MipsAssembler::SqrtS(FRegister fd, FRegister fs) { 1291 DsFsmInstrFff(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x4), fd, fs, fs); 1292 } 1293 1294 void MipsAssembler::SqrtD(FRegister fd, FRegister fs) { 1295 DsFsmInstrFff(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x4), fd, fs, fs); 1296 } 1297 1298 void MipsAssembler::AbsS(FRegister fd, FRegister fs) { 1299 DsFsmInstrFff(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x5), fd, fs, fs); 1300 } 1301 1302 void MipsAssembler::AbsD(FRegister fd, FRegister fs) { 1303 DsFsmInstrFff(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x5), fd, fs, fs); 1304 } 1305 1306 void MipsAssembler::MovS(FRegister fd, FRegister fs) { 1307 DsFsmInstrFff(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x6), fd, fs, fs); 1308 } 1309 1310 void MipsAssembler::MovD(FRegister fd, FRegister fs) { 1311 DsFsmInstrFff(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x6), fd, fs, fs); 1312 } 1313 1314 void MipsAssembler::NegS(FRegister fd, FRegister fs) { 1315 DsFsmInstrFff(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x7), fd, fs, fs); 1316 } 1317 1318 void MipsAssembler::NegD(FRegister fd, FRegister fs) { 1319 DsFsmInstrFff(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x7), fd, fs, fs); 1320 } 1321 1322 void MipsAssembler::CunS(FRegister fs, FRegister ft) { 1323 CunS(0, fs, ft); 1324 } 1325 1326 void MipsAssembler::CunS(int cc, FRegister fs, FRegister ft) { 1327 CHECK(!IsR6()); 1328 CHECK(IsUint<3>(cc)) << cc; 1329 DsFsmInstrCff(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x31), cc, fs, ft); 1330 } 1331 1332 void MipsAssembler::CeqS(FRegister fs, FRegister ft) { 1333 CeqS(0, fs, ft); 1334 } 1335 1336 void MipsAssembler::CeqS(int cc, FRegister fs, FRegister ft) { 1337 CHECK(!IsR6()); 1338 CHECK(IsUint<3>(cc)) << cc; 1339 DsFsmInstrCff(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x32), cc, fs, ft); 1340 } 1341 1342 void MipsAssembler::CueqS(FRegister fs, FRegister ft) { 1343 CueqS(0, fs, ft); 1344 } 1345 1346 void MipsAssembler::CueqS(int cc, FRegister fs, FRegister ft) { 1347 CHECK(!IsR6()); 1348 CHECK(IsUint<3>(cc)) << cc; 1349 DsFsmInstrCff(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x33), cc, fs, ft); 1350 } 1351 1352 void MipsAssembler::ColtS(FRegister fs, FRegister ft) { 1353 ColtS(0, fs, ft); 1354 } 1355 1356 void MipsAssembler::ColtS(int cc, FRegister fs, FRegister ft) { 1357 CHECK(!IsR6()); 1358 CHECK(IsUint<3>(cc)) << cc; 1359 DsFsmInstrCff(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x34), cc, fs, ft); 1360 } 1361 1362 void MipsAssembler::CultS(FRegister fs, FRegister ft) { 1363 CultS(0, fs, ft); 1364 } 1365 1366 void MipsAssembler::CultS(int cc, FRegister fs, FRegister ft) { 1367 CHECK(!IsR6()); 1368 CHECK(IsUint<3>(cc)) << cc; 1369 DsFsmInstrCff(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x35), cc, fs, ft); 1370 } 1371 1372 void MipsAssembler::ColeS(FRegister fs, FRegister ft) { 1373 ColeS(0, fs, ft); 1374 } 1375 1376 void MipsAssembler::ColeS(int cc, FRegister fs, FRegister ft) { 1377 CHECK(!IsR6()); 1378 CHECK(IsUint<3>(cc)) << cc; 1379 DsFsmInstrCff(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x36), cc, fs, ft); 1380 } 1381 1382 void MipsAssembler::CuleS(FRegister fs, FRegister ft) { 1383 CuleS(0, fs, ft); 1384 } 1385 1386 void MipsAssembler::CuleS(int cc, FRegister fs, FRegister ft) { 1387 CHECK(!IsR6()); 1388 CHECK(IsUint<3>(cc)) << cc; 1389 DsFsmInstrCff(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x37), cc, fs, ft); 1390 } 1391 1392 void MipsAssembler::CunD(FRegister fs, FRegister ft) { 1393 CunD(0, fs, ft); 1394 } 1395 1396 void MipsAssembler::CunD(int cc, FRegister fs, FRegister ft) { 1397 CHECK(!IsR6()); 1398 CHECK(IsUint<3>(cc)) << cc; 1399 DsFsmInstrCff(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x31), cc, fs, ft); 1400 } 1401 1402 void MipsAssembler::CeqD(FRegister fs, FRegister ft) { 1403 CeqD(0, fs, ft); 1404 } 1405 1406 void MipsAssembler::CeqD(int cc, FRegister fs, FRegister ft) { 1407 CHECK(!IsR6()); 1408 CHECK(IsUint<3>(cc)) << cc; 1409 DsFsmInstrCff(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x32), cc, fs, ft); 1410 } 1411 1412 void MipsAssembler::CueqD(FRegister fs, FRegister ft) { 1413 CueqD(0, fs, ft); 1414 } 1415 1416 void MipsAssembler::CueqD(int cc, FRegister fs, FRegister ft) { 1417 CHECK(!IsR6()); 1418 CHECK(IsUint<3>(cc)) << cc; 1419 DsFsmInstrCff(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x33), cc, fs, ft); 1420 } 1421 1422 void MipsAssembler::ColtD(FRegister fs, FRegister ft) { 1423 ColtD(0, fs, ft); 1424 } 1425 1426 void MipsAssembler::ColtD(int cc, FRegister fs, FRegister ft) { 1427 CHECK(!IsR6()); 1428 CHECK(IsUint<3>(cc)) << cc; 1429 DsFsmInstrCff(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x34), cc, fs, ft); 1430 } 1431 1432 void MipsAssembler::CultD(FRegister fs, FRegister ft) { 1433 CultD(0, fs, ft); 1434 } 1435 1436 void MipsAssembler::CultD(int cc, FRegister fs, FRegister ft) { 1437 CHECK(!IsR6()); 1438 CHECK(IsUint<3>(cc)) << cc; 1439 DsFsmInstrCff(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x35), cc, fs, ft); 1440 } 1441 1442 void MipsAssembler::ColeD(FRegister fs, FRegister ft) { 1443 ColeD(0, fs, ft); 1444 } 1445 1446 void MipsAssembler::ColeD(int cc, FRegister fs, FRegister ft) { 1447 CHECK(!IsR6()); 1448 CHECK(IsUint<3>(cc)) << cc; 1449 DsFsmInstrCff(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x36), cc, fs, ft); 1450 } 1451 1452 void MipsAssembler::CuleD(FRegister fs, FRegister ft) { 1453 CuleD(0, fs, ft); 1454 } 1455 1456 void MipsAssembler::CuleD(int cc, FRegister fs, FRegister ft) { 1457 CHECK(!IsR6()); 1458 CHECK(IsUint<3>(cc)) << cc; 1459 DsFsmInstrCff(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x37), cc, fs, ft); 1460 } 1461 1462 void MipsAssembler::CmpUnS(FRegister fd, FRegister fs, FRegister ft) { 1463 CHECK(IsR6()); 1464 DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x01), fd, fs, ft); 1465 } 1466 1467 void MipsAssembler::CmpEqS(FRegister fd, FRegister fs, FRegister ft) { 1468 CHECK(IsR6()); 1469 DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x02), fd, fs, ft); 1470 } 1471 1472 void MipsAssembler::CmpUeqS(FRegister fd, FRegister fs, FRegister ft) { 1473 CHECK(IsR6()); 1474 DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x03), fd, fs, ft); 1475 } 1476 1477 void MipsAssembler::CmpLtS(FRegister fd, FRegister fs, FRegister ft) { 1478 CHECK(IsR6()); 1479 DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x04), fd, fs, ft); 1480 } 1481 1482 void MipsAssembler::CmpUltS(FRegister fd, FRegister fs, FRegister ft) { 1483 CHECK(IsR6()); 1484 DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x05), fd, fs, ft); 1485 } 1486 1487 void MipsAssembler::CmpLeS(FRegister fd, FRegister fs, FRegister ft) { 1488 CHECK(IsR6()); 1489 DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x06), fd, fs, ft); 1490 } 1491 1492 void MipsAssembler::CmpUleS(FRegister fd, FRegister fs, FRegister ft) { 1493 CHECK(IsR6()); 1494 DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x07), fd, fs, ft); 1495 } 1496 1497 void MipsAssembler::CmpOrS(FRegister fd, FRegister fs, FRegister ft) { 1498 CHECK(IsR6()); 1499 DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x11), fd, fs, ft); 1500 } 1501 1502 void MipsAssembler::CmpUneS(FRegister fd, FRegister fs, FRegister ft) { 1503 CHECK(IsR6()); 1504 DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x12), fd, fs, ft); 1505 } 1506 1507 void MipsAssembler::CmpNeS(FRegister fd, FRegister fs, FRegister ft) { 1508 CHECK(IsR6()); 1509 DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x13), fd, fs, ft); 1510 } 1511 1512 void MipsAssembler::CmpUnD(FRegister fd, FRegister fs, FRegister ft) { 1513 CHECK(IsR6()); 1514 DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x01), fd, fs, ft); 1515 } 1516 1517 void MipsAssembler::CmpEqD(FRegister fd, FRegister fs, FRegister ft) { 1518 CHECK(IsR6()); 1519 DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x02), fd, fs, ft); 1520 } 1521 1522 void MipsAssembler::CmpUeqD(FRegister fd, FRegister fs, FRegister ft) { 1523 CHECK(IsR6()); 1524 DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x03), fd, fs, ft); 1525 } 1526 1527 void MipsAssembler::CmpLtD(FRegister fd, FRegister fs, FRegister ft) { 1528 CHECK(IsR6()); 1529 DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x04), fd, fs, ft); 1530 } 1531 1532 void MipsAssembler::CmpUltD(FRegister fd, FRegister fs, FRegister ft) { 1533 CHECK(IsR6()); 1534 DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x05), fd, fs, ft); 1535 } 1536 1537 void MipsAssembler::CmpLeD(FRegister fd, FRegister fs, FRegister ft) { 1538 CHECK(IsR6()); 1539 DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x06), fd, fs, ft); 1540 } 1541 1542 void MipsAssembler::CmpUleD(FRegister fd, FRegister fs, FRegister ft) { 1543 CHECK(IsR6()); 1544 DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x07), fd, fs, ft); 1545 } 1546 1547 void MipsAssembler::CmpOrD(FRegister fd, FRegister fs, FRegister ft) { 1548 CHECK(IsR6()); 1549 DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x11), fd, fs, ft); 1550 } 1551 1552 void MipsAssembler::CmpUneD(FRegister fd, FRegister fs, FRegister ft) { 1553 CHECK(IsR6()); 1554 DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x12), fd, fs, ft); 1555 } 1556 1557 void MipsAssembler::CmpNeD(FRegister fd, FRegister fs, FRegister ft) { 1558 CHECK(IsR6()); 1559 DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x13), fd, fs, ft); 1560 } 1561 1562 void MipsAssembler::Movf(Register rd, Register rs, int cc) { 1563 CHECK(!IsR6()); 1564 CHECK(IsUint<3>(cc)) << cc; 1565 DsFsmInstrRrrc(EmitR(0, rs, static_cast<Register>(cc << 2), rd, 0, 0x01), rd, rs, cc); 1566 } 1567 1568 void MipsAssembler::Movt(Register rd, Register rs, int cc) { 1569 CHECK(!IsR6()); 1570 CHECK(IsUint<3>(cc)) << cc; 1571 DsFsmInstrRrrc(EmitR(0, rs, static_cast<Register>((cc << 2) | 1), rd, 0, 0x01), rd, rs, cc); 1572 } 1573 1574 void MipsAssembler::MovfS(FRegister fd, FRegister fs, int cc) { 1575 CHECK(!IsR6()); 1576 CHECK(IsUint<3>(cc)) << cc; 1577 DsFsmInstrFffc(EmitFR(0x11, 0x10, static_cast<FRegister>(cc << 2), fs, fd, 0x11), fd, fs, cc); 1578 } 1579 1580 void MipsAssembler::MovfD(FRegister fd, FRegister fs, int cc) { 1581 CHECK(!IsR6()); 1582 CHECK(IsUint<3>(cc)) << cc; 1583 DsFsmInstrFffc(EmitFR(0x11, 0x11, static_cast<FRegister>(cc << 2), fs, fd, 0x11), fd, fs, cc); 1584 } 1585 1586 void MipsAssembler::MovtS(FRegister fd, FRegister fs, int cc) { 1587 CHECK(!IsR6()); 1588 CHECK(IsUint<3>(cc)) << cc; 1589 DsFsmInstrFffc(EmitFR(0x11, 0x10, static_cast<FRegister>((cc << 2) | 1), fs, fd, 0x11), 1590 fd, 1591 fs, 1592 cc); 1593 } 1594 1595 void MipsAssembler::MovtD(FRegister fd, FRegister fs, int cc) { 1596 CHECK(!IsR6()); 1597 CHECK(IsUint<3>(cc)) << cc; 1598 DsFsmInstrFffc(EmitFR(0x11, 0x11, static_cast<FRegister>((cc << 2) | 1), fs, fd, 0x11), 1599 fd, 1600 fs, 1601 cc); 1602 } 1603 1604 void MipsAssembler::MovzS(FRegister fd, FRegister fs, Register rt) { 1605 CHECK(!IsR6()); 1606 DsFsmInstrFffr(EmitFR(0x11, 0x10, static_cast<FRegister>(rt), fs, fd, 0x12), fd, fs, rt); 1607 } 1608 1609 void MipsAssembler::MovzD(FRegister fd, FRegister fs, Register rt) { 1610 CHECK(!IsR6()); 1611 DsFsmInstrFffr(EmitFR(0x11, 0x11, static_cast<FRegister>(rt), fs, fd, 0x12), fd, fs, rt); 1612 } 1613 1614 void MipsAssembler::MovnS(FRegister fd, FRegister fs, Register rt) { 1615 CHECK(!IsR6()); 1616 DsFsmInstrFffr(EmitFR(0x11, 0x10, static_cast<FRegister>(rt), fs, fd, 0x13), fd, fs, rt); 1617 } 1618 1619 void MipsAssembler::MovnD(FRegister fd, FRegister fs, Register rt) { 1620 CHECK(!IsR6()); 1621 DsFsmInstrFffr(EmitFR(0x11, 0x11, static_cast<FRegister>(rt), fs, fd, 0x13), fd, fs, rt); 1622 } 1623 1624 void MipsAssembler::SelS(FRegister fd, FRegister fs, FRegister ft) { 1625 CHECK(IsR6()); 1626 DsFsmInstrFfff(EmitFR(0x11, 0x10, ft, fs, fd, 0x10), fd, fs, ft); 1627 } 1628 1629 void MipsAssembler::SelD(FRegister fd, FRegister fs, FRegister ft) { 1630 CHECK(IsR6()); 1631 DsFsmInstrFfff(EmitFR(0x11, 0x11, ft, fs, fd, 0x10), fd, fs, ft); 1632 } 1633 1634 void MipsAssembler::SeleqzS(FRegister fd, FRegister fs, FRegister ft) { 1635 CHECK(IsR6()); 1636 DsFsmInstrFff(EmitFR(0x11, 0x10, ft, fs, fd, 0x14), fd, fs, ft); 1637 } 1638 1639 void MipsAssembler::SeleqzD(FRegister fd, FRegister fs, FRegister ft) { 1640 CHECK(IsR6()); 1641 DsFsmInstrFff(EmitFR(0x11, 0x11, ft, fs, fd, 0x14), fd, fs, ft); 1642 } 1643 1644 void MipsAssembler::SelnezS(FRegister fd, FRegister fs, FRegister ft) { 1645 CHECK(IsR6()); 1646 DsFsmInstrFff(EmitFR(0x11, 0x10, ft, fs, fd, 0x17), fd, fs, ft); 1647 } 1648 1649 void MipsAssembler::SelnezD(FRegister fd, FRegister fs, FRegister ft) { 1650 CHECK(IsR6()); 1651 DsFsmInstrFff(EmitFR(0x11, 0x11, ft, fs, fd, 0x17), fd, fs, ft); 1652 } 1653 1654 void MipsAssembler::ClassS(FRegister fd, FRegister fs) { 1655 CHECK(IsR6()); 1656 DsFsmInstrFff(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x1b), fd, fs, fs); 1657 } 1658 1659 void MipsAssembler::ClassD(FRegister fd, FRegister fs) { 1660 CHECK(IsR6()); 1661 DsFsmInstrFff(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x1b), fd, fs, fs); 1662 } 1663 1664 void MipsAssembler::MinS(FRegister fd, FRegister fs, FRegister ft) { 1665 CHECK(IsR6()); 1666 DsFsmInstrFff(EmitFR(0x11, 0x10, ft, fs, fd, 0x1c), fd, fs, ft); 1667 } 1668 1669 void MipsAssembler::MinD(FRegister fd, FRegister fs, FRegister ft) { 1670 CHECK(IsR6()); 1671 DsFsmInstrFff(EmitFR(0x11, 0x11, ft, fs, fd, 0x1c), fd, fs, ft); 1672 } 1673 1674 void MipsAssembler::MaxS(FRegister fd, FRegister fs, FRegister ft) { 1675 CHECK(IsR6()); 1676 DsFsmInstrFff(EmitFR(0x11, 0x10, ft, fs, fd, 0x1e), fd, fs, ft); 1677 } 1678 1679 void MipsAssembler::MaxD(FRegister fd, FRegister fs, FRegister ft) { 1680 CHECK(IsR6()); 1681 DsFsmInstrFff(EmitFR(0x11, 0x11, ft, fs, fd, 0x1e), fd, fs, ft); 1682 } 1683 1684 void MipsAssembler::TruncLS(FRegister fd, FRegister fs) { 1685 DsFsmInstrFff(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x09), fd, fs, fs); 1686 } 1687 1688 void MipsAssembler::TruncLD(FRegister fd, FRegister fs) { 1689 DsFsmInstrFff(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x09), fd, fs, fs); 1690 } 1691 1692 void MipsAssembler::TruncWS(FRegister fd, FRegister fs) { 1693 DsFsmInstrFff(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x0D), fd, fs, fs); 1694 } 1695 1696 void MipsAssembler::TruncWD(FRegister fd, FRegister fs) { 1697 DsFsmInstrFff(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x0D), fd, fs, fs); 1698 } 1699 1700 void MipsAssembler::Cvtsw(FRegister fd, FRegister fs) { 1701 DsFsmInstrFff(EmitFR(0x11, 0x14, static_cast<FRegister>(0), fs, fd, 0x20), fd, fs, fs); 1702 } 1703 1704 void MipsAssembler::Cvtdw(FRegister fd, FRegister fs) { 1705 DsFsmInstrFff(EmitFR(0x11, 0x14, static_cast<FRegister>(0), fs, fd, 0x21), fd, fs, fs); 1706 } 1707 1708 void MipsAssembler::Cvtsd(FRegister fd, FRegister fs) { 1709 DsFsmInstrFff(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x20), fd, fs, fs); 1710 } 1711 1712 void MipsAssembler::Cvtds(FRegister fd, FRegister fs) { 1713 DsFsmInstrFff(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x21), fd, fs, fs); 1714 } 1715 1716 void MipsAssembler::Cvtsl(FRegister fd, FRegister fs) { 1717 DsFsmInstrFff(EmitFR(0x11, 0x15, static_cast<FRegister>(0), fs, fd, 0x20), fd, fs, fs); 1718 } 1719 1720 void MipsAssembler::Cvtdl(FRegister fd, FRegister fs) { 1721 DsFsmInstrFff(EmitFR(0x11, 0x15, static_cast<FRegister>(0), fs, fd, 0x21), fd, fs, fs); 1722 } 1723 1724 void MipsAssembler::FloorWS(FRegister fd, FRegister fs) { 1725 DsFsmInstrFff(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0xf), fd, fs, fs); 1726 } 1727 1728 void MipsAssembler::FloorWD(FRegister fd, FRegister fs) { 1729 DsFsmInstrFff(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0xf), fd, fs, fs); 1730 } 1731 1732 void MipsAssembler::Mfc1(Register rt, FRegister fs) { 1733 DsFsmInstrRf(EmitFR(0x11, 0x00, static_cast<FRegister>(rt), fs, static_cast<FRegister>(0), 0x0), 1734 rt, 1735 fs); 1736 } 1737 1738 void MipsAssembler::Mtc1(Register rt, FRegister fs) { 1739 DsFsmInstrFr(EmitFR(0x11, 0x04, static_cast<FRegister>(rt), fs, static_cast<FRegister>(0), 0x0), 1740 fs, 1741 rt); 1742 } 1743 1744 void MipsAssembler::Mfhc1(Register rt, FRegister fs) { 1745 DsFsmInstrRf(EmitFR(0x11, 0x03, static_cast<FRegister>(rt), fs, static_cast<FRegister>(0), 0x0), 1746 rt, 1747 fs); 1748 } 1749 1750 void MipsAssembler::Mthc1(Register rt, FRegister fs) { 1751 DsFsmInstrFr(EmitFR(0x11, 0x07, static_cast<FRegister>(rt), fs, static_cast<FRegister>(0), 0x0), 1752 fs, 1753 rt); 1754 } 1755 1756 void MipsAssembler::MoveFromFpuHigh(Register rt, FRegister fs) { 1757 if (Is32BitFPU()) { 1758 CHECK_EQ(fs % 2, 0) << fs; 1759 Mfc1(rt, static_cast<FRegister>(fs + 1)); 1760 } else { 1761 Mfhc1(rt, fs); 1762 } 1763 } 1764 1765 void MipsAssembler::MoveToFpuHigh(Register rt, FRegister fs) { 1766 if (Is32BitFPU()) { 1767 CHECK_EQ(fs % 2, 0) << fs; 1768 Mtc1(rt, static_cast<FRegister>(fs + 1)); 1769 } else { 1770 Mthc1(rt, fs); 1771 } 1772 } 1773 1774 void MipsAssembler::Lwc1(FRegister ft, Register rs, uint16_t imm16) { 1775 DsFsmInstrFr(EmitI(0x31, rs, static_cast<Register>(ft), imm16), ft, rs); 1776 } 1777 1778 void MipsAssembler::Ldc1(FRegister ft, Register rs, uint16_t imm16) { 1779 DsFsmInstrFr(EmitI(0x35, rs, static_cast<Register>(ft), imm16), ft, rs); 1780 } 1781 1782 void MipsAssembler::Swc1(FRegister ft, Register rs, uint16_t imm16) { 1783 DsFsmInstrFR(EmitI(0x39, rs, static_cast<Register>(ft), imm16), ft, rs); 1784 } 1785 1786 void MipsAssembler::Sdc1(FRegister ft, Register rs, uint16_t imm16) { 1787 DsFsmInstrFR(EmitI(0x3d, rs, static_cast<Register>(ft), imm16), ft, rs); 1788 } 1789 1790 void MipsAssembler::Break() { 1791 DsFsmInstrNop(EmitR(0, ZERO, ZERO, ZERO, 0, 0xD)); 1792 } 1793 1794 void MipsAssembler::Nop() { 1795 DsFsmInstrNop(EmitR(0x0, ZERO, ZERO, ZERO, 0, 0x0)); 1796 } 1797 1798 void MipsAssembler::NopIfNoReordering() { 1799 if (!reordering_) { 1800 Nop(); 1801 } 1802 } 1803 1804 void MipsAssembler::Move(Register rd, Register rs) { 1805 Or(rd, rs, ZERO); 1806 } 1807 1808 void MipsAssembler::Clear(Register rd) { 1809 Move(rd, ZERO); 1810 } 1811 1812 void MipsAssembler::Not(Register rd, Register rs) { 1813 Nor(rd, rs, ZERO); 1814 } 1815 1816 void MipsAssembler::Push(Register rs) { 1817 IncreaseFrameSize(kMipsWordSize); 1818 Sw(rs, SP, 0); 1819 } 1820 1821 void MipsAssembler::Pop(Register rd) { 1822 Lw(rd, SP, 0); 1823 DecreaseFrameSize(kMipsWordSize); 1824 } 1825 1826 void MipsAssembler::PopAndReturn(Register rd, Register rt) { 1827 bool reordering = SetReorder(false); 1828 Lw(rd, SP, 0); 1829 Jr(rt); 1830 DecreaseFrameSize(kMipsWordSize); // Single instruction in delay slot. 1831 SetReorder(reordering); 1832 } 1833 1834 void MipsAssembler::AndV(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1835 CHECK(HasMsa()); 1836 DsFsmInstrFff(EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x1e), 1837 static_cast<FRegister>(wd), 1838 static_cast<FRegister>(ws), 1839 static_cast<FRegister>(wt)); 1840 } 1841 1842 void MipsAssembler::OrV(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1843 CHECK(HasMsa()); 1844 DsFsmInstrFff(EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x1e), 1845 static_cast<FRegister>(wd), 1846 static_cast<FRegister>(ws), 1847 static_cast<FRegister>(wt)); 1848 } 1849 1850 void MipsAssembler::NorV(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1851 CHECK(HasMsa()); 1852 DsFsmInstrFff(EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x1e), 1853 static_cast<FRegister>(wd), 1854 static_cast<FRegister>(ws), 1855 static_cast<FRegister>(wt)); 1856 } 1857 1858 void MipsAssembler::XorV(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1859 CHECK(HasMsa()); 1860 DsFsmInstrFff(EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x1e), 1861 static_cast<FRegister>(wd), 1862 static_cast<FRegister>(ws), 1863 static_cast<FRegister>(wt)); 1864 } 1865 1866 void MipsAssembler::AddvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1867 CHECK(HasMsa()); 1868 DsFsmInstrFff(EmitMsa3R(0x0, 0x0, wt, ws, wd, 0xe), 1869 static_cast<FRegister>(wd), 1870 static_cast<FRegister>(ws), 1871 static_cast<FRegister>(wt)); 1872 } 1873 1874 void MipsAssembler::AddvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1875 CHECK(HasMsa()); 1876 DsFsmInstrFff(EmitMsa3R(0x0, 0x1, wt, ws, wd, 0xe), 1877 static_cast<FRegister>(wd), 1878 static_cast<FRegister>(ws), 1879 static_cast<FRegister>(wt)); 1880 } 1881 1882 void MipsAssembler::AddvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1883 CHECK(HasMsa()); 1884 DsFsmInstrFff(EmitMsa3R(0x0, 0x2, wt, ws, wd, 0xe), 1885 static_cast<FRegister>(wd), 1886 static_cast<FRegister>(ws), 1887 static_cast<FRegister>(wt)); 1888 } 1889 1890 void MipsAssembler::AddvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1891 CHECK(HasMsa()); 1892 DsFsmInstrFff(EmitMsa3R(0x0, 0x3, wt, ws, wd, 0xe), 1893 static_cast<FRegister>(wd), 1894 static_cast<FRegister>(ws), 1895 static_cast<FRegister>(wt)); 1896 } 1897 1898 void MipsAssembler::SubvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1899 CHECK(HasMsa()); 1900 DsFsmInstrFff(EmitMsa3R(0x1, 0x0, wt, ws, wd, 0xe), 1901 static_cast<FRegister>(wd), 1902 static_cast<FRegister>(ws), 1903 static_cast<FRegister>(wt)); 1904 } 1905 1906 void MipsAssembler::SubvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1907 CHECK(HasMsa()); 1908 DsFsmInstrFff(EmitMsa3R(0x1, 0x1, wt, ws, wd, 0xe), 1909 static_cast<FRegister>(wd), 1910 static_cast<FRegister>(ws), 1911 static_cast<FRegister>(wt)); 1912 } 1913 1914 void MipsAssembler::SubvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1915 CHECK(HasMsa()); 1916 DsFsmInstrFff(EmitMsa3R(0x1, 0x2, wt, ws, wd, 0xe), 1917 static_cast<FRegister>(wd), 1918 static_cast<FRegister>(ws), 1919 static_cast<FRegister>(wt)); 1920 } 1921 1922 void MipsAssembler::SubvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1923 CHECK(HasMsa()); 1924 DsFsmInstrFff(EmitMsa3R(0x1, 0x3, wt, ws, wd, 0xe), 1925 static_cast<FRegister>(wd), 1926 static_cast<FRegister>(ws), 1927 static_cast<FRegister>(wt)); 1928 } 1929 1930 void MipsAssembler::MulvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1931 CHECK(HasMsa()); 1932 DsFsmInstrFff(EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x12), 1933 static_cast<FRegister>(wd), 1934 static_cast<FRegister>(ws), 1935 static_cast<FRegister>(wt)); 1936 } 1937 1938 void MipsAssembler::MulvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1939 CHECK(HasMsa()); 1940 DsFsmInstrFff(EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x12), 1941 static_cast<FRegister>(wd), 1942 static_cast<FRegister>(ws), 1943 static_cast<FRegister>(wt)); 1944 } 1945 1946 void MipsAssembler::MulvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1947 CHECK(HasMsa()); 1948 DsFsmInstrFff(EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x12), 1949 static_cast<FRegister>(wd), 1950 static_cast<FRegister>(ws), 1951 static_cast<FRegister>(wt)); 1952 } 1953 1954 void MipsAssembler::MulvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1955 CHECK(HasMsa()); 1956 DsFsmInstrFff(EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x12), 1957 static_cast<FRegister>(wd), 1958 static_cast<FRegister>(ws), 1959 static_cast<FRegister>(wt)); 1960 } 1961 1962 void MipsAssembler::Div_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1963 CHECK(HasMsa()); 1964 DsFsmInstrFff(EmitMsa3R(0x4, 0x0, wt, ws, wd, 0x12), 1965 static_cast<FRegister>(wd), 1966 static_cast<FRegister>(ws), 1967 static_cast<FRegister>(wt)); 1968 } 1969 1970 void MipsAssembler::Div_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1971 CHECK(HasMsa()); 1972 DsFsmInstrFff(EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x12), 1973 static_cast<FRegister>(wd), 1974 static_cast<FRegister>(ws), 1975 static_cast<FRegister>(wt)); 1976 } 1977 1978 void MipsAssembler::Div_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1979 CHECK(HasMsa()); 1980 DsFsmInstrFff(EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x12), 1981 static_cast<FRegister>(wd), 1982 static_cast<FRegister>(ws), 1983 static_cast<FRegister>(wt)); 1984 } 1985 1986 void MipsAssembler::Div_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1987 CHECK(HasMsa()); 1988 DsFsmInstrFff(EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x12), 1989 static_cast<FRegister>(wd), 1990 static_cast<FRegister>(ws), 1991 static_cast<FRegister>(wt)); 1992 } 1993 1994 void MipsAssembler::Div_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1995 CHECK(HasMsa()); 1996 DsFsmInstrFff(EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x12), 1997 static_cast<FRegister>(wd), 1998 static_cast<FRegister>(ws), 1999 static_cast<FRegister>(wt)); 2000 } 2001 2002 void MipsAssembler::Div_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2003 CHECK(HasMsa()); 2004 DsFsmInstrFff(EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x12), 2005 static_cast<FRegister>(wd), 2006 static_cast<FRegister>(ws), 2007 static_cast<FRegister>(wt)); 2008 } 2009 2010 void MipsAssembler::Div_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2011 CHECK(HasMsa()); 2012 DsFsmInstrFff(EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x12), 2013 static_cast<FRegister>(wd), 2014 static_cast<FRegister>(ws), 2015 static_cast<FRegister>(wt)); 2016 } 2017 2018 void MipsAssembler::Div_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2019 CHECK(HasMsa()); 2020 DsFsmInstrFff(EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x12), 2021 static_cast<FRegister>(wd), 2022 static_cast<FRegister>(ws), 2023 static_cast<FRegister>(wt)); 2024 } 2025 2026 void MipsAssembler::Mod_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2027 CHECK(HasMsa()); 2028 DsFsmInstrFff(EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x12), 2029 static_cast<FRegister>(wd), 2030 static_cast<FRegister>(ws), 2031 static_cast<FRegister>(wt)); 2032 } 2033 2034 void MipsAssembler::Mod_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2035 CHECK(HasMsa()); 2036 DsFsmInstrFff(EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x12), 2037 static_cast<FRegister>(wd), 2038 static_cast<FRegister>(ws), 2039 static_cast<FRegister>(wt)); 2040 } 2041 2042 void MipsAssembler::Mod_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2043 CHECK(HasMsa()); 2044 DsFsmInstrFff(EmitMsa3R(0x6, 0x2, wt, ws, wd, 0x12), 2045 static_cast<FRegister>(wd), 2046 static_cast<FRegister>(ws), 2047 static_cast<FRegister>(wt)); 2048 } 2049 2050 void MipsAssembler::Mod_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2051 CHECK(HasMsa()); 2052 DsFsmInstrFff(EmitMsa3R(0x6, 0x3, wt, ws, wd, 0x12), 2053 static_cast<FRegister>(wd), 2054 static_cast<FRegister>(ws), 2055 static_cast<FRegister>(wt)); 2056 } 2057 2058 void MipsAssembler::Mod_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2059 CHECK(HasMsa()); 2060 DsFsmInstrFff(EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x12), 2061 static_cast<FRegister>(wd), 2062 static_cast<FRegister>(ws), 2063 static_cast<FRegister>(wt)); 2064 } 2065 2066 void MipsAssembler::Mod_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2067 CHECK(HasMsa()); 2068 DsFsmInstrFff(EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x12), 2069 static_cast<FRegister>(wd), 2070 static_cast<FRegister>(ws), 2071 static_cast<FRegister>(wt)); 2072 } 2073 2074 void MipsAssembler::Mod_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2075 CHECK(HasMsa()); 2076 DsFsmInstrFff(EmitMsa3R(0x7, 0x2, wt, ws, wd, 0x12), 2077 static_cast<FRegister>(wd), 2078 static_cast<FRegister>(ws), 2079 static_cast<FRegister>(wt)); 2080 } 2081 2082 void MipsAssembler::Mod_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2083 CHECK(HasMsa()); 2084 DsFsmInstrFff(EmitMsa3R(0x7, 0x3, wt, ws, wd, 0x12), 2085 static_cast<FRegister>(wd), 2086 static_cast<FRegister>(ws), 2087 static_cast<FRegister>(wt)); 2088 } 2089 2090 void MipsAssembler::Add_aB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2091 CHECK(HasMsa()); 2092 DsFsmInstrFff(EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x10), 2093 static_cast<FRegister>(wd), 2094 static_cast<FRegister>(ws), 2095 static_cast<FRegister>(wt)); 2096 } 2097 2098 void MipsAssembler::Add_aH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2099 CHECK(HasMsa()); 2100 DsFsmInstrFff(EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x10), 2101 static_cast<FRegister>(wd), 2102 static_cast<FRegister>(ws), 2103 static_cast<FRegister>(wt)); 2104 } 2105 2106 void MipsAssembler::Add_aW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2107 CHECK(HasMsa()); 2108 DsFsmInstrFff(EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x10), 2109 static_cast<FRegister>(wd), 2110 static_cast<FRegister>(ws), 2111 static_cast<FRegister>(wt)); 2112 } 2113 2114 void MipsAssembler::Add_aD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2115 CHECK(HasMsa()); 2116 DsFsmInstrFff(EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x10), 2117 static_cast<FRegister>(wd), 2118 static_cast<FRegister>(ws), 2119 static_cast<FRegister>(wt)); 2120 } 2121 2122 void MipsAssembler::Ave_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2123 CHECK(HasMsa()); 2124 DsFsmInstrFff(EmitMsa3R(0x4, 0x0, wt, ws, wd, 0x10), 2125 static_cast<FRegister>(wd), 2126 static_cast<FRegister>(ws), 2127 static_cast<FRegister>(wt)); 2128 } 2129 2130 void MipsAssembler::Ave_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2131 CHECK(HasMsa()); 2132 DsFsmInstrFff(EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x10), 2133 static_cast<FRegister>(wd), 2134 static_cast<FRegister>(ws), 2135 static_cast<FRegister>(wt)); 2136 } 2137 2138 void MipsAssembler::Ave_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2139 CHECK(HasMsa()); 2140 DsFsmInstrFff(EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x10), 2141 static_cast<FRegister>(wd), 2142 static_cast<FRegister>(ws), 2143 static_cast<FRegister>(wt)); 2144 } 2145 2146 void MipsAssembler::Ave_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2147 CHECK(HasMsa()); 2148 DsFsmInstrFff(EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x10), 2149 static_cast<FRegister>(wd), 2150 static_cast<FRegister>(ws), 2151 static_cast<FRegister>(wt)); 2152 } 2153 2154 void MipsAssembler::Ave_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2155 CHECK(HasMsa()); 2156 DsFsmInstrFff(EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x10), 2157 static_cast<FRegister>(wd), 2158 static_cast<FRegister>(ws), 2159 static_cast<FRegister>(wt)); 2160 } 2161 2162 void MipsAssembler::Ave_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2163 CHECK(HasMsa()); 2164 DsFsmInstrFff(EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x10), 2165 static_cast<FRegister>(wd), 2166 static_cast<FRegister>(ws), 2167 static_cast<FRegister>(wt)); 2168 } 2169 2170 void MipsAssembler::Ave_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2171 CHECK(HasMsa()); 2172 DsFsmInstrFff(EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x10), 2173 static_cast<FRegister>(wd), 2174 static_cast<FRegister>(ws), 2175 static_cast<FRegister>(wt)); 2176 } 2177 2178 void MipsAssembler::Ave_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2179 CHECK(HasMsa()); 2180 DsFsmInstrFff(EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x10), 2181 static_cast<FRegister>(wd), 2182 static_cast<FRegister>(ws), 2183 static_cast<FRegister>(wt)); 2184 } 2185 2186 void MipsAssembler::Aver_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2187 CHECK(HasMsa()); 2188 DsFsmInstrFff(EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x10), 2189 static_cast<FRegister>(wd), 2190 static_cast<FRegister>(ws), 2191 static_cast<FRegister>(wt)); 2192 } 2193 2194 void MipsAssembler::Aver_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2195 CHECK(HasMsa()); 2196 DsFsmInstrFff(EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x10), 2197 static_cast<FRegister>(wd), 2198 static_cast<FRegister>(ws), 2199 static_cast<FRegister>(wt)); 2200 } 2201 2202 void MipsAssembler::Aver_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2203 CHECK(HasMsa()); 2204 DsFsmInstrFff(EmitMsa3R(0x6, 0x2, wt, ws, wd, 0x10), 2205 static_cast<FRegister>(wd), 2206 static_cast<FRegister>(ws), 2207 static_cast<FRegister>(wt)); 2208 } 2209 2210 void MipsAssembler::Aver_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2211 CHECK(HasMsa()); 2212 DsFsmInstrFff(EmitMsa3R(0x6, 0x3, wt, ws, wd, 0x10), 2213 static_cast<FRegister>(wd), 2214 static_cast<FRegister>(ws), 2215 static_cast<FRegister>(wt)); 2216 } 2217 2218 void MipsAssembler::Aver_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2219 CHECK(HasMsa()); 2220 DsFsmInstrFff(EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x10), 2221 static_cast<FRegister>(wd), 2222 static_cast<FRegister>(ws), 2223 static_cast<FRegister>(wt)); 2224 } 2225 2226 void MipsAssembler::Aver_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2227 CHECK(HasMsa()); 2228 DsFsmInstrFff(EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x10), 2229 static_cast<FRegister>(wd), 2230 static_cast<FRegister>(ws), 2231 static_cast<FRegister>(wt)); 2232 } 2233 2234 void MipsAssembler::Aver_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2235 CHECK(HasMsa()); 2236 DsFsmInstrFff(EmitMsa3R(0x7, 0x2, wt, ws, wd, 0x10), 2237 static_cast<FRegister>(wd), 2238 static_cast<FRegister>(ws), 2239 static_cast<FRegister>(wt)); 2240 } 2241 2242 void MipsAssembler::Aver_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2243 CHECK(HasMsa()); 2244 DsFsmInstrFff(EmitMsa3R(0x7, 0x3, wt, ws, wd, 0x10), 2245 static_cast<FRegister>(wd), 2246 static_cast<FRegister>(ws), 2247 static_cast<FRegister>(wt)); 2248 } 2249 2250 void MipsAssembler::Max_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2251 CHECK(HasMsa()); 2252 DsFsmInstrFff(EmitMsa3R(0x2, 0x0, wt, ws, wd, 0xe), 2253 static_cast<FRegister>(wd), 2254 static_cast<FRegister>(ws), 2255 static_cast<FRegister>(wt)); 2256 } 2257 2258 void MipsAssembler::Max_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2259 CHECK(HasMsa()); 2260 DsFsmInstrFff(EmitMsa3R(0x2, 0x1, wt, ws, wd, 0xe), 2261 static_cast<FRegister>(wd), 2262 static_cast<FRegister>(ws), 2263 static_cast<FRegister>(wt)); 2264 } 2265 2266 void MipsAssembler::Max_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2267 CHECK(HasMsa()); 2268 DsFsmInstrFff(EmitMsa3R(0x2, 0x2, wt, ws, wd, 0xe), 2269 static_cast<FRegister>(wd), 2270 static_cast<FRegister>(ws), 2271 static_cast<FRegister>(wt)); 2272 } 2273 2274 void MipsAssembler::Max_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2275 CHECK(HasMsa()); 2276 DsFsmInstrFff(EmitMsa3R(0x2, 0x3, wt, ws, wd, 0xe), 2277 static_cast<FRegister>(wd), 2278 static_cast<FRegister>(ws), 2279 static_cast<FRegister>(wt)); 2280 } 2281 2282 void MipsAssembler::Max_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2283 CHECK(HasMsa()); 2284 DsFsmInstrFff(EmitMsa3R(0x3, 0x0, wt, ws, wd, 0xe), 2285 static_cast<FRegister>(wd), 2286 static_cast<FRegister>(ws), 2287 static_cast<FRegister>(wt)); 2288 } 2289 2290 void MipsAssembler::Max_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2291 CHECK(HasMsa()); 2292 DsFsmInstrFff(EmitMsa3R(0x3, 0x1, wt, ws, wd, 0xe), 2293 static_cast<FRegister>(wd), 2294 static_cast<FRegister>(ws), 2295 static_cast<FRegister>(wt)); 2296 } 2297 2298 void MipsAssembler::Max_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2299 CHECK(HasMsa()); 2300 DsFsmInstrFff(EmitMsa3R(0x3, 0x2, wt, ws, wd, 0xe), 2301 static_cast<FRegister>(wd), 2302 static_cast<FRegister>(ws), 2303 static_cast<FRegister>(wt)); 2304 } 2305 2306 void MipsAssembler::Max_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2307 CHECK(HasMsa()); 2308 DsFsmInstrFff(EmitMsa3R(0x3, 0x3, wt, ws, wd, 0xe), 2309 static_cast<FRegister>(wd), 2310 static_cast<FRegister>(ws), 2311 static_cast<FRegister>(wt)); 2312 } 2313 2314 void MipsAssembler::Min_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2315 CHECK(HasMsa()); 2316 DsFsmInstrFff(EmitMsa3R(0x4, 0x0, wt, ws, wd, 0xe), 2317 static_cast<FRegister>(wd), 2318 static_cast<FRegister>(ws), 2319 static_cast<FRegister>(wt)); 2320 } 2321 2322 void MipsAssembler::Min_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2323 CHECK(HasMsa()); 2324 DsFsmInstrFff(EmitMsa3R(0x4, 0x1, wt, ws, wd, 0xe), 2325 static_cast<FRegister>(wd), 2326 static_cast<FRegister>(ws), 2327 static_cast<FRegister>(wt)); 2328 } 2329 2330 void MipsAssembler::Min_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2331 CHECK(HasMsa()); 2332 DsFsmInstrFff(EmitMsa3R(0x4, 0x2, wt, ws, wd, 0xe), 2333 static_cast<FRegister>(wd), 2334 static_cast<FRegister>(ws), 2335 static_cast<FRegister>(wt)); 2336 } 2337 2338 void MipsAssembler::Min_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2339 CHECK(HasMsa()); 2340 DsFsmInstrFff(EmitMsa3R(0x4, 0x3, wt, ws, wd, 0xe), 2341 static_cast<FRegister>(wd), 2342 static_cast<FRegister>(ws), 2343 static_cast<FRegister>(wt)); 2344 } 2345 2346 void MipsAssembler::Min_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2347 CHECK(HasMsa()); 2348 DsFsmInstrFff(EmitMsa3R(0x5, 0x0, wt, ws, wd, 0xe), 2349 static_cast<FRegister>(wd), 2350 static_cast<FRegister>(ws), 2351 static_cast<FRegister>(wt)); 2352 } 2353 2354 void MipsAssembler::Min_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2355 CHECK(HasMsa()); 2356 DsFsmInstrFff(EmitMsa3R(0x5, 0x1, wt, ws, wd, 0xe), 2357 static_cast<FRegister>(wd), 2358 static_cast<FRegister>(ws), 2359 static_cast<FRegister>(wt)); 2360 } 2361 2362 void MipsAssembler::Min_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2363 CHECK(HasMsa()); 2364 DsFsmInstrFff(EmitMsa3R(0x5, 0x2, wt, ws, wd, 0xe), 2365 static_cast<FRegister>(wd), 2366 static_cast<FRegister>(ws), 2367 static_cast<FRegister>(wt)); 2368 } 2369 2370 void MipsAssembler::Min_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2371 CHECK(HasMsa()); 2372 DsFsmInstrFff(EmitMsa3R(0x5, 0x3, wt, ws, wd, 0xe), 2373 static_cast<FRegister>(wd), 2374 static_cast<FRegister>(ws), 2375 static_cast<FRegister>(wt)); 2376 } 2377 2378 void MipsAssembler::FaddW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2379 CHECK(HasMsa()); 2380 DsFsmInstrFff(EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x1b), 2381 static_cast<FRegister>(wd), 2382 static_cast<FRegister>(ws), 2383 static_cast<FRegister>(wt)); 2384 } 2385 2386 void MipsAssembler::FaddD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2387 CHECK(HasMsa()); 2388 DsFsmInstrFff(EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x1b), 2389 static_cast<FRegister>(wd), 2390 static_cast<FRegister>(ws), 2391 static_cast<FRegister>(wt)); 2392 } 2393 2394 void MipsAssembler::FsubW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2395 CHECK(HasMsa()); 2396 DsFsmInstrFff(EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x1b), 2397 static_cast<FRegister>(wd), 2398 static_cast<FRegister>(ws), 2399 static_cast<FRegister>(wt)); 2400 } 2401 2402 void MipsAssembler::FsubD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2403 CHECK(HasMsa()); 2404 DsFsmInstrFff(EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x1b), 2405 static_cast<FRegister>(wd), 2406 static_cast<FRegister>(ws), 2407 static_cast<FRegister>(wt)); 2408 } 2409 2410 void MipsAssembler::FmulW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2411 CHECK(HasMsa()); 2412 DsFsmInstrFff(EmitMsa3R(0x1, 0x0, wt, ws, wd, 0x1b), 2413 static_cast<FRegister>(wd), 2414 static_cast<FRegister>(ws), 2415 static_cast<FRegister>(wt)); 2416 } 2417 2418 void MipsAssembler::FmulD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2419 CHECK(HasMsa()); 2420 DsFsmInstrFff(EmitMsa3R(0x1, 0x1, wt, ws, wd, 0x1b), 2421 static_cast<FRegister>(wd), 2422 static_cast<FRegister>(ws), 2423 static_cast<FRegister>(wt)); 2424 } 2425 2426 void MipsAssembler::FdivW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2427 CHECK(HasMsa()); 2428 DsFsmInstrFff(EmitMsa3R(0x1, 0x2, wt, ws, wd, 0x1b), 2429 static_cast<FRegister>(wd), 2430 static_cast<FRegister>(ws), 2431 static_cast<FRegister>(wt)); 2432 } 2433 2434 void MipsAssembler::FdivD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2435 CHECK(HasMsa()); 2436 DsFsmInstrFff(EmitMsa3R(0x1, 0x3, wt, ws, wd, 0x1b), 2437 static_cast<FRegister>(wd), 2438 static_cast<FRegister>(ws), 2439 static_cast<FRegister>(wt)); 2440 } 2441 2442 void MipsAssembler::FmaxW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2443 CHECK(HasMsa()); 2444 DsFsmInstrFff(EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x1b), 2445 static_cast<FRegister>(wd), 2446 static_cast<FRegister>(ws), 2447 static_cast<FRegister>(wt)); 2448 } 2449 2450 void MipsAssembler::FmaxD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2451 CHECK(HasMsa()); 2452 DsFsmInstrFff(EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x1b), 2453 static_cast<FRegister>(wd), 2454 static_cast<FRegister>(ws), 2455 static_cast<FRegister>(wt)); 2456 } 2457 2458 void MipsAssembler::FminW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2459 CHECK(HasMsa()); 2460 DsFsmInstrFff(EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x1b), 2461 static_cast<FRegister>(wd), 2462 static_cast<FRegister>(ws), 2463 static_cast<FRegister>(wt)); 2464 } 2465 2466 void MipsAssembler::FminD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2467 CHECK(HasMsa()); 2468 DsFsmInstrFff(EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x1b), 2469 static_cast<FRegister>(wd), 2470 static_cast<FRegister>(ws), 2471 static_cast<FRegister>(wt)); 2472 } 2473 2474 void MipsAssembler::Ffint_sW(VectorRegister wd, VectorRegister ws) { 2475 CHECK(HasMsa()); 2476 DsFsmInstrFff(EmitMsa2RF(0x19e, 0x0, ws, wd, 0x1e), 2477 static_cast<FRegister>(wd), 2478 static_cast<FRegister>(ws), 2479 static_cast<FRegister>(ws)); 2480 } 2481 2482 void MipsAssembler::Ffint_sD(VectorRegister wd, VectorRegister ws) { 2483 CHECK(HasMsa()); 2484 DsFsmInstrFff(EmitMsa2RF(0x19e, 0x1, ws, wd, 0x1e), 2485 static_cast<FRegister>(wd), 2486 static_cast<FRegister>(ws), 2487 static_cast<FRegister>(ws)); 2488 } 2489 2490 void MipsAssembler::Ftint_sW(VectorRegister wd, VectorRegister ws) { 2491 CHECK(HasMsa()); 2492 DsFsmInstrFff(EmitMsa2RF(0x19c, 0x0, ws, wd, 0x1e), 2493 static_cast<FRegister>(wd), 2494 static_cast<FRegister>(ws), 2495 static_cast<FRegister>(ws)); 2496 } 2497 2498 void MipsAssembler::Ftint_sD(VectorRegister wd, VectorRegister ws) { 2499 CHECK(HasMsa()); 2500 DsFsmInstrFff(EmitMsa2RF(0x19c, 0x1, ws, wd, 0x1e), 2501 static_cast<FRegister>(wd), 2502 static_cast<FRegister>(ws), 2503 static_cast<FRegister>(ws)); 2504 } 2505 2506 void MipsAssembler::SllB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2507 CHECK(HasMsa()); 2508 DsFsmInstrFff(EmitMsa3R(0x0, 0x0, wt, ws, wd, 0xd), 2509 static_cast<FRegister>(wd), 2510 static_cast<FRegister>(ws), 2511 static_cast<FRegister>(wt)); 2512 } 2513 2514 void MipsAssembler::SllH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2515 CHECK(HasMsa()); 2516 DsFsmInstrFff(EmitMsa3R(0x0, 0x1, wt, ws, wd, 0xd), 2517 static_cast<FRegister>(wd), 2518 static_cast<FRegister>(ws), 2519 static_cast<FRegister>(wt)); 2520 } 2521 2522 void MipsAssembler::SllW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2523 CHECK(HasMsa()); 2524 DsFsmInstrFff(EmitMsa3R(0x0, 0x2, wt, ws, wd, 0xd), 2525 static_cast<FRegister>(wd), 2526 static_cast<FRegister>(ws), 2527 static_cast<FRegister>(wt)); 2528 } 2529 2530 void MipsAssembler::SllD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2531 CHECK(HasMsa()); 2532 DsFsmInstrFff(EmitMsa3R(0x0, 0x3, wt, ws, wd, 0xd), 2533 static_cast<FRegister>(wd), 2534 static_cast<FRegister>(ws), 2535 static_cast<FRegister>(wt)); 2536 } 2537 2538 void MipsAssembler::SraB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2539 CHECK(HasMsa()); 2540 DsFsmInstrFff(EmitMsa3R(0x1, 0x0, wt, ws, wd, 0xd), 2541 static_cast<FRegister>(wd), 2542 static_cast<FRegister>(ws), 2543 static_cast<FRegister>(wt)); 2544 } 2545 2546 void MipsAssembler::SraH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2547 CHECK(HasMsa()); 2548 DsFsmInstrFff(EmitMsa3R(0x1, 0x1, wt, ws, wd, 0xd), 2549 static_cast<FRegister>(wd), 2550 static_cast<FRegister>(ws), 2551 static_cast<FRegister>(wt)); 2552 } 2553 2554 void MipsAssembler::SraW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2555 CHECK(HasMsa()); 2556 DsFsmInstrFff(EmitMsa3R(0x1, 0x2, wt, ws, wd, 0xd), 2557 static_cast<FRegister>(wd), 2558 static_cast<FRegister>(ws), 2559 static_cast<FRegister>(wt)); 2560 } 2561 2562 void MipsAssembler::SraD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2563 CHECK(HasMsa()); 2564 DsFsmInstrFff(EmitMsa3R(0x1, 0x3, wt, ws, wd, 0xd), 2565 static_cast<FRegister>(wd), 2566 static_cast<FRegister>(ws), 2567 static_cast<FRegister>(wt)); 2568 } 2569 2570 void MipsAssembler::SrlB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2571 CHECK(HasMsa()); 2572 DsFsmInstrFff(EmitMsa3R(0x2, 0x0, wt, ws, wd, 0xd), 2573 static_cast<FRegister>(wd), 2574 static_cast<FRegister>(ws), 2575 static_cast<FRegister>(wt)); 2576 } 2577 2578 void MipsAssembler::SrlH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2579 CHECK(HasMsa()); 2580 DsFsmInstrFff(EmitMsa3R(0x2, 0x1, wt, ws, wd, 0xd), 2581 static_cast<FRegister>(wd), 2582 static_cast<FRegister>(ws), 2583 static_cast<FRegister>(wt)); 2584 } 2585 2586 void MipsAssembler::SrlW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2587 CHECK(HasMsa()); 2588 DsFsmInstrFff(EmitMsa3R(0x2, 0x2, wt, ws, wd, 0xd), 2589 static_cast<FRegister>(wd), 2590 static_cast<FRegister>(ws), 2591 static_cast<FRegister>(wt)); 2592 } 2593 2594 void MipsAssembler::SrlD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2595 CHECK(HasMsa()); 2596 DsFsmInstrFff(EmitMsa3R(0x2, 0x3, wt, ws, wd, 0xd), 2597 static_cast<FRegister>(wd), 2598 static_cast<FRegister>(ws), 2599 static_cast<FRegister>(wt)); 2600 } 2601 2602 void MipsAssembler::SlliB(VectorRegister wd, VectorRegister ws, int shamt3) { 2603 CHECK(HasMsa()); 2604 CHECK(IsUint<3>(shamt3)) << shamt3; 2605 DsFsmInstrFff(EmitMsaBIT(0x0, shamt3 | kMsaDfMByteMask, ws, wd, 0x9), 2606 static_cast<FRegister>(wd), 2607 static_cast<FRegister>(ws), 2608 static_cast<FRegister>(ws)); 2609 } 2610 2611 void MipsAssembler::SlliH(VectorRegister wd, VectorRegister ws, int shamt4) { 2612 CHECK(HasMsa()); 2613 CHECK(IsUint<4>(shamt4)) << shamt4; 2614 DsFsmInstrFff(EmitMsaBIT(0x0, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9), 2615 static_cast<FRegister>(wd), 2616 static_cast<FRegister>(ws), 2617 static_cast<FRegister>(ws)); 2618 } 2619 2620 void MipsAssembler::SlliW(VectorRegister wd, VectorRegister ws, int shamt5) { 2621 CHECK(HasMsa()); 2622 CHECK(IsUint<5>(shamt5)) << shamt5; 2623 DsFsmInstrFff(EmitMsaBIT(0x0, shamt5 | kMsaDfMWordMask, ws, wd, 0x9), 2624 static_cast<FRegister>(wd), 2625 static_cast<FRegister>(ws), 2626 static_cast<FRegister>(ws)); 2627 } 2628 2629 void MipsAssembler::SlliD(VectorRegister wd, VectorRegister ws, int shamt6) { 2630 CHECK(HasMsa()); 2631 CHECK(IsUint<6>(shamt6)) << shamt6; 2632 DsFsmInstrFff(EmitMsaBIT(0x0, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9), 2633 static_cast<FRegister>(wd), 2634 static_cast<FRegister>(ws), 2635 static_cast<FRegister>(ws)); 2636 } 2637 2638 void MipsAssembler::SraiB(VectorRegister wd, VectorRegister ws, int shamt3) { 2639 CHECK(HasMsa()); 2640 CHECK(IsUint<3>(shamt3)) << shamt3; 2641 DsFsmInstrFff(EmitMsaBIT(0x1, shamt3 | kMsaDfMByteMask, ws, wd, 0x9), 2642 static_cast<FRegister>(wd), 2643 static_cast<FRegister>(ws), 2644 static_cast<FRegister>(ws)); 2645 } 2646 2647 void MipsAssembler::SraiH(VectorRegister wd, VectorRegister ws, int shamt4) { 2648 CHECK(HasMsa()); 2649 CHECK(IsUint<4>(shamt4)) << shamt4; 2650 DsFsmInstrFff(EmitMsaBIT(0x1, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9), 2651 static_cast<FRegister>(wd), 2652 static_cast<FRegister>(ws), 2653 static_cast<FRegister>(ws)); 2654 } 2655 2656 void MipsAssembler::SraiW(VectorRegister wd, VectorRegister ws, int shamt5) { 2657 CHECK(HasMsa()); 2658 CHECK(IsUint<5>(shamt5)) << shamt5; 2659 DsFsmInstrFff(EmitMsaBIT(0x1, shamt5 | kMsaDfMWordMask, ws, wd, 0x9), 2660 static_cast<FRegister>(wd), 2661 static_cast<FRegister>(ws), 2662 static_cast<FRegister>(ws)); 2663 } 2664 2665 void MipsAssembler::SraiD(VectorRegister wd, VectorRegister ws, int shamt6) { 2666 CHECK(HasMsa()); 2667 CHECK(IsUint<6>(shamt6)) << shamt6; 2668 DsFsmInstrFff(EmitMsaBIT(0x1, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9), 2669 static_cast<FRegister>(wd), 2670 static_cast<FRegister>(ws), 2671 static_cast<FRegister>(ws)); 2672 } 2673 2674 void MipsAssembler::SrliB(VectorRegister wd, VectorRegister ws, int shamt3) { 2675 CHECK(HasMsa()); 2676 CHECK(IsUint<3>(shamt3)) << shamt3; 2677 DsFsmInstrFff(EmitMsaBIT(0x2, shamt3 | kMsaDfMByteMask, ws, wd, 0x9), 2678 static_cast<FRegister>(wd), 2679 static_cast<FRegister>(ws), 2680 static_cast<FRegister>(ws)); 2681 } 2682 2683 void MipsAssembler::SrliH(VectorRegister wd, VectorRegister ws, int shamt4) { 2684 CHECK(HasMsa()); 2685 CHECK(IsUint<4>(shamt4)) << shamt4; 2686 DsFsmInstrFff(EmitMsaBIT(0x2, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9), 2687 static_cast<FRegister>(wd), 2688 static_cast<FRegister>(ws), 2689 static_cast<FRegister>(ws)); 2690 } 2691 2692 void MipsAssembler::SrliW(VectorRegister wd, VectorRegister ws, int shamt5) { 2693 CHECK(HasMsa()); 2694 CHECK(IsUint<5>(shamt5)) << shamt5; 2695 DsFsmInstrFff(EmitMsaBIT(0x2, shamt5 | kMsaDfMWordMask, ws, wd, 0x9), 2696 static_cast<FRegister>(wd), 2697 static_cast<FRegister>(ws), 2698 static_cast<FRegister>(ws)); 2699 } 2700 2701 void MipsAssembler::SrliD(VectorRegister wd, VectorRegister ws, int shamt6) { 2702 CHECK(HasMsa()); 2703 CHECK(IsUint<6>(shamt6)) << shamt6; 2704 DsFsmInstrFff(EmitMsaBIT(0x2, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9), 2705 static_cast<FRegister>(wd), 2706 static_cast<FRegister>(ws), 2707 static_cast<FRegister>(ws)); 2708 } 2709 2710 void MipsAssembler::MoveV(VectorRegister wd, VectorRegister ws) { 2711 CHECK(HasMsa()); 2712 DsFsmInstrFff(EmitMsaBIT(0x1, 0x3e, ws, wd, 0x19), 2713 static_cast<FRegister>(wd), 2714 static_cast<FRegister>(ws), 2715 static_cast<FRegister>(ws)); 2716 } 2717 2718 void MipsAssembler::SplatiB(VectorRegister wd, VectorRegister ws, int n4) { 2719 CHECK(HasMsa()); 2720 CHECK(IsUint<4>(n4)) << n4; 2721 DsFsmInstrFff(EmitMsaELM(0x1, n4 | kMsaDfNByteMask, ws, wd, 0x19), 2722 static_cast<FRegister>(wd), 2723 static_cast<FRegister>(ws), 2724 static_cast<FRegister>(ws)); 2725 } 2726 2727 void MipsAssembler::SplatiH(VectorRegister wd, VectorRegister ws, int n3) { 2728 CHECK(HasMsa()); 2729 CHECK(IsUint<3>(n3)) << n3; 2730 DsFsmInstrFff(EmitMsaELM(0x1, n3 | kMsaDfNHalfwordMask, ws, wd, 0x19), 2731 static_cast<FRegister>(wd), 2732 static_cast<FRegister>(ws), 2733 static_cast<FRegister>(ws)); 2734 } 2735 2736 void MipsAssembler::SplatiW(VectorRegister wd, VectorRegister ws, int n2) { 2737 CHECK(HasMsa()); 2738 CHECK(IsUint<2>(n2)) << n2; 2739 DsFsmInstrFff(EmitMsaELM(0x1, n2 | kMsaDfNWordMask, ws, wd, 0x19), 2740 static_cast<FRegister>(wd), 2741 static_cast<FRegister>(ws), 2742 static_cast<FRegister>(ws)); 2743 } 2744 2745 void MipsAssembler::SplatiD(VectorRegister wd, VectorRegister ws, int n1) { 2746 CHECK(HasMsa()); 2747 CHECK(IsUint<1>(n1)) << n1; 2748 DsFsmInstrFff(EmitMsaELM(0x1, n1 | kMsaDfNDoublewordMask, ws, wd, 0x19), 2749 static_cast<FRegister>(wd), 2750 static_cast<FRegister>(ws), 2751 static_cast<FRegister>(ws)); 2752 } 2753 2754 void MipsAssembler::FillB(VectorRegister wd, Register rs) { 2755 CHECK(HasMsa()); 2756 DsFsmInstrFr(EmitMsa2R(0xc0, 0x0, static_cast<VectorRegister>(rs), wd, 0x1e), 2757 static_cast<FRegister>(wd), 2758 rs); 2759 } 2760 2761 void MipsAssembler::FillH(VectorRegister wd, Register rs) { 2762 CHECK(HasMsa()); 2763 DsFsmInstrFr(EmitMsa2R(0xc0, 0x1, static_cast<VectorRegister>(rs), wd, 0x1e), 2764 static_cast<FRegister>(wd), 2765 rs); 2766 } 2767 2768 void MipsAssembler::FillW(VectorRegister wd, Register rs) { 2769 CHECK(HasMsa()); 2770 DsFsmInstrFr(EmitMsa2R(0xc0, 0x2, static_cast<VectorRegister>(rs), wd, 0x1e), 2771 static_cast<FRegister>(wd), 2772 rs); 2773 } 2774 2775 void MipsAssembler::LdiB(VectorRegister wd, int imm8) { 2776 CHECK(HasMsa()); 2777 CHECK(IsInt<8>(imm8)) << imm8; 2778 DsFsmInstrFr(EmitMsaI10(0x6, 0x0, imm8 & kMsaS10Mask, wd, 0x7), 2779 static_cast<FRegister>(wd), 2780 ZERO); 2781 } 2782 2783 void MipsAssembler::LdiH(VectorRegister wd, int imm10) { 2784 CHECK(HasMsa()); 2785 CHECK(IsInt<10>(imm10)) << imm10; 2786 DsFsmInstrFr(EmitMsaI10(0x6, 0x1, imm10 & kMsaS10Mask, wd, 0x7), 2787 static_cast<FRegister>(wd), 2788 ZERO); 2789 } 2790 2791 void MipsAssembler::LdiW(VectorRegister wd, int imm10) { 2792 CHECK(HasMsa()); 2793 CHECK(IsInt<10>(imm10)) << imm10; 2794 DsFsmInstrFr(EmitMsaI10(0x6, 0x2, imm10 & kMsaS10Mask, wd, 0x7), 2795 static_cast<FRegister>(wd), 2796 ZERO); 2797 } 2798 2799 void MipsAssembler::LdiD(VectorRegister wd, int imm10) { 2800 CHECK(HasMsa()); 2801 CHECK(IsInt<10>(imm10)) << imm10; 2802 DsFsmInstrFr(EmitMsaI10(0x6, 0x3, imm10 & kMsaS10Mask, wd, 0x7), 2803 static_cast<FRegister>(wd), 2804 ZERO); 2805 } 2806 2807 void MipsAssembler::LdB(VectorRegister wd, Register rs, int offset) { 2808 CHECK(HasMsa()); 2809 CHECK(IsInt<10>(offset)) << offset; 2810 DsFsmInstrFr(EmitMsaMI10(offset & kMsaS10Mask, rs, wd, 0x8, 0x0), 2811 static_cast<FRegister>(wd), 2812 rs); 2813 } 2814 2815 void MipsAssembler::LdH(VectorRegister wd, Register rs, int offset) { 2816 CHECK(HasMsa()); 2817 CHECK(IsInt<11>(offset)) << offset; 2818 CHECK_ALIGNED(offset, kMipsHalfwordSize); 2819 DsFsmInstrFr(EmitMsaMI10((offset >> TIMES_2) & kMsaS10Mask, rs, wd, 0x8, 0x1), 2820 static_cast<FRegister>(wd), 2821 rs); 2822 } 2823 2824 void MipsAssembler::LdW(VectorRegister wd, Register rs, int offset) { 2825 CHECK(HasMsa()); 2826 CHECK(IsInt<12>(offset)) << offset; 2827 CHECK_ALIGNED(offset, kMipsWordSize); 2828 DsFsmInstrFr(EmitMsaMI10((offset >> TIMES_4) & kMsaS10Mask, rs, wd, 0x8, 0x2), 2829 static_cast<FRegister>(wd), 2830 rs); 2831 } 2832 2833 void MipsAssembler::LdD(VectorRegister wd, Register rs, int offset) { 2834 CHECK(HasMsa()); 2835 CHECK(IsInt<13>(offset)) << offset; 2836 CHECK_ALIGNED(offset, kMipsDoublewordSize); 2837 DsFsmInstrFr(EmitMsaMI10((offset >> TIMES_8) & kMsaS10Mask, rs, wd, 0x8, 0x3), 2838 static_cast<FRegister>(wd), 2839 rs); 2840 } 2841 2842 void MipsAssembler::StB(VectorRegister wd, Register rs, int offset) { 2843 CHECK(HasMsa()); 2844 CHECK(IsInt<10>(offset)) << offset; 2845 DsFsmInstrFR(EmitMsaMI10(offset & kMsaS10Mask, rs, wd, 0x9, 0x0), static_cast<FRegister>(wd), rs); 2846 } 2847 2848 void MipsAssembler::StH(VectorRegister wd, Register rs, int offset) { 2849 CHECK(HasMsa()); 2850 CHECK(IsInt<11>(offset)) << offset; 2851 CHECK_ALIGNED(offset, kMipsHalfwordSize); 2852 DsFsmInstrFR(EmitMsaMI10((offset >> TIMES_2) & kMsaS10Mask, rs, wd, 0x9, 0x1), 2853 static_cast<FRegister>(wd), 2854 rs); 2855 } 2856 2857 void MipsAssembler::StW(VectorRegister wd, Register rs, int offset) { 2858 CHECK(HasMsa()); 2859 CHECK(IsInt<12>(offset)) << offset; 2860 CHECK_ALIGNED(offset, kMipsWordSize); 2861 DsFsmInstrFR(EmitMsaMI10((offset >> TIMES_4) & kMsaS10Mask, rs, wd, 0x9, 0x2), 2862 static_cast<FRegister>(wd), 2863 rs); 2864 } 2865 2866 void MipsAssembler::StD(VectorRegister wd, Register rs, int offset) { 2867 CHECK(HasMsa()); 2868 CHECK(IsInt<13>(offset)) << offset; 2869 CHECK_ALIGNED(offset, kMipsDoublewordSize); 2870 DsFsmInstrFR(EmitMsaMI10((offset >> TIMES_8) & kMsaS10Mask, rs, wd, 0x9, 0x3), 2871 static_cast<FRegister>(wd), 2872 rs); 2873 } 2874 2875 void MipsAssembler::IlvrB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2876 CHECK(HasMsa()); 2877 DsFsmInstrFff(EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x14), 2878 static_cast<FRegister>(wd), 2879 static_cast<FRegister>(ws), 2880 static_cast<FRegister>(wt)); 2881 } 2882 2883 void MipsAssembler::IlvrH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2884 CHECK(HasMsa()); 2885 DsFsmInstrFff(EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x14), 2886 static_cast<FRegister>(wd), 2887 static_cast<FRegister>(ws), 2888 static_cast<FRegister>(wt)); 2889 } 2890 2891 void MipsAssembler::IlvrW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2892 CHECK(HasMsa()); 2893 DsFsmInstrFff(EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x14), 2894 static_cast<FRegister>(wd), 2895 static_cast<FRegister>(ws), 2896 static_cast<FRegister>(wt)); 2897 } 2898 2899 void MipsAssembler::IlvrD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2900 CHECK(HasMsa()); 2901 DsFsmInstrFff(EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x14), 2902 static_cast<FRegister>(wd), 2903 static_cast<FRegister>(ws), 2904 static_cast<FRegister>(wt)); 2905 } 2906 2907 void MipsAssembler::ReplicateFPToVectorRegister(VectorRegister dst, 2908 FRegister src, 2909 bool is_double) { 2910 // Float or double in FPU register Fx can be considered as 0th element in vector register Wx. 2911 if (is_double) { 2912 SplatiD(dst, static_cast<VectorRegister>(src), 0); 2913 } else { 2914 SplatiW(dst, static_cast<VectorRegister>(src), 0); 2915 } 2916 } 2917 2918 void MipsAssembler::LoadConst32(Register rd, int32_t value) { 2919 if (IsUint<16>(value)) { 2920 // Use OR with (unsigned) immediate to encode 16b unsigned int. 2921 Ori(rd, ZERO, value); 2922 } else if (IsInt<16>(value)) { 2923 // Use ADD with (signed) immediate to encode 16b signed int. 2924 Addiu(rd, ZERO, value); 2925 } else { 2926 Lui(rd, High16Bits(value)); 2927 if (value & 0xFFFF) 2928 Ori(rd, rd, Low16Bits(value)); 2929 } 2930 } 2931 2932 void MipsAssembler::LoadConst64(Register reg_hi, Register reg_lo, int64_t value) { 2933 uint32_t low = Low32Bits(value); 2934 uint32_t high = High32Bits(value); 2935 LoadConst32(reg_lo, low); 2936 if (high != low) { 2937 LoadConst32(reg_hi, high); 2938 } else { 2939 Move(reg_hi, reg_lo); 2940 } 2941 } 2942 2943 void MipsAssembler::LoadSConst32(FRegister r, int32_t value, Register temp) { 2944 if (value == 0) { 2945 temp = ZERO; 2946 } else { 2947 LoadConst32(temp, value); 2948 } 2949 Mtc1(temp, r); 2950 } 2951 2952 void MipsAssembler::LoadDConst64(FRegister rd, int64_t value, Register temp) { 2953 uint32_t low = Low32Bits(value); 2954 uint32_t high = High32Bits(value); 2955 if (low == 0) { 2956 Mtc1(ZERO, rd); 2957 } else { 2958 LoadConst32(temp, low); 2959 Mtc1(temp, rd); 2960 } 2961 if (high == 0) { 2962 MoveToFpuHigh(ZERO, rd); 2963 } else { 2964 LoadConst32(temp, high); 2965 MoveToFpuHigh(temp, rd); 2966 } 2967 } 2968 2969 void MipsAssembler::Addiu32(Register rt, Register rs, int32_t value, Register temp) { 2970 CHECK_NE(rs, temp); // Must not overwrite the register `rs` while loading `value`. 2971 if (IsInt<16>(value)) { 2972 Addiu(rt, rs, value); 2973 } else if (IsR6()) { 2974 int16_t high = High16Bits(value); 2975 int16_t low = Low16Bits(value); 2976 high += (low < 0) ? 1 : 0; // Account for sign extension in addiu. 2977 if (low != 0) { 2978 Aui(temp, rs, high); 2979 Addiu(rt, temp, low); 2980 } else { 2981 Aui(rt, rs, high); 2982 } 2983 } else { 2984 // Do not load the whole 32-bit `value` if it can be represented as 2985 // a sum of two 16-bit signed values. This can save an instruction. 2986 constexpr int32_t kMinValueForSimpleAdjustment = std::numeric_limits<int16_t>::min() * 2; 2987 constexpr int32_t kMaxValueForSimpleAdjustment = std::numeric_limits<int16_t>::max() * 2; 2988 if (0 <= value && value <= kMaxValueForSimpleAdjustment) { 2989 Addiu(temp, rs, kMaxValueForSimpleAdjustment / 2); 2990 Addiu(rt, temp, value - kMaxValueForSimpleAdjustment / 2); 2991 } else if (kMinValueForSimpleAdjustment <= value && value < 0) { 2992 Addiu(temp, rs, kMinValueForSimpleAdjustment / 2); 2993 Addiu(rt, temp, value - kMinValueForSimpleAdjustment / 2); 2994 } else { 2995 // Now that all shorter options have been exhausted, load the full 32-bit value. 2996 LoadConst32(temp, value); 2997 Addu(rt, rs, temp); 2998 } 2999 } 3000 } 3001 3002 void MipsAssembler::Branch::InitShortOrLong(MipsAssembler::Branch::OffsetBits offset_size, 3003 MipsAssembler::Branch::Type short_type, 3004 MipsAssembler::Branch::Type long_type) { 3005 type_ = (offset_size <= branch_info_[short_type].offset_size) ? short_type : long_type; 3006 } 3007 3008 void MipsAssembler::Branch::InitializeType(Type initial_type, bool is_r6) { 3009 OffsetBits offset_size = GetOffsetSizeNeeded(location_, target_); 3010 if (is_r6) { 3011 // R6 3012 switch (initial_type) { 3013 case kLabel: 3014 CHECK(!IsResolved()); 3015 type_ = kR6Label; 3016 break; 3017 case kLiteral: 3018 CHECK(!IsResolved()); 3019 type_ = kR6Literal; 3020 break; 3021 case kCall: 3022 InitShortOrLong(offset_size, kR6Call, kR6LongCall); 3023 break; 3024 case kCondBranch: 3025 switch (condition_) { 3026 case kUncond: 3027 InitShortOrLong(offset_size, kR6UncondBranch, kR6LongUncondBranch); 3028 break; 3029 case kCondEQZ: 3030 case kCondNEZ: 3031 // Special case for beqzc/bnezc with longer offset than in other b<cond>c instructions. 3032 type_ = (offset_size <= kOffset23) ? kR6CondBranch : kR6LongCondBranch; 3033 break; 3034 default: 3035 InitShortOrLong(offset_size, kR6CondBranch, kR6LongCondBranch); 3036 break; 3037 } 3038 break; 3039 default: 3040 LOG(FATAL) << "Unexpected branch type " << initial_type; 3041 UNREACHABLE(); 3042 } 3043 } else { 3044 // R2 3045 switch (initial_type) { 3046 case kLabel: 3047 CHECK(!IsResolved()); 3048 type_ = kLabel; 3049 break; 3050 case kLiteral: 3051 CHECK(!IsResolved()); 3052 type_ = kLiteral; 3053 break; 3054 case kCall: 3055 InitShortOrLong(offset_size, kCall, kLongCall); 3056 break; 3057 case kCondBranch: 3058 switch (condition_) { 3059 case kUncond: 3060 InitShortOrLong(offset_size, kUncondBranch, kLongUncondBranch); 3061 break; 3062 default: 3063 InitShortOrLong(offset_size, kCondBranch, kLongCondBranch); 3064 break; 3065 } 3066 break; 3067 default: 3068 LOG(FATAL) << "Unexpected branch type " << initial_type; 3069 UNREACHABLE(); 3070 } 3071 } 3072 old_type_ = type_; 3073 } 3074 3075 bool MipsAssembler::Branch::IsNop(BranchCondition condition, Register lhs, Register rhs) { 3076 switch (condition) { 3077 case kCondLT: 3078 case kCondGT: 3079 case kCondNE: 3080 case kCondLTU: 3081 return lhs == rhs; 3082 default: 3083 return false; 3084 } 3085 } 3086 3087 bool MipsAssembler::Branch::IsUncond(BranchCondition condition, Register lhs, Register rhs) { 3088 switch (condition) { 3089 case kUncond: 3090 return true; 3091 case kCondGE: 3092 case kCondLE: 3093 case kCondEQ: 3094 case kCondGEU: 3095 return lhs == rhs; 3096 default: 3097 return false; 3098 } 3099 } 3100 3101 MipsAssembler::Branch::Branch(bool is_r6, uint32_t location, uint32_t target, bool is_call) 3102 : old_location_(location), 3103 location_(location), 3104 target_(target), 3105 lhs_reg_(0), 3106 rhs_reg_(0), 3107 condition_(kUncond), 3108 delayed_instruction_(kUnfilledDelaySlot) { 3109 InitializeType((is_call ? kCall : kCondBranch), is_r6); 3110 } 3111 3112 MipsAssembler::Branch::Branch(bool is_r6, 3113 uint32_t location, 3114 uint32_t target, 3115 MipsAssembler::BranchCondition condition, 3116 Register lhs_reg, 3117 Register rhs_reg) 3118 : old_location_(location), 3119 location_(location), 3120 target_(target), 3121 lhs_reg_(lhs_reg), 3122 rhs_reg_(rhs_reg), 3123 condition_(condition), 3124 delayed_instruction_(kUnfilledDelaySlot) { 3125 CHECK_NE(condition, kUncond); 3126 switch (condition) { 3127 case kCondLT: 3128 case kCondGE: 3129 case kCondLE: 3130 case kCondGT: 3131 case kCondLTU: 3132 case kCondGEU: 3133 // We don't support synthetic R2 branches (preceded with slt[u]) at this level 3134 // (R2 doesn't have branches to compare 2 registers using <, <=, >=, >). 3135 // We leave this up to the caller. 3136 CHECK(is_r6); 3137 FALLTHROUGH_INTENDED; 3138 case kCondEQ: 3139 case kCondNE: 3140 // Require registers other than 0 not only for R6, but also for R2 to catch errors. 3141 // To compare with 0, use dedicated kCond*Z conditions. 3142 CHECK_NE(lhs_reg, ZERO); 3143 CHECK_NE(rhs_reg, ZERO); 3144 break; 3145 case kCondLTZ: 3146 case kCondGEZ: 3147 case kCondLEZ: 3148 case kCondGTZ: 3149 case kCondEQZ: 3150 case kCondNEZ: 3151 // Require registers other than 0 not only for R6, but also for R2 to catch errors. 3152 CHECK_NE(lhs_reg, ZERO); 3153 CHECK_EQ(rhs_reg, ZERO); 3154 break; 3155 case kCondF: 3156 case kCondT: 3157 CHECK_EQ(rhs_reg, ZERO); 3158 break; 3159 case kUncond: 3160 UNREACHABLE(); 3161 } 3162 CHECK(!IsNop(condition, lhs_reg, rhs_reg)); 3163 if (IsUncond(condition, lhs_reg, rhs_reg)) { 3164 // Branch condition is always true, make the branch unconditional. 3165 condition_ = kUncond; 3166 } 3167 InitializeType(kCondBranch, is_r6); 3168 } 3169 3170 MipsAssembler::Branch::Branch(bool is_r6, 3171 uint32_t location, 3172 Register dest_reg, 3173 Register base_reg, 3174 Type label_or_literal_type) 3175 : old_location_(location), 3176 location_(location), 3177 target_(kUnresolved), 3178 lhs_reg_(dest_reg), 3179 rhs_reg_(base_reg), 3180 condition_(kUncond), 3181 delayed_instruction_(kUnfilledDelaySlot) { 3182 CHECK_NE(dest_reg, ZERO); 3183 if (is_r6) { 3184 CHECK_EQ(base_reg, ZERO); 3185 } else { 3186 CHECK_NE(base_reg, ZERO); 3187 } 3188 InitializeType(label_or_literal_type, is_r6); 3189 } 3190 3191 MipsAssembler::BranchCondition MipsAssembler::Branch::OppositeCondition( 3192 MipsAssembler::BranchCondition cond) { 3193 switch (cond) { 3194 case kCondLT: 3195 return kCondGE; 3196 case kCondGE: 3197 return kCondLT; 3198 case kCondLE: 3199 return kCondGT; 3200 case kCondGT: 3201 return kCondLE; 3202 case kCondLTZ: 3203 return kCondGEZ; 3204 case kCondGEZ: 3205 return kCondLTZ; 3206 case kCondLEZ: 3207 return kCondGTZ; 3208 case kCondGTZ: 3209 return kCondLEZ; 3210 case kCondEQ: 3211 return kCondNE; 3212 case kCondNE: 3213 return kCondEQ; 3214 case kCondEQZ: 3215 return kCondNEZ; 3216 case kCondNEZ: 3217 return kCondEQZ; 3218 case kCondLTU: 3219 return kCondGEU; 3220 case kCondGEU: 3221 return kCondLTU; 3222 case kCondF: 3223 return kCondT; 3224 case kCondT: 3225 return kCondF; 3226 case kUncond: 3227 LOG(FATAL) << "Unexpected branch condition " << cond; 3228 } 3229 UNREACHABLE(); 3230 } 3231 3232 MipsAssembler::Branch::Type MipsAssembler::Branch::GetType() const { 3233 return type_; 3234 } 3235 3236 MipsAssembler::BranchCondition MipsAssembler::Branch::GetCondition() const { 3237 return condition_; 3238 } 3239 3240 Register MipsAssembler::Branch::GetLeftRegister() const { 3241 return static_cast<Register>(lhs_reg_); 3242 } 3243 3244 Register MipsAssembler::Branch::GetRightRegister() const { 3245 return static_cast<Register>(rhs_reg_); 3246 } 3247 3248 uint32_t MipsAssembler::Branch::GetTarget() const { 3249 return target_; 3250 } 3251 3252 uint32_t MipsAssembler::Branch::GetLocation() const { 3253 return location_; 3254 } 3255 3256 uint32_t MipsAssembler::Branch::GetOldLocation() const { 3257 return old_location_; 3258 } 3259 3260 uint32_t MipsAssembler::Branch::GetPrecedingInstructionLength(Type type) const { 3261 // Short branches with delay slots always consist of two instructions, the branch 3262 // and the delay slot, irrespective of whether the delay slot is filled with a 3263 // useful instruction or not. 3264 // Long composite branches may have a length longer by one instruction than 3265 // specified in branch_info_[].length. This happens when an instruction is taken 3266 // to fill the short branch delay slot, but the branch eventually becomes long 3267 // and formally has no delay slot to fill. This instruction is placed at the 3268 // beginning of the long composite branch and this needs to be accounted for in 3269 // the branch length and the location of the offset encoded in the branch. 3270 switch (type) { 3271 case kLongUncondBranch: 3272 case kLongCondBranch: 3273 case kLongCall: 3274 case kR6LongCondBranch: 3275 return (delayed_instruction_ != kUnfilledDelaySlot && 3276 delayed_instruction_ != kUnfillableDelaySlot) ? 1 : 0; 3277 default: 3278 return 0; 3279 } 3280 } 3281 3282 uint32_t MipsAssembler::Branch::GetPrecedingInstructionSize(Type type) const { 3283 return GetPrecedingInstructionLength(type) * sizeof(uint32_t); 3284 } 3285 3286 uint32_t MipsAssembler::Branch::GetLength() const { 3287 return GetPrecedingInstructionLength(type_) + branch_info_[type_].length; 3288 } 3289 3290 uint32_t MipsAssembler::Branch::GetOldLength() const { 3291 return GetPrecedingInstructionLength(old_type_) + branch_info_[old_type_].length; 3292 } 3293 3294 uint32_t MipsAssembler::Branch::GetSize() const { 3295 return GetLength() * sizeof(uint32_t); 3296 } 3297 3298 uint32_t MipsAssembler::Branch::GetOldSize() const { 3299 return GetOldLength() * sizeof(uint32_t); 3300 } 3301 3302 uint32_t MipsAssembler::Branch::GetEndLocation() const { 3303 return GetLocation() + GetSize(); 3304 } 3305 3306 uint32_t MipsAssembler::Branch::GetOldEndLocation() const { 3307 return GetOldLocation() + GetOldSize(); 3308 } 3309 3310 bool MipsAssembler::Branch::IsLong() const { 3311 switch (type_) { 3312 // R2 short branches. 3313 case kUncondBranch: 3314 case kCondBranch: 3315 case kCall: 3316 // R2 near label. 3317 case kLabel: 3318 // R2 near literal. 3319 case kLiteral: 3320 // R6 short branches. 3321 case kR6UncondBranch: 3322 case kR6CondBranch: 3323 case kR6Call: 3324 // R6 near label. 3325 case kR6Label: 3326 // R6 near literal. 3327 case kR6Literal: 3328 return false; 3329 // R2 long branches. 3330 case kLongUncondBranch: 3331 case kLongCondBranch: 3332 case kLongCall: 3333 // R2 far label. 3334 case kFarLabel: 3335 // R2 far literal. 3336 case kFarLiteral: 3337 // R6 long branches. 3338 case kR6LongUncondBranch: 3339 case kR6LongCondBranch: 3340 case kR6LongCall: 3341 // R6 far label. 3342 case kR6FarLabel: 3343 // R6 far literal. 3344 case kR6FarLiteral: 3345 return true; 3346 } 3347 UNREACHABLE(); 3348 } 3349 3350 bool MipsAssembler::Branch::IsResolved() const { 3351 return target_ != kUnresolved; 3352 } 3353 3354 MipsAssembler::Branch::OffsetBits MipsAssembler::Branch::GetOffsetSize() const { 3355 OffsetBits offset_size = 3356 (type_ == kR6CondBranch && (condition_ == kCondEQZ || condition_ == kCondNEZ)) 3357 ? kOffset23 3358 : branch_info_[type_].offset_size; 3359 return offset_size; 3360 } 3361 3362 MipsAssembler::Branch::OffsetBits MipsAssembler::Branch::GetOffsetSizeNeeded(uint32_t location, 3363 uint32_t target) { 3364 // For unresolved targets assume the shortest encoding 3365 // (later it will be made longer if needed). 3366 if (target == kUnresolved) 3367 return kOffset16; 3368 int64_t distance = static_cast<int64_t>(target) - location; 3369 // To simplify calculations in composite branches consisting of multiple instructions 3370 // bump up the distance by a value larger than the max byte size of a composite branch. 3371 distance += (distance >= 0) ? kMaxBranchSize : -kMaxBranchSize; 3372 if (IsInt<kOffset16>(distance)) 3373 return kOffset16; 3374 else if (IsInt<kOffset18>(distance)) 3375 return kOffset18; 3376 else if (IsInt<kOffset21>(distance)) 3377 return kOffset21; 3378 else if (IsInt<kOffset23>(distance)) 3379 return kOffset23; 3380 else if (IsInt<kOffset28>(distance)) 3381 return kOffset28; 3382 return kOffset32; 3383 } 3384 3385 void MipsAssembler::Branch::Resolve(uint32_t target) { 3386 target_ = target; 3387 } 3388 3389 void MipsAssembler::Branch::Relocate(uint32_t expand_location, uint32_t delta) { 3390 if (location_ > expand_location) { 3391 location_ += delta; 3392 } 3393 if (!IsResolved()) { 3394 return; // Don't know the target yet. 3395 } 3396 if (target_ > expand_location) { 3397 target_ += delta; 3398 } 3399 } 3400 3401 void MipsAssembler::Branch::PromoteToLong() { 3402 switch (type_) { 3403 // R2 short branches. 3404 case kUncondBranch: 3405 type_ = kLongUncondBranch; 3406 break; 3407 case kCondBranch: 3408 type_ = kLongCondBranch; 3409 break; 3410 case kCall: 3411 type_ = kLongCall; 3412 break; 3413 // R2 near label. 3414 case kLabel: 3415 type_ = kFarLabel; 3416 break; 3417 // R2 near literal. 3418 case kLiteral: 3419 type_ = kFarLiteral; 3420 break; 3421 // R6 short branches. 3422 case kR6UncondBranch: 3423 type_ = kR6LongUncondBranch; 3424 break; 3425 case kR6CondBranch: 3426 type_ = kR6LongCondBranch; 3427 break; 3428 case kR6Call: 3429 type_ = kR6LongCall; 3430 break; 3431 // R6 near label. 3432 case kR6Label: 3433 type_ = kR6FarLabel; 3434 break; 3435 // R6 near literal. 3436 case kR6Literal: 3437 type_ = kR6FarLiteral; 3438 break; 3439 default: 3440 // Note: 'type_' is already long. 3441 break; 3442 } 3443 CHECK(IsLong()); 3444 } 3445 3446 uint32_t MipsAssembler::GetBranchLocationOrPcRelBase(const MipsAssembler::Branch* branch) const { 3447 switch (branch->GetType()) { 3448 case Branch::kLabel: 3449 case Branch::kFarLabel: 3450 case Branch::kLiteral: 3451 case Branch::kFarLiteral: 3452 return GetLabelLocation(&pc_rel_base_label_); 3453 default: 3454 return branch->GetLocation(); 3455 } 3456 } 3457 3458 uint32_t MipsAssembler::Branch::PromoteIfNeeded(uint32_t location, uint32_t max_short_distance) { 3459 // `location` is either `GetLabelLocation(&pc_rel_base_label_)` for R2 labels/literals or 3460 // `this->GetLocation()` for everything else. 3461 // If the branch is still unresolved or already long, nothing to do. 3462 if (IsLong() || !IsResolved()) { 3463 return 0; 3464 } 3465 // Promote the short branch to long if the offset size is too small 3466 // to hold the distance between location and target_. 3467 if (GetOffsetSizeNeeded(location, target_) > GetOffsetSize()) { 3468 PromoteToLong(); 3469 uint32_t old_size = GetOldSize(); 3470 uint32_t new_size = GetSize(); 3471 CHECK_GT(new_size, old_size); 3472 return new_size - old_size; 3473 } 3474 // The following logic is for debugging/testing purposes. 3475 // Promote some short branches to long when it's not really required. 3476 if (UNLIKELY(max_short_distance != std::numeric_limits<uint32_t>::max())) { 3477 int64_t distance = static_cast<int64_t>(target_) - location; 3478 distance = (distance >= 0) ? distance : -distance; 3479 if (distance >= max_short_distance) { 3480 PromoteToLong(); 3481 uint32_t old_size = GetOldSize(); 3482 uint32_t new_size = GetSize(); 3483 CHECK_GT(new_size, old_size); 3484 return new_size - old_size; 3485 } 3486 } 3487 return 0; 3488 } 3489 3490 uint32_t MipsAssembler::Branch::GetOffsetLocation() const { 3491 return location_ + GetPrecedingInstructionSize(type_) + 3492 branch_info_[type_].instr_offset * sizeof(uint32_t); 3493 } 3494 3495 uint32_t MipsAssembler::GetBranchOrPcRelBaseForEncoding(const MipsAssembler::Branch* branch) const { 3496 switch (branch->GetType()) { 3497 case Branch::kLabel: 3498 case Branch::kFarLabel: 3499 case Branch::kLiteral: 3500 case Branch::kFarLiteral: 3501 return GetLabelLocation(&pc_rel_base_label_); 3502 default: 3503 return branch->GetOffsetLocation() + 3504 Branch::branch_info_[branch->GetType()].pc_org * sizeof(uint32_t); 3505 } 3506 } 3507 3508 uint32_t MipsAssembler::Branch::GetOffset(uint32_t location) const { 3509 // `location` is either `GetLabelLocation(&pc_rel_base_label_)` for R2 labels/literals or 3510 // `this->GetOffsetLocation() + branch_info_[this->GetType()].pc_org * sizeof(uint32_t)` 3511 // for everything else. 3512 CHECK(IsResolved()); 3513 uint32_t ofs_mask = 0xFFFFFFFF >> (32 - GetOffsetSize()); 3514 // Calculate the byte distance between instructions and also account for 3515 // different PC-relative origins. 3516 uint32_t offset = target_ - location; 3517 // Prepare the offset for encoding into the instruction(s). 3518 offset = (offset & ofs_mask) >> branch_info_[type_].offset_shift; 3519 return offset; 3520 } 3521 3522 MipsAssembler::Branch* MipsAssembler::GetBranch(uint32_t branch_id) { 3523 CHECK_LT(branch_id, branches_.size()); 3524 return &branches_[branch_id]; 3525 } 3526 3527 const MipsAssembler::Branch* MipsAssembler::GetBranch(uint32_t branch_id) const { 3528 CHECK_LT(branch_id, branches_.size()); 3529 return &branches_[branch_id]; 3530 } 3531 3532 void MipsAssembler::Bind(MipsLabel* label) { 3533 CHECK(!label->IsBound()); 3534 uint32_t bound_pc = buffer_.Size(); 3535 3536 // Make the delay slot FSM aware of the new label. 3537 DsFsmLabel(); 3538 3539 // Walk the list of branches referring to and preceding this label. 3540 // Store the previously unknown target addresses in them. 3541 while (label->IsLinked()) { 3542 uint32_t branch_id = label->Position(); 3543 Branch* branch = GetBranch(branch_id); 3544 branch->Resolve(bound_pc); 3545 3546 uint32_t branch_location = branch->GetLocation(); 3547 // Extract the location of the previous branch in the list (walking the list backwards; 3548 // the previous branch ID was stored in the space reserved for this branch). 3549 uint32_t prev = buffer_.Load<uint32_t>(branch_location); 3550 3551 // On to the previous branch in the list... 3552 label->position_ = prev; 3553 } 3554 3555 // Now make the label object contain its own location (relative to the end of the preceding 3556 // branch, if any; it will be used by the branches referring to and following this label). 3557 label->prev_branch_id_plus_one_ = branches_.size(); 3558 if (label->prev_branch_id_plus_one_) { 3559 uint32_t branch_id = label->prev_branch_id_plus_one_ - 1; 3560 const Branch* branch = GetBranch(branch_id); 3561 bound_pc -= branch->GetEndLocation(); 3562 } 3563 label->BindTo(bound_pc); 3564 } 3565 3566 uint32_t MipsAssembler::GetLabelLocation(const MipsLabel* label) const { 3567 CHECK(label->IsBound()); 3568 uint32_t target = label->Position(); 3569 if (label->prev_branch_id_plus_one_) { 3570 // Get label location based on the branch preceding it. 3571 uint32_t branch_id = label->prev_branch_id_plus_one_ - 1; 3572 const Branch* branch = GetBranch(branch_id); 3573 target += branch->GetEndLocation(); 3574 } 3575 return target; 3576 } 3577 3578 uint32_t MipsAssembler::GetAdjustedPosition(uint32_t old_position) { 3579 // We can reconstruct the adjustment by going through all the branches from the beginning 3580 // up to the old_position. Since we expect AdjustedPosition() to be called in a loop 3581 // with increasing old_position, we can use the data from last AdjustedPosition() to 3582 // continue where we left off and the whole loop should be O(m+n) where m is the number 3583 // of positions to adjust and n is the number of branches. 3584 if (old_position < last_old_position_) { 3585 last_position_adjustment_ = 0; 3586 last_old_position_ = 0; 3587 last_branch_id_ = 0; 3588 } 3589 while (last_branch_id_ != branches_.size()) { 3590 const Branch* branch = GetBranch(last_branch_id_); 3591 if (branch->GetLocation() >= old_position + last_position_adjustment_) { 3592 break; 3593 } 3594 last_position_adjustment_ += branch->GetSize() - branch->GetOldSize(); 3595 ++last_branch_id_; 3596 } 3597 last_old_position_ = old_position; 3598 return old_position + last_position_adjustment_; 3599 } 3600 3601 void MipsAssembler::BindPcRelBaseLabel() { 3602 Bind(&pc_rel_base_label_); 3603 } 3604 3605 uint32_t MipsAssembler::GetPcRelBaseLabelLocation() const { 3606 return GetLabelLocation(&pc_rel_base_label_); 3607 } 3608 3609 void MipsAssembler::FinalizeLabeledBranch(MipsLabel* label) { 3610 uint32_t length = branches_.back().GetLength(); 3611 // Commit the last branch target label (if any). 3612 DsFsmCommitLabel(); 3613 if (!label->IsBound()) { 3614 // Branch forward (to a following label), distance is unknown. 3615 // The first branch forward will contain 0, serving as the terminator of 3616 // the list of forward-reaching branches. 3617 Emit(label->position_); 3618 // Nothing for the delay slot (yet). 3619 DsFsmInstrNop(0); 3620 length--; 3621 // Now make the label object point to this branch 3622 // (this forms a linked list of branches preceding this label). 3623 uint32_t branch_id = branches_.size() - 1; 3624 label->LinkTo(branch_id); 3625 } 3626 // Reserve space for the branch. 3627 while (length--) { 3628 Nop(); 3629 } 3630 } 3631 3632 bool MipsAssembler::Branch::CanHaveDelayedInstruction(const DelaySlot& delay_slot) const { 3633 if (delay_slot.instruction_ == 0) { 3634 // NOP or no instruction for the delay slot. 3635 return false; 3636 } 3637 switch (type_) { 3638 // R2 unconditional branches. 3639 case kUncondBranch: 3640 case kLongUncondBranch: 3641 // There are no register interdependencies. 3642 return true; 3643 3644 // R2 calls. 3645 case kCall: 3646 case kLongCall: 3647 // Instructions depending on or modifying RA should not be moved into delay slots 3648 // of branches modifying RA. 3649 return ((delay_slot.gpr_ins_mask_ | delay_slot.gpr_outs_mask_) & (1u << RA)) == 0; 3650 3651 // R2 conditional branches. 3652 case kCondBranch: 3653 case kLongCondBranch: 3654 switch (condition_) { 3655 // Branches with one GPR source. 3656 case kCondLTZ: 3657 case kCondGEZ: 3658 case kCondLEZ: 3659 case kCondGTZ: 3660 case kCondEQZ: 3661 case kCondNEZ: 3662 return (delay_slot.gpr_outs_mask_ & (1u << lhs_reg_)) == 0; 3663 3664 // Branches with two GPR sources. 3665 case kCondEQ: 3666 case kCondNE: 3667 return (delay_slot.gpr_outs_mask_ & ((1u << lhs_reg_) | (1u << rhs_reg_))) == 0; 3668 3669 // Branches with one FPU condition code source. 3670 case kCondF: 3671 case kCondT: 3672 return (delay_slot.cc_outs_mask_ & (1u << lhs_reg_)) == 0; 3673 3674 default: 3675 // We don't support synthetic R2 branches (preceded with slt[u]) at this level 3676 // (R2 doesn't have branches to compare 2 registers using <, <=, >=, >). 3677 LOG(FATAL) << "Unexpected branch condition " << condition_; 3678 UNREACHABLE(); 3679 } 3680 3681 // R6 unconditional branches. 3682 case kR6UncondBranch: 3683 case kR6LongUncondBranch: 3684 // R6 calls. 3685 case kR6Call: 3686 case kR6LongCall: 3687 // There are no delay slots. 3688 return false; 3689 3690 // R6 conditional branches. 3691 case kR6CondBranch: 3692 case kR6LongCondBranch: 3693 switch (condition_) { 3694 // Branches with one FPU register source. 3695 case kCondF: 3696 case kCondT: 3697 return (delay_slot.fpr_outs_mask_ & (1u << lhs_reg_)) == 0; 3698 // Others have a forbidden slot instead of a delay slot. 3699 default: 3700 return false; 3701 } 3702 3703 // Literals. 3704 default: 3705 LOG(FATAL) << "Unexpected branch type " << type_; 3706 UNREACHABLE(); 3707 } 3708 } 3709 3710 uint32_t MipsAssembler::Branch::GetDelayedInstruction() const { 3711 return delayed_instruction_; 3712 } 3713 3714 void MipsAssembler::Branch::SetDelayedInstruction(uint32_t instruction) { 3715 CHECK_NE(instruction, kUnfilledDelaySlot); 3716 CHECK_EQ(delayed_instruction_, kUnfilledDelaySlot); 3717 delayed_instruction_ = instruction; 3718 } 3719 3720 void MipsAssembler::Branch::DecrementLocations() { 3721 // We first create a branch object, which gets its type and locations initialized, 3722 // and then we check if the branch can actually have the preceding instruction moved 3723 // into its delay slot. If it can, the branch locations need to be decremented. 3724 // 3725 // We could make the check before creating the branch object and avoid the location 3726 // adjustment, but the check is cleaner when performed on an initialized branch 3727 // object. 3728 // 3729 // If the branch is backwards (to a previously bound label), reducing the locations 3730 // cannot cause a short branch to exceed its offset range because the offset reduces. 3731 // And this is not at all a problem for a long branch backwards. 3732 // 3733 // If the branch is forward (not linked to any label yet), reducing the locations 3734 // is harmless. The branch will be promoted to long if needed when the target is known. 3735 CHECK_EQ(location_, old_location_); 3736 CHECK_GE(old_location_, sizeof(uint32_t)); 3737 old_location_ -= sizeof(uint32_t); 3738 location_ = old_location_; 3739 } 3740 3741 void MipsAssembler::MoveInstructionToDelaySlot(Branch& branch) { 3742 if (branch.CanHaveDelayedInstruction(delay_slot_)) { 3743 // The last instruction cannot be used in a different delay slot, 3744 // do not commit the label before it (if any). 3745 DsFsmDropLabel(); 3746 // Remove the last emitted instruction. 3747 size_t size = buffer_.Size(); 3748 CHECK_GE(size, sizeof(uint32_t)); 3749 size -= sizeof(uint32_t); 3750 CHECK_EQ(buffer_.Load<uint32_t>(size), delay_slot_.instruction_); 3751 buffer_.Resize(size); 3752 // Attach it to the branch and adjust the branch locations. 3753 branch.DecrementLocations(); 3754 branch.SetDelayedInstruction(delay_slot_.instruction_); 3755 } else if (!reordering_ && branch.GetType() == Branch::kUncondBranch) { 3756 // If reordefing is disabled, prevent absorption of the target instruction. 3757 branch.SetDelayedInstruction(Branch::kUnfillableDelaySlot); 3758 } 3759 } 3760 3761 void MipsAssembler::Buncond(MipsLabel* label) { 3762 uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved; 3763 branches_.emplace_back(IsR6(), buffer_.Size(), target, /* is_call */ false); 3764 MoveInstructionToDelaySlot(branches_.back()); 3765 FinalizeLabeledBranch(label); 3766 } 3767 3768 void MipsAssembler::Bcond(MipsLabel* label, BranchCondition condition, Register lhs, Register rhs) { 3769 // If lhs = rhs, this can be a NOP. 3770 if (Branch::IsNop(condition, lhs, rhs)) { 3771 return; 3772 } 3773 uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved; 3774 branches_.emplace_back(IsR6(), buffer_.Size(), target, condition, lhs, rhs); 3775 MoveInstructionToDelaySlot(branches_.back()); 3776 FinalizeLabeledBranch(label); 3777 } 3778 3779 void MipsAssembler::Call(MipsLabel* label) { 3780 uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved; 3781 branches_.emplace_back(IsR6(), buffer_.Size(), target, /* is_call */ true); 3782 MoveInstructionToDelaySlot(branches_.back()); 3783 FinalizeLabeledBranch(label); 3784 } 3785 3786 void MipsAssembler::LoadLabelAddress(Register dest_reg, Register base_reg, MipsLabel* label) { 3787 // Label address loads are treated as pseudo branches since they require very similar handling. 3788 DCHECK(!label->IsBound()); 3789 branches_.emplace_back(IsR6(), buffer_.Size(), dest_reg, base_reg, Branch::kLabel); 3790 FinalizeLabeledBranch(label); 3791 } 3792 3793 Literal* MipsAssembler::NewLiteral(size_t size, const uint8_t* data) { 3794 DCHECK(size == 4u || size == 8u) << size; 3795 literals_.emplace_back(size, data); 3796 return &literals_.back(); 3797 } 3798 3799 void MipsAssembler::LoadLiteral(Register dest_reg, Register base_reg, Literal* literal) { 3800 // Literal loads are treated as pseudo branches since they require very similar handling. 3801 DCHECK_EQ(literal->GetSize(), 4u); 3802 MipsLabel* label = literal->GetLabel(); 3803 DCHECK(!label->IsBound()); 3804 branches_.emplace_back(IsR6(), buffer_.Size(), dest_reg, base_reg, Branch::kLiteral); 3805 FinalizeLabeledBranch(label); 3806 } 3807 3808 JumpTable* MipsAssembler::CreateJumpTable(std::vector<MipsLabel*>&& labels) { 3809 jump_tables_.emplace_back(std::move(labels)); 3810 JumpTable* table = &jump_tables_.back(); 3811 DCHECK(!table->GetLabel()->IsBound()); 3812 return table; 3813 } 3814 3815 void MipsAssembler::EmitLiterals() { 3816 if (!literals_.empty()) { 3817 // We don't support byte and half-word literals. 3818 // TODO: proper alignment for 64-bit literals when they're implemented. 3819 for (Literal& literal : literals_) { 3820 MipsLabel* label = literal.GetLabel(); 3821 Bind(label); 3822 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 3823 DCHECK(literal.GetSize() == 4u || literal.GetSize() == 8u); 3824 for (size_t i = 0, size = literal.GetSize(); i != size; ++i) { 3825 buffer_.Emit<uint8_t>(literal.GetData()[i]); 3826 } 3827 } 3828 } 3829 } 3830 3831 void MipsAssembler::ReserveJumpTableSpace() { 3832 if (!jump_tables_.empty()) { 3833 for (JumpTable& table : jump_tables_) { 3834 MipsLabel* label = table.GetLabel(); 3835 Bind(label); 3836 3837 // Bulk ensure capacity, as this may be large. 3838 size_t orig_size = buffer_.Size(); 3839 size_t required_capacity = orig_size + table.GetSize(); 3840 if (required_capacity > buffer_.Capacity()) { 3841 buffer_.ExtendCapacity(required_capacity); 3842 } 3843 #ifndef NDEBUG 3844 buffer_.has_ensured_capacity_ = true; 3845 #endif 3846 3847 // Fill the space with dummy data as the data is not final 3848 // until the branches have been promoted. And we shouldn't 3849 // be moving uninitialized data during branch promotion. 3850 for (size_t cnt = table.GetData().size(), i = 0; i < cnt; i++) { 3851 buffer_.Emit<uint32_t>(0x1abe1234u); 3852 } 3853 3854 #ifndef NDEBUG 3855 buffer_.has_ensured_capacity_ = false; 3856 #endif 3857 } 3858 } 3859 } 3860 3861 void MipsAssembler::EmitJumpTables() { 3862 if (!jump_tables_.empty()) { 3863 CHECK(!overwriting_); 3864 // Switch from appending instructions at the end of the buffer to overwriting 3865 // existing instructions (here, jump tables) in the buffer. 3866 overwriting_ = true; 3867 3868 for (JumpTable& table : jump_tables_) { 3869 MipsLabel* table_label = table.GetLabel(); 3870 uint32_t start = GetLabelLocation(table_label); 3871 overwrite_location_ = start; 3872 3873 for (MipsLabel* target : table.GetData()) { 3874 CHECK_EQ(buffer_.Load<uint32_t>(overwrite_location_), 0x1abe1234u); 3875 // The table will contain target addresses relative to the table start. 3876 uint32_t offset = GetLabelLocation(target) - start; 3877 Emit(offset); 3878 } 3879 } 3880 3881 overwriting_ = false; 3882 } 3883 } 3884 3885 void MipsAssembler::PromoteBranches() { 3886 // Promote short branches to long as necessary. 3887 bool changed; 3888 do { 3889 changed = false; 3890 for (auto& branch : branches_) { 3891 CHECK(branch.IsResolved()); 3892 uint32_t base = GetBranchLocationOrPcRelBase(&branch); 3893 uint32_t delta = branch.PromoteIfNeeded(base); 3894 // If this branch has been promoted and needs to expand in size, 3895 // relocate all branches by the expansion size. 3896 if (delta) { 3897 changed = true; 3898 uint32_t expand_location = branch.GetLocation(); 3899 for (auto& branch2 : branches_) { 3900 branch2.Relocate(expand_location, delta); 3901 } 3902 } 3903 } 3904 } while (changed); 3905 3906 // Account for branch expansion by resizing the code buffer 3907 // and moving the code in it to its final location. 3908 size_t branch_count = branches_.size(); 3909 if (branch_count > 0) { 3910 // Resize. 3911 Branch& last_branch = branches_[branch_count - 1]; 3912 uint32_t size_delta = last_branch.GetEndLocation() - last_branch.GetOldEndLocation(); 3913 uint32_t old_size = buffer_.Size(); 3914 buffer_.Resize(old_size + size_delta); 3915 // Move the code residing between branch placeholders. 3916 uint32_t end = old_size; 3917 for (size_t i = branch_count; i > 0; ) { 3918 Branch& branch = branches_[--i]; 3919 CHECK_GE(end, branch.GetOldEndLocation()); 3920 uint32_t size = end - branch.GetOldEndLocation(); 3921 buffer_.Move(branch.GetEndLocation(), branch.GetOldEndLocation(), size); 3922 end = branch.GetOldLocation(); 3923 } 3924 } 3925 } 3926 3927 // Note: make sure branch_info_[] and EmitBranch() are kept synchronized. 3928 const MipsAssembler::Branch::BranchInfo MipsAssembler::Branch::branch_info_[] = { 3929 // R2 short branches. 3930 { 2, 0, 1, MipsAssembler::Branch::kOffset18, 2 }, // kUncondBranch 3931 { 2, 0, 1, MipsAssembler::Branch::kOffset18, 2 }, // kCondBranch 3932 { 2, 0, 1, MipsAssembler::Branch::kOffset18, 2 }, // kCall 3933 // R2 near label. 3934 { 1, 0, 0, MipsAssembler::Branch::kOffset16, 0 }, // kLabel 3935 // R2 near literal. 3936 { 1, 0, 0, MipsAssembler::Branch::kOffset16, 0 }, // kLiteral 3937 // R2 long branches. 3938 { 9, 3, 1, MipsAssembler::Branch::kOffset32, 0 }, // kLongUncondBranch 3939 { 10, 4, 1, MipsAssembler::Branch::kOffset32, 0 }, // kLongCondBranch 3940 { 6, 1, 1, MipsAssembler::Branch::kOffset32, 0 }, // kLongCall 3941 // R2 far label. 3942 { 3, 0, 0, MipsAssembler::Branch::kOffset32, 0 }, // kFarLabel 3943 // R2 far literal. 3944 { 3, 0, 0, MipsAssembler::Branch::kOffset32, 0 }, // kFarLiteral 3945 // R6 short branches. 3946 { 1, 0, 1, MipsAssembler::Branch::kOffset28, 2 }, // kR6UncondBranch 3947 { 2, 0, 1, MipsAssembler::Branch::kOffset18, 2 }, // kR6CondBranch 3948 // Exception: kOffset23 for beqzc/bnezc. 3949 { 1, 0, 1, MipsAssembler::Branch::kOffset28, 2 }, // kR6Call 3950 // R6 near label. 3951 { 1, 0, 0, MipsAssembler::Branch::kOffset21, 2 }, // kR6Label 3952 // R6 near literal. 3953 { 1, 0, 0, MipsAssembler::Branch::kOffset21, 2 }, // kR6Literal 3954 // R6 long branches. 3955 { 2, 0, 0, MipsAssembler::Branch::kOffset32, 0 }, // kR6LongUncondBranch 3956 { 3, 1, 0, MipsAssembler::Branch::kOffset32, 0 }, // kR6LongCondBranch 3957 { 2, 0, 0, MipsAssembler::Branch::kOffset32, 0 }, // kR6LongCall 3958 // R6 far label. 3959 { 2, 0, 0, MipsAssembler::Branch::kOffset32, 0 }, // kR6FarLabel 3960 // R6 far literal. 3961 { 2, 0, 0, MipsAssembler::Branch::kOffset32, 0 }, // kR6FarLiteral 3962 }; 3963 3964 // Note: make sure branch_info_[] and EmitBranch() are kept synchronized. 3965 void MipsAssembler::EmitBranch(MipsAssembler::Branch* branch) { 3966 CHECK_EQ(overwriting_, true); 3967 overwrite_location_ = branch->GetLocation(); 3968 uint32_t offset = branch->GetOffset(GetBranchOrPcRelBaseForEncoding(branch)); 3969 BranchCondition condition = branch->GetCondition(); 3970 Register lhs = branch->GetLeftRegister(); 3971 Register rhs = branch->GetRightRegister(); 3972 uint32_t delayed_instruction = branch->GetDelayedInstruction(); 3973 switch (branch->GetType()) { 3974 // R2 short branches. 3975 case Branch::kUncondBranch: 3976 if (delayed_instruction == Branch::kUnfillableDelaySlot) { 3977 // The branch was created when reordering was disabled, do not absorb the target 3978 // instruction. 3979 delayed_instruction = 0; // NOP. 3980 } else if (delayed_instruction == Branch::kUnfilledDelaySlot) { 3981 // Try to absorb the target instruction into the delay slot. 3982 delayed_instruction = 0; // NOP. 3983 // Incrementing the signed 16-bit offset past the target instruction must not 3984 // cause overflow into the negative subrange, check for the max offset. 3985 if (offset != 0x7FFF) { 3986 uint32_t target = branch->GetTarget(); 3987 if (std::binary_search(ds_fsm_target_pcs_.begin(), ds_fsm_target_pcs_.end(), target)) { 3988 delayed_instruction = buffer_.Load<uint32_t>(target); 3989 offset++; 3990 } 3991 } 3992 } 3993 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 3994 B(offset); 3995 Emit(delayed_instruction); 3996 break; 3997 case Branch::kCondBranch: 3998 DCHECK_NE(delayed_instruction, Branch::kUnfillableDelaySlot); 3999 if (delayed_instruction == Branch::kUnfilledDelaySlot) { 4000 delayed_instruction = 0; // NOP. 4001 } 4002 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 4003 EmitBcondR2(condition, lhs, rhs, offset); 4004 Emit(delayed_instruction); 4005 break; 4006 case Branch::kCall: 4007 DCHECK_NE(delayed_instruction, Branch::kUnfillableDelaySlot); 4008 if (delayed_instruction == Branch::kUnfilledDelaySlot) { 4009 delayed_instruction = 0; // NOP. 4010 } 4011 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 4012 Bal(offset); 4013 Emit(delayed_instruction); 4014 break; 4015 4016 // R2 near label. 4017 case Branch::kLabel: 4018 DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot); 4019 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 4020 Addiu(lhs, rhs, offset); 4021 break; 4022 // R2 near literal. 4023 case Branch::kLiteral: 4024 DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot); 4025 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 4026 Lw(lhs, rhs, offset); 4027 break; 4028 4029 // R2 long branches. 4030 case Branch::kLongUncondBranch: 4031 // To get the value of the PC register we need to use the NAL instruction. 4032 // NAL clobbers the RA register. However, RA must be preserved if the 4033 // method is compiled without the entry/exit sequences that would take care 4034 // of preserving RA (typically, leaf methods don't preserve RA explicitly). 4035 // So, we need to preserve RA in some temporary storage ourselves. The AT 4036 // register can't be used for this because we need it to load a constant 4037 // which will be added to the value that NAL stores in RA. And we can't 4038 // use T9 for this in the context of the JNI compiler, which uses it 4039 // as a scratch register (see InterproceduralScratchRegister()). 4040 // If we were to add a 32-bit constant to RA using two ADDIU instructions, 4041 // we'd also need to use the ROTR instruction, which requires no less than 4042 // MIPSR2. 4043 // Perhaps, we could use T8 or one of R2's multiplier/divider registers 4044 // (LO or HI) or even a floating-point register, but that doesn't seem 4045 // like a nice solution. We may want this to work on both R6 and pre-R6. 4046 // For now simply use the stack for RA. This should be OK since for the 4047 // vast majority of code a short PC-relative branch is sufficient. 4048 // TODO: can this be improved? 4049 // TODO: consider generation of a shorter sequence when we know that RA 4050 // is explicitly preserved by the method entry/exit code. 4051 if (delayed_instruction != Branch::kUnfilledDelaySlot && 4052 delayed_instruction != Branch::kUnfillableDelaySlot) { 4053 Emit(delayed_instruction); 4054 } 4055 Push(RA); 4056 Nal(); 4057 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 4058 Lui(AT, High16Bits(offset)); 4059 Ori(AT, AT, Low16Bits(offset)); 4060 Addu(AT, AT, RA); 4061 Lw(RA, SP, 0); 4062 Jr(AT); 4063 DecreaseFrameSize(kMipsWordSize); 4064 break; 4065 case Branch::kLongCondBranch: 4066 // The comment on case 'Branch::kLongUncondBranch' applies here as well. 4067 DCHECK_NE(delayed_instruction, Branch::kUnfillableDelaySlot); 4068 if (delayed_instruction != Branch::kUnfilledDelaySlot) { 4069 Emit(delayed_instruction); 4070 } 4071 // Note: the opposite condition branch encodes 8 as the distance, which is equal to the 4072 // number of instructions skipped: 4073 // (PUSH(IncreaseFrameSize(ADDIU) + SW) + NAL + LUI + ORI + ADDU + LW + JR). 4074 EmitBcondR2(Branch::OppositeCondition(condition), lhs, rhs, 8); 4075 Push(RA); 4076 Nal(); 4077 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 4078 Lui(AT, High16Bits(offset)); 4079 Ori(AT, AT, Low16Bits(offset)); 4080 Addu(AT, AT, RA); 4081 Lw(RA, SP, 0); 4082 Jr(AT); 4083 DecreaseFrameSize(kMipsWordSize); 4084 break; 4085 case Branch::kLongCall: 4086 DCHECK_NE(delayed_instruction, Branch::kUnfillableDelaySlot); 4087 if (delayed_instruction != Branch::kUnfilledDelaySlot) { 4088 Emit(delayed_instruction); 4089 } 4090 Nal(); 4091 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 4092 Lui(AT, High16Bits(offset)); 4093 Ori(AT, AT, Low16Bits(offset)); 4094 Addu(AT, AT, RA); 4095 Jalr(AT); 4096 Nop(); 4097 break; 4098 4099 // R2 far label. 4100 case Branch::kFarLabel: 4101 DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot); 4102 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 4103 Lui(AT, High16Bits(offset)); 4104 Ori(AT, AT, Low16Bits(offset)); 4105 Addu(lhs, AT, rhs); 4106 break; 4107 // R2 far literal. 4108 case Branch::kFarLiteral: 4109 DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot); 4110 offset += (offset & 0x8000) << 1; // Account for sign extension in lw. 4111 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 4112 Lui(AT, High16Bits(offset)); 4113 Addu(AT, AT, rhs); 4114 Lw(lhs, AT, Low16Bits(offset)); 4115 break; 4116 4117 // R6 short branches. 4118 case Branch::kR6UncondBranch: 4119 DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot); 4120 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 4121 Bc(offset); 4122 break; 4123 case Branch::kR6CondBranch: 4124 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 4125 EmitBcondR6(condition, lhs, rhs, offset); 4126 DCHECK_NE(delayed_instruction, Branch::kUnfillableDelaySlot); 4127 if (delayed_instruction != Branch::kUnfilledDelaySlot) { 4128 Emit(delayed_instruction); 4129 } else { 4130 // TODO: improve by filling the forbidden slot (IFF this is 4131 // a forbidden and not a delay slot). 4132 Nop(); 4133 } 4134 break; 4135 case Branch::kR6Call: 4136 DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot); 4137 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 4138 Balc(offset); 4139 break; 4140 4141 // R6 near label. 4142 case Branch::kR6Label: 4143 DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot); 4144 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 4145 Addiupc(lhs, offset); 4146 break; 4147 // R6 near literal. 4148 case Branch::kR6Literal: 4149 DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot); 4150 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 4151 Lwpc(lhs, offset); 4152 break; 4153 4154 // R6 long branches. 4155 case Branch::kR6LongUncondBranch: 4156 DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot); 4157 offset += (offset & 0x8000) << 1; // Account for sign extension in jic. 4158 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 4159 Auipc(AT, High16Bits(offset)); 4160 Jic(AT, Low16Bits(offset)); 4161 break; 4162 case Branch::kR6LongCondBranch: 4163 DCHECK_NE(delayed_instruction, Branch::kUnfillableDelaySlot); 4164 if (delayed_instruction != Branch::kUnfilledDelaySlot) { 4165 Emit(delayed_instruction); 4166 } 4167 EmitBcondR6(Branch::OppositeCondition(condition), lhs, rhs, 2); 4168 offset += (offset & 0x8000) << 1; // Account for sign extension in jic. 4169 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 4170 Auipc(AT, High16Bits(offset)); 4171 Jic(AT, Low16Bits(offset)); 4172 break; 4173 case Branch::kR6LongCall: 4174 DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot); 4175 offset += (offset & 0x8000) << 1; // Account for sign extension in jialc. 4176 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 4177 Auipc(AT, High16Bits(offset)); 4178 Jialc(AT, Low16Bits(offset)); 4179 break; 4180 4181 // R6 far label. 4182 case Branch::kR6FarLabel: 4183 DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot); 4184 offset += (offset & 0x8000) << 1; // Account for sign extension in addiu. 4185 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 4186 Auipc(AT, High16Bits(offset)); 4187 Addiu(lhs, AT, Low16Bits(offset)); 4188 break; 4189 // R6 far literal. 4190 case Branch::kR6FarLiteral: 4191 DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot); 4192 offset += (offset & 0x8000) << 1; // Account for sign extension in lw. 4193 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 4194 Auipc(AT, High16Bits(offset)); 4195 Lw(lhs, AT, Low16Bits(offset)); 4196 break; 4197 } 4198 CHECK_EQ(overwrite_location_, branch->GetEndLocation()); 4199 CHECK_LT(branch->GetSize(), static_cast<uint32_t>(Branch::kMaxBranchSize)); 4200 } 4201 4202 void MipsAssembler::B(MipsLabel* label) { 4203 Buncond(label); 4204 } 4205 4206 void MipsAssembler::Bal(MipsLabel* label) { 4207 Call(label); 4208 } 4209 4210 void MipsAssembler::Beq(Register rs, Register rt, MipsLabel* label) { 4211 Bcond(label, kCondEQ, rs, rt); 4212 } 4213 4214 void MipsAssembler::Bne(Register rs, Register rt, MipsLabel* label) { 4215 Bcond(label, kCondNE, rs, rt); 4216 } 4217 4218 void MipsAssembler::Beqz(Register rt, MipsLabel* label) { 4219 Bcond(label, kCondEQZ, rt); 4220 } 4221 4222 void MipsAssembler::Bnez(Register rt, MipsLabel* label) { 4223 Bcond(label, kCondNEZ, rt); 4224 } 4225 4226 void MipsAssembler::Bltz(Register rt, MipsLabel* label) { 4227 Bcond(label, kCondLTZ, rt); 4228 } 4229 4230 void MipsAssembler::Bgez(Register rt, MipsLabel* label) { 4231 Bcond(label, kCondGEZ, rt); 4232 } 4233 4234 void MipsAssembler::Blez(Register rt, MipsLabel* label) { 4235 Bcond(label, kCondLEZ, rt); 4236 } 4237 4238 void MipsAssembler::Bgtz(Register rt, MipsLabel* label) { 4239 Bcond(label, kCondGTZ, rt); 4240 } 4241 4242 bool MipsAssembler::CanExchangeWithSlt(Register rs, Register rt) const { 4243 // If the instruction modifies AT, `rs` or `rt`, it can't be exchanged with the slt[u] 4244 // instruction because either slt[u] depends on `rs` or `rt` or the following 4245 // conditional branch depends on AT set by slt[u]. 4246 // Likewise, if the instruction depends on AT, it can't be exchanged with slt[u] 4247 // because slt[u] changes AT. 4248 return (delay_slot_.instruction_ != 0 && 4249 (delay_slot_.gpr_outs_mask_ & ((1u << AT) | (1u << rs) | (1u << rt))) == 0 && 4250 (delay_slot_.gpr_ins_mask_ & (1u << AT)) == 0); 4251 } 4252 4253 void MipsAssembler::ExchangeWithSlt(const DelaySlot& forwarded_slot) { 4254 // Exchange the last two instructions in the assembler buffer. 4255 size_t size = buffer_.Size(); 4256 CHECK_GE(size, 2 * sizeof(uint32_t)); 4257 size_t pos1 = size - 2 * sizeof(uint32_t); 4258 size_t pos2 = size - sizeof(uint32_t); 4259 uint32_t instr1 = buffer_.Load<uint32_t>(pos1); 4260 uint32_t instr2 = buffer_.Load<uint32_t>(pos2); 4261 CHECK_EQ(instr1, forwarded_slot.instruction_); 4262 CHECK_EQ(instr2, delay_slot_.instruction_); 4263 buffer_.Store<uint32_t>(pos1, instr2); 4264 buffer_.Store<uint32_t>(pos2, instr1); 4265 // Set the current delay slot information to that of the last instruction 4266 // in the buffer. 4267 delay_slot_ = forwarded_slot; 4268 } 4269 4270 void MipsAssembler::GenerateSltForCondBranch(bool unsigned_slt, Register rs, Register rt) { 4271 // If possible, exchange the slt[u] instruction with the preceding instruction, 4272 // so it can fill the delay slot. 4273 DelaySlot forwarded_slot = delay_slot_; 4274 bool exchange = CanExchangeWithSlt(rs, rt); 4275 if (exchange) { 4276 // The last instruction cannot be used in a different delay slot, 4277 // do not commit the label before it (if any). 4278 DsFsmDropLabel(); 4279 } 4280 if (unsigned_slt) { 4281 Sltu(AT, rs, rt); 4282 } else { 4283 Slt(AT, rs, rt); 4284 } 4285 if (exchange) { 4286 ExchangeWithSlt(forwarded_slot); 4287 } 4288 } 4289 4290 void MipsAssembler::Blt(Register rs, Register rt, MipsLabel* label) { 4291 if (IsR6()) { 4292 Bcond(label, kCondLT, rs, rt); 4293 } else if (!Branch::IsNop(kCondLT, rs, rt)) { 4294 // Synthesize the instruction (not available on R2). 4295 GenerateSltForCondBranch(/* unsigned_slt */ false, rs, rt); 4296 Bnez(AT, label); 4297 } 4298 } 4299 4300 void MipsAssembler::Bge(Register rs, Register rt, MipsLabel* label) { 4301 if (IsR6()) { 4302 Bcond(label, kCondGE, rs, rt); 4303 } else if (Branch::IsUncond(kCondGE, rs, rt)) { 4304 B(label); 4305 } else { 4306 // Synthesize the instruction (not available on R2). 4307 GenerateSltForCondBranch(/* unsigned_slt */ false, rs, rt); 4308 Beqz(AT, label); 4309 } 4310 } 4311 4312 void MipsAssembler::Bltu(Register rs, Register rt, MipsLabel* label) { 4313 if (IsR6()) { 4314 Bcond(label, kCondLTU, rs, rt); 4315 } else if (!Branch::IsNop(kCondLTU, rs, rt)) { 4316 // Synthesize the instruction (not available on R2). 4317 GenerateSltForCondBranch(/* unsigned_slt */ true, rs, rt); 4318 Bnez(AT, label); 4319 } 4320 } 4321 4322 void MipsAssembler::Bgeu(Register rs, Register rt, MipsLabel* label) { 4323 if (IsR6()) { 4324 Bcond(label, kCondGEU, rs, rt); 4325 } else if (Branch::IsUncond(kCondGEU, rs, rt)) { 4326 B(label); 4327 } else { 4328 // Synthesize the instruction (not available on R2). 4329 GenerateSltForCondBranch(/* unsigned_slt */ true, rs, rt); 4330 Beqz(AT, label); 4331 } 4332 } 4333 4334 void MipsAssembler::Bc1f(MipsLabel* label) { 4335 Bc1f(0, label); 4336 } 4337 4338 void MipsAssembler::Bc1f(int cc, MipsLabel* label) { 4339 CHECK(IsUint<3>(cc)) << cc; 4340 Bcond(label, kCondF, static_cast<Register>(cc), ZERO); 4341 } 4342 4343 void MipsAssembler::Bc1t(MipsLabel* label) { 4344 Bc1t(0, label); 4345 } 4346 4347 void MipsAssembler::Bc1t(int cc, MipsLabel* label) { 4348 CHECK(IsUint<3>(cc)) << cc; 4349 Bcond(label, kCondT, static_cast<Register>(cc), ZERO); 4350 } 4351 4352 void MipsAssembler::Bc1eqz(FRegister ft, MipsLabel* label) { 4353 Bcond(label, kCondF, static_cast<Register>(ft), ZERO); 4354 } 4355 4356 void MipsAssembler::Bc1nez(FRegister ft, MipsLabel* label) { 4357 Bcond(label, kCondT, static_cast<Register>(ft), ZERO); 4358 } 4359 4360 void MipsAssembler::AdjustBaseAndOffset(Register& base, 4361 int32_t& offset, 4362 bool is_doubleword, 4363 bool is_float) { 4364 // This method is used to adjust the base register and offset pair 4365 // for a load/store when the offset doesn't fit into int16_t. 4366 // It is assumed that `base + offset` is sufficiently aligned for memory 4367 // operands that are machine word in size or smaller. For doubleword-sized 4368 // operands it's assumed that `base` is a multiple of 8, while `offset` 4369 // may be a multiple of 4 (e.g. 4-byte-aligned long and double arguments 4370 // and spilled variables on the stack accessed relative to the stack 4371 // pointer register). 4372 // We preserve the "alignment" of `offset` by adjusting it by a multiple of 8. 4373 CHECK_NE(base, AT); // Must not overwrite the register `base` while loading `offset`. 4374 4375 bool doubleword_aligned = IsAligned<kMipsDoublewordSize>(offset); 4376 bool two_accesses = is_doubleword && (!is_float || !doubleword_aligned); 4377 4378 // IsInt<16> must be passed a signed value, hence the static cast below. 4379 if (IsInt<16>(offset) && 4380 (!two_accesses || IsInt<16>(static_cast<int32_t>(offset + kMipsWordSize)))) { 4381 // Nothing to do: `offset` (and, if needed, `offset + 4`) fits into int16_t. 4382 return; 4383 } 4384 4385 // Remember the "(mis)alignment" of `offset`, it will be checked at the end. 4386 uint32_t misalignment = offset & (kMipsDoublewordSize - 1); 4387 4388 // Do not load the whole 32-bit `offset` if it can be represented as 4389 // a sum of two 16-bit signed offsets. This can save an instruction or two. 4390 // To simplify matters, only do this for a symmetric range of offsets from 4391 // about -64KB to about +64KB, allowing further addition of 4 when accessing 4392 // 64-bit variables with two 32-bit accesses. 4393 constexpr int32_t kMinOffsetForSimpleAdjustment = 0x7ff8; // Max int16_t that's a multiple of 8. 4394 constexpr int32_t kMaxOffsetForSimpleAdjustment = 2 * kMinOffsetForSimpleAdjustment; 4395 if (0 <= offset && offset <= kMaxOffsetForSimpleAdjustment) { 4396 Addiu(AT, base, kMinOffsetForSimpleAdjustment); 4397 offset -= kMinOffsetForSimpleAdjustment; 4398 } else if (-kMaxOffsetForSimpleAdjustment <= offset && offset < 0) { 4399 Addiu(AT, base, -kMinOffsetForSimpleAdjustment); 4400 offset += kMinOffsetForSimpleAdjustment; 4401 } else if (IsR6()) { 4402 // On R6 take advantage of the aui instruction, e.g.: 4403 // aui AT, base, offset_high 4404 // lw reg_lo, offset_low(AT) 4405 // lw reg_hi, (offset_low+4)(AT) 4406 // or when offset_low+4 overflows int16_t: 4407 // aui AT, base, offset_high 4408 // addiu AT, AT, 8 4409 // lw reg_lo, (offset_low-8)(AT) 4410 // lw reg_hi, (offset_low-4)(AT) 4411 int16_t offset_high = High16Bits(offset); 4412 int16_t offset_low = Low16Bits(offset); 4413 offset_high += (offset_low < 0) ? 1 : 0; // Account for offset sign extension in load/store. 4414 Aui(AT, base, offset_high); 4415 if (two_accesses && !IsInt<16>(static_cast<int32_t>(offset_low + kMipsWordSize))) { 4416 // Avoid overflow in the 16-bit offset of the load/store instruction when adding 4. 4417 Addiu(AT, AT, kMipsDoublewordSize); 4418 offset_low -= kMipsDoublewordSize; 4419 } 4420 offset = offset_low; 4421 } else { 4422 // Do not load the whole 32-bit `offset` if it can be represented as 4423 // a sum of three 16-bit signed offsets. This can save an instruction. 4424 // To simplify matters, only do this for a symmetric range of offsets from 4425 // about -96KB to about +96KB, allowing further addition of 4 when accessing 4426 // 64-bit variables with two 32-bit accesses. 4427 constexpr int32_t kMinOffsetForMediumAdjustment = 2 * kMinOffsetForSimpleAdjustment; 4428 constexpr int32_t kMaxOffsetForMediumAdjustment = 3 * kMinOffsetForSimpleAdjustment; 4429 if (0 <= offset && offset <= kMaxOffsetForMediumAdjustment) { 4430 Addiu(AT, base, kMinOffsetForMediumAdjustment / 2); 4431 Addiu(AT, AT, kMinOffsetForMediumAdjustment / 2); 4432 offset -= kMinOffsetForMediumAdjustment; 4433 } else if (-kMaxOffsetForMediumAdjustment <= offset && offset < 0) { 4434 Addiu(AT, base, -kMinOffsetForMediumAdjustment / 2); 4435 Addiu(AT, AT, -kMinOffsetForMediumAdjustment / 2); 4436 offset += kMinOffsetForMediumAdjustment; 4437 } else { 4438 // Now that all shorter options have been exhausted, load the full 32-bit offset. 4439 int32_t loaded_offset = RoundDown(offset, kMipsDoublewordSize); 4440 LoadConst32(AT, loaded_offset); 4441 Addu(AT, AT, base); 4442 offset -= loaded_offset; 4443 } 4444 } 4445 base = AT; 4446 4447 CHECK(IsInt<16>(offset)); 4448 if (two_accesses) { 4449 CHECK(IsInt<16>(static_cast<int32_t>(offset + kMipsWordSize))); 4450 } 4451 CHECK_EQ(misalignment, offset & (kMipsDoublewordSize - 1)); 4452 } 4453 4454 void MipsAssembler::AdjustBaseOffsetAndElementSizeShift(Register& base, 4455 int32_t& offset, 4456 int& element_size_shift) { 4457 // This method is used to adjust the base register, offset and element_size_shift 4458 // for a vector load/store when the offset doesn't fit into allowed number of bits. 4459 // MSA ld.df and st.df instructions take signed offsets as arguments, but maximum 4460 // offset is dependant on the size of the data format df (10-bit offsets for ld.b, 4461 // 11-bit for ld.h, 12-bit for ld.w and 13-bit for ld.d). 4462 // If element_size_shift is non-negative at entry, it won't be changed, but offset 4463 // will be checked for appropriate alignment. If negative at entry, it will be 4464 // adjusted based on offset for maximum fit. 4465 // It's assumed that `base` is a multiple of 8. 4466 CHECK_NE(base, AT); // Must not overwrite the register `base` while loading `offset`. 4467 4468 if (element_size_shift >= 0) { 4469 CHECK_LE(element_size_shift, TIMES_8); 4470 CHECK_GE(JAVASTYLE_CTZ(offset), element_size_shift); 4471 } else if (IsAligned<kMipsDoublewordSize>(offset)) { 4472 element_size_shift = TIMES_8; 4473 } else if (IsAligned<kMipsWordSize>(offset)) { 4474 element_size_shift = TIMES_4; 4475 } else if (IsAligned<kMipsHalfwordSize>(offset)) { 4476 element_size_shift = TIMES_2; 4477 } else { 4478 element_size_shift = TIMES_1; 4479 } 4480 4481 const int low_len = 10 + element_size_shift; // How many low bits of `offset` ld.df/st.df 4482 // will take. 4483 int16_t low = offset & ((1 << low_len) - 1); // Isolate these bits. 4484 low -= (low & (1 << (low_len - 1))) << 1; // Sign-extend these bits. 4485 if (low == offset) { 4486 return; // `offset` fits into ld.df/st.df. 4487 } 4488 4489 // First, see if `offset` can be represented as a sum of two or three signed offsets. 4490 // This can save an instruction or two. 4491 4492 // Max int16_t that's a multiple of element size. 4493 const int32_t kMaxDeltaForSimpleAdjustment = 0x8000 - (1 << element_size_shift); 4494 // Max ld.df/st.df offset that's a multiple of element size. 4495 const int32_t kMaxLoadStoreOffset = 0x1ff << element_size_shift; 4496 const int32_t kMaxOffsetForSimpleAdjustment = kMaxDeltaForSimpleAdjustment + kMaxLoadStoreOffset; 4497 const int32_t kMinOffsetForMediumAdjustment = 2 * kMaxDeltaForSimpleAdjustment; 4498 const int32_t kMaxOffsetForMediumAdjustment = kMinOffsetForMediumAdjustment + kMaxLoadStoreOffset; 4499 4500 if (IsInt<16>(offset)) { 4501 Addiu(AT, base, offset); 4502 offset = 0; 4503 } else if (0 <= offset && offset <= kMaxOffsetForSimpleAdjustment) { 4504 Addiu(AT, base, kMaxDeltaForSimpleAdjustment); 4505 offset -= kMaxDeltaForSimpleAdjustment; 4506 } else if (-kMaxOffsetForSimpleAdjustment <= offset && offset < 0) { 4507 Addiu(AT, base, -kMaxDeltaForSimpleAdjustment); 4508 offset += kMaxDeltaForSimpleAdjustment; 4509 } else if (!IsR6() && 0 <= offset && offset <= kMaxOffsetForMediumAdjustment) { 4510 Addiu(AT, base, kMaxDeltaForSimpleAdjustment); 4511 if (offset <= kMinOffsetForMediumAdjustment) { 4512 Addiu(AT, AT, offset - kMaxDeltaForSimpleAdjustment); 4513 offset = 0; 4514 } else { 4515 Addiu(AT, AT, kMaxDeltaForSimpleAdjustment); 4516 offset -= kMinOffsetForMediumAdjustment; 4517 } 4518 } else if (!IsR6() && -kMaxOffsetForMediumAdjustment <= offset && offset < 0) { 4519 Addiu(AT, base, -kMaxDeltaForSimpleAdjustment); 4520 if (-kMinOffsetForMediumAdjustment <= offset) { 4521 Addiu(AT, AT, offset + kMaxDeltaForSimpleAdjustment); 4522 offset = 0; 4523 } else { 4524 Addiu(AT, AT, -kMaxDeltaForSimpleAdjustment); 4525 offset += kMinOffsetForMediumAdjustment; 4526 } 4527 } else { 4528 // 16-bit or smaller parts of `offset`: 4529 // |31 hi 16|15 mid 13-10|12-9 low 0| 4530 // 4531 // Instructions that supply each part as a signed integer addend: 4532 // |aui |addiu |ld.df/st.df | 4533 uint32_t tmp = static_cast<uint32_t>(offset) - low; // Exclude `low` from the rest of `offset` 4534 // (accounts for sign of `low`). 4535 tmp += (tmp & (UINT32_C(1) << 15)) << 1; // Account for sign extension in addiu. 4536 int16_t mid = Low16Bits(tmp); 4537 int16_t hi = High16Bits(tmp); 4538 if (IsR6()) { 4539 Aui(AT, base, hi); 4540 } else { 4541 Lui(AT, hi); 4542 Addu(AT, AT, base); 4543 } 4544 if (mid != 0) { 4545 Addiu(AT, AT, mid); 4546 } 4547 offset = low; 4548 } 4549 base = AT; 4550 CHECK_GE(JAVASTYLE_CTZ(offset), element_size_shift); 4551 CHECK(IsInt<10>(offset >> element_size_shift)); 4552 } 4553 4554 void MipsAssembler::LoadFromOffset(LoadOperandType type, 4555 Register reg, 4556 Register base, 4557 int32_t offset) { 4558 LoadFromOffset<>(type, reg, base, offset); 4559 } 4560 4561 void MipsAssembler::LoadSFromOffset(FRegister reg, Register base, int32_t offset) { 4562 LoadSFromOffset<>(reg, base, offset); 4563 } 4564 4565 void MipsAssembler::LoadDFromOffset(FRegister reg, Register base, int32_t offset) { 4566 LoadDFromOffset<>(reg, base, offset); 4567 } 4568 4569 void MipsAssembler::LoadQFromOffset(FRegister reg, Register base, int32_t offset) { 4570 LoadQFromOffset<>(reg, base, offset); 4571 } 4572 4573 void MipsAssembler::EmitLoad(ManagedRegister m_dst, Register src_register, int32_t src_offset, 4574 size_t size) { 4575 MipsManagedRegister dst = m_dst.AsMips(); 4576 if (dst.IsNoRegister()) { 4577 CHECK_EQ(0u, size) << dst; 4578 } else if (dst.IsCoreRegister()) { 4579 CHECK_EQ(kMipsWordSize, size) << dst; 4580 LoadFromOffset(kLoadWord, dst.AsCoreRegister(), src_register, src_offset); 4581 } else if (dst.IsRegisterPair()) { 4582 CHECK_EQ(kMipsDoublewordSize, size) << dst; 4583 LoadFromOffset(kLoadDoubleword, dst.AsRegisterPairLow(), src_register, src_offset); 4584 } else if (dst.IsFRegister()) { 4585 if (size == kMipsWordSize) { 4586 LoadSFromOffset(dst.AsFRegister(), src_register, src_offset); 4587 } else { 4588 CHECK_EQ(kMipsDoublewordSize, size) << dst; 4589 LoadDFromOffset(dst.AsFRegister(), src_register, src_offset); 4590 } 4591 } else if (dst.IsDRegister()) { 4592 CHECK_EQ(kMipsDoublewordSize, size) << dst; 4593 LoadDFromOffset(dst.AsOverlappingDRegisterLow(), src_register, src_offset); 4594 } 4595 } 4596 4597 void MipsAssembler::StoreToOffset(StoreOperandType type, 4598 Register reg, 4599 Register base, 4600 int32_t offset) { 4601 StoreToOffset<>(type, reg, base, offset); 4602 } 4603 4604 void MipsAssembler::StoreSToOffset(FRegister reg, Register base, int32_t offset) { 4605 StoreSToOffset<>(reg, base, offset); 4606 } 4607 4608 void MipsAssembler::StoreDToOffset(FRegister reg, Register base, int32_t offset) { 4609 StoreDToOffset<>(reg, base, offset); 4610 } 4611 4612 void MipsAssembler::StoreQToOffset(FRegister reg, Register base, int32_t offset) { 4613 StoreQToOffset<>(reg, base, offset); 4614 } 4615 4616 static dwarf::Reg DWARFReg(Register reg) { 4617 return dwarf::Reg::MipsCore(static_cast<int>(reg)); 4618 } 4619 4620 constexpr size_t kFramePointerSize = 4; 4621 4622 void MipsAssembler::BuildFrame(size_t frame_size, 4623 ManagedRegister method_reg, 4624 ArrayRef<const ManagedRegister> callee_save_regs, 4625 const ManagedRegisterEntrySpills& entry_spills) { 4626 CHECK_ALIGNED(frame_size, kStackAlignment); 4627 DCHECK(!overwriting_); 4628 4629 // Increase frame to required size. 4630 IncreaseFrameSize(frame_size); 4631 4632 // Push callee saves and return address. 4633 int stack_offset = frame_size - kFramePointerSize; 4634 StoreToOffset(kStoreWord, RA, SP, stack_offset); 4635 cfi_.RelOffset(DWARFReg(RA), stack_offset); 4636 for (int i = callee_save_regs.size() - 1; i >= 0; --i) { 4637 stack_offset -= kFramePointerSize; 4638 Register reg = callee_save_regs[i].AsMips().AsCoreRegister(); 4639 StoreToOffset(kStoreWord, reg, SP, stack_offset); 4640 cfi_.RelOffset(DWARFReg(reg), stack_offset); 4641 } 4642 4643 // Write out Method*. 4644 StoreToOffset(kStoreWord, method_reg.AsMips().AsCoreRegister(), SP, 0); 4645 4646 // Write out entry spills. 4647 int32_t offset = frame_size + kFramePointerSize; 4648 for (size_t i = 0; i < entry_spills.size(); ++i) { 4649 MipsManagedRegister reg = entry_spills.at(i).AsMips(); 4650 if (reg.IsNoRegister()) { 4651 ManagedRegisterSpill spill = entry_spills.at(i); 4652 offset += spill.getSize(); 4653 } else if (reg.IsCoreRegister()) { 4654 StoreToOffset(kStoreWord, reg.AsCoreRegister(), SP, offset); 4655 offset += kMipsWordSize; 4656 } else if (reg.IsFRegister()) { 4657 StoreSToOffset(reg.AsFRegister(), SP, offset); 4658 offset += kMipsWordSize; 4659 } else if (reg.IsDRegister()) { 4660 StoreDToOffset(reg.AsOverlappingDRegisterLow(), SP, offset); 4661 offset += kMipsDoublewordSize; 4662 } 4663 } 4664 } 4665 4666 void MipsAssembler::RemoveFrame(size_t frame_size, 4667 ArrayRef<const ManagedRegister> callee_save_regs) { 4668 CHECK_ALIGNED(frame_size, kStackAlignment); 4669 DCHECK(!overwriting_); 4670 cfi_.RememberState(); 4671 4672 // Pop callee saves and return address. 4673 int stack_offset = frame_size - (callee_save_regs.size() * kFramePointerSize) - kFramePointerSize; 4674 for (size_t i = 0; i < callee_save_regs.size(); ++i) { 4675 Register reg = callee_save_regs[i].AsMips().AsCoreRegister(); 4676 LoadFromOffset(kLoadWord, reg, SP, stack_offset); 4677 cfi_.Restore(DWARFReg(reg)); 4678 stack_offset += kFramePointerSize; 4679 } 4680 LoadFromOffset(kLoadWord, RA, SP, stack_offset); 4681 cfi_.Restore(DWARFReg(RA)); 4682 4683 // Adjust the stack pointer in the delay slot if doing so doesn't break CFI. 4684 bool exchange = IsInt<16>(static_cast<int32_t>(frame_size)); 4685 bool reordering = SetReorder(false); 4686 if (exchange) { 4687 // Jump to the return address. 4688 Jr(RA); 4689 // Decrease frame to required size. 4690 DecreaseFrameSize(frame_size); // Single instruction in delay slot. 4691 } else { 4692 // Decrease frame to required size. 4693 DecreaseFrameSize(frame_size); 4694 // Jump to the return address. 4695 Jr(RA); 4696 Nop(); // In delay slot. 4697 } 4698 SetReorder(reordering); 4699 4700 // The CFI should be restored for any code that follows the exit block. 4701 cfi_.RestoreState(); 4702 cfi_.DefCFAOffset(frame_size); 4703 } 4704 4705 void MipsAssembler::IncreaseFrameSize(size_t adjust) { 4706 CHECK_ALIGNED(adjust, kFramePointerSize); 4707 Addiu32(SP, SP, -adjust); 4708 cfi_.AdjustCFAOffset(adjust); 4709 if (overwriting_) { 4710 cfi_.OverrideDelayedPC(overwrite_location_); 4711 } 4712 } 4713 4714 void MipsAssembler::DecreaseFrameSize(size_t adjust) { 4715 CHECK_ALIGNED(adjust, kFramePointerSize); 4716 Addiu32(SP, SP, adjust); 4717 cfi_.AdjustCFAOffset(-adjust); 4718 if (overwriting_) { 4719 cfi_.OverrideDelayedPC(overwrite_location_); 4720 } 4721 } 4722 4723 void MipsAssembler::Store(FrameOffset dest, ManagedRegister msrc, size_t size) { 4724 MipsManagedRegister src = msrc.AsMips(); 4725 if (src.IsNoRegister()) { 4726 CHECK_EQ(0u, size); 4727 } else if (src.IsCoreRegister()) { 4728 CHECK_EQ(kMipsWordSize, size); 4729 StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value()); 4730 } else if (src.IsRegisterPair()) { 4731 CHECK_EQ(kMipsDoublewordSize, size); 4732 StoreToOffset(kStoreWord, src.AsRegisterPairLow(), SP, dest.Int32Value()); 4733 StoreToOffset(kStoreWord, src.AsRegisterPairHigh(), 4734 SP, dest.Int32Value() + kMipsWordSize); 4735 } else if (src.IsFRegister()) { 4736 if (size == kMipsWordSize) { 4737 StoreSToOffset(src.AsFRegister(), SP, dest.Int32Value()); 4738 } else { 4739 CHECK_EQ(kMipsDoublewordSize, size); 4740 StoreDToOffset(src.AsFRegister(), SP, dest.Int32Value()); 4741 } 4742 } else if (src.IsDRegister()) { 4743 CHECK_EQ(kMipsDoublewordSize, size); 4744 StoreDToOffset(src.AsOverlappingDRegisterLow(), SP, dest.Int32Value()); 4745 } 4746 } 4747 4748 void MipsAssembler::StoreRef(FrameOffset dest, ManagedRegister msrc) { 4749 MipsManagedRegister src = msrc.AsMips(); 4750 CHECK(src.IsCoreRegister()); 4751 StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value()); 4752 } 4753 4754 void MipsAssembler::StoreRawPtr(FrameOffset dest, ManagedRegister msrc) { 4755 MipsManagedRegister src = msrc.AsMips(); 4756 CHECK(src.IsCoreRegister()); 4757 StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value()); 4758 } 4759 4760 void MipsAssembler::StoreImmediateToFrame(FrameOffset dest, uint32_t imm, 4761 ManagedRegister mscratch) { 4762 MipsManagedRegister scratch = mscratch.AsMips(); 4763 CHECK(scratch.IsCoreRegister()) << scratch; 4764 LoadConst32(scratch.AsCoreRegister(), imm); 4765 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value()); 4766 } 4767 4768 void MipsAssembler::StoreStackOffsetToThread(ThreadOffset32 thr_offs, 4769 FrameOffset fr_offs, 4770 ManagedRegister mscratch) { 4771 MipsManagedRegister scratch = mscratch.AsMips(); 4772 CHECK(scratch.IsCoreRegister()) << scratch; 4773 Addiu32(scratch.AsCoreRegister(), SP, fr_offs.Int32Value()); 4774 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), 4775 S1, thr_offs.Int32Value()); 4776 } 4777 4778 void MipsAssembler::StoreStackPointerToThread(ThreadOffset32 thr_offs) { 4779 StoreToOffset(kStoreWord, SP, S1, thr_offs.Int32Value()); 4780 } 4781 4782 void MipsAssembler::StoreSpanning(FrameOffset dest, ManagedRegister msrc, 4783 FrameOffset in_off, ManagedRegister mscratch) { 4784 MipsManagedRegister src = msrc.AsMips(); 4785 MipsManagedRegister scratch = mscratch.AsMips(); 4786 StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value()); 4787 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, in_off.Int32Value()); 4788 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value() + kMipsWordSize); 4789 } 4790 4791 void MipsAssembler::Load(ManagedRegister mdest, FrameOffset src, size_t size) { 4792 return EmitLoad(mdest, SP, src.Int32Value(), size); 4793 } 4794 4795 void MipsAssembler::LoadFromThread(ManagedRegister mdest, ThreadOffset32 src, size_t size) { 4796 return EmitLoad(mdest, S1, src.Int32Value(), size); 4797 } 4798 4799 void MipsAssembler::LoadRef(ManagedRegister mdest, FrameOffset src) { 4800 MipsManagedRegister dest = mdest.AsMips(); 4801 CHECK(dest.IsCoreRegister()); 4802 LoadFromOffset(kLoadWord, dest.AsCoreRegister(), SP, src.Int32Value()); 4803 } 4804 4805 void MipsAssembler::LoadRef(ManagedRegister mdest, ManagedRegister base, MemberOffset offs, 4806 bool unpoison_reference) { 4807 MipsManagedRegister dest = mdest.AsMips(); 4808 CHECK(dest.IsCoreRegister() && base.AsMips().IsCoreRegister()); 4809 LoadFromOffset(kLoadWord, dest.AsCoreRegister(), 4810 base.AsMips().AsCoreRegister(), offs.Int32Value()); 4811 if (unpoison_reference) { 4812 MaybeUnpoisonHeapReference(dest.AsCoreRegister()); 4813 } 4814 } 4815 4816 void MipsAssembler::LoadRawPtr(ManagedRegister mdest, ManagedRegister base, Offset offs) { 4817 MipsManagedRegister dest = mdest.AsMips(); 4818 CHECK(dest.IsCoreRegister() && base.AsMips().IsCoreRegister()); 4819 LoadFromOffset(kLoadWord, dest.AsCoreRegister(), 4820 base.AsMips().AsCoreRegister(), offs.Int32Value()); 4821 } 4822 4823 void MipsAssembler::LoadRawPtrFromThread(ManagedRegister mdest, ThreadOffset32 offs) { 4824 MipsManagedRegister dest = mdest.AsMips(); 4825 CHECK(dest.IsCoreRegister()); 4826 LoadFromOffset(kLoadWord, dest.AsCoreRegister(), S1, offs.Int32Value()); 4827 } 4828 4829 void MipsAssembler::SignExtend(ManagedRegister /*mreg*/, size_t /*size*/) { 4830 UNIMPLEMENTED(FATAL) << "no sign extension necessary for mips"; 4831 } 4832 4833 void MipsAssembler::ZeroExtend(ManagedRegister /*mreg*/, size_t /*size*/) { 4834 UNIMPLEMENTED(FATAL) << "no zero extension necessary for mips"; 4835 } 4836 4837 void MipsAssembler::Move(ManagedRegister mdest, ManagedRegister msrc, size_t size) { 4838 MipsManagedRegister dest = mdest.AsMips(); 4839 MipsManagedRegister src = msrc.AsMips(); 4840 if (!dest.Equals(src)) { 4841 if (dest.IsCoreRegister()) { 4842 CHECK(src.IsCoreRegister()) << src; 4843 Move(dest.AsCoreRegister(), src.AsCoreRegister()); 4844 } else if (dest.IsFRegister()) { 4845 CHECK(src.IsFRegister()) << src; 4846 if (size == kMipsWordSize) { 4847 MovS(dest.AsFRegister(), src.AsFRegister()); 4848 } else { 4849 CHECK_EQ(kMipsDoublewordSize, size); 4850 MovD(dest.AsFRegister(), src.AsFRegister()); 4851 } 4852 } else if (dest.IsDRegister()) { 4853 CHECK(src.IsDRegister()) << src; 4854 MovD(dest.AsOverlappingDRegisterLow(), src.AsOverlappingDRegisterLow()); 4855 } else { 4856 CHECK(dest.IsRegisterPair()) << dest; 4857 CHECK(src.IsRegisterPair()) << src; 4858 // Ensure that the first move doesn't clobber the input of the second. 4859 if (src.AsRegisterPairHigh() != dest.AsRegisterPairLow()) { 4860 Move(dest.AsRegisterPairLow(), src.AsRegisterPairLow()); 4861 Move(dest.AsRegisterPairHigh(), src.AsRegisterPairHigh()); 4862 } else { 4863 Move(dest.AsRegisterPairHigh(), src.AsRegisterPairHigh()); 4864 Move(dest.AsRegisterPairLow(), src.AsRegisterPairLow()); 4865 } 4866 } 4867 } 4868 } 4869 4870 void MipsAssembler::CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister mscratch) { 4871 MipsManagedRegister scratch = mscratch.AsMips(); 4872 CHECK(scratch.IsCoreRegister()) << scratch; 4873 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value()); 4874 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value()); 4875 } 4876 4877 void MipsAssembler::CopyRawPtrFromThread(FrameOffset fr_offs, 4878 ThreadOffset32 thr_offs, 4879 ManagedRegister mscratch) { 4880 MipsManagedRegister scratch = mscratch.AsMips(); 4881 CHECK(scratch.IsCoreRegister()) << scratch; 4882 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), 4883 S1, thr_offs.Int32Value()); 4884 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), 4885 SP, fr_offs.Int32Value()); 4886 } 4887 4888 void MipsAssembler::CopyRawPtrToThread(ThreadOffset32 thr_offs, 4889 FrameOffset fr_offs, 4890 ManagedRegister mscratch) { 4891 MipsManagedRegister scratch = mscratch.AsMips(); 4892 CHECK(scratch.IsCoreRegister()) << scratch; 4893 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), 4894 SP, fr_offs.Int32Value()); 4895 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), 4896 S1, thr_offs.Int32Value()); 4897 } 4898 4899 void MipsAssembler::Copy(FrameOffset dest, FrameOffset src, ManagedRegister mscratch, size_t size) { 4900 MipsManagedRegister scratch = mscratch.AsMips(); 4901 CHECK(scratch.IsCoreRegister()) << scratch; 4902 CHECK(size == kMipsWordSize || size == kMipsDoublewordSize) << size; 4903 if (size == kMipsWordSize) { 4904 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value()); 4905 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value()); 4906 } else if (size == kMipsDoublewordSize) { 4907 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value()); 4908 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value()); 4909 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value() + kMipsWordSize); 4910 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value() + kMipsWordSize); 4911 } 4912 } 4913 4914 void MipsAssembler::Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset, 4915 ManagedRegister mscratch, size_t size) { 4916 Register scratch = mscratch.AsMips().AsCoreRegister(); 4917 CHECK_EQ(size, kMipsWordSize); 4918 LoadFromOffset(kLoadWord, scratch, src_base.AsMips().AsCoreRegister(), src_offset.Int32Value()); 4919 StoreToOffset(kStoreWord, scratch, SP, dest.Int32Value()); 4920 } 4921 4922 void MipsAssembler::Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src, 4923 ManagedRegister mscratch, size_t size) { 4924 Register scratch = mscratch.AsMips().AsCoreRegister(); 4925 CHECK_EQ(size, kMipsWordSize); 4926 LoadFromOffset(kLoadWord, scratch, SP, src.Int32Value()); 4927 StoreToOffset(kStoreWord, scratch, dest_base.AsMips().AsCoreRegister(), dest_offset.Int32Value()); 4928 } 4929 4930 void MipsAssembler::Copy(FrameOffset dest ATTRIBUTE_UNUSED, 4931 FrameOffset src_base ATTRIBUTE_UNUSED, 4932 Offset src_offset ATTRIBUTE_UNUSED, 4933 ManagedRegister mscratch ATTRIBUTE_UNUSED, 4934 size_t size ATTRIBUTE_UNUSED) { 4935 UNIMPLEMENTED(FATAL) << "no MIPS implementation"; 4936 } 4937 4938 void MipsAssembler::Copy(ManagedRegister dest, Offset dest_offset, 4939 ManagedRegister src, Offset src_offset, 4940 ManagedRegister mscratch, size_t size) { 4941 CHECK_EQ(size, kMipsWordSize); 4942 Register scratch = mscratch.AsMips().AsCoreRegister(); 4943 LoadFromOffset(kLoadWord, scratch, src.AsMips().AsCoreRegister(), src_offset.Int32Value()); 4944 StoreToOffset(kStoreWord, scratch, dest.AsMips().AsCoreRegister(), dest_offset.Int32Value()); 4945 } 4946 4947 void MipsAssembler::Copy(FrameOffset dest ATTRIBUTE_UNUSED, 4948 Offset dest_offset ATTRIBUTE_UNUSED, 4949 FrameOffset src ATTRIBUTE_UNUSED, 4950 Offset src_offset ATTRIBUTE_UNUSED, 4951 ManagedRegister mscratch ATTRIBUTE_UNUSED, 4952 size_t size ATTRIBUTE_UNUSED) { 4953 UNIMPLEMENTED(FATAL) << "no MIPS implementation"; 4954 } 4955 4956 void MipsAssembler::MemoryBarrier(ManagedRegister) { 4957 // TODO: sync? 4958 UNIMPLEMENTED(FATAL) << "no MIPS implementation"; 4959 } 4960 4961 void MipsAssembler::CreateHandleScopeEntry(ManagedRegister mout_reg, 4962 FrameOffset handle_scope_offset, 4963 ManagedRegister min_reg, 4964 bool null_allowed) { 4965 MipsManagedRegister out_reg = mout_reg.AsMips(); 4966 MipsManagedRegister in_reg = min_reg.AsMips(); 4967 CHECK(in_reg.IsNoRegister() || in_reg.IsCoreRegister()) << in_reg; 4968 CHECK(out_reg.IsCoreRegister()) << out_reg; 4969 if (null_allowed) { 4970 MipsLabel null_arg; 4971 // Null values get a handle scope entry value of 0. Otherwise, the handle scope entry is 4972 // the address in the handle scope holding the reference. 4973 // E.g. out_reg = (handle == 0) ? 0 : (SP+handle_offset). 4974 if (in_reg.IsNoRegister()) { 4975 LoadFromOffset(kLoadWord, out_reg.AsCoreRegister(), 4976 SP, handle_scope_offset.Int32Value()); 4977 in_reg = out_reg; 4978 } 4979 if (!out_reg.Equals(in_reg)) { 4980 LoadConst32(out_reg.AsCoreRegister(), 0); 4981 } 4982 Beqz(in_reg.AsCoreRegister(), &null_arg); 4983 Addiu32(out_reg.AsCoreRegister(), SP, handle_scope_offset.Int32Value()); 4984 Bind(&null_arg); 4985 } else { 4986 Addiu32(out_reg.AsCoreRegister(), SP, handle_scope_offset.Int32Value()); 4987 } 4988 } 4989 4990 void MipsAssembler::CreateHandleScopeEntry(FrameOffset out_off, 4991 FrameOffset handle_scope_offset, 4992 ManagedRegister mscratch, 4993 bool null_allowed) { 4994 MipsManagedRegister scratch = mscratch.AsMips(); 4995 CHECK(scratch.IsCoreRegister()) << scratch; 4996 if (null_allowed) { 4997 MipsLabel null_arg; 4998 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, handle_scope_offset.Int32Value()); 4999 // Null values get a handle scope entry value of 0. Otherwise, the handle scope entry is 5000 // the address in the handle scope holding the reference. 5001 // E.g. scratch = (scratch == 0) ? 0 : (SP+handle_scope_offset). 5002 Beqz(scratch.AsCoreRegister(), &null_arg); 5003 Addiu32(scratch.AsCoreRegister(), SP, handle_scope_offset.Int32Value()); 5004 Bind(&null_arg); 5005 } else { 5006 Addiu32(scratch.AsCoreRegister(), SP, handle_scope_offset.Int32Value()); 5007 } 5008 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, out_off.Int32Value()); 5009 } 5010 5011 // Given a handle scope entry, load the associated reference. 5012 void MipsAssembler::LoadReferenceFromHandleScope(ManagedRegister mout_reg, 5013 ManagedRegister min_reg) { 5014 MipsManagedRegister out_reg = mout_reg.AsMips(); 5015 MipsManagedRegister in_reg = min_reg.AsMips(); 5016 CHECK(out_reg.IsCoreRegister()) << out_reg; 5017 CHECK(in_reg.IsCoreRegister()) << in_reg; 5018 MipsLabel null_arg; 5019 if (!out_reg.Equals(in_reg)) { 5020 LoadConst32(out_reg.AsCoreRegister(), 0); 5021 } 5022 Beqz(in_reg.AsCoreRegister(), &null_arg); 5023 LoadFromOffset(kLoadWord, out_reg.AsCoreRegister(), 5024 in_reg.AsCoreRegister(), 0); 5025 Bind(&null_arg); 5026 } 5027 5028 void MipsAssembler::VerifyObject(ManagedRegister src ATTRIBUTE_UNUSED, 5029 bool could_be_null ATTRIBUTE_UNUSED) { 5030 // TODO: not validating references. 5031 } 5032 5033 void MipsAssembler::VerifyObject(FrameOffset src ATTRIBUTE_UNUSED, 5034 bool could_be_null ATTRIBUTE_UNUSED) { 5035 // TODO: not validating references. 5036 } 5037 5038 void MipsAssembler::Call(ManagedRegister mbase, Offset offset, ManagedRegister mscratch) { 5039 MipsManagedRegister base = mbase.AsMips(); 5040 MipsManagedRegister scratch = mscratch.AsMips(); 5041 CHECK(base.IsCoreRegister()) << base; 5042 CHECK(scratch.IsCoreRegister()) << scratch; 5043 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), 5044 base.AsCoreRegister(), offset.Int32Value()); 5045 Jalr(scratch.AsCoreRegister()); 5046 NopIfNoReordering(); 5047 // TODO: place reference map on call. 5048 } 5049 5050 void MipsAssembler::Call(FrameOffset base, Offset offset, ManagedRegister mscratch) { 5051 MipsManagedRegister scratch = mscratch.AsMips(); 5052 CHECK(scratch.IsCoreRegister()) << scratch; 5053 // Call *(*(SP + base) + offset) 5054 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, base.Int32Value()); 5055 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), 5056 scratch.AsCoreRegister(), offset.Int32Value()); 5057 Jalr(scratch.AsCoreRegister()); 5058 NopIfNoReordering(); 5059 // TODO: place reference map on call. 5060 } 5061 5062 void MipsAssembler::CallFromThread(ThreadOffset32 offset ATTRIBUTE_UNUSED, 5063 ManagedRegister mscratch ATTRIBUTE_UNUSED) { 5064 UNIMPLEMENTED(FATAL) << "no mips implementation"; 5065 } 5066 5067 void MipsAssembler::GetCurrentThread(ManagedRegister tr) { 5068 Move(tr.AsMips().AsCoreRegister(), S1); 5069 } 5070 5071 void MipsAssembler::GetCurrentThread(FrameOffset offset, 5072 ManagedRegister mscratch ATTRIBUTE_UNUSED) { 5073 StoreToOffset(kStoreWord, S1, SP, offset.Int32Value()); 5074 } 5075 5076 void MipsAssembler::ExceptionPoll(ManagedRegister mscratch, size_t stack_adjust) { 5077 MipsManagedRegister scratch = mscratch.AsMips(); 5078 exception_blocks_.emplace_back(scratch, stack_adjust); 5079 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), 5080 S1, Thread::ExceptionOffset<kMipsPointerSize>().Int32Value()); 5081 Bnez(scratch.AsCoreRegister(), exception_blocks_.back().Entry()); 5082 } 5083 5084 void MipsAssembler::EmitExceptionPoll(MipsExceptionSlowPath* exception) { 5085 Bind(exception->Entry()); 5086 if (exception->stack_adjust_ != 0) { // Fix up the frame. 5087 DecreaseFrameSize(exception->stack_adjust_); 5088 } 5089 // Pass exception object as argument. 5090 // Don't care about preserving A0 as this call won't return. 5091 CheckEntrypointTypes<kQuickDeliverException, void, mirror::Object*>(); 5092 Move(A0, exception->scratch_.AsCoreRegister()); 5093 // Set up call to Thread::Current()->pDeliverException. 5094 LoadFromOffset(kLoadWord, T9, S1, 5095 QUICK_ENTRYPOINT_OFFSET(kMipsPointerSize, pDeliverException).Int32Value()); 5096 Jr(T9); 5097 NopIfNoReordering(); 5098 5099 // Call never returns. 5100 Break(); 5101 } 5102 5103 } // namespace mips 5104 } // namespace art 5105