Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(167)

Side by Side Diff: src/arm64/macro-assembler-arm64.cc

Issue 2922173004: [arm64] Fix pre-shifted immediate generation involving csp. (Closed)
Patch Set: Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #if V8_TARGET_ARCH_ARM64 5 #if V8_TARGET_ARCH_ARM64
6 6
7 #include "src/arm64/frames-arm64.h" 7 #include "src/arm64/frames-arm64.h"
8 #include "src/assembler.h" 8 #include "src/assembler.h"
9 #include "src/base/bits.h" 9 #include "src/base/bits.h"
10 #include "src/base/division-by-constant.h" 10 #include "src/base/division-by-constant.h"
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 } 122 }
123 } 123 }
124 124
125 unsigned n, imm_s, imm_r; 125 unsigned n, imm_s, imm_r;
126 if (IsImmLogical(immediate, reg_size, &n, &imm_s, &imm_r)) { 126 if (IsImmLogical(immediate, reg_size, &n, &imm_s, &imm_r)) {
127 // Immediate can be encoded in the instruction. 127 // Immediate can be encoded in the instruction.
128 LogicalImmediate(rd, rn, n, imm_s, imm_r, op); 128 LogicalImmediate(rd, rn, n, imm_s, imm_r, op);
129 } else { 129 } else {
130 // Immediate can't be encoded: synthesize using move immediate. 130 // Immediate can't be encoded: synthesize using move immediate.
131 Register temp = temps.AcquireSameSizeAs(rn); 131 Register temp = temps.AcquireSameSizeAs(rn);
132 Operand imm_operand = MoveImmediateForShiftedOp(temp, immediate); 132
133 // If the left-hand input is the stack pointer, we can't pre-shift the
134 // immediate, as the encoding won't allow the subsequent post shift.
135 PreShiftImmMode mode = rn.Is(csp) ? kNoShift : kAnyShift;
136 Operand imm_operand = MoveImmediateForShiftedOp(temp, immediate, mode);
137
133 if (rd.Is(csp)) { 138 if (rd.Is(csp)) {
134 // If rd is the stack pointer we cannot use it as the destination 139 // If rd is the stack pointer we cannot use it as the destination
135 // register so we use the temp register as an intermediate again. 140 // register so we use the temp register as an intermediate again.
136 Logical(temp, rn, imm_operand, op); 141 Logical(temp, rn, imm_operand, op);
137 Mov(csp, temp); 142 Mov(csp, temp);
138 AssertStackConsistency(); 143 AssertStackConsistency();
139 } else { 144 } else {
140 Logical(rd, rn, imm_operand, op); 145 Logical(rd, rn, imm_operand, op);
141 } 146 }
142 } 147 }
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after
595 movn(dst, dst.Is64Bits() ? ~imm : (~imm & kWRegMask)); 600 movn(dst, dst.Is64Bits() ? ~imm : (~imm & kWRegMask));
596 return true; 601 return true;
597 } else if (IsImmLogical(imm, reg_size, &n, &imm_s, &imm_r)) { 602 } else if (IsImmLogical(imm, reg_size, &n, &imm_s, &imm_r)) {
598 // Immediate can be represented in a logical orr instruction. 603 // Immediate can be represented in a logical orr instruction.
599 LogicalImmediate(dst, AppropriateZeroRegFor(dst), n, imm_s, imm_r, ORR); 604 LogicalImmediate(dst, AppropriateZeroRegFor(dst), n, imm_s, imm_r, ORR);
600 return true; 605 return true;
601 } 606 }
602 return false; 607 return false;
603 } 608 }
604 609
605
606 Operand MacroAssembler::MoveImmediateForShiftedOp(const Register& dst, 610 Operand MacroAssembler::MoveImmediateForShiftedOp(const Register& dst,
607 int64_t imm) { 611 int64_t imm,
612 PreShiftImmMode mode) {
608 int reg_size = dst.SizeInBits(); 613 int reg_size = dst.SizeInBits();
609 614
610 // Encode the immediate in a single move instruction, if possible. 615 // Encode the immediate in a single move instruction, if possible.
611 if (TryOneInstrMoveImmediate(dst, imm)) { 616 if (TryOneInstrMoveImmediate(dst, imm)) {
612 // The move was successful; nothing to do here. 617 // The move was successful; nothing to do here.
613 } else { 618 } else {
614 // Pre-shift the immediate to the least-significant bits of the register. 619 // Pre-shift the immediate to the least-significant bits of the register.
615 int shift_low = CountTrailingZeros(imm, reg_size); 620 int shift_low = CountTrailingZeros(imm, reg_size);
621 if (mode == kLimitShiftForSP) {
622 // When applied to the stack pointer, the subsequent arithmetic operation
623 // can use the extend form to shift left by a maximum of four bits. Right
624 // shifts are not allowed, so we filter them out later before the new
625 // immediate is tested.
626 shift_low = std::min(shift_low, 4);
627 }
616 int64_t imm_low = imm >> shift_low; 628 int64_t imm_low = imm >> shift_low;
617 629
618 // Pre-shift the immediate to the most-significant bits of the register. We 630 // Pre-shift the immediate to the most-significant bits of the register. We
619 // insert set bits in the least-significant bits, as this creates a 631 // insert set bits in the least-significant bits, as this creates a
620 // different immediate that may be encodable using movn or orr-immediate. 632 // different immediate that may be encodable using movn or orr-immediate.
621 // If this new immediate is encodable, the set bits will be eliminated by 633 // If this new immediate is encodable, the set bits will be eliminated by
622 // the post shift on the following instruction. 634 // the post shift on the following instruction.
623 int shift_high = CountLeadingZeros(imm, reg_size); 635 int shift_high = CountLeadingZeros(imm, reg_size);
624 int64_t imm_high = (imm << shift_high) | ((1 << shift_high) - 1); 636 int64_t imm_high = (imm << shift_high) | ((1 << shift_high) - 1);
625 637
626 if (TryOneInstrMoveImmediate(dst, imm_low)) { 638 if ((mode != kNoShift) && TryOneInstrMoveImmediate(dst, imm_low)) {
627 // The new immediate has been moved into the destination's low bits: 639 // The new immediate has been moved into the destination's low bits:
628 // return a new leftward-shifting operand. 640 // return a new leftward-shifting operand.
629 return Operand(dst, LSL, shift_low); 641 return Operand(dst, LSL, shift_low);
630 } else if (TryOneInstrMoveImmediate(dst, imm_high)) { 642 } else if ((mode == kAnyShift) && TryOneInstrMoveImmediate(dst, imm_high)) {
631 // The new immediate has been moved into the destination's high bits: 643 // The new immediate has been moved into the destination's high bits:
632 // return a new rightward-shifting operand. 644 // return a new rightward-shifting operand.
633 return Operand(dst, LSR, shift_high); 645 return Operand(dst, LSR, shift_high);
634 } else { 646 } else {
635 // Use the generic move operation to set up the immediate. 647 // Use the generic move operation to set up the immediate.
636 Mov(dst, imm); 648 Mov(dst, imm);
637 } 649 }
638 } 650 }
639 return Operand(dst); 651 return Operand(dst);
640 } 652 }
(...skipping 15 matching lines...) Expand all
656 Register temp = temps.AcquireX(); 668 Register temp = temps.AcquireX();
657 Ldr(temp, operand.immediate()); 669 Ldr(temp, operand.immediate());
658 AddSubMacro(rd, rn, temp, S, op); 670 AddSubMacro(rd, rn, temp, S, op);
659 } else if ((operand.IsImmediate() && 671 } else if ((operand.IsImmediate() &&
660 !IsImmAddSub(operand.ImmediateValue())) || 672 !IsImmAddSub(operand.ImmediateValue())) ||
661 (rn.IsZero() && !operand.IsShiftedRegister()) || 673 (rn.IsZero() && !operand.IsShiftedRegister()) ||
662 (operand.IsShiftedRegister() && (operand.shift() == ROR))) { 674 (operand.IsShiftedRegister() && (operand.shift() == ROR))) {
663 UseScratchRegisterScope temps(this); 675 UseScratchRegisterScope temps(this);
664 Register temp = temps.AcquireSameSizeAs(rn); 676 Register temp = temps.AcquireSameSizeAs(rn);
665 if (operand.IsImmediate()) { 677 if (operand.IsImmediate()) {
678 PreShiftImmMode mode = kAnyShift;
679
680 // If the destination or source register is the stack pointer, we can
681 // only pre-shift the immediate right by values supported in the add/sub
682 // extend encoding.
683 if (rd.Is(csp)) {
684 // If the destination is SP and flags will be set, we can't pre-shift
685 // the immediate at all.
686 mode = (S == SetFlags) ? kNoShift : kLimitShiftForSP;
687 } else if (rn.Is(csp)) {
688 mode = kLimitShiftForSP;
689 }
690
666 Operand imm_operand = 691 Operand imm_operand =
667 MoveImmediateForShiftedOp(temp, operand.ImmediateValue()); 692 MoveImmediateForShiftedOp(temp, operand.ImmediateValue(), mode);
668 AddSub(rd, rn, imm_operand, S, op); 693 AddSub(rd, rn, imm_operand, S, op);
669 } else { 694 } else {
670 Mov(temp, operand); 695 Mov(temp, operand);
671 AddSub(rd, rn, temp, S, op); 696 AddSub(rd, rn, temp, S, op);
672 } 697 }
673 } else { 698 } else {
674 AddSub(rd, rn, operand, S, op); 699 AddSub(rd, rn, operand, S, op);
675 } 700 }
676 } 701 }
677 702
(...skipping 4091 matching lines...) Expand 10 before | Expand all | Expand 10 after
4769 } 4794 }
4770 4795
4771 4796
4772 #undef __ 4797 #undef __
4773 4798
4774 4799
4775 } // namespace internal 4800 } // namespace internal
4776 } // namespace v8 4801 } // namespace v8
4777 4802
4778 #endif // V8_TARGET_ARCH_ARM64 4803 #endif // V8_TARGET_ARCH_ARM64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698