class ArmVIXLMacroAssembler final : public vixl32::MacroAssembler { public: // Most methods fit in a 1KB code buffer, which results in more optimal alloc/realloc and // fewer system calls than a larger default capacity. static constexpr size_t kDefaultCodeBufferCapacity = 1 * KB;
// The following interfaces can generate CMP+Bcc or Cbz/Cbnz. // CMP+Bcc are generated by default. // If a hint is given (is_far_target = false) and rn and label can all fit into Cbz/Cbnz, // then Cbz/Cbnz is generated. // Prefer following interfaces to using vixl32::MacroAssembler::Cbz/Cbnz. // In T32, Cbz/Cbnz instructions have following limitations: // - Far targets, which are over 126 bytes away, are not supported. // - Only low registers can be encoded. // - Backward branches are not supported. void CompareAndBranchIfZero(vixl32::Register rn,
vixl32::Label* label, bool is_far_target = true); void CompareAndBranchIfNonZero(vixl32::Register rn,
vixl32::Label* label, bool is_far_target = true);
// In T32 some of the instructions (add, mov, etc) outside an IT block // have only 32-bit encodings. But there are 16-bit flag setting // versions of these instructions (adds, movs, etc). In most of the // cases in ART we don't care if the instructions keep flags or not; // thus we can benefit from smaller code size. // VIXL will never generate flag setting versions (for example, adds // for Add macro instruction) unless vixl32::DontCare option is // explicitly specified. That's why we introduce wrappers to use // DontCare option by default. #define WITH_FLAGS_DONT_CARE_RD_RN_OP(func_name) \ void (func_name)(vixl32::Register rd, vixl32::Register rn, const vixl32::Operand& operand) { \
MacroAssembler::func_name(vixl32::DontCare, rd, rn, operand); \
} \ using MacroAssembler::func_name
// The following two functions don't fall into above categories. Overload them separately. void Rrx(vixl32::Register rd, vixl32::Register rn) {
MacroAssembler::Rrx(vixl32::DontCare, rd, rn);
} using MacroAssembler::Rrx;
// TODO: Remove when MacroAssembler::Add(FlagsUpdate, Condition, Register, Register, Operand) // makes the right decision about 16-bit encodings. void Add(vixl32::Register rd, vixl32::Register rn, const vixl32::Operand& operand) { if (rd.Is(rn) && operand.IsPlainRegister()) {
MacroAssembler::Add(rd, rn, operand);
} else {
MacroAssembler::Add(vixl32::DontCare, rd, rn, operand);
}
} using MacroAssembler::Add;
// These interfaces try to use 16-bit T2 encoding of B instruction. void B(vixl32::Label* label); // For B(label), we always try to use Narrow encoding, because 16-bit T2 encoding supports // jumping within 2KB range. For B(cond, label), because the supported branch range is 256 // bytes; we use the far_target hint to try to use 16-bit T1 encoding for short range jumps. void B(vixl32::Condition cond, vixl32::Label* label, bool is_far_target = true);
// Use literal for generating double constant if it doesn't fit VMOV encoding. void Vmov(vixl32::DRegister rd, double imm) { if (vixl::VFP::IsImmFP64(imm)) {
MacroAssembler::Vmov(rd, imm);
} else {
MacroAssembler::Vldr(rd, imm);
}
} using MacroAssembler::Vmov;
// TODO(b/281982421): Move the implementation of Mrrc to vixl and remove this implementation. void Mrrc(vixl32::Register r1, vixl32::Register r2, int coproc, int opc1, int crm) { // See ARM A-profile A32/T32 Instruction set architecture // https://developer.arm.com/documentation/ddi0597/2022-09/Base-Instructions/MRRC--Move-to-two-general-purpose-registers-from-System-register-
CHECK(coproc == 15 || coproc == 14); if (IsUsingT32()) {
uint32_t inst = (0b111011000101 << 20) |
(r2.GetCode() << 16) |
(r1.GetCode() << 12) |
(coproc << 8) |
(opc1 << 4) |
crm;
EmitT32_32(inst);
} else {
uint32_t inst = (0b000011000101 << 20) |
(r2.GetCode() << 16) |
(r1.GetCode() << 12) |
(coproc << 8) |
(opc1 << 4) |
crm;
EmitA32(inst);
}
}
};
class ArmVIXLAssembler final : public Assembler { private: class ArmException; public: explicit ArmVIXLAssembler(ArenaAllocator* allocator)
: Assembler(allocator) { // Use Thumb2 instruction set.
vixl_masm_.UseT32();
}
// Copy instructions out of assembly buffer into the given region of memory. void CopyInstructions(const MemoryRegion& region) override;
void Bind([[maybe_unused]] Label* label) override {
UNIMPLEMENTED(FATAL) << "Do not use Bind(Label*) for ARM";
} void Jump([[maybe_unused]] Label* label) override {
UNIMPLEMENTED(FATAL) << "Do not use Jump(Label*) for ARM";
}
// Poison a heap reference contained in `reg`. void PoisonHeapReference(vixl32::Register reg); // Unpoison a heap reference contained in `reg`. void UnpoisonHeapReference(vixl32::Register reg); // Poison a heap reference contained in `reg` if heap poisoning is enabled. void MaybePoisonHeapReference(vixl32::Register reg); // Unpoison a heap reference contained in `reg` if heap poisoning is enabled. void MaybeUnpoisonHeapReference(vixl32::Register reg);
// Emit code checking the status of the Marking Register, and aborting // the program if MR does not match the value stored in the art::Thread // object. // // Argument `temp` is used as a temporary register to generate code. // Argument `code` is used to identify the different occurrences of // MaybeGenerateMarkingRegisterCheck and is passed to the BKPT instruction. void GenerateMarkingRegisterCheck(vixl32::Register temp, int code = 0);
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.