1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "assembler_mips64.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 mips64 { 28 29 static_assert(static_cast<size_t>(kMips64PointerSize) == kMips64DoublewordSize, 30 "Unexpected Mips64 pointer size."); 31 static_assert(kMips64PointerSize == PointerSize::k64, "Unexpected Mips64 pointer size."); 32 33 34 void Mips64Assembler::FinalizeCode() { 35 for (auto& exception_block : exception_blocks_) { 36 EmitExceptionPoll(&exception_block); 37 } 38 ReserveJumpTableSpace(); 39 EmitLiterals(); 40 PromoteBranches(); 41 } 42 43 void Mips64Assembler::FinalizeInstructions(const MemoryRegion& region) { 44 EmitBranches(); 45 EmitJumpTables(); 46 Assembler::FinalizeInstructions(region); 47 PatchCFI(); 48 } 49 50 void Mips64Assembler::PatchCFI() { 51 if (cfi().NumberOfDelayedAdvancePCs() == 0u) { 52 return; 53 } 54 55 typedef DebugFrameOpCodeWriterForAssembler::DelayedAdvancePC DelayedAdvancePC; 56 const auto data = cfi().ReleaseStreamAndPrepareForDelayedAdvancePC(); 57 const std::vector<uint8_t>& old_stream = data.first; 58 const std::vector<DelayedAdvancePC>& advances = data.second; 59 60 // Refill our data buffer with patched opcodes. 61 cfi().ReserveCFIStream(old_stream.size() + advances.size() + 16); 62 size_t stream_pos = 0; 63 for (const DelayedAdvancePC& advance : advances) { 64 DCHECK_GE(advance.stream_pos, stream_pos); 65 // Copy old data up to the point where advance was issued. 66 cfi().AppendRawData(old_stream, stream_pos, advance.stream_pos); 67 stream_pos = advance.stream_pos; 68 // Insert the advance command with its final offset. 69 size_t final_pc = GetAdjustedPosition(advance.pc); 70 cfi().AdvancePC(final_pc); 71 } 72 // Copy the final segment if any. 73 cfi().AppendRawData(old_stream, stream_pos, old_stream.size()); 74 } 75 76 void Mips64Assembler::EmitBranches() { 77 CHECK(!overwriting_); 78 // Switch from appending instructions at the end of the buffer to overwriting 79 // existing instructions (branch placeholders) in the buffer. 80 overwriting_ = true; 81 for (auto& branch : branches_) { 82 EmitBranch(&branch); 83 } 84 overwriting_ = false; 85 } 86 87 void Mips64Assembler::Emit(uint32_t value) { 88 if (overwriting_) { 89 // Branches to labels are emitted into their placeholders here. 90 buffer_.Store<uint32_t>(overwrite_location_, value); 91 overwrite_location_ += sizeof(uint32_t); 92 } else { 93 // Other instructions are simply appended at the end here. 94 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 95 buffer_.Emit<uint32_t>(value); 96 } 97 } 98 99 void Mips64Assembler::EmitR(int opcode, GpuRegister rs, GpuRegister rt, GpuRegister rd, 100 int shamt, int funct) { 101 CHECK_NE(rs, kNoGpuRegister); 102 CHECK_NE(rt, kNoGpuRegister); 103 CHECK_NE(rd, kNoGpuRegister); 104 uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift | 105 static_cast<uint32_t>(rs) << kRsShift | 106 static_cast<uint32_t>(rt) << kRtShift | 107 static_cast<uint32_t>(rd) << kRdShift | 108 shamt << kShamtShift | 109 funct; 110 Emit(encoding); 111 } 112 113 void Mips64Assembler::EmitRsd(int opcode, GpuRegister rs, GpuRegister rd, 114 int shamt, int funct) { 115 CHECK_NE(rs, kNoGpuRegister); 116 CHECK_NE(rd, kNoGpuRegister); 117 uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift | 118 static_cast<uint32_t>(rs) << kRsShift | 119 static_cast<uint32_t>(ZERO) << kRtShift | 120 static_cast<uint32_t>(rd) << kRdShift | 121 shamt << kShamtShift | 122 funct; 123 Emit(encoding); 124 } 125 126 void Mips64Assembler::EmitRtd(int opcode, GpuRegister rt, GpuRegister rd, 127 int shamt, int funct) { 128 CHECK_NE(rt, kNoGpuRegister); 129 CHECK_NE(rd, kNoGpuRegister); 130 uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift | 131 static_cast<uint32_t>(ZERO) << kRsShift | 132 static_cast<uint32_t>(rt) << kRtShift | 133 static_cast<uint32_t>(rd) << kRdShift | 134 shamt << kShamtShift | 135 funct; 136 Emit(encoding); 137 } 138 139 void Mips64Assembler::EmitI(int opcode, GpuRegister rs, GpuRegister rt, uint16_t imm) { 140 CHECK_NE(rs, kNoGpuRegister); 141 CHECK_NE(rt, kNoGpuRegister); 142 uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift | 143 static_cast<uint32_t>(rs) << kRsShift | 144 static_cast<uint32_t>(rt) << kRtShift | 145 imm; 146 Emit(encoding); 147 } 148 149 void Mips64Assembler::EmitI21(int opcode, GpuRegister rs, uint32_t imm21) { 150 CHECK_NE(rs, kNoGpuRegister); 151 CHECK(IsUint<21>(imm21)) << imm21; 152 uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift | 153 static_cast<uint32_t>(rs) << kRsShift | 154 imm21; 155 Emit(encoding); 156 } 157 158 void Mips64Assembler::EmitI26(int opcode, uint32_t imm26) { 159 CHECK(IsUint<26>(imm26)) << imm26; 160 uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift | imm26; 161 Emit(encoding); 162 } 163 164 void Mips64Assembler::EmitFR(int opcode, int fmt, FpuRegister ft, FpuRegister fs, FpuRegister fd, 165 int funct) { 166 CHECK_NE(ft, kNoFpuRegister); 167 CHECK_NE(fs, kNoFpuRegister); 168 CHECK_NE(fd, kNoFpuRegister); 169 uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift | 170 fmt << kFmtShift | 171 static_cast<uint32_t>(ft) << kFtShift | 172 static_cast<uint32_t>(fs) << kFsShift | 173 static_cast<uint32_t>(fd) << kFdShift | 174 funct; 175 Emit(encoding); 176 } 177 178 void Mips64Assembler::EmitFI(int opcode, int fmt, FpuRegister ft, uint16_t imm) { 179 CHECK_NE(ft, kNoFpuRegister); 180 uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift | 181 fmt << kFmtShift | 182 static_cast<uint32_t>(ft) << kFtShift | 183 imm; 184 Emit(encoding); 185 } 186 187 void Mips64Assembler::EmitMsa3R(int operation, 188 int df, 189 VectorRegister wt, 190 VectorRegister ws, 191 VectorRegister wd, 192 int minor_opcode) { 193 CHECK_NE(wt, kNoVectorRegister); 194 CHECK_NE(ws, kNoVectorRegister); 195 CHECK_NE(wd, kNoVectorRegister); 196 uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift | 197 operation << kMsaOperationShift | 198 df << kDfShift | 199 static_cast<uint32_t>(wt) << kWtShift | 200 static_cast<uint32_t>(ws) << kWsShift | 201 static_cast<uint32_t>(wd) << kWdShift | 202 minor_opcode; 203 Emit(encoding); 204 } 205 206 void Mips64Assembler::EmitMsaBIT(int operation, 207 int df_m, 208 VectorRegister ws, 209 VectorRegister wd, 210 int minor_opcode) { 211 CHECK_NE(ws, kNoVectorRegister); 212 CHECK_NE(wd, kNoVectorRegister); 213 uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift | 214 operation << kMsaOperationShift | 215 df_m << kDfMShift | 216 static_cast<uint32_t>(ws) << kWsShift | 217 static_cast<uint32_t>(wd) << kWdShift | 218 minor_opcode; 219 Emit(encoding); 220 } 221 222 void Mips64Assembler::EmitMsaELM(int operation, 223 int df_n, 224 VectorRegister ws, 225 VectorRegister wd, 226 int minor_opcode) { 227 CHECK_NE(ws, kNoVectorRegister); 228 CHECK_NE(wd, kNoVectorRegister); 229 uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift | 230 operation << kMsaELMOperationShift | 231 df_n << kDfNShift | 232 static_cast<uint32_t>(ws) << kWsShift | 233 static_cast<uint32_t>(wd) << kWdShift | 234 minor_opcode; 235 Emit(encoding); 236 } 237 238 void Mips64Assembler::EmitMsaMI10(int s10, 239 GpuRegister rs, 240 VectorRegister wd, 241 int minor_opcode, 242 int df) { 243 CHECK_NE(rs, kNoGpuRegister); 244 CHECK_NE(wd, kNoVectorRegister); 245 CHECK(IsUint<10>(s10)) << s10; 246 uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift | 247 s10 << kS10Shift | 248 static_cast<uint32_t>(rs) << kWsShift | 249 static_cast<uint32_t>(wd) << kWdShift | 250 minor_opcode << kS10MinorShift | 251 df; 252 Emit(encoding); 253 } 254 255 void Mips64Assembler::EmitMsaI10(int operation, 256 int df, 257 int i10, 258 VectorRegister wd, 259 int minor_opcode) { 260 CHECK_NE(wd, kNoVectorRegister); 261 CHECK(IsUint<10>(i10)) << i10; 262 uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift | 263 operation << kMsaOperationShift | 264 df << kDfShift | 265 i10 << kI10Shift | 266 static_cast<uint32_t>(wd) << kWdShift | 267 minor_opcode; 268 Emit(encoding); 269 } 270 271 void Mips64Assembler::EmitMsa2R(int operation, 272 int df, 273 VectorRegister ws, 274 VectorRegister wd, 275 int minor_opcode) { 276 CHECK_NE(ws, kNoVectorRegister); 277 CHECK_NE(wd, kNoVectorRegister); 278 uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift | 279 operation << kMsa2ROperationShift | 280 df << kDf2RShift | 281 static_cast<uint32_t>(ws) << kWsShift | 282 static_cast<uint32_t>(wd) << kWdShift | 283 minor_opcode; 284 Emit(encoding); 285 } 286 287 void Mips64Assembler::EmitMsa2RF(int operation, 288 int df, 289 VectorRegister ws, 290 VectorRegister wd, 291 int minor_opcode) { 292 CHECK_NE(ws, kNoVectorRegister); 293 CHECK_NE(wd, kNoVectorRegister); 294 uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift | 295 operation << kMsa2RFOperationShift | 296 df << kDf2RShift | 297 static_cast<uint32_t>(ws) << kWsShift | 298 static_cast<uint32_t>(wd) << kWdShift | 299 minor_opcode; 300 Emit(encoding); 301 } 302 303 void Mips64Assembler::Addu(GpuRegister rd, GpuRegister rs, GpuRegister rt) { 304 EmitR(0, rs, rt, rd, 0, 0x21); 305 } 306 307 void Mips64Assembler::Addiu(GpuRegister rt, GpuRegister rs, uint16_t imm16) { 308 EmitI(0x9, rs, rt, imm16); 309 } 310 311 void Mips64Assembler::Daddu(GpuRegister rd, GpuRegister rs, GpuRegister rt) { 312 EmitR(0, rs, rt, rd, 0, 0x2d); 313 } 314 315 void Mips64Assembler::Daddiu(GpuRegister rt, GpuRegister rs, uint16_t imm16) { 316 EmitI(0x19, rs, rt, imm16); 317 } 318 319 void Mips64Assembler::Subu(GpuRegister rd, GpuRegister rs, GpuRegister rt) { 320 EmitR(0, rs, rt, rd, 0, 0x23); 321 } 322 323 void Mips64Assembler::Dsubu(GpuRegister rd, GpuRegister rs, GpuRegister rt) { 324 EmitR(0, rs, rt, rd, 0, 0x2f); 325 } 326 327 void Mips64Assembler::MulR6(GpuRegister rd, GpuRegister rs, GpuRegister rt) { 328 EmitR(0, rs, rt, rd, 2, 0x18); 329 } 330 331 void Mips64Assembler::MuhR6(GpuRegister rd, GpuRegister rs, GpuRegister rt) { 332 EmitR(0, rs, rt, rd, 3, 0x18); 333 } 334 335 void Mips64Assembler::DivR6(GpuRegister rd, GpuRegister rs, GpuRegister rt) { 336 EmitR(0, rs, rt, rd, 2, 0x1a); 337 } 338 339 void Mips64Assembler::ModR6(GpuRegister rd, GpuRegister rs, GpuRegister rt) { 340 EmitR(0, rs, rt, rd, 3, 0x1a); 341 } 342 343 void Mips64Assembler::DivuR6(GpuRegister rd, GpuRegister rs, GpuRegister rt) { 344 EmitR(0, rs, rt, rd, 2, 0x1b); 345 } 346 347 void Mips64Assembler::ModuR6(GpuRegister rd, GpuRegister rs, GpuRegister rt) { 348 EmitR(0, rs, rt, rd, 3, 0x1b); 349 } 350 351 void Mips64Assembler::Dmul(GpuRegister rd, GpuRegister rs, GpuRegister rt) { 352 EmitR(0, rs, rt, rd, 2, 0x1c); 353 } 354 355 void Mips64Assembler::Dmuh(GpuRegister rd, GpuRegister rs, GpuRegister rt) { 356 EmitR(0, rs, rt, rd, 3, 0x1c); 357 } 358 359 void Mips64Assembler::Ddiv(GpuRegister rd, GpuRegister rs, GpuRegister rt) { 360 EmitR(0, rs, rt, rd, 2, 0x1e); 361 } 362 363 void Mips64Assembler::Dmod(GpuRegister rd, GpuRegister rs, GpuRegister rt) { 364 EmitR(0, rs, rt, rd, 3, 0x1e); 365 } 366 367 void Mips64Assembler::Ddivu(GpuRegister rd, GpuRegister rs, GpuRegister rt) { 368 EmitR(0, rs, rt, rd, 2, 0x1f); 369 } 370 371 void Mips64Assembler::Dmodu(GpuRegister rd, GpuRegister rs, GpuRegister rt) { 372 EmitR(0, rs, rt, rd, 3, 0x1f); 373 } 374 375 void Mips64Assembler::And(GpuRegister rd, GpuRegister rs, GpuRegister rt) { 376 EmitR(0, rs, rt, rd, 0, 0x24); 377 } 378 379 void Mips64Assembler::Andi(GpuRegister rt, GpuRegister rs, uint16_t imm16) { 380 EmitI(0xc, rs, rt, imm16); 381 } 382 383 void Mips64Assembler::Or(GpuRegister rd, GpuRegister rs, GpuRegister rt) { 384 EmitR(0, rs, rt, rd, 0, 0x25); 385 } 386 387 void Mips64Assembler::Ori(GpuRegister rt, GpuRegister rs, uint16_t imm16) { 388 EmitI(0xd, rs, rt, imm16); 389 } 390 391 void Mips64Assembler::Xor(GpuRegister rd, GpuRegister rs, GpuRegister rt) { 392 EmitR(0, rs, rt, rd, 0, 0x26); 393 } 394 395 void Mips64Assembler::Xori(GpuRegister rt, GpuRegister rs, uint16_t imm16) { 396 EmitI(0xe, rs, rt, imm16); 397 } 398 399 void Mips64Assembler::Nor(GpuRegister rd, GpuRegister rs, GpuRegister rt) { 400 EmitR(0, rs, rt, rd, 0, 0x27); 401 } 402 403 void Mips64Assembler::Bitswap(GpuRegister rd, GpuRegister rt) { 404 EmitRtd(0x1f, rt, rd, 0x0, 0x20); 405 } 406 407 void Mips64Assembler::Dbitswap(GpuRegister rd, GpuRegister rt) { 408 EmitRtd(0x1f, rt, rd, 0x0, 0x24); 409 } 410 411 void Mips64Assembler::Seb(GpuRegister rd, GpuRegister rt) { 412 EmitR(0x1f, static_cast<GpuRegister>(0), rt, rd, 0x10, 0x20); 413 } 414 415 void Mips64Assembler::Seh(GpuRegister rd, GpuRegister rt) { 416 EmitR(0x1f, static_cast<GpuRegister>(0), rt, rd, 0x18, 0x20); 417 } 418 419 void Mips64Assembler::Dsbh(GpuRegister rd, GpuRegister rt) { 420 EmitRtd(0x1f, rt, rd, 0x2, 0x24); 421 } 422 423 void Mips64Assembler::Dshd(GpuRegister rd, GpuRegister rt) { 424 EmitRtd(0x1f, rt, rd, 0x5, 0x24); 425 } 426 427 void Mips64Assembler::Dext(GpuRegister rt, GpuRegister rs, int pos, int size) { 428 CHECK(IsUint<5>(pos)) << pos; 429 CHECK(IsUint<5>(size - 1)) << size; 430 EmitR(0x1f, rs, rt, static_cast<GpuRegister>(size - 1), pos, 0x3); 431 } 432 433 void Mips64Assembler::Ins(GpuRegister rd, GpuRegister rt, int pos, int size) { 434 CHECK(IsUint<5>(pos)) << pos; 435 CHECK(IsUint<5>(size - 1)) << size; 436 CHECK(IsUint<5>(pos + size - 1)) << pos << " + " << size; 437 EmitR(0x1f, rt, rd, static_cast<GpuRegister>(pos + size - 1), pos, 0x04); 438 } 439 440 void Mips64Assembler::Dinsm(GpuRegister rt, GpuRegister rs, int pos, int size) { 441 CHECK(IsUint<5>(pos)) << pos; 442 CHECK(2 <= size && size <= 64) << size; 443 CHECK(IsUint<5>(pos + size - 33)) << pos << " + " << size; 444 EmitR(0x1f, rs, rt, static_cast<GpuRegister>(pos + size - 33), pos, 0x5); 445 } 446 447 void Mips64Assembler::Dinsu(GpuRegister rt, GpuRegister rs, int pos, int size) { 448 CHECK(IsUint<5>(pos - 32)) << pos; 449 CHECK(IsUint<5>(size - 1)) << size; 450 CHECK(IsUint<5>(pos + size - 33)) << pos << " + " << size; 451 EmitR(0x1f, rs, rt, static_cast<GpuRegister>(pos + size - 33), pos - 32, 0x6); 452 } 453 454 void Mips64Assembler::Dins(GpuRegister rt, GpuRegister rs, int pos, int size) { 455 CHECK(IsUint<5>(pos)) << pos; 456 CHECK(IsUint<5>(size - 1)) << size; 457 CHECK(IsUint<5>(pos + size - 1)) << pos << " + " << size; 458 EmitR(0x1f, rs, rt, static_cast<GpuRegister>(pos + size - 1), pos, 0x7); 459 } 460 461 void Mips64Assembler::DblIns(GpuRegister rt, GpuRegister rs, int pos, int size) { 462 if (pos >= 32) { 463 Dinsu(rt, rs, pos, size); 464 } else if ((static_cast<int64_t>(pos) + size - 1) >= 32) { 465 Dinsm(rt, rs, pos, size); 466 } else { 467 Dins(rt, rs, pos, size); 468 } 469 } 470 471 void Mips64Assembler::Lsa(GpuRegister rd, GpuRegister rs, GpuRegister rt, int saPlusOne) { 472 CHECK(1 <= saPlusOne && saPlusOne <= 4) << saPlusOne; 473 int sa = saPlusOne - 1; 474 EmitR(0x0, rs, rt, rd, sa, 0x05); 475 } 476 477 void Mips64Assembler::Dlsa(GpuRegister rd, GpuRegister rs, GpuRegister rt, int saPlusOne) { 478 CHECK(1 <= saPlusOne && saPlusOne <= 4) << saPlusOne; 479 int sa = saPlusOne - 1; 480 EmitR(0x0, rs, rt, rd, sa, 0x15); 481 } 482 483 void Mips64Assembler::Wsbh(GpuRegister rd, GpuRegister rt) { 484 EmitRtd(0x1f, rt, rd, 2, 0x20); 485 } 486 487 void Mips64Assembler::Sc(GpuRegister rt, GpuRegister base, int16_t imm9) { 488 CHECK(IsInt<9>(imm9)); 489 EmitI(0x1f, base, rt, ((imm9 & 0x1FF) << 7) | 0x26); 490 } 491 492 void Mips64Assembler::Scd(GpuRegister rt, GpuRegister base, int16_t imm9) { 493 CHECK(IsInt<9>(imm9)); 494 EmitI(0x1f, base, rt, ((imm9 & 0x1FF) << 7) | 0x27); 495 } 496 497 void Mips64Assembler::Ll(GpuRegister rt, GpuRegister base, int16_t imm9) { 498 CHECK(IsInt<9>(imm9)); 499 EmitI(0x1f, base, rt, ((imm9 & 0x1FF) << 7) | 0x36); 500 } 501 502 void Mips64Assembler::Lld(GpuRegister rt, GpuRegister base, int16_t imm9) { 503 CHECK(IsInt<9>(imm9)); 504 EmitI(0x1f, base, rt, ((imm9 & 0x1FF) << 7) | 0x37); 505 } 506 507 void Mips64Assembler::Sll(GpuRegister rd, GpuRegister rt, int shamt) { 508 EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x00); 509 } 510 511 void Mips64Assembler::Srl(GpuRegister rd, GpuRegister rt, int shamt) { 512 EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x02); 513 } 514 515 void Mips64Assembler::Rotr(GpuRegister rd, GpuRegister rt, int shamt) { 516 EmitR(0, static_cast<GpuRegister>(1), rt, rd, shamt, 0x02); 517 } 518 519 void Mips64Assembler::Sra(GpuRegister rd, GpuRegister rt, int shamt) { 520 EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x03); 521 } 522 523 void Mips64Assembler::Sllv(GpuRegister rd, GpuRegister rt, GpuRegister rs) { 524 EmitR(0, rs, rt, rd, 0, 0x04); 525 } 526 527 void Mips64Assembler::Rotrv(GpuRegister rd, GpuRegister rt, GpuRegister rs) { 528 EmitR(0, rs, rt, rd, 1, 0x06); 529 } 530 531 void Mips64Assembler::Srlv(GpuRegister rd, GpuRegister rt, GpuRegister rs) { 532 EmitR(0, rs, rt, rd, 0, 0x06); 533 } 534 535 void Mips64Assembler::Srav(GpuRegister rd, GpuRegister rt, GpuRegister rs) { 536 EmitR(0, rs, rt, rd, 0, 0x07); 537 } 538 539 void Mips64Assembler::Dsll(GpuRegister rd, GpuRegister rt, int shamt) { 540 EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x38); 541 } 542 543 void Mips64Assembler::Dsrl(GpuRegister rd, GpuRegister rt, int shamt) { 544 EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x3a); 545 } 546 547 void Mips64Assembler::Drotr(GpuRegister rd, GpuRegister rt, int shamt) { 548 EmitR(0, static_cast<GpuRegister>(1), rt, rd, shamt, 0x3a); 549 } 550 551 void Mips64Assembler::Dsra(GpuRegister rd, GpuRegister rt, int shamt) { 552 EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x3b); 553 } 554 555 void Mips64Assembler::Dsll32(GpuRegister rd, GpuRegister rt, int shamt) { 556 EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x3c); 557 } 558 559 void Mips64Assembler::Dsrl32(GpuRegister rd, GpuRegister rt, int shamt) { 560 EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x3e); 561 } 562 563 void Mips64Assembler::Drotr32(GpuRegister rd, GpuRegister rt, int shamt) { 564 EmitR(0, static_cast<GpuRegister>(1), rt, rd, shamt, 0x3e); 565 } 566 567 void Mips64Assembler::Dsra32(GpuRegister rd, GpuRegister rt, int shamt) { 568 EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x3f); 569 } 570 571 void Mips64Assembler::Dsllv(GpuRegister rd, GpuRegister rt, GpuRegister rs) { 572 EmitR(0, rs, rt, rd, 0, 0x14); 573 } 574 575 void Mips64Assembler::Dsrlv(GpuRegister rd, GpuRegister rt, GpuRegister rs) { 576 EmitR(0, rs, rt, rd, 0, 0x16); 577 } 578 579 void Mips64Assembler::Drotrv(GpuRegister rd, GpuRegister rt, GpuRegister rs) { 580 EmitR(0, rs, rt, rd, 1, 0x16); 581 } 582 583 void Mips64Assembler::Dsrav(GpuRegister rd, GpuRegister rt, GpuRegister rs) { 584 EmitR(0, rs, rt, rd, 0, 0x17); 585 } 586 587 void Mips64Assembler::Lb(GpuRegister rt, GpuRegister rs, uint16_t imm16) { 588 EmitI(0x20, rs, rt, imm16); 589 } 590 591 void Mips64Assembler::Lh(GpuRegister rt, GpuRegister rs, uint16_t imm16) { 592 EmitI(0x21, rs, rt, imm16); 593 } 594 595 void Mips64Assembler::Lw(GpuRegister rt, GpuRegister rs, uint16_t imm16) { 596 EmitI(0x23, rs, rt, imm16); 597 } 598 599 void Mips64Assembler::Ld(GpuRegister rt, GpuRegister rs, uint16_t imm16) { 600 EmitI(0x37, rs, rt, imm16); 601 } 602 603 void Mips64Assembler::Lbu(GpuRegister rt, GpuRegister rs, uint16_t imm16) { 604 EmitI(0x24, rs, rt, imm16); 605 } 606 607 void Mips64Assembler::Lhu(GpuRegister rt, GpuRegister rs, uint16_t imm16) { 608 EmitI(0x25, rs, rt, imm16); 609 } 610 611 void Mips64Assembler::Lwu(GpuRegister rt, GpuRegister rs, uint16_t imm16) { 612 EmitI(0x27, rs, rt, imm16); 613 } 614 615 void Mips64Assembler::Lwpc(GpuRegister rs, uint32_t imm19) { 616 CHECK(IsUint<19>(imm19)) << imm19; 617 EmitI21(0x3B, rs, (0x01 << 19) | imm19); 618 } 619 620 void Mips64Assembler::Lwupc(GpuRegister rs, uint32_t imm19) { 621 CHECK(IsUint<19>(imm19)) << imm19; 622 EmitI21(0x3B, rs, (0x02 << 19) | imm19); 623 } 624 625 void Mips64Assembler::Ldpc(GpuRegister rs, uint32_t imm18) { 626 CHECK(IsUint<18>(imm18)) << imm18; 627 EmitI21(0x3B, rs, (0x06 << 18) | imm18); 628 } 629 630 void Mips64Assembler::Lui(GpuRegister rt, uint16_t imm16) { 631 EmitI(0xf, static_cast<GpuRegister>(0), rt, imm16); 632 } 633 634 void Mips64Assembler::Aui(GpuRegister rt, GpuRegister rs, uint16_t imm16) { 635 EmitI(0xf, rs, rt, imm16); 636 } 637 638 void Mips64Assembler::Daui(GpuRegister rt, GpuRegister rs, uint16_t imm16) { 639 CHECK_NE(rs, ZERO); 640 EmitI(0x1d, rs, rt, imm16); 641 } 642 643 void Mips64Assembler::Dahi(GpuRegister rs, uint16_t imm16) { 644 EmitI(1, rs, static_cast<GpuRegister>(6), imm16); 645 } 646 647 void Mips64Assembler::Dati(GpuRegister rs, uint16_t imm16) { 648 EmitI(1, rs, static_cast<GpuRegister>(0x1e), imm16); 649 } 650 651 void Mips64Assembler::Sync(uint32_t stype) { 652 EmitR(0, static_cast<GpuRegister>(0), static_cast<GpuRegister>(0), 653 static_cast<GpuRegister>(0), stype & 0x1f, 0xf); 654 } 655 656 void Mips64Assembler::Sb(GpuRegister rt, GpuRegister rs, uint16_t imm16) { 657 EmitI(0x28, rs, rt, imm16); 658 } 659 660 void Mips64Assembler::Sh(GpuRegister rt, GpuRegister rs, uint16_t imm16) { 661 EmitI(0x29, rs, rt, imm16); 662 } 663 664 void Mips64Assembler::Sw(GpuRegister rt, GpuRegister rs, uint16_t imm16) { 665 EmitI(0x2b, rs, rt, imm16); 666 } 667 668 void Mips64Assembler::Sd(GpuRegister rt, GpuRegister rs, uint16_t imm16) { 669 EmitI(0x3f, rs, rt, imm16); 670 } 671 672 void Mips64Assembler::Slt(GpuRegister rd, GpuRegister rs, GpuRegister rt) { 673 EmitR(0, rs, rt, rd, 0, 0x2a); 674 } 675 676 void Mips64Assembler::Sltu(GpuRegister rd, GpuRegister rs, GpuRegister rt) { 677 EmitR(0, rs, rt, rd, 0, 0x2b); 678 } 679 680 void Mips64Assembler::Slti(GpuRegister rt, GpuRegister rs, uint16_t imm16) { 681 EmitI(0xa, rs, rt, imm16); 682 } 683 684 void Mips64Assembler::Sltiu(GpuRegister rt, GpuRegister rs, uint16_t imm16) { 685 EmitI(0xb, rs, rt, imm16); 686 } 687 688 void Mips64Assembler::Seleqz(GpuRegister rd, GpuRegister rs, GpuRegister rt) { 689 EmitR(0, rs, rt, rd, 0, 0x35); 690 } 691 692 void Mips64Assembler::Selnez(GpuRegister rd, GpuRegister rs, GpuRegister rt) { 693 EmitR(0, rs, rt, rd, 0, 0x37); 694 } 695 696 void Mips64Assembler::Clz(GpuRegister rd, GpuRegister rs) { 697 EmitRsd(0, rs, rd, 0x01, 0x10); 698 } 699 700 void Mips64Assembler::Clo(GpuRegister rd, GpuRegister rs) { 701 EmitRsd(0, rs, rd, 0x01, 0x11); 702 } 703 704 void Mips64Assembler::Dclz(GpuRegister rd, GpuRegister rs) { 705 EmitRsd(0, rs, rd, 0x01, 0x12); 706 } 707 708 void Mips64Assembler::Dclo(GpuRegister rd, GpuRegister rs) { 709 EmitRsd(0, rs, rd, 0x01, 0x13); 710 } 711 712 void Mips64Assembler::Jalr(GpuRegister rd, GpuRegister rs) { 713 EmitR(0, rs, static_cast<GpuRegister>(0), rd, 0, 0x09); 714 } 715 716 void Mips64Assembler::Jalr(GpuRegister rs) { 717 Jalr(RA, rs); 718 } 719 720 void Mips64Assembler::Jr(GpuRegister rs) { 721 Jalr(ZERO, rs); 722 } 723 724 void Mips64Assembler::Auipc(GpuRegister rs, uint16_t imm16) { 725 EmitI(0x3B, rs, static_cast<GpuRegister>(0x1E), imm16); 726 } 727 728 void Mips64Assembler::Addiupc(GpuRegister rs, uint32_t imm19) { 729 CHECK(IsUint<19>(imm19)) << imm19; 730 EmitI21(0x3B, rs, imm19); 731 } 732 733 void Mips64Assembler::Bc(uint32_t imm26) { 734 EmitI26(0x32, imm26); 735 } 736 737 void Mips64Assembler::Balc(uint32_t imm26) { 738 EmitI26(0x3A, imm26); 739 } 740 741 void Mips64Assembler::Jic(GpuRegister rt, uint16_t imm16) { 742 EmitI(0x36, static_cast<GpuRegister>(0), rt, imm16); 743 } 744 745 void Mips64Assembler::Jialc(GpuRegister rt, uint16_t imm16) { 746 EmitI(0x3E, static_cast<GpuRegister>(0), rt, imm16); 747 } 748 749 void Mips64Assembler::Bltc(GpuRegister rs, GpuRegister rt, uint16_t imm16) { 750 CHECK_NE(rs, ZERO); 751 CHECK_NE(rt, ZERO); 752 CHECK_NE(rs, rt); 753 EmitI(0x17, rs, rt, imm16); 754 } 755 756 void Mips64Assembler::Bltzc(GpuRegister rt, uint16_t imm16) { 757 CHECK_NE(rt, ZERO); 758 EmitI(0x17, rt, rt, imm16); 759 } 760 761 void Mips64Assembler::Bgtzc(GpuRegister rt, uint16_t imm16) { 762 CHECK_NE(rt, ZERO); 763 EmitI(0x17, static_cast<GpuRegister>(0), rt, imm16); 764 } 765 766 void Mips64Assembler::Bgec(GpuRegister rs, GpuRegister rt, uint16_t imm16) { 767 CHECK_NE(rs, ZERO); 768 CHECK_NE(rt, ZERO); 769 CHECK_NE(rs, rt); 770 EmitI(0x16, rs, rt, imm16); 771 } 772 773 void Mips64Assembler::Bgezc(GpuRegister rt, uint16_t imm16) { 774 CHECK_NE(rt, ZERO); 775 EmitI(0x16, rt, rt, imm16); 776 } 777 778 void Mips64Assembler::Blezc(GpuRegister rt, uint16_t imm16) { 779 CHECK_NE(rt, ZERO); 780 EmitI(0x16, static_cast<GpuRegister>(0), rt, imm16); 781 } 782 783 void Mips64Assembler::Bltuc(GpuRegister rs, GpuRegister rt, uint16_t imm16) { 784 CHECK_NE(rs, ZERO); 785 CHECK_NE(rt, ZERO); 786 CHECK_NE(rs, rt); 787 EmitI(0x7, rs, rt, imm16); 788 } 789 790 void Mips64Assembler::Bgeuc(GpuRegister rs, GpuRegister rt, uint16_t imm16) { 791 CHECK_NE(rs, ZERO); 792 CHECK_NE(rt, ZERO); 793 CHECK_NE(rs, rt); 794 EmitI(0x6, rs, rt, imm16); 795 } 796 797 void Mips64Assembler::Beqc(GpuRegister rs, GpuRegister rt, uint16_t imm16) { 798 CHECK_NE(rs, ZERO); 799 CHECK_NE(rt, ZERO); 800 CHECK_NE(rs, rt); 801 EmitI(0x8, std::min(rs, rt), std::max(rs, rt), imm16); 802 } 803 804 void Mips64Assembler::Bnec(GpuRegister rs, GpuRegister rt, uint16_t imm16) { 805 CHECK_NE(rs, ZERO); 806 CHECK_NE(rt, ZERO); 807 CHECK_NE(rs, rt); 808 EmitI(0x18, std::min(rs, rt), std::max(rs, rt), imm16); 809 } 810 811 void Mips64Assembler::Beqzc(GpuRegister rs, uint32_t imm21) { 812 CHECK_NE(rs, ZERO); 813 EmitI21(0x36, rs, imm21); 814 } 815 816 void Mips64Assembler::Bnezc(GpuRegister rs, uint32_t imm21) { 817 CHECK_NE(rs, ZERO); 818 EmitI21(0x3E, rs, imm21); 819 } 820 821 void Mips64Assembler::Bc1eqz(FpuRegister ft, uint16_t imm16) { 822 EmitFI(0x11, 0x9, ft, imm16); 823 } 824 825 void Mips64Assembler::Bc1nez(FpuRegister ft, uint16_t imm16) { 826 EmitFI(0x11, 0xD, ft, imm16); 827 } 828 829 void Mips64Assembler::Beq(GpuRegister rs, GpuRegister rt, uint16_t imm16) { 830 EmitI(0x4, rs, rt, imm16); 831 } 832 833 void Mips64Assembler::Bne(GpuRegister rs, GpuRegister rt, uint16_t imm16) { 834 EmitI(0x5, rs, rt, imm16); 835 } 836 837 void Mips64Assembler::Beqz(GpuRegister rt, uint16_t imm16) { 838 Beq(rt, ZERO, imm16); 839 } 840 841 void Mips64Assembler::Bnez(GpuRegister rt, uint16_t imm16) { 842 Bne(rt, ZERO, imm16); 843 } 844 845 void Mips64Assembler::Bltz(GpuRegister rt, uint16_t imm16) { 846 EmitI(0x1, rt, static_cast<GpuRegister>(0), imm16); 847 } 848 849 void Mips64Assembler::Bgez(GpuRegister rt, uint16_t imm16) { 850 EmitI(0x1, rt, static_cast<GpuRegister>(0x1), imm16); 851 } 852 853 void Mips64Assembler::Blez(GpuRegister rt, uint16_t imm16) { 854 EmitI(0x6, rt, static_cast<GpuRegister>(0), imm16); 855 } 856 857 void Mips64Assembler::Bgtz(GpuRegister rt, uint16_t imm16) { 858 EmitI(0x7, rt, static_cast<GpuRegister>(0), imm16); 859 } 860 861 void Mips64Assembler::EmitBcondR6(BranchCondition cond, 862 GpuRegister rs, 863 GpuRegister rt, 864 uint32_t imm16_21) { 865 switch (cond) { 866 case kCondLT: 867 Bltc(rs, rt, imm16_21); 868 break; 869 case kCondGE: 870 Bgec(rs, rt, imm16_21); 871 break; 872 case kCondLE: 873 Bgec(rt, rs, imm16_21); 874 break; 875 case kCondGT: 876 Bltc(rt, rs, imm16_21); 877 break; 878 case kCondLTZ: 879 CHECK_EQ(rt, ZERO); 880 Bltzc(rs, imm16_21); 881 break; 882 case kCondGEZ: 883 CHECK_EQ(rt, ZERO); 884 Bgezc(rs, imm16_21); 885 break; 886 case kCondLEZ: 887 CHECK_EQ(rt, ZERO); 888 Blezc(rs, imm16_21); 889 break; 890 case kCondGTZ: 891 CHECK_EQ(rt, ZERO); 892 Bgtzc(rs, imm16_21); 893 break; 894 case kCondEQ: 895 Beqc(rs, rt, imm16_21); 896 break; 897 case kCondNE: 898 Bnec(rs, rt, imm16_21); 899 break; 900 case kCondEQZ: 901 CHECK_EQ(rt, ZERO); 902 Beqzc(rs, imm16_21); 903 break; 904 case kCondNEZ: 905 CHECK_EQ(rt, ZERO); 906 Bnezc(rs, imm16_21); 907 break; 908 case kCondLTU: 909 Bltuc(rs, rt, imm16_21); 910 break; 911 case kCondGEU: 912 Bgeuc(rs, rt, imm16_21); 913 break; 914 case kCondF: 915 CHECK_EQ(rt, ZERO); 916 Bc1eqz(static_cast<FpuRegister>(rs), imm16_21); 917 break; 918 case kCondT: 919 CHECK_EQ(rt, ZERO); 920 Bc1nez(static_cast<FpuRegister>(rs), imm16_21); 921 break; 922 case kUncond: 923 LOG(FATAL) << "Unexpected branch condition " << cond; 924 UNREACHABLE(); 925 } 926 } 927 928 void Mips64Assembler::EmitBcondR2(BranchCondition cond, 929 GpuRegister rs, 930 GpuRegister rt, 931 uint16_t imm16) { 932 switch (cond) { 933 case kCondLTZ: 934 CHECK_EQ(rt, ZERO); 935 Bltz(rs, imm16); 936 break; 937 case kCondGEZ: 938 CHECK_EQ(rt, ZERO); 939 Bgez(rs, imm16); 940 break; 941 case kCondLEZ: 942 CHECK_EQ(rt, ZERO); 943 Blez(rs, imm16); 944 break; 945 case kCondGTZ: 946 CHECK_EQ(rt, ZERO); 947 Bgtz(rs, imm16); 948 break; 949 case kCondEQ: 950 Beq(rs, rt, imm16); 951 break; 952 case kCondNE: 953 Bne(rs, rt, imm16); 954 break; 955 case kCondEQZ: 956 CHECK_EQ(rt, ZERO); 957 Beqz(rs, imm16); 958 break; 959 case kCondNEZ: 960 CHECK_EQ(rt, ZERO); 961 Bnez(rs, imm16); 962 break; 963 case kCondF: 964 case kCondT: 965 case kCondLT: 966 case kCondGE: 967 case kCondLE: 968 case kCondGT: 969 case kCondLTU: 970 case kCondGEU: 971 case kUncond: 972 LOG(FATAL) << "Unexpected branch condition " << cond; 973 UNREACHABLE(); 974 } 975 } 976 977 void Mips64Assembler::AddS(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 978 EmitFR(0x11, 0x10, ft, fs, fd, 0x0); 979 } 980 981 void Mips64Assembler::SubS(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 982 EmitFR(0x11, 0x10, ft, fs, fd, 0x1); 983 } 984 985 void Mips64Assembler::MulS(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 986 EmitFR(0x11, 0x10, ft, fs, fd, 0x2); 987 } 988 989 void Mips64Assembler::DivS(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 990 EmitFR(0x11, 0x10, ft, fs, fd, 0x3); 991 } 992 993 void Mips64Assembler::AddD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 994 EmitFR(0x11, 0x11, ft, fs, fd, 0x0); 995 } 996 997 void Mips64Assembler::SubD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 998 EmitFR(0x11, 0x11, ft, fs, fd, 0x1); 999 } 1000 1001 void Mips64Assembler::MulD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1002 EmitFR(0x11, 0x11, ft, fs, fd, 0x2); 1003 } 1004 1005 void Mips64Assembler::DivD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1006 EmitFR(0x11, 0x11, ft, fs, fd, 0x3); 1007 } 1008 1009 void Mips64Assembler::SqrtS(FpuRegister fd, FpuRegister fs) { 1010 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x4); 1011 } 1012 1013 void Mips64Assembler::SqrtD(FpuRegister fd, FpuRegister fs) { 1014 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x4); 1015 } 1016 1017 void Mips64Assembler::AbsS(FpuRegister fd, FpuRegister fs) { 1018 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x5); 1019 } 1020 1021 void Mips64Assembler::AbsD(FpuRegister fd, FpuRegister fs) { 1022 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x5); 1023 } 1024 1025 void Mips64Assembler::MovS(FpuRegister fd, FpuRegister fs) { 1026 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x6); 1027 } 1028 1029 void Mips64Assembler::MovD(FpuRegister fd, FpuRegister fs) { 1030 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x6); 1031 } 1032 1033 void Mips64Assembler::NegS(FpuRegister fd, FpuRegister fs) { 1034 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x7); 1035 } 1036 1037 void Mips64Assembler::NegD(FpuRegister fd, FpuRegister fs) { 1038 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x7); 1039 } 1040 1041 void Mips64Assembler::RoundLS(FpuRegister fd, FpuRegister fs) { 1042 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x8); 1043 } 1044 1045 void Mips64Assembler::RoundLD(FpuRegister fd, FpuRegister fs) { 1046 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x8); 1047 } 1048 1049 void Mips64Assembler::RoundWS(FpuRegister fd, FpuRegister fs) { 1050 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xc); 1051 } 1052 1053 void Mips64Assembler::RoundWD(FpuRegister fd, FpuRegister fs) { 1054 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xc); 1055 } 1056 1057 void Mips64Assembler::TruncLS(FpuRegister fd, FpuRegister fs) { 1058 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x9); 1059 } 1060 1061 void Mips64Assembler::TruncLD(FpuRegister fd, FpuRegister fs) { 1062 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x9); 1063 } 1064 1065 void Mips64Assembler::TruncWS(FpuRegister fd, FpuRegister fs) { 1066 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xd); 1067 } 1068 1069 void Mips64Assembler::TruncWD(FpuRegister fd, FpuRegister fs) { 1070 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xd); 1071 } 1072 1073 void Mips64Assembler::CeilLS(FpuRegister fd, FpuRegister fs) { 1074 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xa); 1075 } 1076 1077 void Mips64Assembler::CeilLD(FpuRegister fd, FpuRegister fs) { 1078 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xa); 1079 } 1080 1081 void Mips64Assembler::CeilWS(FpuRegister fd, FpuRegister fs) { 1082 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xe); 1083 } 1084 1085 void Mips64Assembler::CeilWD(FpuRegister fd, FpuRegister fs) { 1086 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xe); 1087 } 1088 1089 void Mips64Assembler::FloorLS(FpuRegister fd, FpuRegister fs) { 1090 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xb); 1091 } 1092 1093 void Mips64Assembler::FloorLD(FpuRegister fd, FpuRegister fs) { 1094 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xb); 1095 } 1096 1097 void Mips64Assembler::FloorWS(FpuRegister fd, FpuRegister fs) { 1098 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xf); 1099 } 1100 1101 void Mips64Assembler::FloorWD(FpuRegister fd, FpuRegister fs) { 1102 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xf); 1103 } 1104 1105 void Mips64Assembler::SelS(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1106 EmitFR(0x11, 0x10, ft, fs, fd, 0x10); 1107 } 1108 1109 void Mips64Assembler::SelD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1110 EmitFR(0x11, 0x11, ft, fs, fd, 0x10); 1111 } 1112 1113 void Mips64Assembler::SeleqzS(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1114 EmitFR(0x11, 0x10, ft, fs, fd, 0x14); 1115 } 1116 1117 void Mips64Assembler::SeleqzD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1118 EmitFR(0x11, 0x11, ft, fs, fd, 0x14); 1119 } 1120 1121 void Mips64Assembler::SelnezS(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1122 EmitFR(0x11, 0x10, ft, fs, fd, 0x17); 1123 } 1124 1125 void Mips64Assembler::SelnezD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1126 EmitFR(0x11, 0x11, ft, fs, fd, 0x17); 1127 } 1128 1129 void Mips64Assembler::RintS(FpuRegister fd, FpuRegister fs) { 1130 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x1a); 1131 } 1132 1133 void Mips64Assembler::RintD(FpuRegister fd, FpuRegister fs) { 1134 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x1a); 1135 } 1136 1137 void Mips64Assembler::ClassS(FpuRegister fd, FpuRegister fs) { 1138 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x1b); 1139 } 1140 1141 void Mips64Assembler::ClassD(FpuRegister fd, FpuRegister fs) { 1142 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x1b); 1143 } 1144 1145 void Mips64Assembler::MinS(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1146 EmitFR(0x11, 0x10, ft, fs, fd, 0x1c); 1147 } 1148 1149 void Mips64Assembler::MinD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1150 EmitFR(0x11, 0x11, ft, fs, fd, 0x1c); 1151 } 1152 1153 void Mips64Assembler::MaxS(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1154 EmitFR(0x11, 0x10, ft, fs, fd, 0x1e); 1155 } 1156 1157 void Mips64Assembler::MaxD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1158 EmitFR(0x11, 0x11, ft, fs, fd, 0x1e); 1159 } 1160 1161 void Mips64Assembler::CmpUnS(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1162 EmitFR(0x11, 0x14, ft, fs, fd, 0x01); 1163 } 1164 1165 void Mips64Assembler::CmpEqS(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1166 EmitFR(0x11, 0x14, ft, fs, fd, 0x02); 1167 } 1168 1169 void Mips64Assembler::CmpUeqS(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1170 EmitFR(0x11, 0x14, ft, fs, fd, 0x03); 1171 } 1172 1173 void Mips64Assembler::CmpLtS(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1174 EmitFR(0x11, 0x14, ft, fs, fd, 0x04); 1175 } 1176 1177 void Mips64Assembler::CmpUltS(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1178 EmitFR(0x11, 0x14, ft, fs, fd, 0x05); 1179 } 1180 1181 void Mips64Assembler::CmpLeS(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1182 EmitFR(0x11, 0x14, ft, fs, fd, 0x06); 1183 } 1184 1185 void Mips64Assembler::CmpUleS(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1186 EmitFR(0x11, 0x14, ft, fs, fd, 0x07); 1187 } 1188 1189 void Mips64Assembler::CmpOrS(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1190 EmitFR(0x11, 0x14, ft, fs, fd, 0x11); 1191 } 1192 1193 void Mips64Assembler::CmpUneS(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1194 EmitFR(0x11, 0x14, ft, fs, fd, 0x12); 1195 } 1196 1197 void Mips64Assembler::CmpNeS(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1198 EmitFR(0x11, 0x14, ft, fs, fd, 0x13); 1199 } 1200 1201 void Mips64Assembler::CmpUnD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1202 EmitFR(0x11, 0x15, ft, fs, fd, 0x01); 1203 } 1204 1205 void Mips64Assembler::CmpEqD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1206 EmitFR(0x11, 0x15, ft, fs, fd, 0x02); 1207 } 1208 1209 void Mips64Assembler::CmpUeqD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1210 EmitFR(0x11, 0x15, ft, fs, fd, 0x03); 1211 } 1212 1213 void Mips64Assembler::CmpLtD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1214 EmitFR(0x11, 0x15, ft, fs, fd, 0x04); 1215 } 1216 1217 void Mips64Assembler::CmpUltD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1218 EmitFR(0x11, 0x15, ft, fs, fd, 0x05); 1219 } 1220 1221 void Mips64Assembler::CmpLeD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1222 EmitFR(0x11, 0x15, ft, fs, fd, 0x06); 1223 } 1224 1225 void Mips64Assembler::CmpUleD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1226 EmitFR(0x11, 0x15, ft, fs, fd, 0x07); 1227 } 1228 1229 void Mips64Assembler::CmpOrD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1230 EmitFR(0x11, 0x15, ft, fs, fd, 0x11); 1231 } 1232 1233 void Mips64Assembler::CmpUneD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1234 EmitFR(0x11, 0x15, ft, fs, fd, 0x12); 1235 } 1236 1237 void Mips64Assembler::CmpNeD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1238 EmitFR(0x11, 0x15, ft, fs, fd, 0x13); 1239 } 1240 1241 void Mips64Assembler::Cvtsw(FpuRegister fd, FpuRegister fs) { 1242 EmitFR(0x11, 0x14, static_cast<FpuRegister>(0), fs, fd, 0x20); 1243 } 1244 1245 void Mips64Assembler::Cvtdw(FpuRegister fd, FpuRegister fs) { 1246 EmitFR(0x11, 0x14, static_cast<FpuRegister>(0), fs, fd, 0x21); 1247 } 1248 1249 void Mips64Assembler::Cvtsd(FpuRegister fd, FpuRegister fs) { 1250 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x20); 1251 } 1252 1253 void Mips64Assembler::Cvtds(FpuRegister fd, FpuRegister fs) { 1254 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x21); 1255 } 1256 1257 void Mips64Assembler::Cvtsl(FpuRegister fd, FpuRegister fs) { 1258 EmitFR(0x11, 0x15, static_cast<FpuRegister>(0), fs, fd, 0x20); 1259 } 1260 1261 void Mips64Assembler::Cvtdl(FpuRegister fd, FpuRegister fs) { 1262 EmitFR(0x11, 0x15, static_cast<FpuRegister>(0), fs, fd, 0x21); 1263 } 1264 1265 void Mips64Assembler::Mfc1(GpuRegister rt, FpuRegister fs) { 1266 EmitFR(0x11, 0x00, static_cast<FpuRegister>(rt), fs, static_cast<FpuRegister>(0), 0x0); 1267 } 1268 1269 void Mips64Assembler::Mfhc1(GpuRegister rt, FpuRegister fs) { 1270 EmitFR(0x11, 0x03, static_cast<FpuRegister>(rt), fs, static_cast<FpuRegister>(0), 0x0); 1271 } 1272 1273 void Mips64Assembler::Mtc1(GpuRegister rt, FpuRegister fs) { 1274 EmitFR(0x11, 0x04, static_cast<FpuRegister>(rt), fs, static_cast<FpuRegister>(0), 0x0); 1275 } 1276 1277 void Mips64Assembler::Mthc1(GpuRegister rt, FpuRegister fs) { 1278 EmitFR(0x11, 0x07, static_cast<FpuRegister>(rt), fs, static_cast<FpuRegister>(0), 0x0); 1279 } 1280 1281 void Mips64Assembler::Dmfc1(GpuRegister rt, FpuRegister fs) { 1282 EmitFR(0x11, 0x01, static_cast<FpuRegister>(rt), fs, static_cast<FpuRegister>(0), 0x0); 1283 } 1284 1285 void Mips64Assembler::Dmtc1(GpuRegister rt, FpuRegister fs) { 1286 EmitFR(0x11, 0x05, static_cast<FpuRegister>(rt), fs, static_cast<FpuRegister>(0), 0x0); 1287 } 1288 1289 void Mips64Assembler::Lwc1(FpuRegister ft, GpuRegister rs, uint16_t imm16) { 1290 EmitI(0x31, rs, static_cast<GpuRegister>(ft), imm16); 1291 } 1292 1293 void Mips64Assembler::Ldc1(FpuRegister ft, GpuRegister rs, uint16_t imm16) { 1294 EmitI(0x35, rs, static_cast<GpuRegister>(ft), imm16); 1295 } 1296 1297 void Mips64Assembler::Swc1(FpuRegister ft, GpuRegister rs, uint16_t imm16) { 1298 EmitI(0x39, rs, static_cast<GpuRegister>(ft), imm16); 1299 } 1300 1301 void Mips64Assembler::Sdc1(FpuRegister ft, GpuRegister rs, uint16_t imm16) { 1302 EmitI(0x3d, rs, static_cast<GpuRegister>(ft), imm16); 1303 } 1304 1305 void Mips64Assembler::Break() { 1306 EmitR(0, static_cast<GpuRegister>(0), static_cast<GpuRegister>(0), 1307 static_cast<GpuRegister>(0), 0, 0xD); 1308 } 1309 1310 void Mips64Assembler::Nop() { 1311 EmitR(0x0, static_cast<GpuRegister>(0), static_cast<GpuRegister>(0), 1312 static_cast<GpuRegister>(0), 0, 0x0); 1313 } 1314 1315 void Mips64Assembler::Move(GpuRegister rd, GpuRegister rs) { 1316 Or(rd, rs, ZERO); 1317 } 1318 1319 void Mips64Assembler::Clear(GpuRegister rd) { 1320 Move(rd, ZERO); 1321 } 1322 1323 void Mips64Assembler::Not(GpuRegister rd, GpuRegister rs) { 1324 Nor(rd, rs, ZERO); 1325 } 1326 1327 void Mips64Assembler::AndV(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1328 CHECK(HasMsa()); 1329 EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x1e); 1330 } 1331 1332 void Mips64Assembler::OrV(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1333 CHECK(HasMsa()); 1334 EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x1e); 1335 } 1336 1337 void Mips64Assembler::NorV(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1338 CHECK(HasMsa()); 1339 EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x1e); 1340 } 1341 1342 void Mips64Assembler::XorV(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1343 CHECK(HasMsa()); 1344 EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x1e); 1345 } 1346 1347 void Mips64Assembler::AddvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1348 CHECK(HasMsa()); 1349 EmitMsa3R(0x0, 0x0, wt, ws, wd, 0xe); 1350 } 1351 1352 void Mips64Assembler::AddvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1353 CHECK(HasMsa()); 1354 EmitMsa3R(0x0, 0x1, wt, ws, wd, 0xe); 1355 } 1356 1357 void Mips64Assembler::AddvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1358 CHECK(HasMsa()); 1359 EmitMsa3R(0x0, 0x2, wt, ws, wd, 0xe); 1360 } 1361 1362 void Mips64Assembler::AddvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1363 CHECK(HasMsa()); 1364 EmitMsa3R(0x0, 0x3, wt, ws, wd, 0xe); 1365 } 1366 1367 void Mips64Assembler::SubvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1368 CHECK(HasMsa()); 1369 EmitMsa3R(0x1, 0x0, wt, ws, wd, 0xe); 1370 } 1371 1372 void Mips64Assembler::SubvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1373 CHECK(HasMsa()); 1374 EmitMsa3R(0x1, 0x1, wt, ws, wd, 0xe); 1375 } 1376 1377 void Mips64Assembler::SubvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1378 CHECK(HasMsa()); 1379 EmitMsa3R(0x1, 0x2, wt, ws, wd, 0xe); 1380 } 1381 1382 void Mips64Assembler::SubvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1383 CHECK(HasMsa()); 1384 EmitMsa3R(0x1, 0x3, wt, ws, wd, 0xe); 1385 } 1386 1387 void Mips64Assembler::Asub_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1388 CHECK(HasMsa()); 1389 EmitMsa3R(0x4, 0x0, wt, ws, wd, 0x11); 1390 } 1391 1392 void Mips64Assembler::Asub_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1393 CHECK(HasMsa()); 1394 EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x11); 1395 } 1396 1397 void Mips64Assembler::Asub_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1398 CHECK(HasMsa()); 1399 EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x11); 1400 } 1401 1402 void Mips64Assembler::Asub_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1403 CHECK(HasMsa()); 1404 EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x11); 1405 } 1406 1407 void Mips64Assembler::Asub_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1408 CHECK(HasMsa()); 1409 EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x11); 1410 } 1411 1412 void Mips64Assembler::Asub_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1413 CHECK(HasMsa()); 1414 EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x11); 1415 } 1416 1417 void Mips64Assembler::Asub_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1418 CHECK(HasMsa()); 1419 EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x11); 1420 } 1421 1422 void Mips64Assembler::Asub_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1423 CHECK(HasMsa()); 1424 EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x11); 1425 } 1426 1427 void Mips64Assembler::MulvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1428 CHECK(HasMsa()); 1429 EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x12); 1430 } 1431 1432 void Mips64Assembler::MulvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1433 CHECK(HasMsa()); 1434 EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x12); 1435 } 1436 1437 void Mips64Assembler::MulvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1438 CHECK(HasMsa()); 1439 EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x12); 1440 } 1441 1442 void Mips64Assembler::MulvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1443 CHECK(HasMsa()); 1444 EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x12); 1445 } 1446 1447 void Mips64Assembler::Div_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1448 CHECK(HasMsa()); 1449 EmitMsa3R(0x4, 0x0, wt, ws, wd, 0x12); 1450 } 1451 1452 void Mips64Assembler::Div_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1453 CHECK(HasMsa()); 1454 EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x12); 1455 } 1456 1457 void Mips64Assembler::Div_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1458 CHECK(HasMsa()); 1459 EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x12); 1460 } 1461 1462 void Mips64Assembler::Div_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1463 CHECK(HasMsa()); 1464 EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x12); 1465 } 1466 1467 void Mips64Assembler::Div_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1468 CHECK(HasMsa()); 1469 EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x12); 1470 } 1471 1472 void Mips64Assembler::Div_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1473 CHECK(HasMsa()); 1474 EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x12); 1475 } 1476 1477 void Mips64Assembler::Div_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1478 CHECK(HasMsa()); 1479 EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x12); 1480 } 1481 1482 void Mips64Assembler::Div_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1483 CHECK(HasMsa()); 1484 EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x12); 1485 } 1486 1487 void Mips64Assembler::Mod_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1488 CHECK(HasMsa()); 1489 EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x12); 1490 } 1491 1492 void Mips64Assembler::Mod_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1493 CHECK(HasMsa()); 1494 EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x12); 1495 } 1496 1497 void Mips64Assembler::Mod_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1498 CHECK(HasMsa()); 1499 EmitMsa3R(0x6, 0x2, wt, ws, wd, 0x12); 1500 } 1501 1502 void Mips64Assembler::Mod_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1503 CHECK(HasMsa()); 1504 EmitMsa3R(0x6, 0x3, wt, ws, wd, 0x12); 1505 } 1506 1507 void Mips64Assembler::Mod_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1508 CHECK(HasMsa()); 1509 EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x12); 1510 } 1511 1512 void Mips64Assembler::Mod_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1513 CHECK(HasMsa()); 1514 EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x12); 1515 } 1516 1517 void Mips64Assembler::Mod_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1518 CHECK(HasMsa()); 1519 EmitMsa3R(0x7, 0x2, wt, ws, wd, 0x12); 1520 } 1521 1522 void Mips64Assembler::Mod_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1523 CHECK(HasMsa()); 1524 EmitMsa3R(0x7, 0x3, wt, ws, wd, 0x12); 1525 } 1526 1527 void Mips64Assembler::Add_aB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1528 CHECK(HasMsa()); 1529 EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x10); 1530 } 1531 1532 void Mips64Assembler::Add_aH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1533 CHECK(HasMsa()); 1534 EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x10); 1535 } 1536 1537 void Mips64Assembler::Add_aW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1538 CHECK(HasMsa()); 1539 EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x10); 1540 } 1541 1542 void Mips64Assembler::Add_aD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1543 CHECK(HasMsa()); 1544 EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x10); 1545 } 1546 1547 void Mips64Assembler::Ave_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1548 CHECK(HasMsa()); 1549 EmitMsa3R(0x4, 0x0, wt, ws, wd, 0x10); 1550 } 1551 1552 void Mips64Assembler::Ave_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1553 CHECK(HasMsa()); 1554 EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x10); 1555 } 1556 1557 void Mips64Assembler::Ave_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1558 CHECK(HasMsa()); 1559 EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x10); 1560 } 1561 1562 void Mips64Assembler::Ave_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1563 CHECK(HasMsa()); 1564 EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x10); 1565 } 1566 1567 void Mips64Assembler::Ave_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1568 CHECK(HasMsa()); 1569 EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x10); 1570 } 1571 1572 void Mips64Assembler::Ave_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1573 CHECK(HasMsa()); 1574 EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x10); 1575 } 1576 1577 void Mips64Assembler::Ave_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1578 CHECK(HasMsa()); 1579 EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x10); 1580 } 1581 1582 void Mips64Assembler::Ave_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1583 CHECK(HasMsa()); 1584 EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x10); 1585 } 1586 1587 void Mips64Assembler::Aver_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1588 CHECK(HasMsa()); 1589 EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x10); 1590 } 1591 1592 void Mips64Assembler::Aver_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1593 CHECK(HasMsa()); 1594 EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x10); 1595 } 1596 1597 void Mips64Assembler::Aver_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1598 CHECK(HasMsa()); 1599 EmitMsa3R(0x6, 0x2, wt, ws, wd, 0x10); 1600 } 1601 1602 void Mips64Assembler::Aver_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1603 CHECK(HasMsa()); 1604 EmitMsa3R(0x6, 0x3, wt, ws, wd, 0x10); 1605 } 1606 1607 void Mips64Assembler::Aver_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1608 CHECK(HasMsa()); 1609 EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x10); 1610 } 1611 1612 void Mips64Assembler::Aver_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1613 CHECK(HasMsa()); 1614 EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x10); 1615 } 1616 1617 void Mips64Assembler::Aver_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1618 CHECK(HasMsa()); 1619 EmitMsa3R(0x7, 0x2, wt, ws, wd, 0x10); 1620 } 1621 1622 void Mips64Assembler::Aver_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1623 CHECK(HasMsa()); 1624 EmitMsa3R(0x7, 0x3, wt, ws, wd, 0x10); 1625 } 1626 1627 void Mips64Assembler::Max_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1628 CHECK(HasMsa()); 1629 EmitMsa3R(0x2, 0x0, wt, ws, wd, 0xe); 1630 } 1631 1632 void Mips64Assembler::Max_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1633 CHECK(HasMsa()); 1634 EmitMsa3R(0x2, 0x1, wt, ws, wd, 0xe); 1635 } 1636 1637 void Mips64Assembler::Max_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1638 CHECK(HasMsa()); 1639 EmitMsa3R(0x2, 0x2, wt, ws, wd, 0xe); 1640 } 1641 1642 void Mips64Assembler::Max_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1643 CHECK(HasMsa()); 1644 EmitMsa3R(0x2, 0x3, wt, ws, wd, 0xe); 1645 } 1646 1647 void Mips64Assembler::Max_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1648 CHECK(HasMsa()); 1649 EmitMsa3R(0x3, 0x0, wt, ws, wd, 0xe); 1650 } 1651 1652 void Mips64Assembler::Max_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1653 CHECK(HasMsa()); 1654 EmitMsa3R(0x3, 0x1, wt, ws, wd, 0xe); 1655 } 1656 1657 void Mips64Assembler::Max_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1658 CHECK(HasMsa()); 1659 EmitMsa3R(0x3, 0x2, wt, ws, wd, 0xe); 1660 } 1661 1662 void Mips64Assembler::Max_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1663 CHECK(HasMsa()); 1664 EmitMsa3R(0x3, 0x3, wt, ws, wd, 0xe); 1665 } 1666 1667 void Mips64Assembler::Min_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1668 CHECK(HasMsa()); 1669 EmitMsa3R(0x4, 0x0, wt, ws, wd, 0xe); 1670 } 1671 1672 void Mips64Assembler::Min_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1673 CHECK(HasMsa()); 1674 EmitMsa3R(0x4, 0x1, wt, ws, wd, 0xe); 1675 } 1676 1677 void Mips64Assembler::Min_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1678 CHECK(HasMsa()); 1679 EmitMsa3R(0x4, 0x2, wt, ws, wd, 0xe); 1680 } 1681 1682 void Mips64Assembler::Min_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1683 CHECK(HasMsa()); 1684 EmitMsa3R(0x4, 0x3, wt, ws, wd, 0xe); 1685 } 1686 1687 void Mips64Assembler::Min_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1688 CHECK(HasMsa()); 1689 EmitMsa3R(0x5, 0x0, wt, ws, wd, 0xe); 1690 } 1691 1692 void Mips64Assembler::Min_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1693 CHECK(HasMsa()); 1694 EmitMsa3R(0x5, 0x1, wt, ws, wd, 0xe); 1695 } 1696 1697 void Mips64Assembler::Min_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1698 CHECK(HasMsa()); 1699 EmitMsa3R(0x5, 0x2, wt, ws, wd, 0xe); 1700 } 1701 1702 void Mips64Assembler::Min_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1703 CHECK(HasMsa()); 1704 EmitMsa3R(0x5, 0x3, wt, ws, wd, 0xe); 1705 } 1706 1707 void Mips64Assembler::FaddW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1708 CHECK(HasMsa()); 1709 EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x1b); 1710 } 1711 1712 void Mips64Assembler::FaddD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1713 CHECK(HasMsa()); 1714 EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x1b); 1715 } 1716 1717 void Mips64Assembler::FsubW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1718 CHECK(HasMsa()); 1719 EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x1b); 1720 } 1721 1722 void Mips64Assembler::FsubD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1723 CHECK(HasMsa()); 1724 EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x1b); 1725 } 1726 1727 void Mips64Assembler::FmulW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1728 CHECK(HasMsa()); 1729 EmitMsa3R(0x1, 0x0, wt, ws, wd, 0x1b); 1730 } 1731 1732 void Mips64Assembler::FmulD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1733 CHECK(HasMsa()); 1734 EmitMsa3R(0x1, 0x1, wt, ws, wd, 0x1b); 1735 } 1736 1737 void Mips64Assembler::FdivW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1738 CHECK(HasMsa()); 1739 EmitMsa3R(0x1, 0x2, wt, ws, wd, 0x1b); 1740 } 1741 1742 void Mips64Assembler::FdivD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1743 CHECK(HasMsa()); 1744 EmitMsa3R(0x1, 0x3, wt, ws, wd, 0x1b); 1745 } 1746 1747 void Mips64Assembler::FmaxW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1748 CHECK(HasMsa()); 1749 EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x1b); 1750 } 1751 1752 void Mips64Assembler::FmaxD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1753 CHECK(HasMsa()); 1754 EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x1b); 1755 } 1756 1757 void Mips64Assembler::FminW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1758 CHECK(HasMsa()); 1759 EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x1b); 1760 } 1761 1762 void Mips64Assembler::FminD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1763 CHECK(HasMsa()); 1764 EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x1b); 1765 } 1766 1767 void Mips64Assembler::Ffint_sW(VectorRegister wd, VectorRegister ws) { 1768 CHECK(HasMsa()); 1769 EmitMsa2RF(0x19e, 0x0, ws, wd, 0x1e); 1770 } 1771 1772 void Mips64Assembler::Ffint_sD(VectorRegister wd, VectorRegister ws) { 1773 CHECK(HasMsa()); 1774 EmitMsa2RF(0x19e, 0x1, ws, wd, 0x1e); 1775 } 1776 1777 void Mips64Assembler::Ftint_sW(VectorRegister wd, VectorRegister ws) { 1778 CHECK(HasMsa()); 1779 EmitMsa2RF(0x19c, 0x0, ws, wd, 0x1e); 1780 } 1781 1782 void Mips64Assembler::Ftint_sD(VectorRegister wd, VectorRegister ws) { 1783 CHECK(HasMsa()); 1784 EmitMsa2RF(0x19c, 0x1, ws, wd, 0x1e); 1785 } 1786 1787 void Mips64Assembler::SllB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1788 CHECK(HasMsa()); 1789 EmitMsa3R(0x0, 0x0, wt, ws, wd, 0xd); 1790 } 1791 1792 void Mips64Assembler::SllH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1793 CHECK(HasMsa()); 1794 EmitMsa3R(0x0, 0x1, wt, ws, wd, 0xd); 1795 } 1796 1797 void Mips64Assembler::SllW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1798 CHECK(HasMsa()); 1799 EmitMsa3R(0x0, 0x2, wt, ws, wd, 0xd); 1800 } 1801 1802 void Mips64Assembler::SllD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1803 CHECK(HasMsa()); 1804 EmitMsa3R(0x0, 0x3, wt, ws, wd, 0xd); 1805 } 1806 1807 void Mips64Assembler::SraB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1808 CHECK(HasMsa()); 1809 EmitMsa3R(0x1, 0x0, wt, ws, wd, 0xd); 1810 } 1811 1812 void Mips64Assembler::SraH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1813 CHECK(HasMsa()); 1814 EmitMsa3R(0x1, 0x1, wt, ws, wd, 0xd); 1815 } 1816 1817 void Mips64Assembler::SraW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1818 CHECK(HasMsa()); 1819 EmitMsa3R(0x1, 0x2, wt, ws, wd, 0xd); 1820 } 1821 1822 void Mips64Assembler::SraD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1823 CHECK(HasMsa()); 1824 EmitMsa3R(0x1, 0x3, wt, ws, wd, 0xd); 1825 } 1826 1827 void Mips64Assembler::SrlB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1828 CHECK(HasMsa()); 1829 EmitMsa3R(0x2, 0x0, wt, ws, wd, 0xd); 1830 } 1831 1832 void Mips64Assembler::SrlH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1833 CHECK(HasMsa()); 1834 EmitMsa3R(0x2, 0x1, wt, ws, wd, 0xd); 1835 } 1836 1837 void Mips64Assembler::SrlW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1838 CHECK(HasMsa()); 1839 EmitMsa3R(0x2, 0x2, wt, ws, wd, 0xd); 1840 } 1841 1842 void Mips64Assembler::SrlD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1843 CHECK(HasMsa()); 1844 EmitMsa3R(0x2, 0x3, wt, ws, wd, 0xd); 1845 } 1846 1847 void Mips64Assembler::SlliB(VectorRegister wd, VectorRegister ws, int shamt3) { 1848 CHECK(HasMsa()); 1849 CHECK(IsUint<3>(shamt3)) << shamt3; 1850 EmitMsaBIT(0x0, shamt3 | kMsaDfMByteMask, ws, wd, 0x9); 1851 } 1852 1853 void Mips64Assembler::SlliH(VectorRegister wd, VectorRegister ws, int shamt4) { 1854 CHECK(HasMsa()); 1855 CHECK(IsUint<4>(shamt4)) << shamt4; 1856 EmitMsaBIT(0x0, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9); 1857 } 1858 1859 void Mips64Assembler::SlliW(VectorRegister wd, VectorRegister ws, int shamt5) { 1860 CHECK(HasMsa()); 1861 CHECK(IsUint<5>(shamt5)) << shamt5; 1862 EmitMsaBIT(0x0, shamt5 | kMsaDfMWordMask, ws, wd, 0x9); 1863 } 1864 1865 void Mips64Assembler::SlliD(VectorRegister wd, VectorRegister ws, int shamt6) { 1866 CHECK(HasMsa()); 1867 CHECK(IsUint<6>(shamt6)) << shamt6; 1868 EmitMsaBIT(0x0, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9); 1869 } 1870 1871 void Mips64Assembler::SraiB(VectorRegister wd, VectorRegister ws, int shamt3) { 1872 CHECK(HasMsa()); 1873 CHECK(IsUint<3>(shamt3)) << shamt3; 1874 EmitMsaBIT(0x1, shamt3 | kMsaDfMByteMask, ws, wd, 0x9); 1875 } 1876 1877 void Mips64Assembler::SraiH(VectorRegister wd, VectorRegister ws, int shamt4) { 1878 CHECK(HasMsa()); 1879 CHECK(IsUint<4>(shamt4)) << shamt4; 1880 EmitMsaBIT(0x1, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9); 1881 } 1882 1883 void Mips64Assembler::SraiW(VectorRegister wd, VectorRegister ws, int shamt5) { 1884 CHECK(HasMsa()); 1885 CHECK(IsUint<5>(shamt5)) << shamt5; 1886 EmitMsaBIT(0x1, shamt5 | kMsaDfMWordMask, ws, wd, 0x9); 1887 } 1888 1889 void Mips64Assembler::SraiD(VectorRegister wd, VectorRegister ws, int shamt6) { 1890 CHECK(HasMsa()); 1891 CHECK(IsUint<6>(shamt6)) << shamt6; 1892 EmitMsaBIT(0x1, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9); 1893 } 1894 1895 void Mips64Assembler::SrliB(VectorRegister wd, VectorRegister ws, int shamt3) { 1896 CHECK(HasMsa()); 1897 CHECK(IsUint<3>(shamt3)) << shamt3; 1898 EmitMsaBIT(0x2, shamt3 | kMsaDfMByteMask, ws, wd, 0x9); 1899 } 1900 1901 void Mips64Assembler::SrliH(VectorRegister wd, VectorRegister ws, int shamt4) { 1902 CHECK(HasMsa()); 1903 CHECK(IsUint<4>(shamt4)) << shamt4; 1904 EmitMsaBIT(0x2, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9); 1905 } 1906 1907 void Mips64Assembler::SrliW(VectorRegister wd, VectorRegister ws, int shamt5) { 1908 CHECK(HasMsa()); 1909 CHECK(IsUint<5>(shamt5)) << shamt5; 1910 EmitMsaBIT(0x2, shamt5 | kMsaDfMWordMask, ws, wd, 0x9); 1911 } 1912 1913 void Mips64Assembler::SrliD(VectorRegister wd, VectorRegister ws, int shamt6) { 1914 CHECK(HasMsa()); 1915 CHECK(IsUint<6>(shamt6)) << shamt6; 1916 EmitMsaBIT(0x2, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9); 1917 } 1918 1919 void Mips64Assembler::MoveV(VectorRegister wd, VectorRegister ws) { 1920 CHECK(HasMsa()); 1921 EmitMsaBIT(0x1, 0x3e, ws, wd, 0x19); 1922 } 1923 1924 void Mips64Assembler::SplatiB(VectorRegister wd, VectorRegister ws, int n4) { 1925 CHECK(HasMsa()); 1926 CHECK(IsUint<4>(n4)) << n4; 1927 EmitMsaELM(0x1, n4 | kMsaDfNByteMask, ws, wd, 0x19); 1928 } 1929 1930 void Mips64Assembler::SplatiH(VectorRegister wd, VectorRegister ws, int n3) { 1931 CHECK(HasMsa()); 1932 CHECK(IsUint<3>(n3)) << n3; 1933 EmitMsaELM(0x1, n3 | kMsaDfNHalfwordMask, ws, wd, 0x19); 1934 } 1935 1936 void Mips64Assembler::SplatiW(VectorRegister wd, VectorRegister ws, int n2) { 1937 CHECK(HasMsa()); 1938 CHECK(IsUint<2>(n2)) << n2; 1939 EmitMsaELM(0x1, n2 | kMsaDfNWordMask, ws, wd, 0x19); 1940 } 1941 1942 void Mips64Assembler::SplatiD(VectorRegister wd, VectorRegister ws, int n1) { 1943 CHECK(HasMsa()); 1944 CHECK(IsUint<1>(n1)) << n1; 1945 EmitMsaELM(0x1, n1 | kMsaDfNDoublewordMask, ws, wd, 0x19); 1946 } 1947 1948 void Mips64Assembler::Copy_sB(GpuRegister rd, VectorRegister ws, int n4) { 1949 CHECK(HasMsa()); 1950 CHECK(IsUint<4>(n4)) << n4; 1951 EmitMsaELM(0x2, n4 | kMsaDfNByteMask, ws, static_cast<VectorRegister>(rd), 0x19); 1952 } 1953 1954 void Mips64Assembler::Copy_sH(GpuRegister rd, VectorRegister ws, int n3) { 1955 CHECK(HasMsa()); 1956 CHECK(IsUint<3>(n3)) << n3; 1957 EmitMsaELM(0x2, n3 | kMsaDfNHalfwordMask, ws, static_cast<VectorRegister>(rd), 0x19); 1958 } 1959 1960 void Mips64Assembler::Copy_sW(GpuRegister rd, VectorRegister ws, int n2) { 1961 CHECK(HasMsa()); 1962 CHECK(IsUint<2>(n2)) << n2; 1963 EmitMsaELM(0x2, n2 | kMsaDfNWordMask, ws, static_cast<VectorRegister>(rd), 0x19); 1964 } 1965 1966 void Mips64Assembler::Copy_sD(GpuRegister rd, VectorRegister ws, int n1) { 1967 CHECK(HasMsa()); 1968 CHECK(IsUint<1>(n1)) << n1; 1969 EmitMsaELM(0x2, n1 | kMsaDfNDoublewordMask, ws, static_cast<VectorRegister>(rd), 0x19); 1970 } 1971 1972 void Mips64Assembler::Copy_uB(GpuRegister rd, VectorRegister ws, int n4) { 1973 CHECK(HasMsa()); 1974 CHECK(IsUint<4>(n4)) << n4; 1975 EmitMsaELM(0x3, n4 | kMsaDfNByteMask, ws, static_cast<VectorRegister>(rd), 0x19); 1976 } 1977 1978 void Mips64Assembler::Copy_uH(GpuRegister rd, VectorRegister ws, int n3) { 1979 CHECK(HasMsa()); 1980 CHECK(IsUint<3>(n3)) << n3; 1981 EmitMsaELM(0x3, n3 | kMsaDfNHalfwordMask, ws, static_cast<VectorRegister>(rd), 0x19); 1982 } 1983 1984 void Mips64Assembler::Copy_uW(GpuRegister rd, VectorRegister ws, int n2) { 1985 CHECK(HasMsa()); 1986 CHECK(IsUint<2>(n2)) << n2; 1987 EmitMsaELM(0x3, n2 | kMsaDfNWordMask, ws, static_cast<VectorRegister>(rd), 0x19); 1988 } 1989 1990 void Mips64Assembler::InsertB(VectorRegister wd, GpuRegister rs, int n4) { 1991 CHECK(HasMsa()); 1992 CHECK(IsUint<4>(n4)) << n4; 1993 EmitMsaELM(0x4, n4 | kMsaDfNByteMask, static_cast<VectorRegister>(rs), wd, 0x19); 1994 } 1995 1996 void Mips64Assembler::InsertH(VectorRegister wd, GpuRegister rs, int n3) { 1997 CHECK(HasMsa()); 1998 CHECK(IsUint<3>(n3)) << n3; 1999 EmitMsaELM(0x4, n3 | kMsaDfNHalfwordMask, static_cast<VectorRegister>(rs), wd, 0x19); 2000 } 2001 2002 void Mips64Assembler::InsertW(VectorRegister wd, GpuRegister rs, int n2) { 2003 CHECK(HasMsa()); 2004 CHECK(IsUint<2>(n2)) << n2; 2005 EmitMsaELM(0x4, n2 | kMsaDfNWordMask, static_cast<VectorRegister>(rs), wd, 0x19); 2006 } 2007 2008 void Mips64Assembler::InsertD(VectorRegister wd, GpuRegister rs, int n1) { 2009 CHECK(HasMsa()); 2010 CHECK(IsUint<1>(n1)) << n1; 2011 EmitMsaELM(0x4, n1 | kMsaDfNDoublewordMask, static_cast<VectorRegister>(rs), wd, 0x19); 2012 } 2013 2014 void Mips64Assembler::FillB(VectorRegister wd, GpuRegister rs) { 2015 CHECK(HasMsa()); 2016 EmitMsa2R(0xc0, 0x0, static_cast<VectorRegister>(rs), wd, 0x1e); 2017 } 2018 2019 void Mips64Assembler::FillH(VectorRegister wd, GpuRegister rs) { 2020 CHECK(HasMsa()); 2021 EmitMsa2R(0xc0, 0x1, static_cast<VectorRegister>(rs), wd, 0x1e); 2022 } 2023 2024 void Mips64Assembler::FillW(VectorRegister wd, GpuRegister rs) { 2025 CHECK(HasMsa()); 2026 EmitMsa2R(0xc0, 0x2, static_cast<VectorRegister>(rs), wd, 0x1e); 2027 } 2028 2029 void Mips64Assembler::FillD(VectorRegister wd, GpuRegister rs) { 2030 CHECK(HasMsa()); 2031 EmitMsa2R(0xc0, 0x3, static_cast<VectorRegister>(rs), wd, 0x1e); 2032 } 2033 2034 void Mips64Assembler::LdiB(VectorRegister wd, int imm8) { 2035 CHECK(HasMsa()); 2036 CHECK(IsInt<8>(imm8)) << imm8; 2037 EmitMsaI10(0x6, 0x0, imm8 & kMsaS10Mask, wd, 0x7); 2038 } 2039 2040 void Mips64Assembler::LdiH(VectorRegister wd, int imm10) { 2041 CHECK(HasMsa()); 2042 CHECK(IsInt<10>(imm10)) << imm10; 2043 EmitMsaI10(0x6, 0x1, imm10 & kMsaS10Mask, wd, 0x7); 2044 } 2045 2046 void Mips64Assembler::LdiW(VectorRegister wd, int imm10) { 2047 CHECK(HasMsa()); 2048 CHECK(IsInt<10>(imm10)) << imm10; 2049 EmitMsaI10(0x6, 0x2, imm10 & kMsaS10Mask, wd, 0x7); 2050 } 2051 2052 void Mips64Assembler::LdiD(VectorRegister wd, int imm10) { 2053 CHECK(HasMsa()); 2054 CHECK(IsInt<10>(imm10)) << imm10; 2055 EmitMsaI10(0x6, 0x3, imm10 & kMsaS10Mask, wd, 0x7); 2056 } 2057 2058 void Mips64Assembler::LdB(VectorRegister wd, GpuRegister rs, int offset) { 2059 CHECK(HasMsa()); 2060 CHECK(IsInt<10>(offset)) << offset; 2061 EmitMsaMI10(offset & kMsaS10Mask, rs, wd, 0x8, 0x0); 2062 } 2063 2064 void Mips64Assembler::LdH(VectorRegister wd, GpuRegister rs, int offset) { 2065 CHECK(HasMsa()); 2066 CHECK(IsInt<11>(offset)) << offset; 2067 CHECK_ALIGNED(offset, kMips64HalfwordSize); 2068 EmitMsaMI10((offset >> TIMES_2) & kMsaS10Mask, rs, wd, 0x8, 0x1); 2069 } 2070 2071 void Mips64Assembler::LdW(VectorRegister wd, GpuRegister rs, int offset) { 2072 CHECK(HasMsa()); 2073 CHECK(IsInt<12>(offset)) << offset; 2074 CHECK_ALIGNED(offset, kMips64WordSize); 2075 EmitMsaMI10((offset >> TIMES_4) & kMsaS10Mask, rs, wd, 0x8, 0x2); 2076 } 2077 2078 void Mips64Assembler::LdD(VectorRegister wd, GpuRegister rs, int offset) { 2079 CHECK(HasMsa()); 2080 CHECK(IsInt<13>(offset)) << offset; 2081 CHECK_ALIGNED(offset, kMips64DoublewordSize); 2082 EmitMsaMI10((offset >> TIMES_8) & kMsaS10Mask, rs, wd, 0x8, 0x3); 2083 } 2084 2085 void Mips64Assembler::StB(VectorRegister wd, GpuRegister rs, int offset) { 2086 CHECK(HasMsa()); 2087 CHECK(IsInt<10>(offset)) << offset; 2088 EmitMsaMI10(offset & kMsaS10Mask, rs, wd, 0x9, 0x0); 2089 } 2090 2091 void Mips64Assembler::StH(VectorRegister wd, GpuRegister rs, int offset) { 2092 CHECK(HasMsa()); 2093 CHECK(IsInt<11>(offset)) << offset; 2094 CHECK_ALIGNED(offset, kMips64HalfwordSize); 2095 EmitMsaMI10((offset >> TIMES_2) & kMsaS10Mask, rs, wd, 0x9, 0x1); 2096 } 2097 2098 void Mips64Assembler::StW(VectorRegister wd, GpuRegister rs, int offset) { 2099 CHECK(HasMsa()); 2100 CHECK(IsInt<12>(offset)) << offset; 2101 CHECK_ALIGNED(offset, kMips64WordSize); 2102 EmitMsaMI10((offset >> TIMES_4) & kMsaS10Mask, rs, wd, 0x9, 0x2); 2103 } 2104 2105 void Mips64Assembler::StD(VectorRegister wd, GpuRegister rs, int offset) { 2106 CHECK(HasMsa()); 2107 CHECK(IsInt<13>(offset)) << offset; 2108 CHECK_ALIGNED(offset, kMips64DoublewordSize); 2109 EmitMsaMI10((offset >> TIMES_8) & kMsaS10Mask, rs, wd, 0x9, 0x3); 2110 } 2111 2112 void Mips64Assembler::IlvlB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2113 CHECK(HasMsa()); 2114 EmitMsa3R(0x4, 0x0, wt, ws, wd, 0x14); 2115 } 2116 2117 void Mips64Assembler::IlvlH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2118 CHECK(HasMsa()); 2119 EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x14); 2120 } 2121 2122 void Mips64Assembler::IlvlW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2123 CHECK(HasMsa()); 2124 EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x14); 2125 } 2126 2127 void Mips64Assembler::IlvlD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2128 CHECK(HasMsa()); 2129 EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x14); 2130 } 2131 2132 void Mips64Assembler::IlvrB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2133 CHECK(HasMsa()); 2134 EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x14); 2135 } 2136 2137 void Mips64Assembler::IlvrH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2138 CHECK(HasMsa()); 2139 EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x14); 2140 } 2141 2142 void Mips64Assembler::IlvrW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2143 CHECK(HasMsa()); 2144 EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x14); 2145 } 2146 2147 void Mips64Assembler::IlvrD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2148 CHECK(HasMsa()); 2149 EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x14); 2150 } 2151 2152 void Mips64Assembler::IlvevB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2153 CHECK(HasMsa()); 2154 EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x14); 2155 } 2156 2157 void Mips64Assembler::IlvevH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2158 CHECK(HasMsa()); 2159 EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x14); 2160 } 2161 2162 void Mips64Assembler::IlvevW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2163 CHECK(HasMsa()); 2164 EmitMsa3R(0x6, 0x2, wt, ws, wd, 0x14); 2165 } 2166 2167 void Mips64Assembler::IlvevD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2168 CHECK(HasMsa()); 2169 EmitMsa3R(0x6, 0x3, wt, ws, wd, 0x14); 2170 } 2171 2172 void Mips64Assembler::IlvodB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2173 CHECK(HasMsa()); 2174 EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x14); 2175 } 2176 2177 void Mips64Assembler::IlvodH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2178 CHECK(HasMsa()); 2179 EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x14); 2180 } 2181 2182 void Mips64Assembler::IlvodW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2183 CHECK(HasMsa()); 2184 EmitMsa3R(0x7, 0x2, wt, ws, wd, 0x14); 2185 } 2186 2187 void Mips64Assembler::IlvodD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2188 CHECK(HasMsa()); 2189 EmitMsa3R(0x7, 0x3, wt, ws, wd, 0x14); 2190 } 2191 2192 void Mips64Assembler::MaddvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2193 CHECK(HasMsa()); 2194 EmitMsa3R(0x1, 0x0, wt, ws, wd, 0x12); 2195 } 2196 2197 void Mips64Assembler::MaddvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2198 CHECK(HasMsa()); 2199 EmitMsa3R(0x1, 0x1, wt, ws, wd, 0x12); 2200 } 2201 2202 void Mips64Assembler::MaddvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2203 CHECK(HasMsa()); 2204 EmitMsa3R(0x1, 0x2, wt, ws, wd, 0x12); 2205 } 2206 2207 void Mips64Assembler::MaddvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2208 CHECK(HasMsa()); 2209 EmitMsa3R(0x1, 0x3, wt, ws, wd, 0x12); 2210 } 2211 2212 void Mips64Assembler::MsubvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2213 CHECK(HasMsa()); 2214 EmitMsa3R(0x2, 0x0, wt, ws, wd, 0x12); 2215 } 2216 2217 void Mips64Assembler::MsubvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2218 CHECK(HasMsa()); 2219 EmitMsa3R(0x2, 0x1, wt, ws, wd, 0x12); 2220 } 2221 2222 void Mips64Assembler::MsubvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2223 CHECK(HasMsa()); 2224 EmitMsa3R(0x2, 0x2, wt, ws, wd, 0x12); 2225 } 2226 2227 void Mips64Assembler::MsubvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2228 CHECK(HasMsa()); 2229 EmitMsa3R(0x2, 0x3, wt, ws, wd, 0x12); 2230 } 2231 2232 void Mips64Assembler::FmaddW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2233 CHECK(HasMsa()); 2234 EmitMsa3R(0x2, 0x0, wt, ws, wd, 0x1b); 2235 } 2236 2237 void Mips64Assembler::FmaddD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2238 CHECK(HasMsa()); 2239 EmitMsa3R(0x2, 0x1, wt, ws, wd, 0x1b); 2240 } 2241 2242 void Mips64Assembler::FmsubW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2243 CHECK(HasMsa()); 2244 EmitMsa3R(0x2, 0x2, wt, ws, wd, 0x1b); 2245 } 2246 2247 void Mips64Assembler::FmsubD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2248 CHECK(HasMsa()); 2249 EmitMsa3R(0x2, 0x3, wt, ws, wd, 0x1b); 2250 } 2251 2252 void Mips64Assembler::Hadd_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2253 CHECK(HasMsa()); 2254 EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x15); 2255 } 2256 2257 void Mips64Assembler::Hadd_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2258 CHECK(HasMsa()); 2259 EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x15); 2260 } 2261 2262 void Mips64Assembler::Hadd_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2263 CHECK(HasMsa()); 2264 EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x15); 2265 } 2266 2267 void Mips64Assembler::Hadd_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2268 CHECK(HasMsa()); 2269 EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x15); 2270 } 2271 2272 void Mips64Assembler::Hadd_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2273 CHECK(HasMsa()); 2274 EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x15); 2275 } 2276 2277 void Mips64Assembler::Hadd_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 2278 CHECK(HasMsa()); 2279 EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x15); 2280 } 2281 2282 void Mips64Assembler::ReplicateFPToVectorRegister(VectorRegister dst, 2283 FpuRegister src, 2284 bool is_double) { 2285 // Float or double in FPU register Fx can be considered as 0th element in vector register Wx. 2286 if (is_double) { 2287 SplatiD(dst, static_cast<VectorRegister>(src), 0); 2288 } else { 2289 SplatiW(dst, static_cast<VectorRegister>(src), 0); 2290 } 2291 } 2292 2293 void Mips64Assembler::LoadConst32(GpuRegister rd, int32_t value) { 2294 TemplateLoadConst32(this, rd, value); 2295 } 2296 2297 // This function is only used for testing purposes. 2298 void Mips64Assembler::RecordLoadConst64Path(int value ATTRIBUTE_UNUSED) { 2299 } 2300 2301 void Mips64Assembler::LoadConst64(GpuRegister rd, int64_t value) { 2302 TemplateLoadConst64(this, rd, value); 2303 } 2304 2305 void Mips64Assembler::Addiu32(GpuRegister rt, GpuRegister rs, int32_t value) { 2306 if (IsInt<16>(value)) { 2307 Addiu(rt, rs, value); 2308 } else { 2309 int16_t high = High16Bits(value); 2310 int16_t low = Low16Bits(value); 2311 high += (low < 0) ? 1 : 0; // Account for sign extension in addiu. 2312 Aui(rt, rs, high); 2313 if (low != 0) { 2314 Addiu(rt, rt, low); 2315 } 2316 } 2317 } 2318 2319 // TODO: don't use rtmp, use daui, dahi, dati. 2320 void Mips64Assembler::Daddiu64(GpuRegister rt, GpuRegister rs, int64_t value, GpuRegister rtmp) { 2321 CHECK_NE(rs, rtmp); 2322 if (IsInt<16>(value)) { 2323 Daddiu(rt, rs, value); 2324 } else { 2325 LoadConst64(rtmp, value); 2326 Daddu(rt, rs, rtmp); 2327 } 2328 } 2329 2330 void Mips64Assembler::Branch::InitShortOrLong(Mips64Assembler::Branch::OffsetBits offset_size, 2331 Mips64Assembler::Branch::Type short_type, 2332 Mips64Assembler::Branch::Type long_type) { 2333 type_ = (offset_size <= branch_info_[short_type].offset_size) ? short_type : long_type; 2334 } 2335 2336 void Mips64Assembler::Branch::InitializeType(Type initial_type, bool is_r6) { 2337 OffsetBits offset_size_needed = GetOffsetSizeNeeded(location_, target_); 2338 if (is_r6) { 2339 // R6 2340 switch (initial_type) { 2341 case kLabel: 2342 case kLiteral: 2343 case kLiteralUnsigned: 2344 case kLiteralLong: 2345 CHECK(!IsResolved()); 2346 type_ = initial_type; 2347 break; 2348 case kCall: 2349 InitShortOrLong(offset_size_needed, kCall, kLongCall); 2350 break; 2351 case kCondBranch: 2352 switch (condition_) { 2353 case kUncond: 2354 InitShortOrLong(offset_size_needed, kUncondBranch, kLongUncondBranch); 2355 break; 2356 case kCondEQZ: 2357 case kCondNEZ: 2358 // Special case for beqzc/bnezc with longer offset than in other b<cond>c instructions. 2359 type_ = (offset_size_needed <= kOffset23) ? kCondBranch : kLongCondBranch; 2360 break; 2361 default: 2362 InitShortOrLong(offset_size_needed, kCondBranch, kLongCondBranch); 2363 break; 2364 } 2365 break; 2366 case kBareCall: 2367 type_ = kBareCall; 2368 CHECK_LE(offset_size_needed, GetOffsetSize()); 2369 break; 2370 case kBareCondBranch: 2371 type_ = (condition_ == kUncond) ? kBareUncondBranch : kBareCondBranch; 2372 CHECK_LE(offset_size_needed, GetOffsetSize()); 2373 break; 2374 default: 2375 LOG(FATAL) << "Unexpected branch type " << initial_type; 2376 UNREACHABLE(); 2377 } 2378 } else { 2379 // R2 2380 CHECK_EQ(initial_type, kBareCondBranch); 2381 switch (condition_) { 2382 case kCondLTZ: 2383 case kCondGEZ: 2384 case kCondLEZ: 2385 case kCondGTZ: 2386 case kCondEQ: 2387 case kCondNE: 2388 case kCondEQZ: 2389 case kCondNEZ: 2390 break; 2391 default: 2392 LOG(FATAL) << "Unexpected R2 branch condition " << condition_; 2393 UNREACHABLE(); 2394 } 2395 type_ = kR2BareCondBranch; 2396 CHECK_LE(offset_size_needed, GetOffsetSize()); 2397 } 2398 old_type_ = type_; 2399 } 2400 2401 bool Mips64Assembler::Branch::IsNop(BranchCondition condition, GpuRegister lhs, GpuRegister rhs) { 2402 switch (condition) { 2403 case kCondLT: 2404 case kCondGT: 2405 case kCondNE: 2406 case kCondLTU: 2407 return lhs == rhs; 2408 default: 2409 return false; 2410 } 2411 } 2412 2413 bool Mips64Assembler::Branch::IsUncond(BranchCondition condition, 2414 GpuRegister lhs, 2415 GpuRegister rhs) { 2416 switch (condition) { 2417 case kUncond: 2418 return true; 2419 case kCondGE: 2420 case kCondLE: 2421 case kCondEQ: 2422 case kCondGEU: 2423 return lhs == rhs; 2424 default: 2425 return false; 2426 } 2427 } 2428 2429 Mips64Assembler::Branch::Branch(uint32_t location, uint32_t target, bool is_call, bool is_bare) 2430 : old_location_(location), 2431 location_(location), 2432 target_(target), 2433 lhs_reg_(ZERO), 2434 rhs_reg_(ZERO), 2435 condition_(kUncond) { 2436 InitializeType( 2437 (is_call ? (is_bare ? kBareCall : kCall) : (is_bare ? kBareCondBranch : kCondBranch)), 2438 /* is_r6 */ true); 2439 } 2440 2441 Mips64Assembler::Branch::Branch(bool is_r6, 2442 uint32_t location, 2443 uint32_t target, 2444 Mips64Assembler::BranchCondition condition, 2445 GpuRegister lhs_reg, 2446 GpuRegister rhs_reg, 2447 bool is_bare) 2448 : old_location_(location), 2449 location_(location), 2450 target_(target), 2451 lhs_reg_(lhs_reg), 2452 rhs_reg_(rhs_reg), 2453 condition_(condition) { 2454 CHECK_NE(condition, kUncond); 2455 switch (condition) { 2456 case kCondEQ: 2457 case kCondNE: 2458 case kCondLT: 2459 case kCondGE: 2460 case kCondLE: 2461 case kCondGT: 2462 case kCondLTU: 2463 case kCondGEU: 2464 CHECK_NE(lhs_reg, ZERO); 2465 CHECK_NE(rhs_reg, ZERO); 2466 break; 2467 case kCondLTZ: 2468 case kCondGEZ: 2469 case kCondLEZ: 2470 case kCondGTZ: 2471 case kCondEQZ: 2472 case kCondNEZ: 2473 CHECK_NE(lhs_reg, ZERO); 2474 CHECK_EQ(rhs_reg, ZERO); 2475 break; 2476 case kCondF: 2477 case kCondT: 2478 CHECK_EQ(rhs_reg, ZERO); 2479 break; 2480 case kUncond: 2481 UNREACHABLE(); 2482 } 2483 CHECK(!IsNop(condition, lhs_reg, rhs_reg)); 2484 if (IsUncond(condition, lhs_reg, rhs_reg)) { 2485 // Branch condition is always true, make the branch unconditional. 2486 condition_ = kUncond; 2487 } 2488 InitializeType((is_bare ? kBareCondBranch : kCondBranch), is_r6); 2489 } 2490 2491 Mips64Assembler::Branch::Branch(uint32_t location, GpuRegister dest_reg, Type label_or_literal_type) 2492 : old_location_(location), 2493 location_(location), 2494 target_(kUnresolved), 2495 lhs_reg_(dest_reg), 2496 rhs_reg_(ZERO), 2497 condition_(kUncond) { 2498 CHECK_NE(dest_reg, ZERO); 2499 InitializeType(label_or_literal_type, /* is_r6 */ true); 2500 } 2501 2502 Mips64Assembler::BranchCondition Mips64Assembler::Branch::OppositeCondition( 2503 Mips64Assembler::BranchCondition cond) { 2504 switch (cond) { 2505 case kCondLT: 2506 return kCondGE; 2507 case kCondGE: 2508 return kCondLT; 2509 case kCondLE: 2510 return kCondGT; 2511 case kCondGT: 2512 return kCondLE; 2513 case kCondLTZ: 2514 return kCondGEZ; 2515 case kCondGEZ: 2516 return kCondLTZ; 2517 case kCondLEZ: 2518 return kCondGTZ; 2519 case kCondGTZ: 2520 return kCondLEZ; 2521 case kCondEQ: 2522 return kCondNE; 2523 case kCondNE: 2524 return kCondEQ; 2525 case kCondEQZ: 2526 return kCondNEZ; 2527 case kCondNEZ: 2528 return kCondEQZ; 2529 case kCondLTU: 2530 return kCondGEU; 2531 case kCondGEU: 2532 return kCondLTU; 2533 case kCondF: 2534 return kCondT; 2535 case kCondT: 2536 return kCondF; 2537 case kUncond: 2538 LOG(FATAL) << "Unexpected branch condition " << cond; 2539 } 2540 UNREACHABLE(); 2541 } 2542 2543 Mips64Assembler::Branch::Type Mips64Assembler::Branch::GetType() const { 2544 return type_; 2545 } 2546 2547 Mips64Assembler::BranchCondition Mips64Assembler::Branch::GetCondition() const { 2548 return condition_; 2549 } 2550 2551 GpuRegister Mips64Assembler::Branch::GetLeftRegister() const { 2552 return lhs_reg_; 2553 } 2554 2555 GpuRegister Mips64Assembler::Branch::GetRightRegister() const { 2556 return rhs_reg_; 2557 } 2558 2559 uint32_t Mips64Assembler::Branch::GetTarget() const { 2560 return target_; 2561 } 2562 2563 uint32_t Mips64Assembler::Branch::GetLocation() const { 2564 return location_; 2565 } 2566 2567 uint32_t Mips64Assembler::Branch::GetOldLocation() const { 2568 return old_location_; 2569 } 2570 2571 uint32_t Mips64Assembler::Branch::GetLength() const { 2572 return branch_info_[type_].length; 2573 } 2574 2575 uint32_t Mips64Assembler::Branch::GetOldLength() const { 2576 return branch_info_[old_type_].length; 2577 } 2578 2579 uint32_t Mips64Assembler::Branch::GetSize() const { 2580 return GetLength() * sizeof(uint32_t); 2581 } 2582 2583 uint32_t Mips64Assembler::Branch::GetOldSize() const { 2584 return GetOldLength() * sizeof(uint32_t); 2585 } 2586 2587 uint32_t Mips64Assembler::Branch::GetEndLocation() const { 2588 return GetLocation() + GetSize(); 2589 } 2590 2591 uint32_t Mips64Assembler::Branch::GetOldEndLocation() const { 2592 return GetOldLocation() + GetOldSize(); 2593 } 2594 2595 bool Mips64Assembler::Branch::IsBare() const { 2596 switch (type_) { 2597 // R6 short branches (can't be promoted to long), forbidden/delay slots filled manually. 2598 case kBareUncondBranch: 2599 case kBareCondBranch: 2600 case kBareCall: 2601 // R2 short branches (can't be promoted to long), delay slots filled manually. 2602 case kR2BareCondBranch: 2603 return true; 2604 default: 2605 return false; 2606 } 2607 } 2608 2609 bool Mips64Assembler::Branch::IsLong() const { 2610 switch (type_) { 2611 // R6 short branches (can be promoted to long). 2612 case kUncondBranch: 2613 case kCondBranch: 2614 case kCall: 2615 // R6 short branches (can't be promoted to long), forbidden/delay slots filled manually. 2616 case kBareUncondBranch: 2617 case kBareCondBranch: 2618 case kBareCall: 2619 // R2 short branches (can't be promoted to long), delay slots filled manually. 2620 case kR2BareCondBranch: 2621 // Near label. 2622 case kLabel: 2623 // Near literals. 2624 case kLiteral: 2625 case kLiteralUnsigned: 2626 case kLiteralLong: 2627 return false; 2628 // Long branches. 2629 case kLongUncondBranch: 2630 case kLongCondBranch: 2631 case kLongCall: 2632 // Far label. 2633 case kFarLabel: 2634 // Far literals. 2635 case kFarLiteral: 2636 case kFarLiteralUnsigned: 2637 case kFarLiteralLong: 2638 return true; 2639 } 2640 UNREACHABLE(); 2641 } 2642 2643 bool Mips64Assembler::Branch::IsResolved() const { 2644 return target_ != kUnresolved; 2645 } 2646 2647 Mips64Assembler::Branch::OffsetBits Mips64Assembler::Branch::GetOffsetSize() const { 2648 bool r6_cond_branch = (type_ == kCondBranch || type_ == kBareCondBranch); 2649 OffsetBits offset_size = 2650 (r6_cond_branch && (condition_ == kCondEQZ || condition_ == kCondNEZ)) 2651 ? kOffset23 2652 : branch_info_[type_].offset_size; 2653 return offset_size; 2654 } 2655 2656 Mips64Assembler::Branch::OffsetBits Mips64Assembler::Branch::GetOffsetSizeNeeded(uint32_t location, 2657 uint32_t target) { 2658 // For unresolved targets assume the shortest encoding 2659 // (later it will be made longer if needed). 2660 if (target == kUnresolved) 2661 return kOffset16; 2662 int64_t distance = static_cast<int64_t>(target) - location; 2663 // To simplify calculations in composite branches consisting of multiple instructions 2664 // bump up the distance by a value larger than the max byte size of a composite branch. 2665 distance += (distance >= 0) ? kMaxBranchSize : -kMaxBranchSize; 2666 if (IsInt<kOffset16>(distance)) 2667 return kOffset16; 2668 else if (IsInt<kOffset18>(distance)) 2669 return kOffset18; 2670 else if (IsInt<kOffset21>(distance)) 2671 return kOffset21; 2672 else if (IsInt<kOffset23>(distance)) 2673 return kOffset23; 2674 else if (IsInt<kOffset28>(distance)) 2675 return kOffset28; 2676 return kOffset32; 2677 } 2678 2679 void Mips64Assembler::Branch::Resolve(uint32_t target) { 2680 target_ = target; 2681 } 2682 2683 void Mips64Assembler::Branch::Relocate(uint32_t expand_location, uint32_t delta) { 2684 if (location_ > expand_location) { 2685 location_ += delta; 2686 } 2687 if (!IsResolved()) { 2688 return; // Don't know the target yet. 2689 } 2690 if (target_ > expand_location) { 2691 target_ += delta; 2692 } 2693 } 2694 2695 void Mips64Assembler::Branch::PromoteToLong() { 2696 CHECK(!IsBare()); // Bare branches do not promote. 2697 switch (type_) { 2698 // R6 short branches (can be promoted to long). 2699 case kUncondBranch: 2700 type_ = kLongUncondBranch; 2701 break; 2702 case kCondBranch: 2703 type_ = kLongCondBranch; 2704 break; 2705 case kCall: 2706 type_ = kLongCall; 2707 break; 2708 // Near label. 2709 case kLabel: 2710 type_ = kFarLabel; 2711 break; 2712 // Near literals. 2713 case kLiteral: 2714 type_ = kFarLiteral; 2715 break; 2716 case kLiteralUnsigned: 2717 type_ = kFarLiteralUnsigned; 2718 break; 2719 case kLiteralLong: 2720 type_ = kFarLiteralLong; 2721 break; 2722 default: 2723 // Note: 'type_' is already long. 2724 break; 2725 } 2726 CHECK(IsLong()); 2727 } 2728 2729 uint32_t Mips64Assembler::Branch::PromoteIfNeeded(uint32_t max_short_distance) { 2730 // If the branch is still unresolved or already long, nothing to do. 2731 if (IsLong() || !IsResolved()) { 2732 return 0; 2733 } 2734 // Promote the short branch to long if the offset size is too small 2735 // to hold the distance between location_ and target_. 2736 if (GetOffsetSizeNeeded(location_, target_) > GetOffsetSize()) { 2737 PromoteToLong(); 2738 uint32_t old_size = GetOldSize(); 2739 uint32_t new_size = GetSize(); 2740 CHECK_GT(new_size, old_size); 2741 return new_size - old_size; 2742 } 2743 // The following logic is for debugging/testing purposes. 2744 // Promote some short branches to long when it's not really required. 2745 if (UNLIKELY(max_short_distance != std::numeric_limits<uint32_t>::max() && !IsBare())) { 2746 int64_t distance = static_cast<int64_t>(target_) - location_; 2747 distance = (distance >= 0) ? distance : -distance; 2748 if (distance >= max_short_distance) { 2749 PromoteToLong(); 2750 uint32_t old_size = GetOldSize(); 2751 uint32_t new_size = GetSize(); 2752 CHECK_GT(new_size, old_size); 2753 return new_size - old_size; 2754 } 2755 } 2756 return 0; 2757 } 2758 2759 uint32_t Mips64Assembler::Branch::GetOffsetLocation() const { 2760 return location_ + branch_info_[type_].instr_offset * sizeof(uint32_t); 2761 } 2762 2763 uint32_t Mips64Assembler::Branch::GetOffset() const { 2764 CHECK(IsResolved()); 2765 uint32_t ofs_mask = 0xFFFFFFFF >> (32 - GetOffsetSize()); 2766 // Calculate the byte distance between instructions and also account for 2767 // different PC-relative origins. 2768 uint32_t offset_location = GetOffsetLocation(); 2769 if (type_ == kLiteralLong) { 2770 // Special case for the ldpc instruction, whose address (PC) is rounded down to 2771 // a multiple of 8 before adding the offset. 2772 // Note, branch promotion has already taken care of aligning `target_` to an 2773 // address that's a multiple of 8. 2774 offset_location = RoundDown(offset_location, sizeof(uint64_t)); 2775 } 2776 uint32_t offset = target_ - offset_location - branch_info_[type_].pc_org * sizeof(uint32_t); 2777 // Prepare the offset for encoding into the instruction(s). 2778 offset = (offset & ofs_mask) >> branch_info_[type_].offset_shift; 2779 return offset; 2780 } 2781 2782 Mips64Assembler::Branch* Mips64Assembler::GetBranch(uint32_t branch_id) { 2783 CHECK_LT(branch_id, branches_.size()); 2784 return &branches_[branch_id]; 2785 } 2786 2787 const Mips64Assembler::Branch* Mips64Assembler::GetBranch(uint32_t branch_id) const { 2788 CHECK_LT(branch_id, branches_.size()); 2789 return &branches_[branch_id]; 2790 } 2791 2792 void Mips64Assembler::Bind(Mips64Label* label) { 2793 CHECK(!label->IsBound()); 2794 uint32_t bound_pc = buffer_.Size(); 2795 2796 // Walk the list of branches referring to and preceding this label. 2797 // Store the previously unknown target addresses in them. 2798 while (label->IsLinked()) { 2799 uint32_t branch_id = label->Position(); 2800 Branch* branch = GetBranch(branch_id); 2801 branch->Resolve(bound_pc); 2802 2803 uint32_t branch_location = branch->GetLocation(); 2804 // Extract the location of the previous branch in the list (walking the list backwards; 2805 // the previous branch ID was stored in the space reserved for this branch). 2806 uint32_t prev = buffer_.Load<uint32_t>(branch_location); 2807 2808 // On to the previous branch in the list... 2809 label->position_ = prev; 2810 } 2811 2812 // Now make the label object contain its own location (relative to the end of the preceding 2813 // branch, if any; it will be used by the branches referring to and following this label). 2814 label->prev_branch_id_plus_one_ = branches_.size(); 2815 if (label->prev_branch_id_plus_one_) { 2816 uint32_t branch_id = label->prev_branch_id_plus_one_ - 1; 2817 const Branch* branch = GetBranch(branch_id); 2818 bound_pc -= branch->GetEndLocation(); 2819 } 2820 label->BindTo(bound_pc); 2821 } 2822 2823 uint32_t Mips64Assembler::GetLabelLocation(const Mips64Label* label) const { 2824 CHECK(label->IsBound()); 2825 uint32_t target = label->Position(); 2826 if (label->prev_branch_id_plus_one_) { 2827 // Get label location based on the branch preceding it. 2828 uint32_t branch_id = label->prev_branch_id_plus_one_ - 1; 2829 const Branch* branch = GetBranch(branch_id); 2830 target += branch->GetEndLocation(); 2831 } 2832 return target; 2833 } 2834 2835 uint32_t Mips64Assembler::GetAdjustedPosition(uint32_t old_position) { 2836 // We can reconstruct the adjustment by going through all the branches from the beginning 2837 // up to the old_position. Since we expect AdjustedPosition() to be called in a loop 2838 // with increasing old_position, we can use the data from last AdjustedPosition() to 2839 // continue where we left off and the whole loop should be O(m+n) where m is the number 2840 // of positions to adjust and n is the number of branches. 2841 if (old_position < last_old_position_) { 2842 last_position_adjustment_ = 0; 2843 last_old_position_ = 0; 2844 last_branch_id_ = 0; 2845 } 2846 while (last_branch_id_ != branches_.size()) { 2847 const Branch* branch = GetBranch(last_branch_id_); 2848 if (branch->GetLocation() >= old_position + last_position_adjustment_) { 2849 break; 2850 } 2851 last_position_adjustment_ += branch->GetSize() - branch->GetOldSize(); 2852 ++last_branch_id_; 2853 } 2854 last_old_position_ = old_position; 2855 return old_position + last_position_adjustment_; 2856 } 2857 2858 void Mips64Assembler::FinalizeLabeledBranch(Mips64Label* label) { 2859 uint32_t length = branches_.back().GetLength(); 2860 if (!label->IsBound()) { 2861 // Branch forward (to a following label), distance is unknown. 2862 // The first branch forward will contain 0, serving as the terminator of 2863 // the list of forward-reaching branches. 2864 Emit(label->position_); 2865 length--; 2866 // Now make the label object point to this branch 2867 // (this forms a linked list of branches preceding this label). 2868 uint32_t branch_id = branches_.size() - 1; 2869 label->LinkTo(branch_id); 2870 } 2871 // Reserve space for the branch. 2872 while (length--) { 2873 Nop(); 2874 } 2875 } 2876 2877 void Mips64Assembler::Buncond(Mips64Label* label, bool is_bare) { 2878 uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved; 2879 branches_.emplace_back(buffer_.Size(), target, /* is_call */ false, is_bare); 2880 FinalizeLabeledBranch(label); 2881 } 2882 2883 void Mips64Assembler::Bcond(Mips64Label* label, 2884 bool is_r6, 2885 bool is_bare, 2886 BranchCondition condition, 2887 GpuRegister lhs, 2888 GpuRegister rhs) { 2889 // If lhs = rhs, this can be a NOP. 2890 if (Branch::IsNop(condition, lhs, rhs)) { 2891 return; 2892 } 2893 uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved; 2894 branches_.emplace_back(is_r6, buffer_.Size(), target, condition, lhs, rhs, is_bare); 2895 FinalizeLabeledBranch(label); 2896 } 2897 2898 void Mips64Assembler::Call(Mips64Label* label, bool is_bare) { 2899 uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved; 2900 branches_.emplace_back(buffer_.Size(), target, /* is_call */ true, is_bare); 2901 FinalizeLabeledBranch(label); 2902 } 2903 2904 void Mips64Assembler::LoadLabelAddress(GpuRegister dest_reg, Mips64Label* label) { 2905 // Label address loads are treated as pseudo branches since they require very similar handling. 2906 DCHECK(!label->IsBound()); 2907 branches_.emplace_back(buffer_.Size(), dest_reg, Branch::kLabel); 2908 FinalizeLabeledBranch(label); 2909 } 2910 2911 Literal* Mips64Assembler::NewLiteral(size_t size, const uint8_t* data) { 2912 // We don't support byte and half-word literals. 2913 if (size == 4u) { 2914 literals_.emplace_back(size, data); 2915 return &literals_.back(); 2916 } else { 2917 DCHECK_EQ(size, 8u); 2918 long_literals_.emplace_back(size, data); 2919 return &long_literals_.back(); 2920 } 2921 } 2922 2923 void Mips64Assembler::LoadLiteral(GpuRegister dest_reg, 2924 LoadOperandType load_type, 2925 Literal* literal) { 2926 // Literal loads are treated as pseudo branches since they require very similar handling. 2927 Branch::Type literal_type; 2928 switch (load_type) { 2929 case kLoadWord: 2930 DCHECK_EQ(literal->GetSize(), 4u); 2931 literal_type = Branch::kLiteral; 2932 break; 2933 case kLoadUnsignedWord: 2934 DCHECK_EQ(literal->GetSize(), 4u); 2935 literal_type = Branch::kLiteralUnsigned; 2936 break; 2937 case kLoadDoubleword: 2938 DCHECK_EQ(literal->GetSize(), 8u); 2939 literal_type = Branch::kLiteralLong; 2940 break; 2941 default: 2942 LOG(FATAL) << "Unexpected literal load type " << load_type; 2943 UNREACHABLE(); 2944 } 2945 Mips64Label* label = literal->GetLabel(); 2946 DCHECK(!label->IsBound()); 2947 branches_.emplace_back(buffer_.Size(), dest_reg, literal_type); 2948 FinalizeLabeledBranch(label); 2949 } 2950 2951 JumpTable* Mips64Assembler::CreateJumpTable(std::vector<Mips64Label*>&& labels) { 2952 jump_tables_.emplace_back(std::move(labels)); 2953 JumpTable* table = &jump_tables_.back(); 2954 DCHECK(!table->GetLabel()->IsBound()); 2955 return table; 2956 } 2957 2958 void Mips64Assembler::ReserveJumpTableSpace() { 2959 if (!jump_tables_.empty()) { 2960 for (JumpTable& table : jump_tables_) { 2961 Mips64Label* label = table.GetLabel(); 2962 Bind(label); 2963 2964 // Bulk ensure capacity, as this may be large. 2965 size_t orig_size = buffer_.Size(); 2966 size_t required_capacity = orig_size + table.GetSize(); 2967 if (required_capacity > buffer_.Capacity()) { 2968 buffer_.ExtendCapacity(required_capacity); 2969 } 2970 #ifndef NDEBUG 2971 buffer_.has_ensured_capacity_ = true; 2972 #endif 2973 2974 // Fill the space with dummy data as the data is not final 2975 // until the branches have been promoted. And we shouldn't 2976 // be moving uninitialized data during branch promotion. 2977 for (size_t cnt = table.GetData().size(), i = 0; i < cnt; i++) { 2978 buffer_.Emit<uint32_t>(0x1abe1234u); 2979 } 2980 2981 #ifndef NDEBUG 2982 buffer_.has_ensured_capacity_ = false; 2983 #endif 2984 } 2985 } 2986 } 2987 2988 void Mips64Assembler::EmitJumpTables() { 2989 if (!jump_tables_.empty()) { 2990 CHECK(!overwriting_); 2991 // Switch from appending instructions at the end of the buffer to overwriting 2992 // existing instructions (here, jump tables) in the buffer. 2993 overwriting_ = true; 2994 2995 for (JumpTable& table : jump_tables_) { 2996 Mips64Label* table_label = table.GetLabel(); 2997 uint32_t start = GetLabelLocation(table_label); 2998 overwrite_location_ = start; 2999 3000 for (Mips64Label* target : table.GetData()) { 3001 CHECK_EQ(buffer_.Load<uint32_t>(overwrite_location_), 0x1abe1234u); 3002 // The table will contain target addresses relative to the table start. 3003 uint32_t offset = GetLabelLocation(target) - start; 3004 Emit(offset); 3005 } 3006 } 3007 3008 overwriting_ = false; 3009 } 3010 } 3011 3012 void Mips64Assembler::EmitLiterals() { 3013 if (!literals_.empty()) { 3014 for (Literal& literal : literals_) { 3015 Mips64Label* label = literal.GetLabel(); 3016 Bind(label); 3017 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 3018 DCHECK_EQ(literal.GetSize(), 4u); 3019 for (size_t i = 0, size = literal.GetSize(); i != size; ++i) { 3020 buffer_.Emit<uint8_t>(literal.GetData()[i]); 3021 } 3022 } 3023 } 3024 if (!long_literals_.empty()) { 3025 // Reserve 4 bytes for potential alignment. If after the branch promotion the 64-bit 3026 // literals don't end up 8-byte-aligned, they will be moved down 4 bytes. 3027 Emit(0); // NOP. 3028 for (Literal& literal : long_literals_) { 3029 Mips64Label* label = literal.GetLabel(); 3030 Bind(label); 3031 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 3032 DCHECK_EQ(literal.GetSize(), 8u); 3033 for (size_t i = 0, size = literal.GetSize(); i != size; ++i) { 3034 buffer_.Emit<uint8_t>(literal.GetData()[i]); 3035 } 3036 } 3037 } 3038 } 3039 3040 void Mips64Assembler::PromoteBranches() { 3041 // Promote short branches to long as necessary. 3042 bool changed; 3043 do { 3044 changed = false; 3045 for (auto& branch : branches_) { 3046 CHECK(branch.IsResolved()); 3047 uint32_t delta = branch.PromoteIfNeeded(); 3048 // If this branch has been promoted and needs to expand in size, 3049 // relocate all branches by the expansion size. 3050 if (delta) { 3051 changed = true; 3052 uint32_t expand_location = branch.GetLocation(); 3053 for (auto& branch2 : branches_) { 3054 branch2.Relocate(expand_location, delta); 3055 } 3056 } 3057 } 3058 } while (changed); 3059 3060 // Account for branch expansion by resizing the code buffer 3061 // and moving the code in it to its final location. 3062 size_t branch_count = branches_.size(); 3063 if (branch_count > 0) { 3064 // Resize. 3065 Branch& last_branch = branches_[branch_count - 1]; 3066 uint32_t size_delta = last_branch.GetEndLocation() - last_branch.GetOldEndLocation(); 3067 uint32_t old_size = buffer_.Size(); 3068 buffer_.Resize(old_size + size_delta); 3069 // Move the code residing between branch placeholders. 3070 uint32_t end = old_size; 3071 for (size_t i = branch_count; i > 0; ) { 3072 Branch& branch = branches_[--i]; 3073 uint32_t size = end - branch.GetOldEndLocation(); 3074 buffer_.Move(branch.GetEndLocation(), branch.GetOldEndLocation(), size); 3075 end = branch.GetOldLocation(); 3076 } 3077 } 3078 3079 // Align 64-bit literals by moving them down by 4 bytes if needed. 3080 // This will reduce the PC-relative distance, which should be safe for both near and far literals. 3081 if (!long_literals_.empty()) { 3082 uint32_t first_literal_location = GetLabelLocation(long_literals_.front().GetLabel()); 3083 size_t lit_size = long_literals_.size() * sizeof(uint64_t); 3084 size_t buf_size = buffer_.Size(); 3085 // 64-bit literals must be at the very end of the buffer. 3086 CHECK_EQ(first_literal_location + lit_size, buf_size); 3087 if (!IsAligned<sizeof(uint64_t)>(first_literal_location)) { 3088 buffer_.Move(first_literal_location - sizeof(uint32_t), first_literal_location, lit_size); 3089 // The 4 reserved bytes proved useless, reduce the buffer size. 3090 buffer_.Resize(buf_size - sizeof(uint32_t)); 3091 // Reduce target addresses in literal and address loads by 4 bytes in order for correct 3092 // offsets from PC to be generated. 3093 for (auto& branch : branches_) { 3094 uint32_t target = branch.GetTarget(); 3095 if (target >= first_literal_location) { 3096 branch.Resolve(target - sizeof(uint32_t)); 3097 } 3098 } 3099 // If after this we ever call GetLabelLocation() to get the location of a 64-bit literal, 3100 // we need to adjust the location of the literal's label as well. 3101 for (Literal& literal : long_literals_) { 3102 // Bound label's position is negative, hence incrementing it instead of decrementing. 3103 literal.GetLabel()->position_ += sizeof(uint32_t); 3104 } 3105 } 3106 } 3107 } 3108 3109 // Note: make sure branch_info_[] and EmitBranch() are kept synchronized. 3110 const Mips64Assembler::Branch::BranchInfo Mips64Assembler::Branch::branch_info_[] = { 3111 // R6 short branches (can be promoted to long). 3112 { 1, 0, 1, Mips64Assembler::Branch::kOffset28, 2 }, // kUncondBranch 3113 { 2, 0, 1, Mips64Assembler::Branch::kOffset18, 2 }, // kCondBranch 3114 // Exception: kOffset23 for beqzc/bnezc 3115 { 1, 0, 1, Mips64Assembler::Branch::kOffset28, 2 }, // kCall 3116 // R6 short branches (can't be promoted to long), forbidden/delay slots filled manually. 3117 { 1, 0, 1, Mips64Assembler::Branch::kOffset28, 2 }, // kBareUncondBranch 3118 { 1, 0, 1, Mips64Assembler::Branch::kOffset18, 2 }, // kBareCondBranch 3119 // Exception: kOffset23 for beqzc/bnezc 3120 { 1, 0, 1, Mips64Assembler::Branch::kOffset28, 2 }, // kBareCall 3121 // R2 short branches (can't be promoted to long), delay slots filled manually. 3122 { 1, 0, 1, Mips64Assembler::Branch::kOffset18, 2 }, // kR2BareCondBranch 3123 // Near label. 3124 { 1, 0, 0, Mips64Assembler::Branch::kOffset21, 2 }, // kLabel 3125 // Near literals. 3126 { 1, 0, 0, Mips64Assembler::Branch::kOffset21, 2 }, // kLiteral 3127 { 1, 0, 0, Mips64Assembler::Branch::kOffset21, 2 }, // kLiteralUnsigned 3128 { 1, 0, 0, Mips64Assembler::Branch::kOffset21, 3 }, // kLiteralLong 3129 // Long branches. 3130 { 2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kLongUncondBranch 3131 { 3, 1, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kLongCondBranch 3132 { 2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kLongCall 3133 // Far label. 3134 { 2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kFarLabel 3135 // Far literals. 3136 { 2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kFarLiteral 3137 { 2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kFarLiteralUnsigned 3138 { 2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kFarLiteralLong 3139 }; 3140 3141 // Note: make sure branch_info_[] and EmitBranch() are kept synchronized. 3142 void Mips64Assembler::EmitBranch(Mips64Assembler::Branch* branch) { 3143 CHECK(overwriting_); 3144 overwrite_location_ = branch->GetLocation(); 3145 uint32_t offset = branch->GetOffset(); 3146 BranchCondition condition = branch->GetCondition(); 3147 GpuRegister lhs = branch->GetLeftRegister(); 3148 GpuRegister rhs = branch->GetRightRegister(); 3149 switch (branch->GetType()) { 3150 // Short branches. 3151 case Branch::kUncondBranch: 3152 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 3153 Bc(offset); 3154 break; 3155 case Branch::kCondBranch: 3156 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 3157 EmitBcondR6(condition, lhs, rhs, offset); 3158 Nop(); // TODO: improve by filling the forbidden/delay slot. 3159 break; 3160 case Branch::kCall: 3161 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 3162 Balc(offset); 3163 break; 3164 case Branch::kBareUncondBranch: 3165 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 3166 Bc(offset); 3167 break; 3168 case Branch::kBareCondBranch: 3169 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 3170 EmitBcondR6(condition, lhs, rhs, offset); 3171 break; 3172 case Branch::kBareCall: 3173 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 3174 Balc(offset); 3175 break; 3176 case Branch::kR2BareCondBranch: 3177 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 3178 EmitBcondR2(condition, lhs, rhs, offset); 3179 break; 3180 3181 // Near label. 3182 case Branch::kLabel: 3183 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 3184 Addiupc(lhs, offset); 3185 break; 3186 // Near literals. 3187 case Branch::kLiteral: 3188 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 3189 Lwpc(lhs, offset); 3190 break; 3191 case Branch::kLiteralUnsigned: 3192 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 3193 Lwupc(lhs, offset); 3194 break; 3195 case Branch::kLiteralLong: 3196 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 3197 Ldpc(lhs, offset); 3198 break; 3199 3200 // Long branches. 3201 case Branch::kLongUncondBranch: 3202 offset += (offset & 0x8000) << 1; // Account for sign extension in jic. 3203 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 3204 Auipc(AT, High16Bits(offset)); 3205 Jic(AT, Low16Bits(offset)); 3206 break; 3207 case Branch::kLongCondBranch: 3208 EmitBcondR6(Branch::OppositeCondition(condition), lhs, rhs, 2); 3209 offset += (offset & 0x8000) << 1; // Account for sign extension in jic. 3210 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 3211 Auipc(AT, High16Bits(offset)); 3212 Jic(AT, Low16Bits(offset)); 3213 break; 3214 case Branch::kLongCall: 3215 offset += (offset & 0x8000) << 1; // Account for sign extension in jialc. 3216 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 3217 Auipc(AT, High16Bits(offset)); 3218 Jialc(AT, Low16Bits(offset)); 3219 break; 3220 3221 // Far label. 3222 case Branch::kFarLabel: 3223 offset += (offset & 0x8000) << 1; // Account for sign extension in daddiu. 3224 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 3225 Auipc(AT, High16Bits(offset)); 3226 Daddiu(lhs, AT, Low16Bits(offset)); 3227 break; 3228 // Far literals. 3229 case Branch::kFarLiteral: 3230 offset += (offset & 0x8000) << 1; // Account for sign extension in lw. 3231 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 3232 Auipc(AT, High16Bits(offset)); 3233 Lw(lhs, AT, Low16Bits(offset)); 3234 break; 3235 case Branch::kFarLiteralUnsigned: 3236 offset += (offset & 0x8000) << 1; // Account for sign extension in lwu. 3237 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 3238 Auipc(AT, High16Bits(offset)); 3239 Lwu(lhs, AT, Low16Bits(offset)); 3240 break; 3241 case Branch::kFarLiteralLong: 3242 offset += (offset & 0x8000) << 1; // Account for sign extension in ld. 3243 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 3244 Auipc(AT, High16Bits(offset)); 3245 Ld(lhs, AT, Low16Bits(offset)); 3246 break; 3247 } 3248 CHECK_EQ(overwrite_location_, branch->GetEndLocation()); 3249 CHECK_LT(branch->GetSize(), static_cast<uint32_t>(Branch::kMaxBranchSize)); 3250 } 3251 3252 void Mips64Assembler::Bc(Mips64Label* label, bool is_bare) { 3253 Buncond(label, is_bare); 3254 } 3255 3256 void Mips64Assembler::Balc(Mips64Label* label, bool is_bare) { 3257 Call(label, is_bare); 3258 } 3259 3260 void Mips64Assembler::Bltc(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) { 3261 Bcond(label, /* is_r6 */ true, is_bare, kCondLT, rs, rt); 3262 } 3263 3264 void Mips64Assembler::Bltzc(GpuRegister rt, Mips64Label* label, bool is_bare) { 3265 Bcond(label, /* is_r6 */ true, is_bare, kCondLTZ, rt); 3266 } 3267 3268 void Mips64Assembler::Bgtzc(GpuRegister rt, Mips64Label* label, bool is_bare) { 3269 Bcond(label, /* is_r6 */ true, is_bare, kCondGTZ, rt); 3270 } 3271 3272 void Mips64Assembler::Bgec(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) { 3273 Bcond(label, /* is_r6 */ true, is_bare, kCondGE, rs, rt); 3274 } 3275 3276 void Mips64Assembler::Bgezc(GpuRegister rt, Mips64Label* label, bool is_bare) { 3277 Bcond(label, /* is_r6 */ true, is_bare, kCondGEZ, rt); 3278 } 3279 3280 void Mips64Assembler::Blezc(GpuRegister rt, Mips64Label* label, bool is_bare) { 3281 Bcond(label, /* is_r6 */ true, is_bare, kCondLEZ, rt); 3282 } 3283 3284 void Mips64Assembler::Bltuc(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) { 3285 Bcond(label, /* is_r6 */ true, is_bare, kCondLTU, rs, rt); 3286 } 3287 3288 void Mips64Assembler::Bgeuc(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) { 3289 Bcond(label, /* is_r6 */ true, is_bare, kCondGEU, rs, rt); 3290 } 3291 3292 void Mips64Assembler::Beqc(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) { 3293 Bcond(label, /* is_r6 */ true, is_bare, kCondEQ, rs, rt); 3294 } 3295 3296 void Mips64Assembler::Bnec(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) { 3297 Bcond(label, /* is_r6 */ true, is_bare, kCondNE, rs, rt); 3298 } 3299 3300 void Mips64Assembler::Beqzc(GpuRegister rs, Mips64Label* label, bool is_bare) { 3301 Bcond(label, /* is_r6 */ true, is_bare, kCondEQZ, rs); 3302 } 3303 3304 void Mips64Assembler::Bnezc(GpuRegister rs, Mips64Label* label, bool is_bare) { 3305 Bcond(label, /* is_r6 */ true, is_bare, kCondNEZ, rs); 3306 } 3307 3308 void Mips64Assembler::Bc1eqz(FpuRegister ft, Mips64Label* label, bool is_bare) { 3309 Bcond(label, /* is_r6 */ true, is_bare, kCondF, static_cast<GpuRegister>(ft), ZERO); 3310 } 3311 3312 void Mips64Assembler::Bc1nez(FpuRegister ft, Mips64Label* label, bool is_bare) { 3313 Bcond(label, /* is_r6 */ true, is_bare, kCondT, static_cast<GpuRegister>(ft), ZERO); 3314 } 3315 3316 void Mips64Assembler::Bltz(GpuRegister rt, Mips64Label* label, bool is_bare) { 3317 CHECK(is_bare); 3318 Bcond(label, /* is_r6 */ false, is_bare, kCondLTZ, rt); 3319 } 3320 3321 void Mips64Assembler::Bgtz(GpuRegister rt, Mips64Label* label, bool is_bare) { 3322 CHECK(is_bare); 3323 Bcond(label, /* is_r6 */ false, is_bare, kCondGTZ, rt); 3324 } 3325 3326 void Mips64Assembler::Bgez(GpuRegister rt, Mips64Label* label, bool is_bare) { 3327 CHECK(is_bare); 3328 Bcond(label, /* is_r6 */ false, is_bare, kCondGEZ, rt); 3329 } 3330 3331 void Mips64Assembler::Blez(GpuRegister rt, Mips64Label* label, bool is_bare) { 3332 CHECK(is_bare); 3333 Bcond(label, /* is_r6 */ false, is_bare, kCondLEZ, rt); 3334 } 3335 3336 void Mips64Assembler::Beq(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) { 3337 CHECK(is_bare); 3338 Bcond(label, /* is_r6 */ false, is_bare, kCondEQ, rs, rt); 3339 } 3340 3341 void Mips64Assembler::Bne(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) { 3342 CHECK(is_bare); 3343 Bcond(label, /* is_r6 */ false, is_bare, kCondNE, rs, rt); 3344 } 3345 3346 void Mips64Assembler::Beqz(GpuRegister rs, Mips64Label* label, bool is_bare) { 3347 CHECK(is_bare); 3348 Bcond(label, /* is_r6 */ false, is_bare, kCondEQZ, rs); 3349 } 3350 3351 void Mips64Assembler::Bnez(GpuRegister rs, Mips64Label* label, bool is_bare) { 3352 CHECK(is_bare); 3353 Bcond(label, /* is_r6 */ false, is_bare, kCondNEZ, rs); 3354 } 3355 3356 void Mips64Assembler::AdjustBaseAndOffset(GpuRegister& base, 3357 int32_t& offset, 3358 bool is_doubleword) { 3359 // This method is used to adjust the base register and offset pair 3360 // for a load/store when the offset doesn't fit into int16_t. 3361 // It is assumed that `base + offset` is sufficiently aligned for memory 3362 // operands that are machine word in size or smaller. For doubleword-sized 3363 // operands it's assumed that `base` is a multiple of 8, while `offset` 3364 // may be a multiple of 4 (e.g. 4-byte-aligned long and double arguments 3365 // and spilled variables on the stack accessed relative to the stack 3366 // pointer register). 3367 // We preserve the "alignment" of `offset` by adjusting it by a multiple of 8. 3368 CHECK_NE(base, AT); // Must not overwrite the register `base` while loading `offset`. 3369 3370 bool doubleword_aligned = IsAligned<kMips64DoublewordSize>(offset); 3371 bool two_accesses = is_doubleword && !doubleword_aligned; 3372 3373 // IsInt<16> must be passed a signed value, hence the static cast below. 3374 if (IsInt<16>(offset) && 3375 (!two_accesses || IsInt<16>(static_cast<int32_t>(offset + kMips64WordSize)))) { 3376 // Nothing to do: `offset` (and, if needed, `offset + 4`) fits into int16_t. 3377 return; 3378 } 3379 3380 // Remember the "(mis)alignment" of `offset`, it will be checked at the end. 3381 uint32_t misalignment = offset & (kMips64DoublewordSize - 1); 3382 3383 // First, see if `offset` can be represented as a sum of two 16-bit signed 3384 // offsets. This can save an instruction. 3385 // To simplify matters, only do this for a symmetric range of offsets from 3386 // about -64KB to about +64KB, allowing further addition of 4 when accessing 3387 // 64-bit variables with two 32-bit accesses. 3388 constexpr int32_t kMinOffsetForSimpleAdjustment = 0x7ff8; // Max int16_t that's a multiple of 8. 3389 constexpr int32_t kMaxOffsetForSimpleAdjustment = 2 * kMinOffsetForSimpleAdjustment; 3390 3391 if (0 <= offset && offset <= kMaxOffsetForSimpleAdjustment) { 3392 Daddiu(AT, base, kMinOffsetForSimpleAdjustment); 3393 offset -= kMinOffsetForSimpleAdjustment; 3394 } else if (-kMaxOffsetForSimpleAdjustment <= offset && offset < 0) { 3395 Daddiu(AT, base, -kMinOffsetForSimpleAdjustment); 3396 offset += kMinOffsetForSimpleAdjustment; 3397 } else { 3398 // In more complex cases take advantage of the daui instruction, e.g.: 3399 // daui AT, base, offset_high 3400 // [dahi AT, 1] // When `offset` is close to +2GB. 3401 // lw reg_lo, offset_low(AT) 3402 // [lw reg_hi, (offset_low+4)(AT)] // If misaligned 64-bit load. 3403 // or when offset_low+4 overflows int16_t: 3404 // daui AT, base, offset_high 3405 // daddiu AT, AT, 8 3406 // lw reg_lo, (offset_low-8)(AT) 3407 // lw reg_hi, (offset_low-4)(AT) 3408 int16_t offset_low = Low16Bits(offset); 3409 int32_t offset_low32 = offset_low; 3410 int16_t offset_high = High16Bits(offset); 3411 bool increment_hi16 = offset_low < 0; 3412 bool overflow_hi16 = false; 3413 3414 if (increment_hi16) { 3415 offset_high++; 3416 overflow_hi16 = (offset_high == -32768); 3417 } 3418 Daui(AT, base, offset_high); 3419 3420 if (overflow_hi16) { 3421 Dahi(AT, 1); 3422 } 3423 3424 if (two_accesses && !IsInt<16>(static_cast<int32_t>(offset_low32 + kMips64WordSize))) { 3425 // Avoid overflow in the 16-bit offset of the load/store instruction when adding 4. 3426 Daddiu(AT, AT, kMips64DoublewordSize); 3427 offset_low32 -= kMips64DoublewordSize; 3428 } 3429 3430 offset = offset_low32; 3431 } 3432 base = AT; 3433 3434 CHECK(IsInt<16>(offset)); 3435 if (two_accesses) { 3436 CHECK(IsInt<16>(static_cast<int32_t>(offset + kMips64WordSize))); 3437 } 3438 CHECK_EQ(misalignment, offset & (kMips64DoublewordSize - 1)); 3439 } 3440 3441 void Mips64Assembler::AdjustBaseOffsetAndElementSizeShift(GpuRegister& base, 3442 int32_t& offset, 3443 int& element_size_shift) { 3444 // This method is used to adjust the base register, offset and element_size_shift 3445 // for a vector load/store when the offset doesn't fit into allowed number of bits. 3446 // MSA ld.df and st.df instructions take signed offsets as arguments, but maximum 3447 // offset is dependant on the size of the data format df (10-bit offsets for ld.b, 3448 // 11-bit for ld.h, 12-bit for ld.w and 13-bit for ld.d). 3449 // If element_size_shift is non-negative at entry, it won't be changed, but offset 3450 // will be checked for appropriate alignment. If negative at entry, it will be 3451 // adjusted based on offset for maximum fit. 3452 // It's assumed that `base` is a multiple of 8. 3453 3454 CHECK_NE(base, AT); // Must not overwrite the register `base` while loading `offset`. 3455 3456 if (element_size_shift >= 0) { 3457 CHECK_LE(element_size_shift, TIMES_8); 3458 CHECK_GE(JAVASTYLE_CTZ(offset), element_size_shift); 3459 } else if (IsAligned<kMips64DoublewordSize>(offset)) { 3460 element_size_shift = TIMES_8; 3461 } else if (IsAligned<kMips64WordSize>(offset)) { 3462 element_size_shift = TIMES_4; 3463 } else if (IsAligned<kMips64HalfwordSize>(offset)) { 3464 element_size_shift = TIMES_2; 3465 } else { 3466 element_size_shift = TIMES_1; 3467 } 3468 3469 const int low_len = 10 + element_size_shift; // How many low bits of `offset` ld.df/st.df 3470 // will take. 3471 int16_t low = offset & ((1 << low_len) - 1); // Isolate these bits. 3472 low -= (low & (1 << (low_len - 1))) << 1; // Sign-extend these bits. 3473 if (low == offset) { 3474 return; // `offset` fits into ld.df/st.df. 3475 } 3476 3477 // First, see if `offset` can be represented as a sum of two signed offsets. 3478 // This can save an instruction. 3479 3480 // Max int16_t that's a multiple of element size. 3481 const int32_t kMaxDeltaForSimpleAdjustment = 0x8000 - (1 << element_size_shift); 3482 // Max ld.df/st.df offset that's a multiple of element size. 3483 const int32_t kMaxLoadStoreOffset = 0x1ff << element_size_shift; 3484 const int32_t kMaxOffsetForSimpleAdjustment = kMaxDeltaForSimpleAdjustment + kMaxLoadStoreOffset; 3485 3486 if (IsInt<16>(offset)) { 3487 Daddiu(AT, base, offset); 3488 offset = 0; 3489 } else if (0 <= offset && offset <= kMaxOffsetForSimpleAdjustment) { 3490 Daddiu(AT, base, kMaxDeltaForSimpleAdjustment); 3491 offset -= kMaxDeltaForSimpleAdjustment; 3492 } else if (-kMaxOffsetForSimpleAdjustment <= offset && offset < 0) { 3493 Daddiu(AT, base, -kMaxDeltaForSimpleAdjustment); 3494 offset += kMaxDeltaForSimpleAdjustment; 3495 } else { 3496 // Let's treat `offset` as 64-bit to simplify handling of sign 3497 // extensions in the instructions that supply its smaller signed parts. 3498 // 3499 // 16-bit or smaller parts of `offset`: 3500 // |63 top 48|47 hi 32|31 upper 16|15 mid 13-10|12-9 low 0| 3501 // 3502 // Instructions that supply each part as a signed integer addend: 3503 // |dati |dahi |daui |daddiu |ld.df/st.df | 3504 // 3505 // `top` is always 0, so dati isn't used. 3506 // `hi` is 1 when `offset` is close to +2GB and 0 otherwise. 3507 uint64_t tmp = static_cast<uint64_t>(offset) - low; // Exclude `low` from the rest of `offset` 3508 // (accounts for sign of `low`). 3509 tmp += (tmp & (UINT64_C(1) << 15)) << 1; // Account for sign extension in daddiu. 3510 tmp += (tmp & (UINT64_C(1) << 31)) << 1; // Account for sign extension in daui. 3511 int16_t mid = Low16Bits(tmp); 3512 int16_t upper = High16Bits(tmp); 3513 int16_t hi = Low16Bits(High32Bits(tmp)); 3514 Daui(AT, base, upper); 3515 if (hi != 0) { 3516 CHECK_EQ(hi, 1); 3517 Dahi(AT, hi); 3518 } 3519 if (mid != 0) { 3520 Daddiu(AT, AT, mid); 3521 } 3522 offset = low; 3523 } 3524 base = AT; 3525 CHECK_GE(JAVASTYLE_CTZ(offset), element_size_shift); 3526 CHECK(IsInt<10>(offset >> element_size_shift)); 3527 } 3528 3529 void Mips64Assembler::LoadFromOffset(LoadOperandType type, 3530 GpuRegister reg, 3531 GpuRegister base, 3532 int32_t offset) { 3533 LoadFromOffset<>(type, reg, base, offset); 3534 } 3535 3536 void Mips64Assembler::LoadFpuFromOffset(LoadOperandType type, 3537 FpuRegister reg, 3538 GpuRegister base, 3539 int32_t offset) { 3540 LoadFpuFromOffset<>(type, reg, base, offset); 3541 } 3542 3543 void Mips64Assembler::EmitLoad(ManagedRegister m_dst, GpuRegister src_register, int32_t src_offset, 3544 size_t size) { 3545 Mips64ManagedRegister dst = m_dst.AsMips64(); 3546 if (dst.IsNoRegister()) { 3547 CHECK_EQ(0u, size) << dst; 3548 } else if (dst.IsGpuRegister()) { 3549 if (size == 4) { 3550 LoadFromOffset(kLoadWord, dst.AsGpuRegister(), src_register, src_offset); 3551 } else if (size == 8) { 3552 CHECK_EQ(8u, size) << dst; 3553 LoadFromOffset(kLoadDoubleword, dst.AsGpuRegister(), src_register, src_offset); 3554 } else { 3555 UNIMPLEMENTED(FATAL) << "We only support Load() of size 4 and 8"; 3556 } 3557 } else if (dst.IsFpuRegister()) { 3558 if (size == 4) { 3559 CHECK_EQ(4u, size) << dst; 3560 LoadFpuFromOffset(kLoadWord, dst.AsFpuRegister(), src_register, src_offset); 3561 } else if (size == 8) { 3562 CHECK_EQ(8u, size) << dst; 3563 LoadFpuFromOffset(kLoadDoubleword, dst.AsFpuRegister(), src_register, src_offset); 3564 } else { 3565 UNIMPLEMENTED(FATAL) << "We only support Load() of size 4 and 8"; 3566 } 3567 } 3568 } 3569 3570 void Mips64Assembler::StoreToOffset(StoreOperandType type, 3571 GpuRegister reg, 3572 GpuRegister base, 3573 int32_t offset) { 3574 StoreToOffset<>(type, reg, base, offset); 3575 } 3576 3577 void Mips64Assembler::StoreFpuToOffset(StoreOperandType type, 3578 FpuRegister reg, 3579 GpuRegister base, 3580 int32_t offset) { 3581 StoreFpuToOffset<>(type, reg, base, offset); 3582 } 3583 3584 static dwarf::Reg DWARFReg(GpuRegister reg) { 3585 return dwarf::Reg::Mips64Core(static_cast<int>(reg)); 3586 } 3587 3588 constexpr size_t kFramePointerSize = 8; 3589 3590 void Mips64Assembler::BuildFrame(size_t frame_size, 3591 ManagedRegister method_reg, 3592 ArrayRef<const ManagedRegister> callee_save_regs, 3593 const ManagedRegisterEntrySpills& entry_spills) { 3594 CHECK_ALIGNED(frame_size, kStackAlignment); 3595 DCHECK(!overwriting_); 3596 3597 // Increase frame to required size. 3598 IncreaseFrameSize(frame_size); 3599 3600 // Push callee saves and return address 3601 int stack_offset = frame_size - kFramePointerSize; 3602 StoreToOffset(kStoreDoubleword, RA, SP, stack_offset); 3603 cfi_.RelOffset(DWARFReg(RA), stack_offset); 3604 for (int i = callee_save_regs.size() - 1; i >= 0; --i) { 3605 stack_offset -= kFramePointerSize; 3606 GpuRegister reg = callee_save_regs[i].AsMips64().AsGpuRegister(); 3607 StoreToOffset(kStoreDoubleword, reg, SP, stack_offset); 3608 cfi_.RelOffset(DWARFReg(reg), stack_offset); 3609 } 3610 3611 // Write out Method*. 3612 StoreToOffset(kStoreDoubleword, method_reg.AsMips64().AsGpuRegister(), SP, 0); 3613 3614 // Write out entry spills. 3615 int32_t offset = frame_size + kFramePointerSize; 3616 for (size_t i = 0; i < entry_spills.size(); ++i) { 3617 Mips64ManagedRegister reg = entry_spills[i].AsMips64(); 3618 ManagedRegisterSpill spill = entry_spills.at(i); 3619 int32_t size = spill.getSize(); 3620 if (reg.IsNoRegister()) { 3621 // only increment stack offset. 3622 offset += size; 3623 } else if (reg.IsFpuRegister()) { 3624 StoreFpuToOffset((size == 4) ? kStoreWord : kStoreDoubleword, 3625 reg.AsFpuRegister(), SP, offset); 3626 offset += size; 3627 } else if (reg.IsGpuRegister()) { 3628 StoreToOffset((size == 4) ? kStoreWord : kStoreDoubleword, 3629 reg.AsGpuRegister(), SP, offset); 3630 offset += size; 3631 } 3632 } 3633 } 3634 3635 void Mips64Assembler::RemoveFrame(size_t frame_size, 3636 ArrayRef<const ManagedRegister> callee_save_regs, 3637 bool may_suspend ATTRIBUTE_UNUSED) { 3638 CHECK_ALIGNED(frame_size, kStackAlignment); 3639 DCHECK(!overwriting_); 3640 cfi_.RememberState(); 3641 3642 // Pop callee saves and return address 3643 int stack_offset = frame_size - (callee_save_regs.size() * kFramePointerSize) - kFramePointerSize; 3644 for (size_t i = 0; i < callee_save_regs.size(); ++i) { 3645 GpuRegister reg = callee_save_regs[i].AsMips64().AsGpuRegister(); 3646 LoadFromOffset(kLoadDoubleword, reg, SP, stack_offset); 3647 cfi_.Restore(DWARFReg(reg)); 3648 stack_offset += kFramePointerSize; 3649 } 3650 LoadFromOffset(kLoadDoubleword, RA, SP, stack_offset); 3651 cfi_.Restore(DWARFReg(RA)); 3652 3653 // Decrease frame to required size. 3654 DecreaseFrameSize(frame_size); 3655 3656 // Then jump to the return address. 3657 Jr(RA); 3658 Nop(); 3659 3660 // The CFI should be restored for any code that follows the exit block. 3661 cfi_.RestoreState(); 3662 cfi_.DefCFAOffset(frame_size); 3663 } 3664 3665 void Mips64Assembler::IncreaseFrameSize(size_t adjust) { 3666 CHECK_ALIGNED(adjust, kFramePointerSize); 3667 DCHECK(!overwriting_); 3668 Daddiu64(SP, SP, static_cast<int32_t>(-adjust)); 3669 cfi_.AdjustCFAOffset(adjust); 3670 } 3671 3672 void Mips64Assembler::DecreaseFrameSize(size_t adjust) { 3673 CHECK_ALIGNED(adjust, kFramePointerSize); 3674 DCHECK(!overwriting_); 3675 Daddiu64(SP, SP, static_cast<int32_t>(adjust)); 3676 cfi_.AdjustCFAOffset(-adjust); 3677 } 3678 3679 void Mips64Assembler::Store(FrameOffset dest, ManagedRegister msrc, size_t size) { 3680 Mips64ManagedRegister src = msrc.AsMips64(); 3681 if (src.IsNoRegister()) { 3682 CHECK_EQ(0u, size); 3683 } else if (src.IsGpuRegister()) { 3684 CHECK(size == 4 || size == 8) << size; 3685 if (size == 8) { 3686 StoreToOffset(kStoreDoubleword, src.AsGpuRegister(), SP, dest.Int32Value()); 3687 } else if (size == 4) { 3688 StoreToOffset(kStoreWord, src.AsGpuRegister(), SP, dest.Int32Value()); 3689 } else { 3690 UNIMPLEMENTED(FATAL) << "We only support Store() of size 4 and 8"; 3691 } 3692 } else if (src.IsFpuRegister()) { 3693 CHECK(size == 4 || size == 8) << size; 3694 if (size == 8) { 3695 StoreFpuToOffset(kStoreDoubleword, src.AsFpuRegister(), SP, dest.Int32Value()); 3696 } else if (size == 4) { 3697 StoreFpuToOffset(kStoreWord, src.AsFpuRegister(), SP, dest.Int32Value()); 3698 } else { 3699 UNIMPLEMENTED(FATAL) << "We only support Store() of size 4 and 8"; 3700 } 3701 } 3702 } 3703 3704 void Mips64Assembler::StoreRef(FrameOffset dest, ManagedRegister msrc) { 3705 Mips64ManagedRegister src = msrc.AsMips64(); 3706 CHECK(src.IsGpuRegister()); 3707 StoreToOffset(kStoreWord, src.AsGpuRegister(), SP, dest.Int32Value()); 3708 } 3709 3710 void Mips64Assembler::StoreRawPtr(FrameOffset dest, ManagedRegister msrc) { 3711 Mips64ManagedRegister src = msrc.AsMips64(); 3712 CHECK(src.IsGpuRegister()); 3713 StoreToOffset(kStoreDoubleword, src.AsGpuRegister(), SP, dest.Int32Value()); 3714 } 3715 3716 void Mips64Assembler::StoreImmediateToFrame(FrameOffset dest, uint32_t imm, 3717 ManagedRegister mscratch) { 3718 Mips64ManagedRegister scratch = mscratch.AsMips64(); 3719 CHECK(scratch.IsGpuRegister()) << scratch; 3720 LoadConst32(scratch.AsGpuRegister(), imm); 3721 StoreToOffset(kStoreWord, scratch.AsGpuRegister(), SP, dest.Int32Value()); 3722 } 3723 3724 void Mips64Assembler::StoreStackOffsetToThread(ThreadOffset64 thr_offs, 3725 FrameOffset fr_offs, 3726 ManagedRegister mscratch) { 3727 Mips64ManagedRegister scratch = mscratch.AsMips64(); 3728 CHECK(scratch.IsGpuRegister()) << scratch; 3729 Daddiu64(scratch.AsGpuRegister(), SP, fr_offs.Int32Value()); 3730 StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), S1, thr_offs.Int32Value()); 3731 } 3732 3733 void Mips64Assembler::StoreStackPointerToThread(ThreadOffset64 thr_offs) { 3734 StoreToOffset(kStoreDoubleword, SP, S1, thr_offs.Int32Value()); 3735 } 3736 3737 void Mips64Assembler::StoreSpanning(FrameOffset dest, ManagedRegister msrc, 3738 FrameOffset in_off, ManagedRegister mscratch) { 3739 Mips64ManagedRegister src = msrc.AsMips64(); 3740 Mips64ManagedRegister scratch = mscratch.AsMips64(); 3741 StoreToOffset(kStoreDoubleword, src.AsGpuRegister(), SP, dest.Int32Value()); 3742 LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(), SP, in_off.Int32Value()); 3743 StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, dest.Int32Value() + 8); 3744 } 3745 3746 void Mips64Assembler::Load(ManagedRegister mdest, FrameOffset src, size_t size) { 3747 return EmitLoad(mdest, SP, src.Int32Value(), size); 3748 } 3749 3750 void Mips64Assembler::LoadFromThread(ManagedRegister mdest, ThreadOffset64 src, size_t size) { 3751 return EmitLoad(mdest, S1, src.Int32Value(), size); 3752 } 3753 3754 void Mips64Assembler::LoadRef(ManagedRegister mdest, FrameOffset src) { 3755 Mips64ManagedRegister dest = mdest.AsMips64(); 3756 CHECK(dest.IsGpuRegister()); 3757 LoadFromOffset(kLoadUnsignedWord, dest.AsGpuRegister(), SP, src.Int32Value()); 3758 } 3759 3760 void Mips64Assembler::LoadRef(ManagedRegister mdest, ManagedRegister base, MemberOffset offs, 3761 bool unpoison_reference) { 3762 Mips64ManagedRegister dest = mdest.AsMips64(); 3763 CHECK(dest.IsGpuRegister() && base.AsMips64().IsGpuRegister()); 3764 LoadFromOffset(kLoadUnsignedWord, dest.AsGpuRegister(), 3765 base.AsMips64().AsGpuRegister(), offs.Int32Value()); 3766 if (unpoison_reference) { 3767 MaybeUnpoisonHeapReference(dest.AsGpuRegister()); 3768 } 3769 } 3770 3771 void Mips64Assembler::LoadRawPtr(ManagedRegister mdest, ManagedRegister base, 3772 Offset offs) { 3773 Mips64ManagedRegister dest = mdest.AsMips64(); 3774 CHECK(dest.IsGpuRegister() && base.AsMips64().IsGpuRegister()); 3775 LoadFromOffset(kLoadDoubleword, dest.AsGpuRegister(), 3776 base.AsMips64().AsGpuRegister(), offs.Int32Value()); 3777 } 3778 3779 void Mips64Assembler::LoadRawPtrFromThread(ManagedRegister mdest, ThreadOffset64 offs) { 3780 Mips64ManagedRegister dest = mdest.AsMips64(); 3781 CHECK(dest.IsGpuRegister()); 3782 LoadFromOffset(kLoadDoubleword, dest.AsGpuRegister(), S1, offs.Int32Value()); 3783 } 3784 3785 void Mips64Assembler::SignExtend(ManagedRegister mreg ATTRIBUTE_UNUSED, 3786 size_t size ATTRIBUTE_UNUSED) { 3787 UNIMPLEMENTED(FATAL) << "No sign extension necessary for MIPS64"; 3788 } 3789 3790 void Mips64Assembler::ZeroExtend(ManagedRegister mreg ATTRIBUTE_UNUSED, 3791 size_t size ATTRIBUTE_UNUSED) { 3792 UNIMPLEMENTED(FATAL) << "No zero extension necessary for MIPS64"; 3793 } 3794 3795 void Mips64Assembler::Move(ManagedRegister mdest, ManagedRegister msrc, size_t size) { 3796 Mips64ManagedRegister dest = mdest.AsMips64(); 3797 Mips64ManagedRegister src = msrc.AsMips64(); 3798 if (!dest.Equals(src)) { 3799 if (dest.IsGpuRegister()) { 3800 CHECK(src.IsGpuRegister()) << src; 3801 Move(dest.AsGpuRegister(), src.AsGpuRegister()); 3802 } else if (dest.IsFpuRegister()) { 3803 CHECK(src.IsFpuRegister()) << src; 3804 if (size == 4) { 3805 MovS(dest.AsFpuRegister(), src.AsFpuRegister()); 3806 } else if (size == 8) { 3807 MovD(dest.AsFpuRegister(), src.AsFpuRegister()); 3808 } else { 3809 UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8"; 3810 } 3811 } 3812 } 3813 } 3814 3815 void Mips64Assembler::CopyRef(FrameOffset dest, FrameOffset src, 3816 ManagedRegister mscratch) { 3817 Mips64ManagedRegister scratch = mscratch.AsMips64(); 3818 CHECK(scratch.IsGpuRegister()) << scratch; 3819 LoadFromOffset(kLoadWord, scratch.AsGpuRegister(), SP, src.Int32Value()); 3820 StoreToOffset(kStoreWord, scratch.AsGpuRegister(), SP, dest.Int32Value()); 3821 } 3822 3823 void Mips64Assembler::CopyRawPtrFromThread(FrameOffset fr_offs, 3824 ThreadOffset64 thr_offs, 3825 ManagedRegister mscratch) { 3826 Mips64ManagedRegister scratch = mscratch.AsMips64(); 3827 CHECK(scratch.IsGpuRegister()) << scratch; 3828 LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(), S1, thr_offs.Int32Value()); 3829 StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, fr_offs.Int32Value()); 3830 } 3831 3832 void Mips64Assembler::CopyRawPtrToThread(ThreadOffset64 thr_offs, 3833 FrameOffset fr_offs, 3834 ManagedRegister mscratch) { 3835 Mips64ManagedRegister scratch = mscratch.AsMips64(); 3836 CHECK(scratch.IsGpuRegister()) << scratch; 3837 LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(), 3838 SP, fr_offs.Int32Value()); 3839 StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), 3840 S1, thr_offs.Int32Value()); 3841 } 3842 3843 void Mips64Assembler::Copy(FrameOffset dest, FrameOffset src, 3844 ManagedRegister mscratch, size_t size) { 3845 Mips64ManagedRegister scratch = mscratch.AsMips64(); 3846 CHECK(scratch.IsGpuRegister()) << scratch; 3847 CHECK(size == 4 || size == 8) << size; 3848 if (size == 4) { 3849 LoadFromOffset(kLoadWord, scratch.AsGpuRegister(), SP, src.Int32Value()); 3850 StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, dest.Int32Value()); 3851 } else if (size == 8) { 3852 LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(), SP, src.Int32Value()); 3853 StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, dest.Int32Value()); 3854 } else { 3855 UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8"; 3856 } 3857 } 3858 3859 void Mips64Assembler::Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset, 3860 ManagedRegister mscratch, size_t size) { 3861 GpuRegister scratch = mscratch.AsMips64().AsGpuRegister(); 3862 CHECK(size == 4 || size == 8) << size; 3863 if (size == 4) { 3864 LoadFromOffset(kLoadWord, scratch, src_base.AsMips64().AsGpuRegister(), 3865 src_offset.Int32Value()); 3866 StoreToOffset(kStoreDoubleword, scratch, SP, dest.Int32Value()); 3867 } else if (size == 8) { 3868 LoadFromOffset(kLoadDoubleword, scratch, src_base.AsMips64().AsGpuRegister(), 3869 src_offset.Int32Value()); 3870 StoreToOffset(kStoreDoubleword, scratch, SP, dest.Int32Value()); 3871 } else { 3872 UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8"; 3873 } 3874 } 3875 3876 void Mips64Assembler::Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src, 3877 ManagedRegister mscratch, size_t size) { 3878 GpuRegister scratch = mscratch.AsMips64().AsGpuRegister(); 3879 CHECK(size == 4 || size == 8) << size; 3880 if (size == 4) { 3881 LoadFromOffset(kLoadWord, scratch, SP, src.Int32Value()); 3882 StoreToOffset(kStoreDoubleword, scratch, dest_base.AsMips64().AsGpuRegister(), 3883 dest_offset.Int32Value()); 3884 } else if (size == 8) { 3885 LoadFromOffset(kLoadDoubleword, scratch, SP, src.Int32Value()); 3886 StoreToOffset(kStoreDoubleword, scratch, dest_base.AsMips64().AsGpuRegister(), 3887 dest_offset.Int32Value()); 3888 } else { 3889 UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8"; 3890 } 3891 } 3892 3893 void Mips64Assembler::Copy(FrameOffset dest ATTRIBUTE_UNUSED, 3894 FrameOffset src_base ATTRIBUTE_UNUSED, 3895 Offset src_offset ATTRIBUTE_UNUSED, 3896 ManagedRegister mscratch ATTRIBUTE_UNUSED, 3897 size_t size ATTRIBUTE_UNUSED) { 3898 UNIMPLEMENTED(FATAL) << "No MIPS64 implementation"; 3899 } 3900 3901 void Mips64Assembler::Copy(ManagedRegister dest, Offset dest_offset, 3902 ManagedRegister src, Offset src_offset, 3903 ManagedRegister mscratch, size_t size) { 3904 GpuRegister scratch = mscratch.AsMips64().AsGpuRegister(); 3905 CHECK(size == 4 || size == 8) << size; 3906 if (size == 4) { 3907 LoadFromOffset(kLoadWord, scratch, src.AsMips64().AsGpuRegister(), src_offset.Int32Value()); 3908 StoreToOffset(kStoreDoubleword, scratch, dest.AsMips64().AsGpuRegister(), dest_offset.Int32Value()); 3909 } else if (size == 8) { 3910 LoadFromOffset(kLoadDoubleword, scratch, src.AsMips64().AsGpuRegister(), 3911 src_offset.Int32Value()); 3912 StoreToOffset(kStoreDoubleword, scratch, dest.AsMips64().AsGpuRegister(), 3913 dest_offset.Int32Value()); 3914 } else { 3915 UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8"; 3916 } 3917 } 3918 3919 void Mips64Assembler::Copy(FrameOffset dest ATTRIBUTE_UNUSED, 3920 Offset dest_offset ATTRIBUTE_UNUSED, 3921 FrameOffset src ATTRIBUTE_UNUSED, 3922 Offset src_offset ATTRIBUTE_UNUSED, 3923 ManagedRegister mscratch ATTRIBUTE_UNUSED, 3924 size_t size ATTRIBUTE_UNUSED) { 3925 UNIMPLEMENTED(FATAL) << "No MIPS64 implementation"; 3926 } 3927 3928 void Mips64Assembler::MemoryBarrier(ManagedRegister mreg ATTRIBUTE_UNUSED) { 3929 // TODO: sync? 3930 UNIMPLEMENTED(FATAL) << "No MIPS64 implementation"; 3931 } 3932 3933 void Mips64Assembler::CreateHandleScopeEntry(ManagedRegister mout_reg, 3934 FrameOffset handle_scope_offset, 3935 ManagedRegister min_reg, 3936 bool null_allowed) { 3937 Mips64ManagedRegister out_reg = mout_reg.AsMips64(); 3938 Mips64ManagedRegister in_reg = min_reg.AsMips64(); 3939 CHECK(in_reg.IsNoRegister() || in_reg.IsGpuRegister()) << in_reg; 3940 CHECK(out_reg.IsGpuRegister()) << out_reg; 3941 if (null_allowed) { 3942 Mips64Label null_arg; 3943 // Null values get a handle scope entry value of 0. Otherwise, the handle scope entry is 3944 // the address in the handle scope holding the reference. 3945 // e.g. out_reg = (handle == 0) ? 0 : (SP+handle_offset) 3946 if (in_reg.IsNoRegister()) { 3947 LoadFromOffset(kLoadUnsignedWord, out_reg.AsGpuRegister(), 3948 SP, handle_scope_offset.Int32Value()); 3949 in_reg = out_reg; 3950 } 3951 if (!out_reg.Equals(in_reg)) { 3952 LoadConst32(out_reg.AsGpuRegister(), 0); 3953 } 3954 Beqzc(in_reg.AsGpuRegister(), &null_arg); 3955 Daddiu64(out_reg.AsGpuRegister(), SP, handle_scope_offset.Int32Value()); 3956 Bind(&null_arg); 3957 } else { 3958 Daddiu64(out_reg.AsGpuRegister(), SP, handle_scope_offset.Int32Value()); 3959 } 3960 } 3961 3962 void Mips64Assembler::CreateHandleScopeEntry(FrameOffset out_off, 3963 FrameOffset handle_scope_offset, 3964 ManagedRegister mscratch, 3965 bool null_allowed) { 3966 Mips64ManagedRegister scratch = mscratch.AsMips64(); 3967 CHECK(scratch.IsGpuRegister()) << scratch; 3968 if (null_allowed) { 3969 Mips64Label null_arg; 3970 LoadFromOffset(kLoadUnsignedWord, scratch.AsGpuRegister(), SP, 3971 handle_scope_offset.Int32Value()); 3972 // Null values get a handle scope entry value of 0. Otherwise, the handle scope entry is 3973 // the address in the handle scope holding the reference. 3974 // e.g. scratch = (scratch == 0) ? 0 : (SP+handle_scope_offset) 3975 Beqzc(scratch.AsGpuRegister(), &null_arg); 3976 Daddiu64(scratch.AsGpuRegister(), SP, handle_scope_offset.Int32Value()); 3977 Bind(&null_arg); 3978 } else { 3979 Daddiu64(scratch.AsGpuRegister(), SP, handle_scope_offset.Int32Value()); 3980 } 3981 StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, out_off.Int32Value()); 3982 } 3983 3984 // Given a handle scope entry, load the associated reference. 3985 void Mips64Assembler::LoadReferenceFromHandleScope(ManagedRegister mout_reg, 3986 ManagedRegister min_reg) { 3987 Mips64ManagedRegister out_reg = mout_reg.AsMips64(); 3988 Mips64ManagedRegister in_reg = min_reg.AsMips64(); 3989 CHECK(out_reg.IsGpuRegister()) << out_reg; 3990 CHECK(in_reg.IsGpuRegister()) << in_reg; 3991 Mips64Label null_arg; 3992 if (!out_reg.Equals(in_reg)) { 3993 LoadConst32(out_reg.AsGpuRegister(), 0); 3994 } 3995 Beqzc(in_reg.AsGpuRegister(), &null_arg); 3996 LoadFromOffset(kLoadDoubleword, out_reg.AsGpuRegister(), 3997 in_reg.AsGpuRegister(), 0); 3998 Bind(&null_arg); 3999 } 4000 4001 void Mips64Assembler::VerifyObject(ManagedRegister src ATTRIBUTE_UNUSED, 4002 bool could_be_null ATTRIBUTE_UNUSED) { 4003 // TODO: not validating references 4004 } 4005 4006 void Mips64Assembler::VerifyObject(FrameOffset src ATTRIBUTE_UNUSED, 4007 bool could_be_null ATTRIBUTE_UNUSED) { 4008 // TODO: not validating references 4009 } 4010 4011 void Mips64Assembler::Call(ManagedRegister mbase, Offset offset, ManagedRegister mscratch) { 4012 Mips64ManagedRegister base = mbase.AsMips64(); 4013 Mips64ManagedRegister scratch = mscratch.AsMips64(); 4014 CHECK(base.IsGpuRegister()) << base; 4015 CHECK(scratch.IsGpuRegister()) << scratch; 4016 LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(), 4017 base.AsGpuRegister(), offset.Int32Value()); 4018 Jalr(scratch.AsGpuRegister()); 4019 Nop(); 4020 // TODO: place reference map on call 4021 } 4022 4023 void Mips64Assembler::Call(FrameOffset base, Offset offset, ManagedRegister mscratch) { 4024 Mips64ManagedRegister scratch = mscratch.AsMips64(); 4025 CHECK(scratch.IsGpuRegister()) << scratch; 4026 // Call *(*(SP + base) + offset) 4027 LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(), 4028 SP, base.Int32Value()); 4029 LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(), 4030 scratch.AsGpuRegister(), offset.Int32Value()); 4031 Jalr(scratch.AsGpuRegister()); 4032 Nop(); 4033 // TODO: place reference map on call 4034 } 4035 4036 void Mips64Assembler::CallFromThread(ThreadOffset64 offset ATTRIBUTE_UNUSED, 4037 ManagedRegister mscratch ATTRIBUTE_UNUSED) { 4038 UNIMPLEMENTED(FATAL) << "No MIPS64 implementation"; 4039 } 4040 4041 void Mips64Assembler::GetCurrentThread(ManagedRegister tr) { 4042 Move(tr.AsMips64().AsGpuRegister(), S1); 4043 } 4044 4045 void Mips64Assembler::GetCurrentThread(FrameOffset offset, 4046 ManagedRegister mscratch ATTRIBUTE_UNUSED) { 4047 StoreToOffset(kStoreDoubleword, S1, SP, offset.Int32Value()); 4048 } 4049 4050 void Mips64Assembler::ExceptionPoll(ManagedRegister mscratch, size_t stack_adjust) { 4051 Mips64ManagedRegister scratch = mscratch.AsMips64(); 4052 exception_blocks_.emplace_back(scratch, stack_adjust); 4053 LoadFromOffset(kLoadDoubleword, 4054 scratch.AsGpuRegister(), 4055 S1, 4056 Thread::ExceptionOffset<kMips64PointerSize>().Int32Value()); 4057 Bnezc(scratch.AsGpuRegister(), exception_blocks_.back().Entry()); 4058 } 4059 4060 void Mips64Assembler::EmitExceptionPoll(Mips64ExceptionSlowPath* exception) { 4061 Bind(exception->Entry()); 4062 if (exception->stack_adjust_ != 0) { // Fix up the frame. 4063 DecreaseFrameSize(exception->stack_adjust_); 4064 } 4065 // Pass exception object as argument. 4066 // Don't care about preserving A0 as this call won't return. 4067 CheckEntrypointTypes<kQuickDeliverException, void, mirror::Object*>(); 4068 Move(A0, exception->scratch_.AsGpuRegister()); 4069 // Set up call to Thread::Current()->pDeliverException 4070 LoadFromOffset(kLoadDoubleword, 4071 T9, 4072 S1, 4073 QUICK_ENTRYPOINT_OFFSET(kMips64PointerSize, pDeliverException).Int32Value()); 4074 Jr(T9); 4075 Nop(); 4076 4077 // Call never returns 4078 Break(); 4079 } 4080 4081 } // namespace mips64 4082 } // namespace art 4083