Skip to content

Commit

Permalink
Merge pull request #5 from yomaytk/linpack-test
Browse files Browse the repository at this point in the history
support of `examples/linpack` (only recompilation of aarch64)
  • Loading branch information
yomaytk authored Jan 22, 2024
2 parents 2b092b0 + c6daeab commit 53ce2e7
Show file tree
Hide file tree
Showing 22 changed files with 561 additions and 508 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -108,4 +108,5 @@ obj-intel64/*
#VERSION files from CI
VERSION

examples/w2c
examples/w2c
examples/tests
39 changes: 27 additions & 12 deletions backend/remill/include/remill/Arch/Runtime/Operators.h
Original file line number Diff line number Diff line change
Expand Up @@ -229,12 +229,13 @@ MAKE_MWRITE(80, 80, float, float, f80)
#define MAKE_READRV(prefix, size, accessor, base_type) \
template <typename T> \
ALWAYS_INLINE static auto _##prefix##ReadV##size(Memory *, RVnW<T> vec) \
->decltype(T().accessor) { \
-> decltype(T().accessor) { \
return reinterpret_cast<T *>(vec.val_ref)->accessor; \
} \
\
template <typename T> \
ALWAYS_INLINE static auto _##prefix##ReadV##size(Memory *, RVn<T> vec)->decltype(T().accessor) { \
ALWAYS_INLINE static auto _##prefix##ReadV##size(Memory *, RVn<T> vec) \
-> decltype(T().accessor) { \
return reinterpret_cast<const T *>(&vec.val)->accessor; \
}

Expand All @@ -256,12 +257,14 @@ MAKE_READRV(F, 80, tdoubles, float80_t)

#define MAKE_READV(prefix, size, accessor) \
template <typename T> \
ALWAYS_INLINE static auto _##prefix##ReadV##size(Memory *, VnW<T> vec)->decltype(T().accessor) { \
ALWAYS_INLINE static auto _##prefix##ReadV##size(Memory *, VnW<T> vec) \
-> decltype(T().accessor) { \
return reinterpret_cast<T *>(vec.val_ref)->accessor; \
} \
\
template <typename T> \
ALWAYS_INLINE static auto _##prefix##ReadV##size(Memory *, Vn<T> vec)->decltype(T().accessor) { \
ALWAYS_INLINE static auto _##prefix##ReadV##size(Memory *, Vn<T> vec) \
-> decltype(T().accessor) { \
return reinterpret_cast<const T *>(vec.val)->accessor; \
}

Expand Down Expand Up @@ -289,11 +292,13 @@ MAKE_READV(F, 80, tdouble)

#undef MAKE_READV

// MAKE_MREADV(U, 16, words, 16)
// MAKE_MREADV(U, 16, words, 16) \
// e.g. uint16v*_t _UReadV16(memory, memV), float32v*_t _FReadV32(memory, memV), ...
// res_vec = memV
#define MAKE_MREADV(prefix, size, vec_accessor, mem_accessor) \
template <typename T> \
ALWAYS_INLINE static auto _##prefix##ReadV##size(Memory *memory, MVn<T> mem) \
->decltype(T().vec_accessor) { \
-> decltype(T().vec_accessor) { \
decltype(T().vec_accessor) vec = {}; \
const addr_t el_size = sizeof(vec.elems[0]); \
_Pragma("unroll") for (addr_t i = 0; i < NumVectorElems(vec); ++i) { \
Expand All @@ -304,7 +309,7 @@ MAKE_READV(F, 80, tdouble)
\
template <typename T> \
ALWAYS_INLINE static auto _##prefix##ReadV##size(Memory *memory, MVnW<T> mem) \
->decltype(T().vec_accessor) { \
-> decltype(T().vec_accessor) { \
decltype(T().vec_accessor) vec = {}; \
const addr_t el_size = sizeof(vec.elems[0]); \
_Pragma("unroll") for (addr_t i = 0; i < NumVectorElems(vec); ++i) { \
Expand Down Expand Up @@ -338,11 +343,15 @@ MAKE_MREADV(F, 80, tdoubles, f80)
#undef MAKE_MREADV

// MAKE_WRITEV(U, 16, words, VnW, uint16_t)
// e.g. _UWriteV16(memory, vec, value), _FWriteV32(memory, vec, value), ...
// -> vec = {value, 0, 0, ...}
// e.g. _UWriteV16(memory, vec, vec2), _FWriteV32(memory, vec, vec2), ...
// -> vec = {{vec2}, 0, 0, ...}
#define MAKE_WRITEV(prefix, size, accessor, kind, base_type) \
template <typename T> \
ALWAYS_INLINE static Memory /* _UWriteV16 */ *_##prefix##WriteV##size( \
Memory *memory, kind<T> vec, base_type val) { \
auto &sub_vec = reinterpret_cast<T *>(vec.val_ref)->accessor; \
auto &sub_vec = reinterpret_cast<T *>(vec.val_ref) -> accessor; \
sub_vec.elems[0] = val; \
_Pragma("unroll") for (addr_t i = 1; i < NumVectorElems(sub_vec); ++i) { \
sub_vec.elems[i] = 0; \
Expand All @@ -358,7 +367,7 @@ MAKE_MREADV(F, 80, tdoubles, f80)
typedef decltype(V().elems[0]) VT; \
static_assert(std::is_same<BT, VT>::value, \
"Incompatible types to a write to a vector register"); \
auto &sub_vec = reinterpret_cast<T *>(vec.val_ref)->accessor; \
auto &sub_vec = reinterpret_cast<T *>(vec.val_ref) -> accessor; \
_Pragma("unroll") for (addr_t i = 0; i < NumVectorElems(val); ++i) { \
sub_vec.elems[i] = val.elems[i]; \
} \
Expand Down Expand Up @@ -406,7 +415,11 @@ MAKE_WRITEV(F, 80, tdoubles, RVnW, float80_t)

#undef MAKE_WRITEV

// MAKE_MWRITEV(U, 128, dqwords, 128, uint128_t)
// MAKE_MWRITEV(U, 32, dqwords, 32, uint32_t)
// e.g. _UWriteV32(memory, memV, value), _FWriteV64(memory, memV, value)
// memV = {val, 0, 0, ...}
// e.g. _UWriteV32(memory, memV, srcv), _FWriteV64(memory, memV, srcv)
// memV = {{srcv}, ...}
#define MAKE_MWRITEV(prefix, size, vec_accessor, mem_accessor, base_type) \
template <typename T> \
ALWAYS_INLINE static Memory *_##prefix##WriteV##size(Memory *memory, MVnW<T> mem, \
Expand All @@ -421,7 +434,7 @@ MAKE_WRITEV(F, 80, tdoubles, RVnW, float80_t)
return memory; \
} \
\
template <typename T, typename V> \
template <typename T, typename V> /* _UWriteV32(memory, dstv, srcv) */ \
ALWAYS_INLINE static Memory *_##prefix##WriteV##size(Memory *memory, MVnW<T> mem, \
const V &val) { \
static_assert(sizeof(T) == sizeof(V), "Invalid value size for MVnW."); \
Expand Down Expand Up @@ -1138,6 +1151,7 @@ ALWAYS_INLINE static bool BNot(bool a) {
return ret; \
}

// e.g. UAddV32(UReadV(src1), UReadV32(src2))
#define MAKE_BROADCASTS(op, make_int_broadcast, make_float_broadcast) \
make_int_broadcast(U##op, 8, bytes) make_int_broadcast(U##op, 16, words) \
make_int_broadcast(U##op, 32, dwords) make_int_broadcast(U##op, 64, qwords) \
Expand Down Expand Up @@ -1165,7 +1179,7 @@ MAKE_BROADCASTS(Not, MAKE_UN_BROADCAST, MAKE_NOP)
// Binary broadcast operator.
#define MAKE_ACCUMULATE(op, size, accessor) \
template <typename T> \
ALWAYS_INLINE static auto Accumulate##op##V##size(T R)->decltype(R.elems[0] | R.elems[1]) { \
ALWAYS_INLINE static auto Accumulate##op##V##size(T R) -> decltype(R.elems[0] | R.elems[1]) { \
auto L = R.elems[0]; \
_Pragma("unroll") for (auto i = 1UL; i < NumVectorElems(R); ++i) { \
L = op(L, R.elems[i]); \
Expand All @@ -1191,6 +1205,7 @@ ALWAYS_INLINE static auto NthVectorElem(const T &vec, size_t n) ->
}

// Access the Nth element of an aggregate vector.
// MAKE_EXTRACTV(32, float32_t, floats, Identity, F) => FExtractV32
#define MAKE_EXTRACTV(size, base_type, accessor, out, prefix) \
template <typename T> \
ALWAYS_INLINE static base_type prefix##ExtractV##size(const T &vec, size_t n) { \
Expand Down
1 change: 1 addition & 0 deletions backend/remill/include/remill/Arch/Runtime/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ union vec512_t;

// MAKE_VECTOR(uint128_t, uint128, 4, 512, 64)
// MAKE_VECTOR(uint16_t, uint16, 8, 128, 16)
// MAKE_VECTOR(uint64_t, uint64, 2, 128, 16)
#define MAKE_VECTOR(base_type, prefix, nelems, vec_size_bits, width_bytes) \
struct prefix##v##nelems##_t final { \
base_type elems[nelems]; \
Expand Down
139 changes: 139 additions & 0 deletions backend/remill/lib/Arch/AArch64/Arch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1263,6 +1263,22 @@ bool TryDecodeSTR_64_LDST_IMMPOST(const InstData &data, Instruction &inst) {
return true;
}

// STR <St>, [<Xn|SP>], #<simm>
bool TryDecodeSTR_S_LDST_IMMPOST(const InstData &data, Instruction &inst) {
AddRegOperand(inst, kActionRead, kRegS, kUseAsValue, data.Rt);
uint64_t offset = static_cast<uint64_t>(data.imm9.simm9);
AddPostIndexMemOp(inst, kActionWrite, 32, data.Rn, offset);
return true;
}

// STR <Dt>, [<Xn|SP>], #<simm>
bool TryDecodeSTR_D_LDST_IMMPOST(const InstData &data, Instruction &inst) {
AddRegOperand(inst, kActionRead, kRegD, kUseAsValue, data.Rt);
uint64_t offset = static_cast<uint64_t>(data.imm9.simm9);
AddPostIndexMemOp(inst, kActionWrite, 64, data.Rn, offset);
return true;
}

// STR <Qt>, [<Xn|SP>], #<simm>
bool TryDecodeSTR_Q_LDST_IMMPOST(const InstData &data, Instruction &inst) {
AddRegOperand(inst, kActionRead, kRegQ, kUseAsValue, data.Rt);
Expand Down Expand Up @@ -3239,6 +3255,30 @@ bool TryDecodeFMADD_D_FLOATDP3(const InstData &data, Instruction &inst) {
return true;
}

// FMSUB <Sd>, <Sn>, <Sm>, <Sa>
bool TryDecodeFMSUB_S_FLOATDP3(const InstData &data, Instruction &inst) {
if (IsUnallocatedFloatEncoding(data)) {
return false;
}
AddRegOperand(inst, kActionWrite, kRegS, kUseAsValue, data.Rd);
AddRegOperand(inst, kActionRead, kRegS, kUseAsValue, data.Rn);
AddRegOperand(inst, kActionRead, kRegS, kUseAsValue, data.Rm);
AddRegOperand(inst, kActionRead, kRegS, kUseAsValue, data.Ra);
return true;
}

// FMSUB <Dd>, <Dn>, <Dm>, <Da>
bool TryDecodeFMSUB_D_FLOATDP3(const InstData &data, Instruction &inst) {
if (IsUnallocatedFloatEncoding(data)) {
return false;
}
AddRegOperand(inst, kActionWrite, kRegD, kUseAsValue, data.Rd);
AddRegOperand(inst, kActionRead, kRegD, kUseAsValue, data.Rn);
AddRegOperand(inst, kActionRead, kRegD, kUseAsValue, data.Rm);
AddRegOperand(inst, kActionRead, kRegD, kUseAsValue, data.Ra);
return true;
}

// FCMPE <Sn>, <Sm>
bool TryDecodeFCMPE_S_FLOATCMP(const InstData &data, Instruction &inst) {
return TryDecodeFn_Fm(data, inst, kRegS);
Expand Down Expand Up @@ -3801,6 +3841,16 @@ bool TryDecodeCSEL_64_CONDSEL(const InstData &data, Instruction &inst) {
return DecodeConditionalRegSelect(data, inst, kRegX, 3);
}

// FCSEL <Sd>, <Sn>, <Sm>, <cond>
bool TryDecodeFCSEL_S_FLOATSEL(const InstData &data, Instruction &inst) {
return false;
}

// FCSEL <Dd>, <Dn>, <Dm>, <cond>
bool TryDecodeFCSEL_D_FLOATSEL(const InstData &data, Instruction &inst) {
return DecodeConditionalRegSelect(data, inst, kRegD, 3);
}

// CSINC <Wd>, <Wn>, <Wm>, <cond>
bool TryDecodeCSINC_32_CONDSEL(const InstData &data, Instruction &inst) {
return DecodeConditionalRegSelect(data, inst, kRegW, 3);
Expand Down Expand Up @@ -4032,6 +4082,25 @@ bool TryDecodeDUP_ASIMDINS_DR_R(const InstData &data, Instruction &inst) {
return true;
}

// DUP <Vd>.<T>, <Vn>.<Ts>[<index>]
bool TryDecodeDUP_ASIMDINS_DV_V(const InstData &data, Instruction &inst) {
uint64_t size = 4;
auto imm5 = data.imm5.uimm;
for (uint8_t i = 0; i < 4; i++) {
if ((imm5 >> i) & 1) {
size = i;
break;
}
}
if (4 == size)
std::__throw_runtime_error("[ERROR] invalid imm5 at TryDecodeDUP_ASIMDINS_DV_V\n");
AddArrangementSpecifier(inst, data.Q ? 128 : 64, 8UL << size);
AddRegOperand(inst, kActionWrite, data.Q ? kRegV : kRegD, kUseAsValue, data.Rd);
AddRegOperand(inst, kActionRead, kRegD, kUseAsValue, data.Rn);
AddImmOperand(inst, data.imm5.uimm >> (size + 1), kUnsigned, 32);
return true;
}

// ADD <Vd>.<T>, <Vn>.<T>, <Vm>.<T>
bool TryDecodeADD_ASIMDSAME_ONLY(const InstData &data, Instruction &inst) {
if (0x3 == data.size && !data.Q) {
Expand Down Expand Up @@ -4277,6 +4346,76 @@ bool TryDecodeSMAX_ASIMDSAME_ONLY(const InstData &data, Instruction &inst) {
return TryDecodeUMAXP_ASIMDSAME_ONLY(data, inst);
}

// FMLA <Vd>.<T>, <Vn>.<T>, <Vm>.<T>
bool TryDecodeFMLA_ASIMDSAME_ONLY(const InstData &data, Instruction &inst) {
uint64_t elem_size;
if (0b00001 /* half-precistion */ == data.opcode)
elem_size = 16;
else if (0b11001 /* (single | double)-precision */ == data.opcode)
elem_size = data.sz ? 64 : 32;
else
std::__throw_runtime_error(
"[ERROR] invalid opcode of InstData at 'TryDecodeFMLA_ASIMDSAME_ONLY'\n");
AddArrangementSpecifier(inst, data.Q ? 128 : 64, elem_size);
AddRegOperand(inst, kActionWrite, data.Q ? kRegV : kRegD, kUseAsValue, data.Rd);
AddRegOperand(inst, kActionRead, data.Q ? kRegV : kRegD, kUseAsValue, data.Rn);
AddRegOperand(inst, kActionRead, data.Q ? kRegV : kRegD, kUseAsValue, data.Rm);
return true;
}

// FADD <Vd>.<T>, <Vn>.<T>, <Vm>.<T>
bool TryDecodeFADD_ASIMDSAME_ONLY(const InstData &data, Instruction &inst) {
uint64_t elem_size;
if (0b00010 /* half-precision */ == data.opcode)
elem_size = 16;
else if (0b11010 /* (single | double)-precision */ == data.opcode)
elem_size = data.sz ? 64 : 32;
else
std::__throw_runtime_error(
"[ERROR] invaild opcode of InstData at TryDecodeFADD_ASIMDSAME_ONLY\n");
AddArrangementSpecifier(inst, data.Q ? 128 : 64, elem_size);
AddRegOperand(inst, kActionWrite, data.Q ? kRegV : kRegD, kUseAsValue, data.Rd);
AddRegOperand(inst, kActionRead, data.Q ? kRegV : kRegD, kUseAsValue, data.Rn);
AddRegOperand(inst, kActionRead, data.Q ? kRegV : kRegD, kUseAsValue, data.Rm);
return true;
}

// FMUL <Vd>.<T>, <Vn>.<T>, <Vm>.<T>
bool TryDecodeFMUL_ASIMDSAME_ONLY(const InstData &data, Instruction &inst) {
uint64_t elem_size;
if (0b00011 /* half-precision */ == data.opcode)
elem_size = 16;
else if (0b11011 /* (single | double)-precision */ == data.opcode)
elem_size = data.sz ? 64 : 32;
else
std::__throw_runtime_error(
"[ERROR] invalid opcode of InstData at 'TryDecodeFMUL_ASIMDSAME_ONLY'\n");
AddArrangementSpecifier(inst, data.Q ? 128 : 64, elem_size);
AddRegOperand(inst, kActionWrite, data.Q ? kRegV : kRegD, kUseAsValue, data.Rd);
AddRegOperand(inst, kActionRead, data.Q ? kRegV : kRegD, kUseAsValue, data.Rn);
AddRegOperand(inst, kActionRead, data.Q ? kRegV : kRegD, kUseAsValue, data.Rm);
return true;
}

// FMUL <Vd>.<T>, <Vn>.<T>, <Vm>.<Ts>[<index>]
bool TryDecodeFMUL_ASIMDELEM_R_SD(const InstData &data, Instruction &inst) {
int index;
uint64_t elem_size = data.sz ? 64 : 32;
if (0 == data.sz)
index = (data.H << 1) + data.L;
else if (1 == data.sz && 0 == data.L)
index = data.H;
else
std::__throw_runtime_error(
"[ERROR] invalid 'sz' or 'L' of InstData at TryDecodeFMUL_ASIMDELEM_R_SD\n");
AddArrangementSpecifier(inst, data.Q ? 128 : 64, elem_size);
AddRegOperand(inst, kActionWrite, data.Q ? kRegV : kRegD, kUseAsValue, data.Rd);
AddRegOperand(inst, kActionRead, data.Q ? kRegV : kRegD, kUseAsValue, data.Rn);
AddRegOperand(inst, kActionRead, data.Q ? kRegV : kRegD, kUseAsValue, data.Rm);
AddImmOperand(inst, index, kUnsigned, 32);
return true;
}

// UMOV <Wd>, <Vn>.<Ts>[<index>]
bool TryDecodeUMOV_ASIMDINS_W_W(const InstData &data, Instruction &inst) {
uint64_t size = 0;
Expand Down
Loading

0 comments on commit 53ce2e7

Please sign in to comment.