Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ARM64 (aarch64) DRC backend #13162

Draft
wants to merge 21 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 13 additions & 43 deletions 3rdparty/asmjit/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,38 +1,16 @@
cmake_minimum_required(VERSION 3.8 FATAL_ERROR)
cmake_minimum_required(VERSION 3.19 FATAL_ERROR)

cmake_policy(PUSH)

if (POLICY CMP0063)
cmake_policy(SET CMP0063 NEW) # Honor visibility properties.
endif()

if (POLICY CMP0092)
cmake_policy(SET CMP0092 NEW) # Don't add -W3 warning level by default.
endif()

# Don't create a project if it was already created by another CMakeLists.txt.
# This allows one library to embed another library without making a collision.
# Don't create a project if it was already created by another CMakeLists.txt. This makes
# it possible to support both add_subdirectory() and include() ways of using AsmJit as a
# dependency.
if (NOT CMAKE_PROJECT_NAME OR "${CMAKE_PROJECT_NAME}" STREQUAL "asmjit")
project(asmjit CXX)
endif()

include(CheckCXXCompilerFlag)
INCLUDE(CheckCXXSourceCompiles)
include(CheckCXXSourceCompiles)
include(GNUInstallDirs)

# AsmJit - Deprecated
# ===================

if (DEFINED ASMJIT_BUILD_EMBED)
message(DEPRECATION "ASMJIT_BUILD_EMBED is deprecated, use ASMJIT_EMBED")
set(ASMJIT_EMBED "${ASMJIT_BUILD_EMBED}")
endif()

if (DEFINED ASMJIT_BUILD_STATIC)
message(DEPRECATION "ASMJIT_BUILD_STATIC is deprecated, use ASMJIT_STATIC")
set(ASMJIT_STATIC "${ASMJIT_BUILD_STATIC}")
endif()

# AsmJit - Configuration - Build
# ==============================

Expand Down Expand Up @@ -212,18 +190,14 @@ function(asmjit_add_target target target_type)
add_library(${target} ${target_type} ${X_SOURCES})
endif()

set_target_properties(${target} PROPERTIES DEFINE_SYMBOL "")
target_link_libraries(${target} PRIVATE ${X_LIBRARIES})

# target_link_options was added in cmake v3.13, don't use it for now...
foreach(link_flag ${ASMJIT_PRIVATE_LFLAGS})
set_property(TARGET ${target} APPEND_STRING PROPERTY LINK_FLAGS " ${link_flag}")
endforeach()

target_compile_features(${target} PUBLIC cxx_std_11)
set_property(TARGET ${target} PROPERTY CXX_EXTENSIONS NO)
set_property(TARGET ${target} PROPERTY CXX_VISIBILITY_PRESET hidden)
set_target_properties(${target}
PROPERTIES
DEFINE_SYMBOL ""
CXX_VISIBILITY_PRESET hidden)
target_compile_options(${target} PRIVATE ${X_CFLAGS} ${ASMJIT_SANITIZE_CFLAGS} $<$<CONFIG:Debug>:${X_CFLAGS_DBG}> $<$<NOT:$<CONFIG:Debug>>:${X_CFLAGS_REL}>)
target_compile_features(${target} PUBLIC cxx_std_11)
target_link_options(${target} PRIVATE ${ASMJIT_PRIVATE_LFLAGS})
target_link_libraries(${target} PRIVATE ${X_LIBRARIES})

if ("${target_type}" STREQUAL "TEST")
add_test(NAME ${target} COMMAND ${target})
Expand Down Expand Up @@ -590,10 +564,8 @@ if (NOT ASMJIT_EMBED)
$<BUILD_INTERFACE:${ASMJIT_INCLUDE_DIRS}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)

# Add blend2d::blend2d alias.
# Create an asmjit::asmjit alias.
add_library(asmjit::asmjit ALIAS asmjit)
# TODO: [CMAKE] Deprecated alias - we use projectname::libraryname convention now.
add_library(AsmJit::AsmJit ALIAS asmjit)

# Add AsmJit install instructions (library and public headers).
if (NOT ASMJIT_NO_INSTALL)
Expand Down Expand Up @@ -713,5 +685,3 @@ if (NOT ASMJIT_EMBED)

endif()
endif()

cmake_policy(POP)
58 changes: 46 additions & 12 deletions 3rdparty/asmjit/src/asmjit/arm/a64assembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,21 @@ static constexpr uint32_t kWX = InstDB::kWX;
static const uint8_t armShiftOpToLdStOptMap[] = { ASMJIT_LOOKUP_TABLE_16(VALUE, 0) };
#undef VALUE

// a64::Assembler - ExtendOpToRegType
// ==================================

static inline RegType extendOptionToRegType(uint32_t option) noexcept {
uint32_t pred = (uint32_t(RegType::kARM_GpW) << (0x0 * 4)) | // 0b000 - UXTB.
(uint32_t(RegType::kARM_GpW) << (0x1 * 4)) | // 0b001 - UXTH.
(uint32_t(RegType::kARM_GpW) << (0x2 * 4)) | // 0b010 - UXTW.
(uint32_t(RegType::kARM_GpX) << (0x3 * 4)) | // 0b011 - UXTX|LSL.
(uint32_t(RegType::kARM_GpW) << (0x4 * 4)) | // 0b100 - SXTB.
(uint32_t(RegType::kARM_GpW) << (0x5 * 4)) | // 0b101 - SXTH.
(uint32_t(RegType::kARM_GpW) << (0x6 * 4)) | // 0b110 - SXTW.
(uint32_t(RegType::kARM_GpX) << (0x7 * 4)) ; // 0b111 - SXTX.
return RegType((pred >> (option * 4u)) & 0xFu);
}

// asmjit::a64::Assembler - SizeOp
// ===============================

Expand Down Expand Up @@ -1228,9 +1243,6 @@ Error Assembler::_emit(InstId instId, const Operand_& o0, const Operand_& o1, co
}

if (isign4 == ENC_OPS3(Reg, Reg, Reg) || isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) {
if (!checkSignature(o1, o2))
goto InvalidInstruction;

uint32_t opSize = x ? 64 : 32;
uint64_t shift = 0;
uint32_t sType = uint32_t(ShiftOp::kLSL);
Expand All @@ -1247,11 +1259,17 @@ Error Assembler::_emit(InstId instId, const Operand_& o0, const Operand_& o1, co
if (sType <= uint32_t(ShiftOp::kASR)) {
bool hasSP = o0.as<Gp>().isSP() || o1.as<Gp>().isSP();
if (!hasSP) {
if (!checkGpId(o0, o1, kZR))
if (!checkSignature(o1, o2)) {
goto InvalidInstruction;
}

if (!checkGpId(o0, o1, kZR)) {
goto InvalidPhysId;
}

if (shift >= opSize)
if (shift >= opSize) {
goto InvalidImmediate;
}

opcode.reset(uint32_t(opData.shiftedOp) << 21);
opcode.addImm(x, 31);
Expand All @@ -1264,17 +1282,20 @@ Error Assembler::_emit(InstId instId, const Operand_& o0, const Operand_& o1, co
}

// SP register can only be used with LSL or Extend.
if (sType != uint32_t(ShiftOp::kLSL))
if (sType != uint32_t(ShiftOp::kLSL)) {
goto InvalidImmediate;
}

sType = x ? uint32_t(ShiftOp::kUXTX) : uint32_t(ShiftOp::kUXTW);
}

// Extend operation - UXTB, UXTH, UXTW, UXTX, SXTB, SXTH, SXTW, SXTX.
opcode.reset(uint32_t(opData.extendedOp) << 21);
sType -= uint32_t(ShiftOp::kUXTB);

if (sType > 7 || shift > 4)
if (sType > 7 || shift > 4) {
goto InvalidImmediate;
}

if (!(opcode.get() & B(29))) {
// ADD|SUB (extend) - ZR is not allowed.
Expand All @@ -1287,6 +1308,11 @@ Error Assembler::_emit(InstId instId, const Operand_& o0, const Operand_& o1, co
goto InvalidPhysId;
}

// Validate whether the register operands match extend option.
if (o2.as<Reg>().type() != extendOptionToRegType(sType) || o1.as<Reg>().type() < o2.as<Reg>().type()) {
goto InvalidInstruction;
}

opcode.addImm(x, 31);
opcode.addReg(o2, 16);
opcode.addImm(sType, 13);
Expand Down Expand Up @@ -1412,9 +1438,6 @@ Error Assembler::_emit(InstId instId, const Operand_& o0, const Operand_& o1, co
}

if (isign4 == ENC_OPS2(Reg, Reg) || isign4 == ENC_OPS3(Reg, Reg, Imm)) {
if (!checkSignature(o0, o1))
goto InvalidInstruction;

uint32_t opSize = x ? 64 : 32;
uint32_t sType = 0;
uint64_t shift = 0;
Expand All @@ -1429,8 +1452,13 @@ Error Assembler::_emit(InstId instId, const Operand_& o0, const Operand_& o1, co
// Shift operation - LSL, LSR, ASR.
if (sType <= uint32_t(ShiftOp::kASR)) {
if (!hasSP) {
if (shift >= opSize)
if (!checkSignature(o0, o1)) {
goto InvalidInstruction;
}

if (shift >= opSize) {
goto InvalidImmediate;
}

opcode.reset(uint32_t(opData.shiftedOp) << 21);
opcode.addImm(x, 31);
Expand All @@ -1451,8 +1479,14 @@ Error Assembler::_emit(InstId instId, const Operand_& o0, const Operand_& o1, co

// Extend operation - UXTB, UXTH, UXTW, UXTX, SXTB, SXTH, SXTW, SXTX.
sType -= uint32_t(ShiftOp::kUXTB);
if (sType > 7 || shift > 4)
if (sType > 7 || shift > 4) {
goto InvalidImmediate;
}

// Validate whether the register operands match extend option.
if (o1.as<Reg>().type() != extendOptionToRegType(sType) || o0.as<Reg>().type() < o1.as<Reg>().type()) {
goto InvalidInstruction;
}

opcode.reset(uint32_t(opData.extendedOp) << 21);
opcode.addImm(x, 31);
Expand Down
11 changes: 11 additions & 0 deletions 3rdparty/asmjit/src/asmjit/arm/a64emitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,17 @@ struct EmitterExplicitT {

//! \endcond


//! \name Native Registers
//! \{

//! Returns either 32-bit or 64-bit GP register of the given `id` depending on the emitter's architecture.
inline Gp gpz(uint32_t id) const noexcept { return Gp(_emitter()->_gpSignature, id); }
//! Clones the given `reg` to either 32-bit or 64-bit GP register depending on the emitter's architecture.
inline Gp gpz(const Gp& reg) const noexcept { return Gp(_emitter()->_gpSignature, reg.id()); }

//! \}

//! \name General Purpose Instructions
//! \{

Expand Down
4 changes: 2 additions & 2 deletions 3rdparty/asmjit/src/asmjit/arm/a64func.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(a64)

namespace FuncInternal {

static inline bool shouldThreatAsCDecl(CallConvId ccId) noexcept {
static inline bool shouldTreatAsCDecl(CallConvId ccId) noexcept {
return ccId == CallConvId::kCDecl ||
ccId == CallConvId::kStdCall ||
ccId == CallConvId::kFastCall ||
Expand Down Expand Up @@ -53,7 +53,7 @@ ASMJIT_FAVOR_SIZE Error initCallConv(CallConv& cc, CallConvId ccId, const Enviro
cc.setPassedOrder(RegGroup::kVec, 0, 1, 2, 3, 4, 5, 6, 7);
cc.setNaturalStackAlignment(16);

if (shouldThreatAsCDecl(ccId)) {
if (shouldTreatAsCDecl(ccId)) {
// ARM doesn't have that many calling conventions as we can find in X86 world, treat most conventions as __cdecl.
cc.setId(CallConvId::kCDecl);
cc.setPreservedRegs(RegGroup::kGp, Support::bitMask(Gp::kIdOs, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30));
Expand Down
2 changes: 1 addition & 1 deletion 3rdparty/asmjit/src/asmjit/arm/a64globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(a64)
//! AArch64 instruction.
//!
//! \note Only used to hold ARM-specific enumerations and static functions.
struct Inst {
namespace Inst {
//! Instruction id.
enum Id : uint32_t {
// ${InstId:Begin}
Expand Down
9 changes: 7 additions & 2 deletions 3rdparty/asmjit/src/asmjit/arm/a64instapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,11 +137,13 @@ Error queryRWInfo(const BaseInst& inst, const Operand_* operands, size_t opCount

if (memOp.hasBase()) {
op.addOpFlags(OpRWFlags::kMemBaseRead);
if ((memOp.hasIndex() || memOp.hasOffset()) && memOp.isPreOrPost()) {
op.addOpFlags(OpRWFlags::kMemBaseWrite);
}
}

if (memOp.hasIndex()) {
op.addOpFlags(OpRWFlags::kMemIndexRead);
op.addOpFlags(memOp.isPreOrPost() ? OpRWFlags::kMemIndexWrite : OpRWFlags::kNone);
}
}
}
Expand Down Expand Up @@ -191,10 +193,13 @@ Error queryRWInfo(const BaseInst& inst, const Operand_* operands, size_t opCount

if (memOp.hasBase()) {
op.addOpFlags(OpRWFlags::kMemBaseRead);
if ((memOp.hasIndex() || memOp.hasOffset()) && memOp.isPreOrPost()) {
op.addOpFlags(OpRWFlags::kMemBaseWrite);
}
}

if (memOp.hasIndex()) {
op.addOpFlags(memOp.isPreOrPost() ? OpRWFlags::kMemIndexRW : OpRWFlags::kMemIndexRead);
op.addOpFlags(OpRWFlags::kMemIndexRead);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion 3rdparty/asmjit/src/asmjit/arm/a64instdb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ const InstInfo _instInfoTable[] = {
INST(Ldlarb , BaseRM_NoImm , (0b0000100011011111011111, kW , kZR, 0 ) , kRWI_W , 0 , 8 ), // #149
INST(Ldlarh , BaseRM_NoImm , (0b0100100011011111011111, kW , kZR, 0 ) , kRWI_W , 0 , 9 ), // #150
INST(Ldnp , BaseLdpStp , (0b0010100001, 0 , kWX, 31, 2) , kRWI_WW , 0 , 0 ), // #151
INST(Ldp , BaseLdpStp , (0b0010100101, 0b0010100011, kWX, 31, 2) , kRWI_W , 0 , 1 ), // #152
INST(Ldp , BaseLdpStp , (0b0010100101, 0b0010100011, kWX, 31, 2) , kRWI_WW , 0 , 1 ), // #152
INST(Ldpsw , BaseLdpStp , (0b0110100101, 0b0110100011, kX , 0 , 2) , kRWI_WW , 0 , 2 ), // #153
INST(Ldr , BaseLdSt , (0b1011100101, 0b10111000010, 0b10111000011, 0b00011000, kWX, 30, 2, Inst::kIdLdur) , kRWI_W , 0 , 0 ), // #154
INST(Ldraa , BaseRM_SImm10 , (0b1111100000100000000001, kX , kZR, 0, 3) , kRWI_W , 0 , 0 ), // #155
Expand Down
50 changes: 39 additions & 11 deletions 3rdparty/asmjit/src/asmjit/arm/a64operand.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,17 +129,45 @@ class Vec : public BaseVec {
//! Resets vector element type to none.
ASMJIT_INLINE_NODEBUG void resetElementType() noexcept { _signature.setField<kSignatureRegElementTypeMask>(0); }

ASMJIT_INLINE_NODEBUG constexpr bool isVecB8() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecD>::kSignature | kSignatureElementB); }
ASMJIT_INLINE_NODEBUG constexpr bool isVecH4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecD>::kSignature | kSignatureElementH); }
ASMJIT_INLINE_NODEBUG constexpr bool isVecS2() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecD>::kSignature | kSignatureElementS); }
ASMJIT_INLINE_NODEBUG constexpr bool isVecD1() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecD>::kSignature); }

ASMJIT_INLINE_NODEBUG constexpr bool isVecB16() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementB); }
ASMJIT_INLINE_NODEBUG constexpr bool isVecH8() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementH); }
ASMJIT_INLINE_NODEBUG constexpr bool isVecS4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementS); }
ASMJIT_INLINE_NODEBUG constexpr bool isVecD2() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementD); }
ASMJIT_INLINE_NODEBUG constexpr bool isVecB4x4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementB4); }
ASMJIT_INLINE_NODEBUG constexpr bool isVecH2x4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementH2); }
ASMJIT_INLINE_NODEBUG constexpr bool isVecB8() const noexcept {
return _signature.subset(uint32_t(kBaseSignatureMask) | uint32_t(kSignatureRegElementTypeMask)) == (RegTraits<RegType::kARM_VecD>::kSignature | kSignatureElementB);
}

ASMJIT_INLINE_NODEBUG constexpr bool isVecH4() const noexcept {
return _signature.subset(uint32_t(kBaseSignatureMask) | uint32_t(kSignatureRegElementTypeMask)) == (RegTraits<RegType::kARM_VecD>::kSignature | kSignatureElementH);
}

ASMJIT_INLINE_NODEBUG constexpr bool isVecS2() const noexcept {
return _signature.subset(uint32_t(kBaseSignatureMask) | uint32_t(kSignatureRegElementTypeMask)) == (RegTraits<RegType::kARM_VecD>::kSignature | kSignatureElementS);
}

ASMJIT_INLINE_NODEBUG constexpr bool isVecD1() const noexcept {
return _signature.subset(uint32_t(kBaseSignatureMask) | uint32_t(kSignatureRegElementTypeMask)) == (RegTraits<RegType::kARM_VecD>::kSignature);
}

ASMJIT_INLINE_NODEBUG constexpr bool isVecB16() const noexcept {
return _signature.subset(uint32_t(kBaseSignatureMask) | uint32_t(kSignatureRegElementTypeMask)) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementB);
}

ASMJIT_INLINE_NODEBUG constexpr bool isVecH8() const noexcept {
return _signature.subset(uint32_t(kBaseSignatureMask) | uint32_t(kSignatureRegElementTypeMask)) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementH);
}

ASMJIT_INLINE_NODEBUG constexpr bool isVecS4() const noexcept {
return _signature.subset(uint32_t(kBaseSignatureMask) | uint32_t(kSignatureRegElementTypeMask)) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementS);
}

ASMJIT_INLINE_NODEBUG constexpr bool isVecD2() const noexcept {
return _signature.subset(uint32_t(kBaseSignatureMask) | uint32_t(kSignatureRegElementTypeMask)) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementD);
}

ASMJIT_INLINE_NODEBUG constexpr bool isVecB4x4() const noexcept {
return _signature.subset(uint32_t(kBaseSignatureMask) | uint32_t(kSignatureRegElementTypeMask)) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementB4);
}

ASMJIT_INLINE_NODEBUG constexpr bool isVecH2x4() const noexcept {
return _signature.subset(uint32_t(kBaseSignatureMask) | uint32_t(kSignatureRegElementTypeMask)) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementH2);
}

//! Creates a cloned register with element access.
ASMJIT_INLINE_NODEBUG Vec at(uint32_t elementIndex) const noexcept {
Expand Down
Loading
Loading