#pragma once // // This file is distributed under the MIT License. See LICENSE.md for details. // #include "llvm/ADT/Triple.h" #include "revng/Model/OperatingSystem.h" #include "revng/Model/Generated/Early/Architecture.h" namespace model::Architecture { inline bool isLittleEndian(Values V) { switch (V) { case model::Architecture::x86: case model::Architecture::x86_64: case model::Architecture::arm: case model::Architecture::aarch64: case model::Architecture::mipsel: return true; case model::Architecture::mips: case model::Architecture::systemz: return false; default: revng_abort(); } } inline Values fromLLVMArchitecture(llvm::Triple::ArchType A) { switch (A) { case llvm::Triple::x86: return model::Architecture::x86; case llvm::Triple::x86_64: return model::Architecture::x86_64; case llvm::Triple::arm: return model::Architecture::arm; case llvm::Triple::aarch64: return model::Architecture::aarch64; case llvm::Triple::mips: return model::Architecture::mips; case llvm::Triple::mipsel: return model::Architecture::mipsel; case llvm::Triple::systemz: return model::Architecture::systemz; default: return model::Architecture::Invalid; } } inline llvm::Triple::ArchType toLLVMArchitecture(Values V) { switch (V) { case model::Architecture::x86: return llvm::Triple::x86; case model::Architecture::x86_64: return llvm::Triple::x86_64; case model::Architecture::arm: return llvm::Triple::arm; case model::Architecture::aarch64: return llvm::Triple::aarch64; case model::Architecture::mips: return llvm::Triple::mips; case model::Architecture::mipsel: return llvm::Triple::mipsel; case model::Architecture::systemz: return llvm::Triple::systemz; default: revng_abort(); } } /// Return the size of the pointer in bytes constexpr inline uint64_t getPointerSize(Values V) { switch (V) { case model::Architecture::x86: case model::Architecture::arm: case model::Architecture::mips: case model::Architecture::mipsel: return 4; case model::Architecture::x86_64: case model::Architecture::aarch64: case model::Architecture::systemz: return 8; default: revng_abort(); } } constexpr inline uint64_t getCallPushSize(Values V) { switch (V) { case x86: return 4; case x86_64: return 8; case arm: case mips: case mipsel: case aarch64: case systemz: return 0; default: revng_abort(); } } constexpr inline llvm::ArrayRef getBasicBlockEndingPattern(Values V) { switch (V) { case x86: case x86_64: return "\xcc"; case arm: // bx lr return "\x1e\xff\x2f\xe1"; case mips: // jr ra return "\x08\x00\xe0\x03"; case mipsel: // jr ra return "\x03\xe0\x00\x08"; case aarch64: // ret return "\xc0\x03\x5f\xd6"; case systemz: // TODO return ""; default: revng_abort(); } } // TODO: this is libtinycode-specific constexpr inline llvm::StringRef getSyscallHelper(Values V) { switch (V) { case x86: return "helper_raise_interrupt"; case x86_64: return "helper_syscall"; case arm: case aarch64: return "helper_exception_with_syndrome"; case mips: case mipsel: return "helper_raise_exception"; case systemz: return "helper_exception"; default: revng_abort(); } } // TODO: this is libtinycode-specific inline llvm::ArrayRef getNoReturnSyscallNumbers(Values V) { switch (V) { case x86: { static uint64_t NoReturnSyscalls[] = { 0xfc, // exit_group 0x01, // exit 0x0b // execve }; return NoReturnSyscalls; } case x86_64: { static uint64_t NoReturnSyscalls[] = { 0xe7, // exit_group 0x3c, // exit 0x3b // execve }; return NoReturnSyscalls; } case arm: { static uint64_t NoReturnSyscalls[] = { 0xf8, // exit_group 0x1, // exit 0xb // execve }; return NoReturnSyscalls; } case aarch64: { static uint64_t NoReturnSyscalls[] = { 0x5e, // exit_group 0x5d, // exit 0xdd // execve }; return NoReturnSyscalls; } case mips: case mipsel: { static uint64_t NoReturnSyscalls[] = { 0x1096, // exit_group 0xfa1, // exit 0xfab // execve }; return NoReturnSyscalls; } case systemz: { static uint64_t NoReturnSyscalls[] = { 0xf8, // exit_group 0x1, // exit 0xb, // execve }; return NoReturnSyscalls; } default: revng_abort(); } } inline bool hasELFRelocationAddend(Values V) { switch (V) { case model::Architecture::x86_64: case model::Architecture::systemz: case model::Architecture::aarch64: return true; case model::Architecture::x86: case model::Architecture::arm: case model::Architecture::mips: case model::Architecture::mipsel: return false; default: revng_abort(); } } inline llvm::StringRef getReadRegisterAssembly(Values V) { switch (V) { case model::Architecture::x86_64: return "movq %REGISTER, $0"; case model::Architecture::systemz: case model::Architecture::x86: case model::Architecture::arm: case model::Architecture::aarch64: case model::Architecture::mips: case model::Architecture::mipsel: return ""; default: revng_abort(); } } inline llvm::StringRef getWriteRegisterAssembly(Values V) { switch (V) { case model::Architecture::x86_64: return "movq $0, %REGISTER"; case model::Architecture::systemz: case model::Architecture::x86: case model::Architecture::arm: case model::Architecture::aarch64: case model::Architecture::mips: case model::Architecture::mipsel: return ""; default: revng_abort(); } } inline llvm::StringRef getJumpAssembly(Values V) { switch (V) { case model::Architecture::x86_64: return "jmpq *$0"; case model::Architecture::systemz: case model::Architecture::x86: case model::Architecture::arm: case model::Architecture::aarch64: case model::Architecture::mips: case model::Architecture::mipsel: return ""; default: revng_abort(); } } llvm::StringRef getPCCSVName(Values V); inline llvm::StringRef getQEMUName(Values V) { switch (V) { case model::Architecture::x86_64: return "x86_64"; case model::Architecture::systemz: return "s390x"; case model::Architecture::x86: return "i386"; case model::Architecture::arm: return "arm"; case model::Architecture::aarch64: return "aarch64"; case model::Architecture::mips: return "mips"; case model::Architecture::mipsel: return "mipsel"; default: revng_abort(); } } inline Values fromQEMUName(llvm::StringRef Name) { if (Name == "x86_64") return model::Architecture::x86_64; else if (Name == "s390x") return model::Architecture::systemz; else if (Name == "i386") return model::Architecture::x86; else if (Name == "arm") return model::Architecture::arm; else if (Name == "aarch64") return model::Architecture::aarch64; else if (Name == "mips") return model::Architecture::mips; else if (Name == "mipsel") return model::Architecture::mipsel; else revng_abort(); } inline unsigned getMinimalFinalStackOffset(Values V) { switch (V) { case model::Architecture::x86_64: return 8; case model::Architecture::x86: return 4; case model::Architecture::systemz: case model::Architecture::arm: case model::Architecture::aarch64: case model::Architecture::mips: case model::Architecture::mipsel: return 0; default: revng_abort(); } } inline constexpr llvm::StringRef getAssemblyCommentIndicator(Values V) { switch (V) { case model::Architecture::x86: case model::Architecture::x86_64: case model::Architecture::mips: case model::Architecture::mipsel: case model::Architecture::systemz: return "#"; case model::Architecture::arm: return "@"; case model::Architecture::aarch64: return "//"; default: revng_abort(); } } inline constexpr llvm::StringRef getAssemblyLabelIndicator(Values V) { switch (V) { case model::Architecture::x86: case model::Architecture::x86_64: case model::Architecture::arm: case model::Architecture::aarch64: case model::Architecture::mips: case model::Architecture::mipsel: case model::Architecture::systemz: return ":"; default: revng_abort(); } } inline constexpr bool hasDelaySlot(Values V) { switch (V) { case model::Architecture::x86: case model::Architecture::x86_64: case model::Architecture::arm: case model::Architecture::aarch64: case model::Architecture::systemz: return false; case model::Architecture::mips: case model::Architecture::mipsel: return true; default: revng_abort(); } } inline bool isAvailableFor(Values V, model::OperatingSystem::Values OperatingSystem) { switch (OperatingSystem) { case model::OperatingSystem::Linux: switch (V) { case Architecture::x86_64: case Architecture::aarch64: case Architecture::x86: case Architecture::arm: case Architecture::mips: case Architecture::mipsel: case Architecture::systemz: return true; case Architecture::Count: case Architecture::Invalid: revng_abort(); } case model::OperatingSystem::Windows: switch (V) { case Architecture::x86_64: case Architecture::aarch64: case Architecture::x86: case Architecture::arm: return true; case Architecture::mips: case Architecture::mipsel: case Architecture::systemz: return false; case Architecture::Count: case Architecture::Invalid: revng_abort(); } case model::OperatingSystem::MacOS: switch (V) { case Architecture::x86_64: case Architecture::aarch64: return true; case Architecture::x86: case Architecture::arm: case Architecture::mips: case Architecture::mipsel: case Architecture::systemz: return false; case Architecture::Count: case Architecture::Invalid: revng_abort(); } case model::OperatingSystem::Invalid: // If unspecified, any architecture goes revng_assert(V != Architecture::Invalid); return true; default: revng_abort(); } } } // namespace model::Architecture #include "revng/Model/Generated/Late/Architecture.h"