OLD | NEW |
---|---|
1 // Copyright (c) 1994-2006 Sun Microsystems Inc. | 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. |
2 // All Rights Reserved. | 2 // All Rights Reserved. |
3 // | 3 // |
4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
6 // met: | 6 // met: |
7 // | 7 // |
8 // - Redistributions of source code must retain the above copyright notice, | 8 // - Redistributions of source code must retain the above copyright notice, |
9 // this list of conditions and the following disclaimer. | 9 // this list of conditions and the following disclaimer. |
10 // | 10 // |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
257 | 257 |
258 trampoline_emitted_ = FLAG_force_long_branches; | 258 trampoline_emitted_ = FLAG_force_long_branches; |
259 unbound_labels_count_ = 0; | 259 unbound_labels_count_ = 0; |
260 block_buffer_growth_ = false; | 260 block_buffer_growth_ = false; |
261 | 261 |
262 ClearRecordedAstId(); | 262 ClearRecordedAstId(); |
263 } | 263 } |
264 | 264 |
265 | 265 |
266 void Assembler::GetCode(CodeDesc* desc) { | 266 void Assembler::GetCode(CodeDesc* desc) { |
267 EmitPendingInstructions(); | |
267 DCHECK(pc_ <= reloc_info_writer.pos()); // No overlap. | 268 DCHECK(pc_ <= reloc_info_writer.pos()); // No overlap. |
268 // Set up code descriptor. | 269 // Set up code descriptor. |
269 desc->buffer = buffer_; | 270 desc->buffer = buffer_; |
270 desc->buffer_size = buffer_size_; | 271 desc->buffer_size = buffer_size_; |
271 desc->instr_size = pc_offset(); | 272 desc->instr_size = pc_offset(); |
272 desc->reloc_size = | 273 desc->reloc_size = |
273 static_cast<int>((buffer_ + buffer_size_) - reloc_info_writer.pos()); | 274 static_cast<int>((buffer_ + buffer_size_) - reloc_info_writer.pos()); |
274 desc->origin = this; | 275 desc->origin = this; |
275 desc->constant_pool_size = 0; | 276 desc->constant_pool_size = 0; |
276 } | 277 } |
277 | 278 |
278 | 279 |
279 void Assembler::Align(int m) { | 280 void Assembler::Align(int m) { |
280 DCHECK(m >= 4 && base::bits::IsPowerOfTwo32(m)); | 281 DCHECK(m >= 4 && base::bits::IsPowerOfTwo32(m)); |
282 EmitPendingInstructions(); | |
281 while ((pc_offset() & (m - 1)) != 0) { | 283 while ((pc_offset() & (m - 1)) != 0) { |
282 nop(); | 284 nop(); |
283 } | 285 } |
284 } | 286 } |
285 | 287 |
286 | 288 |
287 void Assembler::CodeTargetAlign() { | 289 void Assembler::CodeTargetAlign() { |
288 // No advantage to aligning branch/call targets to more than | 290 // No advantage to aligning branch/call targets to more than |
289 // single instruction, that I am aware of. | 291 // single instruction, that I am aware of. |
290 Align(4); | 292 Align(4); |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
427 const int kEndOfChain = -4; | 429 const int kEndOfChain = -4; |
428 // Determines the end of the Jump chain (a subset of the label link chain). | 430 // Determines the end of the Jump chain (a subset of the label link chain). |
429 const int kEndOfJumpChain = 0; | 431 const int kEndOfJumpChain = 0; |
430 | 432 |
431 | 433 |
432 bool Assembler::IsBranch(Instr instr) { | 434 bool Assembler::IsBranch(Instr instr) { |
433 uint32_t opcode = GetOpcodeField(instr); | 435 uint32_t opcode = GetOpcodeField(instr); |
434 uint32_t rt_field = GetRtField(instr); | 436 uint32_t rt_field = GetRtField(instr); |
435 uint32_t rs_field = GetRsField(instr); | 437 uint32_t rs_field = GetRsField(instr); |
436 // Checks if the instruction is a branch. | 438 // Checks if the instruction is a branch. |
437 return opcode == BEQ || | 439 bool isBranch = |
438 opcode == BNE || | 440 opcode == BEQ || opcode == BNE || opcode == BLEZ || opcode == BGTZ || |
439 opcode == BLEZ || | 441 opcode == BEQL || opcode == BNEL || opcode == BLEZL || opcode == BGTZL || |
440 opcode == BGTZ || | |
441 opcode == BEQL || | |
442 opcode == BNEL || | |
443 opcode == BLEZL || | |
444 opcode == BGTZL || | |
445 (opcode == REGIMM && (rt_field == BLTZ || rt_field == BGEZ || | 442 (opcode == REGIMM && (rt_field == BLTZ || rt_field == BGEZ || |
446 rt_field == BLTZAL || rt_field == BGEZAL)) || | 443 rt_field == BLTZAL || rt_field == BGEZAL)) || |
447 (opcode == COP1 && rs_field == BC1) || // Coprocessor branch. | 444 (opcode == COP1 && rs_field == BC1) || // Coprocessor branch. |
448 (opcode == COP1 && rs_field == BC1EQZ) || | 445 (opcode == COP1 && rs_field == BC1EQZ) || |
449 (opcode == COP1 && rs_field == BC1NEZ); | 446 (opcode == COP1 && rs_field == BC1NEZ); |
447 if (!isBranch && kArchVariant == kMips64r6) { | |
448 // All the 3 variants of POP10 (BOVC, BEQC, BEQZALC) and | |
449 // POP30 (BNVC, BNEC, BNEZALC) are branch ops. | |
450 isBranch |= opcode == POP10 || opcode == POP30 || opcode == BC || | |
451 opcode == BALC || | |
452 (opcode == POP66 && rs_field != 0) || // BEQZC | |
453 (opcode == POP76 && rs_field != 0); // BNEZC | |
454 } | |
455 return isBranch; | |
450 } | 456 } |
451 | 457 |
452 | 458 |
459 bool Assembler::IsBc(Instr instr) { | |
460 uint32_t opcode = GetOpcodeField(instr); | |
461 // Checks if the instruction is a BC or BALC. | |
462 return opcode == BC || opcode == BALC; | |
463 } | |
464 | |
465 | |
466 bool Assembler::IsBzc(Instr instr) { | |
467 uint32_t opcode = GetOpcodeField(instr); | |
468 // Checks if the instruction is BEQZC or BNEZC. | |
469 return (opcode == POP66 && GetRsField(instr) != 0) || | |
470 (opcode == POP76 && GetRsField(instr) != 0); | |
471 } | |
472 | |
473 | |
453 bool Assembler::IsEmittedConstant(Instr instr) { | 474 bool Assembler::IsEmittedConstant(Instr instr) { |
454 uint32_t label_constant = GetLabelConst(instr); | 475 uint32_t label_constant = GetLabelConst(instr); |
455 return label_constant == 0; // Emitted label const in reg-exp engine. | 476 return label_constant == 0; // Emitted label const in reg-exp engine. |
456 } | 477 } |
457 | 478 |
458 | 479 |
459 bool Assembler::IsBeq(Instr instr) { | 480 bool Assembler::IsBeq(Instr instr) { |
460 return GetOpcodeField(instr) == BEQ; | 481 return GetOpcodeField(instr) == BEQ; |
461 } | 482 } |
462 | 483 |
463 | 484 |
464 bool Assembler::IsBne(Instr instr) { | 485 bool Assembler::IsBne(Instr instr) { |
465 return GetOpcodeField(instr) == BNE; | 486 return GetOpcodeField(instr) == BNE; |
466 } | 487 } |
467 | 488 |
468 | 489 |
490 bool Assembler::IsBeqzc(Instr instr) { | |
491 uint32_t opcode = GetOpcodeField(instr); | |
492 return opcode == POP66 && GetRsField(instr) != 0; | |
493 } | |
494 | |
495 | |
496 bool Assembler::IsBnezc(Instr instr) { | |
497 uint32_t opcode = GetOpcodeField(instr); | |
498 return opcode == POP76 && GetRsField(instr) != 0; | |
499 } | |
500 | |
501 | |
502 bool Assembler::IsBeqc(Instr instr) { | |
503 uint32_t opcode = GetOpcodeField(instr); | |
504 uint32_t rs = GetRsField(instr); | |
505 uint32_t rt = GetRtField(instr); | |
506 return opcode == POP10 && rs != 0 && rs < rt; // && rt != 0 | |
507 } | |
508 | |
509 | |
510 bool Assembler::IsBnec(Instr instr) { | |
511 uint32_t opcode = GetOpcodeField(instr); | |
512 uint32_t rs = GetRsField(instr); | |
513 uint32_t rt = GetRtField(instr); | |
514 return opcode == POP30 && rs != 0 && rs < rt; // && rt != 0 | |
515 } | |
516 | |
517 | |
469 bool Assembler::IsJump(Instr instr) { | 518 bool Assembler::IsJump(Instr instr) { |
470 uint32_t opcode = GetOpcodeField(instr); | 519 uint32_t opcode = GetOpcodeField(instr); |
471 uint32_t rt_field = GetRtField(instr); | 520 uint32_t rt_field = GetRtField(instr); |
472 uint32_t rd_field = GetRdField(instr); | 521 uint32_t rd_field = GetRdField(instr); |
473 uint32_t function_field = GetFunctionField(instr); | 522 uint32_t function_field = GetFunctionField(instr); |
474 // Checks if the instruction is a jump. | 523 // Checks if the instruction is a jump. |
475 return opcode == J || opcode == JAL || | 524 return opcode == J || opcode == JAL || |
476 (opcode == SPECIAL && rt_field == 0 && | 525 (opcode == SPECIAL && rt_field == 0 && |
477 ((function_field == JALR) || (rd_field == 0 && (function_field == JR)))); | 526 ((function_field == JALR) || (rd_field == 0 && (function_field == JR)))); |
478 } | 527 } |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
538 } | 587 } |
539 | 588 |
540 | 589 |
541 int32_t Assembler::GetBranchOffset(Instr instr) { | 590 int32_t Assembler::GetBranchOffset(Instr instr) { |
542 DCHECK(IsBranch(instr)); | 591 DCHECK(IsBranch(instr)); |
543 return (static_cast<int16_t>(instr & kImm16Mask)) << 2; | 592 return (static_cast<int16_t>(instr & kImm16Mask)) << 2; |
544 } | 593 } |
545 | 594 |
546 | 595 |
547 bool Assembler::IsLw(Instr instr) { | 596 bool Assembler::IsLw(Instr instr) { |
548 return ((instr & kOpcodeMask) == LW); | 597 return (static_cast<uint32_t>(instr & kOpcodeMask) == LW); |
549 } | 598 } |
550 | 599 |
551 | 600 |
552 int16_t Assembler::GetLwOffset(Instr instr) { | 601 int16_t Assembler::GetLwOffset(Instr instr) { |
553 DCHECK(IsLw(instr)); | 602 DCHECK(IsLw(instr)); |
554 return ((instr & kImm16Mask)); | 603 return ((instr & kImm16Mask)); |
555 } | 604 } |
556 | 605 |
557 | 606 |
558 Instr Assembler::SetLwOffset(Instr instr, int16_t offset) { | 607 Instr Assembler::SetLwOffset(Instr instr, int16_t offset) { |
559 DCHECK(IsLw(instr)); | 608 DCHECK(IsLw(instr)); |
560 | 609 |
561 // We actually create a new lw instruction based on the original one. | 610 // We actually create a new lw instruction based on the original one. |
562 Instr temp_instr = LW | (instr & kRsFieldMask) | (instr & kRtFieldMask) | 611 Instr temp_instr = LW | (instr & kRsFieldMask) | (instr & kRtFieldMask) |
563 | (offset & kImm16Mask); | 612 | (offset & kImm16Mask); |
564 | 613 |
565 return temp_instr; | 614 return temp_instr; |
566 } | 615 } |
567 | 616 |
568 | 617 |
569 bool Assembler::IsSw(Instr instr) { | 618 bool Assembler::IsSw(Instr instr) { |
570 return ((instr & kOpcodeMask) == SW); | 619 return (static_cast<uint32_t>(instr & kOpcodeMask) == SW); |
571 } | 620 } |
572 | 621 |
573 | 622 |
574 Instr Assembler::SetSwOffset(Instr instr, int16_t offset) { | 623 Instr Assembler::SetSwOffset(Instr instr, int16_t offset) { |
575 DCHECK(IsSw(instr)); | 624 DCHECK(IsSw(instr)); |
576 return ((instr & ~kImm16Mask) | (offset & kImm16Mask)); | 625 return ((instr & ~kImm16Mask) | (offset & kImm16Mask)); |
577 } | 626 } |
578 | 627 |
579 | 628 |
580 bool Assembler::IsAddImmediate(Instr instr) { | 629 bool Assembler::IsAddImmediate(Instr instr) { |
581 return ((instr & kOpcodeMask) == ADDIU || (instr & kOpcodeMask) == DADDIU); | 630 return ((instr & kOpcodeMask) == ADDIU || (instr & kOpcodeMask) == DADDIU); |
582 } | 631 } |
583 | 632 |
584 | 633 |
585 Instr Assembler::SetAddImmediateOffset(Instr instr, int16_t offset) { | 634 Instr Assembler::SetAddImmediateOffset(Instr instr, int16_t offset) { |
586 DCHECK(IsAddImmediate(instr)); | 635 DCHECK(IsAddImmediate(instr)); |
587 return ((instr & ~kImm16Mask) | (offset & kImm16Mask)); | 636 return ((instr & ~kImm16Mask) | (offset & kImm16Mask)); |
588 } | 637 } |
589 | 638 |
590 | 639 |
591 bool Assembler::IsAndImmediate(Instr instr) { | 640 bool Assembler::IsAndImmediate(Instr instr) { |
592 return GetOpcodeField(instr) == ANDI; | 641 return GetOpcodeField(instr) == ANDI; |
593 } | 642 } |
594 | 643 |
595 | 644 |
645 static Assembler::OffsetSize OffsetSizeInBits(Instr instr) { | |
646 if (kArchVariant == kMips64r6) { | |
647 if (Assembler::IsBc(instr)) { | |
648 return Assembler::OffsetSize::kOffset26; | |
649 } else if (Assembler::IsBzc(instr)) { | |
650 return Assembler::OffsetSize::kOffset21; | |
651 } | |
652 } | |
653 return Assembler::OffsetSize::kOffset16; | |
654 } | |
655 | |
656 | |
657 static inline int32_t AddBranchOffset(int pos, Instr instr) { | |
658 int bits = OffsetSizeInBits(instr); | |
659 const int32_t mask = (1 << bits) - 1; | |
660 bits = 32 - bits; | |
661 | |
662 // Do NOT change this to <<2. We rely on arithmetic shifts here, assuming | |
663 // the compiler uses arithmetic shifts for signed integers. | |
664 int32_t imm = ((instr & mask) << bits) >> (bits - 2); | |
665 | |
666 if (imm == kEndOfChain) { | |
667 // EndOfChain sentinel is returned directly, not relative to pc or pos. | |
668 return kEndOfChain; | |
669 } else { | |
670 return pos + Assembler::kBranchPCOffset + imm; | |
671 } | |
672 } | |
673 | |
674 | |
596 int Assembler::target_at(int pos, bool is_internal) { | 675 int Assembler::target_at(int pos, bool is_internal) { |
597 if (is_internal) { | 676 if (is_internal) { |
598 int64_t* p = reinterpret_cast<int64_t*>(buffer_ + pos); | 677 int64_t* p = reinterpret_cast<int64_t*>(buffer_ + pos); |
599 int64_t address = *p; | 678 int64_t address = *p; |
600 if (address == kEndOfJumpChain) { | 679 if (address == kEndOfJumpChain) { |
601 return kEndOfChain; | 680 return kEndOfChain; |
602 } else { | 681 } else { |
603 int64_t instr_address = reinterpret_cast<int64_t>(p); | 682 int64_t instr_address = reinterpret_cast<int64_t>(p); |
604 DCHECK(instr_address - address < INT_MAX); | 683 DCHECK(instr_address - address < INT_MAX); |
605 int delta = static_cast<int>(instr_address - address); | 684 int delta = static_cast<int>(instr_address - address); |
606 DCHECK(pos > delta); | 685 DCHECK(pos > delta); |
607 return pos - delta; | 686 return pos - delta; |
608 } | 687 } |
609 } | 688 } |
610 Instr instr = instr_at(pos); | 689 Instr instr = instr_at(pos); |
611 if ((instr & ~kImm16Mask) == 0) { | 690 if ((instr & ~kImm16Mask) == 0) { |
612 // Emitted label constant, not part of a branch. | 691 // Emitted label constant, not part of a branch. |
613 if (instr == 0) { | 692 if (instr == 0) { |
614 return kEndOfChain; | 693 return kEndOfChain; |
615 } else { | 694 } else { |
616 int32_t imm18 =((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14; | 695 int32_t imm18 =((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14; |
617 return (imm18 + pos); | 696 return (imm18 + pos); |
618 } | 697 } |
619 } | 698 } |
620 // Check we have a branch or jump instruction. | 699 // Check we have a branch or jump instruction. |
621 DCHECK(IsBranch(instr) || IsJ(instr) || IsJal(instr) || IsLui(instr)); | 700 DCHECK(IsBranch(instr) || IsJ(instr) || IsJal(instr) || IsLui(instr)); |
622 // Do NOT change this to <<2. We rely on arithmetic shifts here, assuming | 701 // Do NOT change this to <<2. We rely on arithmetic shifts here, assuming |
623 // the compiler uses arithmetic shifts for signed integers. | 702 // the compiler uses arithmetic shifts for signed integers. |
624 if (IsBranch(instr)) { | 703 if (IsBranch(instr)) { |
625 int32_t imm18 = ((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14; | 704 return AddBranchOffset(pos, instr); |
626 if (imm18 == kEndOfChain) { | |
627 // EndOfChain sentinel is returned directly, not relative to pc or pos. | |
628 return kEndOfChain; | |
629 } else { | |
630 return pos + kBranchPCOffset + imm18; | |
631 } | |
632 } else if (IsLui(instr)) { | 705 } else if (IsLui(instr)) { |
633 Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize); | 706 Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize); |
634 Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize); | 707 Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize); |
635 Instr instr_ori2 = instr_at(pos + 3 * Assembler::kInstrSize); | 708 Instr instr_ori2 = instr_at(pos + 3 * Assembler::kInstrSize); |
636 DCHECK(IsOri(instr_ori)); | 709 DCHECK(IsOri(instr_ori)); |
637 DCHECK(IsOri(instr_ori2)); | 710 DCHECK(IsOri(instr_ori2)); |
638 | 711 |
639 // TODO(plind) create named constants for shift values. | 712 // TODO(plind) create named constants for shift values. |
640 int64_t imm = static_cast<int64_t>(instr_lui & kImm16Mask) << 48; | 713 int64_t imm = static_cast<int64_t>(instr_lui & kImm16Mask) << 48; |
641 imm |= static_cast<int64_t>(instr_ori & kImm16Mask) << 32; | 714 imm |= static_cast<int64_t>(instr_ori & kImm16Mask) << 32; |
(...skipping 19 matching lines...) Expand all Loading... | |
661 return kEndOfChain; | 734 return kEndOfChain; |
662 } else { | 735 } else { |
663 // Sign extend 28-bit offset. | 736 // Sign extend 28-bit offset. |
664 int32_t delta = static_cast<int32_t>((imm28 << 4) >> 4); | 737 int32_t delta = static_cast<int32_t>((imm28 << 4) >> 4); |
665 return pos + delta; | 738 return pos + delta; |
666 } | 739 } |
667 } | 740 } |
668 } | 741 } |
669 | 742 |
670 | 743 |
744 static inline Instr SetBranchOffset(int32_t pos, int32_t target_pos, | |
745 Instr instr) { | |
746 int32_t bits = OffsetSizeInBits(instr); | |
747 int32_t imm = target_pos - (pos + Assembler::kBranchPCOffset); | |
748 DCHECK((imm & 3) == 0); | |
749 imm >>= 2; | |
750 | |
751 const int32_t mask = (1 << bits) - 1; | |
752 instr &= ~mask; | |
753 DCHECK(is_intn(imm, bits)); | |
754 | |
755 return instr | (imm & mask); | |
756 } | |
757 | |
758 | |
671 void Assembler::target_at_put(int pos, int target_pos, bool is_internal) { | 759 void Assembler::target_at_put(int pos, int target_pos, bool is_internal) { |
672 if (is_internal) { | 760 if (is_internal) { |
673 uint64_t imm = reinterpret_cast<uint64_t>(buffer_) + target_pos; | 761 uint64_t imm = reinterpret_cast<uint64_t>(buffer_) + target_pos; |
674 *reinterpret_cast<uint64_t*>(buffer_ + pos) = imm; | 762 *reinterpret_cast<uint64_t*>(buffer_ + pos) = imm; |
675 return; | 763 return; |
676 } | 764 } |
677 Instr instr = instr_at(pos); | 765 Instr instr = instr_at(pos); |
678 if ((instr & ~kImm16Mask) == 0) { | 766 if ((instr & ~kImm16Mask) == 0) { |
679 DCHECK(target_pos == kEndOfChain || target_pos >= 0); | 767 DCHECK(target_pos == kEndOfChain || target_pos >= 0); |
680 // Emitted label constant, not part of a branch. | 768 // Emitted label constant, not part of a branch. |
681 // Make label relative to Code* of generated Code object. | 769 // Make label relative to Code* of generated Code object. |
682 instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag)); | 770 instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag)); |
683 return; | 771 return; |
684 } | 772 } |
685 | 773 |
686 if (IsBranch(instr)) { | 774 if (IsBranch(instr)) { |
687 int32_t imm18 = target_pos - (pos + kBranchPCOffset); | 775 instr = SetBranchOffset(pos, target_pos, instr); |
688 DCHECK((imm18 & 3) == 0); | 776 instr_at_put(pos, instr); |
689 | |
690 instr &= ~kImm16Mask; | |
691 int32_t imm16 = imm18 >> 2; | |
692 DCHECK(is_int16(imm16)); | |
693 | |
694 instr_at_put(pos, instr | (imm16 & kImm16Mask)); | |
695 } else if (IsLui(instr)) { | 777 } else if (IsLui(instr)) { |
696 Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize); | 778 Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize); |
697 Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize); | 779 Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize); |
698 Instr instr_ori2 = instr_at(pos + 3 * Assembler::kInstrSize); | 780 Instr instr_ori2 = instr_at(pos + 3 * Assembler::kInstrSize); |
699 DCHECK(IsOri(instr_ori)); | 781 DCHECK(IsOri(instr_ori)); |
700 DCHECK(IsOri(instr_ori2)); | 782 DCHECK(IsOri(instr_ori2)); |
701 | 783 |
702 uint64_t imm = reinterpret_cast<uint64_t>(buffer_) + target_pos; | 784 uint64_t imm = reinterpret_cast<uint64_t>(buffer_) + target_pos; |
703 DCHECK((imm & 3) == 0); | 785 DCHECK((imm & 3) == 0); |
704 | 786 |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
773 while (L->is_linked()) { | 855 while (L->is_linked()) { |
774 int fixup_pos = L->pos(); | 856 int fixup_pos = L->pos(); |
775 int dist = pos - fixup_pos; | 857 int dist = pos - fixup_pos; |
776 is_internal = internal_reference_positions_.find(fixup_pos) != | 858 is_internal = internal_reference_positions_.find(fixup_pos) != |
777 internal_reference_positions_.end(); | 859 internal_reference_positions_.end(); |
778 next(L, is_internal); // Call next before overwriting link with target at | 860 next(L, is_internal); // Call next before overwriting link with target at |
779 // fixup_pos. | 861 // fixup_pos. |
780 Instr instr = instr_at(fixup_pos); | 862 Instr instr = instr_at(fixup_pos); |
781 if (is_internal) { | 863 if (is_internal) { |
782 target_at_put(fixup_pos, pos, is_internal); | 864 target_at_put(fixup_pos, pos, is_internal); |
783 } else if (IsBranch(instr)) { | 865 } else { |
784 if (dist > kMaxBranchOffset) { | 866 if (IsBranch(instr)) { |
785 if (trampoline_pos == kInvalidSlotPos) { | 867 int branch_offset = BranchOffset(instr); |
786 trampoline_pos = get_trampoline_entry(fixup_pos); | 868 if (dist > branch_offset) { |
787 CHECK(trampoline_pos != kInvalidSlotPos); | 869 if (trampoline_pos == kInvalidSlotPos) { |
870 trampoline_pos = get_trampoline_entry(fixup_pos); | |
871 CHECK(trampoline_pos != kInvalidSlotPos); | |
872 } | |
873 CHECK((trampoline_pos - fixup_pos) <= branch_offset); | |
874 target_at_put(fixup_pos, trampoline_pos, false); | |
875 fixup_pos = trampoline_pos; | |
876 dist = pos - fixup_pos; | |
788 } | 877 } |
789 CHECK((trampoline_pos - fixup_pos) <= kMaxBranchOffset); | 878 target_at_put(fixup_pos, pos, false); |
790 target_at_put(fixup_pos, trampoline_pos, false); | 879 } else { |
791 fixup_pos = trampoline_pos; | 880 DCHECK(IsJ(instr) || IsJal(instr) || IsLui(instr) || |
792 dist = pos - fixup_pos; | 881 IsEmittedConstant(instr)); |
882 target_at_put(fixup_pos, pos, false); | |
793 } | 883 } |
794 target_at_put(fixup_pos, pos, false); | |
795 } else { | |
796 DCHECK(IsJ(instr) || IsJal(instr) || IsLui(instr) || | |
797 IsEmittedConstant(instr)); | |
798 target_at_put(fixup_pos, pos, false); | |
799 } | 884 } |
800 } | 885 } |
801 L->bind_to(pos); | 886 L->bind_to(pos); |
802 | 887 |
803 // Keep track of the last bound label so we don't eliminate any instructions | 888 // Keep track of the last bound label so we don't eliminate any instructions |
804 // before a bound label. | 889 // before a bound label. |
805 if (pos > last_bound_pos_) | 890 if (pos > last_bound_pos_) |
806 last_bound_pos_ = pos; | 891 last_bound_pos_ = pos; |
807 } | 892 } |
808 | 893 |
(...skipping 10 matching lines...) Expand all Loading... | |
819 if (link == kEndOfChain) { | 904 if (link == kEndOfChain) { |
820 L->Unuse(); | 905 L->Unuse(); |
821 } else { | 906 } else { |
822 DCHECK(link >= 0); | 907 DCHECK(link >= 0); |
823 L->link_to(link); | 908 L->link_to(link); |
824 } | 909 } |
825 } | 910 } |
826 | 911 |
827 | 912 |
828 bool Assembler::is_near(Label* L) { | 913 bool Assembler::is_near(Label* L) { |
829 if (L->is_bound()) { | 914 DCHECK(L->is_bound()); |
830 return ((pc_offset() - L->pos()) < kMaxBranchOffset - 4 * kInstrSize); | 915 return pc_offset() - L->pos() < kMaxBranchOffset - 4 * kInstrSize; |
831 } | |
832 return false; | |
833 } | 916 } |
834 | 917 |
835 | 918 |
919 bool Assembler::is_near(Label* L, OffsetSize bits) { | |
920 if (L == nullptr || !L->is_bound()) return true; | |
921 return ((pc_offset() - L->pos()) < | |
922 (1 << (bits + 2 - 1)) - 1 - 5 * kInstrSize); | |
923 } | |
924 | |
925 | |
926 bool Assembler::is_near_branch(Label* L) { | |
927 DCHECK(L->is_bound()); | |
928 return kArchVariant == kMips64r6 ? is_near_r6(L) : is_near_pre_r6(L); | |
929 } | |
930 | |
931 | |
932 int Assembler::BranchOffset(Instr instr) { | |
933 // At pre-R6 and for other R6 branches the offset is 16 bits. | |
934 int bits = OffsetSize::kOffset16; | |
935 | |
936 if (kArchVariant == kMips64r6) { | |
937 uint32_t opcode = GetOpcodeField(instr); | |
938 switch (opcode) { | |
939 // Checks BC or BALC. | |
940 case BC: | |
941 case BALC: | |
942 bits = OffsetSize::kOffset26; | |
943 break; | |
944 | |
945 // Checks BEQZC or BNEZC. | |
946 case POP66: | |
947 case POP76: | |
948 if (GetRsField(instr) != 0) bits = OffsetSize::kOffset21; | |
949 break; | |
950 default: | |
951 break; | |
952 } | |
953 } | |
954 | |
955 return (1 << (bits + 2 - 1)) - 1; | |
956 } | |
957 | |
958 | |
836 // We have to use a temporary register for things that can be relocated even | 959 // We have to use a temporary register for things that can be relocated even |
837 // if they can be encoded in the MIPS's 16 bits of immediate-offset instruction | 960 // if they can be encoded in the MIPS's 16 bits of immediate-offset instruction |
838 // space. There is no guarantee that the relocated location can be similarly | 961 // space. There is no guarantee that the relocated location can be similarly |
839 // encoded. | 962 // encoded. |
840 bool Assembler::MustUseReg(RelocInfo::Mode rmode) { | 963 bool Assembler::MustUseReg(RelocInfo::Mode rmode) { |
841 return !RelocInfo::IsNone(rmode); | 964 return !RelocInfo::IsNone(rmode); |
842 } | 965 } |
843 | 966 |
844 void Assembler::GenInstrRegister(Opcode opcode, | 967 void Assembler::GenInstrRegister(Opcode opcode, |
845 Register rs, | 968 Register rs, |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
913 SecondaryField func) { | 1036 SecondaryField func) { |
914 DCHECK(fs.is_valid() && rt.is_valid()); | 1037 DCHECK(fs.is_valid() && rt.is_valid()); |
915 Instr instr = | 1038 Instr instr = |
916 opcode | fmt | (rt.code() << kRtShift) | (fs.code() << kFsShift) | func; | 1039 opcode | fmt | (rt.code() << kRtShift) | (fs.code() << kFsShift) | func; |
917 emit(instr); | 1040 emit(instr); |
918 } | 1041 } |
919 | 1042 |
920 | 1043 |
921 // Instructions with immediate value. | 1044 // Instructions with immediate value. |
922 // Registers are in the order of the instruction encoding, from left to right. | 1045 // Registers are in the order of the instruction encoding, from left to right. |
923 void Assembler::GenInstrImmediate(Opcode opcode, | 1046 void Assembler::GenInstrImmediate(Opcode opcode, Register rs, Register rt, |
924 Register rs, | 1047 int32_t j, |
925 Register rt, | 1048 CompactBranchType is_compact_branch) { |
926 int32_t j) { | |
927 DCHECK(rs.is_valid() && rt.is_valid() && (is_int16(j) || is_uint16(j))); | 1049 DCHECK(rs.is_valid() && rt.is_valid() && (is_int16(j) || is_uint16(j))); |
928 Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift) | 1050 Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift) |
929 | (j & kImm16Mask); | 1051 | (j & kImm16Mask); |
1052 emit(instr, is_compact_branch); | |
1053 } | |
1054 | |
1055 | |
1056 void Assembler::GenInstrImmediate(Opcode opcode, Register rs, SecondaryField SF, | |
1057 int32_t j, | |
1058 CompactBranchType is_compact_branch) { | |
1059 DCHECK(rs.is_valid() && (is_int16(j) || is_uint16(j))); | |
1060 Instr instr = opcode | (rs.code() << kRsShift) | SF | (j & kImm16Mask); | |
1061 emit(instr, is_compact_branch); | |
1062 } | |
1063 | |
1064 | |
1065 void Assembler::GenInstrImmediate(Opcode opcode, Register rs, FPURegister ft, | |
1066 int32_t j, | |
1067 CompactBranchType is_compact_branch) { | |
1068 DCHECK(rs.is_valid() && ft.is_valid() && (is_int16(j) || is_uint16(j))); | |
1069 Instr instr = opcode | (rs.code() << kRsShift) | (ft.code() << kFtShift) | |
1070 | (j & kImm16Mask); | |
1071 emit(instr, is_compact_branch); | |
1072 } | |
1073 | |
1074 | |
1075 void Assembler::GenInstrImmediate(Opcode opcode, Register rs, int32_t offset21, | |
1076 CompactBranchType is_compact_branch) { | |
1077 DCHECK(rs.is_valid() && (is_int21(offset21))); | |
1078 Instr instr = opcode | (rs.code() << kRsShift) | (offset21 & kImm21Mask); | |
1079 emit(instr, is_compact_branch); | |
1080 } | |
1081 | |
1082 | |
1083 void Assembler::GenInstrImmediate(Opcode opcode, Register rs, | |
1084 uint32_t offset21) { | |
1085 DCHECK(rs.is_valid() && (is_uint21(offset21))); | |
1086 Instr instr = opcode | (rs.code() << kRsShift) | (offset21 & kImm21Mask); | |
930 emit(instr); | 1087 emit(instr); |
931 } | 1088 } |
932 | 1089 |
933 | 1090 |
934 void Assembler::GenInstrImmediate(Opcode opcode, | 1091 void Assembler::GenInstrImmediate(Opcode opcode, int32_t offset26, |
935 Register rs, | 1092 CompactBranchType is_compact_branch) { |
936 SecondaryField SF, | 1093 DCHECK(is_int26(offset26)); |
937 int32_t j) { | 1094 Instr instr = opcode | (offset26 & kImm26Mask); |
938 DCHECK(rs.is_valid() && (is_int16(j) || is_uint16(j))); | 1095 emit(instr, is_compact_branch); |
939 Instr instr = opcode | (rs.code() << kRsShift) | SF | (j & kImm16Mask); | |
940 emit(instr); | |
941 } | 1096 } |
942 | 1097 |
943 | 1098 |
944 void Assembler::GenInstrImmediate(Opcode opcode, | |
945 Register rs, | |
946 FPURegister ft, | |
947 int32_t j) { | |
948 DCHECK(rs.is_valid() && ft.is_valid() && (is_int16(j) || is_uint16(j))); | |
949 Instr instr = opcode | (rs.code() << kRsShift) | (ft.code() << kFtShift) | |
950 | (j & kImm16Mask); | |
951 emit(instr); | |
952 } | |
953 | |
954 | |
955 void Assembler::GenInstrImmediate(Opcode opcode, Register rs, int32_t j) { | |
956 DCHECK(rs.is_valid() && (is_uint21(j))); | |
957 Instr instr = opcode | (rs.code() << kRsShift) | (j & kImm21Mask); | |
958 emit(instr); | |
959 } | |
960 | |
961 | |
962 void Assembler::GenInstrImmediate(Opcode opcode, int32_t offset26) { | |
963 DCHECK(is_int26(offset26)); | |
964 Instr instr = opcode | (offset26 & kImm26Mask); | |
965 emit(instr); | |
966 } | |
967 | |
968 | |
969 void Assembler::GenInstrJump(Opcode opcode, | 1099 void Assembler::GenInstrJump(Opcode opcode, |
970 uint32_t address) { | 1100 uint32_t address) { |
971 BlockTrampolinePoolScope block_trampoline_pool(this); | 1101 BlockTrampolinePoolScope block_trampoline_pool(this); |
972 DCHECK(is_uint26(address)); | 1102 DCHECK(is_uint26(address)); |
973 Instr instr = opcode | address; | 1103 Instr instr = opcode | address; |
974 emit(instr); | 1104 emit(instr); |
975 BlockTrampolinePoolFor(1); // For associated delay slot. | 1105 BlockTrampolinePoolFor(1); // For associated delay slot. |
976 } | 1106 } |
977 | 1107 |
978 | 1108 |
(...skipping 28 matching lines...) Expand all Loading... | |
1007 } | 1137 } |
1008 uint64_t imm = reinterpret_cast<uint64_t>(buffer_) + target_pos; | 1138 uint64_t imm = reinterpret_cast<uint64_t>(buffer_) + target_pos; |
1009 DCHECK((imm & 3) == 0); | 1139 DCHECK((imm & 3) == 0); |
1010 | 1140 |
1011 return imm; | 1141 return imm; |
1012 } | 1142 } |
1013 | 1143 |
1014 | 1144 |
1015 uint64_t Assembler::jump_offset(Label* L) { | 1145 uint64_t Assembler::jump_offset(Label* L) { |
1016 int64_t target_pos; | 1146 int64_t target_pos; |
1147 int32_t pad = IsPrevInstrCompactBranch() ? kInstrSize : 0; | |
1148 | |
1017 if (L->is_bound()) { | 1149 if (L->is_bound()) { |
1018 target_pos = L->pos(); | 1150 target_pos = L->pos(); |
1019 } else { | 1151 } else { |
1020 if (L->is_linked()) { | 1152 if (L->is_linked()) { |
1021 target_pos = L->pos(); // L's link. | 1153 target_pos = L->pos(); // L's link. |
1022 L->link_to(pc_offset()); | 1154 L->link_to(pc_offset() + pad); |
1023 } else { | 1155 } else { |
1024 L->link_to(pc_offset()); | 1156 L->link_to(pc_offset() + pad); |
1025 return kEndOfJumpChain; | 1157 return kEndOfJumpChain; |
1026 } | 1158 } |
1027 } | 1159 } |
1028 int64_t imm = target_pos - pc_offset(); | 1160 int64_t imm = target_pos - (pc_offset() + pad); |
1029 DCHECK((imm & 3) == 0); | 1161 DCHECK((imm & 3) == 0); |
1030 | 1162 |
1031 return static_cast<uint64_t>(imm); | 1163 return static_cast<uint64_t>(imm); |
1032 } | 1164 } |
1033 | 1165 |
1034 | 1166 |
1035 int32_t Assembler::branch_offset(Label* L, bool jump_elimination_allowed) { | 1167 int32_t Assembler::branch_offset_helper(Label* L, OffsetSize bits) { |
1036 int32_t target_pos; | 1168 int32_t target_pos; |
1169 int32_t pad = IsPrevInstrCompactBranch() ? kInstrSize : 0; | |
1170 | |
1037 if (L->is_bound()) { | 1171 if (L->is_bound()) { |
1038 target_pos = L->pos(); | 1172 target_pos = L->pos(); |
1039 } else { | 1173 } else { |
1040 if (L->is_linked()) { | 1174 if (L->is_linked()) { |
1041 target_pos = L->pos(); | 1175 target_pos = L->pos(); |
1042 L->link_to(pc_offset()); | 1176 L->link_to(pc_offset() + pad); |
1043 } else { | 1177 } else { |
1044 L->link_to(pc_offset()); | 1178 L->link_to(pc_offset() + pad); |
1045 if (!trampoline_emitted_) { | 1179 if (!trampoline_emitted_) { |
1046 unbound_labels_count_++; | 1180 unbound_labels_count_++; |
1047 next_buffer_check_ -= kTrampolineSlotsSize; | 1181 next_buffer_check_ -= kTrampolineSlotsSize; |
1048 } | |
1049 return kEndOfChain; | |
1050 } | |
1051 } | |
1052 | |
1053 int32_t offset = target_pos - (pc_offset() + kBranchPCOffset); | |
1054 DCHECK((offset & 3) == 0); | |
1055 DCHECK(is_int16(offset >> 2)); | |
1056 | |
1057 return offset; | |
1058 } | |
1059 | |
1060 | |
1061 int32_t Assembler::branch_offset_compact(Label* L, | |
1062 bool jump_elimination_allowed) { | |
1063 int32_t target_pos; | |
1064 if (L->is_bound()) { | |
1065 target_pos = L->pos(); | |
1066 } else { | |
1067 if (L->is_linked()) { | |
1068 target_pos = L->pos(); | |
1069 L->link_to(pc_offset()); | |
1070 } else { | |
1071 L->link_to(pc_offset()); | |
1072 if (!trampoline_emitted_) { | |
1073 unbound_labels_count_++; | |
1074 next_buffer_check_ -= kTrampolineSlotsSize; | |
1075 } | 1182 } |
1076 return kEndOfChain; | 1183 return kEndOfChain; |
1077 } | 1184 } |
1078 } | 1185 } |
1079 | 1186 |
1080 int32_t offset = target_pos - pc_offset(); | 1187 int32_t offset = target_pos - (pc_offset() + kBranchPCOffset + pad); |
1188 DCHECK(is_intn(offset, bits + 2)); | |
1081 DCHECK((offset & 3) == 0); | 1189 DCHECK((offset & 3) == 0); |
1082 DCHECK(is_int16(offset >> 2)); | |
1083 | 1190 |
1084 return offset; | 1191 return offset; |
1085 } | 1192 } |
1086 | |
1087 | |
1088 int32_t Assembler::branch_offset21(Label* L, bool jump_elimination_allowed) { | |
1089 int32_t target_pos; | |
1090 if (L->is_bound()) { | |
1091 target_pos = L->pos(); | |
1092 } else { | |
1093 if (L->is_linked()) { | |
1094 target_pos = L->pos(); | |
1095 L->link_to(pc_offset()); | |
1096 } else { | |
1097 L->link_to(pc_offset()); | |
1098 if (!trampoline_emitted_) { | |
1099 unbound_labels_count_++; | |
1100 next_buffer_check_ -= kTrampolineSlotsSize; | |
1101 } | |
1102 return kEndOfChain; | |
1103 } | |
1104 } | |
1105 | |
1106 int32_t offset = target_pos - (pc_offset() + kBranchPCOffset); | |
1107 DCHECK((offset & 3) == 0); | |
1108 DCHECK(((offset >> 2) & 0xFFE00000) == 0); // Offset is 21bit width. | |
1109 | |
1110 return offset; | |
1111 } | |
1112 | |
1113 | |
1114 int32_t Assembler::branch_offset21_compact(Label* L, | |
1115 bool jump_elimination_allowed) { | |
1116 int32_t target_pos; | |
1117 if (L->is_bound()) { | |
1118 target_pos = L->pos(); | |
1119 } else { | |
1120 if (L->is_linked()) { | |
1121 target_pos = L->pos(); | |
1122 L->link_to(pc_offset()); | |
1123 } else { | |
1124 L->link_to(pc_offset()); | |
1125 if (!trampoline_emitted_) { | |
1126 unbound_labels_count_++; | |
1127 next_buffer_check_ -= kTrampolineSlotsSize; | |
1128 } | |
1129 return kEndOfChain; | |
1130 } | |
1131 } | |
1132 | |
1133 int32_t offset = target_pos - (pc_offset() + kBranchPCOffset); | |
1134 DCHECK((offset & 3) == 0); | |
1135 DCHECK(((offset >> 2) & 0xFFE00000) == 0); // Offset is 21bit width. | |
1136 | |
1137 return offset; | |
1138 } | |
1139 | 1193 |
1140 | 1194 |
1141 void Assembler::label_at_put(Label* L, int at_offset) { | 1195 void Assembler::label_at_put(Label* L, int at_offset) { |
1142 int target_pos; | 1196 int target_pos; |
1143 if (L->is_bound()) { | 1197 if (L->is_bound()) { |
1144 target_pos = L->pos(); | 1198 target_pos = L->pos(); |
1145 instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag)); | 1199 instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag)); |
1146 } else { | 1200 } else { |
1147 if (L->is_linked()) { | 1201 if (L->is_linked()) { |
1148 target_pos = L->pos(); // L's link. | 1202 target_pos = L->pos(); // L's link. |
(...skipping 23 matching lines...) Expand all Loading... | |
1172 | 1226 |
1173 | 1227 |
1174 void Assembler::bal(int16_t offset) { | 1228 void Assembler::bal(int16_t offset) { |
1175 positions_recorder()->WriteRecordedPositions(); | 1229 positions_recorder()->WriteRecordedPositions(); |
1176 bgezal(zero_reg, offset); | 1230 bgezal(zero_reg, offset); |
1177 } | 1231 } |
1178 | 1232 |
1179 | 1233 |
1180 void Assembler::bc(int32_t offset) { | 1234 void Assembler::bc(int32_t offset) { |
1181 DCHECK(kArchVariant == kMips64r6); | 1235 DCHECK(kArchVariant == kMips64r6); |
1182 GenInstrImmediate(BC, offset); | 1236 GenInstrImmediate(BC, offset, CompactBranchType::COMPACT_BRANCH); |
1183 } | 1237 } |
1184 | 1238 |
1185 | 1239 |
1186 void Assembler::balc(int32_t offset) { | 1240 void Assembler::balc(int32_t offset) { |
1187 DCHECK(kArchVariant == kMips64r6); | 1241 DCHECK(kArchVariant == kMips64r6); |
1188 positions_recorder()->WriteRecordedPositions(); | 1242 positions_recorder()->WriteRecordedPositions(); |
1189 GenInstrImmediate(BALC, offset); | 1243 GenInstrImmediate(BALC, offset, CompactBranchType::COMPACT_BRANCH); |
1190 } | 1244 } |
1191 | 1245 |
1192 | 1246 |
1193 void Assembler::beq(Register rs, Register rt, int16_t offset) { | 1247 void Assembler::beq(Register rs, Register rt, int16_t offset) { |
1194 BlockTrampolinePoolScope block_trampoline_pool(this); | 1248 BlockTrampolinePoolScope block_trampoline_pool(this); |
1195 GenInstrImmediate(BEQ, rs, rt, offset); | 1249 GenInstrImmediate(BEQ, rs, rt, offset); |
1196 BlockTrampolinePoolFor(1); // For associated delay slot. | 1250 BlockTrampolinePoolFor(1); // For associated delay slot. |
1197 } | 1251 } |
1198 | 1252 |
1199 | 1253 |
1200 void Assembler::bgez(Register rs, int16_t offset) { | 1254 void Assembler::bgez(Register rs, int16_t offset) { |
1201 BlockTrampolinePoolScope block_trampoline_pool(this); | 1255 BlockTrampolinePoolScope block_trampoline_pool(this); |
1202 GenInstrImmediate(REGIMM, rs, BGEZ, offset); | 1256 GenInstrImmediate(REGIMM, rs, BGEZ, offset); |
1203 BlockTrampolinePoolFor(1); // For associated delay slot. | 1257 BlockTrampolinePoolFor(1); // For associated delay slot. |
1204 } | 1258 } |
1205 | 1259 |
1206 | 1260 |
1207 void Assembler::bgezc(Register rt, int16_t offset) { | 1261 void Assembler::bgezc(Register rt, int16_t offset) { |
1208 DCHECK(kArchVariant == kMips64r6); | 1262 DCHECK(kArchVariant == kMips64r6); |
1209 DCHECK(!(rt.is(zero_reg))); | 1263 DCHECK(!(rt.is(zero_reg))); |
1210 GenInstrImmediate(BLEZL, rt, rt, offset); | 1264 GenInstrImmediate(BLEZL, rt, rt, offset, CompactBranchType::COMPACT_BRANCH); |
1211 } | 1265 } |
1212 | 1266 |
1213 | 1267 |
1214 void Assembler::bgeuc(Register rs, Register rt, int16_t offset) { | 1268 void Assembler::bgeuc(Register rs, Register rt, int16_t offset) { |
1215 DCHECK(kArchVariant == kMips64r6); | 1269 DCHECK(kArchVariant == kMips64r6); |
1216 DCHECK(!(rs.is(zero_reg))); | 1270 DCHECK(!(rs.is(zero_reg))); |
1217 DCHECK(!(rt.is(zero_reg))); | 1271 DCHECK(!(rt.is(zero_reg))); |
1218 DCHECK(rs.code() != rt.code()); | 1272 DCHECK(rs.code() != rt.code()); |
1219 GenInstrImmediate(BLEZ, rs, rt, offset); | 1273 GenInstrImmediate(BLEZ, rs, rt, offset, CompactBranchType::COMPACT_BRANCH); |
1220 } | 1274 } |
1221 | 1275 |
1222 | 1276 |
1223 void Assembler::bgec(Register rs, Register rt, int16_t offset) { | 1277 void Assembler::bgec(Register rs, Register rt, int16_t offset) { |
1224 DCHECK(kArchVariant == kMips64r6); | 1278 DCHECK(kArchVariant == kMips64r6); |
1225 DCHECK(!(rs.is(zero_reg))); | 1279 DCHECK(!(rs.is(zero_reg))); |
1226 DCHECK(!(rt.is(zero_reg))); | 1280 DCHECK(!(rt.is(zero_reg))); |
1227 DCHECK(rs.code() != rt.code()); | 1281 DCHECK(rs.code() != rt.code()); |
1228 GenInstrImmediate(BLEZL, rs, rt, offset); | 1282 GenInstrImmediate(BLEZL, rs, rt, offset, CompactBranchType::COMPACT_BRANCH); |
1229 } | 1283 } |
1230 | 1284 |
1231 | 1285 |
1232 void Assembler::bgezal(Register rs, int16_t offset) { | 1286 void Assembler::bgezal(Register rs, int16_t offset) { |
1233 DCHECK(kArchVariant != kMips64r6 || rs.is(zero_reg)); | 1287 DCHECK(kArchVariant != kMips64r6 || rs.is(zero_reg)); |
1234 BlockTrampolinePoolScope block_trampoline_pool(this); | 1288 BlockTrampolinePoolScope block_trampoline_pool(this); |
1235 positions_recorder()->WriteRecordedPositions(); | 1289 positions_recorder()->WriteRecordedPositions(); |
1236 GenInstrImmediate(REGIMM, rs, BGEZAL, offset); | 1290 GenInstrImmediate(REGIMM, rs, BGEZAL, offset); |
1237 BlockTrampolinePoolFor(1); // For associated delay slot. | 1291 BlockTrampolinePoolFor(1); // For associated delay slot. |
1238 } | 1292 } |
1239 | 1293 |
1240 | 1294 |
1241 void Assembler::bgtz(Register rs, int16_t offset) { | 1295 void Assembler::bgtz(Register rs, int16_t offset) { |
1242 BlockTrampolinePoolScope block_trampoline_pool(this); | 1296 BlockTrampolinePoolScope block_trampoline_pool(this); |
1243 GenInstrImmediate(BGTZ, rs, zero_reg, offset); | 1297 GenInstrImmediate(BGTZ, rs, zero_reg, offset); |
1244 BlockTrampolinePoolFor(1); // For associated delay slot. | 1298 BlockTrampolinePoolFor(1); // For associated delay slot. |
1245 } | 1299 } |
1246 | 1300 |
1247 | 1301 |
1248 void Assembler::bgtzc(Register rt, int16_t offset) { | 1302 void Assembler::bgtzc(Register rt, int16_t offset) { |
1249 DCHECK(kArchVariant == kMips64r6); | 1303 DCHECK(kArchVariant == kMips64r6); |
1250 DCHECK(!(rt.is(zero_reg))); | 1304 DCHECK(!(rt.is(zero_reg))); |
1251 GenInstrImmediate(BGTZL, zero_reg, rt, offset); | 1305 GenInstrImmediate(BGTZL, zero_reg, rt, offset, |
1306 CompactBranchType::COMPACT_BRANCH); | |
1252 } | 1307 } |
1253 | 1308 |
1254 | 1309 |
1255 void Assembler::blez(Register rs, int16_t offset) { | 1310 void Assembler::blez(Register rs, int16_t offset) { |
1256 BlockTrampolinePoolScope block_trampoline_pool(this); | 1311 BlockTrampolinePoolScope block_trampoline_pool(this); |
1257 GenInstrImmediate(BLEZ, rs, zero_reg, offset); | 1312 GenInstrImmediate(BLEZ, rs, zero_reg, offset); |
1258 BlockTrampolinePoolFor(1); // For associated delay slot. | 1313 BlockTrampolinePoolFor(1); // For associated delay slot. |
1259 } | 1314 } |
1260 | 1315 |
1261 | 1316 |
1262 void Assembler::blezc(Register rt, int16_t offset) { | 1317 void Assembler::blezc(Register rt, int16_t offset) { |
1263 DCHECK(kArchVariant == kMips64r6); | 1318 DCHECK(kArchVariant == kMips64r6); |
1264 DCHECK(!(rt.is(zero_reg))); | 1319 DCHECK(!(rt.is(zero_reg))); |
1265 GenInstrImmediate(BLEZL, zero_reg, rt, offset); | 1320 GenInstrImmediate(BLEZL, zero_reg, rt, offset, |
1321 CompactBranchType::COMPACT_BRANCH); | |
1266 } | 1322 } |
1267 | 1323 |
1268 | 1324 |
1269 void Assembler::bltzc(Register rt, int16_t offset) { | 1325 void Assembler::bltzc(Register rt, int16_t offset) { |
1270 DCHECK(kArchVariant == kMips64r6); | 1326 DCHECK(kArchVariant == kMips64r6); |
1271 DCHECK(!(rt.is(zero_reg))); | 1327 DCHECK(!rt.is(zero_reg)); |
1272 GenInstrImmediate(BGTZL, rt, rt, offset); | 1328 GenInstrImmediate(BGTZL, rt, rt, offset, CompactBranchType::COMPACT_BRANCH); |
1273 } | 1329 } |
1274 | 1330 |
1275 | 1331 |
1276 void Assembler::bltuc(Register rs, Register rt, int16_t offset) { | 1332 void Assembler::bltuc(Register rs, Register rt, int16_t offset) { |
1277 DCHECK(kArchVariant == kMips64r6); | 1333 DCHECK(kArchVariant == kMips64r6); |
1278 DCHECK(!(rs.is(zero_reg))); | 1334 DCHECK(!(rs.is(zero_reg))); |
1279 DCHECK(!(rt.is(zero_reg))); | 1335 DCHECK(!(rt.is(zero_reg))); |
1280 DCHECK(rs.code() != rt.code()); | 1336 DCHECK(rs.code() != rt.code()); |
1281 GenInstrImmediate(BGTZ, rs, rt, offset); | 1337 GenInstrImmediate(BGTZ, rs, rt, offset, CompactBranchType::COMPACT_BRANCH); |
1282 } | 1338 } |
1283 | 1339 |
1284 | 1340 |
1285 void Assembler::bltc(Register rs, Register rt, int16_t offset) { | 1341 void Assembler::bltc(Register rs, Register rt, int16_t offset) { |
1286 DCHECK(kArchVariant == kMips64r6); | 1342 DCHECK(kArchVariant == kMips64r6); |
1287 DCHECK(!(rs.is(zero_reg))); | 1343 DCHECK(!rs.is(zero_reg)); |
1288 DCHECK(!(rt.is(zero_reg))); | 1344 DCHECK(!rt.is(zero_reg)); |
1289 DCHECK(rs.code() != rt.code()); | 1345 DCHECK(rs.code() != rt.code()); |
1290 GenInstrImmediate(BGTZL, rs, rt, offset); | 1346 GenInstrImmediate(BGTZL, rs, rt, offset, CompactBranchType::COMPACT_BRANCH); |
1291 } | 1347 } |
1292 | 1348 |
1293 | 1349 |
1294 void Assembler::bltz(Register rs, int16_t offset) { | 1350 void Assembler::bltz(Register rs, int16_t offset) { |
1295 BlockTrampolinePoolScope block_trampoline_pool(this); | 1351 BlockTrampolinePoolScope block_trampoline_pool(this); |
1296 GenInstrImmediate(REGIMM, rs, BLTZ, offset); | 1352 GenInstrImmediate(REGIMM, rs, BLTZ, offset); |
1297 BlockTrampolinePoolFor(1); // For associated delay slot. | 1353 BlockTrampolinePoolFor(1); // For associated delay slot. |
1298 } | 1354 } |
1299 | 1355 |
1300 | 1356 |
(...skipping 10 matching lines...) Expand all Loading... | |
1311 BlockTrampolinePoolScope block_trampoline_pool(this); | 1367 BlockTrampolinePoolScope block_trampoline_pool(this); |
1312 GenInstrImmediate(BNE, rs, rt, offset); | 1368 GenInstrImmediate(BNE, rs, rt, offset); |
1313 BlockTrampolinePoolFor(1); // For associated delay slot. | 1369 BlockTrampolinePoolFor(1); // For associated delay slot. |
1314 } | 1370 } |
1315 | 1371 |
1316 | 1372 |
1317 void Assembler::bovc(Register rs, Register rt, int16_t offset) { | 1373 void Assembler::bovc(Register rs, Register rt, int16_t offset) { |
1318 DCHECK(kArchVariant == kMips64r6); | 1374 DCHECK(kArchVariant == kMips64r6); |
1319 DCHECK(!(rs.is(zero_reg))); | 1375 DCHECK(!(rs.is(zero_reg))); |
1320 DCHECK(rs.code() >= rt.code()); | 1376 DCHECK(rs.code() >= rt.code()); |
1321 GenInstrImmediate(ADDI, rs, rt, offset); | 1377 GenInstrImmediate(ADDI, rs, rt, offset, CompactBranchType::COMPACT_BRANCH); |
1322 } | 1378 } |
1323 | 1379 |
1324 | 1380 |
1325 void Assembler::bnvc(Register rs, Register rt, int16_t offset) { | 1381 void Assembler::bnvc(Register rs, Register rt, int16_t offset) { |
1326 DCHECK(kArchVariant == kMips64r6); | 1382 DCHECK(kArchVariant == kMips64r6); |
1327 DCHECK(!(rs.is(zero_reg))); | 1383 DCHECK(!(rs.is(zero_reg))); |
1328 DCHECK(rs.code() >= rt.code()); | 1384 DCHECK(rs.code() >= rt.code()); |
1329 GenInstrImmediate(DADDI, rs, rt, offset); | 1385 GenInstrImmediate(DADDI, rs, rt, offset, CompactBranchType::COMPACT_BRANCH); |
1330 } | 1386 } |
1331 | 1387 |
1332 | 1388 |
1333 void Assembler::blezalc(Register rt, int16_t offset) { | 1389 void Assembler::blezalc(Register rt, int16_t offset) { |
1334 DCHECK(kArchVariant == kMips64r6); | 1390 DCHECK(kArchVariant == kMips64r6); |
1335 DCHECK(!(rt.is(zero_reg))); | 1391 DCHECK(!(rt.is(zero_reg))); |
1336 GenInstrImmediate(BLEZ, zero_reg, rt, offset); | 1392 positions_recorder()->WriteRecordedPositions(); |
1393 GenInstrImmediate(BLEZ, zero_reg, rt, offset, | |
1394 CompactBranchType::COMPACT_BRANCH); | |
1337 } | 1395 } |
1338 | 1396 |
1339 | 1397 |
1340 void Assembler::bgezalc(Register rt, int16_t offset) { | 1398 void Assembler::bgezalc(Register rt, int16_t offset) { |
1341 DCHECK(kArchVariant == kMips64r6); | 1399 DCHECK(kArchVariant == kMips64r6); |
1342 DCHECK(!(rt.is(zero_reg))); | 1400 DCHECK(!(rt.is(zero_reg))); |
1343 GenInstrImmediate(BLEZ, rt, rt, offset); | 1401 positions_recorder()->WriteRecordedPositions(); |
1402 GenInstrImmediate(BLEZ, rt, rt, offset, CompactBranchType::COMPACT_BRANCH); | |
1344 } | 1403 } |
1345 | 1404 |
1346 | 1405 |
1347 void Assembler::bgezall(Register rs, int16_t offset) { | 1406 void Assembler::bgezall(Register rs, int16_t offset) { |
1348 DCHECK(kArchVariant != kMips64r6); | 1407 DCHECK(kArchVariant != kMips64r6); |
1349 DCHECK(!(rs.is(zero_reg))); | 1408 DCHECK(!(rs.is(zero_reg))); |
1350 BlockTrampolinePoolScope block_trampoline_pool(this); | 1409 BlockTrampolinePoolScope block_trampoline_pool(this); |
1410 positions_recorder()->WriteRecordedPositions(); | |
1351 GenInstrImmediate(REGIMM, rs, BGEZALL, offset); | 1411 GenInstrImmediate(REGIMM, rs, BGEZALL, offset); |
1352 BlockTrampolinePoolFor(1); // For associated delay slot. | 1412 BlockTrampolinePoolFor(1); // For associated delay slot. |
1353 } | 1413 } |
1354 | 1414 |
1355 | 1415 |
1356 void Assembler::bltzalc(Register rt, int16_t offset) { | 1416 void Assembler::bltzalc(Register rt, int16_t offset) { |
1357 DCHECK(kArchVariant == kMips64r6); | 1417 DCHECK(kArchVariant == kMips64r6); |
1358 DCHECK(!(rt.is(zero_reg))); | 1418 DCHECK(!(rt.is(zero_reg))); |
1359 GenInstrImmediate(BGTZ, rt, rt, offset); | 1419 positions_recorder()->WriteRecordedPositions(); |
1420 GenInstrImmediate(BGTZ, rt, rt, offset, CompactBranchType::COMPACT_BRANCH); | |
1360 } | 1421 } |
1361 | 1422 |
1362 | 1423 |
1363 void Assembler::bgtzalc(Register rt, int16_t offset) { | 1424 void Assembler::bgtzalc(Register rt, int16_t offset) { |
1364 DCHECK(kArchVariant == kMips64r6); | 1425 DCHECK(kArchVariant == kMips64r6); |
1365 DCHECK(!(rt.is(zero_reg))); | 1426 DCHECK(!(rt.is(zero_reg))); |
1366 GenInstrImmediate(BGTZ, zero_reg, rt, offset); | 1427 GenInstrImmediate(BGTZ, zero_reg, rt, offset, |
Ilija.Pavlovic1
2015/12/18 11:38:22
Before GenInstrImmediate, to add "positions_record
ivica.bogosavljevic
2015/12/22 10:22:39
Acknowledged.
| |
1428 CompactBranchType::COMPACT_BRANCH); | |
1367 } | 1429 } |
1368 | 1430 |
1369 | 1431 |
1370 void Assembler::beqzalc(Register rt, int16_t offset) { | 1432 void Assembler::beqzalc(Register rt, int16_t offset) { |
1371 DCHECK(kArchVariant == kMips64r6); | 1433 DCHECK(kArchVariant == kMips64r6); |
1372 DCHECK(!(rt.is(zero_reg))); | 1434 DCHECK(!(rt.is(zero_reg))); |
1373 GenInstrImmediate(ADDI, zero_reg, rt, offset); | 1435 positions_recorder()->WriteRecordedPositions(); |
1436 GenInstrImmediate(ADDI, zero_reg, rt, offset, | |
1437 CompactBranchType::COMPACT_BRANCH); | |
1374 } | 1438 } |
1375 | 1439 |
1376 | 1440 |
1377 void Assembler::bnezalc(Register rt, int16_t offset) { | 1441 void Assembler::bnezalc(Register rt, int16_t offset) { |
1378 DCHECK(kArchVariant == kMips64r6); | 1442 DCHECK(kArchVariant == kMips64r6); |
1379 DCHECK(!(rt.is(zero_reg))); | 1443 DCHECK(!(rt.is(zero_reg))); |
1380 GenInstrImmediate(DADDI, zero_reg, rt, offset); | 1444 positions_recorder()->WriteRecordedPositions(); |
1445 positions_recorder()->WriteRecordedPositions(); | |
balazs.kilvady
2015/12/18 19:18:05
one call of 'positions_recorder()->WriteRecordedPo
ivica.bogosavljevic
2015/12/22 10:22:39
Acknowledged.
| |
1446 GenInstrImmediate(DADDI, zero_reg, rt, offset, | |
1447 CompactBranchType::COMPACT_BRANCH); | |
1381 } | 1448 } |
1382 | 1449 |
1383 | 1450 |
1384 void Assembler::beqc(Register rs, Register rt, int16_t offset) { | 1451 void Assembler::beqc(Register rs, Register rt, int16_t offset) { |
1385 DCHECK(kArchVariant == kMips64r6); | 1452 DCHECK(kArchVariant == kMips64r6); |
1386 DCHECK(rs.code() < rt.code()); | 1453 DCHECK(rs.code() != rt.code() && rs.code() != 0 && rt.code() != 0); |
1387 GenInstrImmediate(ADDI, rs, rt, offset); | 1454 if (rs.code() < rt.code()) { |
1455 GenInstrImmediate(ADDI, rs, rt, offset, CompactBranchType::COMPACT_BRANCH); | |
1456 } else { | |
1457 GenInstrImmediate(ADDI, rt, rs, offset, CompactBranchType::COMPACT_BRANCH); | |
1458 } | |
1388 } | 1459 } |
1389 | 1460 |
1390 | 1461 |
1391 void Assembler::beqzc(Register rs, int32_t offset) { | 1462 void Assembler::beqzc(Register rs, int32_t offset) { |
1392 DCHECK(kArchVariant == kMips64r6); | 1463 DCHECK(kArchVariant == kMips64r6); |
1393 DCHECK(!(rs.is(zero_reg))); | 1464 DCHECK(!(rs.is(zero_reg))); |
1394 Instr instr = POP66 | (rs.code() << kRsShift) | (offset & kImm21Mask); | 1465 GenInstrImmediate(POP66, rs, offset, CompactBranchType::COMPACT_BRANCH); |
1395 emit(instr); | |
1396 } | 1466 } |
1397 | 1467 |
1398 | 1468 |
1399 void Assembler::bnec(Register rs, Register rt, int16_t offset) { | 1469 void Assembler::bnec(Register rs, Register rt, int16_t offset) { |
1400 DCHECK(kArchVariant == kMips64r6); | 1470 DCHECK(kArchVariant == kMips64r6); |
1401 DCHECK(rs.code() < rt.code()); | 1471 DCHECK(rs.code() != rt.code() && rs.code() != 0 && rt.code() != 0); |
1402 GenInstrImmediate(DADDI, rs, rt, offset); | 1472 if (rs.code() < rt.code()) { |
1473 GenInstrImmediate(DADDI, rs, rt, offset, CompactBranchType::COMPACT_BRANCH); | |
1474 } else { | |
1475 GenInstrImmediate(DADDI, rt, rs, offset, CompactBranchType::COMPACT_BRANCH); | |
1476 } | |
1403 } | 1477 } |
1404 | 1478 |
1405 | 1479 |
1406 void Assembler::bnezc(Register rs, int32_t offset) { | 1480 void Assembler::bnezc(Register rs, int32_t offset) { |
1407 DCHECK(kArchVariant == kMips64r6); | 1481 DCHECK(kArchVariant == kMips64r6); |
1408 DCHECK(!(rs.is(zero_reg))); | 1482 DCHECK(!(rs.is(zero_reg))); |
1409 Instr instr = POP76 | (rs.code() << kRsShift) | offset; | 1483 GenInstrImmediate(POP76, rs, offset, CompactBranchType::COMPACT_BRANCH); |
1410 emit(instr); | |
1411 } | 1484 } |
1412 | 1485 |
1413 | 1486 |
1414 void Assembler::j(int64_t target) { | 1487 void Assembler::j(int64_t target) { |
1415 BlockTrampolinePoolScope block_trampoline_pool(this); | 1488 BlockTrampolinePoolScope block_trampoline_pool(this); |
1416 GenInstrJump(J, static_cast<uint32_t>(target >> 2) & kImm26Mask); | 1489 GenInstrJump(J, static_cast<uint32_t>(target >> 2) & kImm26Mask); |
1417 BlockTrampolinePoolFor(1); // For associated delay slot. | 1490 BlockTrampolinePoolFor(1); // For associated delay slot. |
1418 } | 1491 } |
1419 | 1492 |
1420 | 1493 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1471 DCHECK(rs.code() != rd.code()); | 1544 DCHECK(rs.code() != rd.code()); |
1472 BlockTrampolinePoolScope block_trampoline_pool(this); | 1545 BlockTrampolinePoolScope block_trampoline_pool(this); |
1473 positions_recorder()->WriteRecordedPositions(); | 1546 positions_recorder()->WriteRecordedPositions(); |
1474 GenInstrRegister(SPECIAL, rs, zero_reg, rd, 0, JALR); | 1547 GenInstrRegister(SPECIAL, rs, zero_reg, rd, 0, JALR); |
1475 BlockTrampolinePoolFor(1); // For associated delay slot. | 1548 BlockTrampolinePoolFor(1); // For associated delay slot. |
1476 } | 1549 } |
1477 | 1550 |
1478 | 1551 |
1479 void Assembler::jic(Register rt, int16_t offset) { | 1552 void Assembler::jic(Register rt, int16_t offset) { |
1480 DCHECK(kArchVariant == kMips64r6); | 1553 DCHECK(kArchVariant == kMips64r6); |
1481 Instr instr = POP66 | (JIC << kRsShift) | (rt.code() << kRtShift) | | 1554 GenInstrImmediate(POP66, zero_reg, rt, offset); |
1482 (offset & kImm16Mask); | |
1483 emit(instr); | |
1484 } | 1555 } |
1485 | 1556 |
1486 | 1557 |
1487 void Assembler::jialc(Register rt, int16_t offset) { | 1558 void Assembler::jialc(Register rt, int16_t offset) { |
1488 DCHECK(kArchVariant == kMips64r6); | 1559 DCHECK(kArchVariant == kMips64r6); |
1489 positions_recorder()->WriteRecordedPositions(); | 1560 positions_recorder()->WriteRecordedPositions(); |
1490 GenInstrImmediate(POP76, zero_reg, rt, offset); | 1561 GenInstrImmediate(POP76, zero_reg, rt, offset); |
1491 } | 1562 } |
1492 | 1563 |
1493 | 1564 |
(...skipping 526 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2020 GenInstrImmediate(SD, at, rd, 0); // Equiv to sw(rd, MemOperand(at, 0)); | 2091 GenInstrImmediate(SD, at, rd, 0); // Equiv to sw(rd, MemOperand(at, 0)); |
2021 } | 2092 } |
2022 } | 2093 } |
2023 | 2094 |
2024 | 2095 |
2025 // ---------PC-Relative instructions----------- | 2096 // ---------PC-Relative instructions----------- |
2026 | 2097 |
2027 void Assembler::addiupc(Register rs, int32_t imm19) { | 2098 void Assembler::addiupc(Register rs, int32_t imm19) { |
2028 DCHECK(kArchVariant == kMips64r6); | 2099 DCHECK(kArchVariant == kMips64r6); |
2029 DCHECK(rs.is_valid() && is_int19(imm19)); | 2100 DCHECK(rs.is_valid() && is_int19(imm19)); |
2030 int32_t imm21 = ADDIUPC << kImm19Bits | (imm19 & kImm19Mask); | 2101 uint32_t imm21 = ADDIUPC << kImm19Bits | (imm19 & kImm19Mask); |
2031 GenInstrImmediate(PCREL, rs, imm21); | 2102 GenInstrImmediate(PCREL, rs, imm21); |
2032 } | 2103 } |
2033 | 2104 |
2034 | 2105 |
2035 void Assembler::lwpc(Register rs, int32_t offset19) { | 2106 void Assembler::lwpc(Register rs, int32_t offset19) { |
2036 DCHECK(kArchVariant == kMips64r6); | 2107 DCHECK(kArchVariant == kMips64r6); |
2037 DCHECK(rs.is_valid() && is_int19(offset19)); | 2108 DCHECK(rs.is_valid() && is_int19(offset19)); |
2038 int32_t imm21 = LWPC << kImm19Bits | (offset19 & kImm19Mask); | 2109 uint32_t imm21 = LWPC << kImm19Bits | (offset19 & kImm19Mask); |
2039 GenInstrImmediate(PCREL, rs, imm21); | 2110 GenInstrImmediate(PCREL, rs, imm21); |
2040 } | 2111 } |
2041 | 2112 |
2042 | 2113 |
2043 void Assembler::lwupc(Register rs, int32_t offset19) { | 2114 void Assembler::lwupc(Register rs, int32_t offset19) { |
2044 DCHECK(kArchVariant == kMips64r6); | 2115 DCHECK(kArchVariant == kMips64r6); |
2045 DCHECK(rs.is_valid() && is_int19(offset19)); | 2116 DCHECK(rs.is_valid() && is_int19(offset19)); |
2046 int32_t imm21 = LWUPC << kImm19Bits | (offset19 & kImm19Mask); | 2117 uint32_t imm21 = LWUPC << kImm19Bits | (offset19 & kImm19Mask); |
2047 GenInstrImmediate(PCREL, rs, imm21); | 2118 GenInstrImmediate(PCREL, rs, imm21); |
2048 } | 2119 } |
2049 | 2120 |
2050 | 2121 |
2051 void Assembler::ldpc(Register rs, int32_t offset18) { | 2122 void Assembler::ldpc(Register rs, int32_t offset18) { |
2052 DCHECK(kArchVariant == kMips64r6); | 2123 DCHECK(kArchVariant == kMips64r6); |
2053 DCHECK(rs.is_valid() && is_int18(offset18)); | 2124 DCHECK(rs.is_valid() && is_int18(offset18)); |
2054 int32_t imm21 = LDPC << kImm18Bits | (offset18 & kImm18Mask); | 2125 uint32_t imm21 = LDPC << kImm18Bits | (offset18 & kImm18Mask); |
2055 GenInstrImmediate(PCREL, rs, imm21); | 2126 GenInstrImmediate(PCREL, rs, imm21); |
2056 } | 2127 } |
2057 | 2128 |
2058 | 2129 |
2059 void Assembler::auipc(Register rs, int16_t imm16) { | 2130 void Assembler::auipc(Register rs, int16_t imm16) { |
2060 DCHECK(kArchVariant == kMips64r6); | 2131 DCHECK(kArchVariant == kMips64r6); |
2061 DCHECK(rs.is_valid() && is_int16(imm16)); | 2132 DCHECK(rs.is_valid()); |
2062 int32_t imm21 = AUIPC << kImm16Bits | (imm16 & kImm16Mask); | 2133 uint32_t imm21 = AUIPC << kImm16Bits | (imm16 & kImm16Mask); |
2063 GenInstrImmediate(PCREL, rs, imm21); | 2134 GenInstrImmediate(PCREL, rs, imm21); |
2064 } | 2135 } |
2065 | 2136 |
2066 | 2137 |
2067 void Assembler::aluipc(Register rs, int16_t imm16) { | 2138 void Assembler::aluipc(Register rs, int16_t imm16) { |
2068 DCHECK(kArchVariant == kMips64r6); | 2139 DCHECK(kArchVariant == kMips64r6); |
2069 DCHECK(rs.is_valid() && is_int16(imm16)); | 2140 DCHECK(rs.is_valid()); |
2070 int32_t imm21 = ALUIPC << kImm16Bits | (imm16 & kImm16Mask); | 2141 uint32_t imm21 = ALUIPC << kImm16Bits | (imm16 & kImm16Mask); |
2071 GenInstrImmediate(PCREL, rs, imm21); | 2142 GenInstrImmediate(PCREL, rs, imm21); |
2072 } | 2143 } |
2073 | 2144 |
2074 | 2145 |
2075 // -------------Misc-instructions-------------- | 2146 // -------------Misc-instructions-------------- |
2076 | 2147 |
2077 // Break / Trap instructions. | 2148 // Break / Trap instructions. |
2078 void Assembler::break_(uint32_t code, bool break_as_stop) { | 2149 void Assembler::break_(uint32_t code, bool break_as_stop) { |
2079 DCHECK((code & ~0xfffff) == 0); | 2150 DCHECK((code & ~0xfffff) == 0); |
2080 // We need to invalidate breaks that could be stops as well because the | 2151 // We need to invalidate breaks that could be stops as well because the |
(...skipping 859 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2940 } | 3011 } |
2941 | 3012 |
2942 | 3013 |
2943 void Assembler::bc1t(int16_t offset, uint16_t cc) { | 3014 void Assembler::bc1t(int16_t offset, uint16_t cc) { |
2944 DCHECK(is_uint3(cc)); | 3015 DCHECK(is_uint3(cc)); |
2945 Instr instr = COP1 | BC1 | cc << 18 | 1 << 16 | (offset & kImm16Mask); | 3016 Instr instr = COP1 | BC1 | cc << 18 | 1 << 16 | (offset & kImm16Mask); |
2946 emit(instr); | 3017 emit(instr); |
2947 } | 3018 } |
2948 | 3019 |
2949 | 3020 |
2950 // Debugging. | |
2951 int Assembler::RelocateInternalReference(RelocInfo::Mode rmode, byte* pc, | 3021 int Assembler::RelocateInternalReference(RelocInfo::Mode rmode, byte* pc, |
2952 intptr_t pc_delta) { | 3022 intptr_t pc_delta) { |
2953 if (RelocInfo::IsInternalReference(rmode)) { | 3023 if (RelocInfo::IsInternalReference(rmode)) { |
2954 int64_t* p = reinterpret_cast<int64_t*>(pc); | 3024 int64_t* p = reinterpret_cast<int64_t*>(pc); |
2955 if (*p == kEndOfJumpChain) { | 3025 if (*p == kEndOfJumpChain) { |
2956 return 0; // Number of instructions patched. | 3026 return 0; // Number of instructions patched. |
2957 } | 3027 } |
2958 *p += pc_delta; | 3028 *p += pc_delta; |
2959 return 2; // Number of instructions patched. | 3029 return 2; // Number of instructions patched. |
2960 } | 3030 } |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2994 // Regular j/jal relocation. | 3064 // Regular j/jal relocation. |
2995 uint32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2; | 3065 uint32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2; |
2996 imm28 += pc_delta; | 3066 imm28 += pc_delta; |
2997 imm28 &= kImm28Mask; | 3067 imm28 &= kImm28Mask; |
2998 instr &= ~kImm26Mask; | 3068 instr &= ~kImm26Mask; |
2999 DCHECK((imm28 & 3) == 0); | 3069 DCHECK((imm28 & 3) == 0); |
3000 uint32_t imm26 = static_cast<uint32_t>(imm28 >> 2); | 3070 uint32_t imm26 = static_cast<uint32_t>(imm28 >> 2); |
3001 instr_at_put(pc, instr | (imm26 & kImm26Mask)); | 3071 instr_at_put(pc, instr | (imm26 & kImm26Mask)); |
3002 return 1; // Number of instructions patched. | 3072 return 1; // Number of instructions patched. |
3003 } else { | 3073 } else { |
3074 DCHECK(((instr & kJumpRawMask) == kJRawMark) || | |
3075 ((instr & kJumpRawMask) == kJalRawMark)); | |
3004 // Unbox raw offset and emit j/jal. | 3076 // Unbox raw offset and emit j/jal. |
3005 int32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2; | 3077 int32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2; |
3006 // Sign extend 28-bit offset to 32-bit. | 3078 // Sign extend 28-bit offset to 32-bit. |
3007 imm28 = (imm28 << 4) >> 4; | 3079 imm28 = (imm28 << 4) >> 4; |
3008 uint64_t target = | 3080 uint64_t target = |
3009 static_cast<int64_t>(imm28) + reinterpret_cast<uint64_t>(pc); | 3081 static_cast<int64_t>(imm28) + reinterpret_cast<uint64_t>(pc); |
3010 target &= kImm28Mask; | 3082 target &= kImm28Mask; |
3011 DCHECK((imm28 & 3) == 0); | 3083 DCHECK((imm28 & 3) == 0); |
3012 uint32_t imm26 = static_cast<uint32_t>(target >> 2); | 3084 uint32_t imm26 = static_cast<uint32_t>(target >> 2); |
3013 // Check markings whether to emit j or jal. | 3085 // Check markings whether to emit j or jal. |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3163 } | 3235 } |
3164 return; | 3236 return; |
3165 } | 3237 } |
3166 | 3238 |
3167 DCHECK(!trampoline_emitted_); | 3239 DCHECK(!trampoline_emitted_); |
3168 DCHECK(unbound_labels_count_ >= 0); | 3240 DCHECK(unbound_labels_count_ >= 0); |
3169 if (unbound_labels_count_ > 0) { | 3241 if (unbound_labels_count_ > 0) { |
3170 // First we emit jump (2 instructions), then we emit trampoline pool. | 3242 // First we emit jump (2 instructions), then we emit trampoline pool. |
3171 { BlockTrampolinePoolScope block_trampoline_pool(this); | 3243 { BlockTrampolinePoolScope block_trampoline_pool(this); |
3172 Label after_pool; | 3244 Label after_pool; |
3173 b(&after_pool); | 3245 if (kArchVariant == kMips64r6) { |
3174 nop(); | 3246 bc(&after_pool); |
3247 } else { | |
3248 b(&after_pool); | |
3249 nop(); | |
3250 } | |
3175 | 3251 |
3252 EmitPendingInstructions(); | |
3176 int pool_start = pc_offset(); | 3253 int pool_start = pc_offset(); |
3177 for (int i = 0; i < unbound_labels_count_; i++) { | 3254 for (int i = 0; i < unbound_labels_count_; i++) { |
3178 { BlockGrowBufferScope block_buf_growth(this); | 3255 { BlockGrowBufferScope block_buf_growth(this); |
3179 // Buffer growth (and relocation) must be blocked for internal | 3256 // Buffer growth (and relocation) must be blocked for internal |
3180 // references until associated instructions are emitted and available | 3257 // references until associated instructions are emitted and available |
3181 // to be patched. | 3258 // to be patched. |
3182 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE_ENCODED); | 3259 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE_ENCODED); |
3183 j(&after_pool); | 3260 j(&after_pool); |
3184 } | 3261 } |
3185 nop(); | 3262 nop(); |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3283 if (icache_flush_mode != SKIP_ICACHE_FLUSH) { | 3360 if (icache_flush_mode != SKIP_ICACHE_FLUSH) { |
3284 Assembler::FlushICache(isolate, pc, 4 * Assembler::kInstrSize); | 3361 Assembler::FlushICache(isolate, pc, 4 * Assembler::kInstrSize); |
3285 } | 3362 } |
3286 } | 3363 } |
3287 | 3364 |
3288 | 3365 |
3289 } // namespace internal | 3366 } // namespace internal |
3290 } // namespace v8 | 3367 } // namespace v8 |
3291 | 3368 |
3292 #endif // V8_TARGET_ARCH_MIPS64 | 3369 #endif // V8_TARGET_ARCH_MIPS64 |
OLD | NEW |