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::Dinsu(GpuRegister rt, GpuRegister rs, int pos, int size) { 434 CHECK(IsUint<5>(pos - 32)) << pos; 435 CHECK(IsUint<5>(size - 1)) << size; 436 CHECK(IsUint<5>(pos + size - 33)) << pos << " + " << size; 437 EmitR(0x1f, rs, rt, static_cast<GpuRegister>(pos + size - 33), pos - 32, 0x6); 438 } 439 440 void Mips64Assembler::Lsa(GpuRegister rd, GpuRegister rs, GpuRegister rt, int saPlusOne) { 441 CHECK(1 <= saPlusOne && saPlusOne <= 4) << saPlusOne; 442 int sa = saPlusOne - 1; 443 EmitR(0x0, rs, rt, rd, sa, 0x05); 444 } 445 446 void Mips64Assembler::Dlsa(GpuRegister rd, GpuRegister rs, GpuRegister rt, int saPlusOne) { 447 CHECK(1 <= saPlusOne && saPlusOne <= 4) << saPlusOne; 448 int sa = saPlusOne - 1; 449 EmitR(0x0, rs, rt, rd, sa, 0x15); 450 } 451 452 void Mips64Assembler::Wsbh(GpuRegister rd, GpuRegister rt) { 453 EmitRtd(0x1f, rt, rd, 2, 0x20); 454 } 455 456 void Mips64Assembler::Sc(GpuRegister rt, GpuRegister base, int16_t imm9) { 457 CHECK(IsInt<9>(imm9)); 458 EmitI(0x1f, base, rt, ((imm9 & 0x1FF) << 7) | 0x26); 459 } 460 461 void Mips64Assembler::Scd(GpuRegister rt, GpuRegister base, int16_t imm9) { 462 CHECK(IsInt<9>(imm9)); 463 EmitI(0x1f, base, rt, ((imm9 & 0x1FF) << 7) | 0x27); 464 } 465 466 void Mips64Assembler::Ll(GpuRegister rt, GpuRegister base, int16_t imm9) { 467 CHECK(IsInt<9>(imm9)); 468 EmitI(0x1f, base, rt, ((imm9 & 0x1FF) << 7) | 0x36); 469 } 470 471 void Mips64Assembler::Lld(GpuRegister rt, GpuRegister base, int16_t imm9) { 472 CHECK(IsInt<9>(imm9)); 473 EmitI(0x1f, base, rt, ((imm9 & 0x1FF) << 7) | 0x37); 474 } 475 476 void Mips64Assembler::Sll(GpuRegister rd, GpuRegister rt, int shamt) { 477 EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x00); 478 } 479 480 void Mips64Assembler::Srl(GpuRegister rd, GpuRegister rt, int shamt) { 481 EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x02); 482 } 483 484 void Mips64Assembler::Rotr(GpuRegister rd, GpuRegister rt, int shamt) { 485 EmitR(0, static_cast<GpuRegister>(1), rt, rd, shamt, 0x02); 486 } 487 488 void Mips64Assembler::Sra(GpuRegister rd, GpuRegister rt, int shamt) { 489 EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x03); 490 } 491 492 void Mips64Assembler::Sllv(GpuRegister rd, GpuRegister rt, GpuRegister rs) { 493 EmitR(0, rs, rt, rd, 0, 0x04); 494 } 495 496 void Mips64Assembler::Rotrv(GpuRegister rd, GpuRegister rt, GpuRegister rs) { 497 EmitR(0, rs, rt, rd, 1, 0x06); 498 } 499 500 void Mips64Assembler::Srlv(GpuRegister rd, GpuRegister rt, GpuRegister rs) { 501 EmitR(0, rs, rt, rd, 0, 0x06); 502 } 503 504 void Mips64Assembler::Srav(GpuRegister rd, GpuRegister rt, GpuRegister rs) { 505 EmitR(0, rs, rt, rd, 0, 0x07); 506 } 507 508 void Mips64Assembler::Dsll(GpuRegister rd, GpuRegister rt, int shamt) { 509 EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x38); 510 } 511 512 void Mips64Assembler::Dsrl(GpuRegister rd, GpuRegister rt, int shamt) { 513 EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x3a); 514 } 515 516 void Mips64Assembler::Drotr(GpuRegister rd, GpuRegister rt, int shamt) { 517 EmitR(0, static_cast<GpuRegister>(1), rt, rd, shamt, 0x3a); 518 } 519 520 void Mips64Assembler::Dsra(GpuRegister rd, GpuRegister rt, int shamt) { 521 EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x3b); 522 } 523 524 void Mips64Assembler::Dsll32(GpuRegister rd, GpuRegister rt, int shamt) { 525 EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x3c); 526 } 527 528 void Mips64Assembler::Dsrl32(GpuRegister rd, GpuRegister rt, int shamt) { 529 EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x3e); 530 } 531 532 void Mips64Assembler::Drotr32(GpuRegister rd, GpuRegister rt, int shamt) { 533 EmitR(0, static_cast<GpuRegister>(1), rt, rd, shamt, 0x3e); 534 } 535 536 void Mips64Assembler::Dsra32(GpuRegister rd, GpuRegister rt, int shamt) { 537 EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x3f); 538 } 539 540 void Mips64Assembler::Dsllv(GpuRegister rd, GpuRegister rt, GpuRegister rs) { 541 EmitR(0, rs, rt, rd, 0, 0x14); 542 } 543 544 void Mips64Assembler::Dsrlv(GpuRegister rd, GpuRegister rt, GpuRegister rs) { 545 EmitR(0, rs, rt, rd, 0, 0x16); 546 } 547 548 void Mips64Assembler::Drotrv(GpuRegister rd, GpuRegister rt, GpuRegister rs) { 549 EmitR(0, rs, rt, rd, 1, 0x16); 550 } 551 552 void Mips64Assembler::Dsrav(GpuRegister rd, GpuRegister rt, GpuRegister rs) { 553 EmitR(0, rs, rt, rd, 0, 0x17); 554 } 555 556 void Mips64Assembler::Lb(GpuRegister rt, GpuRegister rs, uint16_t imm16) { 557 EmitI(0x20, rs, rt, imm16); 558 } 559 560 void Mips64Assembler::Lh(GpuRegister rt, GpuRegister rs, uint16_t imm16) { 561 EmitI(0x21, rs, rt, imm16); 562 } 563 564 void Mips64Assembler::Lw(GpuRegister rt, GpuRegister rs, uint16_t imm16) { 565 EmitI(0x23, rs, rt, imm16); 566 } 567 568 void Mips64Assembler::Ld(GpuRegister rt, GpuRegister rs, uint16_t imm16) { 569 EmitI(0x37, rs, rt, imm16); 570 } 571 572 void Mips64Assembler::Lbu(GpuRegister rt, GpuRegister rs, uint16_t imm16) { 573 EmitI(0x24, rs, rt, imm16); 574 } 575 576 void Mips64Assembler::Lhu(GpuRegister rt, GpuRegister rs, uint16_t imm16) { 577 EmitI(0x25, rs, rt, imm16); 578 } 579 580 void Mips64Assembler::Lwu(GpuRegister rt, GpuRegister rs, uint16_t imm16) { 581 EmitI(0x27, rs, rt, imm16); 582 } 583 584 void Mips64Assembler::Lwpc(GpuRegister rs, uint32_t imm19) { 585 CHECK(IsUint<19>(imm19)) << imm19; 586 EmitI21(0x3B, rs, (0x01 << 19) | imm19); 587 } 588 589 void Mips64Assembler::Lwupc(GpuRegister rs, uint32_t imm19) { 590 CHECK(IsUint<19>(imm19)) << imm19; 591 EmitI21(0x3B, rs, (0x02 << 19) | imm19); 592 } 593 594 void Mips64Assembler::Ldpc(GpuRegister rs, uint32_t imm18) { 595 CHECK(IsUint<18>(imm18)) << imm18; 596 EmitI21(0x3B, rs, (0x06 << 18) | imm18); 597 } 598 599 void Mips64Assembler::Lui(GpuRegister rt, uint16_t imm16) { 600 EmitI(0xf, static_cast<GpuRegister>(0), rt, imm16); 601 } 602 603 void Mips64Assembler::Aui(GpuRegister rt, GpuRegister rs, uint16_t imm16) { 604 EmitI(0xf, rs, rt, imm16); 605 } 606 607 void Mips64Assembler::Daui(GpuRegister rt, GpuRegister rs, uint16_t imm16) { 608 CHECK_NE(rs, ZERO); 609 EmitI(0x1d, rs, rt, imm16); 610 } 611 612 void Mips64Assembler::Dahi(GpuRegister rs, uint16_t imm16) { 613 EmitI(1, rs, static_cast<GpuRegister>(6), imm16); 614 } 615 616 void Mips64Assembler::Dati(GpuRegister rs, uint16_t imm16) { 617 EmitI(1, rs, static_cast<GpuRegister>(0x1e), imm16); 618 } 619 620 void Mips64Assembler::Sync(uint32_t stype) { 621 EmitR(0, static_cast<GpuRegister>(0), static_cast<GpuRegister>(0), 622 static_cast<GpuRegister>(0), stype & 0x1f, 0xf); 623 } 624 625 void Mips64Assembler::Sb(GpuRegister rt, GpuRegister rs, uint16_t imm16) { 626 EmitI(0x28, rs, rt, imm16); 627 } 628 629 void Mips64Assembler::Sh(GpuRegister rt, GpuRegister rs, uint16_t imm16) { 630 EmitI(0x29, rs, rt, imm16); 631 } 632 633 void Mips64Assembler::Sw(GpuRegister rt, GpuRegister rs, uint16_t imm16) { 634 EmitI(0x2b, rs, rt, imm16); 635 } 636 637 void Mips64Assembler::Sd(GpuRegister rt, GpuRegister rs, uint16_t imm16) { 638 EmitI(0x3f, rs, rt, imm16); 639 } 640 641 void Mips64Assembler::Slt(GpuRegister rd, GpuRegister rs, GpuRegister rt) { 642 EmitR(0, rs, rt, rd, 0, 0x2a); 643 } 644 645 void Mips64Assembler::Sltu(GpuRegister rd, GpuRegister rs, GpuRegister rt) { 646 EmitR(0, rs, rt, rd, 0, 0x2b); 647 } 648 649 void Mips64Assembler::Slti(GpuRegister rt, GpuRegister rs, uint16_t imm16) { 650 EmitI(0xa, rs, rt, imm16); 651 } 652 653 void Mips64Assembler::Sltiu(GpuRegister rt, GpuRegister rs, uint16_t imm16) { 654 EmitI(0xb, rs, rt, imm16); 655 } 656 657 void Mips64Assembler::Seleqz(GpuRegister rd, GpuRegister rs, GpuRegister rt) { 658 EmitR(0, rs, rt, rd, 0, 0x35); 659 } 660 661 void Mips64Assembler::Selnez(GpuRegister rd, GpuRegister rs, GpuRegister rt) { 662 EmitR(0, rs, rt, rd, 0, 0x37); 663 } 664 665 void Mips64Assembler::Clz(GpuRegister rd, GpuRegister rs) { 666 EmitRsd(0, rs, rd, 0x01, 0x10); 667 } 668 669 void Mips64Assembler::Clo(GpuRegister rd, GpuRegister rs) { 670 EmitRsd(0, rs, rd, 0x01, 0x11); 671 } 672 673 void Mips64Assembler::Dclz(GpuRegister rd, GpuRegister rs) { 674 EmitRsd(0, rs, rd, 0x01, 0x12); 675 } 676 677 void Mips64Assembler::Dclo(GpuRegister rd, GpuRegister rs) { 678 EmitRsd(0, rs, rd, 0x01, 0x13); 679 } 680 681 void Mips64Assembler::Jalr(GpuRegister rd, GpuRegister rs) { 682 EmitR(0, rs, static_cast<GpuRegister>(0), rd, 0, 0x09); 683 } 684 685 void Mips64Assembler::Jalr(GpuRegister rs) { 686 Jalr(RA, rs); 687 } 688 689 void Mips64Assembler::Jr(GpuRegister rs) { 690 Jalr(ZERO, rs); 691 } 692 693 void Mips64Assembler::Auipc(GpuRegister rs, uint16_t imm16) { 694 EmitI(0x3B, rs, static_cast<GpuRegister>(0x1E), imm16); 695 } 696 697 void Mips64Assembler::Addiupc(GpuRegister rs, uint32_t imm19) { 698 CHECK(IsUint<19>(imm19)) << imm19; 699 EmitI21(0x3B, rs, imm19); 700 } 701 702 void Mips64Assembler::Bc(uint32_t imm26) { 703 EmitI26(0x32, imm26); 704 } 705 706 void Mips64Assembler::Balc(uint32_t imm26) { 707 EmitI26(0x3A, imm26); 708 } 709 710 void Mips64Assembler::Jic(GpuRegister rt, uint16_t imm16) { 711 EmitI(0x36, static_cast<GpuRegister>(0), rt, imm16); 712 } 713 714 void Mips64Assembler::Jialc(GpuRegister rt, uint16_t imm16) { 715 EmitI(0x3E, static_cast<GpuRegister>(0), rt, imm16); 716 } 717 718 void Mips64Assembler::Bltc(GpuRegister rs, GpuRegister rt, uint16_t imm16) { 719 CHECK_NE(rs, ZERO); 720 CHECK_NE(rt, ZERO); 721 CHECK_NE(rs, rt); 722 EmitI(0x17, rs, rt, imm16); 723 } 724 725 void Mips64Assembler::Bltzc(GpuRegister rt, uint16_t imm16) { 726 CHECK_NE(rt, ZERO); 727 EmitI(0x17, rt, rt, imm16); 728 } 729 730 void Mips64Assembler::Bgtzc(GpuRegister rt, uint16_t imm16) { 731 CHECK_NE(rt, ZERO); 732 EmitI(0x17, static_cast<GpuRegister>(0), rt, imm16); 733 } 734 735 void Mips64Assembler::Bgec(GpuRegister rs, GpuRegister rt, uint16_t imm16) { 736 CHECK_NE(rs, ZERO); 737 CHECK_NE(rt, ZERO); 738 CHECK_NE(rs, rt); 739 EmitI(0x16, rs, rt, imm16); 740 } 741 742 void Mips64Assembler::Bgezc(GpuRegister rt, uint16_t imm16) { 743 CHECK_NE(rt, ZERO); 744 EmitI(0x16, rt, rt, imm16); 745 } 746 747 void Mips64Assembler::Blezc(GpuRegister rt, uint16_t imm16) { 748 CHECK_NE(rt, ZERO); 749 EmitI(0x16, static_cast<GpuRegister>(0), rt, imm16); 750 } 751 752 void Mips64Assembler::Bltuc(GpuRegister rs, GpuRegister rt, uint16_t imm16) { 753 CHECK_NE(rs, ZERO); 754 CHECK_NE(rt, ZERO); 755 CHECK_NE(rs, rt); 756 EmitI(0x7, rs, rt, imm16); 757 } 758 759 void Mips64Assembler::Bgeuc(GpuRegister rs, GpuRegister rt, uint16_t imm16) { 760 CHECK_NE(rs, ZERO); 761 CHECK_NE(rt, ZERO); 762 CHECK_NE(rs, rt); 763 EmitI(0x6, rs, rt, imm16); 764 } 765 766 void Mips64Assembler::Beqc(GpuRegister rs, GpuRegister rt, uint16_t imm16) { 767 CHECK_NE(rs, ZERO); 768 CHECK_NE(rt, ZERO); 769 CHECK_NE(rs, rt); 770 EmitI(0x8, std::min(rs, rt), std::max(rs, rt), imm16); 771 } 772 773 void Mips64Assembler::Bnec(GpuRegister rs, GpuRegister rt, uint16_t imm16) { 774 CHECK_NE(rs, ZERO); 775 CHECK_NE(rt, ZERO); 776 CHECK_NE(rs, rt); 777 EmitI(0x18, std::min(rs, rt), std::max(rs, rt), imm16); 778 } 779 780 void Mips64Assembler::Beqzc(GpuRegister rs, uint32_t imm21) { 781 CHECK_NE(rs, ZERO); 782 EmitI21(0x36, rs, imm21); 783 } 784 785 void Mips64Assembler::Bnezc(GpuRegister rs, uint32_t imm21) { 786 CHECK_NE(rs, ZERO); 787 EmitI21(0x3E, rs, imm21); 788 } 789 790 void Mips64Assembler::Bc1eqz(FpuRegister ft, uint16_t imm16) { 791 EmitFI(0x11, 0x9, ft, imm16); 792 } 793 794 void Mips64Assembler::Bc1nez(FpuRegister ft, uint16_t imm16) { 795 EmitFI(0x11, 0xD, ft, imm16); 796 } 797 798 void Mips64Assembler::EmitBcondc(BranchCondition cond, 799 GpuRegister rs, 800 GpuRegister rt, 801 uint32_t imm16_21) { 802 switch (cond) { 803 case kCondLT: 804 Bltc(rs, rt, imm16_21); 805 break; 806 case kCondGE: 807 Bgec(rs, rt, imm16_21); 808 break; 809 case kCondLE: 810 Bgec(rt, rs, imm16_21); 811 break; 812 case kCondGT: 813 Bltc(rt, rs, imm16_21); 814 break; 815 case kCondLTZ: 816 CHECK_EQ(rt, ZERO); 817 Bltzc(rs, imm16_21); 818 break; 819 case kCondGEZ: 820 CHECK_EQ(rt, ZERO); 821 Bgezc(rs, imm16_21); 822 break; 823 case kCondLEZ: 824 CHECK_EQ(rt, ZERO); 825 Blezc(rs, imm16_21); 826 break; 827 case kCondGTZ: 828 CHECK_EQ(rt, ZERO); 829 Bgtzc(rs, imm16_21); 830 break; 831 case kCondEQ: 832 Beqc(rs, rt, imm16_21); 833 break; 834 case kCondNE: 835 Bnec(rs, rt, imm16_21); 836 break; 837 case kCondEQZ: 838 CHECK_EQ(rt, ZERO); 839 Beqzc(rs, imm16_21); 840 break; 841 case kCondNEZ: 842 CHECK_EQ(rt, ZERO); 843 Bnezc(rs, imm16_21); 844 break; 845 case kCondLTU: 846 Bltuc(rs, rt, imm16_21); 847 break; 848 case kCondGEU: 849 Bgeuc(rs, rt, imm16_21); 850 break; 851 case kCondF: 852 CHECK_EQ(rt, ZERO); 853 Bc1eqz(static_cast<FpuRegister>(rs), imm16_21); 854 break; 855 case kCondT: 856 CHECK_EQ(rt, ZERO); 857 Bc1nez(static_cast<FpuRegister>(rs), imm16_21); 858 break; 859 case kUncond: 860 LOG(FATAL) << "Unexpected branch condition " << cond; 861 UNREACHABLE(); 862 } 863 } 864 865 void Mips64Assembler::AddS(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 866 EmitFR(0x11, 0x10, ft, fs, fd, 0x0); 867 } 868 869 void Mips64Assembler::SubS(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 870 EmitFR(0x11, 0x10, ft, fs, fd, 0x1); 871 } 872 873 void Mips64Assembler::MulS(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 874 EmitFR(0x11, 0x10, ft, fs, fd, 0x2); 875 } 876 877 void Mips64Assembler::DivS(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 878 EmitFR(0x11, 0x10, ft, fs, fd, 0x3); 879 } 880 881 void Mips64Assembler::AddD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 882 EmitFR(0x11, 0x11, ft, fs, fd, 0x0); 883 } 884 885 void Mips64Assembler::SubD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 886 EmitFR(0x11, 0x11, ft, fs, fd, 0x1); 887 } 888 889 void Mips64Assembler::MulD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 890 EmitFR(0x11, 0x11, ft, fs, fd, 0x2); 891 } 892 893 void Mips64Assembler::DivD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 894 EmitFR(0x11, 0x11, ft, fs, fd, 0x3); 895 } 896 897 void Mips64Assembler::SqrtS(FpuRegister fd, FpuRegister fs) { 898 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x4); 899 } 900 901 void Mips64Assembler::SqrtD(FpuRegister fd, FpuRegister fs) { 902 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x4); 903 } 904 905 void Mips64Assembler::AbsS(FpuRegister fd, FpuRegister fs) { 906 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x5); 907 } 908 909 void Mips64Assembler::AbsD(FpuRegister fd, FpuRegister fs) { 910 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x5); 911 } 912 913 void Mips64Assembler::MovS(FpuRegister fd, FpuRegister fs) { 914 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x6); 915 } 916 917 void Mips64Assembler::MovD(FpuRegister fd, FpuRegister fs) { 918 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x6); 919 } 920 921 void Mips64Assembler::NegS(FpuRegister fd, FpuRegister fs) { 922 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x7); 923 } 924 925 void Mips64Assembler::NegD(FpuRegister fd, FpuRegister fs) { 926 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x7); 927 } 928 929 void Mips64Assembler::RoundLS(FpuRegister fd, FpuRegister fs) { 930 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x8); 931 } 932 933 void Mips64Assembler::RoundLD(FpuRegister fd, FpuRegister fs) { 934 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x8); 935 } 936 937 void Mips64Assembler::RoundWS(FpuRegister fd, FpuRegister fs) { 938 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xc); 939 } 940 941 void Mips64Assembler::RoundWD(FpuRegister fd, FpuRegister fs) { 942 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xc); 943 } 944 945 void Mips64Assembler::TruncLS(FpuRegister fd, FpuRegister fs) { 946 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x9); 947 } 948 949 void Mips64Assembler::TruncLD(FpuRegister fd, FpuRegister fs) { 950 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x9); 951 } 952 953 void Mips64Assembler::TruncWS(FpuRegister fd, FpuRegister fs) { 954 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xd); 955 } 956 957 void Mips64Assembler::TruncWD(FpuRegister fd, FpuRegister fs) { 958 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xd); 959 } 960 961 void Mips64Assembler::CeilLS(FpuRegister fd, FpuRegister fs) { 962 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xa); 963 } 964 965 void Mips64Assembler::CeilLD(FpuRegister fd, FpuRegister fs) { 966 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xa); 967 } 968 969 void Mips64Assembler::CeilWS(FpuRegister fd, FpuRegister fs) { 970 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xe); 971 } 972 973 void Mips64Assembler::CeilWD(FpuRegister fd, FpuRegister fs) { 974 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xe); 975 } 976 977 void Mips64Assembler::FloorLS(FpuRegister fd, FpuRegister fs) { 978 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xb); 979 } 980 981 void Mips64Assembler::FloorLD(FpuRegister fd, FpuRegister fs) { 982 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xb); 983 } 984 985 void Mips64Assembler::FloorWS(FpuRegister fd, FpuRegister fs) { 986 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xf); 987 } 988 989 void Mips64Assembler::FloorWD(FpuRegister fd, FpuRegister fs) { 990 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xf); 991 } 992 993 void Mips64Assembler::SelS(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 994 EmitFR(0x11, 0x10, ft, fs, fd, 0x10); 995 } 996 997 void Mips64Assembler::SelD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 998 EmitFR(0x11, 0x11, ft, fs, fd, 0x10); 999 } 1000 1001 void Mips64Assembler::RintS(FpuRegister fd, FpuRegister fs) { 1002 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x1a); 1003 } 1004 1005 void Mips64Assembler::RintD(FpuRegister fd, FpuRegister fs) { 1006 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x1a); 1007 } 1008 1009 void Mips64Assembler::ClassS(FpuRegister fd, FpuRegister fs) { 1010 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x1b); 1011 } 1012 1013 void Mips64Assembler::ClassD(FpuRegister fd, FpuRegister fs) { 1014 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x1b); 1015 } 1016 1017 void Mips64Assembler::MinS(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1018 EmitFR(0x11, 0x10, ft, fs, fd, 0x1c); 1019 } 1020 1021 void Mips64Assembler::MinD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1022 EmitFR(0x11, 0x11, ft, fs, fd, 0x1c); 1023 } 1024 1025 void Mips64Assembler::MaxS(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1026 EmitFR(0x11, 0x10, ft, fs, fd, 0x1e); 1027 } 1028 1029 void Mips64Assembler::MaxD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1030 EmitFR(0x11, 0x11, ft, fs, fd, 0x1e); 1031 } 1032 1033 void Mips64Assembler::CmpUnS(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1034 EmitFR(0x11, 0x14, ft, fs, fd, 0x01); 1035 } 1036 1037 void Mips64Assembler::CmpEqS(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1038 EmitFR(0x11, 0x14, ft, fs, fd, 0x02); 1039 } 1040 1041 void Mips64Assembler::CmpUeqS(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1042 EmitFR(0x11, 0x14, ft, fs, fd, 0x03); 1043 } 1044 1045 void Mips64Assembler::CmpLtS(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1046 EmitFR(0x11, 0x14, ft, fs, fd, 0x04); 1047 } 1048 1049 void Mips64Assembler::CmpUltS(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1050 EmitFR(0x11, 0x14, ft, fs, fd, 0x05); 1051 } 1052 1053 void Mips64Assembler::CmpLeS(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1054 EmitFR(0x11, 0x14, ft, fs, fd, 0x06); 1055 } 1056 1057 void Mips64Assembler::CmpUleS(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1058 EmitFR(0x11, 0x14, ft, fs, fd, 0x07); 1059 } 1060 1061 void Mips64Assembler::CmpOrS(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1062 EmitFR(0x11, 0x14, ft, fs, fd, 0x11); 1063 } 1064 1065 void Mips64Assembler::CmpUneS(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1066 EmitFR(0x11, 0x14, ft, fs, fd, 0x12); 1067 } 1068 1069 void Mips64Assembler::CmpNeS(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1070 EmitFR(0x11, 0x14, ft, fs, fd, 0x13); 1071 } 1072 1073 void Mips64Assembler::CmpUnD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1074 EmitFR(0x11, 0x15, ft, fs, fd, 0x01); 1075 } 1076 1077 void Mips64Assembler::CmpEqD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1078 EmitFR(0x11, 0x15, ft, fs, fd, 0x02); 1079 } 1080 1081 void Mips64Assembler::CmpUeqD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1082 EmitFR(0x11, 0x15, ft, fs, fd, 0x03); 1083 } 1084 1085 void Mips64Assembler::CmpLtD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1086 EmitFR(0x11, 0x15, ft, fs, fd, 0x04); 1087 } 1088 1089 void Mips64Assembler::CmpUltD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1090 EmitFR(0x11, 0x15, ft, fs, fd, 0x05); 1091 } 1092 1093 void Mips64Assembler::CmpLeD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1094 EmitFR(0x11, 0x15, ft, fs, fd, 0x06); 1095 } 1096 1097 void Mips64Assembler::CmpUleD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1098 EmitFR(0x11, 0x15, ft, fs, fd, 0x07); 1099 } 1100 1101 void Mips64Assembler::CmpOrD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1102 EmitFR(0x11, 0x15, ft, fs, fd, 0x11); 1103 } 1104 1105 void Mips64Assembler::CmpUneD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1106 EmitFR(0x11, 0x15, ft, fs, fd, 0x12); 1107 } 1108 1109 void Mips64Assembler::CmpNeD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { 1110 EmitFR(0x11, 0x15, ft, fs, fd, 0x13); 1111 } 1112 1113 void Mips64Assembler::Cvtsw(FpuRegister fd, FpuRegister fs) { 1114 EmitFR(0x11, 0x14, static_cast<FpuRegister>(0), fs, fd, 0x20); 1115 } 1116 1117 void Mips64Assembler::Cvtdw(FpuRegister fd, FpuRegister fs) { 1118 EmitFR(0x11, 0x14, static_cast<FpuRegister>(0), fs, fd, 0x21); 1119 } 1120 1121 void Mips64Assembler::Cvtsd(FpuRegister fd, FpuRegister fs) { 1122 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x20); 1123 } 1124 1125 void Mips64Assembler::Cvtds(FpuRegister fd, FpuRegister fs) { 1126 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x21); 1127 } 1128 1129 void Mips64Assembler::Cvtsl(FpuRegister fd, FpuRegister fs) { 1130 EmitFR(0x11, 0x15, static_cast<FpuRegister>(0), fs, fd, 0x20); 1131 } 1132 1133 void Mips64Assembler::Cvtdl(FpuRegister fd, FpuRegister fs) { 1134 EmitFR(0x11, 0x15, static_cast<FpuRegister>(0), fs, fd, 0x21); 1135 } 1136 1137 void Mips64Assembler::Mfc1(GpuRegister rt, FpuRegister fs) { 1138 EmitFR(0x11, 0x00, static_cast<FpuRegister>(rt), fs, static_cast<FpuRegister>(0), 0x0); 1139 } 1140 1141 void Mips64Assembler::Mfhc1(GpuRegister rt, FpuRegister fs) { 1142 EmitFR(0x11, 0x03, static_cast<FpuRegister>(rt), fs, static_cast<FpuRegister>(0), 0x0); 1143 } 1144 1145 void Mips64Assembler::Mtc1(GpuRegister rt, FpuRegister fs) { 1146 EmitFR(0x11, 0x04, static_cast<FpuRegister>(rt), fs, static_cast<FpuRegister>(0), 0x0); 1147 } 1148 1149 void Mips64Assembler::Mthc1(GpuRegister rt, FpuRegister fs) { 1150 EmitFR(0x11, 0x07, static_cast<FpuRegister>(rt), fs, static_cast<FpuRegister>(0), 0x0); 1151 } 1152 1153 void Mips64Assembler::Dmfc1(GpuRegister rt, FpuRegister fs) { 1154 EmitFR(0x11, 0x01, static_cast<FpuRegister>(rt), fs, static_cast<FpuRegister>(0), 0x0); 1155 } 1156 1157 void Mips64Assembler::Dmtc1(GpuRegister rt, FpuRegister fs) { 1158 EmitFR(0x11, 0x05, static_cast<FpuRegister>(rt), fs, static_cast<FpuRegister>(0), 0x0); 1159 } 1160 1161 void Mips64Assembler::Lwc1(FpuRegister ft, GpuRegister rs, uint16_t imm16) { 1162 EmitI(0x31, rs, static_cast<GpuRegister>(ft), imm16); 1163 } 1164 1165 void Mips64Assembler::Ldc1(FpuRegister ft, GpuRegister rs, uint16_t imm16) { 1166 EmitI(0x35, rs, static_cast<GpuRegister>(ft), imm16); 1167 } 1168 1169 void Mips64Assembler::Swc1(FpuRegister ft, GpuRegister rs, uint16_t imm16) { 1170 EmitI(0x39, rs, static_cast<GpuRegister>(ft), imm16); 1171 } 1172 1173 void Mips64Assembler::Sdc1(FpuRegister ft, GpuRegister rs, uint16_t imm16) { 1174 EmitI(0x3d, rs, static_cast<GpuRegister>(ft), imm16); 1175 } 1176 1177 void Mips64Assembler::Break() { 1178 EmitR(0, static_cast<GpuRegister>(0), static_cast<GpuRegister>(0), 1179 static_cast<GpuRegister>(0), 0, 0xD); 1180 } 1181 1182 void Mips64Assembler::Nop() { 1183 EmitR(0x0, static_cast<GpuRegister>(0), static_cast<GpuRegister>(0), 1184 static_cast<GpuRegister>(0), 0, 0x0); 1185 } 1186 1187 void Mips64Assembler::Move(GpuRegister rd, GpuRegister rs) { 1188 Or(rd, rs, ZERO); 1189 } 1190 1191 void Mips64Assembler::Clear(GpuRegister rd) { 1192 Move(rd, ZERO); 1193 } 1194 1195 void Mips64Assembler::Not(GpuRegister rd, GpuRegister rs) { 1196 Nor(rd, rs, ZERO); 1197 } 1198 1199 void Mips64Assembler::AndV(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1200 CHECK(HasMsa()); 1201 EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x1e); 1202 } 1203 1204 void Mips64Assembler::OrV(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1205 CHECK(HasMsa()); 1206 EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x1e); 1207 } 1208 1209 void Mips64Assembler::NorV(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1210 CHECK(HasMsa()); 1211 EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x1e); 1212 } 1213 1214 void Mips64Assembler::XorV(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1215 CHECK(HasMsa()); 1216 EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x1e); 1217 } 1218 1219 void Mips64Assembler::AddvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1220 CHECK(HasMsa()); 1221 EmitMsa3R(0x0, 0x0, wt, ws, wd, 0xe); 1222 } 1223 1224 void Mips64Assembler::AddvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1225 CHECK(HasMsa()); 1226 EmitMsa3R(0x0, 0x1, wt, ws, wd, 0xe); 1227 } 1228 1229 void Mips64Assembler::AddvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1230 CHECK(HasMsa()); 1231 EmitMsa3R(0x0, 0x2, wt, ws, wd, 0xe); 1232 } 1233 1234 void Mips64Assembler::AddvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1235 CHECK(HasMsa()); 1236 EmitMsa3R(0x0, 0x3, wt, ws, wd, 0xe); 1237 } 1238 1239 void Mips64Assembler::SubvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1240 CHECK(HasMsa()); 1241 EmitMsa3R(0x1, 0x0, wt, ws, wd, 0xe); 1242 } 1243 1244 void Mips64Assembler::SubvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1245 CHECK(HasMsa()); 1246 EmitMsa3R(0x1, 0x1, wt, ws, wd, 0xe); 1247 } 1248 1249 void Mips64Assembler::SubvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1250 CHECK(HasMsa()); 1251 EmitMsa3R(0x1, 0x2, wt, ws, wd, 0xe); 1252 } 1253 1254 void Mips64Assembler::SubvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1255 CHECK(HasMsa()); 1256 EmitMsa3R(0x1, 0x3, wt, ws, wd, 0xe); 1257 } 1258 1259 void Mips64Assembler::MulvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1260 CHECK(HasMsa()); 1261 EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x12); 1262 } 1263 1264 void Mips64Assembler::MulvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1265 CHECK(HasMsa()); 1266 EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x12); 1267 } 1268 1269 void Mips64Assembler::MulvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1270 CHECK(HasMsa()); 1271 EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x12); 1272 } 1273 1274 void Mips64Assembler::MulvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1275 CHECK(HasMsa()); 1276 EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x12); 1277 } 1278 1279 void Mips64Assembler::Div_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1280 CHECK(HasMsa()); 1281 EmitMsa3R(0x4, 0x0, wt, ws, wd, 0x12); 1282 } 1283 1284 void Mips64Assembler::Div_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1285 CHECK(HasMsa()); 1286 EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x12); 1287 } 1288 1289 void Mips64Assembler::Div_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1290 CHECK(HasMsa()); 1291 EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x12); 1292 } 1293 1294 void Mips64Assembler::Div_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1295 CHECK(HasMsa()); 1296 EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x12); 1297 } 1298 1299 void Mips64Assembler::Div_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1300 CHECK(HasMsa()); 1301 EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x12); 1302 } 1303 1304 void Mips64Assembler::Div_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1305 CHECK(HasMsa()); 1306 EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x12); 1307 } 1308 1309 void Mips64Assembler::Div_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1310 CHECK(HasMsa()); 1311 EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x12); 1312 } 1313 1314 void Mips64Assembler::Div_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1315 CHECK(HasMsa()); 1316 EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x12); 1317 } 1318 1319 void Mips64Assembler::Mod_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1320 CHECK(HasMsa()); 1321 EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x12); 1322 } 1323 1324 void Mips64Assembler::Mod_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1325 CHECK(HasMsa()); 1326 EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x12); 1327 } 1328 1329 void Mips64Assembler::Mod_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1330 CHECK(HasMsa()); 1331 EmitMsa3R(0x6, 0x2, wt, ws, wd, 0x12); 1332 } 1333 1334 void Mips64Assembler::Mod_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1335 CHECK(HasMsa()); 1336 EmitMsa3R(0x6, 0x3, wt, ws, wd, 0x12); 1337 } 1338 1339 void Mips64Assembler::Mod_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1340 CHECK(HasMsa()); 1341 EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x12); 1342 } 1343 1344 void Mips64Assembler::Mod_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1345 CHECK(HasMsa()); 1346 EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x12); 1347 } 1348 1349 void Mips64Assembler::Mod_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1350 CHECK(HasMsa()); 1351 EmitMsa3R(0x7, 0x2, wt, ws, wd, 0x12); 1352 } 1353 1354 void Mips64Assembler::Mod_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1355 CHECK(HasMsa()); 1356 EmitMsa3R(0x7, 0x3, wt, ws, wd, 0x12); 1357 } 1358 1359 void Mips64Assembler::Add_aB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1360 CHECK(HasMsa()); 1361 EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x10); 1362 } 1363 1364 void Mips64Assembler::Add_aH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1365 CHECK(HasMsa()); 1366 EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x10); 1367 } 1368 1369 void Mips64Assembler::Add_aW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1370 CHECK(HasMsa()); 1371 EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x10); 1372 } 1373 1374 void Mips64Assembler::Add_aD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1375 CHECK(HasMsa()); 1376 EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x10); 1377 } 1378 1379 void Mips64Assembler::Ave_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1380 CHECK(HasMsa()); 1381 EmitMsa3R(0x4, 0x0, wt, ws, wd, 0x10); 1382 } 1383 1384 void Mips64Assembler::Ave_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1385 CHECK(HasMsa()); 1386 EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x10); 1387 } 1388 1389 void Mips64Assembler::Ave_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1390 CHECK(HasMsa()); 1391 EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x10); 1392 } 1393 1394 void Mips64Assembler::Ave_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1395 CHECK(HasMsa()); 1396 EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x10); 1397 } 1398 1399 void Mips64Assembler::Ave_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1400 CHECK(HasMsa()); 1401 EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x10); 1402 } 1403 1404 void Mips64Assembler::Ave_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1405 CHECK(HasMsa()); 1406 EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x10); 1407 } 1408 1409 void Mips64Assembler::Ave_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1410 CHECK(HasMsa()); 1411 EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x10); 1412 } 1413 1414 void Mips64Assembler::Ave_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1415 CHECK(HasMsa()); 1416 EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x10); 1417 } 1418 1419 void Mips64Assembler::Aver_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1420 CHECK(HasMsa()); 1421 EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x10); 1422 } 1423 1424 void Mips64Assembler::Aver_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1425 CHECK(HasMsa()); 1426 EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x10); 1427 } 1428 1429 void Mips64Assembler::Aver_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1430 CHECK(HasMsa()); 1431 EmitMsa3R(0x6, 0x2, wt, ws, wd, 0x10); 1432 } 1433 1434 void Mips64Assembler::Aver_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1435 CHECK(HasMsa()); 1436 EmitMsa3R(0x6, 0x3, wt, ws, wd, 0x10); 1437 } 1438 1439 void Mips64Assembler::Aver_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1440 CHECK(HasMsa()); 1441 EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x10); 1442 } 1443 1444 void Mips64Assembler::Aver_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1445 CHECK(HasMsa()); 1446 EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x10); 1447 } 1448 1449 void Mips64Assembler::Aver_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1450 CHECK(HasMsa()); 1451 EmitMsa3R(0x7, 0x2, wt, ws, wd, 0x10); 1452 } 1453 1454 void Mips64Assembler::Aver_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1455 CHECK(HasMsa()); 1456 EmitMsa3R(0x7, 0x3, wt, ws, wd, 0x10); 1457 } 1458 1459 void Mips64Assembler::Max_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1460 CHECK(HasMsa()); 1461 EmitMsa3R(0x2, 0x0, wt, ws, wd, 0xe); 1462 } 1463 1464 void Mips64Assembler::Max_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1465 CHECK(HasMsa()); 1466 EmitMsa3R(0x2, 0x1, wt, ws, wd, 0xe); 1467 } 1468 1469 void Mips64Assembler::Max_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1470 CHECK(HasMsa()); 1471 EmitMsa3R(0x2, 0x2, wt, ws, wd, 0xe); 1472 } 1473 1474 void Mips64Assembler::Max_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1475 CHECK(HasMsa()); 1476 EmitMsa3R(0x2, 0x3, wt, ws, wd, 0xe); 1477 } 1478 1479 void Mips64Assembler::Max_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1480 CHECK(HasMsa()); 1481 EmitMsa3R(0x3, 0x0, wt, ws, wd, 0xe); 1482 } 1483 1484 void Mips64Assembler::Max_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1485 CHECK(HasMsa()); 1486 EmitMsa3R(0x3, 0x1, wt, ws, wd, 0xe); 1487 } 1488 1489 void Mips64Assembler::Max_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1490 CHECK(HasMsa()); 1491 EmitMsa3R(0x3, 0x2, wt, ws, wd, 0xe); 1492 } 1493 1494 void Mips64Assembler::Max_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1495 CHECK(HasMsa()); 1496 EmitMsa3R(0x3, 0x3, wt, ws, wd, 0xe); 1497 } 1498 1499 void Mips64Assembler::Min_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1500 CHECK(HasMsa()); 1501 EmitMsa3R(0x4, 0x0, wt, ws, wd, 0xe); 1502 } 1503 1504 void Mips64Assembler::Min_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1505 CHECK(HasMsa()); 1506 EmitMsa3R(0x4, 0x1, wt, ws, wd, 0xe); 1507 } 1508 1509 void Mips64Assembler::Min_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1510 CHECK(HasMsa()); 1511 EmitMsa3R(0x4, 0x2, wt, ws, wd, 0xe); 1512 } 1513 1514 void Mips64Assembler::Min_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1515 CHECK(HasMsa()); 1516 EmitMsa3R(0x4, 0x3, wt, ws, wd, 0xe); 1517 } 1518 1519 void Mips64Assembler::Min_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1520 CHECK(HasMsa()); 1521 EmitMsa3R(0x5, 0x0, wt, ws, wd, 0xe); 1522 } 1523 1524 void Mips64Assembler::Min_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1525 CHECK(HasMsa()); 1526 EmitMsa3R(0x5, 0x1, wt, ws, wd, 0xe); 1527 } 1528 1529 void Mips64Assembler::Min_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1530 CHECK(HasMsa()); 1531 EmitMsa3R(0x5, 0x2, wt, ws, wd, 0xe); 1532 } 1533 1534 void Mips64Assembler::Min_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1535 CHECK(HasMsa()); 1536 EmitMsa3R(0x5, 0x3, wt, ws, wd, 0xe); 1537 } 1538 1539 void Mips64Assembler::FaddW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1540 CHECK(HasMsa()); 1541 EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x1b); 1542 } 1543 1544 void Mips64Assembler::FaddD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1545 CHECK(HasMsa()); 1546 EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x1b); 1547 } 1548 1549 void Mips64Assembler::FsubW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1550 CHECK(HasMsa()); 1551 EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x1b); 1552 } 1553 1554 void Mips64Assembler::FsubD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1555 CHECK(HasMsa()); 1556 EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x1b); 1557 } 1558 1559 void Mips64Assembler::FmulW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1560 CHECK(HasMsa()); 1561 EmitMsa3R(0x1, 0x0, wt, ws, wd, 0x1b); 1562 } 1563 1564 void Mips64Assembler::FmulD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1565 CHECK(HasMsa()); 1566 EmitMsa3R(0x1, 0x1, wt, ws, wd, 0x1b); 1567 } 1568 1569 void Mips64Assembler::FdivW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1570 CHECK(HasMsa()); 1571 EmitMsa3R(0x1, 0x2, wt, ws, wd, 0x1b); 1572 } 1573 1574 void Mips64Assembler::FdivD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1575 CHECK(HasMsa()); 1576 EmitMsa3R(0x1, 0x3, wt, ws, wd, 0x1b); 1577 } 1578 1579 void Mips64Assembler::FmaxW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1580 CHECK(HasMsa()); 1581 EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x1b); 1582 } 1583 1584 void Mips64Assembler::FmaxD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1585 CHECK(HasMsa()); 1586 EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x1b); 1587 } 1588 1589 void Mips64Assembler::FminW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1590 CHECK(HasMsa()); 1591 EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x1b); 1592 } 1593 1594 void Mips64Assembler::FminD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1595 CHECK(HasMsa()); 1596 EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x1b); 1597 } 1598 1599 void Mips64Assembler::Ffint_sW(VectorRegister wd, VectorRegister ws) { 1600 CHECK(HasMsa()); 1601 EmitMsa2RF(0x19e, 0x0, ws, wd, 0x1e); 1602 } 1603 1604 void Mips64Assembler::Ffint_sD(VectorRegister wd, VectorRegister ws) { 1605 CHECK(HasMsa()); 1606 EmitMsa2RF(0x19e, 0x1, ws, wd, 0x1e); 1607 } 1608 1609 void Mips64Assembler::Ftint_sW(VectorRegister wd, VectorRegister ws) { 1610 CHECK(HasMsa()); 1611 EmitMsa2RF(0x19c, 0x0, ws, wd, 0x1e); 1612 } 1613 1614 void Mips64Assembler::Ftint_sD(VectorRegister wd, VectorRegister ws) { 1615 CHECK(HasMsa()); 1616 EmitMsa2RF(0x19c, 0x1, ws, wd, 0x1e); 1617 } 1618 1619 void Mips64Assembler::SllB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1620 CHECK(HasMsa()); 1621 EmitMsa3R(0x0, 0x0, wt, ws, wd, 0xd); 1622 } 1623 1624 void Mips64Assembler::SllH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1625 CHECK(HasMsa()); 1626 EmitMsa3R(0x0, 0x1, wt, ws, wd, 0xd); 1627 } 1628 1629 void Mips64Assembler::SllW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1630 CHECK(HasMsa()); 1631 EmitMsa3R(0x0, 0x2, wt, ws, wd, 0xd); 1632 } 1633 1634 void Mips64Assembler::SllD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1635 CHECK(HasMsa()); 1636 EmitMsa3R(0x0, 0x3, wt, ws, wd, 0xd); 1637 } 1638 1639 void Mips64Assembler::SraB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1640 CHECK(HasMsa()); 1641 EmitMsa3R(0x1, 0x0, wt, ws, wd, 0xd); 1642 } 1643 1644 void Mips64Assembler::SraH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1645 CHECK(HasMsa()); 1646 EmitMsa3R(0x1, 0x1, wt, ws, wd, 0xd); 1647 } 1648 1649 void Mips64Assembler::SraW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1650 CHECK(HasMsa()); 1651 EmitMsa3R(0x1, 0x2, wt, ws, wd, 0xd); 1652 } 1653 1654 void Mips64Assembler::SraD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1655 CHECK(HasMsa()); 1656 EmitMsa3R(0x1, 0x3, wt, ws, wd, 0xd); 1657 } 1658 1659 void Mips64Assembler::SrlB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1660 CHECK(HasMsa()); 1661 EmitMsa3R(0x2, 0x0, wt, ws, wd, 0xd); 1662 } 1663 1664 void Mips64Assembler::SrlH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1665 CHECK(HasMsa()); 1666 EmitMsa3R(0x2, 0x1, wt, ws, wd, 0xd); 1667 } 1668 1669 void Mips64Assembler::SrlW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1670 CHECK(HasMsa()); 1671 EmitMsa3R(0x2, 0x2, wt, ws, wd, 0xd); 1672 } 1673 1674 void Mips64Assembler::SrlD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1675 CHECK(HasMsa()); 1676 EmitMsa3R(0x2, 0x3, wt, ws, wd, 0xd); 1677 } 1678 1679 void Mips64Assembler::SlliB(VectorRegister wd, VectorRegister ws, int shamt3) { 1680 CHECK(HasMsa()); 1681 CHECK(IsUint<3>(shamt3)) << shamt3; 1682 EmitMsaBIT(0x0, shamt3 | kMsaDfMByteMask, ws, wd, 0x9); 1683 } 1684 1685 void Mips64Assembler::SlliH(VectorRegister wd, VectorRegister ws, int shamt4) { 1686 CHECK(HasMsa()); 1687 CHECK(IsUint<4>(shamt4)) << shamt4; 1688 EmitMsaBIT(0x0, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9); 1689 } 1690 1691 void Mips64Assembler::SlliW(VectorRegister wd, VectorRegister ws, int shamt5) { 1692 CHECK(HasMsa()); 1693 CHECK(IsUint<5>(shamt5)) << shamt5; 1694 EmitMsaBIT(0x0, shamt5 | kMsaDfMWordMask, ws, wd, 0x9); 1695 } 1696 1697 void Mips64Assembler::SlliD(VectorRegister wd, VectorRegister ws, int shamt6) { 1698 CHECK(HasMsa()); 1699 CHECK(IsUint<6>(shamt6)) << shamt6; 1700 EmitMsaBIT(0x0, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9); 1701 } 1702 1703 void Mips64Assembler::SraiB(VectorRegister wd, VectorRegister ws, int shamt3) { 1704 CHECK(HasMsa()); 1705 CHECK(IsUint<3>(shamt3)) << shamt3; 1706 EmitMsaBIT(0x1, shamt3 | kMsaDfMByteMask, ws, wd, 0x9); 1707 } 1708 1709 void Mips64Assembler::SraiH(VectorRegister wd, VectorRegister ws, int shamt4) { 1710 CHECK(HasMsa()); 1711 CHECK(IsUint<4>(shamt4)) << shamt4; 1712 EmitMsaBIT(0x1, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9); 1713 } 1714 1715 void Mips64Assembler::SraiW(VectorRegister wd, VectorRegister ws, int shamt5) { 1716 CHECK(HasMsa()); 1717 CHECK(IsUint<5>(shamt5)) << shamt5; 1718 EmitMsaBIT(0x1, shamt5 | kMsaDfMWordMask, ws, wd, 0x9); 1719 } 1720 1721 void Mips64Assembler::SraiD(VectorRegister wd, VectorRegister ws, int shamt6) { 1722 CHECK(HasMsa()); 1723 CHECK(IsUint<6>(shamt6)) << shamt6; 1724 EmitMsaBIT(0x1, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9); 1725 } 1726 1727 void Mips64Assembler::SrliB(VectorRegister wd, VectorRegister ws, int shamt3) { 1728 CHECK(HasMsa()); 1729 CHECK(IsUint<3>(shamt3)) << shamt3; 1730 EmitMsaBIT(0x2, shamt3 | kMsaDfMByteMask, ws, wd, 0x9); 1731 } 1732 1733 void Mips64Assembler::SrliH(VectorRegister wd, VectorRegister ws, int shamt4) { 1734 CHECK(HasMsa()); 1735 CHECK(IsUint<4>(shamt4)) << shamt4; 1736 EmitMsaBIT(0x2, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9); 1737 } 1738 1739 void Mips64Assembler::SrliW(VectorRegister wd, VectorRegister ws, int shamt5) { 1740 CHECK(HasMsa()); 1741 CHECK(IsUint<5>(shamt5)) << shamt5; 1742 EmitMsaBIT(0x2, shamt5 | kMsaDfMWordMask, ws, wd, 0x9); 1743 } 1744 1745 void Mips64Assembler::SrliD(VectorRegister wd, VectorRegister ws, int shamt6) { 1746 CHECK(HasMsa()); 1747 CHECK(IsUint<6>(shamt6)) << shamt6; 1748 EmitMsaBIT(0x2, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9); 1749 } 1750 1751 void Mips64Assembler::MoveV(VectorRegister wd, VectorRegister ws) { 1752 CHECK(HasMsa()); 1753 EmitMsaBIT(0x1, 0x3e, ws, wd, 0x19); 1754 } 1755 1756 void Mips64Assembler::SplatiB(VectorRegister wd, VectorRegister ws, int n4) { 1757 CHECK(HasMsa()); 1758 CHECK(IsUint<4>(n4)) << n4; 1759 EmitMsaELM(0x1, n4 | kMsaDfNByteMask, ws, wd, 0x19); 1760 } 1761 1762 void Mips64Assembler::SplatiH(VectorRegister wd, VectorRegister ws, int n3) { 1763 CHECK(HasMsa()); 1764 CHECK(IsUint<3>(n3)) << n3; 1765 EmitMsaELM(0x1, n3 | kMsaDfNHalfwordMask, ws, wd, 0x19); 1766 } 1767 1768 void Mips64Assembler::SplatiW(VectorRegister wd, VectorRegister ws, int n2) { 1769 CHECK(HasMsa()); 1770 CHECK(IsUint<2>(n2)) << n2; 1771 EmitMsaELM(0x1, n2 | kMsaDfNWordMask, ws, wd, 0x19); 1772 } 1773 1774 void Mips64Assembler::SplatiD(VectorRegister wd, VectorRegister ws, int n1) { 1775 CHECK(HasMsa()); 1776 CHECK(IsUint<1>(n1)) << n1; 1777 EmitMsaELM(0x1, n1 | kMsaDfNDoublewordMask, ws, wd, 0x19); 1778 } 1779 1780 void Mips64Assembler::FillB(VectorRegister wd, GpuRegister rs) { 1781 CHECK(HasMsa()); 1782 EmitMsa2R(0xc0, 0x0, static_cast<VectorRegister>(rs), wd, 0x1e); 1783 } 1784 1785 void Mips64Assembler::FillH(VectorRegister wd, GpuRegister rs) { 1786 CHECK(HasMsa()); 1787 EmitMsa2R(0xc0, 0x1, static_cast<VectorRegister>(rs), wd, 0x1e); 1788 } 1789 1790 void Mips64Assembler::FillW(VectorRegister wd, GpuRegister rs) { 1791 CHECK(HasMsa()); 1792 EmitMsa2R(0xc0, 0x2, static_cast<VectorRegister>(rs), wd, 0x1e); 1793 } 1794 1795 void Mips64Assembler::FillD(VectorRegister wd, GpuRegister rs) { 1796 CHECK(HasMsa()); 1797 EmitMsa2R(0xc0, 0x3, static_cast<VectorRegister>(rs), wd, 0x1e); 1798 } 1799 1800 void Mips64Assembler::LdiB(VectorRegister wd, int imm8) { 1801 CHECK(HasMsa()); 1802 CHECK(IsInt<8>(imm8)) << imm8; 1803 EmitMsaI10(0x6, 0x0, imm8 & kMsaS10Mask, wd, 0x7); 1804 } 1805 1806 void Mips64Assembler::LdiH(VectorRegister wd, int imm10) { 1807 CHECK(HasMsa()); 1808 CHECK(IsInt<10>(imm10)) << imm10; 1809 EmitMsaI10(0x6, 0x1, imm10 & kMsaS10Mask, wd, 0x7); 1810 } 1811 1812 void Mips64Assembler::LdiW(VectorRegister wd, int imm10) { 1813 CHECK(HasMsa()); 1814 CHECK(IsInt<10>(imm10)) << imm10; 1815 EmitMsaI10(0x6, 0x2, imm10 & kMsaS10Mask, wd, 0x7); 1816 } 1817 1818 void Mips64Assembler::LdiD(VectorRegister wd, int imm10) { 1819 CHECK(HasMsa()); 1820 CHECK(IsInt<10>(imm10)) << imm10; 1821 EmitMsaI10(0x6, 0x3, imm10 & kMsaS10Mask, wd, 0x7); 1822 } 1823 1824 void Mips64Assembler::LdB(VectorRegister wd, GpuRegister rs, int offset) { 1825 CHECK(HasMsa()); 1826 CHECK(IsInt<10>(offset)) << offset; 1827 EmitMsaMI10(offset & kMsaS10Mask, rs, wd, 0x8, 0x0); 1828 } 1829 1830 void Mips64Assembler::LdH(VectorRegister wd, GpuRegister rs, int offset) { 1831 CHECK(HasMsa()); 1832 CHECK(IsInt<11>(offset)) << offset; 1833 CHECK_ALIGNED(offset, kMips64HalfwordSize); 1834 EmitMsaMI10((offset >> TIMES_2) & kMsaS10Mask, rs, wd, 0x8, 0x1); 1835 } 1836 1837 void Mips64Assembler::LdW(VectorRegister wd, GpuRegister rs, int offset) { 1838 CHECK(HasMsa()); 1839 CHECK(IsInt<12>(offset)) << offset; 1840 CHECK_ALIGNED(offset, kMips64WordSize); 1841 EmitMsaMI10((offset >> TIMES_4) & kMsaS10Mask, rs, wd, 0x8, 0x2); 1842 } 1843 1844 void Mips64Assembler::LdD(VectorRegister wd, GpuRegister rs, int offset) { 1845 CHECK(HasMsa()); 1846 CHECK(IsInt<13>(offset)) << offset; 1847 CHECK_ALIGNED(offset, kMips64DoublewordSize); 1848 EmitMsaMI10((offset >> TIMES_8) & kMsaS10Mask, rs, wd, 0x8, 0x3); 1849 } 1850 1851 void Mips64Assembler::StB(VectorRegister wd, GpuRegister rs, int offset) { 1852 CHECK(HasMsa()); 1853 CHECK(IsInt<10>(offset)) << offset; 1854 EmitMsaMI10(offset & kMsaS10Mask, rs, wd, 0x9, 0x0); 1855 } 1856 1857 void Mips64Assembler::StH(VectorRegister wd, GpuRegister rs, int offset) { 1858 CHECK(HasMsa()); 1859 CHECK(IsInt<11>(offset)) << offset; 1860 CHECK_ALIGNED(offset, kMips64HalfwordSize); 1861 EmitMsaMI10((offset >> TIMES_2) & kMsaS10Mask, rs, wd, 0x9, 0x1); 1862 } 1863 1864 void Mips64Assembler::StW(VectorRegister wd, GpuRegister rs, int offset) { 1865 CHECK(HasMsa()); 1866 CHECK(IsInt<12>(offset)) << offset; 1867 CHECK_ALIGNED(offset, kMips64WordSize); 1868 EmitMsaMI10((offset >> TIMES_4) & kMsaS10Mask, rs, wd, 0x9, 0x2); 1869 } 1870 1871 void Mips64Assembler::StD(VectorRegister wd, GpuRegister rs, int offset) { 1872 CHECK(HasMsa()); 1873 CHECK(IsInt<13>(offset)) << offset; 1874 CHECK_ALIGNED(offset, kMips64DoublewordSize); 1875 EmitMsaMI10((offset >> TIMES_8) & kMsaS10Mask, rs, wd, 0x9, 0x3); 1876 } 1877 1878 void Mips64Assembler::IlvrB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1879 CHECK(HasMsa()); 1880 EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x14); 1881 } 1882 1883 void Mips64Assembler::IlvrH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1884 CHECK(HasMsa()); 1885 EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x14); 1886 } 1887 1888 void Mips64Assembler::IlvrW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1889 CHECK(HasMsa()); 1890 EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x14); 1891 } 1892 1893 void Mips64Assembler::IlvrD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1894 CHECK(HasMsa()); 1895 EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x14); 1896 } 1897 1898 void Mips64Assembler::ReplicateFPToVectorRegister(VectorRegister dst, 1899 FpuRegister src, 1900 bool is_double) { 1901 // Float or double in FPU register Fx can be considered as 0th element in vector register Wx. 1902 if (is_double) { 1903 SplatiD(dst, static_cast<VectorRegister>(src), 0); 1904 } else { 1905 SplatiW(dst, static_cast<VectorRegister>(src), 0); 1906 } 1907 } 1908 1909 void Mips64Assembler::LoadConst32(GpuRegister rd, int32_t value) { 1910 TemplateLoadConst32(this, rd, value); 1911 } 1912 1913 // This function is only used for testing purposes. 1914 void Mips64Assembler::RecordLoadConst64Path(int value ATTRIBUTE_UNUSED) { 1915 } 1916 1917 void Mips64Assembler::LoadConst64(GpuRegister rd, int64_t value) { 1918 TemplateLoadConst64(this, rd, value); 1919 } 1920 1921 void Mips64Assembler::Addiu32(GpuRegister rt, GpuRegister rs, int32_t value) { 1922 if (IsInt<16>(value)) { 1923 Addiu(rt, rs, value); 1924 } else { 1925 int16_t high = High16Bits(value); 1926 int16_t low = Low16Bits(value); 1927 high += (low < 0) ? 1 : 0; // Account for sign extension in addiu. 1928 Aui(rt, rs, high); 1929 if (low != 0) { 1930 Addiu(rt, rt, low); 1931 } 1932 } 1933 } 1934 1935 // TODO: don't use rtmp, use daui, dahi, dati. 1936 void Mips64Assembler::Daddiu64(GpuRegister rt, GpuRegister rs, int64_t value, GpuRegister rtmp) { 1937 CHECK_NE(rs, rtmp); 1938 if (IsInt<16>(value)) { 1939 Daddiu(rt, rs, value); 1940 } else { 1941 LoadConst64(rtmp, value); 1942 Daddu(rt, rs, rtmp); 1943 } 1944 } 1945 1946 void Mips64Assembler::Branch::InitShortOrLong(Mips64Assembler::Branch::OffsetBits offset_size, 1947 Mips64Assembler::Branch::Type short_type, 1948 Mips64Assembler::Branch::Type long_type) { 1949 type_ = (offset_size <= branch_info_[short_type].offset_size) ? short_type : long_type; 1950 } 1951 1952 void Mips64Assembler::Branch::InitializeType(Type initial_type) { 1953 OffsetBits offset_size = GetOffsetSizeNeeded(location_, target_); 1954 switch (initial_type) { 1955 case kLabel: 1956 case kLiteral: 1957 case kLiteralUnsigned: 1958 case kLiteralLong: 1959 CHECK(!IsResolved()); 1960 type_ = initial_type; 1961 break; 1962 case kCall: 1963 InitShortOrLong(offset_size, kCall, kLongCall); 1964 break; 1965 case kCondBranch: 1966 switch (condition_) { 1967 case kUncond: 1968 InitShortOrLong(offset_size, kUncondBranch, kLongUncondBranch); 1969 break; 1970 case kCondEQZ: 1971 case kCondNEZ: 1972 // Special case for beqzc/bnezc with longer offset than in other b<cond>c instructions. 1973 type_ = (offset_size <= kOffset23) ? kCondBranch : kLongCondBranch; 1974 break; 1975 default: 1976 InitShortOrLong(offset_size, kCondBranch, kLongCondBranch); 1977 break; 1978 } 1979 break; 1980 default: 1981 LOG(FATAL) << "Unexpected branch type " << initial_type; 1982 UNREACHABLE(); 1983 } 1984 old_type_ = type_; 1985 } 1986 1987 bool Mips64Assembler::Branch::IsNop(BranchCondition condition, GpuRegister lhs, GpuRegister rhs) { 1988 switch (condition) { 1989 case kCondLT: 1990 case kCondGT: 1991 case kCondNE: 1992 case kCondLTU: 1993 return lhs == rhs; 1994 default: 1995 return false; 1996 } 1997 } 1998 1999 bool Mips64Assembler::Branch::IsUncond(BranchCondition condition, 2000 GpuRegister lhs, 2001 GpuRegister rhs) { 2002 switch (condition) { 2003 case kUncond: 2004 return true; 2005 case kCondGE: 2006 case kCondLE: 2007 case kCondEQ: 2008 case kCondGEU: 2009 return lhs == rhs; 2010 default: 2011 return false; 2012 } 2013 } 2014 2015 Mips64Assembler::Branch::Branch(uint32_t location, uint32_t target, bool is_call) 2016 : old_location_(location), 2017 location_(location), 2018 target_(target), 2019 lhs_reg_(ZERO), 2020 rhs_reg_(ZERO), 2021 condition_(kUncond) { 2022 InitializeType(is_call ? kCall : kCondBranch); 2023 } 2024 2025 Mips64Assembler::Branch::Branch(uint32_t location, 2026 uint32_t target, 2027 Mips64Assembler::BranchCondition condition, 2028 GpuRegister lhs_reg, 2029 GpuRegister rhs_reg) 2030 : old_location_(location), 2031 location_(location), 2032 target_(target), 2033 lhs_reg_(lhs_reg), 2034 rhs_reg_(rhs_reg), 2035 condition_(condition) { 2036 CHECK_NE(condition, kUncond); 2037 switch (condition) { 2038 case kCondEQ: 2039 case kCondNE: 2040 case kCondLT: 2041 case kCondGE: 2042 case kCondLE: 2043 case kCondGT: 2044 case kCondLTU: 2045 case kCondGEU: 2046 CHECK_NE(lhs_reg, ZERO); 2047 CHECK_NE(rhs_reg, ZERO); 2048 break; 2049 case kCondLTZ: 2050 case kCondGEZ: 2051 case kCondLEZ: 2052 case kCondGTZ: 2053 case kCondEQZ: 2054 case kCondNEZ: 2055 CHECK_NE(lhs_reg, ZERO); 2056 CHECK_EQ(rhs_reg, ZERO); 2057 break; 2058 case kCondF: 2059 case kCondT: 2060 CHECK_EQ(rhs_reg, ZERO); 2061 break; 2062 case kUncond: 2063 UNREACHABLE(); 2064 } 2065 CHECK(!IsNop(condition, lhs_reg, rhs_reg)); 2066 if (IsUncond(condition, lhs_reg, rhs_reg)) { 2067 // Branch condition is always true, make the branch unconditional. 2068 condition_ = kUncond; 2069 } 2070 InitializeType(kCondBranch); 2071 } 2072 2073 Mips64Assembler::Branch::Branch(uint32_t location, GpuRegister dest_reg, Type label_or_literal_type) 2074 : old_location_(location), 2075 location_(location), 2076 target_(kUnresolved), 2077 lhs_reg_(dest_reg), 2078 rhs_reg_(ZERO), 2079 condition_(kUncond) { 2080 CHECK_NE(dest_reg, ZERO); 2081 InitializeType(label_or_literal_type); 2082 } 2083 2084 Mips64Assembler::BranchCondition Mips64Assembler::Branch::OppositeCondition( 2085 Mips64Assembler::BranchCondition cond) { 2086 switch (cond) { 2087 case kCondLT: 2088 return kCondGE; 2089 case kCondGE: 2090 return kCondLT; 2091 case kCondLE: 2092 return kCondGT; 2093 case kCondGT: 2094 return kCondLE; 2095 case kCondLTZ: 2096 return kCondGEZ; 2097 case kCondGEZ: 2098 return kCondLTZ; 2099 case kCondLEZ: 2100 return kCondGTZ; 2101 case kCondGTZ: 2102 return kCondLEZ; 2103 case kCondEQ: 2104 return kCondNE; 2105 case kCondNE: 2106 return kCondEQ; 2107 case kCondEQZ: 2108 return kCondNEZ; 2109 case kCondNEZ: 2110 return kCondEQZ; 2111 case kCondLTU: 2112 return kCondGEU; 2113 case kCondGEU: 2114 return kCondLTU; 2115 case kCondF: 2116 return kCondT; 2117 case kCondT: 2118 return kCondF; 2119 case kUncond: 2120 LOG(FATAL) << "Unexpected branch condition " << cond; 2121 } 2122 UNREACHABLE(); 2123 } 2124 2125 Mips64Assembler::Branch::Type Mips64Assembler::Branch::GetType() const { 2126 return type_; 2127 } 2128 2129 Mips64Assembler::BranchCondition Mips64Assembler::Branch::GetCondition() const { 2130 return condition_; 2131 } 2132 2133 GpuRegister Mips64Assembler::Branch::GetLeftRegister() const { 2134 return lhs_reg_; 2135 } 2136 2137 GpuRegister Mips64Assembler::Branch::GetRightRegister() const { 2138 return rhs_reg_; 2139 } 2140 2141 uint32_t Mips64Assembler::Branch::GetTarget() const { 2142 return target_; 2143 } 2144 2145 uint32_t Mips64Assembler::Branch::GetLocation() const { 2146 return location_; 2147 } 2148 2149 uint32_t Mips64Assembler::Branch::GetOldLocation() const { 2150 return old_location_; 2151 } 2152 2153 uint32_t Mips64Assembler::Branch::GetLength() const { 2154 return branch_info_[type_].length; 2155 } 2156 2157 uint32_t Mips64Assembler::Branch::GetOldLength() const { 2158 return branch_info_[old_type_].length; 2159 } 2160 2161 uint32_t Mips64Assembler::Branch::GetSize() const { 2162 return GetLength() * sizeof(uint32_t); 2163 } 2164 2165 uint32_t Mips64Assembler::Branch::GetOldSize() const { 2166 return GetOldLength() * sizeof(uint32_t); 2167 } 2168 2169 uint32_t Mips64Assembler::Branch::GetEndLocation() const { 2170 return GetLocation() + GetSize(); 2171 } 2172 2173 uint32_t Mips64Assembler::Branch::GetOldEndLocation() const { 2174 return GetOldLocation() + GetOldSize(); 2175 } 2176 2177 bool Mips64Assembler::Branch::IsLong() const { 2178 switch (type_) { 2179 // Short branches. 2180 case kUncondBranch: 2181 case kCondBranch: 2182 case kCall: 2183 // Near label. 2184 case kLabel: 2185 // Near literals. 2186 case kLiteral: 2187 case kLiteralUnsigned: 2188 case kLiteralLong: 2189 return false; 2190 // Long branches. 2191 case kLongUncondBranch: 2192 case kLongCondBranch: 2193 case kLongCall: 2194 // Far label. 2195 case kFarLabel: 2196 // Far literals. 2197 case kFarLiteral: 2198 case kFarLiteralUnsigned: 2199 case kFarLiteralLong: 2200 return true; 2201 } 2202 UNREACHABLE(); 2203 } 2204 2205 bool Mips64Assembler::Branch::IsResolved() const { 2206 return target_ != kUnresolved; 2207 } 2208 2209 Mips64Assembler::Branch::OffsetBits Mips64Assembler::Branch::GetOffsetSize() const { 2210 OffsetBits offset_size = 2211 (type_ == kCondBranch && (condition_ == kCondEQZ || condition_ == kCondNEZ)) 2212 ? kOffset23 2213 : branch_info_[type_].offset_size; 2214 return offset_size; 2215 } 2216 2217 Mips64Assembler::Branch::OffsetBits Mips64Assembler::Branch::GetOffsetSizeNeeded(uint32_t location, 2218 uint32_t target) { 2219 // For unresolved targets assume the shortest encoding 2220 // (later it will be made longer if needed). 2221 if (target == kUnresolved) 2222 return kOffset16; 2223 int64_t distance = static_cast<int64_t>(target) - location; 2224 // To simplify calculations in composite branches consisting of multiple instructions 2225 // bump up the distance by a value larger than the max byte size of a composite branch. 2226 distance += (distance >= 0) ? kMaxBranchSize : -kMaxBranchSize; 2227 if (IsInt<kOffset16>(distance)) 2228 return kOffset16; 2229 else if (IsInt<kOffset18>(distance)) 2230 return kOffset18; 2231 else if (IsInt<kOffset21>(distance)) 2232 return kOffset21; 2233 else if (IsInt<kOffset23>(distance)) 2234 return kOffset23; 2235 else if (IsInt<kOffset28>(distance)) 2236 return kOffset28; 2237 return kOffset32; 2238 } 2239 2240 void Mips64Assembler::Branch::Resolve(uint32_t target) { 2241 target_ = target; 2242 } 2243 2244 void Mips64Assembler::Branch::Relocate(uint32_t expand_location, uint32_t delta) { 2245 if (location_ > expand_location) { 2246 location_ += delta; 2247 } 2248 if (!IsResolved()) { 2249 return; // Don't know the target yet. 2250 } 2251 if (target_ > expand_location) { 2252 target_ += delta; 2253 } 2254 } 2255 2256 void Mips64Assembler::Branch::PromoteToLong() { 2257 switch (type_) { 2258 // Short branches. 2259 case kUncondBranch: 2260 type_ = kLongUncondBranch; 2261 break; 2262 case kCondBranch: 2263 type_ = kLongCondBranch; 2264 break; 2265 case kCall: 2266 type_ = kLongCall; 2267 break; 2268 // Near label. 2269 case kLabel: 2270 type_ = kFarLabel; 2271 break; 2272 // Near literals. 2273 case kLiteral: 2274 type_ = kFarLiteral; 2275 break; 2276 case kLiteralUnsigned: 2277 type_ = kFarLiteralUnsigned; 2278 break; 2279 case kLiteralLong: 2280 type_ = kFarLiteralLong; 2281 break; 2282 default: 2283 // Note: 'type_' is already long. 2284 break; 2285 } 2286 CHECK(IsLong()); 2287 } 2288 2289 uint32_t Mips64Assembler::Branch::PromoteIfNeeded(uint32_t max_short_distance) { 2290 // If the branch is still unresolved or already long, nothing to do. 2291 if (IsLong() || !IsResolved()) { 2292 return 0; 2293 } 2294 // Promote the short branch to long if the offset size is too small 2295 // to hold the distance between location_ and target_. 2296 if (GetOffsetSizeNeeded(location_, target_) > GetOffsetSize()) { 2297 PromoteToLong(); 2298 uint32_t old_size = GetOldSize(); 2299 uint32_t new_size = GetSize(); 2300 CHECK_GT(new_size, old_size); 2301 return new_size - old_size; 2302 } 2303 // The following logic is for debugging/testing purposes. 2304 // Promote some short branches to long when it's not really required. 2305 if (UNLIKELY(max_short_distance != std::numeric_limits<uint32_t>::max())) { 2306 int64_t distance = static_cast<int64_t>(target_) - location_; 2307 distance = (distance >= 0) ? distance : -distance; 2308 if (distance >= max_short_distance) { 2309 PromoteToLong(); 2310 uint32_t old_size = GetOldSize(); 2311 uint32_t new_size = GetSize(); 2312 CHECK_GT(new_size, old_size); 2313 return new_size - old_size; 2314 } 2315 } 2316 return 0; 2317 } 2318 2319 uint32_t Mips64Assembler::Branch::GetOffsetLocation() const { 2320 return location_ + branch_info_[type_].instr_offset * sizeof(uint32_t); 2321 } 2322 2323 uint32_t Mips64Assembler::Branch::GetOffset() const { 2324 CHECK(IsResolved()); 2325 uint32_t ofs_mask = 0xFFFFFFFF >> (32 - GetOffsetSize()); 2326 // Calculate the byte distance between instructions and also account for 2327 // different PC-relative origins. 2328 uint32_t offset_location = GetOffsetLocation(); 2329 if (type_ == kLiteralLong) { 2330 // Special case for the ldpc instruction, whose address (PC) is rounded down to 2331 // a multiple of 8 before adding the offset. 2332 // Note, branch promotion has already taken care of aligning `target_` to an 2333 // address that's a multiple of 8. 2334 offset_location = RoundDown(offset_location, sizeof(uint64_t)); 2335 } 2336 uint32_t offset = target_ - offset_location - branch_info_[type_].pc_org * sizeof(uint32_t); 2337 // Prepare the offset for encoding into the instruction(s). 2338 offset = (offset & ofs_mask) >> branch_info_[type_].offset_shift; 2339 return offset; 2340 } 2341 2342 Mips64Assembler::Branch* Mips64Assembler::GetBranch(uint32_t branch_id) { 2343 CHECK_LT(branch_id, branches_.size()); 2344 return &branches_[branch_id]; 2345 } 2346 2347 const Mips64Assembler::Branch* Mips64Assembler::GetBranch(uint32_t branch_id) const { 2348 CHECK_LT(branch_id, branches_.size()); 2349 return &branches_[branch_id]; 2350 } 2351 2352 void Mips64Assembler::Bind(Mips64Label* label) { 2353 CHECK(!label->IsBound()); 2354 uint32_t bound_pc = buffer_.Size(); 2355 2356 // Walk the list of branches referring to and preceding this label. 2357 // Store the previously unknown target addresses in them. 2358 while (label->IsLinked()) { 2359 uint32_t branch_id = label->Position(); 2360 Branch* branch = GetBranch(branch_id); 2361 branch->Resolve(bound_pc); 2362 2363 uint32_t branch_location = branch->GetLocation(); 2364 // Extract the location of the previous branch in the list (walking the list backwards; 2365 // the previous branch ID was stored in the space reserved for this branch). 2366 uint32_t prev = buffer_.Load<uint32_t>(branch_location); 2367 2368 // On to the previous branch in the list... 2369 label->position_ = prev; 2370 } 2371 2372 // Now make the label object contain its own location (relative to the end of the preceding 2373 // branch, if any; it will be used by the branches referring to and following this label). 2374 label->prev_branch_id_plus_one_ = branches_.size(); 2375 if (label->prev_branch_id_plus_one_) { 2376 uint32_t branch_id = label->prev_branch_id_plus_one_ - 1; 2377 const Branch* branch = GetBranch(branch_id); 2378 bound_pc -= branch->GetEndLocation(); 2379 } 2380 label->BindTo(bound_pc); 2381 } 2382 2383 uint32_t Mips64Assembler::GetLabelLocation(const Mips64Label* label) const { 2384 CHECK(label->IsBound()); 2385 uint32_t target = label->Position(); 2386 if (label->prev_branch_id_plus_one_) { 2387 // Get label location based on the branch preceding it. 2388 uint32_t branch_id = label->prev_branch_id_plus_one_ - 1; 2389 const Branch* branch = GetBranch(branch_id); 2390 target += branch->GetEndLocation(); 2391 } 2392 return target; 2393 } 2394 2395 uint32_t Mips64Assembler::GetAdjustedPosition(uint32_t old_position) { 2396 // We can reconstruct the adjustment by going through all the branches from the beginning 2397 // up to the old_position. Since we expect AdjustedPosition() to be called in a loop 2398 // with increasing old_position, we can use the data from last AdjustedPosition() to 2399 // continue where we left off and the whole loop should be O(m+n) where m is the number 2400 // of positions to adjust and n is the number of branches. 2401 if (old_position < last_old_position_) { 2402 last_position_adjustment_ = 0; 2403 last_old_position_ = 0; 2404 last_branch_id_ = 0; 2405 } 2406 while (last_branch_id_ != branches_.size()) { 2407 const Branch* branch = GetBranch(last_branch_id_); 2408 if (branch->GetLocation() >= old_position + last_position_adjustment_) { 2409 break; 2410 } 2411 last_position_adjustment_ += branch->GetSize() - branch->GetOldSize(); 2412 ++last_branch_id_; 2413 } 2414 last_old_position_ = old_position; 2415 return old_position + last_position_adjustment_; 2416 } 2417 2418 void Mips64Assembler::FinalizeLabeledBranch(Mips64Label* label) { 2419 uint32_t length = branches_.back().GetLength(); 2420 if (!label->IsBound()) { 2421 // Branch forward (to a following label), distance is unknown. 2422 // The first branch forward will contain 0, serving as the terminator of 2423 // the list of forward-reaching branches. 2424 Emit(label->position_); 2425 length--; 2426 // Now make the label object point to this branch 2427 // (this forms a linked list of branches preceding this label). 2428 uint32_t branch_id = branches_.size() - 1; 2429 label->LinkTo(branch_id); 2430 } 2431 // Reserve space for the branch. 2432 while (length--) { 2433 Nop(); 2434 } 2435 } 2436 2437 void Mips64Assembler::Buncond(Mips64Label* label) { 2438 uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved; 2439 branches_.emplace_back(buffer_.Size(), target, /* is_call */ false); 2440 FinalizeLabeledBranch(label); 2441 } 2442 2443 void Mips64Assembler::Bcond(Mips64Label* label, 2444 BranchCondition condition, 2445 GpuRegister lhs, 2446 GpuRegister rhs) { 2447 // If lhs = rhs, this can be a NOP. 2448 if (Branch::IsNop(condition, lhs, rhs)) { 2449 return; 2450 } 2451 uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved; 2452 branches_.emplace_back(buffer_.Size(), target, condition, lhs, rhs); 2453 FinalizeLabeledBranch(label); 2454 } 2455 2456 void Mips64Assembler::Call(Mips64Label* label) { 2457 uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved; 2458 branches_.emplace_back(buffer_.Size(), target, /* is_call */ true); 2459 FinalizeLabeledBranch(label); 2460 } 2461 2462 void Mips64Assembler::LoadLabelAddress(GpuRegister dest_reg, Mips64Label* label) { 2463 // Label address loads are treated as pseudo branches since they require very similar handling. 2464 DCHECK(!label->IsBound()); 2465 branches_.emplace_back(buffer_.Size(), dest_reg, Branch::kLabel); 2466 FinalizeLabeledBranch(label); 2467 } 2468 2469 Literal* Mips64Assembler::NewLiteral(size_t size, const uint8_t* data) { 2470 // We don't support byte and half-word literals. 2471 if (size == 4u) { 2472 literals_.emplace_back(size, data); 2473 return &literals_.back(); 2474 } else { 2475 DCHECK_EQ(size, 8u); 2476 long_literals_.emplace_back(size, data); 2477 return &long_literals_.back(); 2478 } 2479 } 2480 2481 void Mips64Assembler::LoadLiteral(GpuRegister dest_reg, 2482 LoadOperandType load_type, 2483 Literal* literal) { 2484 // Literal loads are treated as pseudo branches since they require very similar handling. 2485 Branch::Type literal_type; 2486 switch (load_type) { 2487 case kLoadWord: 2488 DCHECK_EQ(literal->GetSize(), 4u); 2489 literal_type = Branch::kLiteral; 2490 break; 2491 case kLoadUnsignedWord: 2492 DCHECK_EQ(literal->GetSize(), 4u); 2493 literal_type = Branch::kLiteralUnsigned; 2494 break; 2495 case kLoadDoubleword: 2496 DCHECK_EQ(literal->GetSize(), 8u); 2497 literal_type = Branch::kLiteralLong; 2498 break; 2499 default: 2500 LOG(FATAL) << "Unexpected literal load type " << load_type; 2501 UNREACHABLE(); 2502 } 2503 Mips64Label* label = literal->GetLabel(); 2504 DCHECK(!label->IsBound()); 2505 branches_.emplace_back(buffer_.Size(), dest_reg, literal_type); 2506 FinalizeLabeledBranch(label); 2507 } 2508 2509 JumpTable* Mips64Assembler::CreateJumpTable(std::vector<Mips64Label*>&& labels) { 2510 jump_tables_.emplace_back(std::move(labels)); 2511 JumpTable* table = &jump_tables_.back(); 2512 DCHECK(!table->GetLabel()->IsBound()); 2513 return table; 2514 } 2515 2516 void Mips64Assembler::ReserveJumpTableSpace() { 2517 if (!jump_tables_.empty()) { 2518 for (JumpTable& table : jump_tables_) { 2519 Mips64Label* label = table.GetLabel(); 2520 Bind(label); 2521 2522 // Bulk ensure capacity, as this may be large. 2523 size_t orig_size = buffer_.Size(); 2524 size_t required_capacity = orig_size + table.GetSize(); 2525 if (required_capacity > buffer_.Capacity()) { 2526 buffer_.ExtendCapacity(required_capacity); 2527 } 2528 #ifndef NDEBUG 2529 buffer_.has_ensured_capacity_ = true; 2530 #endif 2531 2532 // Fill the space with dummy data as the data is not final 2533 // until the branches have been promoted. And we shouldn't 2534 // be moving uninitialized data during branch promotion. 2535 for (size_t cnt = table.GetData().size(), i = 0; i < cnt; i++) { 2536 buffer_.Emit<uint32_t>(0x1abe1234u); 2537 } 2538 2539 #ifndef NDEBUG 2540 buffer_.has_ensured_capacity_ = false; 2541 #endif 2542 } 2543 } 2544 } 2545 2546 void Mips64Assembler::EmitJumpTables() { 2547 if (!jump_tables_.empty()) { 2548 CHECK(!overwriting_); 2549 // Switch from appending instructions at the end of the buffer to overwriting 2550 // existing instructions (here, jump tables) in the buffer. 2551 overwriting_ = true; 2552 2553 for (JumpTable& table : jump_tables_) { 2554 Mips64Label* table_label = table.GetLabel(); 2555 uint32_t start = GetLabelLocation(table_label); 2556 overwrite_location_ = start; 2557 2558 for (Mips64Label* target : table.GetData()) { 2559 CHECK_EQ(buffer_.Load<uint32_t>(overwrite_location_), 0x1abe1234u); 2560 // The table will contain target addresses relative to the table start. 2561 uint32_t offset = GetLabelLocation(target) - start; 2562 Emit(offset); 2563 } 2564 } 2565 2566 overwriting_ = false; 2567 } 2568 } 2569 2570 void Mips64Assembler::EmitLiterals() { 2571 if (!literals_.empty()) { 2572 for (Literal& literal : literals_) { 2573 Mips64Label* label = literal.GetLabel(); 2574 Bind(label); 2575 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 2576 DCHECK_EQ(literal.GetSize(), 4u); 2577 for (size_t i = 0, size = literal.GetSize(); i != size; ++i) { 2578 buffer_.Emit<uint8_t>(literal.GetData()[i]); 2579 } 2580 } 2581 } 2582 if (!long_literals_.empty()) { 2583 // Reserve 4 bytes for potential alignment. If after the branch promotion the 64-bit 2584 // literals don't end up 8-byte-aligned, they will be moved down 4 bytes. 2585 Emit(0); // NOP. 2586 for (Literal& literal : long_literals_) { 2587 Mips64Label* label = literal.GetLabel(); 2588 Bind(label); 2589 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 2590 DCHECK_EQ(literal.GetSize(), 8u); 2591 for (size_t i = 0, size = literal.GetSize(); i != size; ++i) { 2592 buffer_.Emit<uint8_t>(literal.GetData()[i]); 2593 } 2594 } 2595 } 2596 } 2597 2598 void Mips64Assembler::PromoteBranches() { 2599 // Promote short branches to long as necessary. 2600 bool changed; 2601 do { 2602 changed = false; 2603 for (auto& branch : branches_) { 2604 CHECK(branch.IsResolved()); 2605 uint32_t delta = branch.PromoteIfNeeded(); 2606 // If this branch has been promoted and needs to expand in size, 2607 // relocate all branches by the expansion size. 2608 if (delta) { 2609 changed = true; 2610 uint32_t expand_location = branch.GetLocation(); 2611 for (auto& branch2 : branches_) { 2612 branch2.Relocate(expand_location, delta); 2613 } 2614 } 2615 } 2616 } while (changed); 2617 2618 // Account for branch expansion by resizing the code buffer 2619 // and moving the code in it to its final location. 2620 size_t branch_count = branches_.size(); 2621 if (branch_count > 0) { 2622 // Resize. 2623 Branch& last_branch = branches_[branch_count - 1]; 2624 uint32_t size_delta = last_branch.GetEndLocation() - last_branch.GetOldEndLocation(); 2625 uint32_t old_size = buffer_.Size(); 2626 buffer_.Resize(old_size + size_delta); 2627 // Move the code residing between branch placeholders. 2628 uint32_t end = old_size; 2629 for (size_t i = branch_count; i > 0; ) { 2630 Branch& branch = branches_[--i]; 2631 uint32_t size = end - branch.GetOldEndLocation(); 2632 buffer_.Move(branch.GetEndLocation(), branch.GetOldEndLocation(), size); 2633 end = branch.GetOldLocation(); 2634 } 2635 } 2636 2637 // Align 64-bit literals by moving them down by 4 bytes if needed. 2638 // This will reduce the PC-relative distance, which should be safe for both near and far literals. 2639 if (!long_literals_.empty()) { 2640 uint32_t first_literal_location = GetLabelLocation(long_literals_.front().GetLabel()); 2641 size_t lit_size = long_literals_.size() * sizeof(uint64_t); 2642 size_t buf_size = buffer_.Size(); 2643 // 64-bit literals must be at the very end of the buffer. 2644 CHECK_EQ(first_literal_location + lit_size, buf_size); 2645 if (!IsAligned<sizeof(uint64_t)>(first_literal_location)) { 2646 buffer_.Move(first_literal_location - sizeof(uint32_t), first_literal_location, lit_size); 2647 // The 4 reserved bytes proved useless, reduce the buffer size. 2648 buffer_.Resize(buf_size - sizeof(uint32_t)); 2649 // Reduce target addresses in literal and address loads by 4 bytes in order for correct 2650 // offsets from PC to be generated. 2651 for (auto& branch : branches_) { 2652 uint32_t target = branch.GetTarget(); 2653 if (target >= first_literal_location) { 2654 branch.Resolve(target - sizeof(uint32_t)); 2655 } 2656 } 2657 // If after this we ever call GetLabelLocation() to get the location of a 64-bit literal, 2658 // we need to adjust the location of the literal's label as well. 2659 for (Literal& literal : long_literals_) { 2660 // Bound label's position is negative, hence incrementing it instead of decrementing. 2661 literal.GetLabel()->position_ += sizeof(uint32_t); 2662 } 2663 } 2664 } 2665 } 2666 2667 // Note: make sure branch_info_[] and EmitBranch() are kept synchronized. 2668 const Mips64Assembler::Branch::BranchInfo Mips64Assembler::Branch::branch_info_[] = { 2669 // Short branches. 2670 { 1, 0, 1, Mips64Assembler::Branch::kOffset28, 2 }, // kUncondBranch 2671 { 2, 0, 1, Mips64Assembler::Branch::kOffset18, 2 }, // kCondBranch 2672 // Exception: kOffset23 for beqzc/bnezc 2673 { 1, 0, 1, Mips64Assembler::Branch::kOffset28, 2 }, // kCall 2674 // Near label. 2675 { 1, 0, 0, Mips64Assembler::Branch::kOffset21, 2 }, // kLabel 2676 // Near literals. 2677 { 1, 0, 0, Mips64Assembler::Branch::kOffset21, 2 }, // kLiteral 2678 { 1, 0, 0, Mips64Assembler::Branch::kOffset21, 2 }, // kLiteralUnsigned 2679 { 1, 0, 0, Mips64Assembler::Branch::kOffset21, 3 }, // kLiteralLong 2680 // Long branches. 2681 { 2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kLongUncondBranch 2682 { 3, 1, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kLongCondBranch 2683 { 2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kLongCall 2684 // Far label. 2685 { 2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kFarLabel 2686 // Far literals. 2687 { 2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kFarLiteral 2688 { 2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kFarLiteralUnsigned 2689 { 2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kFarLiteralLong 2690 }; 2691 2692 // Note: make sure branch_info_[] and EmitBranch() are kept synchronized. 2693 void Mips64Assembler::EmitBranch(Mips64Assembler::Branch* branch) { 2694 CHECK(overwriting_); 2695 overwrite_location_ = branch->GetLocation(); 2696 uint32_t offset = branch->GetOffset(); 2697 BranchCondition condition = branch->GetCondition(); 2698 GpuRegister lhs = branch->GetLeftRegister(); 2699 GpuRegister rhs = branch->GetRightRegister(); 2700 switch (branch->GetType()) { 2701 // Short branches. 2702 case Branch::kUncondBranch: 2703 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 2704 Bc(offset); 2705 break; 2706 case Branch::kCondBranch: 2707 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 2708 EmitBcondc(condition, lhs, rhs, offset); 2709 Nop(); // TODO: improve by filling the forbidden/delay slot. 2710 break; 2711 case Branch::kCall: 2712 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 2713 Balc(offset); 2714 break; 2715 2716 // Near label. 2717 case Branch::kLabel: 2718 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 2719 Addiupc(lhs, offset); 2720 break; 2721 // Near literals. 2722 case Branch::kLiteral: 2723 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 2724 Lwpc(lhs, offset); 2725 break; 2726 case Branch::kLiteralUnsigned: 2727 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 2728 Lwupc(lhs, offset); 2729 break; 2730 case Branch::kLiteralLong: 2731 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 2732 Ldpc(lhs, offset); 2733 break; 2734 2735 // Long branches. 2736 case Branch::kLongUncondBranch: 2737 offset += (offset & 0x8000) << 1; // Account for sign extension in jic. 2738 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 2739 Auipc(AT, High16Bits(offset)); 2740 Jic(AT, Low16Bits(offset)); 2741 break; 2742 case Branch::kLongCondBranch: 2743 EmitBcondc(Branch::OppositeCondition(condition), lhs, rhs, 2); 2744 offset += (offset & 0x8000) << 1; // Account for sign extension in jic. 2745 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 2746 Auipc(AT, High16Bits(offset)); 2747 Jic(AT, Low16Bits(offset)); 2748 break; 2749 case Branch::kLongCall: 2750 offset += (offset & 0x8000) << 1; // Account for sign extension in jialc. 2751 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 2752 Auipc(AT, High16Bits(offset)); 2753 Jialc(AT, Low16Bits(offset)); 2754 break; 2755 2756 // Far label. 2757 case Branch::kFarLabel: 2758 offset += (offset & 0x8000) << 1; // Account for sign extension in daddiu. 2759 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 2760 Auipc(AT, High16Bits(offset)); 2761 Daddiu(lhs, AT, Low16Bits(offset)); 2762 break; 2763 // Far literals. 2764 case Branch::kFarLiteral: 2765 offset += (offset & 0x8000) << 1; // Account for sign extension in lw. 2766 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 2767 Auipc(AT, High16Bits(offset)); 2768 Lw(lhs, AT, Low16Bits(offset)); 2769 break; 2770 case Branch::kFarLiteralUnsigned: 2771 offset += (offset & 0x8000) << 1; // Account for sign extension in lwu. 2772 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 2773 Auipc(AT, High16Bits(offset)); 2774 Lwu(lhs, AT, Low16Bits(offset)); 2775 break; 2776 case Branch::kFarLiteralLong: 2777 offset += (offset & 0x8000) << 1; // Account for sign extension in ld. 2778 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 2779 Auipc(AT, High16Bits(offset)); 2780 Ld(lhs, AT, Low16Bits(offset)); 2781 break; 2782 } 2783 CHECK_EQ(overwrite_location_, branch->GetEndLocation()); 2784 CHECK_LT(branch->GetSize(), static_cast<uint32_t>(Branch::kMaxBranchSize)); 2785 } 2786 2787 void Mips64Assembler::Bc(Mips64Label* label) { 2788 Buncond(label); 2789 } 2790 2791 void Mips64Assembler::Balc(Mips64Label* label) { 2792 Call(label); 2793 } 2794 2795 void Mips64Assembler::Bltc(GpuRegister rs, GpuRegister rt, Mips64Label* label) { 2796 Bcond(label, kCondLT, rs, rt); 2797 } 2798 2799 void Mips64Assembler::Bltzc(GpuRegister rt, Mips64Label* label) { 2800 Bcond(label, kCondLTZ, rt); 2801 } 2802 2803 void Mips64Assembler::Bgtzc(GpuRegister rt, Mips64Label* label) { 2804 Bcond(label, kCondGTZ, rt); 2805 } 2806 2807 void Mips64Assembler::Bgec(GpuRegister rs, GpuRegister rt, Mips64Label* label) { 2808 Bcond(label, kCondGE, rs, rt); 2809 } 2810 2811 void Mips64Assembler::Bgezc(GpuRegister rt, Mips64Label* label) { 2812 Bcond(label, kCondGEZ, rt); 2813 } 2814 2815 void Mips64Assembler::Blezc(GpuRegister rt, Mips64Label* label) { 2816 Bcond(label, kCondLEZ, rt); 2817 } 2818 2819 void Mips64Assembler::Bltuc(GpuRegister rs, GpuRegister rt, Mips64Label* label) { 2820 Bcond(label, kCondLTU, rs, rt); 2821 } 2822 2823 void Mips64Assembler::Bgeuc(GpuRegister rs, GpuRegister rt, Mips64Label* label) { 2824 Bcond(label, kCondGEU, rs, rt); 2825 } 2826 2827 void Mips64Assembler::Beqc(GpuRegister rs, GpuRegister rt, Mips64Label* label) { 2828 Bcond(label, kCondEQ, rs, rt); 2829 } 2830 2831 void Mips64Assembler::Bnec(GpuRegister rs, GpuRegister rt, Mips64Label* label) { 2832 Bcond(label, kCondNE, rs, rt); 2833 } 2834 2835 void Mips64Assembler::Beqzc(GpuRegister rs, Mips64Label* label) { 2836 Bcond(label, kCondEQZ, rs); 2837 } 2838 2839 void Mips64Assembler::Bnezc(GpuRegister rs, Mips64Label* label) { 2840 Bcond(label, kCondNEZ, rs); 2841 } 2842 2843 void Mips64Assembler::Bc1eqz(FpuRegister ft, Mips64Label* label) { 2844 Bcond(label, kCondF, static_cast<GpuRegister>(ft), ZERO); 2845 } 2846 2847 void Mips64Assembler::Bc1nez(FpuRegister ft, Mips64Label* label) { 2848 Bcond(label, kCondT, static_cast<GpuRegister>(ft), ZERO); 2849 } 2850 2851 void Mips64Assembler::AdjustBaseAndOffset(GpuRegister& base, 2852 int32_t& offset, 2853 bool is_doubleword) { 2854 // This method is used to adjust the base register and offset pair 2855 // for a load/store when the offset doesn't fit into int16_t. 2856 // It is assumed that `base + offset` is sufficiently aligned for memory 2857 // operands that are machine word in size or smaller. For doubleword-sized 2858 // operands it's assumed that `base` is a multiple of 8, while `offset` 2859 // may be a multiple of 4 (e.g. 4-byte-aligned long and double arguments 2860 // and spilled variables on the stack accessed relative to the stack 2861 // pointer register). 2862 // We preserve the "alignment" of `offset` by adjusting it by a multiple of 8. 2863 CHECK_NE(base, AT); // Must not overwrite the register `base` while loading `offset`. 2864 2865 bool doubleword_aligned = IsAligned<kMips64DoublewordSize>(offset); 2866 bool two_accesses = is_doubleword && !doubleword_aligned; 2867 2868 // IsInt<16> must be passed a signed value, hence the static cast below. 2869 if (IsInt<16>(offset) && 2870 (!two_accesses || IsInt<16>(static_cast<int32_t>(offset + kMips64WordSize)))) { 2871 // Nothing to do: `offset` (and, if needed, `offset + 4`) fits into int16_t. 2872 return; 2873 } 2874 2875 // Remember the "(mis)alignment" of `offset`, it will be checked at the end. 2876 uint32_t misalignment = offset & (kMips64DoublewordSize - 1); 2877 2878 // First, see if `offset` can be represented as a sum of two 16-bit signed 2879 // offsets. This can save an instruction. 2880 // To simplify matters, only do this for a symmetric range of offsets from 2881 // about -64KB to about +64KB, allowing further addition of 4 when accessing 2882 // 64-bit variables with two 32-bit accesses. 2883 constexpr int32_t kMinOffsetForSimpleAdjustment = 0x7ff8; // Max int16_t that's a multiple of 8. 2884 constexpr int32_t kMaxOffsetForSimpleAdjustment = 2 * kMinOffsetForSimpleAdjustment; 2885 2886 if (0 <= offset && offset <= kMaxOffsetForSimpleAdjustment) { 2887 Daddiu(AT, base, kMinOffsetForSimpleAdjustment); 2888 offset -= kMinOffsetForSimpleAdjustment; 2889 } else if (-kMaxOffsetForSimpleAdjustment <= offset && offset < 0) { 2890 Daddiu(AT, base, -kMinOffsetForSimpleAdjustment); 2891 offset += kMinOffsetForSimpleAdjustment; 2892 } else { 2893 // In more complex cases take advantage of the daui instruction, e.g.: 2894 // daui AT, base, offset_high 2895 // [dahi AT, 1] // When `offset` is close to +2GB. 2896 // lw reg_lo, offset_low(AT) 2897 // [lw reg_hi, (offset_low+4)(AT)] // If misaligned 64-bit load. 2898 // or when offset_low+4 overflows int16_t: 2899 // daui AT, base, offset_high 2900 // daddiu AT, AT, 8 2901 // lw reg_lo, (offset_low-8)(AT) 2902 // lw reg_hi, (offset_low-4)(AT) 2903 int16_t offset_low = Low16Bits(offset); 2904 int32_t offset_low32 = offset_low; 2905 int16_t offset_high = High16Bits(offset); 2906 bool increment_hi16 = offset_low < 0; 2907 bool overflow_hi16 = false; 2908 2909 if (increment_hi16) { 2910 offset_high++; 2911 overflow_hi16 = (offset_high == -32768); 2912 } 2913 Daui(AT, base, offset_high); 2914 2915 if (overflow_hi16) { 2916 Dahi(AT, 1); 2917 } 2918 2919 if (two_accesses && !IsInt<16>(static_cast<int32_t>(offset_low32 + kMips64WordSize))) { 2920 // Avoid overflow in the 16-bit offset of the load/store instruction when adding 4. 2921 Daddiu(AT, AT, kMips64DoublewordSize); 2922 offset_low32 -= kMips64DoublewordSize; 2923 } 2924 2925 offset = offset_low32; 2926 } 2927 base = AT; 2928 2929 CHECK(IsInt<16>(offset)); 2930 if (two_accesses) { 2931 CHECK(IsInt<16>(static_cast<int32_t>(offset + kMips64WordSize))); 2932 } 2933 CHECK_EQ(misalignment, offset & (kMips64DoublewordSize - 1)); 2934 } 2935 2936 void Mips64Assembler::AdjustBaseOffsetAndElementSizeShift(GpuRegister& base, 2937 int32_t& offset, 2938 int& element_size_shift) { 2939 // This method is used to adjust the base register, offset and element_size_shift 2940 // for a vector load/store when the offset doesn't fit into allowed number of bits. 2941 // MSA ld.df and st.df instructions take signed offsets as arguments, but maximum 2942 // offset is dependant on the size of the data format df (10-bit offsets for ld.b, 2943 // 11-bit for ld.h, 12-bit for ld.w and 13-bit for ld.d). 2944 // If element_size_shift is non-negative at entry, it won't be changed, but offset 2945 // will be checked for appropriate alignment. If negative at entry, it will be 2946 // adjusted based on offset for maximum fit. 2947 // It's assumed that `base` is a multiple of 8. 2948 2949 CHECK_NE(base, AT); // Must not overwrite the register `base` while loading `offset`. 2950 2951 if (element_size_shift >= 0) { 2952 CHECK_LE(element_size_shift, TIMES_8); 2953 CHECK_GE(JAVASTYLE_CTZ(offset), element_size_shift); 2954 } else if (IsAligned<kMips64DoublewordSize>(offset)) { 2955 element_size_shift = TIMES_8; 2956 } else if (IsAligned<kMips64WordSize>(offset)) { 2957 element_size_shift = TIMES_4; 2958 } else if (IsAligned<kMips64HalfwordSize>(offset)) { 2959 element_size_shift = TIMES_2; 2960 } else { 2961 element_size_shift = TIMES_1; 2962 } 2963 2964 const int low_len = 10 + element_size_shift; // How many low bits of `offset` ld.df/st.df 2965 // will take. 2966 int16_t low = offset & ((1 << low_len) - 1); // Isolate these bits. 2967 low -= (low & (1 << (low_len - 1))) << 1; // Sign-extend these bits. 2968 if (low == offset) { 2969 return; // `offset` fits into ld.df/st.df. 2970 } 2971 2972 // First, see if `offset` can be represented as a sum of two signed offsets. 2973 // This can save an instruction. 2974 2975 // Max int16_t that's a multiple of element size. 2976 const int32_t kMaxDeltaForSimpleAdjustment = 0x8000 - (1 << element_size_shift); 2977 // Max ld.df/st.df offset that's a multiple of element size. 2978 const int32_t kMaxLoadStoreOffset = 0x1ff << element_size_shift; 2979 const int32_t kMaxOffsetForSimpleAdjustment = kMaxDeltaForSimpleAdjustment + kMaxLoadStoreOffset; 2980 2981 if (IsInt<16>(offset)) { 2982 Daddiu(AT, base, offset); 2983 offset = 0; 2984 } else if (0 <= offset && offset <= kMaxOffsetForSimpleAdjustment) { 2985 Daddiu(AT, base, kMaxDeltaForSimpleAdjustment); 2986 offset -= kMaxDeltaForSimpleAdjustment; 2987 } else if (-kMaxOffsetForSimpleAdjustment <= offset && offset < 0) { 2988 Daddiu(AT, base, -kMaxDeltaForSimpleAdjustment); 2989 offset += kMaxDeltaForSimpleAdjustment; 2990 } else { 2991 // Let's treat `offset` as 64-bit to simplify handling of sign 2992 // extensions in the instructions that supply its smaller signed parts. 2993 // 2994 // 16-bit or smaller parts of `offset`: 2995 // |63 top 48|47 hi 32|31 upper 16|15 mid 13-10|12-9 low 0| 2996 // 2997 // Instructions that supply each part as a signed integer addend: 2998 // |dati |dahi |daui |daddiu |ld.df/st.df | 2999 // 3000 // `top` is always 0, so dati isn't used. 3001 // `hi` is 1 when `offset` is close to +2GB and 0 otherwise. 3002 uint64_t tmp = static_cast<uint64_t>(offset) - low; // Exclude `low` from the rest of `offset` 3003 // (accounts for sign of `low`). 3004 tmp += (tmp & (UINT64_C(1) << 15)) << 1; // Account for sign extension in daddiu. 3005 tmp += (tmp & (UINT64_C(1) << 31)) << 1; // Account for sign extension in daui. 3006 int16_t mid = Low16Bits(tmp); 3007 int16_t upper = High16Bits(tmp); 3008 int16_t hi = Low16Bits(High32Bits(tmp)); 3009 Daui(AT, base, upper); 3010 if (hi != 0) { 3011 CHECK_EQ(hi, 1); 3012 Dahi(AT, hi); 3013 } 3014 if (mid != 0) { 3015 Daddiu(AT, AT, mid); 3016 } 3017 offset = low; 3018 } 3019 base = AT; 3020 CHECK_GE(JAVASTYLE_CTZ(offset), element_size_shift); 3021 CHECK(IsInt<10>(offset >> element_size_shift)); 3022 } 3023 3024 void Mips64Assembler::LoadFromOffset(LoadOperandType type, 3025 GpuRegister reg, 3026 GpuRegister base, 3027 int32_t offset) { 3028 LoadFromOffset<>(type, reg, base, offset); 3029 } 3030 3031 void Mips64Assembler::LoadFpuFromOffset(LoadOperandType type, 3032 FpuRegister reg, 3033 GpuRegister base, 3034 int32_t offset) { 3035 LoadFpuFromOffset<>(type, reg, base, offset); 3036 } 3037 3038 void Mips64Assembler::EmitLoad(ManagedRegister m_dst, GpuRegister src_register, int32_t src_offset, 3039 size_t size) { 3040 Mips64ManagedRegister dst = m_dst.AsMips64(); 3041 if (dst.IsNoRegister()) { 3042 CHECK_EQ(0u, size) << dst; 3043 } else if (dst.IsGpuRegister()) { 3044 if (size == 4) { 3045 LoadFromOffset(kLoadWord, dst.AsGpuRegister(), src_register, src_offset); 3046 } else if (size == 8) { 3047 CHECK_EQ(8u, size) << dst; 3048 LoadFromOffset(kLoadDoubleword, dst.AsGpuRegister(), src_register, src_offset); 3049 } else { 3050 UNIMPLEMENTED(FATAL) << "We only support Load() of size 4 and 8"; 3051 } 3052 } else if (dst.IsFpuRegister()) { 3053 if (size == 4) { 3054 CHECK_EQ(4u, size) << dst; 3055 LoadFpuFromOffset(kLoadWord, dst.AsFpuRegister(), src_register, src_offset); 3056 } else if (size == 8) { 3057 CHECK_EQ(8u, size) << dst; 3058 LoadFpuFromOffset(kLoadDoubleword, dst.AsFpuRegister(), src_register, src_offset); 3059 } else { 3060 UNIMPLEMENTED(FATAL) << "We only support Load() of size 4 and 8"; 3061 } 3062 } 3063 } 3064 3065 void Mips64Assembler::StoreToOffset(StoreOperandType type, 3066 GpuRegister reg, 3067 GpuRegister base, 3068 int32_t offset) { 3069 StoreToOffset<>(type, reg, base, offset); 3070 } 3071 3072 void Mips64Assembler::StoreFpuToOffset(StoreOperandType type, 3073 FpuRegister reg, 3074 GpuRegister base, 3075 int32_t offset) { 3076 StoreFpuToOffset<>(type, reg, base, offset); 3077 } 3078 3079 static dwarf::Reg DWARFReg(GpuRegister reg) { 3080 return dwarf::Reg::Mips64Core(static_cast<int>(reg)); 3081 } 3082 3083 constexpr size_t kFramePointerSize = 8; 3084 3085 void Mips64Assembler::BuildFrame(size_t frame_size, 3086 ManagedRegister method_reg, 3087 ArrayRef<const ManagedRegister> callee_save_regs, 3088 const ManagedRegisterEntrySpills& entry_spills) { 3089 CHECK_ALIGNED(frame_size, kStackAlignment); 3090 DCHECK(!overwriting_); 3091 3092 // Increase frame to required size. 3093 IncreaseFrameSize(frame_size); 3094 3095 // Push callee saves and return address 3096 int stack_offset = frame_size - kFramePointerSize; 3097 StoreToOffset(kStoreDoubleword, RA, SP, stack_offset); 3098 cfi_.RelOffset(DWARFReg(RA), stack_offset); 3099 for (int i = callee_save_regs.size() - 1; i >= 0; --i) { 3100 stack_offset -= kFramePointerSize; 3101 GpuRegister reg = callee_save_regs[i].AsMips64().AsGpuRegister(); 3102 StoreToOffset(kStoreDoubleword, reg, SP, stack_offset); 3103 cfi_.RelOffset(DWARFReg(reg), stack_offset); 3104 } 3105 3106 // Write out Method*. 3107 StoreToOffset(kStoreDoubleword, method_reg.AsMips64().AsGpuRegister(), SP, 0); 3108 3109 // Write out entry spills. 3110 int32_t offset = frame_size + kFramePointerSize; 3111 for (size_t i = 0; i < entry_spills.size(); ++i) { 3112 Mips64ManagedRegister reg = entry_spills[i].AsMips64(); 3113 ManagedRegisterSpill spill = entry_spills.at(i); 3114 int32_t size = spill.getSize(); 3115 if (reg.IsNoRegister()) { 3116 // only increment stack offset. 3117 offset += size; 3118 } else if (reg.IsFpuRegister()) { 3119 StoreFpuToOffset((size == 4) ? kStoreWord : kStoreDoubleword, 3120 reg.AsFpuRegister(), SP, offset); 3121 offset += size; 3122 } else if (reg.IsGpuRegister()) { 3123 StoreToOffset((size == 4) ? kStoreWord : kStoreDoubleword, 3124 reg.AsGpuRegister(), SP, offset); 3125 offset += size; 3126 } 3127 } 3128 } 3129 3130 void Mips64Assembler::RemoveFrame(size_t frame_size, 3131 ArrayRef<const ManagedRegister> callee_save_regs) { 3132 CHECK_ALIGNED(frame_size, kStackAlignment); 3133 DCHECK(!overwriting_); 3134 cfi_.RememberState(); 3135 3136 // Pop callee saves and return address 3137 int stack_offset = frame_size - (callee_save_regs.size() * kFramePointerSize) - kFramePointerSize; 3138 for (size_t i = 0; i < callee_save_regs.size(); ++i) { 3139 GpuRegister reg = callee_save_regs[i].AsMips64().AsGpuRegister(); 3140 LoadFromOffset(kLoadDoubleword, reg, SP, stack_offset); 3141 cfi_.Restore(DWARFReg(reg)); 3142 stack_offset += kFramePointerSize; 3143 } 3144 LoadFromOffset(kLoadDoubleword, RA, SP, stack_offset); 3145 cfi_.Restore(DWARFReg(RA)); 3146 3147 // Decrease frame to required size. 3148 DecreaseFrameSize(frame_size); 3149 3150 // Then jump to the return address. 3151 Jr(RA); 3152 Nop(); 3153 3154 // The CFI should be restored for any code that follows the exit block. 3155 cfi_.RestoreState(); 3156 cfi_.DefCFAOffset(frame_size); 3157 } 3158 3159 void Mips64Assembler::IncreaseFrameSize(size_t adjust) { 3160 CHECK_ALIGNED(adjust, kFramePointerSize); 3161 DCHECK(!overwriting_); 3162 Daddiu64(SP, SP, static_cast<int32_t>(-adjust)); 3163 cfi_.AdjustCFAOffset(adjust); 3164 } 3165 3166 void Mips64Assembler::DecreaseFrameSize(size_t adjust) { 3167 CHECK_ALIGNED(adjust, kFramePointerSize); 3168 DCHECK(!overwriting_); 3169 Daddiu64(SP, SP, static_cast<int32_t>(adjust)); 3170 cfi_.AdjustCFAOffset(-adjust); 3171 } 3172 3173 void Mips64Assembler::Store(FrameOffset dest, ManagedRegister msrc, size_t size) { 3174 Mips64ManagedRegister src = msrc.AsMips64(); 3175 if (src.IsNoRegister()) { 3176 CHECK_EQ(0u, size); 3177 } else if (src.IsGpuRegister()) { 3178 CHECK(size == 4 || size == 8) << size; 3179 if (size == 8) { 3180 StoreToOffset(kStoreDoubleword, src.AsGpuRegister(), SP, dest.Int32Value()); 3181 } else if (size == 4) { 3182 StoreToOffset(kStoreWord, src.AsGpuRegister(), SP, dest.Int32Value()); 3183 } else { 3184 UNIMPLEMENTED(FATAL) << "We only support Store() of size 4 and 8"; 3185 } 3186 } else if (src.IsFpuRegister()) { 3187 CHECK(size == 4 || size == 8) << size; 3188 if (size == 8) { 3189 StoreFpuToOffset(kStoreDoubleword, src.AsFpuRegister(), SP, dest.Int32Value()); 3190 } else if (size == 4) { 3191 StoreFpuToOffset(kStoreWord, src.AsFpuRegister(), SP, dest.Int32Value()); 3192 } else { 3193 UNIMPLEMENTED(FATAL) << "We only support Store() of size 4 and 8"; 3194 } 3195 } 3196 } 3197 3198 void Mips64Assembler::StoreRef(FrameOffset dest, ManagedRegister msrc) { 3199 Mips64ManagedRegister src = msrc.AsMips64(); 3200 CHECK(src.IsGpuRegister()); 3201 StoreToOffset(kStoreWord, src.AsGpuRegister(), SP, dest.Int32Value()); 3202 } 3203 3204 void Mips64Assembler::StoreRawPtr(FrameOffset dest, ManagedRegister msrc) { 3205 Mips64ManagedRegister src = msrc.AsMips64(); 3206 CHECK(src.IsGpuRegister()); 3207 StoreToOffset(kStoreDoubleword, src.AsGpuRegister(), SP, dest.Int32Value()); 3208 } 3209 3210 void Mips64Assembler::StoreImmediateToFrame(FrameOffset dest, uint32_t imm, 3211 ManagedRegister mscratch) { 3212 Mips64ManagedRegister scratch = mscratch.AsMips64(); 3213 CHECK(scratch.IsGpuRegister()) << scratch; 3214 LoadConst32(scratch.AsGpuRegister(), imm); 3215 StoreToOffset(kStoreWord, scratch.AsGpuRegister(), SP, dest.Int32Value()); 3216 } 3217 3218 void Mips64Assembler::StoreStackOffsetToThread(ThreadOffset64 thr_offs, 3219 FrameOffset fr_offs, 3220 ManagedRegister mscratch) { 3221 Mips64ManagedRegister scratch = mscratch.AsMips64(); 3222 CHECK(scratch.IsGpuRegister()) << scratch; 3223 Daddiu64(scratch.AsGpuRegister(), SP, fr_offs.Int32Value()); 3224 StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), S1, thr_offs.Int32Value()); 3225 } 3226 3227 void Mips64Assembler::StoreStackPointerToThread(ThreadOffset64 thr_offs) { 3228 StoreToOffset(kStoreDoubleword, SP, S1, thr_offs.Int32Value()); 3229 } 3230 3231 void Mips64Assembler::StoreSpanning(FrameOffset dest, ManagedRegister msrc, 3232 FrameOffset in_off, ManagedRegister mscratch) { 3233 Mips64ManagedRegister src = msrc.AsMips64(); 3234 Mips64ManagedRegister scratch = mscratch.AsMips64(); 3235 StoreToOffset(kStoreDoubleword, src.AsGpuRegister(), SP, dest.Int32Value()); 3236 LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(), SP, in_off.Int32Value()); 3237 StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, dest.Int32Value() + 8); 3238 } 3239 3240 void Mips64Assembler::Load(ManagedRegister mdest, FrameOffset src, size_t size) { 3241 return EmitLoad(mdest, SP, src.Int32Value(), size); 3242 } 3243 3244 void Mips64Assembler::LoadFromThread(ManagedRegister mdest, ThreadOffset64 src, size_t size) { 3245 return EmitLoad(mdest, S1, src.Int32Value(), size); 3246 } 3247 3248 void Mips64Assembler::LoadRef(ManagedRegister mdest, FrameOffset src) { 3249 Mips64ManagedRegister dest = mdest.AsMips64(); 3250 CHECK(dest.IsGpuRegister()); 3251 LoadFromOffset(kLoadUnsignedWord, dest.AsGpuRegister(), SP, src.Int32Value()); 3252 } 3253 3254 void Mips64Assembler::LoadRef(ManagedRegister mdest, ManagedRegister base, MemberOffset offs, 3255 bool unpoison_reference) { 3256 Mips64ManagedRegister dest = mdest.AsMips64(); 3257 CHECK(dest.IsGpuRegister() && base.AsMips64().IsGpuRegister()); 3258 LoadFromOffset(kLoadUnsignedWord, dest.AsGpuRegister(), 3259 base.AsMips64().AsGpuRegister(), offs.Int32Value()); 3260 if (unpoison_reference) { 3261 MaybeUnpoisonHeapReference(dest.AsGpuRegister()); 3262 } 3263 } 3264 3265 void Mips64Assembler::LoadRawPtr(ManagedRegister mdest, ManagedRegister base, 3266 Offset offs) { 3267 Mips64ManagedRegister dest = mdest.AsMips64(); 3268 CHECK(dest.IsGpuRegister() && base.AsMips64().IsGpuRegister()); 3269 LoadFromOffset(kLoadDoubleword, dest.AsGpuRegister(), 3270 base.AsMips64().AsGpuRegister(), offs.Int32Value()); 3271 } 3272 3273 void Mips64Assembler::LoadRawPtrFromThread(ManagedRegister mdest, ThreadOffset64 offs) { 3274 Mips64ManagedRegister dest = mdest.AsMips64(); 3275 CHECK(dest.IsGpuRegister()); 3276 LoadFromOffset(kLoadDoubleword, dest.AsGpuRegister(), S1, offs.Int32Value()); 3277 } 3278 3279 void Mips64Assembler::SignExtend(ManagedRegister mreg ATTRIBUTE_UNUSED, 3280 size_t size ATTRIBUTE_UNUSED) { 3281 UNIMPLEMENTED(FATAL) << "No sign extension necessary for MIPS64"; 3282 } 3283 3284 void Mips64Assembler::ZeroExtend(ManagedRegister mreg ATTRIBUTE_UNUSED, 3285 size_t size ATTRIBUTE_UNUSED) { 3286 UNIMPLEMENTED(FATAL) << "No zero extension necessary for MIPS64"; 3287 } 3288 3289 void Mips64Assembler::Move(ManagedRegister mdest, ManagedRegister msrc, size_t size) { 3290 Mips64ManagedRegister dest = mdest.AsMips64(); 3291 Mips64ManagedRegister src = msrc.AsMips64(); 3292 if (!dest.Equals(src)) { 3293 if (dest.IsGpuRegister()) { 3294 CHECK(src.IsGpuRegister()) << src; 3295 Move(dest.AsGpuRegister(), src.AsGpuRegister()); 3296 } else if (dest.IsFpuRegister()) { 3297 CHECK(src.IsFpuRegister()) << src; 3298 if (size == 4) { 3299 MovS(dest.AsFpuRegister(), src.AsFpuRegister()); 3300 } else if (size == 8) { 3301 MovD(dest.AsFpuRegister(), src.AsFpuRegister()); 3302 } else { 3303 UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8"; 3304 } 3305 } 3306 } 3307 } 3308 3309 void Mips64Assembler::CopyRef(FrameOffset dest, FrameOffset src, 3310 ManagedRegister mscratch) { 3311 Mips64ManagedRegister scratch = mscratch.AsMips64(); 3312 CHECK(scratch.IsGpuRegister()) << scratch; 3313 LoadFromOffset(kLoadWord, scratch.AsGpuRegister(), SP, src.Int32Value()); 3314 StoreToOffset(kStoreWord, scratch.AsGpuRegister(), SP, dest.Int32Value()); 3315 } 3316 3317 void Mips64Assembler::CopyRawPtrFromThread(FrameOffset fr_offs, 3318 ThreadOffset64 thr_offs, 3319 ManagedRegister mscratch) { 3320 Mips64ManagedRegister scratch = mscratch.AsMips64(); 3321 CHECK(scratch.IsGpuRegister()) << scratch; 3322 LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(), S1, thr_offs.Int32Value()); 3323 StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, fr_offs.Int32Value()); 3324 } 3325 3326 void Mips64Assembler::CopyRawPtrToThread(ThreadOffset64 thr_offs, 3327 FrameOffset fr_offs, 3328 ManagedRegister mscratch) { 3329 Mips64ManagedRegister scratch = mscratch.AsMips64(); 3330 CHECK(scratch.IsGpuRegister()) << scratch; 3331 LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(), 3332 SP, fr_offs.Int32Value()); 3333 StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), 3334 S1, thr_offs.Int32Value()); 3335 } 3336 3337 void Mips64Assembler::Copy(FrameOffset dest, FrameOffset src, 3338 ManagedRegister mscratch, size_t size) { 3339 Mips64ManagedRegister scratch = mscratch.AsMips64(); 3340 CHECK(scratch.IsGpuRegister()) << scratch; 3341 CHECK(size == 4 || size == 8) << size; 3342 if (size == 4) { 3343 LoadFromOffset(kLoadWord, scratch.AsGpuRegister(), SP, src.Int32Value()); 3344 StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, dest.Int32Value()); 3345 } else if (size == 8) { 3346 LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(), SP, src.Int32Value()); 3347 StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, dest.Int32Value()); 3348 } else { 3349 UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8"; 3350 } 3351 } 3352 3353 void Mips64Assembler::Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset, 3354 ManagedRegister mscratch, size_t size) { 3355 GpuRegister scratch = mscratch.AsMips64().AsGpuRegister(); 3356 CHECK(size == 4 || size == 8) << size; 3357 if (size == 4) { 3358 LoadFromOffset(kLoadWord, scratch, src_base.AsMips64().AsGpuRegister(), 3359 src_offset.Int32Value()); 3360 StoreToOffset(kStoreDoubleword, scratch, SP, dest.Int32Value()); 3361 } else if (size == 8) { 3362 LoadFromOffset(kLoadDoubleword, scratch, src_base.AsMips64().AsGpuRegister(), 3363 src_offset.Int32Value()); 3364 StoreToOffset(kStoreDoubleword, scratch, SP, dest.Int32Value()); 3365 } else { 3366 UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8"; 3367 } 3368 } 3369 3370 void Mips64Assembler::Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src, 3371 ManagedRegister mscratch, size_t size) { 3372 GpuRegister scratch = mscratch.AsMips64().AsGpuRegister(); 3373 CHECK(size == 4 || size == 8) << size; 3374 if (size == 4) { 3375 LoadFromOffset(kLoadWord, scratch, SP, src.Int32Value()); 3376 StoreToOffset(kStoreDoubleword, scratch, dest_base.AsMips64().AsGpuRegister(), 3377 dest_offset.Int32Value()); 3378 } else if (size == 8) { 3379 LoadFromOffset(kLoadDoubleword, scratch, SP, src.Int32Value()); 3380 StoreToOffset(kStoreDoubleword, scratch, dest_base.AsMips64().AsGpuRegister(), 3381 dest_offset.Int32Value()); 3382 } else { 3383 UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8"; 3384 } 3385 } 3386 3387 void Mips64Assembler::Copy(FrameOffset dest ATTRIBUTE_UNUSED, 3388 FrameOffset src_base ATTRIBUTE_UNUSED, 3389 Offset src_offset ATTRIBUTE_UNUSED, 3390 ManagedRegister mscratch ATTRIBUTE_UNUSED, 3391 size_t size ATTRIBUTE_UNUSED) { 3392 UNIMPLEMENTED(FATAL) << "No MIPS64 implementation"; 3393 } 3394 3395 void Mips64Assembler::Copy(ManagedRegister dest, Offset dest_offset, 3396 ManagedRegister src, Offset src_offset, 3397 ManagedRegister mscratch, size_t size) { 3398 GpuRegister scratch = mscratch.AsMips64().AsGpuRegister(); 3399 CHECK(size == 4 || size == 8) << size; 3400 if (size == 4) { 3401 LoadFromOffset(kLoadWord, scratch, src.AsMips64().AsGpuRegister(), src_offset.Int32Value()); 3402 StoreToOffset(kStoreDoubleword, scratch, dest.AsMips64().AsGpuRegister(), dest_offset.Int32Value()); 3403 } else if (size == 8) { 3404 LoadFromOffset(kLoadDoubleword, scratch, src.AsMips64().AsGpuRegister(), 3405 src_offset.Int32Value()); 3406 StoreToOffset(kStoreDoubleword, scratch, dest.AsMips64().AsGpuRegister(), 3407 dest_offset.Int32Value()); 3408 } else { 3409 UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8"; 3410 } 3411 } 3412 3413 void Mips64Assembler::Copy(FrameOffset dest ATTRIBUTE_UNUSED, 3414 Offset dest_offset ATTRIBUTE_UNUSED, 3415 FrameOffset src ATTRIBUTE_UNUSED, 3416 Offset src_offset ATTRIBUTE_UNUSED, 3417 ManagedRegister mscratch ATTRIBUTE_UNUSED, 3418 size_t size ATTRIBUTE_UNUSED) { 3419 UNIMPLEMENTED(FATAL) << "No MIPS64 implementation"; 3420 } 3421 3422 void Mips64Assembler::MemoryBarrier(ManagedRegister mreg ATTRIBUTE_UNUSED) { 3423 // TODO: sync? 3424 UNIMPLEMENTED(FATAL) << "No MIPS64 implementation"; 3425 } 3426 3427 void Mips64Assembler::CreateHandleScopeEntry(ManagedRegister mout_reg, 3428 FrameOffset handle_scope_offset, 3429 ManagedRegister min_reg, 3430 bool null_allowed) { 3431 Mips64ManagedRegister out_reg = mout_reg.AsMips64(); 3432 Mips64ManagedRegister in_reg = min_reg.AsMips64(); 3433 CHECK(in_reg.IsNoRegister() || in_reg.IsGpuRegister()) << in_reg; 3434 CHECK(out_reg.IsGpuRegister()) << out_reg; 3435 if (null_allowed) { 3436 Mips64Label null_arg; 3437 // Null values get a handle scope entry value of 0. Otherwise, the handle scope entry is 3438 // the address in the handle scope holding the reference. 3439 // e.g. out_reg = (handle == 0) ? 0 : (SP+handle_offset) 3440 if (in_reg.IsNoRegister()) { 3441 LoadFromOffset(kLoadUnsignedWord, out_reg.AsGpuRegister(), 3442 SP, handle_scope_offset.Int32Value()); 3443 in_reg = out_reg; 3444 } 3445 if (!out_reg.Equals(in_reg)) { 3446 LoadConst32(out_reg.AsGpuRegister(), 0); 3447 } 3448 Beqzc(in_reg.AsGpuRegister(), &null_arg); 3449 Daddiu64(out_reg.AsGpuRegister(), SP, handle_scope_offset.Int32Value()); 3450 Bind(&null_arg); 3451 } else { 3452 Daddiu64(out_reg.AsGpuRegister(), SP, handle_scope_offset.Int32Value()); 3453 } 3454 } 3455 3456 void Mips64Assembler::CreateHandleScopeEntry(FrameOffset out_off, 3457 FrameOffset handle_scope_offset, 3458 ManagedRegister mscratch, 3459 bool null_allowed) { 3460 Mips64ManagedRegister scratch = mscratch.AsMips64(); 3461 CHECK(scratch.IsGpuRegister()) << scratch; 3462 if (null_allowed) { 3463 Mips64Label null_arg; 3464 LoadFromOffset(kLoadUnsignedWord, scratch.AsGpuRegister(), SP, 3465 handle_scope_offset.Int32Value()); 3466 // Null values get a handle scope entry value of 0. Otherwise, the handle scope entry is 3467 // the address in the handle scope holding the reference. 3468 // e.g. scratch = (scratch == 0) ? 0 : (SP+handle_scope_offset) 3469 Beqzc(scratch.AsGpuRegister(), &null_arg); 3470 Daddiu64(scratch.AsGpuRegister(), SP, handle_scope_offset.Int32Value()); 3471 Bind(&null_arg); 3472 } else { 3473 Daddiu64(scratch.AsGpuRegister(), SP, handle_scope_offset.Int32Value()); 3474 } 3475 StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, out_off.Int32Value()); 3476 } 3477 3478 // Given a handle scope entry, load the associated reference. 3479 void Mips64Assembler::LoadReferenceFromHandleScope(ManagedRegister mout_reg, 3480 ManagedRegister min_reg) { 3481 Mips64ManagedRegister out_reg = mout_reg.AsMips64(); 3482 Mips64ManagedRegister in_reg = min_reg.AsMips64(); 3483 CHECK(out_reg.IsGpuRegister()) << out_reg; 3484 CHECK(in_reg.IsGpuRegister()) << in_reg; 3485 Mips64Label null_arg; 3486 if (!out_reg.Equals(in_reg)) { 3487 LoadConst32(out_reg.AsGpuRegister(), 0); 3488 } 3489 Beqzc(in_reg.AsGpuRegister(), &null_arg); 3490 LoadFromOffset(kLoadDoubleword, out_reg.AsGpuRegister(), 3491 in_reg.AsGpuRegister(), 0); 3492 Bind(&null_arg); 3493 } 3494 3495 void Mips64Assembler::VerifyObject(ManagedRegister src ATTRIBUTE_UNUSED, 3496 bool could_be_null ATTRIBUTE_UNUSED) { 3497 // TODO: not validating references 3498 } 3499 3500 void Mips64Assembler::VerifyObject(FrameOffset src ATTRIBUTE_UNUSED, 3501 bool could_be_null ATTRIBUTE_UNUSED) { 3502 // TODO: not validating references 3503 } 3504 3505 void Mips64Assembler::Call(ManagedRegister mbase, Offset offset, ManagedRegister mscratch) { 3506 Mips64ManagedRegister base = mbase.AsMips64(); 3507 Mips64ManagedRegister scratch = mscratch.AsMips64(); 3508 CHECK(base.IsGpuRegister()) << base; 3509 CHECK(scratch.IsGpuRegister()) << scratch; 3510 LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(), 3511 base.AsGpuRegister(), offset.Int32Value()); 3512 Jalr(scratch.AsGpuRegister()); 3513 Nop(); 3514 // TODO: place reference map on call 3515 } 3516 3517 void Mips64Assembler::Call(FrameOffset base, Offset offset, ManagedRegister mscratch) { 3518 Mips64ManagedRegister scratch = mscratch.AsMips64(); 3519 CHECK(scratch.IsGpuRegister()) << scratch; 3520 // Call *(*(SP + base) + offset) 3521 LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(), 3522 SP, base.Int32Value()); 3523 LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(), 3524 scratch.AsGpuRegister(), offset.Int32Value()); 3525 Jalr(scratch.AsGpuRegister()); 3526 Nop(); 3527 // TODO: place reference map on call 3528 } 3529 3530 void Mips64Assembler::CallFromThread(ThreadOffset64 offset ATTRIBUTE_UNUSED, 3531 ManagedRegister mscratch ATTRIBUTE_UNUSED) { 3532 UNIMPLEMENTED(FATAL) << "No MIPS64 implementation"; 3533 } 3534 3535 void Mips64Assembler::GetCurrentThread(ManagedRegister tr) { 3536 Move(tr.AsMips64().AsGpuRegister(), S1); 3537 } 3538 3539 void Mips64Assembler::GetCurrentThread(FrameOffset offset, 3540 ManagedRegister mscratch ATTRIBUTE_UNUSED) { 3541 StoreToOffset(kStoreDoubleword, S1, SP, offset.Int32Value()); 3542 } 3543 3544 void Mips64Assembler::ExceptionPoll(ManagedRegister mscratch, size_t stack_adjust) { 3545 Mips64ManagedRegister scratch = mscratch.AsMips64(); 3546 exception_blocks_.emplace_back(scratch, stack_adjust); 3547 LoadFromOffset(kLoadDoubleword, 3548 scratch.AsGpuRegister(), 3549 S1, 3550 Thread::ExceptionOffset<kMips64PointerSize>().Int32Value()); 3551 Bnezc(scratch.AsGpuRegister(), exception_blocks_.back().Entry()); 3552 } 3553 3554 void Mips64Assembler::EmitExceptionPoll(Mips64ExceptionSlowPath* exception) { 3555 Bind(exception->Entry()); 3556 if (exception->stack_adjust_ != 0) { // Fix up the frame. 3557 DecreaseFrameSize(exception->stack_adjust_); 3558 } 3559 // Pass exception object as argument. 3560 // Don't care about preserving A0 as this call won't return. 3561 CheckEntrypointTypes<kQuickDeliverException, void, mirror::Object*>(); 3562 Move(A0, exception->scratch_.AsGpuRegister()); 3563 // Set up call to Thread::Current()->pDeliverException 3564 LoadFromOffset(kLoadDoubleword, 3565 T9, 3566 S1, 3567 QUICK_ENTRYPOINT_OFFSET(kMips64PointerSize, pDeliverException).Int32Value()); 3568 Jr(T9); 3569 Nop(); 3570 3571 // Call never returns 3572 Break(); 3573 } 3574 3575 } // namespace mips64 3576 } // namespace art 3577