MacroAssembler-mips64-inl.h (31252B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef jit_mips64_MacroAssembler_mips64_inl_h 8 #define jit_mips64_MacroAssembler_mips64_inl_h 9 10 #include "jit/mips64/MacroAssembler-mips64.h" 11 12 #include "vm/BigIntType.h" // JS::BigInt 13 14 #include "jit/mips-shared/MacroAssembler-mips-shared-inl.h" 15 16 namespace js { 17 namespace jit { 18 19 //{{{ check_macroassembler_style 20 21 void MacroAssembler::move64(Register64 src, Register64 dest) { 22 movePtr(src.reg, dest.reg); 23 } 24 25 void MacroAssembler::move64(Imm64 imm, Register64 dest) { 26 movePtr(ImmWord(imm.value), dest.reg); 27 } 28 29 void MacroAssembler::moveDoubleToGPR64(FloatRegister src, Register64 dest) { 30 moveFromDouble(src, dest.reg); 31 } 32 33 void MacroAssembler::moveGPR64ToDouble(Register64 src, FloatRegister dest) { 34 moveToDouble(src.reg, dest); 35 } 36 37 void MacroAssembler::move64To32(Register64 src, Register dest) { 38 ma_sll(dest, src.reg, Imm32(0)); 39 } 40 41 void MacroAssembler::move32To64ZeroExtend(Register src, Register64 dest) { 42 ma_dext(dest.reg, src, Imm32(0), Imm32(32)); 43 } 44 45 void MacroAssembler::move8To64SignExtend(Register src, Register64 dest) { 46 move32To64SignExtend(src, dest); 47 move8SignExtend(dest.reg, dest.reg); 48 } 49 50 void MacroAssembler::move16To64SignExtend(Register src, Register64 dest) { 51 move32To64SignExtend(src, dest); 52 move16SignExtend(dest.reg, dest.reg); 53 } 54 55 void MacroAssembler::move32To64SignExtend(Register src, Register64 dest) { 56 ma_sll(dest.reg, src, Imm32(0)); 57 } 58 59 void MacroAssembler::move8SignExtendToPtr(Register src, Register dest) { 60 move8To64SignExtend(src, Register64(dest)); 61 } 62 63 void MacroAssembler::move16SignExtendToPtr(Register src, Register dest) { 64 move16To64SignExtend(src, Register64(dest)); 65 } 66 67 void MacroAssembler::move32SignExtendToPtr(Register src, Register dest) { 68 ma_sll(dest, src, Imm32(0)); 69 } 70 71 void MacroAssembler::move32ZeroExtendToPtr(Register src, Register dest) { 72 ma_dext(dest, src, Imm32(0), Imm32(32)); 73 } 74 75 // =============================================================== 76 // Load instructions 77 78 void MacroAssembler::load32SignExtendToPtr(const Address& src, Register dest) { 79 load32(src, dest); 80 } 81 82 // =============================================================== 83 // Logical instructions 84 85 void MacroAssembler::notPtr(Register reg) { ma_not(reg, reg); } 86 87 void MacroAssembler::andPtr(Register src, Register dest) { ma_and(dest, src); } 88 89 void MacroAssembler::andPtr(Imm32 imm, Register dest) { ma_and(dest, imm); } 90 91 void MacroAssembler::andPtr(Imm32 imm, Register src, Register dest) { 92 ma_and(dest, src, imm); 93 } 94 95 void MacroAssembler::and64(Imm64 imm, Register64 dest) { 96 UseScratchRegisterScope temps(*this); 97 Register scratch = temps.Acquire(); 98 ma_li(scratch, ImmWord(imm.value)); 99 ma_and(dest.reg, scratch); 100 } 101 102 void MacroAssembler::and64(Register64 src, Register64 dest) { 103 ma_and(dest.reg, src.reg); 104 } 105 106 void MacroAssembler::or64(Imm64 imm, Register64 dest) { 107 UseScratchRegisterScope temps(*this); 108 Register scratch = temps.Acquire(); 109 ma_li(scratch, ImmWord(imm.value)); 110 ma_or(dest.reg, scratch); 111 } 112 113 void MacroAssembler::xor64(Imm64 imm, Register64 dest) { 114 UseScratchRegisterScope temps(*this); 115 Register scratch = temps.Acquire(); 116 ma_li(scratch, ImmWord(imm.value)); 117 ma_xor(dest.reg, scratch); 118 } 119 120 void MacroAssembler::orPtr(Register src, Register dest) { ma_or(dest, src); } 121 122 void MacroAssembler::orPtr(Imm32 imm, Register dest) { ma_or(dest, imm); } 123 124 void MacroAssembler::orPtr(Imm32 imm, Register src, Register dest) { 125 ma_or(dest, src, imm); 126 } 127 128 void MacroAssembler::or64(Register64 src, Register64 dest) { 129 ma_or(dest.reg, src.reg); 130 } 131 132 void MacroAssembler::xor64(Register64 src, Register64 dest) { 133 ma_xor(dest.reg, src.reg); 134 } 135 136 void MacroAssembler::xorPtr(Register src, Register dest) { ma_xor(dest, src); } 137 138 void MacroAssembler::xorPtr(Imm32 imm, Register dest) { ma_xor(dest, imm); } 139 140 void MacroAssembler::xorPtr(Imm32 imm, Register src, Register dest) { 141 ma_xor(dest, src, imm); 142 } 143 144 // =============================================================== 145 // Swap instructions 146 147 void MacroAssembler::byteSwap64(Register64 reg64) { 148 Register reg = reg64.reg; 149 ma_dsbh(reg, reg); 150 ma_dshd(reg, reg); 151 } 152 153 // =============================================================== 154 // Arithmetic functions 155 156 void MacroAssembler::addPtr(Register src, Register dest) { 157 ma_daddu(dest, src); 158 } 159 160 void MacroAssembler::addPtr(Imm32 imm, Register dest) { ma_daddu(dest, imm); } 161 162 void MacroAssembler::addPtr(ImmWord imm, Register dest) { 163 UseScratchRegisterScope temps(*this); 164 Register scratch = temps.Acquire(); 165 movePtr(imm, scratch); 166 addPtr(scratch, dest); 167 } 168 169 void MacroAssembler::add64(Register64 src, Register64 dest) { 170 addPtr(src.reg, dest.reg); 171 } 172 173 void MacroAssembler::add64(Imm32 imm, Register64 dest) { 174 ma_daddu(dest.reg, imm); 175 } 176 177 void MacroAssembler::add64(Imm64 imm, Register64 dest) { 178 UseScratchRegisterScope temps(*this); 179 Register scratch = temps.Acquire(); 180 mov(ImmWord(imm.value), scratch); 181 ma_daddu(dest.reg, scratch); 182 } 183 184 CodeOffset MacroAssembler::sub32FromStackPtrWithPatch(Register dest) { 185 CodeOffset offset = CodeOffset(currentOffset()); 186 ma_liPatchable(dest, Imm32(0)); 187 as_dsubu(dest, StackPointer, dest); 188 return offset; 189 } 190 191 void MacroAssembler::patchSub32FromStackPtr(CodeOffset offset, Imm32 imm) { 192 Instruction* lui = 193 (Instruction*)m_buffer.getInst(BufferOffset(offset.offset())); 194 Instruction* ori = 195 (Instruction*)m_buffer.getInst(BufferOffset(offset.offset() + 4)); 196 197 MOZ_ASSERT(lui->extractOpcode() == ((uint32_t)op_lui >> OpcodeShift)); 198 MOZ_ASSERT(ori->extractOpcode() == ((uint32_t)op_ori >> OpcodeShift)); 199 200 MacroAssemblerMIPSShared::UpdateLuiOriValue(lui, ori, imm.value); 201 } 202 203 void MacroAssembler::subPtr(Register src, Register dest) { 204 as_dsubu(dest, dest, src); 205 } 206 207 void MacroAssembler::subPtr(Imm32 imm, Register dest) { 208 ma_dsubu(dest, dest, imm); 209 } 210 211 void MacroAssembler::sub64(Register64 src, Register64 dest) { 212 as_dsubu(dest.reg, dest.reg, src.reg); 213 } 214 215 void MacroAssembler::sub64(Imm64 imm, Register64 dest) { 216 UseScratchRegisterScope temps(*this); 217 Register scratch = temps.Acquire(); 218 mov(ImmWord(imm.value), scratch); 219 as_dsubu(dest.reg, dest.reg, scratch); 220 } 221 222 void MacroAssembler::mulHighUnsigned32(Imm32 imm, Register src, Register dest) { 223 UseScratchRegisterScope temps(*this); 224 Register scratch = temps.Acquire(); 225 MOZ_ASSERT(src != scratch); 226 move32(imm, scratch); 227 #ifdef MIPSR6 228 as_muhu(dest, src, scratch); 229 #else 230 as_multu(src, scratch); 231 as_mfhi(dest); 232 #endif 233 } 234 235 void MacroAssembler::mulPtr(Register rhs, Register srcDest) { 236 #ifdef MIPSR6 237 as_dmulu(srcDest, srcDest, rhs); 238 #else 239 as_dmultu(srcDest, rhs); 240 as_mflo(srcDest); 241 #endif 242 } 243 244 void MacroAssembler::mulPtr(ImmWord rhs, Register srcDest) { 245 UseScratchRegisterScope temps(*this); 246 Register scratch = temps.Acquire(); 247 MOZ_ASSERT(srcDest != scratch); 248 mov(rhs, scratch); 249 mulPtr(scratch, srcDest); 250 } 251 252 void MacroAssembler::mul64(Imm64 imm, const Register64& dest) { 253 UseScratchRegisterScope temps(*this); 254 Register scratch = temps.Acquire(); 255 mov(ImmWord(imm.value), scratch); 256 #ifdef MIPSR6 257 as_dmulu(dest.reg, scratch, dest.reg); 258 #else 259 as_dmultu(dest.reg, scratch); 260 as_mflo(dest.reg); 261 #endif 262 } 263 264 void MacroAssembler::mul64(Imm64 imm, const Register64& dest, 265 const Register temp) { 266 MOZ_ASSERT(temp == InvalidReg); 267 mul64(imm, dest); 268 } 269 270 void MacroAssembler::mul64(const Register64& src, const Register64& dest, 271 const Register temp) { 272 MOZ_ASSERT(temp == InvalidReg); 273 #ifdef MIPSR6 274 as_dmulu(dest.reg, src.reg, dest.reg); 275 #else 276 as_dmultu(dest.reg, src.reg); 277 as_mflo(dest.reg); 278 #endif 279 } 280 281 void MacroAssembler::mulBy3(Register src, Register dest) { 282 UseScratchRegisterScope temps(*this); 283 Register scratch = temps.Acquire(); 284 MOZ_ASSERT(src != scratch); 285 as_daddu(scratch, src, src); 286 as_daddu(dest, scratch, src); 287 } 288 289 void MacroAssembler::inc64(AbsoluteAddress dest) { 290 UseScratchRegisterScope temps(*this); 291 Register scratch = temps.Acquire(); 292 Register scratch2 = temps.Acquire(); 293 ma_li(scratch, ImmWord(uintptr_t(dest.addr))); 294 as_ld(scratch2, scratch, 0); 295 as_daddiu(scratch2, scratch2, 1); 296 as_sd(scratch2, scratch, 0); 297 } 298 299 void MacroAssembler::quotient64(Register lhs, Register rhs, Register dest, 300 bool isUnsigned) { 301 #ifdef MIPSR6 302 if (isUnsigned) { 303 as_ddivu(dest, lhs, rhs); 304 } else { 305 as_ddiv(dest, lhs, rhs); 306 } 307 #else 308 if (isUnsigned) { 309 as_ddivu(lhs, rhs); 310 } else { 311 as_ddiv(lhs, rhs); 312 } 313 as_mflo(dest); 314 #endif 315 } 316 317 void MacroAssembler::remainder64(Register lhs, Register rhs, Register dest, 318 bool isUnsigned) { 319 #ifdef MIPSR6 320 if (isUnsigned) { 321 as_dmodu(dest, lhs, rhs); 322 } else { 323 as_dmod(dest, lhs, rhs); 324 } 325 #else 326 if (isUnsigned) { 327 as_ddivu(lhs, rhs); 328 } else { 329 as_ddiv(lhs, rhs); 330 } 331 as_mfhi(dest); 332 #endif 333 } 334 335 void MacroAssembler::neg64(Register64 reg) { as_dsubu(reg.reg, zero, reg.reg); } 336 337 void MacroAssembler::negPtr(Register reg) { as_dsubu(reg, zero, reg); } 338 339 // =============================================================== 340 // Shift functions 341 342 void MacroAssembler::lshiftPtr(Imm32 imm, Register dest) { 343 lshiftPtr(imm, dest, dest); 344 } 345 346 void MacroAssembler::lshiftPtr(Imm32 imm, Register src, Register dest) { 347 MOZ_ASSERT(0 <= imm.value && imm.value < 64); 348 ma_dsll(dest, src, imm); 349 } 350 351 void MacroAssembler::lshiftPtr(Register shift, Register dest) { 352 ma_dsll(dest, dest, shift); 353 } 354 355 void MacroAssembler::lshift64(Imm32 imm, Register64 dest) { 356 MOZ_ASSERT(0 <= imm.value && imm.value < 64); 357 ma_dsll(dest.reg, dest.reg, imm); 358 } 359 360 void MacroAssembler::lshift64(Register shift, Register64 dest) { 361 ma_dsll(dest.reg, dest.reg, shift); 362 } 363 364 void MacroAssembler::rshiftPtr(Imm32 imm, Register dest) { 365 rshiftPtr(imm, dest, dest); 366 } 367 368 void MacroAssembler::rshiftPtr(Imm32 imm, Register src, Register dest) { 369 MOZ_ASSERT(0 <= imm.value && imm.value < 64); 370 ma_dsrl(dest, src, imm); 371 } 372 373 void MacroAssembler::rshiftPtr(Register shift, Register dest) { 374 ma_dsrl(dest, dest, shift); 375 } 376 377 void MacroAssembler::rshift64(Imm32 imm, Register64 dest) { 378 MOZ_ASSERT(0 <= imm.value && imm.value < 64); 379 ma_dsrl(dest.reg, dest.reg, imm); 380 } 381 382 void MacroAssembler::rshift64(Register shift, Register64 dest) { 383 ma_dsrl(dest.reg, dest.reg, shift); 384 } 385 386 void MacroAssembler::rshiftPtrArithmetic(Imm32 imm, Register dest) { 387 rshiftPtrArithmetic(imm, dest, dest); 388 } 389 390 void MacroAssembler::rshiftPtrArithmetic(Imm32 imm, Register src, 391 Register dest) { 392 MOZ_ASSERT(0 <= imm.value && imm.value < 64); 393 ma_dsra(dest, src, imm); 394 } 395 396 void MacroAssembler::rshiftPtrArithmetic(Register shift, Register dest) { 397 ma_dsra(dest, dest, shift); 398 } 399 400 void MacroAssembler::rshift64Arithmetic(Imm32 imm, Register64 dest) { 401 MOZ_ASSERT(0 <= imm.value && imm.value < 64); 402 ma_dsra(dest.reg, dest.reg, imm); 403 } 404 405 void MacroAssembler::rshift64Arithmetic(Register shift, Register64 dest) { 406 ma_dsra(dest.reg, dest.reg, shift); 407 } 408 409 // =============================================================== 410 // Rotation functions 411 412 void MacroAssembler::rotateLeft64(Imm32 count, Register64 src, Register64 dest, 413 Register temp) { 414 MOZ_ASSERT(temp == InvalidReg); 415 416 if (count.value) { 417 ma_drol(dest.reg, src.reg, count); 418 } else { 419 ma_move(dest.reg, src.reg); 420 } 421 } 422 423 void MacroAssembler::rotateLeft64(Register count, Register64 src, 424 Register64 dest, Register temp) { 425 MOZ_ASSERT(temp == InvalidReg); 426 ma_drol(dest.reg, src.reg, count); 427 } 428 429 void MacroAssembler::rotateRight64(Imm32 count, Register64 src, Register64 dest, 430 Register temp) { 431 MOZ_ASSERT(temp == InvalidReg); 432 433 if (count.value) { 434 ma_dror(dest.reg, src.reg, count); 435 } else { 436 ma_move(dest.reg, src.reg); 437 } 438 } 439 440 void MacroAssembler::rotateRight64(Register count, Register64 src, 441 Register64 dest, Register temp) { 442 MOZ_ASSERT(temp == InvalidReg); 443 ma_dror(dest.reg, src.reg, count); 444 } 445 446 // =============================================================== 447 // Condition functions 448 449 template <typename T1, typename T2> 450 void MacroAssembler::cmpPtrSet(Condition cond, T1 lhs, T2 rhs, Register dest) { 451 ma_cmp_set(dest, lhs, rhs, cond); 452 } 453 454 // Also see below for specializations of cmpPtrSet. 455 456 template <typename T1, typename T2> 457 void MacroAssembler::cmp32Set(Condition cond, T1 lhs, T2 rhs, Register dest) { 458 ma_cmp_set(dest, lhs, rhs, cond); 459 } 460 461 void MacroAssembler::cmp64Set(Condition cond, Register64 lhs, Register64 rhs, 462 Register dest) { 463 ma_cmp_set(dest, lhs.reg, rhs.reg, cond); 464 } 465 466 void MacroAssembler::cmp64Set(Condition cond, Register64 lhs, Imm64 rhs, 467 Register dest) { 468 ma_cmp_set(dest, lhs.reg, ImmWord(uint64_t(rhs.value)), cond); 469 } 470 471 void MacroAssembler::cmp64Set(Condition cond, Address lhs, Register64 rhs, 472 Register dest) { 473 ma_cmp_set(dest, lhs, rhs.reg, cond); 474 } 475 476 void MacroAssembler::cmp64Set(Condition cond, Address lhs, Imm64 rhs, 477 Register dest) { 478 ma_cmp_set(dest, lhs, ImmWord(uint64_t(rhs.value)), cond); 479 } 480 481 // =============================================================== 482 // Bit counting functions 483 484 void MacroAssembler::clz64(Register64 src, Register64 dest) { 485 as_dclz(dest.reg, src.reg); 486 } 487 488 void MacroAssembler::ctz64(Register64 src, Register64 dest) { 489 ma_dctz(dest.reg, src.reg); 490 } 491 492 void MacroAssembler::popcnt64(Register64 input, Register64 output, 493 Register tmp) { 494 UseScratchRegisterScope temps(*this); 495 Register scratch = temps.Acquire(); 496 ma_move(output.reg, input.reg); 497 ma_dsra(tmp, input.reg, Imm32(1)); 498 ma_li(scratch, ImmWord(0x5555555555555555UL)); 499 ma_and(tmp, scratch); 500 ma_dsubu(output.reg, tmp); 501 ma_dsra(tmp, output.reg, Imm32(2)); 502 ma_li(scratch, ImmWord(0x3333333333333333UL)); 503 ma_and(output.reg, scratch); 504 ma_and(tmp, scratch); 505 ma_daddu(output.reg, tmp); 506 ma_dsrl(tmp, output.reg, Imm32(4)); 507 ma_daddu(output.reg, tmp); 508 ma_li(scratch, ImmWord(0xF0F0F0F0F0F0F0FUL)); 509 ma_and(output.reg, scratch); 510 ma_dsll(tmp, output.reg, Imm32(8)); 511 ma_daddu(output.reg, tmp); 512 ma_dsll(tmp, output.reg, Imm32(16)); 513 ma_daddu(output.reg, tmp); 514 ma_dsll(tmp, output.reg, Imm32(32)); 515 ma_daddu(output.reg, tmp); 516 ma_dsra(output.reg, output.reg, Imm32(56)); 517 } 518 519 // =============================================================== 520 // Branch functions 521 522 void MacroAssembler::branch64(Condition cond, Register64 lhs, Imm64 val, 523 Label* success, Label* fail) { 524 MOZ_ASSERT(cond == Assembler::NotEqual || cond == Assembler::Equal || 525 cond == Assembler::LessThan || 526 cond == Assembler::LessThanOrEqual || 527 cond == Assembler::GreaterThan || 528 cond == Assembler::GreaterThanOrEqual || 529 cond == Assembler::Below || cond == Assembler::BelowOrEqual || 530 cond == Assembler::Above || cond == Assembler::AboveOrEqual, 531 "other condition codes not supported"); 532 533 branchPtr(cond, lhs.reg, ImmWord(val.value), success); 534 if (fail) { 535 jump(fail); 536 } 537 } 538 539 void MacroAssembler::branch64(Condition cond, Register64 lhs, Register64 rhs, 540 Label* success, Label* fail) { 541 MOZ_ASSERT(cond == Assembler::NotEqual || cond == Assembler::Equal || 542 cond == Assembler::LessThan || 543 cond == Assembler::LessThanOrEqual || 544 cond == Assembler::GreaterThan || 545 cond == Assembler::GreaterThanOrEqual || 546 cond == Assembler::Below || cond == Assembler::BelowOrEqual || 547 cond == Assembler::Above || cond == Assembler::AboveOrEqual, 548 "other condition codes not supported"); 549 550 branchPtr(cond, lhs.reg, rhs.reg, success); 551 if (fail) { 552 jump(fail); 553 } 554 } 555 556 void MacroAssembler::branch64(Condition cond, const Address& lhs, Imm64 val, 557 Label* success, Label* fail) { 558 MOZ_ASSERT(cond == Assembler::NotEqual || cond == Assembler::Equal || 559 cond == Assembler::LessThan || 560 cond == Assembler::LessThanOrEqual || 561 cond == Assembler::GreaterThan || 562 cond == Assembler::GreaterThanOrEqual || 563 cond == Assembler::Below || cond == Assembler::BelowOrEqual || 564 cond == Assembler::Above || cond == Assembler::AboveOrEqual, 565 "other condition codes not supported"); 566 567 branchPtr(cond, lhs, ImmWord(val.value), success); 568 if (fail) { 569 jump(fail); 570 } 571 } 572 573 void MacroAssembler::branch64(Condition cond, const Address& lhs, 574 Register64 rhs, Label* success, Label* fail) { 575 MOZ_ASSERT(cond == Assembler::NotEqual || cond == Assembler::Equal || 576 cond == Assembler::LessThan || 577 cond == Assembler::LessThanOrEqual || 578 cond == Assembler::GreaterThan || 579 cond == Assembler::GreaterThanOrEqual || 580 cond == Assembler::Below || cond == Assembler::BelowOrEqual || 581 cond == Assembler::Above || cond == Assembler::AboveOrEqual, 582 "other condition codes not supported"); 583 584 branchPtr(cond, lhs, rhs.reg, success); 585 if (fail) { 586 jump(fail); 587 } 588 } 589 590 void MacroAssembler::branch64(Condition cond, const Address& lhs, 591 const Address& rhs, Register scratch, 592 Label* label) { 593 MOZ_ASSERT(cond == Assembler::NotEqual || cond == Assembler::Equal, 594 "other condition codes not supported"); 595 MOZ_ASSERT(lhs.base != scratch); 596 MOZ_ASSERT(rhs.base != scratch); 597 598 loadPtr(rhs, scratch); 599 branchPtr(cond, lhs, scratch, label); 600 } 601 602 void MacroAssembler::branchPrivatePtr(Condition cond, const Address& lhs, 603 Register rhs, Label* label) { 604 branchPtr(cond, lhs, rhs, label); 605 } 606 607 void MacroAssembler::branchTest64(Condition cond, Register64 lhs, 608 Register64 rhs, Register temp, Label* success, 609 Label* fail) { 610 branchTestPtr(cond, lhs.reg, rhs.reg, success); 611 if (fail) { 612 jump(fail); 613 } 614 } 615 616 void MacroAssembler::branchTest64(Condition cond, Register64 lhs, Imm64 rhs, 617 Label* success, Label* fail) { 618 branchTestPtr(cond, lhs.reg, ImmWord(rhs.value), success); 619 if (fail) { 620 jump(fail); 621 } 622 } 623 624 void MacroAssembler::branchTestUndefined(Condition cond, 625 const ValueOperand& value, 626 Label* label) { 627 UseScratchRegisterScope temps(*this); 628 Register scratch2 = temps.Acquire(); 629 splitTag(value, scratch2); 630 branchTestUndefined(cond, scratch2, label); 631 } 632 633 void MacroAssembler::branchTestInt32(Condition cond, const ValueOperand& value, 634 Label* label) { 635 UseScratchRegisterScope temps(*this); 636 Register scratch2 = temps.Acquire(); 637 splitTag(value, scratch2); 638 branchTestInt32(cond, scratch2, label); 639 } 640 641 void MacroAssembler::branchTestInt32Truthy(bool b, const ValueOperand& value, 642 Label* label) { 643 UseScratchRegisterScope temps(*this); 644 Register scratch = temps.Acquire(); 645 ma_dext(scratch, value.valueReg(), Imm32(0), Imm32(32)); 646 ma_b(scratch, scratch, label, b ? NonZero : Zero); 647 } 648 649 void MacroAssembler::branchTestDouble(Condition cond, Register tag, 650 Label* label) { 651 MOZ_ASSERT(cond == Equal || cond == NotEqual); 652 Condition actual = (cond == Equal) ? BelowOrEqual : Above; 653 ma_b(tag, ImmTag(JSVAL_TAG_MAX_DOUBLE), label, actual); 654 } 655 656 void MacroAssembler::branchTestDouble(Condition cond, const ValueOperand& value, 657 Label* label) { 658 UseScratchRegisterScope temps(*this); 659 Register scratch2 = temps.Acquire(); 660 splitTag(value, scratch2); 661 branchTestDouble(cond, scratch2, label); 662 } 663 664 void MacroAssembler::branchTestNumber(Condition cond, const ValueOperand& value, 665 Label* label) { 666 UseScratchRegisterScope temps(*this); 667 Register scratch2 = temps.Acquire(); 668 splitTag(value, scratch2); 669 branchTestNumber(cond, scratch2, label); 670 } 671 672 void MacroAssembler::branchTestBoolean(Condition cond, 673 const ValueOperand& value, 674 Label* label) { 675 UseScratchRegisterScope temps(*this); 676 Register scratch2 = temps.Acquire(); 677 splitTag(value, scratch2); 678 branchTestBoolean(cond, scratch2, label); 679 } 680 681 void MacroAssembler::branchTestBooleanTruthy(bool b, const ValueOperand& value, 682 Label* label) { 683 UseScratchRegisterScope temps(*this); 684 Register scratch2 = temps.Acquire(); 685 unboxBoolean(value, scratch2); 686 ma_b(scratch2, scratch2, label, b ? NonZero : Zero); 687 } 688 689 void MacroAssembler::branchTestString(Condition cond, const ValueOperand& value, 690 Label* label) { 691 UseScratchRegisterScope temps(*this); 692 Register scratch2 = temps.Acquire(); 693 splitTag(value, scratch2); 694 branchTestString(cond, scratch2, label); 695 } 696 697 void MacroAssembler::branchTestStringTruthy(bool b, const ValueOperand& value, 698 Label* label) { 699 UseScratchRegisterScope temps(*this); 700 Register scratch2 = temps.Acquire(); 701 unboxString(value, scratch2); 702 load32(Address(scratch2, JSString::offsetOfLength()), scratch2); 703 ma_b(scratch2, Imm32(0), label, b ? NotEqual : Equal); 704 } 705 706 void MacroAssembler::branchTestSymbol(Condition cond, const ValueOperand& value, 707 Label* label) { 708 UseScratchRegisterScope temps(*this); 709 Register scratch2 = temps.Acquire(); 710 splitTag(value, scratch2); 711 branchTestSymbol(cond, scratch2, label); 712 } 713 714 void MacroAssembler::branchTestBigInt(Condition cond, const BaseIndex& address, 715 Label* label) { 716 UseScratchRegisterScope temps(*this); 717 Register scratch2 = temps.Acquire(); 718 computeEffectiveAddress(address, scratch2); 719 splitTag(scratch2, scratch2); 720 branchTestBigInt(cond, scratch2, label); 721 } 722 723 void MacroAssembler::branchTestBigInt(Condition cond, const ValueOperand& value, 724 Label* label) { 725 UseScratchRegisterScope temps(*this); 726 Register scratch2 = temps.Acquire(); 727 splitTag(value, scratch2); 728 branchTestBigInt(cond, scratch2, label); 729 } 730 731 void MacroAssembler::branchTestBigIntTruthy(bool b, const ValueOperand& value, 732 Label* label) { 733 UseScratchRegisterScope temps(*this); 734 Register scratch2 = temps.Acquire(); 735 unboxBigInt(value, scratch2); 736 load32(Address(scratch2, BigInt::offsetOfDigitLength()), scratch2); 737 ma_b(scratch2, Imm32(0), label, b ? NotEqual : Equal); 738 } 739 740 void MacroAssembler::branchTestNull(Condition cond, const ValueOperand& value, 741 Label* label) { 742 UseScratchRegisterScope temps(*this); 743 Register scratch2 = temps.Acquire(); 744 splitTag(value, scratch2); 745 branchTestNull(cond, scratch2, label); 746 } 747 748 void MacroAssembler::branchTestObject(Condition cond, const ValueOperand& value, 749 Label* label) { 750 UseScratchRegisterScope temps(*this); 751 Register scratch2 = temps.Acquire(); 752 splitTag(value, scratch2); 753 branchTestObject(cond, scratch2, label); 754 } 755 756 void MacroAssembler::branchTestPrimitive(Condition cond, 757 const ValueOperand& value, 758 Label* label) { 759 UseScratchRegisterScope temps(*this); 760 Register scratch2 = temps.Acquire(); 761 splitTag(value, scratch2); 762 branchTestPrimitive(cond, scratch2, label); 763 } 764 765 void MacroAssembler::branchTestMagic(Condition cond, const ValueOperand& value, 766 Label* label) { 767 UseScratchRegisterScope temps(*this); 768 Register scratch2 = temps.Acquire(); 769 splitTag(value, scratch2); 770 ma_b(scratch2, ImmTag(JSVAL_TAG_MAGIC), label, cond); 771 } 772 773 void MacroAssembler::branchTestMagic(Condition cond, const Address& valaddr, 774 JSWhyMagic why, Label* label) { 775 uint64_t magic = MagicValue(why).asRawBits(); 776 UseScratchRegisterScope temps(*this); 777 Register scratch = temps.Acquire(); 778 loadPtr(valaddr, scratch); 779 ma_b(scratch, ImmWord(magic), label, cond); 780 } 781 782 template <typename T> 783 void MacroAssembler::branchTestValue(Condition cond, const T& lhs, 784 const ValueOperand& rhs, Label* label) { 785 MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual); 786 branchPtr(cond, lhs, rhs.valueReg(), label); 787 } 788 789 void MacroAssembler::branchTruncateDoubleMaybeModUint32(FloatRegister src, 790 Register dest, 791 Label* fail) { 792 UseScratchRegisterScope temps(*this); 793 Register scratch = temps.Acquire(); 794 as_truncld(ScratchDoubleReg, src); 795 as_cfc1(scratch, Assembler::FCSR); 796 moveFromDouble(ScratchDoubleReg, dest); 797 ma_ext(scratch, scratch, Assembler::CauseV, 1); 798 ma_b(scratch, Imm32(0), fail, Assembler::NotEqual); 799 800 as_sll(dest, dest, 0); 801 } 802 803 void MacroAssembler::branchTruncateFloat32MaybeModUint32(FloatRegister src, 804 Register dest, 805 Label* fail) { 806 UseScratchRegisterScope temps(*this); 807 Register scratch = temps.Acquire(); 808 as_truncls(ScratchDoubleReg, src); 809 as_cfc1(scratch, Assembler::FCSR); 810 moveFromDouble(ScratchDoubleReg, dest); 811 ma_ext(scratch, scratch, Assembler::CauseV, 1); 812 ma_b(scratch, Imm32(0), fail, Assembler::NotEqual); 813 814 as_sll(dest, dest, 0); 815 } 816 817 void MacroAssembler::branchTruncateDoubleToInt32(FloatRegister src, 818 Register dest, Label* fail) { 819 UseScratchRegisterScope temps(*this); 820 Register scratch = temps.Acquire(); 821 ScratchDoubleScope fpscratch(asMasm()); 822 823 // Convert scalar to signed 64-bit fixed-point, rounding toward zero. 824 // In the case of -0, the output is zero. 825 // In the case of overflow, the output is: 826 // - MIPS64R2: 2^63-1 827 // - MIPS64R6: saturated 828 // In the case of NaN, the output is: 829 // - MIPS64R2: 2^63-1 830 // - MIPS64R6: 0 831 as_truncld(fpscratch, src); 832 moveFromDouble(fpscratch, dest); 833 834 // Fail on overflow cases, besides MIPS64R2 will also fail here on NaN cases. 835 as_sll(scratch, dest, 0); 836 ma_b(dest, scratch, fail, Assembler::NotEqual); 837 } 838 839 void MacroAssembler::branchInt64NotInPtrRange(Register64 src, Label* label) { 840 // No-op on 64-bit platforms. 841 } 842 843 void MacroAssembler::branchUInt64NotInPtrRange(Register64 src, Label* label) { 844 branchTest64(Assembler::Signed, src, src, label); 845 } 846 847 void MacroAssembler::fallibleUnboxPtr(const ValueOperand& src, Register dest, 848 JSValueType type, Label* fail) { 849 MOZ_ASSERT(type == JSVAL_TYPE_OBJECT || type == JSVAL_TYPE_STRING || 850 type == JSVAL_TYPE_SYMBOL || type == JSVAL_TYPE_BIGINT); 851 // dest := src XOR mask 852 // scratch := dest >> JSVAL_TAG_SHIFT 853 // fail if scratch != 0 854 // 855 // Note: src and dest can be the same register 856 UseScratchRegisterScope temps(*this); 857 Register scratch = temps.Acquire(); 858 mov(ImmShiftedTag(type), scratch); 859 ma_xor(scratch, src.valueReg()); 860 ma_move(dest, scratch); 861 ma_dsrl(scratch, scratch, Imm32(JSVAL_TAG_SHIFT)); 862 ma_b(scratch, Imm32(0), fail, Assembler::NotEqual); 863 } 864 865 void MacroAssembler::fallibleUnboxPtr(const Address& src, Register dest, 866 JSValueType type, Label* fail) { 867 loadValue(src, ValueOperand(dest)); 868 fallibleUnboxPtr(ValueOperand(dest), dest, type, fail); 869 } 870 871 void MacroAssembler::fallibleUnboxPtr(const BaseIndex& src, Register dest, 872 JSValueType type, Label* fail) { 873 loadValue(src, ValueOperand(dest)); 874 fallibleUnboxPtr(ValueOperand(dest), dest, type, fail); 875 } 876 877 //}}} check_macroassembler_style 878 // =============================================================== 879 880 // The specializations for cmpPtrSet are outside the braces because 881 // check_macroassembler_style can't yet deal with specializations. 882 883 template <> 884 inline void MacroAssembler::cmpPtrSet(Assembler::Condition cond, Address lhs, 885 ImmPtr rhs, Register dest) { 886 UseScratchRegisterScope temps(*this); 887 Register scratch2 = temps.Acquire(); 888 loadPtr(lhs, scratch2); 889 cmpPtrSet(cond, scratch2, rhs, dest); 890 } 891 892 template <> 893 inline void MacroAssembler::cmpPtrSet(Assembler::Condition cond, Register lhs, 894 Address rhs, Register dest) { 895 UseScratchRegisterScope temps(*this); 896 Register scratch = temps.Acquire(); 897 loadPtr(rhs, scratch); 898 cmpPtrSet(cond, lhs, scratch, dest); 899 } 900 901 template <> 902 inline void MacroAssembler::cmpPtrSet(Assembler::Condition cond, Address lhs, 903 Register rhs, Register dest) { 904 UseScratchRegisterScope temps(*this); 905 Register scratch = temps.Acquire(); 906 loadPtr(lhs, scratch); 907 cmpPtrSet(cond, scratch, rhs, dest); 908 } 909 910 template <> 911 inline void MacroAssembler::cmp32Set(Assembler::Condition cond, Register lhs, 912 Address rhs, Register dest) { 913 UseScratchRegisterScope temps(*this); 914 Register scratch = temps.Acquire(); 915 load32(rhs, scratch); 916 cmp32Set(cond, lhs, scratch, dest); 917 } 918 919 template <> 920 inline void MacroAssembler::cmp32Set(Assembler::Condition cond, Address lhs, 921 Register rhs, Register dest) { 922 UseScratchRegisterScope temps(*this); 923 Register scratch = temps.Acquire(); 924 load32(lhs, scratch); 925 cmp32Set(cond, scratch, rhs, dest); 926 } 927 928 void MacroAssembler::cmpPtrMovePtr(Condition cond, Register lhs, Register rhs, 929 Register src, Register dest) { 930 UseScratchRegisterScope temps(*this); 931 Register scratch = temps.Acquire(); 932 MOZ_ASSERT(src != scratch && dest != scratch); 933 cmpPtrSet(cond, lhs, rhs, scratch); 934 #ifdef MIPSR6 935 as_selnez(src, src, scratch); 936 as_seleqz(dest, dest, scratch); 937 as_or(dest, dest, src); 938 #else 939 as_movn(dest, src, scratch); 940 #endif 941 } 942 943 void MacroAssembler::cmpPtrMovePtr(Condition cond, Register lhs, 944 const Address& rhs, Register src, 945 Register dest) { 946 MOZ_CRASH("NYI"); 947 } 948 949 void MacroAssemblerMIPS64Compat::incrementInt32Value(const Address& addr) { 950 asMasm().add32(Imm32(1), addr); 951 } 952 953 void MacroAssemblerMIPS64Compat::retn(Imm32 n) { 954 // pc <- [sp]; sp += n 955 loadPtr(Address(StackPointer, 0), ra); 956 asMasm().addPtr(n, StackPointer); 957 as_jr(ra); 958 as_nop(); 959 } 960 961 } // namespace jit 962 } // namespace js 963 964 #endif /* jit_mips64_MacroAssembler_mips64_inl_h */