diff --git a/.build_number b/.build_number index 99814cec1..4f6811f46 100644 --- a/.build_number +++ b/.build_number @@ -1 +1 @@ -1595 +1597 diff --git a/CMakeLists.txt b/CMakeLists.txt index d8c375d74..5b553fa44 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -187,13 +187,13 @@ if(LLVM_INTERFACE) find_package(LLVM REQUIRED CONFIG) message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") - include_directories(${LLVM_INCLUDE_DIRS}) if(LLVM_LINK_LLVM_DYLIB) set(LLVM_LIBRARIES LLVM) else() set(LLVM_LIBRARIES ${LLVM_AVAILABLE_LIBS}) endif() endif() + include_directories(${LLVM_INCLUDE_DIRS}) set(TRITON_LLVM_INTERFACE ON) endif() diff --git a/src/libtriton/CMakeLists.txt b/src/libtriton/CMakeLists.txt index f8b664618..dc82de0cc 100644 --- a/src/libtriton/CMakeLists.txt +++ b/src/libtriton/CMakeLists.txt @@ -69,6 +69,7 @@ set(LIBTRITON_SOURCE_FILES stubs/x8664-ms-libc.cpp stubs/x8664-systemv-libc.cpp utils/coreUtils.cpp + utils/softfloat.cpp ) # Define all header files @@ -106,6 +107,7 @@ set(LIBTRITON_HEADER_FILES includes/triton/comparableFunctor.hpp includes/triton/context.hpp includes/triton/coreUtils.hpp + includes/triton/softfloat.hpp includes/triton/cpuInterface.hpp includes/triton/cpuSize.hpp includes/triton/dllexport.hpp @@ -157,6 +159,10 @@ set(LIBTRITON_HEADER_FILES includes/triton/z3ToTriton.hpp ) +set_source_files_properties(utils/softfloat.cpp PROPERTIES COMPILE_DEFINITIONS + ${CMAKE_CXX_BYTE_ORDER} +) + # Define all resource files set(LIBTRITON_RESOURCE_FILES includes/triton/version.hpp.in diff --git a/src/libtriton/arch/arm/aarch64/aarch64Cpu.cpp b/src/libtriton/arch/arm/aarch64/aarch64Cpu.cpp index 9da1f436e..da9f2093c 100644 --- a/src/libtriton/arch/arm/aarch64/aarch64Cpu.cpp +++ b/src/libtriton/arch/arm/aarch64/aarch64Cpu.cpp @@ -531,8 +531,23 @@ namespace triton { break; } + case triton::extlibs::capstone::ARM64_OP_FP: { + if (size == 0) { + throw triton::exceptions::Disassembly("Aarch64Cpu::disassembly(): Cannot correctly decode FP operand"); + } + + Immediate imm{op->fp, size, this->getEndianness()}; + + /* Set Shift type and value */ + imm.setShiftType(this->capstoneShiftToTritonShift(op->shift.type)); + imm.setShiftValue(op->shift.value); + + inst.operands.push_back(triton::arch::OperandWrapper(imm)); + break; + } + default: - /* NOTE: FP, CIMM, and missing one are not supported yet. */ + /* NOTE: CIMM, and missing one are not supported yet. */ throw triton::exceptions::Disassembly("AArch64Cpu::disassembly(): Invalid operand."); } // switch } // for operand diff --git a/src/libtriton/arch/arm/aarch64/aarch64Semantics.cpp b/src/libtriton/arch/arm/aarch64/aarch64Semantics.cpp index dccff3f09..cd6b52eaa 100644 --- a/src/libtriton/arch/arm/aarch64/aarch64Semantics.cpp +++ b/src/libtriton/arch/arm/aarch64/aarch64Semantics.cpp @@ -3298,7 +3298,7 @@ namespace triton { auto op = this->symbolicEngine->getOperandAst(inst, src); /* Create the semantics of the LOAD */ - auto node1 = this->astCtxt->sx(dst.getBitSize() - 8, op); + auto node1 = this->astCtxt->sx(dst.getBitSize() - 8, this->astCtxt->extract(7, 0, op)); /* Create symbolic expression */ auto expr1 = this->symbolicEngine->createSymbolicExpression(inst, node1, dst, "LDRSB operation - LOAD access"); @@ -3353,7 +3353,7 @@ namespace triton { auto op = this->symbolicEngine->getOperandAst(inst, src); /* Create the semantics of the LOAD */ - auto node1 = this->astCtxt->sx(dst.getBitSize() - 16, op); + auto node1 = this->astCtxt->sx(dst.getBitSize() - 16, this->astCtxt->extract(15, 0, op)); /* Create symbolic expression */ auto expr1 = this->symbolicEngine->createSymbolicExpression(inst, node1, dst, "LDRSH operation - LOAD access"); @@ -3413,7 +3413,7 @@ namespace triton { auto op = this->symbolicEngine->getOperandAst(inst, src); /* Create the semantics of the LOAD */ - auto node1 = this->astCtxt->sx(dst.getBitSize() - 32, op); + auto node1 = this->astCtxt->sx(dst.getBitSize() - 32, this->astCtxt->extract(31, 0, op)); /* Create symbolic expression */ auto expr1 = this->symbolicEngine->createSymbolicExpression(inst, node1, dst, "LDRSW operation - LOAD access"); diff --git a/src/libtriton/arch/immediate.cpp b/src/libtriton/arch/immediate.cpp index 301e25a8f..40616e0f3 100644 --- a/src/libtriton/arch/immediate.cpp +++ b/src/libtriton/arch/immediate.cpp @@ -5,10 +5,17 @@ ** This program is under the terms of the Apache License 2.0. */ +#include #include #include -#include +#include +#include +#ifdef LITTLE_ENDIAN // provided by CMake +constexpr auto sys_endianness = triton::arch::LE_ENDIANNESS; +#else +constexpr auto sys_endianness = triton::arch::BE_ENDIANNESS; +#endif namespace triton { @@ -24,6 +31,40 @@ namespace triton { } + Immediate::Immediate(double value, triton::uint32 size /* bytes */, triton::arch::endianness_e platform_endianness) { + triton::uint64 imm_value; + auto need_swap = sys_endianness != platform_endianness; + + if (size == sizeof(double)) { + static_assert(sizeof(double) == sizeof(triton::uint64), "Unexpected double type size"); + std::memcpy(&imm_value, &value, sizeof(double)); + if (need_swap) { + imm_value = utils::byteswap(imm_value); + } + } + + else if (size == sizeof(float)) { // single-precision + float fvalue = static_cast(value); + triton::uint32 repr; + static_assert(sizeof(float) == sizeof(uint32_t), "Unexpected float type size"); + std::memcpy(&repr, &fvalue, sizeof(float)); + imm_value = need_swap ? static_cast(utils::byteswap(repr)) : static_cast(repr); + } + + else if (size == 2) { // half-precision + float fvalue = static_cast(value); + triton::uint16 repr = triton::sf::f32_to_f16(fvalue); + imm_value = need_swap ? static_cast(utils::byteswap(repr)) : static_cast(repr); + } + + else { + throw triton::exceptions::Immediate("Immediate::Immediate(double): Invalid encoding size."); + } + + this->setValue(imm_value, size); + } + + Immediate::Immediate(const Immediate& other) : BitsVector(other), ArmOperandProperties(other) { diff --git a/src/libtriton/includes/triton/coreUtils.hpp b/src/libtriton/includes/triton/coreUtils.hpp index 9fdec4d62..b9aaf1579 100644 --- a/src/libtriton/includes/triton/coreUtils.hpp +++ b/src/libtriton/includes/triton/coreUtils.hpp @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -81,6 +82,16 @@ namespace triton { template <> TRITON_EXPORT triton::uint80 cast(const triton::uint512& value); template <> TRITON_EXPORT triton::uint512 cast(const triton::uint80& value); + template + std::enable_if_t, T> byteswap(T value) { + std::array repr; + std::memcpy(&repr, &value, sizeof(value)); + std::reverse(repr.begin(), repr.end()); + T result; + std::memcpy(&result, &repr, sizeof(result)); + return result; + } + /*! @} End of utils namespace */ }; /*! @} End of triton namespace */ diff --git a/src/libtriton/includes/triton/immediate.hpp b/src/libtriton/includes/triton/immediate.hpp index 9db4a9301..29f94a9c5 100644 --- a/src/libtriton/includes/triton/immediate.hpp +++ b/src/libtriton/includes/triton/immediate.hpp @@ -50,6 +50,9 @@ namespace triton { //! Constructor. TRITON_EXPORT Immediate(triton::uint64 value, triton::uint32 size /* bytes*/); + //! Constructor. + TRITON_EXPORT Immediate(double value, triton::uint32 size /* bytes */, triton::arch::endianness_e platform_endianness); + //! Constructor by copy. TRITON_EXPORT Immediate(const Immediate& other); diff --git a/src/libtriton/includes/triton/softfloat.hpp b/src/libtriton/includes/triton/softfloat.hpp new file mode 100644 index 000000000..fc2df6abf --- /dev/null +++ b/src/libtriton/includes/triton/softfloat.hpp @@ -0,0 +1,35 @@ +//! \file +/* +** Copyright (C) - Triton +** +** This program is under the terms of the Apache License 2.0. +*/ + +#ifndef TRITON_SOFTFLOAT_HPP +#define TRITON_SOFTFLOAT_HPP + +#include + +//! The Triton namespace +namespace triton { +/*! + * \addtogroup triton + * @{ + */ + //! The Softfloat namespace + namespace sf { + /*! + * \ingroup triton + * \addtogroup softfloat + * @{ + */ + + //! Cast 32-bit floating point value to 16-bit according to IEEE-754 + auto f32_to_f16(float value) -> uint16_t; + + /*! @} End of softfloat namespace */ + }; +/*! @} End of triton namespace */ +}; + +#endif /* TRITON_SOFTFLOAT_HPP */ diff --git a/src/libtriton/utils/softfloat.cpp b/src/libtriton/utils/softfloat.cpp new file mode 100644 index 000000000..be02c0cbd --- /dev/null +++ b/src/libtriton/utils/softfloat.cpp @@ -0,0 +1,49 @@ +//! \file +/* +** Copyright (C) - Triton +** +** This program is under the terms of the Apache License 2.0. +*/ + +#include + +#include + +namespace triton { + namespace sf { + + uint16_t f32_to_f16(float value) { + uint32_t f; + + static_assert(sizeof(float) == sizeof(uint32_t), "Unexpected float type size"); + std::memcpy(&f, &value, sizeof(uint32_t)); + + uint16_t sign = ((f >> 16) & 0x8000); + int16_t exponent = ((f >> 23) & 0xff) - 127 + 15; + uint16_t mantissa = ((f >> 13) & 0x3ff); + + if (exponent <= 0) { + if (exponent < -10) { + return sign; + } + mantissa = (mantissa | 0x400) >> (1 - exponent); + return sign | mantissa; + } + + else if (exponent == 0xff - (127 - 15)) { + if (mantissa) { + return sign | 0x7fff; + } else { + return sign | 0x7c00; + } + } + + else if (exponent > 30) { + return sign | 0x7c00; + } + + return sign | (exponent << 10) | mantissa; + } + + }; /* sf namespace */ +}; /* triton namespace */ diff --git a/src/testers/aarch64/unicorn_test_aarch64.py b/src/testers/aarch64/unicorn_test_aarch64.py index ed4c67307..f905ad261 100644 --- a/src/testers/aarch64/unicorn_test_aarch64.py +++ b/src/testers/aarch64/unicorn_test_aarch64.py @@ -2159,6 +2159,10 @@ #(b"\x00\x00\xaf\x9e", "fmov v0.D[1], x0"), # working on capstone next branch (b"\x40\x03\x67\x9e", "fmov d0, x26"), (b"\x02\x00\x66\x9e", "fmov x2, d0"), + (b"\x00\x10\x20\x1e", "fmov s0, #2.0"), + (b"\x03\x10\x2e\x1e", "fmov s3, #1.0"), + (b"\x01\x90\x61\x1e", "fmov d1, #3.5"), + #(b"\x04\x90\xe0\x1e", "fmov h4, #2.5"), # unicorn not implement f16 ops ] def emu_with_unicorn(opcode, istate):