Arm64Assembler::Arm64Assembler(ArenaAllocator* allocator, const Arm64InstructionSetFeatures* art_features)
: Assembler(allocator) { // Retrieve already initialized default features of vixl.
vixl::CPUFeatures* features = vixl_masm_.GetCPUFeatures();
// These features should always be available.
DCHECK(features->Has(vixl::CPUFeatures::kFP));
DCHECK(features->Has(vixl::CPUFeatures::kNEON));
// The default vixl features should never assume atomics. We instead rely entirely on the ART // feature definitions to allow atomic usage (via LSE), as there may be chipset variants where LSE // is technically supported but better avoided in production.
DCHECK(!features->Has(vixl::CPUFeatures::kAtomics));
// Configure vixl::CPUFeatures according to ART instruction set features. if (art_features != nullptr) { if (art_features->HasCRC()) {
features->Combine(vixl::CPUFeatures::kCRC32);
} if (art_features->HasDotProd()) {
features->Combine(vixl::CPUFeatures::kDotProduct);
} if (art_features->HasFP16()) {
features->Combine(vixl::CPUFeatures::kFPHalf);
features->Combine(vixl::CPUFeatures::kNEONHalf);
} if (art_features->HasLSE()) {
features->Combine(vixl::CPUFeatures::kAtomics);
} if (art_features->HasSVE()) {
features->Combine(vixl::CPUFeatures::kSVE);
}
}
}
void Arm64Assembler::CopyInstructions(const MemoryRegion& region) { // Copy the instructions from the buffer.
MemoryRegion from(vixl_masm_.GetBuffer()->GetStartAddress<void*>(), CodeSize());
region.CopyFrom(0, from);
}
void Arm64Assembler::LoadRawPtr(ManagedRegister m_dst, ManagedRegister m_base, Offset offs) {
Arm64ManagedRegister dst = m_dst.AsArm64();
Arm64ManagedRegister base = m_base.AsArm64();
CHECK(dst.IsXRegister() && base.IsXRegister()); // Remove dst and base form the temp list - higher level API uses IP1, IP0.
UseScratchRegisterScope temps(&vixl_masm_);
temps.Exclude(reg_x(dst.AsXRegister()), reg_x(base.AsXRegister()));
___ Ldr(reg_x(dst.AsXRegister()), MEM_OP(reg_x(base.AsXRegister()), offs.Int32Value()));
}
void Arm64Assembler::JumpTo(ManagedRegister m_base, Offset offs, ManagedRegister m_scratch) {
Arm64ManagedRegister base = m_base.AsArm64();
Arm64ManagedRegister scratch = m_scratch.AsArm64();
CHECK(base.IsXRegister()) << base;
CHECK(scratch.IsXRegister()) << scratch; // Remove base and scratch form the temp list - higher level API uses IP1, IP0.
UseScratchRegisterScope temps(&vixl_masm_);
temps.Exclude(reg_x(base.AsXRegister()), reg_x(scratch.AsXRegister()));
___ Ldr(reg_x(scratch.AsXRegister()), MEM_OP(reg_x(base.AsXRegister()), offs.Int32Value()));
___ Br(reg_x(scratch.AsXRegister()));
}
void Arm64Assembler::SpillRegisters(CPURegList registers, int offset) { int size = registers.GetRegisterSizeInBytes(); constRegister sp = vixl_masm_.StackPointer(); // Since we are operating on register pairs, we would like to align on // double the standard size; on the other hand, we don't want to insert // an extra store, which will happen if the number of registers is even. if (!IsAlignedParam(offset, 2 * size) && registers.GetCount() % 2 != 0) { const CPURegister& dst0 = registers.PopLowestIndex();
___ Str(dst0, MemOperand(sp, offset));
cfi_.RelOffset(DWARFReg(dst0), offset);
offset += size;
} while (registers.GetCount() >= 2) { const CPURegister& dst0 = registers.PopLowestIndex(); const CPURegister& dst1 = registers.PopLowestIndex();
___ Stp(dst0, dst1, MemOperand(sp, offset));
cfi_.RelOffset(DWARFReg(dst0), offset);
cfi_.RelOffset(DWARFReg(dst1), offset + size);
offset += 2 * size;
} if (!registers.IsEmpty()) { const CPURegister& dst0 = registers.PopLowestIndex();
___ Str(dst0, MemOperand(sp, offset));
cfi_.RelOffset(DWARFReg(dst0), offset);
}
DCHECK(registers.IsEmpty());
}
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.