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::FaddW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1360 CHECK(HasMsa()); 1361 EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x1b); 1362 } 1363 1364 void Mips64Assembler::FaddD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1365 CHECK(HasMsa()); 1366 EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x1b); 1367 } 1368 1369 void Mips64Assembler::FsubW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1370 CHECK(HasMsa()); 1371 EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x1b); 1372 } 1373 1374 void Mips64Assembler::FsubD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1375 CHECK(HasMsa()); 1376 EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x1b); 1377 } 1378 1379 void Mips64Assembler::FmulW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1380 CHECK(HasMsa()); 1381 EmitMsa3R(0x1, 0x0, wt, ws, wd, 0x1b); 1382 } 1383 1384 void Mips64Assembler::FmulD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1385 CHECK(HasMsa()); 1386 EmitMsa3R(0x1, 0x1, wt, ws, wd, 0x1b); 1387 } 1388 1389 void Mips64Assembler::FdivW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1390 CHECK(HasMsa()); 1391 EmitMsa3R(0x1, 0x2, wt, ws, wd, 0x1b); 1392 } 1393 1394 void Mips64Assembler::FdivD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1395 CHECK(HasMsa()); 1396 EmitMsa3R(0x1, 0x3, wt, ws, wd, 0x1b); 1397 } 1398 1399 void Mips64Assembler::Ffint_sW(VectorRegister wd, VectorRegister ws) { 1400 CHECK(HasMsa()); 1401 EmitMsa2RF(0x19e, 0x0, ws, wd, 0x1e); 1402 } 1403 1404 void Mips64Assembler::Ffint_sD(VectorRegister wd, VectorRegister ws) { 1405 CHECK(HasMsa()); 1406 EmitMsa2RF(0x19e, 0x1, ws, wd, 0x1e); 1407 } 1408 1409 void Mips64Assembler::Ftint_sW(VectorRegister wd, VectorRegister ws) { 1410 CHECK(HasMsa()); 1411 EmitMsa2RF(0x19c, 0x0, ws, wd, 0x1e); 1412 } 1413 1414 void Mips64Assembler::Ftint_sD(VectorRegister wd, VectorRegister ws) { 1415 CHECK(HasMsa()); 1416 EmitMsa2RF(0x19c, 0x1, ws, wd, 0x1e); 1417 } 1418 1419 void Mips64Assembler::SllB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1420 CHECK(HasMsa()); 1421 EmitMsa3R(0x0, 0x0, wt, ws, wd, 0xd); 1422 } 1423 1424 void Mips64Assembler::SllH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1425 CHECK(HasMsa()); 1426 EmitMsa3R(0x0, 0x1, wt, ws, wd, 0xd); 1427 } 1428 1429 void Mips64Assembler::SllW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1430 CHECK(HasMsa()); 1431 EmitMsa3R(0x0, 0x2, wt, ws, wd, 0xd); 1432 } 1433 1434 void Mips64Assembler::SllD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1435 CHECK(HasMsa()); 1436 EmitMsa3R(0x0, 0x3, wt, ws, wd, 0xd); 1437 } 1438 1439 void Mips64Assembler::SraB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1440 CHECK(HasMsa()); 1441 EmitMsa3R(0x1, 0x0, wt, ws, wd, 0xd); 1442 } 1443 1444 void Mips64Assembler::SraH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1445 CHECK(HasMsa()); 1446 EmitMsa3R(0x1, 0x1, wt, ws, wd, 0xd); 1447 } 1448 1449 void Mips64Assembler::SraW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1450 CHECK(HasMsa()); 1451 EmitMsa3R(0x1, 0x2, wt, ws, wd, 0xd); 1452 } 1453 1454 void Mips64Assembler::SraD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1455 CHECK(HasMsa()); 1456 EmitMsa3R(0x1, 0x3, wt, ws, wd, 0xd); 1457 } 1458 1459 void Mips64Assembler::SrlB(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1460 CHECK(HasMsa()); 1461 EmitMsa3R(0x2, 0x0, wt, ws, wd, 0xd); 1462 } 1463 1464 void Mips64Assembler::SrlH(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1465 CHECK(HasMsa()); 1466 EmitMsa3R(0x2, 0x1, wt, ws, wd, 0xd); 1467 } 1468 1469 void Mips64Assembler::SrlW(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1470 CHECK(HasMsa()); 1471 EmitMsa3R(0x2, 0x2, wt, ws, wd, 0xd); 1472 } 1473 1474 void Mips64Assembler::SrlD(VectorRegister wd, VectorRegister ws, VectorRegister wt) { 1475 CHECK(HasMsa()); 1476 EmitMsa3R(0x2, 0x3, wt, ws, wd, 0xd); 1477 } 1478 1479 void Mips64Assembler::SlliB(VectorRegister wd, VectorRegister ws, int shamt3) { 1480 CHECK(HasMsa()); 1481 CHECK(IsUint<3>(shamt3)) << shamt3; 1482 EmitMsaBIT(0x0, shamt3 | kMsaDfMByteMask, ws, wd, 0x9); 1483 } 1484 1485 void Mips64Assembler::SlliH(VectorRegister wd, VectorRegister ws, int shamt4) { 1486 CHECK(HasMsa()); 1487 CHECK(IsUint<4>(shamt4)) << shamt4; 1488 EmitMsaBIT(0x0, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9); 1489 } 1490 1491 void Mips64Assembler::SlliW(VectorRegister wd, VectorRegister ws, int shamt5) { 1492 CHECK(HasMsa()); 1493 CHECK(IsUint<5>(shamt5)) << shamt5; 1494 EmitMsaBIT(0x0, shamt5 | kMsaDfMWordMask, ws, wd, 0x9); 1495 } 1496 1497 void Mips64Assembler::SlliD(VectorRegister wd, VectorRegister ws, int shamt6) { 1498 CHECK(HasMsa()); 1499 CHECK(IsUint<6>(shamt6)) << shamt6; 1500 EmitMsaBIT(0x0, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9); 1501 } 1502 1503 void Mips64Assembler::SraiB(VectorRegister wd, VectorRegister ws, int shamt3) { 1504 CHECK(HasMsa()); 1505 CHECK(IsUint<3>(shamt3)) << shamt3; 1506 EmitMsaBIT(0x1, shamt3 | kMsaDfMByteMask, ws, wd, 0x9); 1507 } 1508 1509 void Mips64Assembler::SraiH(VectorRegister wd, VectorRegister ws, int shamt4) { 1510 CHECK(HasMsa()); 1511 CHECK(IsUint<4>(shamt4)) << shamt4; 1512 EmitMsaBIT(0x1, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9); 1513 } 1514 1515 void Mips64Assembler::SraiW(VectorRegister wd, VectorRegister ws, int shamt5) { 1516 CHECK(HasMsa()); 1517 CHECK(IsUint<5>(shamt5)) << shamt5; 1518 EmitMsaBIT(0x1, shamt5 | kMsaDfMWordMask, ws, wd, 0x9); 1519 } 1520 1521 void Mips64Assembler::SraiD(VectorRegister wd, VectorRegister ws, int shamt6) { 1522 CHECK(HasMsa()); 1523 CHECK(IsUint<6>(shamt6)) << shamt6; 1524 EmitMsaBIT(0x1, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9); 1525 } 1526 1527 void Mips64Assembler::SrliB(VectorRegister wd, VectorRegister ws, int shamt3) { 1528 CHECK(HasMsa()); 1529 CHECK(IsUint<3>(shamt3)) << shamt3; 1530 EmitMsaBIT(0x2, shamt3 | kMsaDfMByteMask, ws, wd, 0x9); 1531 } 1532 1533 void Mips64Assembler::SrliH(VectorRegister wd, VectorRegister ws, int shamt4) { 1534 CHECK(HasMsa()); 1535 CHECK(IsUint<4>(shamt4)) << shamt4; 1536 EmitMsaBIT(0x2, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9); 1537 } 1538 1539 void Mips64Assembler::SrliW(VectorRegister wd, VectorRegister ws, int shamt5) { 1540 CHECK(HasMsa()); 1541 CHECK(IsUint<5>(shamt5)) << shamt5; 1542 EmitMsaBIT(0x2, shamt5 | kMsaDfMWordMask, ws, wd, 0x9); 1543 } 1544 1545 void Mips64Assembler::SrliD(VectorRegister wd, VectorRegister ws, int shamt6) { 1546 CHECK(HasMsa()); 1547 CHECK(IsUint<6>(shamt6)) << shamt6; 1548 EmitMsaBIT(0x2, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9); 1549 } 1550 1551 void Mips64Assembler::MoveV(VectorRegister wd, VectorRegister ws) { 1552 CHECK(HasMsa()); 1553 EmitMsaBIT(0x1, 0x3e, ws, wd, 0x19); 1554 } 1555 1556 void Mips64Assembler::SplatiB(VectorRegister wd, VectorRegister ws, int n4) { 1557 CHECK(HasMsa()); 1558 CHECK(IsUint<4>(n4)) << n4; 1559 EmitMsaELM(0x1, n4 | kMsaDfNByteMask, ws, wd, 0x19); 1560 } 1561 1562 void Mips64Assembler::SplatiH(VectorRegister wd, VectorRegister ws, int n3) { 1563 CHECK(HasMsa()); 1564 CHECK(IsUint<3>(n3)) << n3; 1565 EmitMsaELM(0x1, n3 | kMsaDfNHalfwordMask, ws, wd, 0x19); 1566 } 1567 1568 void Mips64Assembler::SplatiW(VectorRegister wd, VectorRegister ws, int n2) { 1569 CHECK(HasMsa()); 1570 CHECK(IsUint<2>(n2)) << n2; 1571 EmitMsaELM(0x1, n2 | kMsaDfNWordMask, ws, wd, 0x19); 1572 } 1573 1574 void Mips64Assembler::SplatiD(VectorRegister wd, VectorRegister ws, int n1) { 1575 CHECK(HasMsa()); 1576 CHECK(IsUint<1>(n1)) << n1; 1577 EmitMsaELM(0x1, n1 | kMsaDfNDoublewordMask, ws, wd, 0x19); 1578 } 1579 1580 void Mips64Assembler::FillB(VectorRegister wd, GpuRegister rs) { 1581 CHECK(HasMsa()); 1582 EmitMsa2R(0xc0, 0x0, static_cast<VectorRegister>(rs), wd, 0x1e); 1583 } 1584 1585 void Mips64Assembler::FillH(VectorRegister wd, GpuRegister rs) { 1586 CHECK(HasMsa()); 1587 EmitMsa2R(0xc0, 0x1, static_cast<VectorRegister>(rs), wd, 0x1e); 1588 } 1589 1590 void Mips64Assembler::FillW(VectorRegister wd, GpuRegister rs) { 1591 CHECK(HasMsa()); 1592 EmitMsa2R(0xc0, 0x2, static_cast<VectorRegister>(rs), wd, 0x1e); 1593 } 1594 1595 void Mips64Assembler::FillD(VectorRegister wd, GpuRegister rs) { 1596 CHECK(HasMsa()); 1597 EmitMsa2R(0xc0, 0x3, static_cast<VectorRegister>(rs), wd, 0x1e); 1598 } 1599 1600 void Mips64Assembler::LdiB(VectorRegister wd, int imm8) { 1601 CHECK(HasMsa()); 1602 CHECK(IsInt<8>(imm8)) << imm8; 1603 EmitMsaI10(0x6, 0x0, imm8 & kMsaS10Mask, wd, 0x7); 1604 } 1605 1606 void Mips64Assembler::LdiH(VectorRegister wd, int imm10) { 1607 CHECK(HasMsa()); 1608 CHECK(IsInt<10>(imm10)) << imm10; 1609 EmitMsaI10(0x6, 0x1, imm10 & kMsaS10Mask, wd, 0x7); 1610 } 1611 1612 void Mips64Assembler::LdiW(VectorRegister wd, int imm10) { 1613 CHECK(HasMsa()); 1614 CHECK(IsInt<10>(imm10)) << imm10; 1615 EmitMsaI10(0x6, 0x2, imm10 & kMsaS10Mask, wd, 0x7); 1616 } 1617 1618 void Mips64Assembler::LdiD(VectorRegister wd, int imm10) { 1619 CHECK(HasMsa()); 1620 CHECK(IsInt<10>(imm10)) << imm10; 1621 EmitMsaI10(0x6, 0x3, imm10 & kMsaS10Mask, wd, 0x7); 1622 } 1623 1624 void Mips64Assembler::LdB(VectorRegister wd, GpuRegister rs, int offset) { 1625 CHECK(HasMsa()); 1626 CHECK(IsInt<10>(offset)) << offset; 1627 EmitMsaMI10(offset & kMsaS10Mask, rs, wd, 0x8, 0x0); 1628 } 1629 1630 void Mips64Assembler::LdH(VectorRegister wd, GpuRegister rs, int offset) { 1631 CHECK(HasMsa()); 1632 CHECK(IsInt<11>(offset)) << offset; 1633 CHECK_ALIGNED(offset, kMips64HalfwordSize); 1634 EmitMsaMI10((offset >> TIMES_2) & kMsaS10Mask, rs, wd, 0x8, 0x1); 1635 } 1636 1637 void Mips64Assembler::LdW(VectorRegister wd, GpuRegister rs, int offset) { 1638 CHECK(HasMsa()); 1639 CHECK(IsInt<12>(offset)) << offset; 1640 CHECK_ALIGNED(offset, kMips64WordSize); 1641 EmitMsaMI10((offset >> TIMES_4) & kMsaS10Mask, rs, wd, 0x8, 0x2); 1642 } 1643 1644 void Mips64Assembler::LdD(VectorRegister wd, GpuRegister rs, int offset) { 1645 CHECK(HasMsa()); 1646 CHECK(IsInt<13>(offset)) << offset; 1647 CHECK_ALIGNED(offset, kMips64DoublewordSize); 1648 EmitMsaMI10((offset >> TIMES_8) & kMsaS10Mask, rs, wd, 0x8, 0x3); 1649 } 1650 1651 void Mips64Assembler::StB(VectorRegister wd, GpuRegister rs, int offset) { 1652 CHECK(HasMsa()); 1653 CHECK(IsInt<10>(offset)) << offset; 1654 EmitMsaMI10(offset & kMsaS10Mask, rs, wd, 0x9, 0x0); 1655 } 1656 1657 void Mips64Assembler::StH(VectorRegister wd, GpuRegister rs, int offset) { 1658 CHECK(HasMsa()); 1659 CHECK(IsInt<11>(offset)) << offset; 1660 CHECK_ALIGNED(offset, kMips64HalfwordSize); 1661 EmitMsaMI10((offset >> TIMES_2) & kMsaS10Mask, rs, wd, 0x9, 0x1); 1662 } 1663 1664 void Mips64Assembler::StW(VectorRegister wd, GpuRegister rs, int offset) { 1665 CHECK(HasMsa()); 1666 CHECK(IsInt<12>(offset)) << offset; 1667 CHECK_ALIGNED(offset, kMips64WordSize); 1668 EmitMsaMI10((offset >> TIMES_4) & kMsaS10Mask, rs, wd, 0x9, 0x2); 1669 } 1670 1671 void Mips64Assembler::StD(VectorRegister wd, GpuRegister rs, int offset) { 1672 CHECK(HasMsa()); 1673 CHECK(IsInt<13>(offset)) << offset; 1674 CHECK_ALIGNED(offset, kMips64DoublewordSize); 1675 EmitMsaMI10((offset >> TIMES_8) & kMsaS10Mask, rs, wd, 0x9, 0x3); 1676 } 1677 1678 void Mips64Assembler::LoadConst32(GpuRegister rd, int32_t value) { 1679 TemplateLoadConst32(this, rd, value); 1680 } 1681 1682 // This function is only used for testing purposes. 1683 void Mips64Assembler::RecordLoadConst64Path(int value ATTRIBUTE_UNUSED) { 1684 } 1685 1686 void Mips64Assembler::LoadConst64(GpuRegister rd, int64_t value) { 1687 TemplateLoadConst64(this, rd, value); 1688 } 1689 1690 void Mips64Assembler::Addiu32(GpuRegister rt, GpuRegister rs, int32_t value) { 1691 if (IsInt<16>(value)) { 1692 Addiu(rt, rs, value); 1693 } else { 1694 int16_t high = High16Bits(value); 1695 int16_t low = Low16Bits(value); 1696 high += (low < 0) ? 1 : 0; // Account for sign extension in addiu. 1697 Aui(rt, rs, high); 1698 if (low != 0) { 1699 Addiu(rt, rt, low); 1700 } 1701 } 1702 } 1703 1704 // TODO: don't use rtmp, use daui, dahi, dati. 1705 void Mips64Assembler::Daddiu64(GpuRegister rt, GpuRegister rs, int64_t value, GpuRegister rtmp) { 1706 CHECK_NE(rs, rtmp); 1707 if (IsInt<16>(value)) { 1708 Daddiu(rt, rs, value); 1709 } else { 1710 LoadConst64(rtmp, value); 1711 Daddu(rt, rs, rtmp); 1712 } 1713 } 1714 1715 void Mips64Assembler::Branch::InitShortOrLong(Mips64Assembler::Branch::OffsetBits offset_size, 1716 Mips64Assembler::Branch::Type short_type, 1717 Mips64Assembler::Branch::Type long_type) { 1718 type_ = (offset_size <= branch_info_[short_type].offset_size) ? short_type : long_type; 1719 } 1720 1721 void Mips64Assembler::Branch::InitializeType(Type initial_type) { 1722 OffsetBits offset_size = GetOffsetSizeNeeded(location_, target_); 1723 switch (initial_type) { 1724 case kLabel: 1725 case kLiteral: 1726 case kLiteralUnsigned: 1727 case kLiteralLong: 1728 CHECK(!IsResolved()); 1729 type_ = initial_type; 1730 break; 1731 case kCall: 1732 InitShortOrLong(offset_size, kCall, kLongCall); 1733 break; 1734 case kCondBranch: 1735 switch (condition_) { 1736 case kUncond: 1737 InitShortOrLong(offset_size, kUncondBranch, kLongUncondBranch); 1738 break; 1739 case kCondEQZ: 1740 case kCondNEZ: 1741 // Special case for beqzc/bnezc with longer offset than in other b<cond>c instructions. 1742 type_ = (offset_size <= kOffset23) ? kCondBranch : kLongCondBranch; 1743 break; 1744 default: 1745 InitShortOrLong(offset_size, kCondBranch, kLongCondBranch); 1746 break; 1747 } 1748 break; 1749 default: 1750 LOG(FATAL) << "Unexpected branch type " << initial_type; 1751 UNREACHABLE(); 1752 } 1753 old_type_ = type_; 1754 } 1755 1756 bool Mips64Assembler::Branch::IsNop(BranchCondition condition, GpuRegister lhs, GpuRegister rhs) { 1757 switch (condition) { 1758 case kCondLT: 1759 case kCondGT: 1760 case kCondNE: 1761 case kCondLTU: 1762 return lhs == rhs; 1763 default: 1764 return false; 1765 } 1766 } 1767 1768 bool Mips64Assembler::Branch::IsUncond(BranchCondition condition, 1769 GpuRegister lhs, 1770 GpuRegister rhs) { 1771 switch (condition) { 1772 case kUncond: 1773 return true; 1774 case kCondGE: 1775 case kCondLE: 1776 case kCondEQ: 1777 case kCondGEU: 1778 return lhs == rhs; 1779 default: 1780 return false; 1781 } 1782 } 1783 1784 Mips64Assembler::Branch::Branch(uint32_t location, uint32_t target, bool is_call) 1785 : old_location_(location), 1786 location_(location), 1787 target_(target), 1788 lhs_reg_(ZERO), 1789 rhs_reg_(ZERO), 1790 condition_(kUncond) { 1791 InitializeType(is_call ? kCall : kCondBranch); 1792 } 1793 1794 Mips64Assembler::Branch::Branch(uint32_t location, 1795 uint32_t target, 1796 Mips64Assembler::BranchCondition condition, 1797 GpuRegister lhs_reg, 1798 GpuRegister rhs_reg) 1799 : old_location_(location), 1800 location_(location), 1801 target_(target), 1802 lhs_reg_(lhs_reg), 1803 rhs_reg_(rhs_reg), 1804 condition_(condition) { 1805 CHECK_NE(condition, kUncond); 1806 switch (condition) { 1807 case kCondEQ: 1808 case kCondNE: 1809 case kCondLT: 1810 case kCondGE: 1811 case kCondLE: 1812 case kCondGT: 1813 case kCondLTU: 1814 case kCondGEU: 1815 CHECK_NE(lhs_reg, ZERO); 1816 CHECK_NE(rhs_reg, ZERO); 1817 break; 1818 case kCondLTZ: 1819 case kCondGEZ: 1820 case kCondLEZ: 1821 case kCondGTZ: 1822 case kCondEQZ: 1823 case kCondNEZ: 1824 CHECK_NE(lhs_reg, ZERO); 1825 CHECK_EQ(rhs_reg, ZERO); 1826 break; 1827 case kCondF: 1828 case kCondT: 1829 CHECK_EQ(rhs_reg, ZERO); 1830 break; 1831 case kUncond: 1832 UNREACHABLE(); 1833 } 1834 CHECK(!IsNop(condition, lhs_reg, rhs_reg)); 1835 if (IsUncond(condition, lhs_reg, rhs_reg)) { 1836 // Branch condition is always true, make the branch unconditional. 1837 condition_ = kUncond; 1838 } 1839 InitializeType(kCondBranch); 1840 } 1841 1842 Mips64Assembler::Branch::Branch(uint32_t location, GpuRegister dest_reg, Type label_or_literal_type) 1843 : old_location_(location), 1844 location_(location), 1845 target_(kUnresolved), 1846 lhs_reg_(dest_reg), 1847 rhs_reg_(ZERO), 1848 condition_(kUncond) { 1849 CHECK_NE(dest_reg, ZERO); 1850 InitializeType(label_or_literal_type); 1851 } 1852 1853 Mips64Assembler::BranchCondition Mips64Assembler::Branch::OppositeCondition( 1854 Mips64Assembler::BranchCondition cond) { 1855 switch (cond) { 1856 case kCondLT: 1857 return kCondGE; 1858 case kCondGE: 1859 return kCondLT; 1860 case kCondLE: 1861 return kCondGT; 1862 case kCondGT: 1863 return kCondLE; 1864 case kCondLTZ: 1865 return kCondGEZ; 1866 case kCondGEZ: 1867 return kCondLTZ; 1868 case kCondLEZ: 1869 return kCondGTZ; 1870 case kCondGTZ: 1871 return kCondLEZ; 1872 case kCondEQ: 1873 return kCondNE; 1874 case kCondNE: 1875 return kCondEQ; 1876 case kCondEQZ: 1877 return kCondNEZ; 1878 case kCondNEZ: 1879 return kCondEQZ; 1880 case kCondLTU: 1881 return kCondGEU; 1882 case kCondGEU: 1883 return kCondLTU; 1884 case kCondF: 1885 return kCondT; 1886 case kCondT: 1887 return kCondF; 1888 case kUncond: 1889 LOG(FATAL) << "Unexpected branch condition " << cond; 1890 } 1891 UNREACHABLE(); 1892 } 1893 1894 Mips64Assembler::Branch::Type Mips64Assembler::Branch::GetType() const { 1895 return type_; 1896 } 1897 1898 Mips64Assembler::BranchCondition Mips64Assembler::Branch::GetCondition() const { 1899 return condition_; 1900 } 1901 1902 GpuRegister Mips64Assembler::Branch::GetLeftRegister() const { 1903 return lhs_reg_; 1904 } 1905 1906 GpuRegister Mips64Assembler::Branch::GetRightRegister() const { 1907 return rhs_reg_; 1908 } 1909 1910 uint32_t Mips64Assembler::Branch::GetTarget() const { 1911 return target_; 1912 } 1913 1914 uint32_t Mips64Assembler::Branch::GetLocation() const { 1915 return location_; 1916 } 1917 1918 uint32_t Mips64Assembler::Branch::GetOldLocation() const { 1919 return old_location_; 1920 } 1921 1922 uint32_t Mips64Assembler::Branch::GetLength() const { 1923 return branch_info_[type_].length; 1924 } 1925 1926 uint32_t Mips64Assembler::Branch::GetOldLength() const { 1927 return branch_info_[old_type_].length; 1928 } 1929 1930 uint32_t Mips64Assembler::Branch::GetSize() const { 1931 return GetLength() * sizeof(uint32_t); 1932 } 1933 1934 uint32_t Mips64Assembler::Branch::GetOldSize() const { 1935 return GetOldLength() * sizeof(uint32_t); 1936 } 1937 1938 uint32_t Mips64Assembler::Branch::GetEndLocation() const { 1939 return GetLocation() + GetSize(); 1940 } 1941 1942 uint32_t Mips64Assembler::Branch::GetOldEndLocation() const { 1943 return GetOldLocation() + GetOldSize(); 1944 } 1945 1946 bool Mips64Assembler::Branch::IsLong() const { 1947 switch (type_) { 1948 // Short branches. 1949 case kUncondBranch: 1950 case kCondBranch: 1951 case kCall: 1952 // Near label. 1953 case kLabel: 1954 // Near literals. 1955 case kLiteral: 1956 case kLiteralUnsigned: 1957 case kLiteralLong: 1958 return false; 1959 // Long branches. 1960 case kLongUncondBranch: 1961 case kLongCondBranch: 1962 case kLongCall: 1963 // Far label. 1964 case kFarLabel: 1965 // Far literals. 1966 case kFarLiteral: 1967 case kFarLiteralUnsigned: 1968 case kFarLiteralLong: 1969 return true; 1970 } 1971 UNREACHABLE(); 1972 } 1973 1974 bool Mips64Assembler::Branch::IsResolved() const { 1975 return target_ != kUnresolved; 1976 } 1977 1978 Mips64Assembler::Branch::OffsetBits Mips64Assembler::Branch::GetOffsetSize() const { 1979 OffsetBits offset_size = 1980 (type_ == kCondBranch && (condition_ == kCondEQZ || condition_ == kCondNEZ)) 1981 ? kOffset23 1982 : branch_info_[type_].offset_size; 1983 return offset_size; 1984 } 1985 1986 Mips64Assembler::Branch::OffsetBits Mips64Assembler::Branch::GetOffsetSizeNeeded(uint32_t location, 1987 uint32_t target) { 1988 // For unresolved targets assume the shortest encoding 1989 // (later it will be made longer if needed). 1990 if (target == kUnresolved) 1991 return kOffset16; 1992 int64_t distance = static_cast<int64_t>(target) - location; 1993 // To simplify calculations in composite branches consisting of multiple instructions 1994 // bump up the distance by a value larger than the max byte size of a composite branch. 1995 distance += (distance >= 0) ? kMaxBranchSize : -kMaxBranchSize; 1996 if (IsInt<kOffset16>(distance)) 1997 return kOffset16; 1998 else if (IsInt<kOffset18>(distance)) 1999 return kOffset18; 2000 else if (IsInt<kOffset21>(distance)) 2001 return kOffset21; 2002 else if (IsInt<kOffset23>(distance)) 2003 return kOffset23; 2004 else if (IsInt<kOffset28>(distance)) 2005 return kOffset28; 2006 return kOffset32; 2007 } 2008 2009 void Mips64Assembler::Branch::Resolve(uint32_t target) { 2010 target_ = target; 2011 } 2012 2013 void Mips64Assembler::Branch::Relocate(uint32_t expand_location, uint32_t delta) { 2014 if (location_ > expand_location) { 2015 location_ += delta; 2016 } 2017 if (!IsResolved()) { 2018 return; // Don't know the target yet. 2019 } 2020 if (target_ > expand_location) { 2021 target_ += delta; 2022 } 2023 } 2024 2025 void Mips64Assembler::Branch::PromoteToLong() { 2026 switch (type_) { 2027 // Short branches. 2028 case kUncondBranch: 2029 type_ = kLongUncondBranch; 2030 break; 2031 case kCondBranch: 2032 type_ = kLongCondBranch; 2033 break; 2034 case kCall: 2035 type_ = kLongCall; 2036 break; 2037 // Near label. 2038 case kLabel: 2039 type_ = kFarLabel; 2040 break; 2041 // Near literals. 2042 case kLiteral: 2043 type_ = kFarLiteral; 2044 break; 2045 case kLiteralUnsigned: 2046 type_ = kFarLiteralUnsigned; 2047 break; 2048 case kLiteralLong: 2049 type_ = kFarLiteralLong; 2050 break; 2051 default: 2052 // Note: 'type_' is already long. 2053 break; 2054 } 2055 CHECK(IsLong()); 2056 } 2057 2058 uint32_t Mips64Assembler::Branch::PromoteIfNeeded(uint32_t max_short_distance) { 2059 // If the branch is still unresolved or already long, nothing to do. 2060 if (IsLong() || !IsResolved()) { 2061 return 0; 2062 } 2063 // Promote the short branch to long if the offset size is too small 2064 // to hold the distance between location_ and target_. 2065 if (GetOffsetSizeNeeded(location_, target_) > GetOffsetSize()) { 2066 PromoteToLong(); 2067 uint32_t old_size = GetOldSize(); 2068 uint32_t new_size = GetSize(); 2069 CHECK_GT(new_size, old_size); 2070 return new_size - old_size; 2071 } 2072 // The following logic is for debugging/testing purposes. 2073 // Promote some short branches to long when it's not really required. 2074 if (UNLIKELY(max_short_distance != std::numeric_limits<uint32_t>::max())) { 2075 int64_t distance = static_cast<int64_t>(target_) - location_; 2076 distance = (distance >= 0) ? distance : -distance; 2077 if (distance >= max_short_distance) { 2078 PromoteToLong(); 2079 uint32_t old_size = GetOldSize(); 2080 uint32_t new_size = GetSize(); 2081 CHECK_GT(new_size, old_size); 2082 return new_size - old_size; 2083 } 2084 } 2085 return 0; 2086 } 2087 2088 uint32_t Mips64Assembler::Branch::GetOffsetLocation() const { 2089 return location_ + branch_info_[type_].instr_offset * sizeof(uint32_t); 2090 } 2091 2092 uint32_t Mips64Assembler::Branch::GetOffset() const { 2093 CHECK(IsResolved()); 2094 uint32_t ofs_mask = 0xFFFFFFFF >> (32 - GetOffsetSize()); 2095 // Calculate the byte distance between instructions and also account for 2096 // different PC-relative origins. 2097 uint32_t offset_location = GetOffsetLocation(); 2098 if (type_ == kLiteralLong) { 2099 // Special case for the ldpc instruction, whose address (PC) is rounded down to 2100 // a multiple of 8 before adding the offset. 2101 // Note, branch promotion has already taken care of aligning `target_` to an 2102 // address that's a multiple of 8. 2103 offset_location = RoundDown(offset_location, sizeof(uint64_t)); 2104 } 2105 uint32_t offset = target_ - offset_location - branch_info_[type_].pc_org * sizeof(uint32_t); 2106 // Prepare the offset for encoding into the instruction(s). 2107 offset = (offset & ofs_mask) >> branch_info_[type_].offset_shift; 2108 return offset; 2109 } 2110 2111 Mips64Assembler::Branch* Mips64Assembler::GetBranch(uint32_t branch_id) { 2112 CHECK_LT(branch_id, branches_.size()); 2113 return &branches_[branch_id]; 2114 } 2115 2116 const Mips64Assembler::Branch* Mips64Assembler::GetBranch(uint32_t branch_id) const { 2117 CHECK_LT(branch_id, branches_.size()); 2118 return &branches_[branch_id]; 2119 } 2120 2121 void Mips64Assembler::Bind(Mips64Label* label) { 2122 CHECK(!label->IsBound()); 2123 uint32_t bound_pc = buffer_.Size(); 2124 2125 // Walk the list of branches referring to and preceding this label. 2126 // Store the previously unknown target addresses in them. 2127 while (label->IsLinked()) { 2128 uint32_t branch_id = label->Position(); 2129 Branch* branch = GetBranch(branch_id); 2130 branch->Resolve(bound_pc); 2131 2132 uint32_t branch_location = branch->GetLocation(); 2133 // Extract the location of the previous branch in the list (walking the list backwards; 2134 // the previous branch ID was stored in the space reserved for this branch). 2135 uint32_t prev = buffer_.Load<uint32_t>(branch_location); 2136 2137 // On to the previous branch in the list... 2138 label->position_ = prev; 2139 } 2140 2141 // Now make the label object contain its own location (relative to the end of the preceding 2142 // branch, if any; it will be used by the branches referring to and following this label). 2143 label->prev_branch_id_plus_one_ = branches_.size(); 2144 if (label->prev_branch_id_plus_one_) { 2145 uint32_t branch_id = label->prev_branch_id_plus_one_ - 1; 2146 const Branch* branch = GetBranch(branch_id); 2147 bound_pc -= branch->GetEndLocation(); 2148 } 2149 label->BindTo(bound_pc); 2150 } 2151 2152 uint32_t Mips64Assembler::GetLabelLocation(const Mips64Label* label) const { 2153 CHECK(label->IsBound()); 2154 uint32_t target = label->Position(); 2155 if (label->prev_branch_id_plus_one_) { 2156 // Get label location based on the branch preceding it. 2157 uint32_t branch_id = label->prev_branch_id_plus_one_ - 1; 2158 const Branch* branch = GetBranch(branch_id); 2159 target += branch->GetEndLocation(); 2160 } 2161 return target; 2162 } 2163 2164 uint32_t Mips64Assembler::GetAdjustedPosition(uint32_t old_position) { 2165 // We can reconstruct the adjustment by going through all the branches from the beginning 2166 // up to the old_position. Since we expect AdjustedPosition() to be called in a loop 2167 // with increasing old_position, we can use the data from last AdjustedPosition() to 2168 // continue where we left off and the whole loop should be O(m+n) where m is the number 2169 // of positions to adjust and n is the number of branches. 2170 if (old_position < last_old_position_) { 2171 last_position_adjustment_ = 0; 2172 last_old_position_ = 0; 2173 last_branch_id_ = 0; 2174 } 2175 while (last_branch_id_ != branches_.size()) { 2176 const Branch* branch = GetBranch(last_branch_id_); 2177 if (branch->GetLocation() >= old_position + last_position_adjustment_) { 2178 break; 2179 } 2180 last_position_adjustment_ += branch->GetSize() - branch->GetOldSize(); 2181 ++last_branch_id_; 2182 } 2183 last_old_position_ = old_position; 2184 return old_position + last_position_adjustment_; 2185 } 2186 2187 void Mips64Assembler::FinalizeLabeledBranch(Mips64Label* label) { 2188 uint32_t length = branches_.back().GetLength(); 2189 if (!label->IsBound()) { 2190 // Branch forward (to a following label), distance is unknown. 2191 // The first branch forward will contain 0, serving as the terminator of 2192 // the list of forward-reaching branches. 2193 Emit(label->position_); 2194 length--; 2195 // Now make the label object point to this branch 2196 // (this forms a linked list of branches preceding this label). 2197 uint32_t branch_id = branches_.size() - 1; 2198 label->LinkTo(branch_id); 2199 } 2200 // Reserve space for the branch. 2201 while (length--) { 2202 Nop(); 2203 } 2204 } 2205 2206 void Mips64Assembler::Buncond(Mips64Label* label) { 2207 uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved; 2208 branches_.emplace_back(buffer_.Size(), target, /* is_call */ false); 2209 FinalizeLabeledBranch(label); 2210 } 2211 2212 void Mips64Assembler::Bcond(Mips64Label* label, 2213 BranchCondition condition, 2214 GpuRegister lhs, 2215 GpuRegister rhs) { 2216 // If lhs = rhs, this can be a NOP. 2217 if (Branch::IsNop(condition, lhs, rhs)) { 2218 return; 2219 } 2220 uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved; 2221 branches_.emplace_back(buffer_.Size(), target, condition, lhs, rhs); 2222 FinalizeLabeledBranch(label); 2223 } 2224 2225 void Mips64Assembler::Call(Mips64Label* label) { 2226 uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved; 2227 branches_.emplace_back(buffer_.Size(), target, /* is_call */ true); 2228 FinalizeLabeledBranch(label); 2229 } 2230 2231 void Mips64Assembler::LoadLabelAddress(GpuRegister dest_reg, Mips64Label* label) { 2232 // Label address loads are treated as pseudo branches since they require very similar handling. 2233 DCHECK(!label->IsBound()); 2234 branches_.emplace_back(buffer_.Size(), dest_reg, Branch::kLabel); 2235 FinalizeLabeledBranch(label); 2236 } 2237 2238 Literal* Mips64Assembler::NewLiteral(size_t size, const uint8_t* data) { 2239 // We don't support byte and half-word literals. 2240 if (size == 4u) { 2241 literals_.emplace_back(size, data); 2242 return &literals_.back(); 2243 } else { 2244 DCHECK_EQ(size, 8u); 2245 long_literals_.emplace_back(size, data); 2246 return &long_literals_.back(); 2247 } 2248 } 2249 2250 void Mips64Assembler::LoadLiteral(GpuRegister dest_reg, 2251 LoadOperandType load_type, 2252 Literal* literal) { 2253 // Literal loads are treated as pseudo branches since they require very similar handling. 2254 Branch::Type literal_type; 2255 switch (load_type) { 2256 case kLoadWord: 2257 DCHECK_EQ(literal->GetSize(), 4u); 2258 literal_type = Branch::kLiteral; 2259 break; 2260 case kLoadUnsignedWord: 2261 DCHECK_EQ(literal->GetSize(), 4u); 2262 literal_type = Branch::kLiteralUnsigned; 2263 break; 2264 case kLoadDoubleword: 2265 DCHECK_EQ(literal->GetSize(), 8u); 2266 literal_type = Branch::kLiteralLong; 2267 break; 2268 default: 2269 LOG(FATAL) << "Unexpected literal load type " << load_type; 2270 UNREACHABLE(); 2271 } 2272 Mips64Label* label = literal->GetLabel(); 2273 DCHECK(!label->IsBound()); 2274 branches_.emplace_back(buffer_.Size(), dest_reg, literal_type); 2275 FinalizeLabeledBranch(label); 2276 } 2277 2278 JumpTable* Mips64Assembler::CreateJumpTable(std::vector<Mips64Label*>&& labels) { 2279 jump_tables_.emplace_back(std::move(labels)); 2280 JumpTable* table = &jump_tables_.back(); 2281 DCHECK(!table->GetLabel()->IsBound()); 2282 return table; 2283 } 2284 2285 void Mips64Assembler::ReserveJumpTableSpace() { 2286 if (!jump_tables_.empty()) { 2287 for (JumpTable& table : jump_tables_) { 2288 Mips64Label* label = table.GetLabel(); 2289 Bind(label); 2290 2291 // Bulk ensure capacity, as this may be large. 2292 size_t orig_size = buffer_.Size(); 2293 size_t required_capacity = orig_size + table.GetSize(); 2294 if (required_capacity > buffer_.Capacity()) { 2295 buffer_.ExtendCapacity(required_capacity); 2296 } 2297 #ifndef NDEBUG 2298 buffer_.has_ensured_capacity_ = true; 2299 #endif 2300 2301 // Fill the space with dummy data as the data is not final 2302 // until the branches have been promoted. And we shouldn't 2303 // be moving uninitialized data during branch promotion. 2304 for (size_t cnt = table.GetData().size(), i = 0; i < cnt; i++) { 2305 buffer_.Emit<uint32_t>(0x1abe1234u); 2306 } 2307 2308 #ifndef NDEBUG 2309 buffer_.has_ensured_capacity_ = false; 2310 #endif 2311 } 2312 } 2313 } 2314 2315 void Mips64Assembler::EmitJumpTables() { 2316 if (!jump_tables_.empty()) { 2317 CHECK(!overwriting_); 2318 // Switch from appending instructions at the end of the buffer to overwriting 2319 // existing instructions (here, jump tables) in the buffer. 2320 overwriting_ = true; 2321 2322 for (JumpTable& table : jump_tables_) { 2323 Mips64Label* table_label = table.GetLabel(); 2324 uint32_t start = GetLabelLocation(table_label); 2325 overwrite_location_ = start; 2326 2327 for (Mips64Label* target : table.GetData()) { 2328 CHECK_EQ(buffer_.Load<uint32_t>(overwrite_location_), 0x1abe1234u); 2329 // The table will contain target addresses relative to the table start. 2330 uint32_t offset = GetLabelLocation(target) - start; 2331 Emit(offset); 2332 } 2333 } 2334 2335 overwriting_ = false; 2336 } 2337 } 2338 2339 void Mips64Assembler::EmitLiterals() { 2340 if (!literals_.empty()) { 2341 for (Literal& literal : literals_) { 2342 Mips64Label* label = literal.GetLabel(); 2343 Bind(label); 2344 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 2345 DCHECK_EQ(literal.GetSize(), 4u); 2346 for (size_t i = 0, size = literal.GetSize(); i != size; ++i) { 2347 buffer_.Emit<uint8_t>(literal.GetData()[i]); 2348 } 2349 } 2350 } 2351 if (!long_literals_.empty()) { 2352 // Reserve 4 bytes for potential alignment. If after the branch promotion the 64-bit 2353 // literals don't end up 8-byte-aligned, they will be moved down 4 bytes. 2354 Emit(0); // NOP. 2355 for (Literal& literal : long_literals_) { 2356 Mips64Label* label = literal.GetLabel(); 2357 Bind(label); 2358 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 2359 DCHECK_EQ(literal.GetSize(), 8u); 2360 for (size_t i = 0, size = literal.GetSize(); i != size; ++i) { 2361 buffer_.Emit<uint8_t>(literal.GetData()[i]); 2362 } 2363 } 2364 } 2365 } 2366 2367 void Mips64Assembler::PromoteBranches() { 2368 // Promote short branches to long as necessary. 2369 bool changed; 2370 do { 2371 changed = false; 2372 for (auto& branch : branches_) { 2373 CHECK(branch.IsResolved()); 2374 uint32_t delta = branch.PromoteIfNeeded(); 2375 // If this branch has been promoted and needs to expand in size, 2376 // relocate all branches by the expansion size. 2377 if (delta) { 2378 changed = true; 2379 uint32_t expand_location = branch.GetLocation(); 2380 for (auto& branch2 : branches_) { 2381 branch2.Relocate(expand_location, delta); 2382 } 2383 } 2384 } 2385 } while (changed); 2386 2387 // Account for branch expansion by resizing the code buffer 2388 // and moving the code in it to its final location. 2389 size_t branch_count = branches_.size(); 2390 if (branch_count > 0) { 2391 // Resize. 2392 Branch& last_branch = branches_[branch_count - 1]; 2393 uint32_t size_delta = last_branch.GetEndLocation() - last_branch.GetOldEndLocation(); 2394 uint32_t old_size = buffer_.Size(); 2395 buffer_.Resize(old_size + size_delta); 2396 // Move the code residing between branch placeholders. 2397 uint32_t end = old_size; 2398 for (size_t i = branch_count; i > 0; ) { 2399 Branch& branch = branches_[--i]; 2400 uint32_t size = end - branch.GetOldEndLocation(); 2401 buffer_.Move(branch.GetEndLocation(), branch.GetOldEndLocation(), size); 2402 end = branch.GetOldLocation(); 2403 } 2404 } 2405 2406 // Align 64-bit literals by moving them down by 4 bytes if needed. 2407 // This will reduce the PC-relative distance, which should be safe for both near and far literals. 2408 if (!long_literals_.empty()) { 2409 uint32_t first_literal_location = GetLabelLocation(long_literals_.front().GetLabel()); 2410 size_t lit_size = long_literals_.size() * sizeof(uint64_t); 2411 size_t buf_size = buffer_.Size(); 2412 // 64-bit literals must be at the very end of the buffer. 2413 CHECK_EQ(first_literal_location + lit_size, buf_size); 2414 if (!IsAligned<sizeof(uint64_t)>(first_literal_location)) { 2415 buffer_.Move(first_literal_location - sizeof(uint32_t), first_literal_location, lit_size); 2416 // The 4 reserved bytes proved useless, reduce the buffer size. 2417 buffer_.Resize(buf_size - sizeof(uint32_t)); 2418 // Reduce target addresses in literal and address loads by 4 bytes in order for correct 2419 // offsets from PC to be generated. 2420 for (auto& branch : branches_) { 2421 uint32_t target = branch.GetTarget(); 2422 if (target >= first_literal_location) { 2423 branch.Resolve(target - sizeof(uint32_t)); 2424 } 2425 } 2426 // If after this we ever call GetLabelLocation() to get the location of a 64-bit literal, 2427 // we need to adjust the location of the literal's label as well. 2428 for (Literal& literal : long_literals_) { 2429 // Bound label's position is negative, hence incrementing it instead of decrementing. 2430 literal.GetLabel()->position_ += sizeof(uint32_t); 2431 } 2432 } 2433 } 2434 } 2435 2436 // Note: make sure branch_info_[] and EmitBranch() are kept synchronized. 2437 const Mips64Assembler::Branch::BranchInfo Mips64Assembler::Branch::branch_info_[] = { 2438 // Short branches. 2439 { 1, 0, 1, Mips64Assembler::Branch::kOffset28, 2 }, // kUncondBranch 2440 { 2, 0, 1, Mips64Assembler::Branch::kOffset18, 2 }, // kCondBranch 2441 // Exception: kOffset23 for beqzc/bnezc 2442 { 1, 0, 1, Mips64Assembler::Branch::kOffset28, 2 }, // kCall 2443 // Near label. 2444 { 1, 0, 0, Mips64Assembler::Branch::kOffset21, 2 }, // kLabel 2445 // Near literals. 2446 { 1, 0, 0, Mips64Assembler::Branch::kOffset21, 2 }, // kLiteral 2447 { 1, 0, 0, Mips64Assembler::Branch::kOffset21, 2 }, // kLiteralUnsigned 2448 { 1, 0, 0, Mips64Assembler::Branch::kOffset21, 3 }, // kLiteralLong 2449 // Long branches. 2450 { 2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kLongUncondBranch 2451 { 3, 1, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kLongCondBranch 2452 { 2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kLongCall 2453 // Far label. 2454 { 2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kFarLabel 2455 // Far literals. 2456 { 2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kFarLiteral 2457 { 2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kFarLiteralUnsigned 2458 { 2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kFarLiteralLong 2459 }; 2460 2461 // Note: make sure branch_info_[] and EmitBranch() are kept synchronized. 2462 void Mips64Assembler::EmitBranch(Mips64Assembler::Branch* branch) { 2463 CHECK(overwriting_); 2464 overwrite_location_ = branch->GetLocation(); 2465 uint32_t offset = branch->GetOffset(); 2466 BranchCondition condition = branch->GetCondition(); 2467 GpuRegister lhs = branch->GetLeftRegister(); 2468 GpuRegister rhs = branch->GetRightRegister(); 2469 switch (branch->GetType()) { 2470 // Short branches. 2471 case Branch::kUncondBranch: 2472 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 2473 Bc(offset); 2474 break; 2475 case Branch::kCondBranch: 2476 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 2477 EmitBcondc(condition, lhs, rhs, offset); 2478 Nop(); // TODO: improve by filling the forbidden/delay slot. 2479 break; 2480 case Branch::kCall: 2481 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 2482 Balc(offset); 2483 break; 2484 2485 // Near label. 2486 case Branch::kLabel: 2487 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 2488 Addiupc(lhs, offset); 2489 break; 2490 // Near literals. 2491 case Branch::kLiteral: 2492 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 2493 Lwpc(lhs, offset); 2494 break; 2495 case Branch::kLiteralUnsigned: 2496 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 2497 Lwupc(lhs, offset); 2498 break; 2499 case Branch::kLiteralLong: 2500 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 2501 Ldpc(lhs, offset); 2502 break; 2503 2504 // Long branches. 2505 case Branch::kLongUncondBranch: 2506 offset += (offset & 0x8000) << 1; // Account for sign extension in jic. 2507 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 2508 Auipc(AT, High16Bits(offset)); 2509 Jic(AT, Low16Bits(offset)); 2510 break; 2511 case Branch::kLongCondBranch: 2512 EmitBcondc(Branch::OppositeCondition(condition), lhs, rhs, 2); 2513 offset += (offset & 0x8000) << 1; // Account for sign extension in jic. 2514 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 2515 Auipc(AT, High16Bits(offset)); 2516 Jic(AT, Low16Bits(offset)); 2517 break; 2518 case Branch::kLongCall: 2519 offset += (offset & 0x8000) << 1; // Account for sign extension in jialc. 2520 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 2521 Auipc(AT, High16Bits(offset)); 2522 Jialc(AT, Low16Bits(offset)); 2523 break; 2524 2525 // Far label. 2526 case Branch::kFarLabel: 2527 offset += (offset & 0x8000) << 1; // Account for sign extension in daddiu. 2528 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 2529 Auipc(AT, High16Bits(offset)); 2530 Daddiu(lhs, AT, Low16Bits(offset)); 2531 break; 2532 // Far literals. 2533 case Branch::kFarLiteral: 2534 offset += (offset & 0x8000) << 1; // Account for sign extension in lw. 2535 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 2536 Auipc(AT, High16Bits(offset)); 2537 Lw(lhs, AT, Low16Bits(offset)); 2538 break; 2539 case Branch::kFarLiteralUnsigned: 2540 offset += (offset & 0x8000) << 1; // Account for sign extension in lwu. 2541 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 2542 Auipc(AT, High16Bits(offset)); 2543 Lwu(lhs, AT, Low16Bits(offset)); 2544 break; 2545 case Branch::kFarLiteralLong: 2546 offset += (offset & 0x8000) << 1; // Account for sign extension in ld. 2547 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); 2548 Auipc(AT, High16Bits(offset)); 2549 Ld(lhs, AT, Low16Bits(offset)); 2550 break; 2551 } 2552 CHECK_EQ(overwrite_location_, branch->GetEndLocation()); 2553 CHECK_LT(branch->GetSize(), static_cast<uint32_t>(Branch::kMaxBranchSize)); 2554 } 2555 2556 void Mips64Assembler::Bc(Mips64Label* label) { 2557 Buncond(label); 2558 } 2559 2560 void Mips64Assembler::Balc(Mips64Label* label) { 2561 Call(label); 2562 } 2563 2564 void Mips64Assembler::Bltc(GpuRegister rs, GpuRegister rt, Mips64Label* label) { 2565 Bcond(label, kCondLT, rs, rt); 2566 } 2567 2568 void Mips64Assembler::Bltzc(GpuRegister rt, Mips64Label* label) { 2569 Bcond(label, kCondLTZ, rt); 2570 } 2571 2572 void Mips64Assembler::Bgtzc(GpuRegister rt, Mips64Label* label) { 2573 Bcond(label, kCondGTZ, rt); 2574 } 2575 2576 void Mips64Assembler::Bgec(GpuRegister rs, GpuRegister rt, Mips64Label* label) { 2577 Bcond(label, kCondGE, rs, rt); 2578 } 2579 2580 void Mips64Assembler::Bgezc(GpuRegister rt, Mips64Label* label) { 2581 Bcond(label, kCondGEZ, rt); 2582 } 2583 2584 void Mips64Assembler::Blezc(GpuRegister rt, Mips64Label* label) { 2585 Bcond(label, kCondLEZ, rt); 2586 } 2587 2588 void Mips64Assembler::Bltuc(GpuRegister rs, GpuRegister rt, Mips64Label* label) { 2589 Bcond(label, kCondLTU, rs, rt); 2590 } 2591 2592 void Mips64Assembler::Bgeuc(GpuRegister rs, GpuRegister rt, Mips64Label* label) { 2593 Bcond(label, kCondGEU, rs, rt); 2594 } 2595 2596 void Mips64Assembler::Beqc(GpuRegister rs, GpuRegister rt, Mips64Label* label) { 2597 Bcond(label, kCondEQ, rs, rt); 2598 } 2599 2600 void Mips64Assembler::Bnec(GpuRegister rs, GpuRegister rt, Mips64Label* label) { 2601 Bcond(label, kCondNE, rs, rt); 2602 } 2603 2604 void Mips64Assembler::Beqzc(GpuRegister rs, Mips64Label* label) { 2605 Bcond(label, kCondEQZ, rs); 2606 } 2607 2608 void Mips64Assembler::Bnezc(GpuRegister rs, Mips64Label* label) { 2609 Bcond(label, kCondNEZ, rs); 2610 } 2611 2612 void Mips64Assembler::Bc1eqz(FpuRegister ft, Mips64Label* label) { 2613 Bcond(label, kCondF, static_cast<GpuRegister>(ft), ZERO); 2614 } 2615 2616 void Mips64Assembler::Bc1nez(FpuRegister ft, Mips64Label* label) { 2617 Bcond(label, kCondT, static_cast<GpuRegister>(ft), ZERO); 2618 } 2619 2620 void Mips64Assembler::AdjustBaseAndOffset(GpuRegister& base, 2621 int32_t& offset, 2622 bool is_doubleword) { 2623 // This method is used to adjust the base register and offset pair 2624 // for a load/store when the offset doesn't fit into int16_t. 2625 // It is assumed that `base + offset` is sufficiently aligned for memory 2626 // operands that are machine word in size or smaller. For doubleword-sized 2627 // operands it's assumed that `base` is a multiple of 8, while `offset` 2628 // may be a multiple of 4 (e.g. 4-byte-aligned long and double arguments 2629 // and spilled variables on the stack accessed relative to the stack 2630 // pointer register). 2631 // We preserve the "alignment" of `offset` by adjusting it by a multiple of 8. 2632 CHECK_NE(base, AT); // Must not overwrite the register `base` while loading `offset`. 2633 2634 bool doubleword_aligned = IsAligned<kMips64DoublewordSize>(offset); 2635 bool two_accesses = is_doubleword && !doubleword_aligned; 2636 2637 // IsInt<16> must be passed a signed value, hence the static cast below. 2638 if (IsInt<16>(offset) && 2639 (!two_accesses || IsInt<16>(static_cast<int32_t>(offset + kMips64WordSize)))) { 2640 // Nothing to do: `offset` (and, if needed, `offset + 4`) fits into int16_t. 2641 return; 2642 } 2643 2644 // Remember the "(mis)alignment" of `offset`, it will be checked at the end. 2645 uint32_t misalignment = offset & (kMips64DoublewordSize - 1); 2646 2647 // First, see if `offset` can be represented as a sum of two 16-bit signed 2648 // offsets. This can save an instruction. 2649 // To simplify matters, only do this for a symmetric range of offsets from 2650 // about -64KB to about +64KB, allowing further addition of 4 when accessing 2651 // 64-bit variables with two 32-bit accesses. 2652 constexpr int32_t kMinOffsetForSimpleAdjustment = 0x7ff8; // Max int16_t that's a multiple of 8. 2653 constexpr int32_t kMaxOffsetForSimpleAdjustment = 2 * kMinOffsetForSimpleAdjustment; 2654 2655 if (0 <= offset && offset <= kMaxOffsetForSimpleAdjustment) { 2656 Daddiu(AT, base, kMinOffsetForSimpleAdjustment); 2657 offset -= kMinOffsetForSimpleAdjustment; 2658 } else if (-kMaxOffsetForSimpleAdjustment <= offset && offset < 0) { 2659 Daddiu(AT, base, -kMinOffsetForSimpleAdjustment); 2660 offset += kMinOffsetForSimpleAdjustment; 2661 } else { 2662 // In more complex cases take advantage of the daui instruction, e.g.: 2663 // daui AT, base, offset_high 2664 // [dahi AT, 1] // When `offset` is close to +2GB. 2665 // lw reg_lo, offset_low(AT) 2666 // [lw reg_hi, (offset_low+4)(AT)] // If misaligned 64-bit load. 2667 // or when offset_low+4 overflows int16_t: 2668 // daui AT, base, offset_high 2669 // daddiu AT, AT, 8 2670 // lw reg_lo, (offset_low-8)(AT) 2671 // lw reg_hi, (offset_low-4)(AT) 2672 int16_t offset_low = Low16Bits(offset); 2673 int32_t offset_low32 = offset_low; 2674 int16_t offset_high = High16Bits(offset); 2675 bool increment_hi16 = offset_low < 0; 2676 bool overflow_hi16 = false; 2677 2678 if (increment_hi16) { 2679 offset_high++; 2680 overflow_hi16 = (offset_high == -32768); 2681 } 2682 Daui(AT, base, offset_high); 2683 2684 if (overflow_hi16) { 2685 Dahi(AT, 1); 2686 } 2687 2688 if (two_accesses && !IsInt<16>(static_cast<int32_t>(offset_low32 + kMips64WordSize))) { 2689 // Avoid overflow in the 16-bit offset of the load/store instruction when adding 4. 2690 Daddiu(AT, AT, kMips64DoublewordSize); 2691 offset_low32 -= kMips64DoublewordSize; 2692 } 2693 2694 offset = offset_low32; 2695 } 2696 base = AT; 2697 2698 CHECK(IsInt<16>(offset)); 2699 if (two_accesses) { 2700 CHECK(IsInt<16>(static_cast<int32_t>(offset + kMips64WordSize))); 2701 } 2702 CHECK_EQ(misalignment, offset & (kMips64DoublewordSize - 1)); 2703 } 2704 2705 void Mips64Assembler::LoadFromOffset(LoadOperandType type, 2706 GpuRegister reg, 2707 GpuRegister base, 2708 int32_t offset) { 2709 LoadFromOffset<>(type, reg, base, offset); 2710 } 2711 2712 void Mips64Assembler::LoadFpuFromOffset(LoadOperandType type, 2713 FpuRegister reg, 2714 GpuRegister base, 2715 int32_t offset) { 2716 LoadFpuFromOffset<>(type, reg, base, offset); 2717 } 2718 2719 void Mips64Assembler::EmitLoad(ManagedRegister m_dst, GpuRegister src_register, int32_t src_offset, 2720 size_t size) { 2721 Mips64ManagedRegister dst = m_dst.AsMips64(); 2722 if (dst.IsNoRegister()) { 2723 CHECK_EQ(0u, size) << dst; 2724 } else if (dst.IsGpuRegister()) { 2725 if (size == 4) { 2726 LoadFromOffset(kLoadWord, dst.AsGpuRegister(), src_register, src_offset); 2727 } else if (size == 8) { 2728 CHECK_EQ(8u, size) << dst; 2729 LoadFromOffset(kLoadDoubleword, dst.AsGpuRegister(), src_register, src_offset); 2730 } else { 2731 UNIMPLEMENTED(FATAL) << "We only support Load() of size 4 and 8"; 2732 } 2733 } else if (dst.IsFpuRegister()) { 2734 if (size == 4) { 2735 CHECK_EQ(4u, size) << dst; 2736 LoadFpuFromOffset(kLoadWord, dst.AsFpuRegister(), src_register, src_offset); 2737 } else if (size == 8) { 2738 CHECK_EQ(8u, size) << dst; 2739 LoadFpuFromOffset(kLoadDoubleword, dst.AsFpuRegister(), src_register, src_offset); 2740 } else { 2741 UNIMPLEMENTED(FATAL) << "We only support Load() of size 4 and 8"; 2742 } 2743 } 2744 } 2745 2746 void Mips64Assembler::StoreToOffset(StoreOperandType type, 2747 GpuRegister reg, 2748 GpuRegister base, 2749 int32_t offset) { 2750 StoreToOffset<>(type, reg, base, offset); 2751 } 2752 2753 void Mips64Assembler::StoreFpuToOffset(StoreOperandType type, 2754 FpuRegister reg, 2755 GpuRegister base, 2756 int32_t offset) { 2757 StoreFpuToOffset<>(type, reg, base, offset); 2758 } 2759 2760 static dwarf::Reg DWARFReg(GpuRegister reg) { 2761 return dwarf::Reg::Mips64Core(static_cast<int>(reg)); 2762 } 2763 2764 constexpr size_t kFramePointerSize = 8; 2765 2766 void Mips64Assembler::BuildFrame(size_t frame_size, 2767 ManagedRegister method_reg, 2768 ArrayRef<const ManagedRegister> callee_save_regs, 2769 const ManagedRegisterEntrySpills& entry_spills) { 2770 CHECK_ALIGNED(frame_size, kStackAlignment); 2771 DCHECK(!overwriting_); 2772 2773 // Increase frame to required size. 2774 IncreaseFrameSize(frame_size); 2775 2776 // Push callee saves and return address 2777 int stack_offset = frame_size - kFramePointerSize; 2778 StoreToOffset(kStoreDoubleword, RA, SP, stack_offset); 2779 cfi_.RelOffset(DWARFReg(RA), stack_offset); 2780 for (int i = callee_save_regs.size() - 1; i >= 0; --i) { 2781 stack_offset -= kFramePointerSize; 2782 GpuRegister reg = callee_save_regs[i].AsMips64().AsGpuRegister(); 2783 StoreToOffset(kStoreDoubleword, reg, SP, stack_offset); 2784 cfi_.RelOffset(DWARFReg(reg), stack_offset); 2785 } 2786 2787 // Write out Method*. 2788 StoreToOffset(kStoreDoubleword, method_reg.AsMips64().AsGpuRegister(), SP, 0); 2789 2790 // Write out entry spills. 2791 int32_t offset = frame_size + kFramePointerSize; 2792 for (size_t i = 0; i < entry_spills.size(); ++i) { 2793 Mips64ManagedRegister reg = entry_spills[i].AsMips64(); 2794 ManagedRegisterSpill spill = entry_spills.at(i); 2795 int32_t size = spill.getSize(); 2796 if (reg.IsNoRegister()) { 2797 // only increment stack offset. 2798 offset += size; 2799 } else if (reg.IsFpuRegister()) { 2800 StoreFpuToOffset((size == 4) ? kStoreWord : kStoreDoubleword, 2801 reg.AsFpuRegister(), SP, offset); 2802 offset += size; 2803 } else if (reg.IsGpuRegister()) { 2804 StoreToOffset((size == 4) ? kStoreWord : kStoreDoubleword, 2805 reg.AsGpuRegister(), SP, offset); 2806 offset += size; 2807 } 2808 } 2809 } 2810 2811 void Mips64Assembler::RemoveFrame(size_t frame_size, 2812 ArrayRef<const ManagedRegister> callee_save_regs) { 2813 CHECK_ALIGNED(frame_size, kStackAlignment); 2814 DCHECK(!overwriting_); 2815 cfi_.RememberState(); 2816 2817 // Pop callee saves and return address 2818 int stack_offset = frame_size - (callee_save_regs.size() * kFramePointerSize) - kFramePointerSize; 2819 for (size_t i = 0; i < callee_save_regs.size(); ++i) { 2820 GpuRegister reg = callee_save_regs[i].AsMips64().AsGpuRegister(); 2821 LoadFromOffset(kLoadDoubleword, reg, SP, stack_offset); 2822 cfi_.Restore(DWARFReg(reg)); 2823 stack_offset += kFramePointerSize; 2824 } 2825 LoadFromOffset(kLoadDoubleword, RA, SP, stack_offset); 2826 cfi_.Restore(DWARFReg(RA)); 2827 2828 // Decrease frame to required size. 2829 DecreaseFrameSize(frame_size); 2830 2831 // Then jump to the return address. 2832 Jr(RA); 2833 Nop(); 2834 2835 // The CFI should be restored for any code that follows the exit block. 2836 cfi_.RestoreState(); 2837 cfi_.DefCFAOffset(frame_size); 2838 } 2839 2840 void Mips64Assembler::IncreaseFrameSize(size_t adjust) { 2841 CHECK_ALIGNED(adjust, kFramePointerSize); 2842 DCHECK(!overwriting_); 2843 Daddiu64(SP, SP, static_cast<int32_t>(-adjust)); 2844 cfi_.AdjustCFAOffset(adjust); 2845 } 2846 2847 void Mips64Assembler::DecreaseFrameSize(size_t adjust) { 2848 CHECK_ALIGNED(adjust, kFramePointerSize); 2849 DCHECK(!overwriting_); 2850 Daddiu64(SP, SP, static_cast<int32_t>(adjust)); 2851 cfi_.AdjustCFAOffset(-adjust); 2852 } 2853 2854 void Mips64Assembler::Store(FrameOffset dest, ManagedRegister msrc, size_t size) { 2855 Mips64ManagedRegister src = msrc.AsMips64(); 2856 if (src.IsNoRegister()) { 2857 CHECK_EQ(0u, size); 2858 } else if (src.IsGpuRegister()) { 2859 CHECK(size == 4 || size == 8) << size; 2860 if (size == 8) { 2861 StoreToOffset(kStoreDoubleword, src.AsGpuRegister(), SP, dest.Int32Value()); 2862 } else if (size == 4) { 2863 StoreToOffset(kStoreWord, src.AsGpuRegister(), SP, dest.Int32Value()); 2864 } else { 2865 UNIMPLEMENTED(FATAL) << "We only support Store() of size 4 and 8"; 2866 } 2867 } else if (src.IsFpuRegister()) { 2868 CHECK(size == 4 || size == 8) << size; 2869 if (size == 8) { 2870 StoreFpuToOffset(kStoreDoubleword, src.AsFpuRegister(), SP, dest.Int32Value()); 2871 } else if (size == 4) { 2872 StoreFpuToOffset(kStoreWord, src.AsFpuRegister(), SP, dest.Int32Value()); 2873 } else { 2874 UNIMPLEMENTED(FATAL) << "We only support Store() of size 4 and 8"; 2875 } 2876 } 2877 } 2878 2879 void Mips64Assembler::StoreRef(FrameOffset dest, ManagedRegister msrc) { 2880 Mips64ManagedRegister src = msrc.AsMips64(); 2881 CHECK(src.IsGpuRegister()); 2882 StoreToOffset(kStoreWord, src.AsGpuRegister(), SP, dest.Int32Value()); 2883 } 2884 2885 void Mips64Assembler::StoreRawPtr(FrameOffset dest, ManagedRegister msrc) { 2886 Mips64ManagedRegister src = msrc.AsMips64(); 2887 CHECK(src.IsGpuRegister()); 2888 StoreToOffset(kStoreDoubleword, src.AsGpuRegister(), SP, dest.Int32Value()); 2889 } 2890 2891 void Mips64Assembler::StoreImmediateToFrame(FrameOffset dest, uint32_t imm, 2892 ManagedRegister mscratch) { 2893 Mips64ManagedRegister scratch = mscratch.AsMips64(); 2894 CHECK(scratch.IsGpuRegister()) << scratch; 2895 LoadConst32(scratch.AsGpuRegister(), imm); 2896 StoreToOffset(kStoreWord, scratch.AsGpuRegister(), SP, dest.Int32Value()); 2897 } 2898 2899 void Mips64Assembler::StoreStackOffsetToThread(ThreadOffset64 thr_offs, 2900 FrameOffset fr_offs, 2901 ManagedRegister mscratch) { 2902 Mips64ManagedRegister scratch = mscratch.AsMips64(); 2903 CHECK(scratch.IsGpuRegister()) << scratch; 2904 Daddiu64(scratch.AsGpuRegister(), SP, fr_offs.Int32Value()); 2905 StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), S1, thr_offs.Int32Value()); 2906 } 2907 2908 void Mips64Assembler::StoreStackPointerToThread(ThreadOffset64 thr_offs) { 2909 StoreToOffset(kStoreDoubleword, SP, S1, thr_offs.Int32Value()); 2910 } 2911 2912 void Mips64Assembler::StoreSpanning(FrameOffset dest, ManagedRegister msrc, 2913 FrameOffset in_off, ManagedRegister mscratch) { 2914 Mips64ManagedRegister src = msrc.AsMips64(); 2915 Mips64ManagedRegister scratch = mscratch.AsMips64(); 2916 StoreToOffset(kStoreDoubleword, src.AsGpuRegister(), SP, dest.Int32Value()); 2917 LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(), SP, in_off.Int32Value()); 2918 StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, dest.Int32Value() + 8); 2919 } 2920 2921 void Mips64Assembler::Load(ManagedRegister mdest, FrameOffset src, size_t size) { 2922 return EmitLoad(mdest, SP, src.Int32Value(), size); 2923 } 2924 2925 void Mips64Assembler::LoadFromThread(ManagedRegister mdest, ThreadOffset64 src, size_t size) { 2926 return EmitLoad(mdest, S1, src.Int32Value(), size); 2927 } 2928 2929 void Mips64Assembler::LoadRef(ManagedRegister mdest, FrameOffset src) { 2930 Mips64ManagedRegister dest = mdest.AsMips64(); 2931 CHECK(dest.IsGpuRegister()); 2932 LoadFromOffset(kLoadUnsignedWord, dest.AsGpuRegister(), SP, src.Int32Value()); 2933 } 2934 2935 void Mips64Assembler::LoadRef(ManagedRegister mdest, ManagedRegister base, MemberOffset offs, 2936 bool unpoison_reference) { 2937 Mips64ManagedRegister dest = mdest.AsMips64(); 2938 CHECK(dest.IsGpuRegister() && base.AsMips64().IsGpuRegister()); 2939 LoadFromOffset(kLoadUnsignedWord, dest.AsGpuRegister(), 2940 base.AsMips64().AsGpuRegister(), offs.Int32Value()); 2941 if (unpoison_reference) { 2942 MaybeUnpoisonHeapReference(dest.AsGpuRegister()); 2943 } 2944 } 2945 2946 void Mips64Assembler::LoadRawPtr(ManagedRegister mdest, ManagedRegister base, 2947 Offset offs) { 2948 Mips64ManagedRegister dest = mdest.AsMips64(); 2949 CHECK(dest.IsGpuRegister() && base.AsMips64().IsGpuRegister()); 2950 LoadFromOffset(kLoadDoubleword, dest.AsGpuRegister(), 2951 base.AsMips64().AsGpuRegister(), offs.Int32Value()); 2952 } 2953 2954 void Mips64Assembler::LoadRawPtrFromThread(ManagedRegister mdest, ThreadOffset64 offs) { 2955 Mips64ManagedRegister dest = mdest.AsMips64(); 2956 CHECK(dest.IsGpuRegister()); 2957 LoadFromOffset(kLoadDoubleword, dest.AsGpuRegister(), S1, offs.Int32Value()); 2958 } 2959 2960 void Mips64Assembler::SignExtend(ManagedRegister mreg ATTRIBUTE_UNUSED, 2961 size_t size ATTRIBUTE_UNUSED) { 2962 UNIMPLEMENTED(FATAL) << "No sign extension necessary for MIPS64"; 2963 } 2964 2965 void Mips64Assembler::ZeroExtend(ManagedRegister mreg ATTRIBUTE_UNUSED, 2966 size_t size ATTRIBUTE_UNUSED) { 2967 UNIMPLEMENTED(FATAL) << "No zero extension necessary for MIPS64"; 2968 } 2969 2970 void Mips64Assembler::Move(ManagedRegister mdest, ManagedRegister msrc, size_t size) { 2971 Mips64ManagedRegister dest = mdest.AsMips64(); 2972 Mips64ManagedRegister src = msrc.AsMips64(); 2973 if (!dest.Equals(src)) { 2974 if (dest.IsGpuRegister()) { 2975 CHECK(src.IsGpuRegister()) << src; 2976 Move(dest.AsGpuRegister(), src.AsGpuRegister()); 2977 } else if (dest.IsFpuRegister()) { 2978 CHECK(src.IsFpuRegister()) << src; 2979 if (size == 4) { 2980 MovS(dest.AsFpuRegister(), src.AsFpuRegister()); 2981 } else if (size == 8) { 2982 MovD(dest.AsFpuRegister(), src.AsFpuRegister()); 2983 } else { 2984 UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8"; 2985 } 2986 } 2987 } 2988 } 2989 2990 void Mips64Assembler::CopyRef(FrameOffset dest, FrameOffset src, 2991 ManagedRegister mscratch) { 2992 Mips64ManagedRegister scratch = mscratch.AsMips64(); 2993 CHECK(scratch.IsGpuRegister()) << scratch; 2994 LoadFromOffset(kLoadWord, scratch.AsGpuRegister(), SP, src.Int32Value()); 2995 StoreToOffset(kStoreWord, scratch.AsGpuRegister(), SP, dest.Int32Value()); 2996 } 2997 2998 void Mips64Assembler::CopyRawPtrFromThread(FrameOffset fr_offs, 2999 ThreadOffset64 thr_offs, 3000 ManagedRegister mscratch) { 3001 Mips64ManagedRegister scratch = mscratch.AsMips64(); 3002 CHECK(scratch.IsGpuRegister()) << scratch; 3003 LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(), S1, thr_offs.Int32Value()); 3004 StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, fr_offs.Int32Value()); 3005 } 3006 3007 void Mips64Assembler::CopyRawPtrToThread(ThreadOffset64 thr_offs, 3008 FrameOffset fr_offs, 3009 ManagedRegister mscratch) { 3010 Mips64ManagedRegister scratch = mscratch.AsMips64(); 3011 CHECK(scratch.IsGpuRegister()) << scratch; 3012 LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(), 3013 SP, fr_offs.Int32Value()); 3014 StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), 3015 S1, thr_offs.Int32Value()); 3016 } 3017 3018 void Mips64Assembler::Copy(FrameOffset dest, FrameOffset src, 3019 ManagedRegister mscratch, size_t size) { 3020 Mips64ManagedRegister scratch = mscratch.AsMips64(); 3021 CHECK(scratch.IsGpuRegister()) << scratch; 3022 CHECK(size == 4 || size == 8) << size; 3023 if (size == 4) { 3024 LoadFromOffset(kLoadWord, scratch.AsGpuRegister(), SP, src.Int32Value()); 3025 StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, dest.Int32Value()); 3026 } else if (size == 8) { 3027 LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(), SP, src.Int32Value()); 3028 StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, dest.Int32Value()); 3029 } else { 3030 UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8"; 3031 } 3032 } 3033 3034 void Mips64Assembler::Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset, 3035 ManagedRegister mscratch, size_t size) { 3036 GpuRegister scratch = mscratch.AsMips64().AsGpuRegister(); 3037 CHECK(size == 4 || size == 8) << size; 3038 if (size == 4) { 3039 LoadFromOffset(kLoadWord, scratch, src_base.AsMips64().AsGpuRegister(), 3040 src_offset.Int32Value()); 3041 StoreToOffset(kStoreDoubleword, scratch, SP, dest.Int32Value()); 3042 } else if (size == 8) { 3043 LoadFromOffset(kLoadDoubleword, scratch, src_base.AsMips64().AsGpuRegister(), 3044 src_offset.Int32Value()); 3045 StoreToOffset(kStoreDoubleword, scratch, SP, dest.Int32Value()); 3046 } else { 3047 UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8"; 3048 } 3049 } 3050 3051 void Mips64Assembler::Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src, 3052 ManagedRegister mscratch, size_t size) { 3053 GpuRegister scratch = mscratch.AsMips64().AsGpuRegister(); 3054 CHECK(size == 4 || size == 8) << size; 3055 if (size == 4) { 3056 LoadFromOffset(kLoadWord, scratch, SP, src.Int32Value()); 3057 StoreToOffset(kStoreDoubleword, scratch, dest_base.AsMips64().AsGpuRegister(), 3058 dest_offset.Int32Value()); 3059 } else if (size == 8) { 3060 LoadFromOffset(kLoadDoubleword, scratch, SP, src.Int32Value()); 3061 StoreToOffset(kStoreDoubleword, scratch, dest_base.AsMips64().AsGpuRegister(), 3062 dest_offset.Int32Value()); 3063 } else { 3064 UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8"; 3065 } 3066 } 3067 3068 void Mips64Assembler::Copy(FrameOffset dest ATTRIBUTE_UNUSED, 3069 FrameOffset src_base ATTRIBUTE_UNUSED, 3070 Offset src_offset ATTRIBUTE_UNUSED, 3071 ManagedRegister mscratch ATTRIBUTE_UNUSED, 3072 size_t size ATTRIBUTE_UNUSED) { 3073 UNIMPLEMENTED(FATAL) << "No MIPS64 implementation"; 3074 } 3075 3076 void Mips64Assembler::Copy(ManagedRegister dest, Offset dest_offset, 3077 ManagedRegister src, Offset src_offset, 3078 ManagedRegister mscratch, size_t size) { 3079 GpuRegister scratch = mscratch.AsMips64().AsGpuRegister(); 3080 CHECK(size == 4 || size == 8) << size; 3081 if (size == 4) { 3082 LoadFromOffset(kLoadWord, scratch, src.AsMips64().AsGpuRegister(), src_offset.Int32Value()); 3083 StoreToOffset(kStoreDoubleword, scratch, dest.AsMips64().AsGpuRegister(), dest_offset.Int32Value()); 3084 } else if (size == 8) { 3085 LoadFromOffset(kLoadDoubleword, scratch, src.AsMips64().AsGpuRegister(), 3086 src_offset.Int32Value()); 3087 StoreToOffset(kStoreDoubleword, scratch, dest.AsMips64().AsGpuRegister(), 3088 dest_offset.Int32Value()); 3089 } else { 3090 UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8"; 3091 } 3092 } 3093 3094 void Mips64Assembler::Copy(FrameOffset dest ATTRIBUTE_UNUSED, 3095 Offset dest_offset ATTRIBUTE_UNUSED, 3096 FrameOffset src ATTRIBUTE_UNUSED, 3097 Offset src_offset ATTRIBUTE_UNUSED, 3098 ManagedRegister mscratch ATTRIBUTE_UNUSED, 3099 size_t size ATTRIBUTE_UNUSED) { 3100 UNIMPLEMENTED(FATAL) << "No MIPS64 implementation"; 3101 } 3102 3103 void Mips64Assembler::MemoryBarrier(ManagedRegister mreg ATTRIBUTE_UNUSED) { 3104 // TODO: sync? 3105 UNIMPLEMENTED(FATAL) << "No MIPS64 implementation"; 3106 } 3107 3108 void Mips64Assembler::CreateHandleScopeEntry(ManagedRegister mout_reg, 3109 FrameOffset handle_scope_offset, 3110 ManagedRegister min_reg, 3111 bool null_allowed) { 3112 Mips64ManagedRegister out_reg = mout_reg.AsMips64(); 3113 Mips64ManagedRegister in_reg = min_reg.AsMips64(); 3114 CHECK(in_reg.IsNoRegister() || in_reg.IsGpuRegister()) << in_reg; 3115 CHECK(out_reg.IsGpuRegister()) << out_reg; 3116 if (null_allowed) { 3117 Mips64Label null_arg; 3118 // Null values get a handle scope entry value of 0. Otherwise, the handle scope entry is 3119 // the address in the handle scope holding the reference. 3120 // e.g. out_reg = (handle == 0) ? 0 : (SP+handle_offset) 3121 if (in_reg.IsNoRegister()) { 3122 LoadFromOffset(kLoadUnsignedWord, out_reg.AsGpuRegister(), 3123 SP, handle_scope_offset.Int32Value()); 3124 in_reg = out_reg; 3125 } 3126 if (!out_reg.Equals(in_reg)) { 3127 LoadConst32(out_reg.AsGpuRegister(), 0); 3128 } 3129 Beqzc(in_reg.AsGpuRegister(), &null_arg); 3130 Daddiu64(out_reg.AsGpuRegister(), SP, handle_scope_offset.Int32Value()); 3131 Bind(&null_arg); 3132 } else { 3133 Daddiu64(out_reg.AsGpuRegister(), SP, handle_scope_offset.Int32Value()); 3134 } 3135 } 3136 3137 void Mips64Assembler::CreateHandleScopeEntry(FrameOffset out_off, 3138 FrameOffset handle_scope_offset, 3139 ManagedRegister mscratch, 3140 bool null_allowed) { 3141 Mips64ManagedRegister scratch = mscratch.AsMips64(); 3142 CHECK(scratch.IsGpuRegister()) << scratch; 3143 if (null_allowed) { 3144 Mips64Label null_arg; 3145 LoadFromOffset(kLoadUnsignedWord, scratch.AsGpuRegister(), SP, 3146 handle_scope_offset.Int32Value()); 3147 // Null values get a handle scope entry value of 0. Otherwise, the handle scope entry is 3148 // the address in the handle scope holding the reference. 3149 // e.g. scratch = (scratch == 0) ? 0 : (SP+handle_scope_offset) 3150 Beqzc(scratch.AsGpuRegister(), &null_arg); 3151 Daddiu64(scratch.AsGpuRegister(), SP, handle_scope_offset.Int32Value()); 3152 Bind(&null_arg); 3153 } else { 3154 Daddiu64(scratch.AsGpuRegister(), SP, handle_scope_offset.Int32Value()); 3155 } 3156 StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, out_off.Int32Value()); 3157 } 3158 3159 // Given a handle scope entry, load the associated reference. 3160 void Mips64Assembler::LoadReferenceFromHandleScope(ManagedRegister mout_reg, 3161 ManagedRegister min_reg) { 3162 Mips64ManagedRegister out_reg = mout_reg.AsMips64(); 3163 Mips64ManagedRegister in_reg = min_reg.AsMips64(); 3164 CHECK(out_reg.IsGpuRegister()) << out_reg; 3165 CHECK(in_reg.IsGpuRegister()) << in_reg; 3166 Mips64Label null_arg; 3167 if (!out_reg.Equals(in_reg)) { 3168 LoadConst32(out_reg.AsGpuRegister(), 0); 3169 } 3170 Beqzc(in_reg.AsGpuRegister(), &null_arg); 3171 LoadFromOffset(kLoadDoubleword, out_reg.AsGpuRegister(), 3172 in_reg.AsGpuRegister(), 0); 3173 Bind(&null_arg); 3174 } 3175 3176 void Mips64Assembler::VerifyObject(ManagedRegister src ATTRIBUTE_UNUSED, 3177 bool could_be_null ATTRIBUTE_UNUSED) { 3178 // TODO: not validating references 3179 } 3180 3181 void Mips64Assembler::VerifyObject(FrameOffset src ATTRIBUTE_UNUSED, 3182 bool could_be_null ATTRIBUTE_UNUSED) { 3183 // TODO: not validating references 3184 } 3185 3186 void Mips64Assembler::Call(ManagedRegister mbase, Offset offset, ManagedRegister mscratch) { 3187 Mips64ManagedRegister base = mbase.AsMips64(); 3188 Mips64ManagedRegister scratch = mscratch.AsMips64(); 3189 CHECK(base.IsGpuRegister()) << base; 3190 CHECK(scratch.IsGpuRegister()) << scratch; 3191 LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(), 3192 base.AsGpuRegister(), offset.Int32Value()); 3193 Jalr(scratch.AsGpuRegister()); 3194 Nop(); 3195 // TODO: place reference map on call 3196 } 3197 3198 void Mips64Assembler::Call(FrameOffset base, Offset offset, ManagedRegister mscratch) { 3199 Mips64ManagedRegister scratch = mscratch.AsMips64(); 3200 CHECK(scratch.IsGpuRegister()) << scratch; 3201 // Call *(*(SP + base) + offset) 3202 LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(), 3203 SP, base.Int32Value()); 3204 LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(), 3205 scratch.AsGpuRegister(), offset.Int32Value()); 3206 Jalr(scratch.AsGpuRegister()); 3207 Nop(); 3208 // TODO: place reference map on call 3209 } 3210 3211 void Mips64Assembler::CallFromThread(ThreadOffset64 offset ATTRIBUTE_UNUSED, 3212 ManagedRegister mscratch ATTRIBUTE_UNUSED) { 3213 UNIMPLEMENTED(FATAL) << "No MIPS64 implementation"; 3214 } 3215 3216 void Mips64Assembler::GetCurrentThread(ManagedRegister tr) { 3217 Move(tr.AsMips64().AsGpuRegister(), S1); 3218 } 3219 3220 void Mips64Assembler::GetCurrentThread(FrameOffset offset, 3221 ManagedRegister mscratch ATTRIBUTE_UNUSED) { 3222 StoreToOffset(kStoreDoubleword, S1, SP, offset.Int32Value()); 3223 } 3224 3225 void Mips64Assembler::ExceptionPoll(ManagedRegister mscratch, size_t stack_adjust) { 3226 Mips64ManagedRegister scratch = mscratch.AsMips64(); 3227 exception_blocks_.emplace_back(scratch, stack_adjust); 3228 LoadFromOffset(kLoadDoubleword, 3229 scratch.AsGpuRegister(), 3230 S1, 3231 Thread::ExceptionOffset<kMips64PointerSize>().Int32Value()); 3232 Bnezc(scratch.AsGpuRegister(), exception_blocks_.back().Entry()); 3233 } 3234 3235 void Mips64Assembler::EmitExceptionPoll(Mips64ExceptionSlowPath* exception) { 3236 Bind(exception->Entry()); 3237 if (exception->stack_adjust_ != 0) { // Fix up the frame. 3238 DecreaseFrameSize(exception->stack_adjust_); 3239 } 3240 // Pass exception object as argument. 3241 // Don't care about preserving A0 as this call won't return. 3242 CheckEntrypointTypes<kQuickDeliverException, void, mirror::Object*>(); 3243 Move(A0, exception->scratch_.AsGpuRegister()); 3244 // Set up call to Thread::Current()->pDeliverException 3245 LoadFromOffset(kLoadDoubleword, 3246 T9, 3247 S1, 3248 QUICK_ENTRYPOINT_OFFSET(kMips64PointerSize, pDeliverException).Int32Value()); 3249 Jr(T9); 3250 Nop(); 3251 3252 // Call never returns 3253 Break(); 3254 } 3255 3256 } // namespace mips64 3257 } // namespace art 3258