// 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.
using js::jit::BufferOffset;
using js::jit::Label;
using js::jit::Address;
using js::jit::BaseIndex;
using js::jit::DisassemblerSpew;
using LabelDoc = DisassemblerSpew::LabelDoc;
// 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)); return static_cast<Condition>(cond ^ 1);
}
// This is chaging the condition codes for cmp a, b to the same codes for cmp b, a. staticinline Condition SwapCmpOperandsCondition(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 lt; case le: return ge; case ge: return le; case lt: return gt; 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.");
} return static_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.
BufferOffset 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.
BufferOffset 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.
BufferOffset 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.
BufferOffset 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.
BufferOffset 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.
BufferOffset 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.
BufferOffset 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;
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.