// Copyright 2016, VIXL authors // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // * Neither the name of ARM Limited nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include"jit/arm64/vixl/Operands-vixl.h"
namespace vixl {
// CPURegList utilities.
CPURegister CPURegList::PopLowestIndex(RegList mask) {
RegList list = list_ & mask; if (list == 0) return NoCPUReg; int index = CountTrailingZeros(list);
VIXL_ASSERT(((static_cast<RegList>(1) << index) & list) != 0);
Remove(index); return CPURegister(index, size_, type_);
}
CPURegister CPURegList::PopHighestIndex(RegList mask) {
RegList list = list_ & mask; if (list == 0) return NoCPUReg; int index = CountLeadingZeros(list);
index = kRegListSizeInBits - 1 - index;
VIXL_ASSERT(((static_cast<RegList>(1) << index) & list) != 0);
Remove(index); return CPURegister(index, size_, type_);
}
bool CPURegList::IsValid() const { if (type_ == CPURegister::kNoRegister) { // We can't use IsEmpty here because that asserts IsValid(). return list_ == 0;
} else { bool is_valid = true; // Try to create a CPURegister for each element in the list. for (int i = 0; i < kRegListSizeInBits; i++) { if (((list_ >> i) & 1) != 0) {
is_valid &= CPURegister(i, size_, type_).IsValid();
}
} return is_valid;
}
}
void CPURegList::RemoveCalleeSaved() { if (GetType() == CPURegister::kRegister) {
Remove(GetCalleeSaved(GetRegisterSizeInBits()));
} elseif (GetType() == CPURegister::kVRegister) {
Remove(GetCalleeSavedV(GetRegisterSizeInBits()));
} else {
VIXL_ASSERT(GetType() == CPURegister::kNoRegister);
VIXL_ASSERT(IsEmpty()); // The list must already be empty, so do nothing.
}
}
CPURegList CPURegList::GetCallerSaved(unsigned size) { // Registers x0-x18 and lr (x30) are caller-saved.
CPURegList list = CPURegList(CPURegister::kRegister, size, 0, 18); // Do not use lr directly to avoid initialisation order fiasco bugs for users.
list.Combine(Register(30, kXRegSize)); return list;
}
CPURegList CPURegList::GetCallerSavedV(unsigned size) { // Registers d0-d7 and d16-d31 are caller-saved.
CPURegList list = CPURegList(CPURegister::kVRegister, size, 0, 7);
list.Combine(CPURegList(CPURegister::kVRegister, size, 16, 31)); return list;
}
bool Operand::IsPlainRegister() const { return reg_.IsValid() &&
(((shift_ == NO_SHIFT) && (extend_ == NO_EXTEND)) || // No-op shifts.
((shift_ != NO_SHIFT) && (shift_amount_ == 0)) || // No-op extend operations. // We can't include [US]XTW here without knowing more about the // context; they are only no-ops for 32-bit operations. // // For example, this operand could be replaced with w1: // __ Add(w0, w0, Operand(w1, UXTW)); // However, no plain register can replace it in this context: // __ Add(x0, x0, Operand(w1, UXTW));
(((extend_ == UXTX) || (extend_ == SXTX)) && (shift_amount_ == 0)));
}
// These assertions match those in the shifted-register constructor.
VIXL_ASSERT(regoffset_.Is64Bits() && !regoffset_.IsSP());
VIXL_ASSERT(shift_ == LSL);
} else {
VIXL_ASSERT(offset.IsExtendedRegister());
VIXL_ASSERT(addrmode == Offset);
bool MemOperand::IsEquivalentToPlainRegister() const { if (regoffset_.Is(NoReg)) { // Immediate offset, pre-index or post-index. return GetOffset() == 0;
} elseif (GetRegisterOffset().IsZero()) { // Zero register offset, pre-index or post-index. // We can ignore shift and extend options because they all result in zero. return true;
} returnfalse;
}
bool SVEMemOperand::IsValid() const { #ifdef VIXL_DEBUG
{ // It should not be possible for an SVEMemOperand to match multiple types. int count = 0; if (IsScalarPlusImmediate()) count++; if (IsScalarPlusScalar()) count++; if (IsScalarPlusVector()) count++; if (IsVectorPlusImmediate()) count++; if (IsVectorPlusScalar()) count++; if (IsVectorPlusVector()) count++;
VIXL_ASSERT(count <= 1);
} #endif
// We can't have a register _and_ an immediate offset. if ((offset_ != 0) && (!regoffset_.IsNone())) returnfalse;
if (shift_amount_ != 0) { // Only shift and extend modifiers can take a shift amount. switch (mod_) { case NO_SVE_OFFSET_MODIFIER: case SVE_MUL_VL: returnfalse; case SVE_LSL: case SVE_UXTW: case SVE_SXTW: // Fall through. break;
}
}
bool SVEMemOperand::IsEquivalentToScalar() const { if (IsScalarPlusImmediate()) { return GetImmediateOffset() == 0;
} if (IsScalarPlusScalar()) { // We can ignore the shift because it will still result in zero. return GetScalarOffset().IsZero();
} // Forms involving vectors are never equivalent to a single scalar. returnfalse;
}
GenericOperand::GenericOperand(const CPURegister& reg)
: cpu_register_(reg), mem_op_size_(0) { if (reg.IsQ()) {
VIXL_ASSERT(reg.GetSizeInBits() > static_cast<int>(kXRegSize)); // Support for Q registers is not implemented yet.
VIXL_UNIMPLEMENTED();
}
}
GenericOperand::GenericOperand(const MemOperand& mem_op, size_t mem_op_size)
: cpu_register_(NoReg), mem_op_(mem_op), mem_op_size_(mem_op_size) { if (mem_op_size_ > kXRegSizeInBytes) { // We only support generic operands up to the size of X registers.
VIXL_UNIMPLEMENTED();
}
}
bool GenericOperand::Equals(const GenericOperand& other) const { if (!IsValid() || !other.IsValid()) { // Two invalid generic operands are considered equal. return !IsValid() && !other.IsValid();
} if (IsCPURegister() && other.IsCPURegister()) { return GetCPURegister().Is(other.GetCPURegister());
} elseif (IsMemOperand() && other.IsMemOperand()) { return GetMemOperand().Equals(other.GetMemOperand()) &&
(GetMemOperandSizeInBytes() == other.GetMemOperandSizeInBytes());
} returnfalse;
}
} // namespace vixl
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.