// Copyright 2015, 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.
// Some CPURegister methods can return Register or VRegister types, so we need // to declare them in advance. classRegister; class VRegister;
class CPURegister { public: enum RegisterType { // The kInvalid value is used to detect uninitialized static instances, // which are always zero-initialized before any constructors are called.
kInvalid = 0,
kRegister,
kVRegister,
kFPRegister = kVRegister,
kNoRegister
};
bool IsValid() const { if (IsValidRegister() || IsValidVRegister()) {
VIXL_ASSERT(!IsNone()); returntrue;
} else { // This assert is hit when the register has not been properly initialized. // One cause for this can be an initialisation order fiasco. See // https://isocpp.org/wiki/faq/ctors#static-init-order for some details.
VIXL_ASSERT(IsNone()); returnfalse;
}
}
// These assertions ensure that the size and type of the register are as // described. They do not consider the number of lanes that make up a vector. // So, for example, Is8B() implies IsD(), and Is1D() implies IsD, but IsD() // does not imply Is1D() or Is8B(). // Check the number of lanes, ie. the format of the vector, using methods such // as Is8B(), Is1D(), etc. in the VRegister class. bool IsV() const { return IsVRegister(); } bool IsB() const { return IsV() && Is8Bits(); } bool IsH() const { return IsV() && Is16Bits(); } bool IsS() const { return IsV() && Is32Bits(); } bool IsD() const { return IsV() && Is64Bits(); } bool IsQ() const { return IsV() && Is128Bits(); }
js::jit::Register asUnsized() const { // asUnsized() is only ever used on temp registers or on registers that // are known not to be SP, and there should be no risk of it being // applied to SP. Check anyway.
VIXL_ASSERT(code_ != kSPRegInternalCode); return js::jit::Register::FromCode((js::jit::Register::Code)code_);
}
// For consistency, we assert the number of lanes of these scalar registers, // even though there are no vectors of equivalent total size with which they // could alias. bool Is1B() const {
VIXL_ASSERT(!(Is8Bits() && IsVector())); return Is8Bits();
} bool Is1H() const {
VIXL_ASSERT(!(Is16Bits() && IsVector())); return Is16Bits();
} bool Is1S() const {
VIXL_ASSERT(!(Is32Bits() && IsVector())); return Is32Bits();
}
// Backward compatibility for FPRegisters. typedef VRegister FPRegister;
// No*Reg is used to indicate an unused argument, or an error case. Note that // these all compare equal (using the Is() method). The Register and VRegister // variants are provided for convenience. constRegister NoReg; const VRegister NoVReg; const FPRegister NoFPReg; // For backward compatibility. const CPURegister NoCPUReg;
// AreAliased returns true if any of the named registers overlap. Arguments // set to NoReg are ignored. The system stack pointer may be specified. bool AreAliased(const CPURegister& reg1, const CPURegister& reg2, const CPURegister& reg3 = NoReg, const CPURegister& reg4 = NoReg, const CPURegister& reg5 = NoReg, const CPURegister& reg6 = NoReg, const CPURegister& reg7 = NoReg, const CPURegister& reg8 = NoReg);
// AreSameSizeAndType returns true if all of the specified registers have the // same size, and are of the same type. The system stack pointer may be // specified. Arguments set to NoReg are ignored, as are any subsequent // arguments. At least one argument (reg1) must be valid (not NoCPUReg). bool AreSameSizeAndType(const CPURegister& reg1, const CPURegister& reg2, const CPURegister& reg3 = NoCPUReg, const CPURegister& reg4 = NoCPUReg, const CPURegister& reg5 = NoCPUReg, const CPURegister& reg6 = NoCPUReg, const CPURegister& reg7 = NoCPUReg, const CPURegister& reg8 = NoCPUReg);
// AreEven returns true if all of the specified registers have even register // indices. Arguments set to NoReg are ignored, as are any subsequent // arguments. At least one argument (reg1) must be valid (not NoCPUReg). bool AreEven(const CPURegister& reg1, const CPURegister& reg2, const CPURegister& reg3 = NoReg, const CPURegister& reg4 = NoReg, const CPURegister& reg5 = NoReg, const CPURegister& reg6 = NoReg, const CPURegister& reg7 = NoReg, const CPURegister& reg8 = NoReg);
// AreConsecutive returns true if all of the specified registers are // consecutive in the register file. Arguments set to NoReg are ignored, as are // any subsequent arguments. At least one argument (reg1) must be valid // (not NoCPUReg). bool AreConsecutive(const CPURegister& reg1, const CPURegister& reg2, const CPURegister& reg3 = NoCPUReg, const CPURegister& reg4 = NoCPUReg);
// AreSameFormat returns true if all of the specified VRegisters have the same // vector format. Arguments set to NoReg are ignored, as are any subsequent // arguments. At least one argument (reg1) must be valid (not NoVReg). bool AreSameFormat(const VRegister& reg1, const VRegister& reg2, const VRegister& reg3 = NoVReg, const VRegister& reg4 = NoVReg);
// AreConsecutive returns true if all of the specified VRegisters are // consecutive in the register file. Arguments set to NoReg are ignored, as are // any subsequent arguments. At least one argument (reg1) must be valid // (not NoVReg). bool AreConsecutive(const VRegister& reg1, const VRegister& reg2, const VRegister& reg3 = NoVReg, const VRegister& reg4 = NoVReg);
// Combine another CPURegList into this one. Registers that already exist in // this list are left unchanged. The type and size of the registers in the // 'other' list must match those in this list. void Combine(const CPURegList& other) {
VIXL_ASSERT(IsValid());
VIXL_ASSERT(other.type() == type_);
VIXL_ASSERT(other.RegisterSizeInBits() == size_);
list_ |= other.list();
}
// Remove every register in the other CPURegList from this one. Registers that // do not exist in this list are ignored. The type and size of the registers // in the 'other' list must match those in this list. void Remove(const CPURegList& other) {
VIXL_ASSERT(IsValid());
VIXL_ASSERT(other.type() == type_);
VIXL_ASSERT(other.RegisterSizeInBits() == size_);
list_ &= ~other.list();
}
// Variants of Combine and Remove which take a single register. void Combine(const CPURegister& other) {
VIXL_ASSERT(other.type() == type_);
VIXL_ASSERT(other.size() == size_);
Combine(other.code());
}
// Variants of Combine and Remove which take a single register by its code; // the type and size of the register is inferred from this list. void Combine(int code) {
VIXL_ASSERT(IsValid());
VIXL_ASSERT(CPURegister(code, size_, type_).IsValid());
list_ |= (UINT64_C(1) << code);
}
// Remove all callee-saved registers from the list. This can be useful when // preparing registers for an AAPCS64 function call, for example. void RemoveCalleeSaved();
// AAPCS64 caller-saved registers. Note that this includes lr. // TODO(all): Determine how we handle d8-d15 being callee-saved, but the top // 64-bits being caller-saved. static CPURegList GetCallerSaved(unsigned size = kXRegSize); static CPURegList GetCallerSavedV(unsigned size = kDRegSize);
// AAPCS64 caller-saved registers. Note that this includes lr. externconst CPURegList kCallerSaved; externconst CPURegList kCallerSavedV;
// Operand. class Operand { public: // #<immediate> // where <immediate> is int64_t. // This is allowed to be an implicit constructor because Operand is // a wrapper class that doesn't normally perform any type conversion.
Operand(int64_t immediate = 0); // NOLINT(runtime/explicit)
// rm, {<shift> #<shift_amount>} // where <shift> is one of {LSL, LSR, ASR, ROR}. // <shift_amount> is uint6_t. // This is allowed to be an implicit constructor because Operand is // a wrapper class that doesn't normally perform any type conversion.
Operand(Register reg,
Shift shift = LSL, unsigned shift_amount = 0); // NOLINT(runtime/explicit)
// rm, {<extend> {#<shift_amount>}} // where <extend> is one of {UXTB, UXTH, UXTW, UXTX, SXTB, SXTH, SXTW, SXTX}. // <shift_amount> is uint2_t. explicit Operand(Register reg, Extend extend, unsigned shift_amount = 0);
// This returns an LSL shift (<= 4) operand as an equivalent extend operand, // which helps in the encoding of instructions that use the stack pointer.
Operand ToExtendedRegister() const;
// Control whether or not position-independent code should be emitted. enum PositionIndependentCodeOption { // All code generated will be position-independent; all branches and // references to labels generated with the Label class will use PC-relative // addressing.
PositionIndependentCode,
// Allow VIXL to generate code that refers to absolute addresses. With this // option, it will not be possible to copy the code buffer and run it from a // different address; code must be generated in its final location.
PositionDependentCode,
// Allow VIXL to assume that the bottom 12 bits of the address will be // constant, but that the top 48 bits may change. This allows `adrp` to // function in systems which copy code between pages, but otherwise maintain // 4KB page alignment.
PageOffsetDependentCode
};
// Control how scaled- and unscaled-offset loads and stores are generated. enum LoadStoreScalingOption { // Prefer scaled-immediate-offset instructions, but emit unscaled-offset, // register-offset, pre-index or post-index instructions if necessary.
PreferScaledOffset,
// Prefer unscaled-immediate-offset instructions, but emit scaled-offset, // register-offset, pre-index or post-index instructions if necessary.
PreferUnscaledOffset,
// Assembler. class Assembler : public MozBaseAssembler { public:
Assembler(PositionIndependentCodeOption pic = PositionIndependentCode);
// System functions.
// Finalize a code buffer of generated instructions. This function must be // called before executing or copying code from the buffer. void FinalizeCode();
// Bit set when a DoubleCondition does not map to a single ARM condition. // The MacroAssembler must special-case these conditions, or else // ConditionFromDoubleCondition will complain. staticconstint DoubleConditionBitSpecial = 0x100;
// If either operand is NaN, these conditions always evaluate to true.
DoubleUnordered = Condition::vs,
DoubleEqualOrUnordered = Condition::eq | DoubleConditionBitSpecial,
DoubleNotEqualOrUnordered = Condition::ne,
DoubleGreaterThanOrUnordered = Condition::hi,
DoubleGreaterThanOrEqualOrUnordered = Condition::hs,
DoubleLessThanOrUnordered = Condition::lt,
DoubleLessThanOrEqualOrUnordered = Condition::le
};
staticinline Condition InvertCondition(Condition cond) { // Conditions al and nv behave identically, as "always true". They can't be // inverted, because there is no "always false" condition.
VIXL_ASSERT((cond != al) && (cond != nv)); returnstatic_cast<Condition>(cond ^ 1);
}
// This is chaging the condition codes for cmp a, b to the same codes for cmp b, a. staticinline Condition InvertCmpCondition(Condition cond) { // Conditions al and nv behave identically, as "always true". They can't be // inverted, because there is no "always false" condition. switch (cond) { case eq: case ne: return cond; case gt: return le; case le: return gt; case ge: return lt; case lt: return ge; case hi: return lo; case lo: return hi; case hs: return ls; case ls: return hs; case mi: return pl; case pl: return mi; default:
MOZ_CRASH("TODO: figure this case out.");
} returnstatic_cast<Condition>(cond ^ 1);
}
staticinline DoubleCondition InvertCondition(DoubleCondition cond) { switch (cond) { case DoubleOrdered: return DoubleUnordered; case DoubleEqual: return DoubleNotEqualOrUnordered; case DoubleNotEqual: return DoubleEqualOrUnordered; case DoubleGreaterThan: return DoubleLessThanOrEqualOrUnordered; case DoubleGreaterThanOrEqual: return DoubleLessThanOrUnordered; case DoubleLessThan: return DoubleGreaterThanOrEqualOrUnordered; case DoubleLessThanOrEqual: return DoubleGreaterThanOrUnordered; case DoubleUnordered: return DoubleOrdered; case DoubleEqualOrUnordered: return DoubleNotEqual; case DoubleNotEqualOrUnordered: return DoubleEqual; case DoubleGreaterThanOrUnordered: return DoubleLessThanOrEqual; case DoubleGreaterThanOrEqualOrUnordered: return DoubleLessThan; case DoubleLessThanOrUnordered: return DoubleGreaterThanOrEqual; case DoubleLessThanOrEqualOrUnordered: return DoubleGreaterThan; default:
MOZ_CRASH("Bad condition");
}
}
// Branch with link to register. void blr(constRegister& xn); staticvoid blr(Instruction* at, constRegister& blr);
// Branch to register with return hint. void ret(constRegister& xn = lr);
// Unconditional branch to label.
BufferOffset b(Label* label);
// Conditional branch to label.
BufferOffset b(Label* label, Condition cond);
// Unconditional branch to PC offset.
BufferOffset b(int imm26, const LabelDoc& doc); staticvoid b(Instruction* at, int imm26);
// Conditional branch to PC offset.
BufferOffset b(int imm19, Condition cond, const LabelDoc& doc); staticvoid b(Instruction*at, int imm19, Condition cond);
// Branch with link to label. void bl(Label* label);
// Branch with link to PC offset. void bl(int imm26, const LabelDoc& doc); staticvoid bl(Instruction* at, int imm26);
// Compare and branch to label if zero. void cbz(constRegister& rt, Label* label);
// Compare and branch to PC offset if zero. void cbz(constRegister& rt, int imm19, const LabelDoc& doc); staticvoid cbz(Instruction* at, constRegister& rt, int imm19);
// Compare and branch to label if not zero. void cbnz(constRegister& rt, Label* label);
// Compare and branch to PC offset if not zero. void cbnz(constRegister& rt, int imm19, const LabelDoc& doc); staticvoid cbnz(Instruction* at, constRegister& rt, int imm19);
// Table lookup from one register. void tbl(const VRegister& vd, const VRegister& vn, const VRegister& vm);
// Table lookup from two registers. void tbl(const VRegister& vd, const VRegister& vn, const VRegister& vn2, const VRegister& vm);
// Test bit and branch to label if zero. void tbz(constRegister& rt, unsigned bit_pos, Label* label);
// Test bit and branch to PC offset if zero. void tbz(constRegister& rt, unsigned bit_pos, int imm14, const LabelDoc& doc); staticvoid tbz(Instruction* at, constRegister& rt, unsigned bit_pos, int imm14);
// Test bit and branch to label if not zero. void tbnz(constRegister& rt, unsigned bit_pos, Label* label);
// Test bit and branch to PC offset if not zero. void tbnz(constRegister& rt, unsigned bit_pos, int imm14, const LabelDoc& doc); staticvoid tbnz(Instruction* at, constRegister& rt, unsigned bit_pos, int imm14);
// Address calculation instructions. // Calculate a PC-relative address. Unlike for branches the offset in adr is // unscaled (i.e. the result can be unaligned).
// Calculate the address of a label. void adr(constRegister& rd, Label* label);
// Calculate the address of a PC offset. void adr(constRegister& rd, int imm21, const LabelDoc& doc); staticvoid adr(Instruction* at, constRegister& rd, int imm21);
// Calculate the page address of a label. void adrp(constRegister& rd, Label* label);
// Calculate the page address of a PC offset. void adrp(constRegister& rd, int imm21, const LabelDoc& doc); staticvoid adrp(Instruction* at, constRegister& rd, int imm21);
// Store integer or FP register pair, non-temporal. void stnp(const CPURegister& rt, const CPURegister& rt2, const MemOperand& dst);
// Load integer or FP register from pc + imm19 << 2. void ldr(const CPURegister& rt, int imm19); staticvoid ldr(Instruction* at, const CPURegister& rt, int imm19);
// Load word with sign extension from pc + imm19 << 2. void ldrsw(constRegister& rt, int imm19); staticvoid ldrsw(Instruction* at, const CPURegister& rt, int imm19);
// Compare and Swap word or doubleword in memory [Armv8.1]. void cas(constRegister& rs, constRegister& rt, const MemOperand& src);
// Compare and Swap word or doubleword in memory [Armv8.1]. void casa(constRegister& rs, constRegister& rt, const MemOperand& src);
// Compare and Swap word or doubleword in memory [Armv8.1]. void casl(constRegister& rs, constRegister& rt, const MemOperand& src);
// Compare and Swap word or doubleword in memory [Armv8.1]. void casal(constRegister& rs, constRegister& rt, const MemOperand& src);
// Compare and Swap byte in memory [Armv8.1]. void casb(constRegister& rs, constRegister& rt, const MemOperand& src);
// Compare and Swap byte in memory [Armv8.1]. void casab(constRegister& rs, constRegister& rt, const MemOperand& src);
// Compare and Swap byte in memory [Armv8.1]. void caslb(constRegister& rs, constRegister& rt, const MemOperand& src);
// Compare and Swap byte in memory [Armv8.1]. void casalb(constRegister& rs, constRegister& rt, const MemOperand& src);
// Compare and Swap halfword in memory [Armv8.1]. void cash(constRegister& rs, constRegister& rt, const MemOperand& src);
// Compare and Swap halfword in memory [Armv8.1]. void casah(constRegister& rs, constRegister& rt, const MemOperand& src);
// Compare and Swap halfword in memory [Armv8.1]. void caslh(constRegister& rs, constRegister& rt, const MemOperand& src);
// Compare and Swap halfword in memory [Armv8.1]. void casalh(constRegister& rs, constRegister& rt, const MemOperand& src);
// Compare and Swap Pair of words or doublewords in memory [Armv8.1]. void casp(constRegister& rs, constRegister& rs2, constRegister& rt, constRegister& rt2, const MemOperand& src);
// Compare and Swap Pair of words or doublewords in memory [Armv8.1]. void caspa(constRegister& rs, constRegister& rs2, constRegister& rt, constRegister& rt2, const MemOperand& src);
// Compare and Swap Pair of words or doublewords in memory [Armv8.1]. void caspl(constRegister& rs, constRegister& rs2, constRegister& rt, constRegister& rt2, const MemOperand& src);
// Compare and Swap Pair of words or doublewords in memory [Armv8.1]. void caspal(constRegister& rs, constRegister& rs2, constRegister& rt, constRegister& rt2, const MemOperand& src);
// Atomic add on byte in memory [Armv8.1] void ldaddb(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic add on byte in memory, with Load-acquire semantics [Armv8.1] void ldaddab(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic add on byte in memory, with Store-release semantics [Armv8.1] void ldaddlb(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic add on byte in memory, with Load-acquire and Store-release semantics // [Armv8.1] void ldaddalb(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic add on halfword in memory [Armv8.1] void ldaddh(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic add on halfword in memory, with Load-acquire semantics [Armv8.1] void ldaddah(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic add on halfword in memory, with Store-release semantics [Armv8.1] void ldaddlh(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic add on halfword in memory, with Load-acquire and Store-release // semantics [Armv8.1] void ldaddalh(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic add on word or doubleword in memory [Armv8.1] void ldadd(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic add on word or doubleword in memory, with Load-acquire semantics // [Armv8.1] void ldadda(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic add on word or doubleword in memory, with Store-release semantics // [Armv8.1] void ldaddl(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic add on word or doubleword in memory, with Load-acquire and // Store-release semantics [Armv8.1] void ldaddal(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic bit clear on byte in memory [Armv8.1] void ldclrb(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic bit clear on byte in memory, with Load-acquire semantics [Armv8.1] void ldclrab(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic bit clear on byte in memory, with Store-release semantics [Armv8.1] void ldclrlb(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic bit clear on byte in memory, with Load-acquire and Store-release // semantics [Armv8.1] void ldclralb(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic bit clear on halfword in memory [Armv8.1] void ldclrh(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic bit clear on halfword in memory, with Load-acquire semantics // [Armv8.1] void ldclrah(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic bit clear on halfword in memory, with Store-release semantics // [Armv8.1] void ldclrlh(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic bit clear on halfword in memory, with Load-acquire and Store-release // semantics [Armv8.1] void ldclralh(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic bit clear on word or doubleword in memory [Armv8.1] void ldclr(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic bit clear on word or doubleword in memory, with Load-acquire // semantics [Armv8.1] void ldclra(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic bit clear on word or doubleword in memory, with Store-release // semantics [Armv8.1] void ldclrl(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic bit clear on word or doubleword in memory, with Load-acquire and // Store-release semantics [Armv8.1] void ldclral(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic exclusive OR on byte in memory [Armv8.1] void ldeorb(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic exclusive OR on byte in memory, with Load-acquire semantics // [Armv8.1] void ldeorab(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic exclusive OR on byte in memory, with Store-release semantics // [Armv8.1] void ldeorlb(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic exclusive OR on byte in memory, with Load-acquire and Store-release // semantics [Armv8.1] void ldeoralb(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic exclusive OR on halfword in memory [Armv8.1] void ldeorh(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic exclusive OR on halfword in memory, with Load-acquire semantics // [Armv8.1] void ldeorah(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic exclusive OR on halfword in memory, with Store-release semantics // [Armv8.1] void ldeorlh(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic exclusive OR on halfword in memory, with Load-acquire and // Store-release semantics [Armv8.1] void ldeoralh(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic exclusive OR on word or doubleword in memory [Armv8.1] void ldeor(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic exclusive OR on word or doubleword in memory, with Load-acquire // semantics [Armv8.1] void ldeora(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic exclusive OR on word or doubleword in memory, with Store-release // semantics [Armv8.1] void ldeorl(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic exclusive OR on word or doubleword in memory, with Load-acquire and // Store-release semantics [Armv8.1] void ldeoral(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic bit set on byte in memory [Armv8.1] void ldsetb(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic bit set on byte in memory, with Load-acquire semantics [Armv8.1] void ldsetab(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic bit set on byte in memory, with Store-release semantics [Armv8.1] void ldsetlb(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic bit set on byte in memory, with Load-acquire and Store-release // semantics [Armv8.1] void ldsetalb(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic bit set on halfword in memory [Armv8.1] void ldseth(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic bit set on halfword in memory, with Load-acquire semantics [Armv8.1] void ldsetah(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic bit set on halfword in memory, with Store-release semantics // [Armv8.1] void ldsetlh(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic bit set on halfword in memory, with Load-acquire and Store-release // semantics [Armv8.1] void ldsetalh(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic bit set on word or doubleword in memory [Armv8.1] void ldset(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic bit set on word or doubleword in memory, with Load-acquire semantics // [Armv8.1] void ldseta(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic bit set on word or doubleword in memory, with Store-release // semantics [Armv8.1] void ldsetl(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic bit set on word or doubleword in memory, with Load-acquire and // Store-release semantics [Armv8.1] void ldsetal(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic signed maximum on byte in memory [Armv8.1] void ldsmaxb(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic signed maximum on byte in memory, with Load-acquire semantics // [Armv8.1] void ldsmaxab(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic signed maximum on byte in memory, with Store-release semantics // [Armv8.1] void ldsmaxlb(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic signed maximum on byte in memory, with Load-acquire and // Store-release semantics [Armv8.1] void ldsmaxalb(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic signed maximum on halfword in memory [Armv8.1] void ldsmaxh(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic signed maximum on halfword in memory, with Load-acquire semantics // [Armv8.1] void ldsmaxah(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic signed maximum on halfword in memory, with Store-release semantics // [Armv8.1] void ldsmaxlh(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic signed maximum on halfword in memory, with Load-acquire and // Store-release semantics [Armv8.1] void ldsmaxalh(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic signed maximum on word or doubleword in memory [Armv8.1] void ldsmax(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic signed maximum on word or doubleword in memory, with Load-acquire // semantics [Armv8.1] void ldsmaxa(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic signed maximum on word or doubleword in memory, with Store-release // semantics [Armv8.1] void ldsmaxl(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic signed maximum on word or doubleword in memory, with Load-acquire // and Store-release semantics [Armv8.1] void ldsmaxal(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic signed minimum on byte in memory [Armv8.1] void ldsminb(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic signed minimum on byte in memory, with Load-acquire semantics // [Armv8.1] void ldsminab(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic signed minimum on byte in memory, with Store-release semantics // [Armv8.1] void ldsminlb(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic signed minimum on byte in memory, with Load-acquire and // Store-release semantics [Armv8.1] void ldsminalb(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic signed minimum on halfword in memory [Armv8.1] void ldsminh(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic signed minimum on halfword in memory, with Load-acquire semantics // [Armv8.1] void ldsminah(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic signed minimum on halfword in memory, with Store-release semantics // [Armv8.1] void ldsminlh(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic signed minimum on halfword in memory, with Load-acquire and // Store-release semantics [Armv8.1] void ldsminalh(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic signed minimum on word or doubleword in memory [Armv8.1] void ldsmin(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic signed minimum on word or doubleword in memory, with Load-acquire // semantics [Armv8.1] void ldsmina(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic signed minimum on word or doubleword in memory, with Store-release // semantics [Armv8.1] void ldsminl(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic signed minimum on word or doubleword in memory, with Load-acquire // and Store-release semantics [Armv8.1] void ldsminal(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic unsigned maximum on byte in memory [Armv8.1] void ldumaxb(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic unsigned maximum on byte in memory, with Load-acquire semantics // [Armv8.1] void ldumaxab(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic unsigned maximum on byte in memory, with Store-release semantics // [Armv8.1] void ldumaxlb(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic unsigned maximum on byte in memory, with Load-acquire and // Store-release semantics [Armv8.1] void ldumaxalb(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic unsigned maximum on halfword in memory [Armv8.1] void ldumaxh(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic unsigned maximum on halfword in memory, with Load-acquire semantics // [Armv8.1] void ldumaxah(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic unsigned maximum on halfword in memory, with Store-release semantics // [Armv8.1] void ldumaxlh(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic unsigned maximum on halfword in memory, with Load-acquire and // Store-release semantics [Armv8.1] void ldumaxalh(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic unsigned maximum on word or doubleword in memory [Armv8.1] void ldumax(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic unsigned maximum on word or doubleword in memory, with Load-acquire // semantics [Armv8.1] void ldumaxa(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic unsigned maximum on word or doubleword in memory, with Store-release // semantics [Armv8.1] void ldumaxl(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic unsigned maximum on word or doubleword in memory, with Load-acquire // and Store-release semantics [Armv8.1] void ldumaxal(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic unsigned minimum on byte in memory [Armv8.1] void lduminb(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic unsigned minimum on byte in memory, with Load-acquire semantics // [Armv8.1] void lduminab(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic unsigned minimum on byte in memory, with Store-release semantics // [Armv8.1] void lduminlb(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic unsigned minimum on byte in memory, with Load-acquire and // Store-release semantics [Armv8.1] void lduminalb(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic unsigned minimum on halfword in memory [Armv8.1] void lduminh(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic unsigned minimum on halfword in memory, with Load-acquire semantics // [Armv8.1] void lduminah(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic unsigned minimum on halfword in memory, with Store-release semantics // [Armv8.1] void lduminlh(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic unsigned minimum on halfword in memory, with Load-acquire and // Store-release semantics [Armv8.1] void lduminalh(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic unsigned minimum on word or doubleword in memory [Armv8.1] void ldumin(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic unsigned minimum on word or doubleword in memory, with Load-acquire // semantics [Armv8.1] void ldumina(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic unsigned minimum on word or doubleword in memory, with Store-release // semantics [Armv8.1] void lduminl(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic unsigned minimum on word or doubleword in memory, with Load-acquire // and Store-release semantics [Armv8.1] void lduminal(constRegister& rs, constRegister& rt, const MemOperand& src);
// Atomic add on byte in memory, without return. [Armv8.1] void staddb(constRegister& rs, const MemOperand& src);
// Atomic add on byte in memory, with Store-release semantics and without // return. [Armv8.1] void staddlb(constRegister& rs, const MemOperand& src);
// Atomic add on halfword in memory, without return. [Armv8.1] void staddh(constRegister& rs, const MemOperand& src);
// Atomic add on halfword in memory, with Store-release semantics and without // return. [Armv8.1] void staddlh(constRegister& rs, const MemOperand& src);
// Atomic add on word or doubleword in memory, without return. [Armv8.1] void stadd(constRegister& rs, const MemOperand& src);
// Atomic add on word or doubleword in memory, with Store-release semantics // and without return. [Armv8.1] void staddl(constRegister& rs, const MemOperand& src);
// Atomic bit clear on byte in memory, without return. [Armv8.1] void stclrb(constRegister& rs, const MemOperand& src);
// Atomic bit clear on byte in memory, with Store-release semantics and // without return. [Armv8.1] void stclrlb(constRegister& rs, const MemOperand& src);
// Atomic bit clear on halfword in memory, without return. [Armv8.1] void stclrh(constRegister& rs, const MemOperand& src);
// Atomic bit clear on halfword in memory, with Store-release semantics and // without return. [Armv8.1] void stclrlh(constRegister& rs, const MemOperand& src);
// Atomic bit clear on word or doubleword in memory, without return. [Armv8.1] void stclr(constRegister& rs, const MemOperand& src);
// Atomic bit clear on word or doubleword in memory, with Store-release // semantics and without return. [Armv8.1] void stclrl(constRegister& rs, const MemOperand& src);
// Atomic exclusive OR on byte in memory, without return. [Armv8.1] void steorb(constRegister& rs, const MemOperand& src);
// Atomic exclusive OR on byte in memory, with Store-release semantics and // without return. [Armv8.1] void steorlb(constRegister& rs, const MemOperand& src);
// Atomic exclusive OR on halfword in memory, without return. [Armv8.1] void steorh(constRegister& rs, const MemOperand& src);
// Atomic exclusive OR on halfword in memory, with Store-release semantics // and without return. [Armv8.1] void steorlh(constRegister& rs, const MemOperand& src);
// Atomic exclusive OR on word or doubleword in memory, without return. // [Armv8.1] void steor(constRegister& rs, const MemOperand& src);
// Atomic exclusive OR on word or doubleword in memory, with Store-release // semantics and without return. [Armv8.1] void steorl(constRegister& rs, const MemOperand& src);
// Atomic bit set on byte in memory, without return. [Armv8.1] void stsetb(constRegister& rs, const MemOperand& src);
// Atomic bit set on byte in memory, with Store-release semantics and without // return. [Armv8.1] void stsetlb(constRegister& rs, const MemOperand& src);
// Atomic bit set on halfword in memory, without return. [Armv8.1] void stseth(constRegister& rs, const MemOperand& src);
// Atomic bit set on halfword in memory, with Store-release semantics and // without return. [Armv8.1] void stsetlh(constRegister& rs, const MemOperand& src);
// Atomic bit set on word or doubleword in memory, without return. [Armv8.1] void stset(constRegister& rs, const MemOperand& src);
// Atomic bit set on word or doubleword in memory, with Store-release // semantics and without return. [Armv8.1] void stsetl(constRegister& rs, const MemOperand& src);
// Atomic signed maximum on byte in memory, without return. [Armv8.1] void stsmaxb(constRegister& rs, const MemOperand& src);
// Atomic signed maximum on byte in memory, with Store-release semantics and // without return. [Armv8.1] void stsmaxlb(constRegister& rs, const MemOperand& src);
// Atomic signed maximum on halfword in memory, without return. [Armv8.1] void stsmaxh(constRegister& rs, const MemOperand& src);
// Atomic signed maximum on halfword in memory, with Store-release semantics // and without return. [Armv8.1] void stsmaxlh(constRegister& rs, const MemOperand& src);
// Atomic signed maximum on word or doubleword in memory, without return. // [Armv8.1] void stsmax(constRegister& rs, const MemOperand& src);
// Atomic signed maximum on word or doubleword in memory, with Store-release // semantics and without return. [Armv8.1] void stsmaxl(constRegister& rs, const MemOperand& src);
// Atomic signed minimum on byte in memory, without return. [Armv8.1] void stsminb(constRegister& rs, const MemOperand& src);
// Atomic signed minimum on byte in memory, with Store-release semantics and // without return. [Armv8.1] void stsminlb(constRegister& rs, const MemOperand& src);
// Atomic signed minimum on halfword in memory, without return. [Armv8.1] void stsminh(constRegister& rs, const MemOperand& src);
// Atomic signed minimum on halfword in memory, with Store-release semantics // and without return. [Armv8.1] void stsminlh(constRegister& rs, const MemOperand& src);
// Atomic signed minimum on word or doubleword in memory, without return. // [Armv8.1] void stsmin(constRegister& rs, const MemOperand& src);
// Atomic signed minimum on word or doubleword in memory, with Store-release // semantics and without return. semantics [Armv8.1] void stsminl(constRegister& rs, const MemOperand& src);
// Atomic unsigned maximum on byte in memory, without return. [Armv8.1] void stumaxb(constRegister& rs, const MemOperand& src);
// Atomic unsigned maximum on byte in memory, with Store-release semantics and // without return. [Armv8.1] void stumaxlb(constRegister& rs, const MemOperand& src);
// Atomic unsigned maximum on halfword in memory, without return. [Armv8.1] void stumaxh(constRegister& rs, const MemOperand& src);
// Atomic unsigned maximum on halfword in memory, with Store-release semantics // and without return. [Armv8.1] void stumaxlh(constRegister& rs, const MemOperand& src);
// Atomic unsigned maximum on word or doubleword in memory, without return. // [Armv8.1] void stumax(constRegister& rs, const MemOperand& src);
// Atomic unsigned maximum on word or doubleword in memory, with Store-release // semantics and without return. [Armv8.1] void stumaxl(constRegister& rs, const MemOperand& src);
// Atomic unsigned minimum on byte in memory, without return. [Armv8.1] void stuminb(constRegister& rs, const MemOperand& src);
// Atomic unsigned minimum on byte in memory, with Store-release semantics and // without return. [Armv8.1] void stuminlb(constRegister& rs, const MemOperand& src);
// Atomic unsigned minimum on halfword in memory, without return. [Armv8.1] void stuminh(constRegister& rs, const MemOperand& src);
// Atomic unsigned minimum on halfword in memory, with Store-release semantics // and without return. [Armv8.1] void stuminlh(constRegister& rs, const MemOperand& src);
// Atomic unsigned minimum on word or doubleword in memory, without return. // [Armv8.1] void stumin(constRegister& rs, const MemOperand& src);
// Atomic unsigned minimum on word or doubleword in memory, with Store-release // semantics and without return. [Armv8.1] void stuminl(constRegister& rs, const MemOperand& src);
// Swap halfword in memory, with Load-acquire semantics [Armv8.1] void swpah(constRegister& rs, constRegister& rt, const MemOperand& src);
// Swap halfword in memory, with Store-release semantics [Armv8.1] void swplh(constRegister& rs, constRegister& rt, const MemOperand& src);
// Swap halfword in memory, with Load-acquire and Store-release semantics // [Armv8.1] void swpalh(constRegister& rs, constRegister& rt, const MemOperand& src);
// Swap word or doubleword in memory [Armv8.1] void swp(constRegister& rs, constRegister& rt, const MemOperand& src);
// Swap word or doubleword in memory, with Load-acquire semantics [Armv8.1] void swpa(constRegister& rs, constRegister& rt, const MemOperand& src);
// Swap word or doubleword in memory, with Store-release semantics [Armv8.1] void swpl(constRegister& rs, constRegister& rt, const MemOperand& src);
// Swap word or doubleword in memory, with Load-acquire and Store-release // semantics [Armv8.1] void swpal(constRegister& rs, constRegister& rt, const MemOperand& src);
// Prefetch from pc + imm19 << 2. void prfm(PrefetchOperation op, int imm19);
// Move instructions. The default shift of -1 indicates that the move // instruction will calculate an appropriate 16-bit immediate and left shift // that is equal to the 64-bit immediate argument. If an explicit left shift // is specified (0, 16, 32 or 48), the immediate must be a 16-bit value. // // For movk, an explicit shift can be used to indicate which half word should // be overwritten, eg. movk(x0, 0, 0) will overwrite the least-significant // half word with zero, whereas movk(x0, 0, 48) will overwrite the // most-significant.
// Move immediate and keep. void movk(constRegister& rd, uint64_t imm, int shift = -1) {
MoveWide(rd, imm, shift, MOVK);
}
// Multiply by scalar element. void mul(const VRegister& vd, const VRegister& vn, const VRegister& vm, int vm_index);
// Multiply-add by scalar element. void mla(const VRegister& vd, const VRegister& vn, const VRegister& vm, int vm_index);
// Multiply-subtract by scalar element. void mls(const VRegister& vd, const VRegister& vn, const VRegister& vm, int vm_index);
// Signed long multiply-add by scalar element. void smlal(const VRegister& vd, const VRegister& vn, const VRegister& vm, int vm_index);
// Signed long multiply-add by scalar element (second part). void smlal2(const VRegister& vd, const VRegister& vn, const VRegister& vm, int vm_index);
// Unsigned long multiply-add by scalar element. void umlal(const VRegister& vd, const VRegister& vn, const VRegister& vm, int vm_index);
// Unsigned long multiply-add by scalar element (second part). void umlal2(const VRegister& vd, const VRegister& vn, const VRegister& vm, int vm_index);
// Signed long multiply-sub by scalar element. void smlsl(const VRegister& vd, const VRegister& vn, const VRegister& vm, int vm_index);
// Signed long multiply-sub by scalar element (second part). void smlsl2(const VRegister& vd, const VRegister& vn, const VRegister& vm, int vm_index);
// Unsigned long multiply-sub by scalar element. void umlsl(const VRegister& vd, const VRegister& vn, const VRegister& vm, int vm_index);
// Unsigned long multiply-sub by scalar element (second part). void umlsl2(const VRegister& vd, const VRegister& vn, const VRegister& vm, int vm_index);
// Signed long multiply by scalar element. void smull(const VRegister& vd, const VRegister& vn, const VRegister& vm, int vm_index);
// Signed long multiply by scalar element (second part). void smull2(const VRegister& vd, const VRegister& vn, const VRegister& vm, int vm_index);
// Unsigned long multiply by scalar element. void umull(const VRegister& vd, const VRegister& vn, const VRegister& vm, int vm_index);
// Unsigned long multiply by scalar element (second part). void umull2(const VRegister& vd, const VRegister& vn, const VRegister& vm, int vm_index);
// Signed saturating double long multiply by element. void sqdmull(const VRegister& vd, const VRegister& vn, const VRegister& vm, int vm_index);
// Signed saturating double long multiply by element (second part). void sqdmull2(const VRegister& vd, const VRegister& vn, const VRegister& vm, int vm_index);
// Signed saturating doubling long multiply-add by element. void sqdmlal(const VRegister& vd, const VRegister& vn, const VRegister& vm, int vm_index);
// Signed saturating doubling long multiply-add by element (second part). void sqdmlal2(const VRegister& vd, const VRegister& vn, const VRegister& vm, int vm_index);
// Signed saturating doubling long multiply-sub by element. void sqdmlsl(const VRegister& vd, const VRegister& vn, const VRegister& vm, int vm_index);
// Signed saturating doubling long multiply-sub by element (second part). void sqdmlsl2(const VRegister& vd, const VRegister& vn, const VRegister& vm, int vm_index);
// Signed minimum across vector. void sminv(const VRegister& vd, const VRegister& vn);
// One-element structure store from one register. void st1(const VRegister& vt, const MemOperand& src);
// One-element structure store from two registers. void st1(const VRegister& vt, const VRegister& vt2, const MemOperand& src);
// One-element structure store from three registers. void st1(const VRegister& vt, const VRegister& vt2, const VRegister& vt3, const MemOperand& src);
// One-element structure store from four registers. void st1(const VRegister& vt, const VRegister& vt2, const VRegister& vt3, const VRegister& vt4, const MemOperand& src);
// One-element single structure store from one lane. void st1(const VRegister& vt, int lane, const MemOperand& src);
// Two-element structure store from two registers. void st2(const VRegister& vt, const VRegister& vt2, const MemOperand& src);
// Two-element single structure store from two lanes. void st2(const VRegister& vt, const VRegister& vt2, int lane, const MemOperand& src);
// Three-element structure store from three registers. void st3(const VRegister& vt, const VRegister& vt2, const VRegister& vt3, const MemOperand& src);
// Three-element single structure store from three lanes. void st3(const VRegister& vt, const VRegister& vt2, const VRegister& vt3, int lane, const MemOperand& src);
// Four-element structure store from four registers. void st4(const VRegister& vt, const VRegister& vt2, const VRegister& vt3, const VRegister& vt4, const MemOperand& src);
// Four-element single structure store from four lanes. void st4(const VRegister& vt, const VRegister& vt2, const VRegister& vt3, const VRegister& vt4, int lane, const MemOperand& src);
// These encoding functions allow the stack pointer to be encoded, and // disallow the zero register. static Instr RdSP(Register rd) {
VIXL_ASSERT(!rd.IsZero()); return (rd.code() & kRegCodeMask) << Rd_offset;
}
static Instr ImmNEON5(Instr format, int index) {
VIXL_ASSERT(IsUint4(index)); int s = LaneSizeInBytesLog2FromFormat(static_cast<VectorFormat>(format)); int imm5 = (index << (s + 1)) | (1 << s); return imm5 << ImmNEON5_offset;
}
static Instr ImmNEON4(Instr format, int index) {
VIXL_ASSERT(IsUint4(index)); int s = LaneSizeInBytesLog2FromFormat(static_cast<VectorFormat>(format)); int imm4 = index << s; return imm4 << ImmNEON4_offset;
}
// Determine whether the target CPU has the specified registers, based on the // currently-enabled CPU features. Presence of a register does not imply // support for arbitrary operations on it. For example, CPUs with FP have H // registers, but most half-precision operations require the FPHalf feature. // // These are used to check CPU features in loads and stores that have the same // entry point for both integer and FP registers. bool CPUHas(const CPURegister& rt) const; bool CPUHas(const CPURegister& rt, const CPURegister& rt2) const;
// Encode the specified MemOperand for the specified access size and scaling // preference.
Instr LoadStoreMemOperand(const MemOperand& addr, unsigned access_size,
LoadStoreScalingOption option);
protected: // Prevent generation of a literal pool for the next |maxInst| instructions. // Guarantees instruction linearity. class AutoBlockLiteralPool {
ARMBuffer* armbuffer_;
protected: // Buffer where the code is emitted.
PositionIndependentCodeOption pic_;
CPUFeatures cpu_features_;
#ifdef DEBUG bool finalized_; #endif
};
} // namespace vixl
#endif// VIXL_A64_ASSEMBLER_A64_H_
Messung V0.5 in Prozent
¤ 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.0.145Bemerkung:
(vorverarbeitet am 2026-04-28)
¤
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.