Skip to content

Commit

Permalink
New x86 instructions (#457)
Browse files Browse the repository at this point in the history
* New x86 instructions

* Add some isels

* Fixes Issue #376

* Fixes Issue #433. Thanks @adahsuzixin for the semantics and tests

* Fixes Issue #374

* Minor fix to the semantics for VINSERTF128, it should only look at the low bit of imm8

* Minor fixes for sparc isel naming
  • Loading branch information
Peter Goodman authored Nov 5, 2020
1 parent b4834f7 commit 90f9ccd
Show file tree
Hide file tree
Showing 20 changed files with 690 additions and 119 deletions.
10 changes: 7 additions & 3 deletions include/remill/Arch/Runtime/Operators.h
Original file line number Diff line number Diff line change
Expand Up @@ -1457,11 +1457,15 @@ ALWAYS_INLINE static Memory *__remill_write_memory_128(Memory *mem, addr_t addr,
return mem;
}

// Issue #374: https://github.com/lifting-bits/remill/issues/374
//
// The builtins may have defined or undefined behavior given a zero, depending
// on the target arch.
#define MAKE_BUILTIN(name, size, input_size, builtin, disp) \
ALWAYS_INLINE static uint##size##_t name(uint##size##_t val) { \
return static_cast<uint##size##_t>( \
builtin(static_cast<uint##input_size##_t>(val))) - \
static_cast<uint##input_size##_t>(disp); \
const auto in_val = static_cast<uint##input_size##_t>(val); \
return in_val ? (static_cast<uint##size##_t>(builtin(in_val)) - \
static_cast<uint##input_size##_t>(disp)) : size; \
}

MAKE_BUILTIN(CountLeadingZeros, 8, 32, __builtin_clz, 24)
Expand Down
4 changes: 4 additions & 0 deletions include/remill/BC/Compat/CTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,14 @@

#pragma once

#if __has_include(<llvm-c/Types.h>)
#include <llvm-c/Types.h>

namespace llvm {
// TODO(pag): This is a rather ugly hack; had some issues with anvill not
// compiling on macOS due to these C types.
struct LLVMOpaqueNamedMDNode;
using LLVMNamedMDNodeRef = struct LLVMOpaqueNamedMDNode *;
} // namespace llvm

#endif
20 changes: 10 additions & 10 deletions lib/Arch/SPARC32/Extract.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1132,11 +1132,11 @@ DEFINE_FUNCTION(FMOVQ, SZERO, QWORD, QWORD)
DEFINE_FUNCTION(FMULS, SWORD, SWORD, SWORD)
DEFINE_FUNCTION(FMULD, DWORD, DWORD, DWORD)
DEFINE_FUNCTION(FMULQ, QWORD, QWORD, QWORD)
DEFINE_FUNCTION(FsMULD, SWORD, SWORD, DWORD)
DEFINE_FUNCTION(FdMULQ, DWORD, DWORD, QWORD)
DEFINE_FUNCTION(FxTOs, SZERO, DWORD, SWORD)
DEFINE_FUNCTION(FxTOd, SZERO, DWORD, DWORD)
DEFINE_FUNCTION(FxTOq, SZERO, DWORD, QWORD)
DEFINE_FUNCTION(FSMULD, SWORD, SWORD, DWORD)
DEFINE_FUNCTION(FDMULQ, DWORD, DWORD, QWORD)
DEFINE_FUNCTION(FXTOS, SZERO, DWORD, SWORD)
DEFINE_FUNCTION(FXTOD, SZERO, DWORD, DWORD)
DEFINE_FUNCTION(FXTOQ, SZERO, DWORD, QWORD)
DEFINE_FUNCTION(FITOS, SZERO, SWORD, SWORD)
DEFINE_FUNCTION(FITOD, SZERO, SWORD, DWORD)
DEFINE_FUNCTION(FITOQ, SZERO, SWORD, QWORD)
Expand Down Expand Up @@ -1270,12 +1270,12 @@ static bool (*const kop10_op352Level[1u << 8])(Instruction &, uint32_t) = {
[0b01100110] = nullptr,
[0b01100111] = nullptr,
[0b01101000] = nullptr,
[0b01101001] = TryDecodeFsMULD,
[0b01101001] = TryDecodeFSMULD,
[0b01101010] = nullptr,
[0b01101011] = nullptr,
[0b01101100] = nullptr,
[0b01101101] = nullptr,
[0b01101110] = TryDecodeFdMULQ,
[0b01101110] = TryDecodeFDMULQ,
[0b01101111] = nullptr,
[0b01110000] = nullptr,
[0b01110001] = nullptr,
Expand All @@ -1297,15 +1297,15 @@ static bool (*const kop10_op352Level[1u << 8])(Instruction &, uint32_t) = {
[0b10000001] = TryDecodeFSTOX,
[0b10000010] = TryDecodeFDTOX,
[0b10000011] = TryDecodeFQTOX,
[0b10000100] = TryDecodeFxTOs,
[0b10000100] = TryDecodeFXTOS,
[0b10000101] = nullptr,
[0b10000110] = nullptr,
[0b10000111] = nullptr,
[0b10001000] = TryDecodeFxTOd,
[0b10001000] = TryDecodeFXTOD,
[0b10001001] = nullptr,
[0b10001010] = nullptr,
[0b10001011] = nullptr,
[0b10001100] = TryDecodeFxTOq,
[0b10001100] = TryDecodeFXTOQ,
[0b10001101] = nullptr,
[0b10001110] = nullptr,
[0b10001111] = nullptr,
Expand Down
2 changes: 1 addition & 1 deletion lib/Arch/SPARC32/Semantics/FOP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ DEF_ISEL(FDIVD) = FDIVD;
DEF_ISEL(FDIVQ) = FDIVD;

DEF_ISEL(FSMULD) = FsMULD;
DEF_ISEL(FDMULQ) = FsMULD;
DEF_ISEL(FDMULQ) = FdMULQ;

namespace {

Expand Down
20 changes: 10 additions & 10 deletions lib/Arch/SPARC64/Extract.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1460,11 +1460,11 @@ DEFINE_FUNCTION(FMOVQ, SZERO, QWORD, QWORD)
DEFINE_FUNCTION(FMULS, SWORD, SWORD, SWORD)
DEFINE_FUNCTION(FMULD, DWORD, DWORD, DWORD)
DEFINE_FUNCTION(FMULQ, QWORD, QWORD, QWORD)
DEFINE_FUNCTION(FsMULD, SWORD, SWORD, DWORD)
DEFINE_FUNCTION(FdMULQ, DWORD, DWORD, QWORD)
DEFINE_FUNCTION(FxTOs, SZERO, DWORD, SWORD)
DEFINE_FUNCTION(FxTOd, SZERO, DWORD, DWORD)
DEFINE_FUNCTION(FxTOq, SZERO, DWORD, QWORD)
DEFINE_FUNCTION(FSMULD, SWORD, SWORD, DWORD)
DEFINE_FUNCTION(FDMULQ, DWORD, DWORD, QWORD)
DEFINE_FUNCTION(FXTOS, SZERO, DWORD, SWORD)
DEFINE_FUNCTION(FXTOD, SZERO, DWORD, DWORD)
DEFINE_FUNCTION(FXTOQ, SZERO, DWORD, QWORD)
DEFINE_FUNCTION(FITOS, SZERO, SWORD, SWORD)
DEFINE_FUNCTION(FITOD, SZERO, SWORD, DWORD)
DEFINE_FUNCTION(FITOQ, SZERO, SWORD, QWORD)
Expand Down Expand Up @@ -1596,12 +1596,12 @@ static bool (*const kop10_op352Level[1u << 8])(Instruction &, uint32_t) = {
[0b01100110] = nullptr,
[0b01100111] = nullptr,
[0b01101000] = nullptr,
[0b01101001] = TryDecodeFsMULD,
[0b01101001] = TryDecodeFSMULD,
[0b01101010] = nullptr,
[0b01101011] = nullptr,
[0b01101100] = nullptr,
[0b01101101] = nullptr,
[0b01101110] = TryDecodeFdMULQ,
[0b01101110] = TryDecodeFDMULQ,
[0b01101111] = nullptr,
[0b01110000] = nullptr,
[0b01110001] = nullptr,
Expand All @@ -1623,15 +1623,15 @@ static bool (*const kop10_op352Level[1u << 8])(Instruction &, uint32_t) = {
[0b10000001] = TryDecodeFSTOX,
[0b10000010] = TryDecodeFDTOX,
[0b10000011] = TryDecodeFQTOX,
[0b10000100] = TryDecodeFxTOs,
[0b10000100] = TryDecodeFXTOS,
[0b10000101] = nullptr,
[0b10000110] = nullptr,
[0b10000111] = nullptr,
[0b10001000] = TryDecodeFxTOd,
[0b10001000] = TryDecodeFXTOD,
[0b10001001] = nullptr,
[0b10001010] = nullptr,
[0b10001011] = nullptr,
[0b10001100] = TryDecodeFxTOq,
[0b10001100] = TryDecodeFXTOQ,
[0b10001101] = nullptr,
[0b10001110] = nullptr,
[0b10001111] = nullptr,
Expand Down
8 changes: 4 additions & 4 deletions lib/Arch/SPARC64/Semantics/FOP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ DEF_ISEL(FDIVD) = FDIVD;
DEF_ISEL(FMULS) = FMULS;
DEF_ISEL(FMULD) = FMULD;

DEF_ISEL(FsMULD) = FsMULD;
DEF_ISEL(FSMULD) = FsMULD;

namespace {

Expand Down Expand Up @@ -447,9 +447,9 @@ DEF_ISEL(FDTOS) = FDTOS;
DEF_ISEL(FITOS) = FITOS;
DEF_ISEL(FITOD) = FITOD;

DEF_ISEL(FxTOs) = FXTOS;
DEF_ISEL(FxTOd) = FXTOD;
DEF_ISEL(FxTOq) = FXTOQ;
DEF_ISEL(FXTOS) = FXTOS;
DEF_ISEL(FXTOD) = FXTOD;
DEF_ISEL(FXTOQ) = FXTOQ;

DEF_ISEL(FSQRTS) = FSQRTS;
DEF_ISEL(FSQRTD) = FSQRTD;
Expand Down
29 changes: 29 additions & 0 deletions lib/Arch/X86/Runtime/Instructions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,35 @@ DEF_HELPER(PopFromStack)->T {
Write(REG_XSP, new_xsp);
return val;
}

DEF_HELPER(SquareRoot32, float32_t src_float) -> float32_t {
auto square_root = src_float;

// Special cases for invalid square root operations. See Intel manual, Table E-10.
if (IsNaN(src_float)) {
// If src is SNaN, return the SNaN converted to a QNaN:
if (IsSignalingNaN(src_float)) {
nan32_t temp_nan = {src_float};
temp_nan.is_quiet_nan = 1; // equivalent to a bitwise OR with 0x00400000
square_root = temp_nan.f;

// Else, src is a QNaN. Pass it directly to the result:
} else {
square_root = src_float;
}
} else { // a number, that is, not a NaN
// A negative operand (except -0.0) results in the QNaN indefinite value.
if (IsNegative(src_float) && src_float != -0.0) {
uint32_t indef_qnan = 0xFFC00000U;
square_root = reinterpret_cast<float32_t &>(indef_qnan);
} else {
square_root = std::sqrt(src_float);
}
}

return square_root;
}

} // namespace

// clang-format off
Expand Down
28 changes: 25 additions & 3 deletions lib/Arch/X86/Semantics/AVX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@ DEF_SEM(DoVZEROUPPER) {
}
return memory;
}
} // namespace

namespace {

template <typename D, typename S1, size_t KL, size_t VL>
DEF_SEM(VPBROADCASTB, D dst, S1 src1) {
Expand All @@ -45,8 +42,33 @@ DEF_SEM(VPBROADCASTB, D dst, S1 src1) {
return memory;
}

template<typename S2>
DEF_SEM(VINSERTF128, VV256W dst, V256 src1, S2 src2, I8 src3) {
auto dst_vec = UReadV128(src1);
auto src2_vec = UReadV128(src2);
auto src3_i8 = Read(src3);
auto i = static_cast<unsigned>(src3_i8 & 1u);
dst_vec = UInsertV128(dst_vec, i, UExtractV128(src2_vec, 0));
UWriteV128(dst, dst_vec);
return memory;
}

//template<typename S2>
//DEF_SEM(VINSERTF128, VV512W dst, V512 src1, S2 src2, I8 src3) {
// auto dst_vec = UReadV128(src1);
// auto src2_vec = UReadV128(src2);
// auto src3_i8 = Read(src3);
// std::size_t i = static_cast<unsigned>(src3_i8 & 3u);
// dst_vec = UInsertV128(dst_vec, i, UExtractV128(src2_vec, 0));
// UWriteV128(dst, dst_vec);
// return memory;
//}

} // namespace

DEF_ISEL(VINSERTF128_YMMqq_YMMqq_MEMdq_IMMb) = VINSERTF128<MV128>;
DEF_ISEL(VINSERTF128_YMMqq_YMMqq_XMMdq_IMMb) = VINSERTF128<V128>;

DEF_ISEL(VZEROUPPER) = DoVZEROUPPER;
DEF_ISEL(VPBROADCASTB_YMMqq_XMMb) = VPBROADCASTB<VV256W, V128, 32, 256>;

Expand Down
59 changes: 42 additions & 17 deletions lib/Arch/X86/Semantics/DATAXFER.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,21 +93,23 @@ DEF_SEM(MOVLPS, D dst, S src) {
return memory;
}

template <typename D, typename S>
DEF_SEM(MOVLHPS, D dst, S src) {

/* DEST[63:0] (Unmodified) */
/* DEST[127:64] ← SRC[63:0] */
/* DEST[VLMAX-1:128] (Unmodified) */

float64v2_t temp_vec = {};
temp_vec = FInsertV64(temp_vec, 0, FExtractV64(FReadV64(dst), 0));
temp_vec = FInsertV64(temp_vec, 1, FExtractV64(FReadV64(src), 0));

FWriteV64(dst, temp_vec);
DEF_SEM(MOVLHPS, V128W dst, V128 src) {
auto res = FReadV32(dst);
auto src1 = FReadV32(src);
res = FInsertV32(res, 2, FExtractV32(src1, 0));
res = FInsertV32(res, 3, FExtractV32(src1, 1));
FWriteV32(dst, res);
return memory;
}

DEF_SEM(MOVHLPS, V128W dst, V128 src) {
auto res = FReadV32(dst);
auto src1 = FReadV32(src);
res = FInsertV32(res, 0, FExtractV32(src1, 2));
res = FInsertV32(res, 1, FExtractV32(src1, 3));
FWriteV32(dst, res);
return memory;
}

template <typename D, typename S>
DEF_SEM(MOVLPD, D dst, S src) {
Expand Down Expand Up @@ -136,14 +138,32 @@ DEF_SEM(VMOVLHPS, VV128W dst, V128 src1, V128 src2) {
/* DEST[127:64] ← SRC2[63:0] */
/* DEST[VLMAX-1:128] ← 0 */

float64v2_t temp_vec = {};
temp_vec = FInsertV64(temp_vec, 0, FExtractV64(FReadV64(src1), 0));
temp_vec = FInsertV64(temp_vec, 1, FExtractV64(FReadV64(src2), 0));
auto src1_vec = FReadV32(src1);
auto src2_vec = FReadV32(src2);

FWriteV64(dst, temp_vec);
float32v4_t temp_vec = {};
temp_vec = FInsertV32(temp_vec, 0, FExtractV32(src1_vec, 0));
temp_vec = FInsertV32(temp_vec, 1, FExtractV32(src1_vec, 1));
temp_vec = FInsertV32(temp_vec, 2, FExtractV32(src2_vec, 0));
temp_vec = FInsertV32(temp_vec, 3, FExtractV32(src2_vec, 1));

FWriteV32(dst, temp_vec);
return memory;
}

DEF_SEM(VMOVHLPS, VV128W dst, V128 src1, V128 src2) {
auto src1_vec = FReadV32(src1);
auto src2_vec = FReadV32(src2);

float32v4_t temp_vec = {};
temp_vec = FInsertV32(temp_vec, 0, FExtractV32(src2_vec, 2));
temp_vec = FInsertV32(temp_vec, 1, FExtractV32(src2_vec, 3));
temp_vec = FInsertV32(temp_vec, 2, FExtractV32(src1_vec, 2));
temp_vec = FInsertV32(temp_vec, 3, FExtractV32(src1_vec, 3));

FWriteV32(dst, temp_vec);
return memory;
}

#endif // HAS_FEATURE_AVX

Expand Down Expand Up @@ -447,8 +467,13 @@ DEF_ISEL(MOVLPS_XMMq_MEMq) = MOVLPS<V128W, MV64>;
IF_AVX(DEF_ISEL(VMOVLPS_MEMq_XMMq) = MOVLPS<MV64W, VV128>;)
IF_AVX(DEF_ISEL(VMOVLPS_XMMdq_XMMdq_MEMq) = VMOVLPS;)

DEF_ISEL(MOVLHPS_XMMq_XMMq) = MOVLHPS<V128W, V128>;
DEF_ISEL(MOVHLPS_XMMq_XMMq) = MOVHLPS;
IF_AVX(DEF_ISEL(VMOVHLPS_XMMdq_XMMq_XMMq) = VMOVHLPS;)
IF_AVX(DEF_ISEL(VMOVHLPS_XMMdq_XMMdq_XMMdq) = VMOVHLPS;)

DEF_ISEL(MOVLHPS_XMMq_XMMq) = MOVLHPS;
IF_AVX(DEF_ISEL(VMOVLHPS_XMMdq_XMMq_XMMq) = VMOVLHPS;)
IF_AVX(DEF_ISEL(VMOVLHPS_XMMdq_XMMdq_XMMdq) = VMOVLHPS;)

#if HAS_FEATURE_AVX
# if HAS_FEATURE_AVX512
Expand Down
7 changes: 6 additions & 1 deletion lib/Arch/X86/Semantics/LOGICAL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -232,8 +232,8 @@ IF_AVX(DEF_ISEL(VPXOR_YMMqq_YMMqq_YMMqq) = PXOR<VV256W, VV256, VV256>;)

DEF_ISEL(XORPD_XMMpd_MEMpd) = PXOR_64<V128W, V128, MV128>;
DEF_ISEL(XORPD_XMMpd_XMMpd) = PXOR_64<V128W, V128, V128>;
DEF_ISEL(XORPD_XMMxuq_XMMxuq) = PXOR_64<V128W, V128, V128>;
DEF_ISEL(XORPD_XMMxuq_MEMxuq) = PXOR_64<V128W, V128, MV128>;
DEF_ISEL(XORPD_XMMxuq_XMMxuq) = PXOR_64<V128W, V128, V128>;

DEF_ISEL(XORPS_XMMps_MEMps) = PXOR<V128W, V128, MV128>;
DEF_ISEL(XORPS_XMMps_XMMps) = PXOR<V128W, V128, V128>;
Expand All @@ -259,6 +259,8 @@ IF_AVX(DEF_ISEL(VPAND_YMMqq_YMMqq_YMMqq) = PAND<VV256W, VV256, VV256>;)

DEF_ISEL(ANDPD_XMMpd_MEMpd) = PAND_64<V128W, V128, MV128>;
DEF_ISEL(ANDPD_XMMpd_XMMpd) = PAND_64<V128W, V128, V128>;

DEF_ISEL(ANDPD_XMMxuq_MEMxuq) = PAND_64<V128W, V128, MV128>;
DEF_ISEL(ANDPD_XMMxuq_XMMxuq) = PAND_64<V128W, V128, V128>;

DEF_ISEL(ANDPS_XMMps_MEMps) = PAND<V128W, V128, MV128>;
Expand All @@ -285,6 +287,7 @@ IF_AVX(DEF_ISEL(VPANDN_YMMqq_YMMqq_YMMqq) = PANDN<VV256W, VV256, VV256>;)

DEF_ISEL(ANDNPD_XMMpd_MEMpd) = PANDN_64<V128W, V128, MV128>;
DEF_ISEL(ANDNPD_XMMpd_XMMpd) = PANDN_64<V128W, V128, V128>;
DEF_ISEL(ANDNPD_XMMxuq_MEMxuq) = PANDN_64<V128W, V128, MV128>;
DEF_ISEL(ANDNPD_XMMxuq_XMMxuq) = PANDN_64<V128W, V128, V128>;

DEF_ISEL(ANDNPS_XMMps_MEMps) = PANDN<V128W, V128, MV128>;
Expand All @@ -311,10 +314,12 @@ IF_AVX(DEF_ISEL(VPOR_YMMqq_YMMqq_YMMqq) = POR<VV256W, VV256, VV256>;)

DEF_ISEL(ORPD_XMMpd_MEMpd) = POR_64<V128W, V128, MV128>;
DEF_ISEL(ORPD_XMMpd_XMMpd) = POR_64<V128W, V128, V128>;
DEF_ISEL(ORPD_XMMxuq_MEMxuq) = POR_64<V128W, V128, MV128>;
DEF_ISEL(ORPD_XMMxuq_XMMxuq) = POR_64<V128W, V128, V128>;

DEF_ISEL(ORPS_XMMps_MEMps) = POR<V128W, V128, MV128>;
DEF_ISEL(ORPS_XMMps_XMMps) = POR<V128W, V128, V128>;
DEF_ISEL(ORPS_XMMxud_MEMxud) = POR<V128W, V128, MV128>;
DEF_ISEL(ORPS_XMMxud_XMMxud) = POR<V128W, V128, V128>;
IF_AVX(DEF_ISEL(VORPD_XMMdq_XMMdq_MEMdq) = POR_64<VV128W, VV128, MV128>;)
IF_AVX(DEF_ISEL(VORPD_XMMdq_XMMdq_XMMdq) = POR_64<VV128W, VV128, VV128>;)
Expand Down
Loading

0 comments on commit 90f9ccd

Please # to comment.