MacroAssembler-riscv64-inl.h (78357B)
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_riscv64_MacroAssembler_riscv64_inl_h 8 #define jit_riscv64_MacroAssembler_riscv64_inl_h 9 10 #include "jit/riscv64/MacroAssembler-riscv64.h" 11 12 namespace js { 13 namespace jit { 14 15 template <> 16 inline void MacroAssembler::cmpPtrSet(Assembler::Condition cond, Address lhs, 17 ImmPtr rhs, Register dest) { 18 UseScratchRegisterScope temps(this); 19 Register scratch2 = temps.Acquire(); 20 loadPtr(lhs, scratch2); 21 cmpPtrSet(cond, Register(scratch2), rhs, dest); 22 } 23 24 template <> 25 inline void MacroAssembler::cmpPtrSet(Assembler::Condition cond, Register lhs, 26 Address rhs, Register dest) { 27 UseScratchRegisterScope temps(this); 28 Register scratch = temps.Acquire(); 29 MOZ_ASSERT(lhs != scratch); 30 loadPtr(rhs, scratch); 31 cmpPtrSet(cond, lhs, Register(scratch), dest); 32 } 33 34 template <> 35 inline void MacroAssembler::cmpPtrSet(Assembler::Condition cond, Address lhs, 36 Register rhs, Register dest) { 37 UseScratchRegisterScope temps(this); 38 Register scratch2 = temps.Acquire(); 39 MOZ_ASSERT(rhs != scratch2); 40 loadPtr(lhs, scratch2); 41 cmpPtrSet(cond, Register(scratch2), rhs, dest); 42 } 43 44 template <> 45 inline void MacroAssembler::cmp32Set(Assembler::Condition cond, Register lhs, 46 Address rhs, Register dest) { 47 UseScratchRegisterScope temps(this); 48 Register scratch = temps.Acquire(); 49 MOZ_ASSERT(lhs != scratch); 50 load32(rhs, scratch); 51 cmp32Set(cond, lhs, Register(scratch), dest); 52 } 53 54 template <> 55 inline void MacroAssembler::cmp32Set(Assembler::Condition cond, Address lhs, 56 Register rhs, Register dest) { 57 UseScratchRegisterScope temps(this); 58 Register scratch2 = temps.Acquire(); 59 MOZ_ASSERT(rhs != scratch2); 60 load32(lhs, scratch2); 61 cmp32Set(cond, Register(scratch2), rhs, dest); 62 } 63 64 //{{{ check_macroassembler_style 65 CodeOffset MacroAssembler::sub32FromStackPtrWithPatch(Register dest) { 66 CodeOffset offset = CodeOffset(currentOffset()); 67 MacroAssemblerRiscv64::ma_liPatchable(dest, Imm32(0)); 68 sub(dest, StackPointer, dest); 69 return offset; 70 } 71 72 void MacroAssembler::branchTest32(Condition cond, Register lhs, Imm32 rhs, 73 Label* label) { 74 MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || 75 cond == NotSigned); 76 UseScratchRegisterScope temps(this); 77 Register scratch = temps.Acquire(); 78 ma_and(scratch, lhs, rhs); 79 ma_b(scratch, scratch, label, cond); 80 } 81 void MacroAssembler::branchTest32(Condition cond, Register lhs, Register rhs, 82 Label* label) { 83 MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || 84 cond == NotSigned); 85 if (lhs == rhs) { 86 ma_b(lhs, rhs, label, cond); 87 } else { 88 UseScratchRegisterScope temps(this); 89 Register scratch = temps.Acquire(); 90 and_(scratch, lhs, rhs); 91 ma_b(scratch, scratch, label, cond); 92 } 93 } 94 void MacroAssembler::branchTest64(Condition cond, Register64 lhs, 95 Register64 rhs, Register temp, Label* success, 96 Label* fail) { 97 branchTestPtr(cond, lhs.reg, rhs.reg, success); 98 if (fail) { 99 jump(fail); 100 } 101 } 102 void MacroAssembler::branchTest64(Condition cond, Register64 lhs, Imm64 rhs, 103 Label* success, Label* fail) { 104 branchTestPtr(cond, lhs.reg, ImmWord(rhs.value), success); 105 if (fail) { 106 jump(fail); 107 } 108 } 109 110 template <typename T> 111 void MacroAssembler::branchAdd32(Condition cond, T src, Register dest, 112 Label* overflow) { 113 switch (cond) { 114 case Overflow: 115 ma_add32TestOverflow(dest, dest, src, overflow); 116 break; 117 case CarryClear: 118 case CarrySet: 119 ma_add32TestCarry(cond, dest, dest, src, overflow); 120 break; 121 default: 122 MOZ_CRASH("NYI"); 123 } 124 } 125 template <typename T> 126 void MacroAssembler::branchAddPtr(Condition cond, T src, Register dest, 127 Label* label) { 128 switch (cond) { 129 case Overflow: 130 ma_addPtrTestOverflow(dest, dest, src, label); 131 break; 132 case CarryClear: 133 case CarrySet: 134 ma_addPtrTestCarry(cond, dest, dest, src, label); 135 break; 136 case Signed: 137 case NotSigned: 138 ma_addPtrTestSigned(cond, dest, dest, src, label); 139 break; 140 default: 141 MOZ_CRASH("NYI"); 142 } 143 } 144 template <typename T> 145 void MacroAssembler::branchMul32(Condition cond, T src, Register dest, 146 Label* overflow) { 147 MOZ_ASSERT(cond == Assembler::Overflow); 148 ma_mul32TestOverflow(dest, dest, src, overflow); 149 } 150 template <typename T> 151 void MacroAssembler::branchRshift32(Condition cond, T src, Register dest, 152 Label* label) { 153 MOZ_ASSERT(cond == Zero || cond == NonZero); 154 rshift32(src, dest); 155 branch32(cond == Zero ? Equal : NotEqual, dest, Imm32(0), label); 156 } 157 // the type of 'T src' maybe a Register, maybe a Imm32,depends on who call it. 158 template <typename T> 159 void MacroAssembler::branchSub32(Condition cond, T src, Register dest, 160 Label* label) { 161 switch (cond) { 162 case Overflow: 163 ma_sub32TestOverflow(dest, dest, src, label); 164 break; 165 case NonZero: 166 case Zero: 167 case Signed: 168 case NotSigned: 169 ma_sub32(dest, dest, src); 170 ma_b(dest, dest, label, cond); 171 break; 172 default: 173 MOZ_CRASH("NYI"); 174 } 175 } 176 template <typename T> 177 void MacroAssembler::branchSubPtr(Condition cond, T src, Register dest, 178 Label* label) { 179 switch (cond) { 180 case Overflow: 181 ma_subPtrTestOverflow(dest, dest, src, label); 182 break; 183 case NonZero: 184 case Zero: 185 case Signed: 186 case NotSigned: 187 subPtr(src, dest); 188 ma_b(dest, dest, label, cond); 189 break; 190 default: 191 MOZ_CRASH("NYI"); 192 } 193 } 194 template <typename T> 195 void MacroAssembler::branchTestGCThingImpl(Condition cond, const T& address, 196 Label* label) { 197 MOZ_ASSERT(cond == Equal || cond == NotEqual); 198 UseScratchRegisterScope temps(this); 199 Register scratch2 = temps.Acquire(); 200 Register tag = extractTag(address, scratch2); 201 ma_b(tag, ImmTag(JS::detail::ValueLowerInclGCThingTag), label, 202 (cond == Equal) ? AboveOrEqual : Below); 203 } 204 template <typename T> 205 void MacroAssembler::testBigIntSet(Condition cond, const T& src, 206 Register dest) { 207 MOZ_ASSERT(cond == Equal || cond == NotEqual); 208 UseScratchRegisterScope temps(this); 209 Register scratch2 = temps.Acquire(); 210 Register tag = extractTag(src, scratch2); 211 ma_cmp_set(dest, tag, ImmTag(JSVAL_TAG_BIGINT), cond); 212 } 213 214 template <typename T> 215 void MacroAssembler::testBooleanSet(Condition cond, const T& src, 216 Register dest) { 217 MOZ_ASSERT(cond == Equal || cond == NotEqual); 218 UseScratchRegisterScope temps(this); 219 Register scratch2 = temps.Acquire(); 220 Register tag = extractTag(src, scratch2); 221 ma_cmp_set(dest, tag, ImmTag(JSVAL_TAG_BOOLEAN), cond); 222 } 223 224 template <typename T> 225 void MacroAssembler::testNumberSet(Condition cond, const T& src, 226 Register dest) { 227 MOZ_ASSERT(cond == Equal || cond == NotEqual); 228 UseScratchRegisterScope temps(this); 229 Register scratch2 = temps.Acquire(); 230 Register tag = extractTag(src, scratch2); 231 ma_cmp_set(dest, tag, ImmTag(JS::detail::ValueUpperInclNumberTag), 232 cond == Equal ? BelowOrEqual : Above); 233 } 234 235 template <typename T> 236 void MacroAssembler::testStringSet(Condition cond, const T& src, 237 Register dest) { 238 MOZ_ASSERT(cond == Equal || cond == NotEqual); 239 UseScratchRegisterScope temps(this); 240 Register scratch2 = temps.Acquire(); 241 Register tag = extractTag(src, scratch2); 242 ma_cmp_set(dest, tag, ImmTag(JSVAL_TAG_STRING), cond); 243 } 244 245 template <typename T> 246 void MacroAssembler::testSymbolSet(Condition cond, const T& src, 247 Register dest) { 248 MOZ_ASSERT(cond == Equal || cond == NotEqual); 249 UseScratchRegisterScope temps(this); 250 Register scratch2 = temps.Acquire(); 251 Register tag = extractTag(src, scratch2); 252 ma_cmp_set(dest, tag, ImmTag(JSVAL_TAG_SYMBOL), cond); 253 } 254 255 // Also see below for specializations of cmpPtrSet. 256 template <typename T1, typename T2> 257 void MacroAssembler::cmp32Set(Condition cond, T1 lhs, T2 rhs, Register dest) { 258 ma_cmp_set(dest, lhs, rhs, cond); 259 } 260 template <typename T1, typename T2> 261 void MacroAssembler::cmpPtrSet(Condition cond, T1 lhs, T2 rhs, Register dest) { 262 ma_cmp_set(dest, lhs, rhs, cond); 263 } 264 void MacroAssembler::abs32(Register src, Register dest) { 265 UseScratchRegisterScope temps(this); 266 Register scratch = temps.Acquire(); 267 sraiw(scratch, src, 31); 268 xor_(dest, src, scratch); 269 subw(dest, dest, scratch); 270 } 271 void MacroAssembler::absFloat32(FloatRegister src, FloatRegister dest) { 272 fabs_s(dest, src); 273 } 274 275 void MacroAssembler::absDouble(FloatRegister src, FloatRegister dest) { 276 fabs_d(dest, src); 277 } 278 void MacroAssembler::add32(Register src, Register dest) { 279 ma_add32(dest, dest, src); 280 } 281 282 void MacroAssembler::add32(Imm32 imm, Register dest) { 283 ma_add32(dest, dest, imm); 284 } 285 286 void MacroAssembler::add32(Imm32 imm, Register src, Register dest) { 287 ma_add32(dest, src, imm); 288 } 289 290 void MacroAssembler::add32(Imm32 imm, const Address& dest) { 291 UseScratchRegisterScope temps(this); 292 Register scratch2 = temps.Acquire(); 293 load32(dest, scratch2); 294 ma_add32(scratch2, scratch2, imm); 295 store32(scratch2, dest); 296 } 297 298 void MacroAssembler::add32(const Address& src, Register dest) { 299 UseScratchRegisterScope temps(this); 300 Register scratch = temps.Acquire(); 301 load32(src, scratch); 302 ma_add32(dest, dest, scratch); 303 } 304 305 void MacroAssembler::add64(Register64 src, Register64 dest) { 306 addPtr(src.reg, dest.reg); 307 } 308 309 void MacroAssembler::add64(Imm32 imm, Register64 dest) { 310 ma_add64(dest.reg, dest.reg, imm); 311 } 312 313 void MacroAssembler::add64(Imm64 imm, Register64 dest) { 314 UseScratchRegisterScope temps(this); 315 Register scratch = temps.Acquire(); 316 MOZ_ASSERT(dest.reg != scratch); 317 mov(ImmWord(imm.value), scratch); 318 add(dest.reg, dest.reg, scratch); 319 } 320 void MacroAssembler::addDouble(FloatRegister src, FloatRegister dest) { 321 fadd_d(dest, dest, src); 322 } 323 324 void MacroAssembler::addFloat32(FloatRegister src, FloatRegister dest) { 325 fadd_s(dest, dest, src); 326 } 327 void MacroAssembler::addPtr(Register src, Register dest) { 328 ma_add64(dest, dest, Operand(src)); 329 } 330 331 void MacroAssembler::addPtr(Imm32 imm, Register dest) { 332 ma_add64(dest, dest, imm); 333 } 334 335 void MacroAssembler::addPtr(ImmWord imm, Register dest) { 336 UseScratchRegisterScope temps(this); 337 Register scratch = temps.Acquire(); 338 movePtr(imm, scratch); 339 addPtr(scratch, dest); 340 } 341 void MacroAssembler::addPtr(Imm32 imm, const Address& dest) { 342 UseScratchRegisterScope temps(this); 343 Register scratch = temps.Acquire(); 344 loadPtr(dest, scratch); 345 addPtr(imm, scratch); 346 storePtr(scratch, dest); 347 } 348 349 void MacroAssembler::addPtr(const Address& src, Register dest) { 350 UseScratchRegisterScope temps(this); 351 Register scratch = temps.Acquire(); 352 loadPtr(src, scratch); 353 addPtr(scratch, dest); 354 } 355 void MacroAssembler::and32(Register src, Register dest) { 356 ma_and(dest, dest, src); 357 } 358 359 void MacroAssembler::and32(Imm32 imm, Register dest) { 360 ma_and(dest, dest, imm); 361 } 362 363 void MacroAssembler::and32(Imm32 imm, Register src, Register dest) { 364 ma_and(dest, src, imm); 365 } 366 367 void MacroAssembler::and32(Imm32 imm, const Address& dest) { 368 UseScratchRegisterScope temps(this); 369 Register scratch2 = temps.Acquire(); 370 load32(dest, scratch2); 371 ma_and(scratch2, imm); 372 store32(scratch2, dest); 373 } 374 375 void MacroAssembler::and32(const Address& src, Register dest) { 376 UseScratchRegisterScope temps(this); 377 Register scratch2 = temps.Acquire(); 378 load32(src, scratch2); 379 ma_and(dest, dest, scratch2); 380 } 381 void MacroAssembler::and64(Imm64 imm, Register64 dest) { 382 UseScratchRegisterScope temps(this); 383 Register scratch = temps.Acquire(); 384 ma_li(scratch, ImmWord(imm.value)); 385 ma_and(dest.reg, dest.reg, scratch); 386 } 387 388 void MacroAssembler::and64(Register64 src, Register64 dest) { 389 ma_and(dest.reg, dest.reg, src.reg); 390 } 391 392 void MacroAssembler::andPtr(Register src, Register dest) { 393 ma_and(dest, dest, src); 394 } 395 396 void MacroAssembler::andPtr(Imm32 imm, Register dest) { 397 ma_and(dest, dest, imm); 398 } 399 400 void MacroAssembler::andPtr(Imm32 imm, Register src, Register dest) { 401 ma_and(dest, src, imm); 402 } 403 404 void MacroAssembler::branch8(Condition cond, const Address& lhs, Imm32 rhs, 405 Label* label) { 406 UseScratchRegisterScope temps(this); 407 Register scratch2 = temps.Acquire(); 408 MOZ_ASSERT(scratch2 != lhs.base); 409 410 switch (cond) { 411 case Assembler::Equal: 412 case Assembler::NotEqual: 413 case Assembler::Above: 414 case Assembler::AboveOrEqual: 415 case Assembler::Below: 416 case Assembler::BelowOrEqual: 417 load8ZeroExtend(lhs, scratch2); 418 branch32(cond, scratch2, Imm32(uint8_t(rhs.value)), label); 419 break; 420 421 case Assembler::GreaterThan: 422 case Assembler::GreaterThanOrEqual: 423 case Assembler::LessThan: 424 case Assembler::LessThanOrEqual: 425 load8SignExtend(lhs, scratch2); 426 branch32(cond, scratch2, Imm32(int8_t(rhs.value)), label); 427 break; 428 429 default: 430 MOZ_CRASH("unexpected condition"); 431 } 432 } 433 434 void MacroAssembler::branch8(Condition cond, const BaseIndex& lhs, Register rhs, 435 Label* label) { 436 UseScratchRegisterScope temps(this); 437 Register scratch2 = temps.Acquire(); 438 MOZ_ASSERT(scratch2 != lhs.base); 439 440 computeScaledAddress(lhs, scratch2); 441 442 switch (cond) { 443 case Assembler::Equal: 444 case Assembler::NotEqual: 445 case Assembler::Above: 446 case Assembler::AboveOrEqual: 447 case Assembler::Below: 448 case Assembler::BelowOrEqual: 449 load8ZeroExtend(Address(scratch2, lhs.offset), scratch2); 450 branch32(cond, scratch2, rhs, label); 451 break; 452 453 case Assembler::GreaterThan: 454 case Assembler::GreaterThanOrEqual: 455 case Assembler::LessThan: 456 case Assembler::LessThanOrEqual: 457 load8SignExtend(Address(scratch2, lhs.offset), scratch2); 458 branch32(cond, scratch2, rhs, label); 459 break; 460 461 default: 462 MOZ_CRASH("unexpected condition"); 463 } 464 } 465 466 void MacroAssembler::branch16(Condition cond, const Address& lhs, Imm32 rhs, 467 Label* label) { 468 UseScratchRegisterScope temps(this); 469 Register scratch2 = temps.Acquire(); 470 MOZ_ASSERT(scratch2 != lhs.base); 471 472 switch (cond) { 473 case Assembler::Equal: 474 case Assembler::NotEqual: 475 case Assembler::Above: 476 case Assembler::AboveOrEqual: 477 case Assembler::Below: 478 case Assembler::BelowOrEqual: 479 load16ZeroExtend(lhs, scratch2); 480 branch32(cond, scratch2, Imm32(uint16_t(rhs.value)), label); 481 break; 482 483 case Assembler::GreaterThan: 484 case Assembler::GreaterThanOrEqual: 485 case Assembler::LessThan: 486 case Assembler::LessThanOrEqual: 487 load16SignExtend(lhs, scratch2); 488 branch32(cond, scratch2, Imm32(int16_t(rhs.value)), label); 489 break; 490 491 default: 492 MOZ_CRASH("unexpected condition"); 493 } 494 } 495 void MacroAssembler::branch32(Condition cond, Register lhs, Register rhs, 496 Label* label) { 497 ma_b(lhs, rhs, label, cond); 498 } 499 500 void MacroAssembler::branch32(Condition cond, Register lhs, Imm32 imm, 501 Label* label) { 502 ma_b(lhs, imm, label, cond); 503 } 504 505 void MacroAssembler::branch32(Condition cond, const Address& lhs, Register rhs, 506 Label* label) { 507 UseScratchRegisterScope temps(this); 508 Register scratch2 = temps.Acquire(); 509 load32(lhs, scratch2); 510 ma_b(scratch2, rhs, label, cond); 511 } 512 513 void MacroAssembler::branch32(Condition cond, const Address& lhs, Imm32 rhs, 514 Label* label) { 515 UseScratchRegisterScope temps(this); 516 Register scratch2 = temps.Acquire(); 517 load32(lhs, scratch2); 518 ma_b(scratch2, rhs, label, cond); 519 } 520 521 void MacroAssembler::branch32(Condition cond, const AbsoluteAddress& lhs, 522 Register rhs, Label* label) { 523 UseScratchRegisterScope temps(this); 524 Register scratch2 = temps.Acquire(); 525 load32(lhs, scratch2); 526 ma_b(scratch2, rhs, label, cond); 527 } 528 529 void MacroAssembler::branch32(Condition cond, const AbsoluteAddress& lhs, 530 Imm32 rhs, Label* label) { 531 UseScratchRegisterScope temps(this); 532 Register scratch2 = temps.Acquire(); 533 load32(lhs, scratch2); 534 ma_b(scratch2, rhs, label, cond); 535 } 536 537 void MacroAssembler::branch32(Condition cond, const BaseIndex& lhs, Imm32 rhs, 538 Label* label) { 539 UseScratchRegisterScope temps(this); 540 Register scratch2 = temps.Acquire(); 541 load32(lhs, scratch2); 542 ma_b(scratch2, rhs, label, cond); 543 } 544 545 void MacroAssembler::branch32(Condition cond, wasm::SymbolicAddress addr, 546 Imm32 imm, Label* label) { 547 UseScratchRegisterScope temps(this); 548 Register scratch2 = temps.Acquire(); 549 load32(addr, scratch2); 550 ma_b(scratch2, imm, label, cond); 551 } 552 void MacroAssembler::branch64(Condition cond, Register64 lhs, Imm64 val, 553 Label* success, Label* fail) { 554 MOZ_ASSERT(cond == Assembler::NotEqual || cond == Assembler::Equal || 555 cond == Assembler::LessThan || 556 cond == Assembler::LessThanOrEqual || 557 cond == Assembler::GreaterThan || 558 cond == Assembler::GreaterThanOrEqual || 559 cond == Assembler::Below || cond == Assembler::BelowOrEqual || 560 cond == Assembler::Above || cond == Assembler::AboveOrEqual, 561 "other condition codes not supported"); 562 563 branchPtr(cond, lhs.reg, ImmWord(val.value), success); 564 if (fail) { 565 jump(fail); 566 } 567 } 568 569 void MacroAssembler::branch64(Condition cond, Register64 lhs, Register64 rhs, 570 Label* success, Label* fail) { 571 MOZ_ASSERT(cond == Assembler::NotEqual || cond == Assembler::Equal || 572 cond == Assembler::LessThan || 573 cond == Assembler::LessThanOrEqual || 574 cond == Assembler::GreaterThan || 575 cond == Assembler::GreaterThanOrEqual || 576 cond == Assembler::Below || cond == Assembler::BelowOrEqual || 577 cond == Assembler::Above || cond == Assembler::AboveOrEqual, 578 "other condition codes not supported"); 579 580 branchPtr(cond, lhs.reg, rhs.reg, success); 581 if (fail) { 582 jump(fail); 583 } 584 } 585 586 void MacroAssembler::branch64(Condition cond, const Address& lhs, Imm64 val, 587 Label* success, Label* fail) { 588 MOZ_ASSERT(cond == Assembler::NotEqual || cond == Assembler::Equal || 589 cond == Assembler::LessThan || 590 cond == Assembler::LessThanOrEqual || 591 cond == Assembler::GreaterThan || 592 cond == Assembler::GreaterThanOrEqual || 593 cond == Assembler::Below || cond == Assembler::BelowOrEqual || 594 cond == Assembler::Above || cond == Assembler::AboveOrEqual, 595 "other condition codes not supported"); 596 597 branchPtr(cond, lhs, ImmWord(val.value), success); 598 if (fail) { 599 jump(fail); 600 } 601 } 602 603 void MacroAssembler::branch64(Condition cond, const Address& lhs, 604 Register64 rhs, Label* success, Label* fail) { 605 MOZ_ASSERT(cond == Assembler::NotEqual || cond == Assembler::Equal || 606 cond == Assembler::LessThan || 607 cond == Assembler::LessThanOrEqual || 608 cond == Assembler::GreaterThan || 609 cond == Assembler::GreaterThanOrEqual || 610 cond == Assembler::Below || cond == Assembler::BelowOrEqual || 611 cond == Assembler::Above || cond == Assembler::AboveOrEqual, 612 "other condition codes not supported"); 613 614 branchPtr(cond, lhs, rhs.reg, success); 615 if (fail) { 616 jump(fail); 617 } 618 } 619 620 void MacroAssembler::branch64(Condition cond, const Address& lhs, 621 const Address& rhs, Register scratch, 622 Label* label) { 623 MOZ_ASSERT(cond == Assembler::NotEqual || cond == Assembler::Equal, 624 "other condition codes not supported"); 625 MOZ_ASSERT(lhs.base != scratch); 626 MOZ_ASSERT(rhs.base != scratch); 627 628 loadPtr(rhs, scratch); 629 branchPtr(cond, lhs, scratch, label); 630 } 631 632 void MacroAssembler::branchDouble(DoubleCondition cc, FloatRegister frs1, 633 FloatRegister frs2, Label* L) { 634 BranchFloat64(cc, frs1, frs2, L, LongJump); 635 } 636 void MacroAssembler::branchFloat(DoubleCondition cc, FloatRegister frs1, 637 FloatRegister frs2, Label* L) { 638 BranchFloat32(cc, frs1, frs2, L, LongJump); 639 } 640 641 void MacroAssembler::branchMulPtr(Condition cond, Register src, Register dest, 642 Label* label) { 643 MOZ_ASSERT(cond == Assembler::Overflow); 644 ma_mulPtrTestOverflow(dest, dest, src, label); 645 } 646 647 void MacroAssembler::branchNegPtr(Condition cond, Register reg, Label* label) { 648 MOZ_ASSERT(cond == Overflow); 649 negPtr(reg); 650 branchPtr(Assembler::Equal, reg, ImmWord(INTPTR_MIN), label); 651 } 652 void MacroAssembler::branchNeg32(Condition cond, Register reg, Label* label) { 653 MOZ_ASSERT(cond == Overflow); 654 neg32(reg); 655 branch32(Assembler::Equal, reg, Imm32(INT32_MIN), label); 656 } 657 658 void MacroAssembler::branchPrivatePtr(Condition cond, const Address& lhs, 659 Register rhs, Label* label) { 660 branchPtr(cond, lhs, rhs, label); 661 } 662 663 void MacroAssembler::branchPtr(Condition cond, Register lhs, Register rhs, 664 Label* label) { 665 ma_b(lhs, rhs, label, cond); 666 } 667 668 void MacroAssembler::branchPtr(Condition cond, Register lhs, Imm32 rhs, 669 Label* label) { 670 ma_b(lhs, rhs, label, cond); 671 } 672 673 void MacroAssembler::branchPtr(Condition cond, Register lhs, ImmPtr rhs, 674 Label* label) { 675 if (rhs.value == nullptr && (cond == Zero || cond == NonZero)) { 676 ma_b(lhs, lhs, label, cond); 677 } else { 678 ma_b(lhs, rhs, label, cond); 679 } 680 } 681 682 void MacroAssembler::branchPtr(Condition cond, Register lhs, ImmGCPtr rhs, 683 Label* label) { 684 ma_b(lhs, rhs, label, cond); 685 } 686 687 void MacroAssembler::branchPtr(Condition cond, Register lhs, ImmWord rhs, 688 Label* label) { 689 ma_b(lhs, rhs, label, cond); 690 } 691 692 void MacroAssembler::branchPtr(Condition cond, const Address& lhs, Register rhs, 693 Label* label) { 694 UseScratchRegisterScope temps(this); 695 Register scratch2 = temps.Acquire(); 696 loadPtr(lhs, scratch2); 697 branchPtr(cond, scratch2, rhs, label); 698 } 699 700 void MacroAssembler::branchPtr(Condition cond, const Address& lhs, ImmPtr rhs, 701 Label* label) { 702 UseScratchRegisterScope temps(this); 703 Register scratch2 = temps.Acquire(); 704 loadPtr(lhs, scratch2); 705 branchPtr(cond, scratch2, rhs, label); 706 } 707 708 void MacroAssembler::branchPtr(Condition cond, const Address& lhs, ImmGCPtr rhs, 709 Label* label) { 710 UseScratchRegisterScope temps(this); 711 Register scratch2 = temps.Acquire(); 712 loadPtr(lhs, scratch2); 713 branchPtr(cond, scratch2, rhs, label); 714 } 715 716 void MacroAssembler::branchPtr(Condition cond, const Address& lhs, ImmWord rhs, 717 Label* label) { 718 UseScratchRegisterScope temps(this); 719 Register scratch2 = temps.Acquire(); 720 loadPtr(lhs, scratch2); 721 branchPtr(cond, scratch2, rhs, label); 722 } 723 724 void MacroAssembler::branchPtr(Condition cond, const AbsoluteAddress& lhs, 725 Register rhs, Label* label) { 726 UseScratchRegisterScope temps(this); 727 Register scratch2 = temps.Acquire(); 728 loadPtr(lhs, scratch2); 729 branchPtr(cond, scratch2, rhs, label); 730 } 731 732 void MacroAssembler::branchPtr(Condition cond, const AbsoluteAddress& lhs, 733 ImmWord rhs, Label* label) { 734 UseScratchRegisterScope temps(this); 735 Register scratch2 = temps.Acquire(); 736 loadPtr(lhs, scratch2); 737 branchPtr(cond, scratch2, rhs, label); 738 } 739 740 void MacroAssembler::branchPtr(Condition cond, wasm::SymbolicAddress lhs, 741 Register rhs, Label* label) { 742 UseScratchRegisterScope temps(this); 743 Register scratch2 = temps.Acquire(); 744 loadPtr(lhs, scratch2); 745 branchPtr(cond, scratch2, rhs, label); 746 } 747 748 void MacroAssembler::branchPtr(Condition cond, const BaseIndex& lhs, 749 Register rhs, Label* label) { 750 UseScratchRegisterScope temps(this); 751 Register scratch2 = temps.Acquire(); 752 loadPtr(lhs, scratch2); 753 branchPtr(cond, scratch2, rhs, label); 754 } 755 756 void MacroAssembler::branchPtr(Condition cond, const BaseIndex& lhs, 757 ImmWord rhs, Label* label) { 758 UseScratchRegisterScope temps(this); 759 Register scratch2 = temps.Acquire(); 760 loadPtr(lhs, scratch2); 761 branchPtr(cond, scratch2, rhs, label); 762 } 763 764 void MacroAssembler::branchTest32(Condition cond, const AbsoluteAddress& lhs, 765 Imm32 rhs, Label* label) { 766 MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || 767 cond == NotSigned); 768 UseScratchRegisterScope temps(this); 769 Register scratch2 = temps.Acquire(); 770 load32(lhs, scratch2); 771 and32(rhs, scratch2); 772 ma_b(scratch2, scratch2, label, cond); 773 } 774 775 void MacroAssembler::branchTest32(Condition cond, const Address& lhs, Imm32 rhs, 776 Label* label) { 777 MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || 778 cond == NotSigned); 779 UseScratchRegisterScope temps(this); 780 Register scratch2 = temps.Acquire(); 781 load32(lhs, scratch2); 782 and32(rhs, scratch2); 783 ma_b(scratch2, scratch2, label, cond); 784 } 785 void MacroAssembler::branchTestBigInt(Condition cond, Register tag, 786 Label* label) { 787 MOZ_ASSERT(cond == Equal || cond == NotEqual); 788 ma_b(tag, ImmTag(JSVAL_TAG_BIGINT), label, cond); 789 } 790 791 void MacroAssembler::branchTestBigInt(Condition cond, const ValueOperand& value, 792 Label* label) { 793 UseScratchRegisterScope temps(this); 794 Register scratch2 = temps.Acquire(); 795 splitTag(value, scratch2); 796 branchTestBigInt(cond, scratch2, label); 797 } 798 799 void MacroAssembler::branchTestBigInt(Condition cond, const Address& address, 800 Label* label) { 801 UseScratchRegisterScope temps(this); 802 Register scratch2 = temps.Acquire(); 803 Register tag = extractTag(address, scratch2); 804 branchTestBigInt(cond, tag, label); 805 } 806 807 void MacroAssembler::branchTestBigInt(Condition cond, const BaseIndex& address, 808 Label* label) { 809 UseScratchRegisterScope temps(this); 810 Register scratch2 = temps.Acquire(); 811 computeEffectiveAddress(address, scratch2); 812 splitTag(scratch2, scratch2); 813 branchTestBigInt(cond, scratch2, label); 814 } 815 void MacroAssembler::branchTestBigIntTruthy(bool b, const ValueOperand& value, 816 Label* label) { 817 UseScratchRegisterScope temps(this); 818 Register scratch2 = temps.Acquire(); 819 unboxBigInt(value, scratch2); 820 load32(Address(scratch2, BigInt::offsetOfDigitLength()), scratch2); 821 ma_b(scratch2, Imm32(0), label, b ? NotEqual : Equal); 822 } 823 void MacroAssembler::branchTestBoolean(Condition cond, Register tag, 824 Label* label) { 825 MOZ_ASSERT(cond == Equal || cond == NotEqual); 826 ma_b(tag, ImmTag(JSVAL_TAG_BOOLEAN), label, cond); 827 } 828 829 void MacroAssembler::branchTestBoolean(Condition cond, 830 const ValueOperand& value, 831 Label* label) { 832 UseScratchRegisterScope temps(this); 833 Register scratch2 = temps.Acquire(); 834 splitTag(value, scratch2); 835 branchTestBoolean(cond, scratch2, label); 836 } 837 838 void MacroAssembler::branchTestBoolean(Condition cond, const Address& address, 839 Label* label) { 840 UseScratchRegisterScope temps(this); 841 Register scratch2 = temps.Acquire(); 842 Register tag = extractTag(address, scratch2); 843 branchTestBoolean(cond, tag, label); 844 } 845 846 void MacroAssembler::branchTestBoolean(Condition cond, const BaseIndex& address, 847 Label* label) { 848 UseScratchRegisterScope temps(this); 849 Register scratch2 = temps.Acquire(); 850 Register tag = extractTag(address, scratch2); 851 branchTestBoolean(cond, tag, label); 852 } 853 void MacroAssembler::branchTestBooleanTruthy(bool b, const ValueOperand& value, 854 Label* label) { 855 UseScratchRegisterScope temps(this); 856 Register scratch2 = temps.Acquire(); 857 unboxBoolean(value, scratch2); 858 ma_b(scratch2, scratch2, label, b ? NonZero : Zero); 859 } 860 void MacroAssembler::branchTestDouble(Condition cond, Register tag, 861 Label* label) { 862 MOZ_ASSERT(cond == Equal || cond == NotEqual); 863 Condition actual = (cond == Equal) ? BelowOrEqual : Above; 864 ma_b(tag, ImmTag(JSVAL_TAG_MAX_DOUBLE), label, actual); 865 } 866 867 void MacroAssembler::branchTestDouble(Condition cond, const ValueOperand& value, 868 Label* label) { 869 UseScratchRegisterScope temps(this); 870 Register scratch2 = temps.Acquire(); 871 splitTag(value, scratch2); 872 branchTestDouble(cond, scratch2, label); 873 } 874 875 void MacroAssembler::branchTestDouble(Condition cond, const Address& address, 876 Label* label) { 877 UseScratchRegisterScope temps(this); 878 Register scratch2 = temps.Acquire(); 879 Register tag = extractTag(address, scratch2); 880 branchTestDouble(cond, tag, label); 881 } 882 883 void MacroAssembler::branchTestDouble(Condition cond, const BaseIndex& address, 884 Label* label) { 885 UseScratchRegisterScope temps(this); 886 Register scratch2 = temps.Acquire(); 887 Register tag = extractTag(address, scratch2); 888 branchTestDouble(cond, tag, label); 889 } 890 891 void MacroAssembler::branchTestDoubleTruthy(bool b, FloatRegister value, 892 Label* label) { 893 ScratchDoubleScope fpscratch(*this); 894 loadConstantDouble(0.0, fpscratch); 895 DoubleCondition cond = b ? DoubleNotEqual : DoubleEqualOrUnordered; 896 branchDouble(cond, value, fpscratch, label); 897 } 898 void MacroAssembler::branchTestGCThing(Condition cond, const Address& address, 899 Label* label) { 900 branchTestGCThingImpl(cond, address, label); 901 } 902 903 void MacroAssembler::branchTestGCThing(Condition cond, const BaseIndex& address, 904 Label* label) { 905 branchTestGCThingImpl(cond, address, label); 906 } 907 908 void MacroAssembler::branchTestGCThing(Condition cond, 909 const ValueOperand& address, 910 Label* label) { 911 branchTestGCThingImpl(cond, address, label); 912 } 913 void MacroAssembler::branchTestInt32(Condition cond, Register tag, 914 Label* label) { 915 MOZ_ASSERT(cond == Equal || cond == NotEqual); 916 ma_b(tag, ImmTag(JSVAL_TAG_INT32), label, cond); 917 } 918 919 void MacroAssembler::branchTestInt32(Condition cond, const ValueOperand& value, 920 Label* label) { 921 UseScratchRegisterScope temps(this); 922 Register scratch2 = temps.Acquire(); 923 splitTag(value, scratch2); 924 branchTestInt32(cond, scratch2, label); 925 } 926 927 void MacroAssembler::branchTestInt32(Condition cond, const Address& address, 928 Label* label) { 929 UseScratchRegisterScope temps(this); 930 Register scratch2 = temps.Acquire(); 931 Register tag = extractTag(address, scratch2); 932 branchTestInt32(cond, tag, label); 933 } 934 935 void MacroAssembler::branchTestInt32(Condition cond, const BaseIndex& address, 936 Label* label) { 937 UseScratchRegisterScope temps(this); 938 Register scratch2 = temps.Acquire(); 939 Register tag = extractTag(address, scratch2); 940 branchTestInt32(cond, tag, label); 941 } 942 void MacroAssembler::branchTestInt32Truthy(bool b, const ValueOperand& value, 943 Label* label) { 944 UseScratchRegisterScope temps(this); 945 Register scratch = temps.Acquire(); 946 ExtractBits(scratch, value.valueReg(), 0, 32); 947 ma_b(scratch, scratch, label, b ? NonZero : Zero); 948 } 949 void MacroAssembler::branchTestMagic(Condition cond, Register tag, 950 Label* label) { 951 MOZ_ASSERT(cond == Equal || cond == NotEqual); 952 ma_b(tag, ImmTag(JSVAL_TAG_MAGIC), label, cond); 953 } 954 955 void MacroAssembler::branchTestMagic(Condition cond, const Address& address, 956 Label* label) { 957 UseScratchRegisterScope temps(this); 958 Register scratch2 = temps.Acquire(); 959 Register tag = extractTag(address, scratch2); 960 branchTestMagic(cond, tag, label); 961 } 962 963 void MacroAssembler::branchTestMagic(Condition cond, const BaseIndex& address, 964 Label* label) { 965 UseScratchRegisterScope temps(this); 966 Register scratch2 = temps.Acquire(); 967 Register tag = extractTag(address, scratch2); 968 branchTestMagic(cond, tag, label); 969 } 970 971 void MacroAssembler::branchTestMagic(Condition cond, const ValueOperand& value, 972 Label* label) { 973 UseScratchRegisterScope temps(this); 974 Register scratch2 = temps.Acquire(); 975 splitTag(value, scratch2); 976 ma_b(scratch2, ImmTag(JSVAL_TAG_MAGIC), label, cond); 977 } 978 979 void MacroAssembler::branchTestMagic(Condition cond, const Address& valaddr, 980 JSWhyMagic why, Label* label) { 981 uint64_t magic = MagicValue(why).asRawBits(); 982 UseScratchRegisterScope temps(this); 983 Register scratch = temps.Acquire(); 984 loadPtr(valaddr, scratch); 985 ma_b(scratch, ImmWord(magic), label, cond); 986 } 987 void MacroAssembler::branchTestNull(Condition cond, Register tag, 988 Label* label) { 989 MOZ_ASSERT(cond == Equal || cond == NotEqual); 990 ma_b(tag, ImmTag(JSVAL_TAG_NULL), label, cond); 991 } 992 993 void MacroAssembler::branchTestNull(Condition cond, const ValueOperand& value, 994 Label* label) { 995 UseScratchRegisterScope temps(this); 996 Register scratch2 = temps.Acquire(); 997 splitTag(value, scratch2); 998 branchTestNull(cond, scratch2, label); 999 } 1000 1001 void MacroAssembler::branchTestNull(Condition cond, const Address& address, 1002 Label* label) { 1003 UseScratchRegisterScope temps(this); 1004 Register scratch2 = temps.Acquire(); 1005 Register tag = extractTag(address, scratch2); 1006 branchTestNull(cond, tag, label); 1007 } 1008 1009 void MacroAssembler::branchTestNull(Condition cond, const BaseIndex& address, 1010 Label* label) { 1011 UseScratchRegisterScope temps(this); 1012 Register scratch2 = temps.Acquire(); 1013 Register tag = extractTag(address, scratch2); 1014 branchTestNull(cond, tag, label); 1015 } 1016 void MacroAssembler::branchTestNumber(Condition cond, Register tag, 1017 Label* label) { 1018 MOZ_ASSERT(cond == Equal || cond == NotEqual); 1019 Condition actual = cond == Equal ? BelowOrEqual : Above; 1020 ma_b(tag, ImmTag(JS::detail::ValueUpperInclNumberTag), label, actual); 1021 } 1022 1023 void MacroAssembler::branchTestNumber(Condition cond, const ValueOperand& value, 1024 Label* label) { 1025 UseScratchRegisterScope temps(this); 1026 Register scratch2 = temps.Acquire(); 1027 splitTag(value, scratch2); 1028 branchTestNumber(cond, scratch2, label); 1029 } 1030 void MacroAssembler::branchTestObject(Condition cond, Register tag, 1031 Label* label) { 1032 MOZ_ASSERT(cond == Equal || cond == NotEqual); 1033 ma_b(tag, ImmTag(JSVAL_TAG_OBJECT), label, cond); 1034 } 1035 1036 void MacroAssembler::branchTestObject(Condition cond, const ValueOperand& value, 1037 Label* label) { 1038 UseScratchRegisterScope temps(this); 1039 Register scratch2 = temps.Acquire(); 1040 splitTag(value, scratch2); 1041 branchTestObject(cond, scratch2, label); 1042 } 1043 1044 void MacroAssembler::branchTestObject(Condition cond, const Address& address, 1045 Label* label) { 1046 UseScratchRegisterScope temps(this); 1047 Register scratch2 = temps.Acquire(); 1048 Register tag = extractTag(address, scratch2); 1049 branchTestObject(cond, tag, label); 1050 } 1051 1052 void MacroAssembler::branchTestObject(Condition cond, const BaseIndex& address, 1053 Label* label) { 1054 UseScratchRegisterScope temps(this); 1055 Register scratch2 = temps.Acquire(); 1056 Register tag = extractTag(address, scratch2); 1057 branchTestObject(cond, tag, label); 1058 } 1059 void MacroAssembler::branchTestPrimitive(Condition cond, 1060 const ValueOperand& value, 1061 Label* label) { 1062 UseScratchRegisterScope temps(this); 1063 Register scratch2 = temps.Acquire(); 1064 splitTag(value, scratch2); 1065 branchTestPrimitive(cond, scratch2, label); 1066 } 1067 void MacroAssembler::branchTestPrimitive(Condition cond, Register tag, 1068 Label* label) { 1069 MOZ_ASSERT(cond == Equal || cond == NotEqual); 1070 ma_b(tag, ImmTag(JS::detail::ValueUpperExclPrimitiveTag), label, 1071 (cond == Equal) ? Below : AboveOrEqual); 1072 } 1073 void MacroAssembler::branchTestPtr(Condition cond, Register lhs, Register rhs, 1074 Label* label) { 1075 MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || 1076 cond == NotSigned); 1077 if (lhs == rhs) { 1078 ma_b(lhs, rhs, label, cond); 1079 } else { 1080 UseScratchRegisterScope temps(this); 1081 Register scratch = temps.Acquire(); 1082 ma_and(scratch, lhs, Operand(rhs)); 1083 ma_b(scratch, scratch, label, cond); 1084 } 1085 } 1086 1087 void MacroAssembler::branchTestPtr(Condition cond, Register lhs, Imm32 rhs, 1088 Label* label) { 1089 MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || 1090 cond == NotSigned); 1091 UseScratchRegisterScope temps(this); 1092 Register scratch = temps.Acquire(); 1093 ma_and(scratch, lhs, rhs); 1094 ma_b(scratch, scratch, label, cond); 1095 } 1096 1097 void MacroAssembler::branchTestPtr(Condition cond, Register lhs, ImmWord rhs, 1098 Label* label) { 1099 MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || 1100 cond == NotSigned); 1101 UseScratchRegisterScope temps(this); 1102 Register scratch = temps.Acquire(); 1103 ma_li(scratch, rhs); 1104 ma_and(scratch, lhs, scratch); 1105 ma_b(scratch, scratch, label, cond); 1106 } 1107 1108 void MacroAssembler::branchTestPtr(Condition cond, const Address& lhs, 1109 Imm32 rhs, Label* label) { 1110 UseScratchRegisterScope temps(this); 1111 Register scratch2 = temps.Acquire(); 1112 loadPtr(lhs, scratch2); 1113 branchTestPtr(cond, scratch2, rhs, label); 1114 } 1115 void MacroAssembler::branchTestString(Condition cond, Register tag, 1116 Label* label) { 1117 MOZ_ASSERT(cond == Equal || cond == NotEqual); 1118 ma_b(tag, ImmTag(JSVAL_TAG_STRING), label, cond); 1119 } 1120 1121 void MacroAssembler::branchTestString(Condition cond, const ValueOperand& value, 1122 Label* label) { 1123 UseScratchRegisterScope temps(this); 1124 Register scratch2 = temps.Acquire(); 1125 splitTag(value, scratch2); 1126 branchTestString(cond, scratch2, label); 1127 } 1128 1129 void MacroAssembler::branchTestString(Condition cond, const Address& address, 1130 Label* label) { 1131 UseScratchRegisterScope temps(this); 1132 Register scratch2 = temps.Acquire(); 1133 Register tag = extractTag(address, scratch2); 1134 branchTestString(cond, tag, label); 1135 } 1136 1137 void MacroAssembler::branchTestString(Condition cond, const BaseIndex& address, 1138 Label* label) { 1139 UseScratchRegisterScope temps(this); 1140 Register scratch2 = temps.Acquire(); 1141 Register tag = extractTag(address, scratch2); 1142 branchTestString(cond, tag, label); 1143 } 1144 void MacroAssembler::branchTestStringTruthy(bool b, const ValueOperand& value, 1145 Label* label) { 1146 UseScratchRegisterScope temps(this); 1147 Register scratch2 = temps.Acquire(); 1148 unboxString(value, scratch2); 1149 load32(Address(scratch2, JSString::offsetOfLength()), scratch2); 1150 ma_b(scratch2, Imm32(0), label, b ? NotEqual : Equal); 1151 } 1152 void MacroAssembler::branchTestSymbol(Condition cond, Register tag, 1153 Label* label) { 1154 MOZ_ASSERT(cond == Equal || cond == NotEqual); 1155 ma_b(tag, ImmTag(JSVAL_TAG_SYMBOL), label, cond); 1156 } 1157 1158 void MacroAssembler::branchTestSymbol(Condition cond, const ValueOperand& value, 1159 Label* label) { 1160 UseScratchRegisterScope temps(this); 1161 Register scratch2 = temps.Acquire(); 1162 splitTag(value, scratch2); 1163 branchTestSymbol(cond, scratch2, label); 1164 } 1165 1166 void MacroAssembler::branchTestSymbol(Condition cond, const BaseIndex& address, 1167 Label* label) { 1168 UseScratchRegisterScope temps(this); 1169 Register scratch2 = temps.Acquire(); 1170 Register tag = extractTag(address, scratch2); 1171 branchTestSymbol(cond, tag, label); 1172 } 1173 1174 void MacroAssembler::branchTestSymbol(Condition cond, const Address& address, 1175 Label* label) { 1176 UseScratchRegisterScope temps(this); 1177 Register scratch2 = temps.Acquire(); 1178 Register tag = extractTag(address, scratch2); 1179 branchTestSymbol(cond, tag, label); 1180 } 1181 void MacroAssembler::branchTestUndefined(Condition cond, 1182 const ValueOperand& value, 1183 Label* label) { 1184 UseScratchRegisterScope temps(this); 1185 Register scratch2 = temps.Acquire(); 1186 splitTag(value, scratch2); 1187 branchTestUndefined(cond, scratch2, label); 1188 } 1189 1190 void MacroAssembler::branchTestUndefined(Condition cond, const Address& address, 1191 Label* label) { 1192 UseScratchRegisterScope temps(this); 1193 Register scratch2 = temps.Acquire(); 1194 Register tag = extractTag(address, scratch2); 1195 branchTestUndefined(cond, tag, label); 1196 } 1197 1198 void MacroAssembler::branchTestUndefined(Condition cond, 1199 const BaseIndex& address, 1200 Label* label) { 1201 UseScratchRegisterScope temps(this); 1202 Register scratch2 = temps.Acquire(); 1203 Register tag = extractTag(address, scratch2); 1204 branchTestUndefined(cond, tag, label); 1205 } 1206 void MacroAssembler::branchTestUndefined(Condition cond, Register tag, 1207 Label* label) { 1208 MOZ_ASSERT(cond == Equal || cond == NotEqual); 1209 ma_b(tag, ImmTag(JSVAL_TAG_UNDEFINED), label, cond); 1210 } 1211 template <typename T> 1212 void MacroAssembler::branchTestValue(Condition cond, const T& lhs, 1213 const ValueOperand& rhs, Label* label) { 1214 MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual); 1215 branchPtr(cond, lhs, rhs.valueReg(), label); 1216 } 1217 void MacroAssembler::branchToComputedAddress(const BaseIndex& addr) { 1218 UseScratchRegisterScope temps(this); 1219 Register scratch2 = temps.Acquire(); 1220 loadPtr(addr, scratch2); 1221 branch(scratch2); 1222 } 1223 void MacroAssembler::branchTruncateDoubleMaybeModUint32(FloatRegister src, 1224 Register dest, 1225 Label* fail) { 1226 UseScratchRegisterScope temps(this); 1227 1228 // Convert scalar to signed 64-bit fixed-point, rounding toward zero. 1229 // In the case of overflow or NaN, the output is saturated. 1230 // In the case of -0, the output is zero. 1231 Trunc_l_d(dest, src); 1232 1233 // Zero if NaN, so we don't take the failure path below. 1234 Clear_if_nan_d(dest, src); 1235 1236 // Unsigned subtraction of INT64_MAX returns 1 resp. 0 for INT64_{MIN,MAX}. 1237 Register scratch = temps.Acquire(); 1238 ma_li(scratch, Imm64(0x7fff'ffff'ffff'ffff)); 1239 ma_sub64(scratch, dest, scratch); 1240 1241 // Fail if the result is saturated. 1242 branchPtr(Assembler::BelowOrEqual, scratch, ImmWord(1), fail); 1243 1244 // Clear upper 32 bits. 1245 move32SignExtendToPtr(dest, dest); 1246 } 1247 1248 void MacroAssembler::branchTruncateDoubleToInt32(FloatRegister src, 1249 Register dest, Label* fail) { 1250 // Convert scalar to signed 64-bit fixed-point, rounding toward zero. 1251 // In the case of overflow or NaN, the output is saturated. 1252 // In the case of -0, the output is zero. 1253 Trunc_l_d(dest, src); 1254 1255 // Zero if NaN, so we don't take the failure path below. 1256 Clear_if_nan_d(dest, src); 1257 1258 // Sign extend lower 32 bits to test if the result isn't an Int32. 1259 { 1260 UseScratchRegisterScope temps(this); 1261 Register scratch = temps.Acquire(); 1262 1263 move32SignExtendToPtr(dest, scratch); 1264 branchPtr(Assembler::NotEqual, dest, scratch, fail); 1265 } 1266 } 1267 void MacroAssembler::branchTruncateFloat32MaybeModUint32(FloatRegister src, 1268 Register dest, 1269 Label* fail) { 1270 // Infallible operation on riscv64. 1271 truncateFloat32ModUint32(src, dest); 1272 } 1273 1274 void MacroAssembler::branchTruncateFloat32ToInt32(FloatRegister src, 1275 Register dest, Label* fail) { 1276 // Convert scalar to signed 64-bit fixed-point, rounding toward zero. 1277 // In the case of overflow or NaN, the output is saturated. 1278 // In the case of -0, the output is zero. 1279 Trunc_l_s(dest, src); 1280 1281 // Zero if NaN, so we don't take the failure path below. 1282 Clear_if_nan_s(dest, src); 1283 1284 // Sign extend lower 32 bits to test if the result isn't an Int32. 1285 { 1286 UseScratchRegisterScope temps(this); 1287 Register scratch = temps.Acquire(); 1288 1289 move32SignExtendToPtr(dest, scratch); 1290 branchPtr(Assembler::NotEqual, dest, scratch, fail); 1291 } 1292 } 1293 1294 void MacroAssembler::branchInt64NotInPtrRange(Register64 src, Label* label) { 1295 // No-op on 64-bit platforms. 1296 } 1297 1298 void MacroAssembler::branchUInt64NotInPtrRange(Register64 src, Label* label) { 1299 branchTest64(Assembler::Signed, src, src, label); 1300 } 1301 1302 void MacroAssembler::byteSwap16SignExtend(Register src) { 1303 JitSpew(JitSpew_Codegen, "[ %s\n", __FUNCTION__); 1304 UseScratchRegisterScope temps(this); 1305 Register scratch = temps.Acquire(); 1306 Register scratch2 = temps.Acquire(); 1307 // src 0xFFFFFFFFFFFF8000 1308 andi(scratch, src, 0xFF); // 1309 slli(scratch, scratch, 8); // scratch 0x00 1310 ma_li(scratch2, 0xFF00); // scratch2 0xFF00 1311 and_(src, src, scratch2); // src 0x8000 1312 srli(src, src, 8); // src 0x0080 1313 or_(src, src, scratch); // src 0x0080 1314 slliw(src, src, 16); 1315 sraiw(src, src, 16); 1316 JitSpew(JitSpew_Codegen, "]"); 1317 } 1318 1319 void MacroAssembler::byteSwap16ZeroExtend(Register src) { 1320 JitSpew(JitSpew_Codegen, "[ %s\n", __FUNCTION__); 1321 UseScratchRegisterScope temps(this); 1322 Register scratch = temps.Acquire(); 1323 Register scratch2 = temps.Acquire(); 1324 andi(scratch, src, 0xFF); 1325 slli(scratch, scratch, 8); 1326 ma_li(scratch2, 0xFF00); 1327 and_(src, src, scratch2); 1328 srli(src, src, 8); 1329 or_(src, src, scratch); 1330 slliw(src, src, 16); 1331 srliw(src, src, 16); 1332 JitSpew(JitSpew_Codegen, "]"); 1333 } 1334 1335 void MacroAssembler::byteSwap32(Register src) { 1336 UseScratchRegisterScope temps(this); 1337 Register scratch = temps.Acquire(); 1338 ByteSwap(src, src, 4, scratch); 1339 } 1340 void MacroAssembler::byteSwap64(Register64 src) { 1341 UseScratchRegisterScope temps(this); 1342 Register scratch = temps.Acquire(); 1343 ByteSwap(src.reg, src.reg, 8, scratch); 1344 } 1345 void MacroAssembler::clampIntToUint8(Register reg) { 1346 // If reg is < 0, then we want to clamp to 0. 1347 { 1348 UseScratchRegisterScope temps(this); 1349 Register scratch = temps.Acquire(); 1350 1351 // reg = -(reg > 0 ? 1 : 0) & reg 1352 sgtz(scratch, reg); 1353 neg(scratch, scratch); 1354 and_(reg, reg, scratch); 1355 } 1356 1357 // If reg is >= 255, then we want to clamp to 255. 1358 Label skip; 1359 ma_branch(&skip, LessThanOrEqual, reg, Operand(255)); 1360 { 1361 ma_li(reg, Imm32(255)); 1362 } 1363 bind(&skip); 1364 } 1365 1366 void MacroAssembler::clz32(Register src, Register dest, bool knownNotZero) { 1367 Clz32(dest, src); 1368 } 1369 void MacroAssembler::clz64(Register64 src, Register64 dest) { 1370 Clz64(dest.reg, src.reg); 1371 } 1372 1373 void MacroAssembler::ctz64(Register64 src, Register64 dest) { 1374 Ctz64(dest.reg, src.reg); 1375 } 1376 1377 void MacroAssembler::cmp16Set(Condition cond, Address lhs, Imm32 rhs, 1378 Register dest) { 1379 UseScratchRegisterScope temps(this); 1380 Register scratch2 = temps.Acquire(); 1381 MOZ_ASSERT(scratch2 != lhs.base); 1382 1383 switch (cond) { 1384 case Assembler::Equal: 1385 case Assembler::NotEqual: 1386 case Assembler::Above: 1387 case Assembler::AboveOrEqual: 1388 case Assembler::Below: 1389 case Assembler::BelowOrEqual: 1390 load16ZeroExtend(lhs, scratch2); 1391 ma_cmp_set(dest, scratch2, Imm32(uint16_t(rhs.value)), cond); 1392 break; 1393 1394 case Assembler::GreaterThan: 1395 case Assembler::GreaterThanOrEqual: 1396 case Assembler::LessThan: 1397 case Assembler::LessThanOrEqual: 1398 load16SignExtend(lhs, scratch2); 1399 ma_cmp_set(dest, scratch2, Imm32(int16_t(rhs.value)), cond); 1400 break; 1401 1402 default: 1403 MOZ_CRASH("unexpected condition"); 1404 } 1405 } 1406 1407 void MacroAssembler::cmp32Load32(Condition cond, Register lhs, 1408 const Address& rhs, const Address& src, 1409 Register dest) { 1410 UseScratchRegisterScope temps(this); 1411 Register scratch = temps.Acquire(); 1412 MOZ_ASSERT(lhs != scratch && dest != scratch); 1413 load32(rhs, scratch); 1414 cmp32Load32(cond, lhs, scratch, src, dest); 1415 } 1416 1417 void MacroAssembler::cmp32Load32(Condition cond, Register lhs, Register rhs, 1418 const Address& src, Register dest) { 1419 Label skip; 1420 branch32(Assembler::InvertCondition(cond), lhs, rhs, &skip); 1421 load32(src, dest); 1422 bind(&skip); 1423 } 1424 1425 void MacroAssembler::cmp32Load32(Condition cond, Register lhs, Imm32 rhs, 1426 const Address& src, Register dest) { 1427 Label skip; 1428 branch32(Assembler::InvertCondition(cond), lhs, rhs, &skip); 1429 load32(src, dest); 1430 bind(&skip); 1431 } 1432 1433 void MacroAssembler::cmp32LoadPtr(Condition cond, const Address& lhs, Imm32 rhs, 1434 const Address& src, Register dest) { 1435 Label skip; 1436 branch32(Assembler::InvertCondition(cond), lhs, rhs, &skip); 1437 loadPtr(src, dest); 1438 bind(&skip); 1439 } 1440 1441 void MacroAssembler::cmp32Move32(Condition cond, Register lhs, Imm32 rhs, 1442 Register src, Register dest) { 1443 UseScratchRegisterScope temps(this); 1444 Register scratch2 = temps.Acquire(); 1445 cmp32Set(cond, lhs, rhs, scratch2); 1446 moveIfNotZero(dest, src, scratch2); 1447 } 1448 1449 void MacroAssembler::cmp32Move32(Condition cond, Register lhs, Register rhs, 1450 Register src, Register dest) { 1451 UseScratchRegisterScope temps(this); 1452 Register scratch2 = temps.Acquire(); 1453 cmp32Set(cond, lhs, rhs, scratch2); 1454 moveIfNotZero(dest, src, scratch2); 1455 } 1456 1457 void MacroAssembler::cmp32Move32(Condition cond, Register lhs, 1458 const Address& rhs, Register src, 1459 Register dest) { 1460 UseScratchRegisterScope temps(this); 1461 Register scratch2 = temps.Acquire(); 1462 MOZ_ASSERT(lhs != scratch2 && src != scratch2 && dest != scratch2); 1463 load32(rhs, scratch2); 1464 cmp32Move32(cond, lhs, scratch2, src, dest); 1465 } 1466 void MacroAssembler::cmp32MovePtr(Condition cond, Register lhs, Imm32 rhs, 1467 Register src, Register dest) { 1468 UseScratchRegisterScope temps(this); 1469 Register scratch2 = temps.Acquire(); 1470 cmp32Set(cond, lhs, rhs, scratch2); 1471 moveIfNotZero(dest, src, scratch2); 1472 } 1473 void MacroAssembler::cmp64Set(Condition cond, Register64 lhs, Register64 rhs, 1474 Register dest) { 1475 ma_cmp_set(dest, lhs.reg, rhs.reg, cond); 1476 } 1477 void MacroAssembler::cmp64Set(Condition cond, Register64 lhs, Imm64 rhs, 1478 Register dest) { 1479 ma_cmp_set(dest, lhs.reg, ImmWord(uint64_t(rhs.value)), cond); 1480 } 1481 void MacroAssembler::cmp64Set(Condition cond, Address lhs, Register64 rhs, 1482 Register dest) { 1483 ma_cmp_set(dest, lhs, rhs.reg, cond); 1484 } 1485 void MacroAssembler::cmp64Set(Condition cond, Address lhs, Imm64 rhs, 1486 Register dest) { 1487 ma_cmp_set(dest, lhs, ImmWord(uint64_t(rhs.value)), cond); 1488 } 1489 void MacroAssembler::cmp8Set(Condition cond, Address lhs, Imm32 rhs, 1490 Register dest) { 1491 UseScratchRegisterScope temps(this); 1492 Register scratch2 = temps.Acquire(); 1493 MOZ_ASSERT(scratch2 != lhs.base); 1494 1495 switch (cond) { 1496 case Assembler::Equal: 1497 case Assembler::NotEqual: 1498 case Assembler::Above: 1499 case Assembler::AboveOrEqual: 1500 case Assembler::Below: 1501 case Assembler::BelowOrEqual: 1502 load8ZeroExtend(lhs, scratch2); 1503 ma_cmp_set(dest, scratch2, Imm32(uint8_t(rhs.value)), cond); 1504 break; 1505 1506 case Assembler::GreaterThan: 1507 case Assembler::GreaterThanOrEqual: 1508 case Assembler::LessThan: 1509 case Assembler::LessThanOrEqual: 1510 load8SignExtend(lhs, scratch2); 1511 ma_cmp_set(dest, scratch2, Imm32(int8_t(rhs.value)), cond); 1512 break; 1513 1514 default: 1515 MOZ_CRASH("unexpected condition"); 1516 } 1517 } 1518 void MacroAssembler::cmpPtrMovePtr(Condition cond, Register lhs, Register rhs, 1519 Register src, Register dest) { 1520 UseScratchRegisterScope temps(this); 1521 Register scratch2 = temps.Acquire(); 1522 cmpPtrSet(cond, lhs, rhs, scratch2); 1523 moveIfNotZero(dest, src, scratch2); 1524 } 1525 1526 void MacroAssembler::cmpPtrMovePtr(Condition cond, Register lhs, Imm32 rhs, 1527 Register src, Register dest) { 1528 MOZ_CRASH("NYI"); 1529 } 1530 1531 void MacroAssembler::cmpPtrMovePtr(Condition cond, Register lhs, 1532 const Address& rhs, Register src, 1533 Register dest) { 1534 MOZ_CRASH("NYI"); 1535 } 1536 1537 void MacroAssembler::ctz32(Register src, Register dest, bool knownNotZero) { 1538 Ctz32(dest, src); 1539 } 1540 1541 void MacroAssembler::decBranchPtr(Condition cond, Register lhs, Imm32 rhs, 1542 Label* label) { 1543 subPtr(rhs, lhs); 1544 branchPtr(cond, lhs, Imm32(0), label); 1545 } 1546 void MacroAssembler::divFloat32(FloatRegister src, FloatRegister dest) { 1547 fdiv_s(dest, dest, src); 1548 } 1549 1550 void MacroAssembler::divDouble(FloatRegister src, FloatRegister dest) { 1551 fdiv_d(dest, dest, src); 1552 } 1553 void MacroAssembler::fallibleUnboxPtr(const ValueOperand& src, Register dest, 1554 JSValueType type, Label* fail) { 1555 MOZ_ASSERT(type == JSVAL_TYPE_OBJECT || type == JSVAL_TYPE_STRING || 1556 type == JSVAL_TYPE_SYMBOL || type == JSVAL_TYPE_BIGINT); 1557 // dest := src XOR mask 1558 // scratch := dest >> JSVAL_TAG_SHIFT 1559 // fail if scratch != 0 1560 // 1561 // Note: src and dest can be the same register 1562 UseScratchRegisterScope temps(this); 1563 Register scratch = temps.Acquire(); 1564 MOZ_ASSERT(src.valueReg() != scratch); 1565 mov(ImmShiftedTag(type), scratch); 1566 xor_(dest, src.valueReg(), scratch); 1567 srli(scratch, dest, JSVAL_TAG_SHIFT); 1568 ma_b(scratch, Imm32(0), fail, Assembler::NotEqual); 1569 } 1570 1571 void MacroAssembler::fallibleUnboxPtr(const Address& src, Register dest, 1572 JSValueType type, Label* fail) { 1573 loadValue(src, ValueOperand(dest)); 1574 fallibleUnboxPtr(ValueOperand(dest), dest, type, fail); 1575 } 1576 1577 void MacroAssembler::fallibleUnboxPtr(const BaseIndex& src, Register dest, 1578 JSValueType type, Label* fail) { 1579 loadValue(src, ValueOperand(dest)); 1580 fallibleUnboxPtr(ValueOperand(dest), dest, type, fail); 1581 } 1582 void MacroAssembler::flexibleLshift32(Register src, Register dest) { 1583 lshift32(src, dest); 1584 } 1585 void MacroAssembler::flexibleRshift32Arithmetic(Register src, Register dest) { 1586 rshift32Arithmetic(src, dest); 1587 } 1588 void MacroAssembler::flexibleRshift32(Register src, Register dest) { 1589 rshift32(src, dest); 1590 } 1591 void MacroAssembler::inc64(AbsoluteAddress dest) { 1592 UseScratchRegisterScope temps(this); 1593 Register scratch = temps.Acquire(); 1594 Register scratch2 = temps.Acquire(); 1595 ma_li(scratch, ImmWord(uintptr_t(dest.addr))); 1596 ld(scratch2, scratch, 0); 1597 addi(scratch2, scratch2, 1); 1598 sd(scratch2, scratch, 0); 1599 } 1600 1601 void MacroAssembler::load32SignExtendToPtr(const Address& src, Register dest) { 1602 load32(src, dest); 1603 } 1604 void MacroAssembler::loadAbiReturnAddress(Register dest) { movePtr(ra, dest); } 1605 1606 void MacroAssembler::lshift32(Register src, Register dest) { 1607 sllw(dest, dest, src); 1608 } 1609 1610 void MacroAssembler::lshift32(Imm32 imm, Register dest) { 1611 lshift32(imm, dest, dest); 1612 } 1613 1614 void MacroAssembler::lshift32(Imm32 imm, Register src, Register dest) { 1615 slliw(dest, src, imm.value & 0x1f); 1616 } 1617 1618 void MacroAssembler::lshift64(Register shift, Register64 dest) { 1619 sll(dest.reg, dest.reg, shift); 1620 } 1621 1622 void MacroAssembler::lshift64(Imm32 imm, Register64 dest) { 1623 MOZ_ASSERT(0 <= imm.value && imm.value < 64); 1624 slli(dest.reg, dest.reg, imm.value); 1625 } 1626 void MacroAssembler::lshiftPtr(Register shift, Register dest) { 1627 sll(dest, dest, shift); 1628 } 1629 1630 void MacroAssembler::lshiftPtr(Imm32 imm, Register dest) { 1631 lshiftPtr(imm, dest, dest); 1632 } 1633 1634 void MacroAssembler::lshiftPtr(Imm32 imm, Register src, Register dest) { 1635 MOZ_ASSERT(0 <= imm.value && imm.value < 64); 1636 slli(dest, src, imm.value); 1637 } 1638 1639 void MacroAssembler::flexibleLshiftPtr(Register shift, Register srcDest) { 1640 lshiftPtr(shift, srcDest); 1641 } 1642 1643 void MacroAssembler::min32(Register lhs, Register rhs, Register dest) { 1644 minMax32(lhs, rhs, dest, /* isMax = */ false); 1645 } 1646 1647 void MacroAssembler::min32(Register lhs, Imm32 rhs, Register dest) { 1648 minMax32(lhs, rhs, dest, /* isMax = */ false); 1649 } 1650 1651 void MacroAssembler::max32(Register lhs, Register rhs, Register dest) { 1652 minMax32(lhs, rhs, dest, /* isMax = */ true); 1653 } 1654 1655 void MacroAssembler::max32(Register lhs, Imm32 rhs, Register dest) { 1656 minMax32(lhs, rhs, dest, /* isMax = */ true); 1657 } 1658 1659 void MacroAssembler::minPtr(Register lhs, Register rhs, Register dest) { 1660 minMaxPtr(lhs, rhs, dest, /* isMax = */ false); 1661 } 1662 1663 void MacroAssembler::minPtr(Register lhs, ImmWord rhs, Register dest) { 1664 minMaxPtr(lhs, rhs, dest, /* isMax = */ false); 1665 } 1666 1667 void MacroAssembler::maxPtr(Register lhs, Register rhs, Register dest) { 1668 minMaxPtr(lhs, rhs, dest, /* isMax = */ true); 1669 } 1670 1671 void MacroAssembler::maxPtr(Register lhs, ImmWord rhs, Register dest) { 1672 minMaxPtr(lhs, rhs, dest, /* isMax = */ true); 1673 } 1674 1675 void MacroAssembler::maxDouble(FloatRegister other, FloatRegister srcDest, 1676 bool handleNaN) { 1677 Float64Max(srcDest, srcDest, other); 1678 } 1679 void MacroAssembler::maxFloat32(FloatRegister other, FloatRegister srcDest, 1680 bool handleNaN) { 1681 Float32Max(srcDest, srcDest, other); 1682 } 1683 void MacroAssembler::memoryBarrier(MemoryBarrier barrier) { 1684 if (!barrier.isNone()) { 1685 sync(); 1686 } 1687 } 1688 void MacroAssembler::minDouble(FloatRegister other, FloatRegister srcDest, 1689 bool handleNaN) { 1690 Float64Min(srcDest, srcDest, other); 1691 } 1692 void MacroAssembler::minFloat32(FloatRegister other, FloatRegister srcDest, 1693 bool handleNaN) { 1694 Float32Min(srcDest, srcDest, other); 1695 } 1696 void MacroAssembler::move16SignExtend(Register src, Register dest) { 1697 slli(dest, src, xlen - 16); 1698 srai(dest, dest, xlen - 16); 1699 } 1700 void MacroAssembler::move16To64SignExtend(Register src, Register64 dest) { 1701 move32To64SignExtend(src, dest); 1702 move16SignExtend(dest.reg, dest.reg); 1703 } 1704 void MacroAssembler::move8SignExtendToPtr(Register src, Register dest) { 1705 move8To64SignExtend(src, Register64(dest)); 1706 } 1707 void MacroAssembler::move16SignExtendToPtr(Register src, Register dest) { 1708 move16To64SignExtend(src, Register64(dest)); 1709 } 1710 void MacroAssembler::move32SignExtendToPtr(Register src, Register dest) { 1711 SignExtendWord(dest, src); 1712 } 1713 void MacroAssembler::move32To64SignExtend(Register src, Register64 dest) { 1714 SignExtendWord(dest.reg, src); 1715 } 1716 void MacroAssembler::move32To64ZeroExtend(Register src, Register64 dest) { 1717 slli(dest.reg, src, 32); 1718 srli(dest.reg, dest.reg, 32); 1719 } 1720 void MacroAssembler::move32ZeroExtendToPtr(Register src, Register dest) { 1721 slli(dest, src, 32); 1722 srli(dest, dest, 32); 1723 } 1724 void MacroAssembler::move64(Register64 src, Register64 dest) { 1725 movePtr(src.reg, dest.reg); 1726 } 1727 1728 void MacroAssembler::move64(Imm64 imm, Register64 dest) { 1729 movePtr(ImmWord(imm.value), dest.reg); 1730 } 1731 1732 void MacroAssembler::move64To32(Register64 src, Register dest) { 1733 SignExtendWord(dest, src.reg); 1734 } 1735 1736 void MacroAssembler::move8ZeroExtend(Register src, Register dest) { 1737 andi(dest, src, 0xFF); 1738 } 1739 1740 void MacroAssembler::move8SignExtend(Register src, Register dest) { 1741 slli(dest, src, xlen - 8); 1742 srai(dest, dest, xlen - 8); 1743 } 1744 void MacroAssembler::move8To64SignExtend(Register src, Register64 dest) { 1745 move32To64SignExtend(src, dest); 1746 move8SignExtend(dest.reg, dest.reg); 1747 } 1748 void MacroAssembler::moveDoubleToGPR64(FloatRegister src, Register64 dest) { 1749 fmv_x_d(dest.reg, src); 1750 } 1751 1752 void MacroAssembler::moveGPR64ToDouble(Register64 src, FloatRegister dest) { 1753 fmv_d_x(dest, src.reg); 1754 } 1755 void MacroAssembler::moveLowDoubleToGPR(FloatRegister src, Register dest) { 1756 MOZ_CRASH("Not supported for this target"); 1757 } 1758 void MacroAssembler::moveFloat32ToGPR(FloatRegister src, Register dest) { 1759 fmv_x_w(dest, src); 1760 } 1761 void MacroAssembler::moveGPRToFloat32(Register src, FloatRegister dest) { 1762 fmv_w_x(dest, src); 1763 } 1764 void MacroAssembler::moveFloat16ToGPR(FloatRegister src, Register dest) { 1765 MOZ_CRASH("Not supported for this target"); 1766 } 1767 void MacroAssembler::moveGPRToFloat16(Register src, FloatRegister dest) { 1768 MOZ_CRASH("Not supported for this target"); 1769 } 1770 void MacroAssembler::mul32(Register rhs, Register srcDest) { 1771 mulw(srcDest, srcDest, rhs); 1772 } 1773 1774 void MacroAssembler::mul32(Imm32 imm, Register srcDest) { 1775 UseScratchRegisterScope temps(this); 1776 Register scratch = temps.Acquire(); 1777 MOZ_ASSERT(srcDest != scratch); 1778 move32(imm, scratch); 1779 mul32(scratch, srcDest); 1780 } 1781 1782 void MacroAssembler::mulHighUnsigned32(Imm32 imm, Register src, Register dest) { 1783 UseScratchRegisterScope temps(this); 1784 Register scratch = temps.Acquire(); 1785 MOZ_ASSERT(src != scratch); 1786 ma_li(scratch, uint32_t(imm.value)); 1787 mul(dest, src, scratch); 1788 srli(dest, dest, 32); 1789 } 1790 1791 void MacroAssembler::mul64(Imm64 imm, const Register64& dest) { 1792 UseScratchRegisterScope temps(this); 1793 Register scratch = temps.Acquire(); 1794 MOZ_ASSERT(dest.reg != scratch); 1795 mov(ImmWord(imm.value), scratch); 1796 mul(dest.reg, dest.reg, scratch); 1797 } 1798 1799 void MacroAssembler::mul64(Imm64 imm, const Register64& dest, 1800 const Register temp) { 1801 MOZ_ASSERT(temp == Register::Invalid()); 1802 mul64(imm, dest); 1803 } 1804 1805 void MacroAssembler::mul64(const Register64& src, const Register64& dest, 1806 const Register temp) { 1807 MOZ_ASSERT(temp == Register::Invalid()); 1808 mul(dest.reg, dest.reg, src.reg); 1809 } 1810 1811 void MacroAssembler::mulBy3(Register src, Register dest) { 1812 UseScratchRegisterScope temps(this); 1813 Register scratch = temps.Acquire(); 1814 MOZ_ASSERT(src != scratch); 1815 add(scratch, src, src); 1816 add(dest, scratch, src); 1817 } 1818 void MacroAssembler::mulDouble(FloatRegister src, FloatRegister dest) { 1819 fmul_d(dest, dest, src); 1820 } 1821 void MacroAssembler::mulDoublePtr(ImmPtr imm, Register temp, 1822 FloatRegister dest) { 1823 UseScratchRegisterScope temps(this); 1824 Register scratch = temps.Acquire(); 1825 ScratchDoubleScope fpscratch(asMasm()); 1826 movePtr(imm, scratch); 1827 loadDouble(Address(scratch, 0), fpscratch); 1828 mulDouble(fpscratch, dest); 1829 } 1830 void MacroAssembler::mulFloat32(FloatRegister src, FloatRegister dest) { 1831 fmul_s(dest, dest, src); 1832 } 1833 void MacroAssembler::mulPtr(Register rhs, Register srcDest) { 1834 mul(srcDest, srcDest, rhs); 1835 } 1836 void MacroAssembler::mulPtr(ImmWord rhs, Register srcDest) { 1837 UseScratchRegisterScope temps(this); 1838 Register scratch = temps.Acquire(); 1839 MOZ_ASSERT(srcDest != scratch); 1840 mov(rhs, scratch); 1841 mulPtr(scratch, srcDest); 1842 } 1843 1844 void MacroAssembler::negateDouble(FloatRegister reg) { fneg_d(reg, reg); } 1845 1846 void MacroAssembler::negateFloat(FloatRegister reg) { fneg_s(reg, reg); } 1847 1848 void MacroAssembler::neg64(Register64 reg) { neg(reg.reg, reg.reg); } 1849 1850 void MacroAssembler::negPtr(Register reg) { neg(reg, reg); } 1851 1852 void MacroAssembler::neg32(Register reg) { negw(reg, reg); } 1853 void MacroAssembler::not32(Register reg) { not_(reg, reg); } 1854 1855 void MacroAssembler::notPtr(Register reg) { not_(reg, reg); } 1856 1857 void MacroAssembler::or32(Register src, Register dest) { 1858 ma_or(dest, dest, src); 1859 } 1860 1861 void MacroAssembler::or32(Imm32 imm, Register dest) { ma_or(dest, dest, imm); } 1862 1863 void MacroAssembler::or32(Imm32 imm, Register src, Register dest) { 1864 ma_or(dest, src, imm); 1865 } 1866 1867 void MacroAssembler::or32(Imm32 imm, const Address& dest) { 1868 UseScratchRegisterScope temps(this); 1869 Register scratch2 = temps.Acquire(); 1870 load32(dest, scratch2); 1871 ma_or(scratch2, imm); 1872 store32(scratch2, dest); 1873 } 1874 1875 void MacroAssembler::or64(Register64 src, Register64 dest) { 1876 ma_or(dest.reg, dest.reg, src.reg); 1877 } 1878 1879 void MacroAssembler::or64(Imm64 imm, Register64 dest) { 1880 UseScratchRegisterScope temps(this); 1881 Register scratch = temps.Acquire(); 1882 ma_li(scratch, ImmWord(imm.value)); 1883 ma_or(dest.reg, dest.reg, scratch); 1884 } 1885 1886 void MacroAssembler::orPtr(Register src, Register dest) { 1887 ma_or(dest, dest, src); 1888 } 1889 1890 void MacroAssembler::orPtr(Imm32 imm, Register dest) { ma_or(dest, dest, imm); } 1891 1892 void MacroAssembler::orPtr(Imm32 imm, Register src, Register dest) { 1893 ma_or(dest, src, imm); 1894 } 1895 1896 void MacroAssembler::patchSub32FromStackPtr(CodeOffset offset, Imm32 imm) { 1897 DEBUG_PRINTF("patchSub32FromStackPtr at offset %zu with immediate %d\n", 1898 offset.offset(), imm.value); 1899 Instruction* inst0 = 1900 (Instruction*)m_buffer.getInst(BufferOffset(offset.offset())); 1901 Instruction* inst1 = 1902 (Instruction*)m_buffer.getInst(BufferOffset(offset.offset() + 4)); 1903 MOZ_ASSERT(IsLui(*reinterpret_cast<Instr*>(inst0))); 1904 MOZ_ASSERT(IsAddi(*reinterpret_cast<Instr*>(inst1))); 1905 1906 int64_t value = imm.value; 1907 int64_t high_20 = ((value + 0x800) >> 12); 1908 int64_t low_12 = value << 52 >> 52; 1909 1910 uint32_t* p0 = reinterpret_cast<uint32_t*>(inst0); 1911 uint32_t* p1 = reinterpret_cast<uint32_t*>(inst1); 1912 1913 (*p0) = (*p0) & 0xfff; 1914 (*p0) = (*p0) | ((int32_t)high_20 << 12); 1915 (*p1) = (*p1) & 0xfffff; 1916 (*p1) = (*p1) | ((int32_t)low_12 << 20); 1917 1918 disassembleInstr(inst0->InstructionBits()); 1919 disassembleInstr(inst1->InstructionBits()); 1920 MOZ_ASSERT((int32_t)(inst0->Imm20UValue() << kImm20Shift) + 1921 (int32_t)(inst1->Imm12Value()) == 1922 imm.value); 1923 } 1924 1925 void MacroAssembler::popcnt32(Register input, Register output, Register tmp) { 1926 Popcnt32(output, input, tmp); 1927 } 1928 void MacroAssembler::popcnt64(Register64 input, Register64 output, 1929 Register tmp) { 1930 Popcnt64(output.reg, input.reg, tmp); 1931 } 1932 void MacroAssembler::quotient32(Register lhs, Register rhs, Register dest, 1933 bool isUnsigned) { 1934 if (isUnsigned) { 1935 ma_divu32(dest, lhs, rhs); 1936 } else { 1937 ma_div32(dest, lhs, rhs); 1938 } 1939 } 1940 1941 void MacroAssembler::quotient64(Register lhs, Register rhs, Register dest, 1942 bool isUnsigned) { 1943 if (isUnsigned) { 1944 ma_divu64(dest, lhs, rhs); 1945 } else { 1946 ma_div64(dest, lhs, rhs); 1947 } 1948 } 1949 1950 void MacroAssembler::remainder32(Register lhs, Register rhs, Register dest, 1951 bool isUnsigned) { 1952 if (isUnsigned) { 1953 ma_modu32(dest, lhs, rhs); 1954 } else { 1955 ma_mod32(dest, lhs, rhs); 1956 } 1957 } 1958 1959 void MacroAssembler::remainder64(Register lhs, Register rhs, Register dest, 1960 bool isUnsigned) { 1961 if (isUnsigned) { 1962 ma_modu64(dest, lhs, rhs); 1963 } else { 1964 ma_mod64(dest, lhs, rhs); 1965 } 1966 } 1967 1968 void MacroAssembler::rotateLeft64(Imm32 count, Register64 src, Register64 dest, 1969 Register temp) { 1970 Drol(dest.reg, src.reg, Operand(count.value)); 1971 } 1972 void MacroAssembler::rotateLeft64(Register count, Register64 src, 1973 Register64 dest, Register temp) { 1974 Drol(dest.reg, src.reg, Operand(count)); 1975 } 1976 1977 void MacroAssembler::rotateLeft(Imm32 count, Register input, Register dest) { 1978 Rol(dest, input, Operand(count.value)); 1979 } 1980 void MacroAssembler::rotateLeft(Register count, Register input, Register dest) { 1981 Rol(dest, input, Operand(count)); 1982 } 1983 1984 void MacroAssembler::rotateRight64(Imm32 count, Register64 src, Register64 dest, 1985 Register temp) { 1986 Dror(dest.reg, src.reg, Operand(count.value)); 1987 } 1988 void MacroAssembler::rotateRight64(Register count, Register64 src, 1989 Register64 dest, Register temp) { 1990 Dror(dest.reg, src.reg, Operand(count)); 1991 } 1992 1993 void MacroAssembler::rotateRight(Imm32 count, Register input, Register dest) { 1994 Ror(dest, input, Operand(count.value)); 1995 } 1996 void MacroAssembler::rotateRight(Register count, Register input, 1997 Register dest) { 1998 Ror(dest, input, Operand(count)); 1999 } 2000 2001 void MacroAssembler::rshift32Arithmetic(Register src, Register dest) { 2002 sraw(dest, dest, src); 2003 } 2004 2005 void MacroAssembler::rshift32Arithmetic(Imm32 imm, Register dest) { 2006 rshift32Arithmetic(imm, dest, dest); 2007 } 2008 2009 void MacroAssembler::rshift32Arithmetic(Imm32 imm, Register src, 2010 Register dest) { 2011 sraiw(dest, src, imm.value & 0x1f); 2012 } 2013 2014 void MacroAssembler::rshift32(Register src, Register dest) { 2015 srlw(dest, dest, src); 2016 } 2017 2018 void MacroAssembler::rshift32(Imm32 imm, Register dest) { 2019 rshift32(imm, dest, dest); 2020 } 2021 2022 void MacroAssembler::rshift32(Imm32 imm, Register src, Register dest) { 2023 srliw(dest, src, imm.value & 0x1f); 2024 } 2025 2026 void MacroAssembler::rshift64Arithmetic(Imm32 imm, Register64 dest) { 2027 MOZ_ASSERT(0 <= imm.value && imm.value < 64); 2028 srai(dest.reg, dest.reg, imm.value); 2029 } 2030 2031 void MacroAssembler::rshift64Arithmetic(Register shift, Register64 dest) { 2032 sra(dest.reg, dest.reg, shift); 2033 } 2034 2035 void MacroAssembler::rshift64(Register shift, Register64 dest) { 2036 srl(dest.reg, dest.reg, shift); 2037 } 2038 2039 void MacroAssembler::rshift64(Imm32 imm, Register64 dest) { 2040 MOZ_ASSERT(0 <= imm.value && imm.value < 64); 2041 srli(dest.reg, dest.reg, imm.value); 2042 } 2043 2044 void MacroAssembler::rshiftPtrArithmetic(Imm32 imm, Register dest) { 2045 rshiftPtrArithmetic(imm, dest, dest); 2046 } 2047 2048 void MacroAssembler::rshiftPtrArithmetic(Imm32 imm, Register src, 2049 Register dest) { 2050 MOZ_ASSERT(0 <= imm.value && imm.value < 64); 2051 srai(dest, src, imm.value); 2052 } 2053 2054 void MacroAssembler::rshiftPtrArithmetic(Register shift, Register dest) { 2055 sra(dest, dest, shift); 2056 } 2057 2058 void MacroAssembler::flexibleRshiftPtrArithmetic(Register shift, 2059 Register srcDest) { 2060 rshiftPtrArithmetic(shift, srcDest); 2061 } 2062 2063 void MacroAssembler::rshiftPtr(Register shift, Register dest) { 2064 srl(dest, dest, shift); 2065 } 2066 2067 void MacroAssembler::rshiftPtr(Imm32 imm, Register dest) { 2068 rshiftPtr(imm, dest, dest); 2069 } 2070 2071 void MacroAssembler::rshiftPtr(Imm32 imm, Register src, Register dest) { 2072 MOZ_ASSERT(0 <= imm.value && imm.value < 64); 2073 srli(dest, src, imm.value); 2074 } 2075 2076 void MacroAssembler::flexibleRshiftPtr(Register shift, Register srcDest) { 2077 rshiftPtr(shift, srcDest); 2078 } 2079 2080 void MacroAssembler::spectreBoundsCheck32(Register index, Register length, 2081 Register maybeScratch, 2082 Label* failure) { 2083 MOZ_RELEASE_ASSERT(!JitOptions.spectreIndexMasking); 2084 branch32(Assembler::BelowOrEqual, length, index, failure); 2085 } 2086 2087 void MacroAssembler::spectreBoundsCheck32(Register index, const Address& length, 2088 Register maybeScratch, 2089 Label* failure) { 2090 MOZ_RELEASE_ASSERT(!JitOptions.spectreIndexMasking); 2091 branch32(Assembler::BelowOrEqual, length, index, failure); 2092 } 2093 void MacroAssembler::spectreBoundsCheckPtr(Register index, Register length, 2094 Register maybeScratch, 2095 Label* failure) { 2096 MOZ_RELEASE_ASSERT(!JitOptions.spectreIndexMasking); 2097 branchPtr(Assembler::BelowOrEqual, length, index, failure); 2098 } 2099 2100 void MacroAssembler::spectreBoundsCheckPtr(Register index, 2101 const Address& length, 2102 Register maybeScratch, 2103 Label* failure) { 2104 MOZ_RELEASE_ASSERT(!JitOptions.spectreIndexMasking); 2105 branchPtr(Assembler::BelowOrEqual, length, index, failure); 2106 } 2107 void MacroAssembler::spectreMovePtr(Condition, Register, Register) { 2108 MOZ_CRASH("spectreMovePtr"); 2109 } 2110 void MacroAssembler::spectreZeroRegister(Condition cond, Register scratch, 2111 Register dest) { 2112 MOZ_CRASH("spectreZeroRegister"); 2113 } 2114 void MacroAssembler::sqrtDouble(FloatRegister src, FloatRegister dest) { 2115 fsqrt_d(dest, src); 2116 } 2117 void MacroAssembler::sqrtFloat32(FloatRegister src, FloatRegister dest) { 2118 fsqrt_s(dest, src); 2119 } 2120 2121 FaultingCodeOffset MacroAssembler::storeFloat16(FloatRegister src, 2122 const Address& dest, Register) { 2123 MOZ_CRASH("Not supported for this target"); 2124 } 2125 FaultingCodeOffset MacroAssembler::storeFloat16(FloatRegister src, 2126 const BaseIndex& dest, 2127 Register) { 2128 MOZ_CRASH("Not supported for this target"); 2129 } 2130 2131 FaultingCodeOffset MacroAssembler::storeFloat32(FloatRegister src, 2132 const Address& addr) { 2133 return ma_fst_s(src, addr); 2134 } 2135 FaultingCodeOffset MacroAssembler::storeFloat32(FloatRegister src, 2136 const BaseIndex& addr) { 2137 return ma_fst_s(src, addr); 2138 } 2139 2140 FaultingCodeOffset MacroAssembler::storeDouble(FloatRegister src, 2141 const Address& addr) { 2142 return ma_fst_d(src, addr); 2143 } 2144 FaultingCodeOffset MacroAssembler::storeDouble(FloatRegister src, 2145 const BaseIndex& addr) { 2146 return ma_fst_d(src, addr); 2147 } 2148 void MacroAssembler::sub32(Register src, Register dest) { 2149 subw(dest, dest, src); 2150 } 2151 2152 void MacroAssembler::sub32(Imm32 imm, Register dest) { 2153 ma_sub32(dest, dest, imm); 2154 } 2155 2156 void MacroAssembler::sub32(const Address& src, Register dest) { 2157 UseScratchRegisterScope temps(this); 2158 Register scratch = temps.Acquire(); 2159 load32(src, scratch); 2160 subw(dest, dest, scratch); 2161 } 2162 2163 void MacroAssembler::sub64(Register64 src, Register64 dest) { 2164 sub(dest.reg, dest.reg, src.reg); 2165 } 2166 2167 void MacroAssembler::sub64(Imm64 imm, Register64 dest) { 2168 UseScratchRegisterScope temps(this); 2169 Register scratch = temps.Acquire(); 2170 MOZ_ASSERT(dest.reg != scratch); 2171 ma_li(scratch, ImmWord(imm.value)); 2172 sub(dest.reg, dest.reg, scratch); 2173 } 2174 2175 void MacroAssembler::subDouble(FloatRegister src, FloatRegister dest) { 2176 fsub_d(dest, dest, src); 2177 } 2178 2179 void MacroAssembler::subFloat32(FloatRegister src, FloatRegister dest) { 2180 fsub_s(dest, dest, src); 2181 } 2182 2183 void MacroAssembler::subPtr(Register src, const Address& dest) { 2184 UseScratchRegisterScope temps(this); 2185 Register scratch = temps.Acquire(); 2186 loadPtr(dest, scratch); 2187 subPtr(src, scratch); 2188 storePtr(scratch, dest); 2189 } 2190 2191 void MacroAssembler::subPtr(const Address& addr, Register dest) { 2192 UseScratchRegisterScope temps(this); 2193 Register scratch = temps.Acquire(); 2194 loadPtr(addr, scratch); 2195 subPtr(scratch, dest); 2196 } 2197 void MacroAssembler::subPtr(Imm32 imm, Register dest) { 2198 ma_sub64(dest, dest, imm); 2199 } 2200 void MacroAssembler::subPtr(Register src, Register dest) { 2201 sub(dest, dest, src); 2202 } 2203 void MacroAssembler::test32LoadPtr(Condition cond, const Address& addr, 2204 Imm32 mask, const Address& src, 2205 Register dest) { 2206 MOZ_RELEASE_ASSERT(!JitOptions.spectreStringMitigations); 2207 Label skip; 2208 branchTest32(Assembler::InvertCondition(cond), addr, mask, &skip); 2209 loadPtr(src, dest); 2210 bind(&skip); 2211 } 2212 void MacroAssembler::test32MovePtr(Condition cond, const Address& addr, 2213 Imm32 mask, Register src, Register dest) { 2214 MOZ_ASSERT(cond == Assembler::Zero || cond == Assembler::NonZero); 2215 Label skip; 2216 branchTest32(Assembler::InvertCondition(cond), addr, mask, &skip); 2217 movePtr(src, dest); 2218 bind(&skip); 2219 } 2220 void MacroAssembler::test32MovePtr(Condition cond, Register operand, Imm32 mask, 2221 Register src, Register dest) { 2222 MOZ_ASSERT(cond == Assembler::Zero || cond == Assembler::NonZero); 2223 Label skip; 2224 branchTest32(Assembler::InvertCondition(cond), operand, mask, &skip); 2225 movePtr(src, dest); 2226 bind(&skip); 2227 } 2228 void MacroAssembler::xor32(Register src, Register dest) { 2229 ma_xor(dest, dest, src); 2230 } 2231 2232 void MacroAssembler::xor32(Imm32 imm, Register dest) { 2233 ma_xor(dest, dest, imm); 2234 } 2235 2236 void MacroAssembler::xor32(Imm32 imm, Register src, Register dest) { 2237 ma_xor(dest, src, imm); 2238 } 2239 2240 void MacroAssembler::xor32(Imm32 imm, const Address& dest) { 2241 UseScratchRegisterScope temps(this); 2242 Register scratch2 = temps.Acquire(); 2243 load32(dest, scratch2); 2244 xor32(imm, scratch2); 2245 store32(scratch2, dest); 2246 } 2247 2248 void MacroAssembler::xor32(const Address& src, Register dest) { 2249 UseScratchRegisterScope temps(this); 2250 Register scratch2 = temps.Acquire(); 2251 load32(src, scratch2); 2252 xor32(scratch2, dest); 2253 } 2254 void MacroAssembler::xor64(Register64 src, Register64 dest) { 2255 ma_xor(dest.reg, dest.reg, src.reg); 2256 } 2257 2258 void MacroAssembler::xor64(Imm64 imm, Register64 dest) { 2259 UseScratchRegisterScope temps(this); 2260 Register scratch = temps.Acquire(); 2261 ma_li(scratch, ImmWord(imm.value)); 2262 ma_xor(dest.reg, dest.reg, scratch); 2263 } 2264 void MacroAssembler::xorPtr(Register src, Register dest) { 2265 ma_xor(dest, dest, src); 2266 } 2267 2268 void MacroAssembler::xorPtr(Imm32 imm, Register dest) { 2269 ma_xor(dest, dest, imm); 2270 } 2271 2272 void MacroAssembler::xorPtr(Imm32 imm, Register src, Register dest) { 2273 ma_xor(dest, src, imm); 2274 } 2275 //}}} check_macroassembler_style 2276 2277 void MacroAssemblerRiscv64Compat::incrementInt32Value(const Address& addr) { 2278 asMasm().add32(Imm32(1), addr); 2279 } 2280 2281 void MacroAssemblerRiscv64Compat::retn(Imm32 n) { 2282 // pc <- [sp]; sp += n 2283 loadPtr(Address(StackPointer, 0), ra); 2284 asMasm().addPtr(n, StackPointer); 2285 jr(ra, 0); 2286 } 2287 } // namespace jit 2288 } // namespace js 2289 2290 #endif /* jit_riscv64_MacroAssembler_riscv64_inl_h */