inline vixl::aarch64::MemOperand HeapOperand(const vixl::aarch64::Register& base,
size_t offset = 0) { // A heap reference must be 32bit, so fit in a W register.
DCHECK(base.IsW()); return vixl::aarch64::MemOperand(base.X(), offset);
}
inline vixl::aarch64::MemOperand HeapOperand(const vixl::aarch64::Register& base, const vixl::aarch64::Register& regoffset,
vixl::aarch64::Shift shift = vixl::aarch64::LSL, unsigned shift_amount = 0) { // A heap reference must be 32bit, so fit in a W register.
DCHECK(base.IsW()); return vixl::aarch64::MemOperand(base.X(), regoffset, shift, shift_amount);
}
inlinebool AddSubCanEncodeAsImmediate(int64_t value) { // If `value` does not fit but `-value` does, VIXL will automatically use // the 'opposite' instruction. return vixl::aarch64::Assembler::IsImmAddSub(value)
|| vixl::aarch64::Assembler::IsImmAddSub(-value);
}
inlinebool Arm64CanEncodeConstantAsImmediate(HConstant* constant, HInstruction* instr) {
int64_t value = CodeGenerator::GetInt64ValueOf(constant);
// TODO: Improve this when IsSIMDConstantEncodable method is implemented in VIXL. if (instr->IsVecReplicateScalar()) { if (constant->IsLongConstant()) { returnfalse;
} elseif (constant->IsFloatConstant()) { return vixl::aarch64::Assembler::IsImmFP32(constant->AsFloatConstant()->GetValue());
} elseif (constant->IsDoubleConstant()) { return vixl::aarch64::Assembler::IsImmFP64(constant->AsDoubleConstant()->GetValue());
} return IsUint<8>(value);
}
// Code generation for Min/Max: // Cmp left_op, right_op // Csel dst, left_op, right_op, cond if (instr->IsMin() || instr->IsMax()) { if (constant->GetUses().HasExactlyOneElement()) { // If value can be encoded as immediate for the Cmp, then let VIXL handle // the constant generation for the Csel. return AddSubCanEncodeAsImmediate(value);
} // These values are encodable as immediates for Cmp and VIXL will use csinc and csinv // with the zr register as right_op, hence no constant generation is required. return constant->IsZeroBitPattern() || constant->IsOne() || constant->IsMinusOne();
}
// For single uses we let VIXL handle the constant generation since it will // use registers that are not managed by the register allocator (wip0, wip1). if (constant->GetUses().HasExactlyOneElement()) { returntrue;
}
// Our code generator ensures shift distances are within an encodable range. if (instr->IsRor()) { returntrue;
}
// Check if registers in art register set have the same register code in vixl. If the register // codes are same, we can initialize vixl register list simply by the register masks. Currently, // only SP/WSP and ZXR/WZR codes are different between art and vixl. // Note: This function is only used for debug checks. inlinebool ArtVixlRegCodeCoherentForRegSet(uint32_t art_core_registers,
size_t num_core,
uint32_t art_fpu_registers,
size_t num_fpu) { // The register masks won't work if the number of register is larger than 32.
DCHECK_GE(sizeof(art_core_registers) * 8, num_core);
DCHECK_GE(sizeof(art_fpu_registers) * 8, num_fpu); for (size_t art_reg_code = 0; art_reg_code < num_core; ++art_reg_code) { if (RegisterSet::Contains(art_core_registers, art_reg_code)) { if (art_reg_code != static_cast<size_t>(VIXLRegCodeFromART(art_reg_code))) { returnfalse;
}
}
} // There is no register code translation for float registers. returntrue;
}
inline vixl::aarch64::Shift ShiftFromOpKind(HDataProcWithShifterOp::OpKind op_kind) { switch (op_kind) { case HDataProcWithShifterOp::kASR: return vixl::aarch64::ASR; case HDataProcWithShifterOp::kLSL: return vixl::aarch64::LSL; case HDataProcWithShifterOp::kLSR: return vixl::aarch64::LSR; default:
LOG(FATAL) << "Unexpected op kind " << op_kind;
UNREACHABLE();
}
}
inline vixl::aarch64::Extend ExtendFromOpKind(HDataProcWithShifterOp::OpKind op_kind) { switch (op_kind) { case HDataProcWithShifterOp::kUXTB: return vixl::aarch64::UXTB; case HDataProcWithShifterOp::kUXTH: return vixl::aarch64::UXTH; case HDataProcWithShifterOp::kUXTW: return vixl::aarch64::UXTW; case HDataProcWithShifterOp::kSXTB: return vixl::aarch64::SXTB; case HDataProcWithShifterOp::kSXTH: return vixl::aarch64::SXTH; case HDataProcWithShifterOp::kSXTW: return vixl::aarch64::SXTW; default:
LOG(FATAL) << "Unexpected op kind " << op_kind;
UNREACHABLE();
}
}
inlinebool ShifterOperandSupportsExtension(HInstruction* instruction) {
DCHECK(HasShifterOperand(instruction, InstructionSet::kArm64)); // Although the `neg` instruction is an alias of the `sub` instruction, `HNeg` // does *not* support extension. This is because the `extended register` form // of the `sub` instruction interprets the left register with code 31 as the // stack pointer and not the zero register. (So does the `immediate` form.) In // the other form `shifted register, the register with code 31 is interpreted // as the zero register. return instruction->IsAdd() || instruction->IsSub();
}
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.