diff --git a/remill/Arch/AArch64/Arch.cpp b/remill/Arch/AArch64/Arch.cpp index aaaec36d4..ed7079ee8 100644 --- a/remill/Arch/AArch64/Arch.cpp +++ b/remill/Arch/AArch64/Arch.cpp @@ -4656,6 +4656,42 @@ bool TryDecodeMVNI_ASIMDIMM_M_SM(const InstData &data, Instruction &inst) { return true; } +// USHLL{2} ., ., # +bool TryDecodeUSHLL_ASIMDSHF_L(const InstData &data, Instruction &inst) { + if (data.immh.uimm & 0b1000) { + return false; // if immh<3> == '1' then ReservedValue() + } + // USHLL has two arrangement specifiers, Ta and Tb, each with a complex encoding + // that is not handled by AddArrangementSpecifier(). + std::stringstream ss; + ss << inst.function << "_"; + uint64_t msb = 5; + const bool found = MostSignificantSetBit(data.immh.uimm, &msb); + switch (msb) { + case 0: + ss << "8H_" << (data.Q ? "16B" : "8B"); + break; + case 1: + ss << "4S_" << (data.Q ? "8H" : "4H"); + break; + case 2: + ss << "2D_" << (data.Q ? "4S" : "2S"); + break; + default: + LOG_IF(ERROR, !found) + << "Advanced SIMD modified immediates are not yet supported."; + // TODO: Add support for advanced SIMD modified immediates + return false; + } + inst.function = ss.str(); + AddRegOperand(inst, kActionWrite, kRegV, kUseAsValue, data.Rd); + AddRegOperand(inst, kActionRead, kRegV, kUseAsValue, data.Rn); + const uint8_t esize = static_cast(8ULL << msb); + const uint8_t shift = ((static_cast(data.immh.uimm) << 4) | data.immb.uimm) - esize; + AddImmOperand(inst, shift, kUnsigned, 8); + return true; +} + // USHR , , # bool TryDecodeUSHR_ASISDSHF_R(const InstData &data, Instruction &inst) { if ((data.immh.uimm & 8) == 0) { diff --git a/remill/Arch/AArch64/Decode.cpp b/remill/Arch/AArch64/Decode.cpp index 3914e2758..fd2e37b9d 100644 --- a/remill/Arch/AArch64/Decode.cpp +++ b/remill/Arch/AArch64/Decode.cpp @@ -39253,44 +39253,6 @@ bool TryDecodeUMLSL_ASIMDDIFF_L(const InstData &, Instruction &) { return false; } -// USHLL USHLL_asimdshf_L: -// 0 x Rd 0 -// 1 x Rd 1 -// 2 x Rd 2 -// 3 x Rd 3 -// 4 x Rd 4 -// 5 x Rn 0 -// 6 x Rn 1 -// 7 x Rn 2 -// 8 x Rn 3 -// 9 x Rn 4 -// 10 1 -// 11 0 opcode 0 -// 12 0 opcode 1 -// 13 1 opcode 2 -// 14 0 opcode 3 -// 15 1 opcode 4 -// 16 x immb 0 -// 17 x immb 1 -// 18 x immb 2 -// 19 x immh 0 -// 20 x immh 1 -// 21 x immh 2 -// 22 x immh 3 -// 23 0 -// 24 1 -// 25 1 -// 26 1 -// 27 1 -// 28 0 -// 29 1 U 0 -// 30 x Q 0 -// 31 0 -// USHLL{2} ., ., # -bool TryDecodeUSHLL_ASIMDSHF_L(const InstData &, Instruction &) { - return false; -} - // STLR STLR_SL64_ldstexcl: // 0 x Rt 0 // 1 x Rt 1 diff --git a/remill/Arch/AArch64/Semantics/SIMD.cpp b/remill/Arch/AArch64/Semantics/SIMD.cpp index cb4df63a7..f682c3a03 100644 --- a/remill/Arch/AArch64/Semantics/SIMD.cpp +++ b/remill/Arch/AArch64/Semantics/SIMD.cpp @@ -880,6 +880,42 @@ DEF_SEM(EXT, V128W dst, T src1, T src2, I32 src3) { DEF_ISEL(EXT_ASIMDEXT_ONLY_8B) = EXT; DEF_ISEL(EXT_ASIMDEXT_ONLY_16B) = EXT; +namespace { + +#define MAKE_SHL(size) \ + template \ + DEF_SEM(SHL_ ## size, V128W dst, S src1, I8 src2) { \ + auto shift = Read(src2); \ + if (shift == 0) { \ + return memory; \ + } \ + const uint_fast8_t elements = 64 / size ; \ + auto val = UReadV ## size (src1); \ + size_t index_min = Q ? 64 : 0; \ + size_t index_max = Q ? elements * 2 : elements; \ + _Pragma("unroll") \ + for (size_t i = index_min; i < index_max; ++i) { \ + uint64_t element = UExtractV ## size (val, i); \ + element <<= shift; \ + // TODO (@ESultanik): Need to populate the dst vector here \ + } \ + return memory; \ + } + +MAKE_SHL(8) +MAKE_SHL(16) +MAKE_SHL(32) + +#undef MAKE_SHL + +} // namespace + +DEF_ISEL(USHLL_ASIMDSHF_L_8H_8B) = SHL_32; +DEF_ISEL(USHLL_ASIMDSHF_L_8H_16B) = SHL_32; +DEF_ISEL(USHLL_ASIMDSHF_L_4S_4H) = SHL_16; +DEF_ISEL(USHLL_ASIMDSHF_L_4S_8H) = SHL_16; +DEF_ISEL(USHLL_ASIMDSHF_L_2D_2S) = SHL_8; +DEF_ISEL(USHLL_ASIMDSHF_L_2D_4S) = SHL_8; // TODO(pag): // FMINV_ASIMDALL_ONLY_H