Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions arch/armv7/arch_armv7.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1601,6 +1601,10 @@ class Armv7Architecture: public ArmCommonArchitecture
return "__vrhadd";
case ARMV7_INTRIN_VRECPE:
return "__vrecpe";
case ARMV7_INTRIN_VABS:
return "__vabs";
case ARMV7_INTRIN_VCVT_FIXED:
return "__vcvt_fixed";
case ARMV7_INTRIN_VQSHL:
return "__vqshl";
case ARMV7_INTRIN_VQRSHL:
Expand Down Expand Up @@ -1866,6 +1870,8 @@ class Armv7Architecture: public ArmCommonArchitecture
ARMV7_INTRIN_VHADD,
ARMV7_INTRIN_VRHADD,
ARMV7_INTRIN_VRECPE,
ARMV7_INTRIN_VABS,
ARMV7_INTRIN_VCVT_FIXED,
ARMV7_INTRIN_VQSHL,
ARMV7_INTRIN_VQRSHL,
ARMV7_INTRIN_VQSHRN,
Expand Down Expand Up @@ -2196,11 +2202,20 @@ class Armv7Architecture: public ArmCommonArchitecture
NameAndType("source2", Type::IntegerType(8, false)),
};
case ARMV7_INTRIN_VRECPE:
case ARMV7_INTRIN_VABS:
return {
NameAndType("size", Type::IntegerType(1, false)),
NameAndType("is_float", Type::BoolType()),
NameAndType("source", Type::IntegerType(8, false)),
};
case ARMV7_INTRIN_VCVT_FIXED:
return {
NameAndType("size", Type::IntegerType(1, false)),
NameAndType("fractional_bits", Type::IntegerType(1, false)),
NameAndType("to_fixed", Type::BoolType()),
NameAndType("is_unsigned", Type::BoolType()),
NameAndType("source", Type::IntegerType(8, false)),
};
case ARMV7_INTRIN_VREV16:
case ARMV7_INTRIN_VREV32:
case ARMV7_INTRIN_VREV64:
Expand Down Expand Up @@ -2550,6 +2565,8 @@ class Armv7Architecture: public ArmCommonArchitecture
case ARMV7_INTRIN_VHADD:
case ARMV7_INTRIN_VRHADD:
case ARMV7_INTRIN_VRECPE:
case ARMV7_INTRIN_VABS:
case ARMV7_INTRIN_VCVT_FIXED:
case ARMV7_INTRIN_VQSHL:
case ARMV7_INTRIN_VQRSHL:
case ARMV7_INTRIN_VQSHRN:
Expand Down
154 changes: 102 additions & 52 deletions arch/armv7/il.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4542,64 +4542,70 @@ bool GetLowLevelILForArmInstruction(Architecture* arch, uint64_t addr, LowLevelI
if (op3.cls == IMM)
{
size_t destSize = get_register_size(op1.reg);
size_t fixedSize = GetDataTypeSize(instr.dataType);
if (!fixedSize)
fixedSize = destSize;
size_t sourceSize = GetDataTypeSize(instr.dataType2);
if (!sourceSize)
sourceSize = get_register_size(op2.reg);
auto source = [&]() {
ExprId value = il.Register(get_register_size(op2.reg), op2.reg);
if (sourceSize < get_register_size(op2.reg))
value = il.LowPart(sourceSize, value);
return value;
};
switch (instr.dataType)
size_t sourceRegisterSize = get_register_size(op2.reg);
bool destIsFloat = instr.dataType == DT_F32 || instr.dataType == DT_F64;
bool sourceIsFloat = instr.dataType2 == DT_F32 || instr.dataType2 == DT_F64;
bool toFixed = !destIsFloat && sourceIsFloat;
bool fromFixed = destIsFloat && !sourceIsFloat;
DataType fixedType = toFixed ? instr.dataType : instr.dataType2;
DataType floatType = toFixed ? instr.dataType2 : instr.dataType;
size_t fixedSize = GetDataTypeSize(fixedType);
size_t floatSize = GetDataTypeSize(floatType);
bool validFixedType = fixedType == DT_S16 || fixedType == DT_U16
|| fixedType == DT_S32 || fixedType == DT_U32;
bool isUnsigned = fixedType == DT_U16 || fixedType == DT_U32;

if ((!toFixed && !fromFixed) || !validFixedType || fixedSize == 0 || floatSize == 0
|| destSize == 0 || sourceRegisterSize == 0 || destSize != sourceRegisterSize)
{
case DT_S16:
case DT_S32:
ConditionExecute(il, instr.cond, il.SetRegister(destSize, op1.reg,
il.SignExtend(destSize,
il.FloatToInt(fixedSize,
il.RoundToInt(sourceSize,
il.FloatMult(sourceSize,
source(),
FixedPointScale(il, sourceSize, op3.imm)))))));
break;
case DT_U16:
case DT_U32:
ConditionExecute(il, instr.cond, il.SetRegister(destSize, op1.reg,
il.ZeroExtend(destSize,
il.FloatToInt(fixedSize,
il.RoundToInt(sourceSize,
il.FloatMult(sourceSize,
source(),
FixedPointScale(il, sourceSize, op3.imm)))))));
ConditionExecute(il, instr.cond, il.Unimplemented());
break;
case DT_F32:
case DT_F64:
switch (instr.dataType2)
}

if (destSize != floatSize)
{
if (floatSize != 4 || fixedSize != 4 || (destSize != 8 && destSize != 16))
{
case DT_S16:
case DT_S32:
ConditionExecute(il, instr.cond, il.SetRegister(destSize, op1.reg,
il.FloatDiv(destSize,
il.IntToFloat(destSize, il.SignExtend(destSize, source())),
FixedPointScale(il, destSize, op3.imm))));
break;
case DT_U16:
case DT_U32:
ConditionExecute(il, instr.cond, il.SetRegister(destSize, op1.reg,
il.FloatDiv(destSize,
il.IntToFloat(destSize, il.ZeroExtend(destSize, source())),
FixedPointScale(il, destSize, op3.imm))));
break;
default:
ConditionExecute(il, instr.cond, il.Unimplemented());
break;
}

ConditionExecute(il, instr.cond,
il.Intrinsic(
{ RegisterOrFlag::Register(op1.reg) },
ARMV7_INTRIN_VCVT_FIXED,
{
il.Const(1, floatSize * 8),
il.Const(1, op3.imm),
il.Const(1, toFixed ? 1 : 0),
il.Const(1, isUnsigned ? 1 : 0),
il.Register(sourceRegisterSize, op2.reg),
}));
break;
default:
break;
}

if (toFixed)
{
ExprId scaled = il.FloatMult(floatSize,
il.Register(sourceRegisterSize, op2.reg),
FixedPointScale(il, floatSize, op3.imm));
ExprId converted = il.FloatToInt(fixedSize, il.FloatTrunc(floatSize, scaled));
converted = isUnsigned
? il.ZeroExtend(destSize, converted)
: il.SignExtend(destSize, converted);
ConditionExecute(il, instr.cond, il.SetRegister(destSize, op1.reg, converted));
}
else
{
ExprId source = il.Register(sourceRegisterSize, op2.reg);
if (fixedSize < sourceRegisterSize)
source = il.LowPart(fixedSize, source);
ExprId converted = isUnsigned
? il.IntToFloat(floatSize, il.ZeroExtend(floatSize, source))
: il.IntToFloat(floatSize, il.SignExtend(floatSize, source));
ConditionExecute(il, instr.cond,
il.SetRegister(destSize, op1.reg,
il.FloatDiv(floatSize, converted, FixedPointScale(il, floatSize, op3.imm))));
}
break;
}
Expand Down Expand Up @@ -4651,6 +4657,12 @@ bool GetLowLevelILForArmInstruction(Architecture* arch, uint64_t addr, LowLevelI
il.ZeroExtend(get_register_size(op1.reg),
il.Register(get_register_size(op2.reg), op2.reg)))));
break;
case DT_F32:
case DT_F64:
ConditionExecute(il, instr.cond, il.SetRegister(get_register_size(op1.reg), op1.reg,
il.FloatConvert(get_register_size(op1.reg),
il.Register(get_register_size(op2.reg), op2.reg))));
break;
default:
break;
}
Expand All @@ -4659,6 +4671,44 @@ bool GetLowLevelILForArmInstruction(Architecture* arch, uint64_t addr, LowLevelI
break;
}
break;
case ARMV7_VABS:
if (op1.cls != REG || op2.cls != REG || op3.cls != NONE)
{
ConditionExecute(il, instr.cond, il.Unimplemented());
break;
}

{
size_t elementSize = GetDataTypeSize(instr.dataType);
size_t destSize = get_register_size(op1.reg);
size_t sourceSize = get_register_size(op2.reg);
bool isFloat = (instr.dataType == DT_F32) || (instr.dataType == DT_F64);
if (elementSize == 0 || destSize == 0 || sourceSize == 0 || destSize != sourceSize)
{
ConditionExecute(il, instr.cond, il.Unimplemented());
break;
}

if (isFloat && elementSize == destSize)
{
ConditionExecute(il, instr.cond,
il.SetRegister(destSize, op1.reg,
il.FloatAbs(destSize, il.Register(sourceSize, op2.reg))));
}
else
{
ConditionExecute(il, instr.cond,
il.Intrinsic(
{ RegisterOrFlag::Register(op1.reg) },
ARMV7_INTRIN_VABS,
{
il.Const(1, elementSize * 8),
il.Const(1, isFloat ? 1 : 0),
il.Register(sourceSize, op2.reg),
}));
}
}
break;
case ARMV7_VADD:
if (op1.cls != REG || op2.cls != REG || op3.cls != REG)
{
Expand Down
2 changes: 2 additions & 0 deletions arch/armv7/il.h
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,8 @@ enum Armv7Intrinsic : uint32_t
ARMV7_INTRIN_VSUB,
ARMV7_INTRIN_VRHADD,
ARMV7_INTRIN_VRECPE,
ARMV7_INTRIN_VABS,
ARMV7_INTRIN_VCVT_FIXED,
};

enum ArmFakeRegister: uint32_t
Expand Down
60 changes: 58 additions & 2 deletions arch/armv7/test_lift.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ def vector_unary_intrinsic_expected(dst, intrinsic, size, modifier, src):
src_size = 'o' if src.startswith('q') else 'q'
return f'LLIL_INTRINSIC([{dst}],__{intrinsic},[LLIL_CONST.b(0x{size:X}),LLIL_CONST.b(0x{modifier:X}),LLIL_REG.{src_size}({src})])'

def vector_fixed_convert_intrinsic_expected(dst, size, fractional_bits, to_fixed, unsigned, src):
src_size = 'o' if src.startswith('q') else 'q'
return (
f'LLIL_INTRINSIC([{dst}],__vcvt_fixed,[LLIL_CONST.b(0x{size:X}),'
f'LLIL_CONST.b(0x{fractional_bits:X}),LLIL_CONST.b(0x{to_fixed:X}),'
f'LLIL_CONST.b(0x{unsigned:X}),LLIL_REG.{src_size}({src})])'
)

def saturating_scalar_expected(dst, src1, src2, intrinsic):
return scalar_q_intrinsic_expected(dst, intrinsic, src1, src2)

Expand Down Expand Up @@ -652,6 +660,26 @@ def vmlal_expected(size, unsigned):
('A', b'\x44\xa4\xfb\xf3', vector_unary_intrinsic_expected('q13', 'vrecpe', 32, 0, 'q2')),
# vrecpe.u32 q13, q2
('T', b'\xfb\xff\x44\xa4', vector_unary_intrinsic_expected('q13', 'vrecpe', 32, 0, 'q2')),
# vabs.f32 s0, s1
('A', b'\xe0\x0a\xb0\xee', 'LLIL_SET_REG.d(s0,LLIL_FABS.d(LLIL_REG.d(s1)))'),
# vabs.f64 d1, d2
('A', b'\xc2\x1b\xb0\xee', 'LLIL_SET_REG.q(d1,LLIL_FABS.q(LLIL_REG.q(d2)))'),
# vabs.f32 d0, d1
('A', b'\x01\x07\xb9\xf3', vector_unary_intrinsic_expected('d0', 'vabs', 32, 1, 'd1')),
# vabs.f32 q1, q2
('A', b'\x44\x27\xb9\xf3', vector_unary_intrinsic_expected('q1', 'vabs', 32, 1, 'q2')),
# vabs.s16 d0, d1
('A', b'\x01\x03\xb5\xf3', vector_unary_intrinsic_expected('d0', 'vabs', 16, 0, 'd1')),
# vabs.f32 s0, s1
('T', b'\xb0\xee\xe0\x0a', 'LLIL_SET_REG.d(s0,LLIL_FABS.d(LLIL_REG.d(s1)))'),
# vabs.f64 d1, d2
('T', b'\xb0\xee\xc2\x1b', 'LLIL_SET_REG.q(d1,LLIL_FABS.q(LLIL_REG.q(d2)))'),
# vabs.f32 d0, d1
('T', b'\xb9\xff\x01\x07', vector_unary_intrinsic_expected('d0', 'vabs', 32, 1, 'd1')),
# vabs.f32 q1, q2
('T', b'\xb9\xff\x44\x27', vector_unary_intrinsic_expected('q1', 'vabs', 32, 1, 'q2')),
# vabs.s16 d0, d1
('T', b'\xb5\xff\x01\x03', vector_unary_intrinsic_expected('d0', 'vabs', 16, 0, 'd1')),
# vceq.s16 d16, d0, d13
('T', b'\x50\xff\x1d\x08', vector_intrinsic_expected('d16', 'vceq', 16, 0, 'd0', 'd13')),
# vcgt.s32 d0, d19, #0
Expand Down Expand Up @@ -692,10 +720,38 @@ def vmlal_expected(size, unsigned):
('T', b'\xba\xee\xef\x7a', 'LLIL_SET_REG.d(s14,LLIL_FDIV.d(LLIL_INT_TO_FLOAT.d(LLIL_SX.d(LLIL_REG.d(s14))),LLIL_FLOAT_CONST.d(2.0)))'),
# vcvt.f64.u32 d7, d7, #1
('T', b'\xbb\xee\xef\x7b', 'LLIL_SET_REG.q(d7,LLIL_FDIV.q(LLIL_INT_TO_FLOAT.q(LLIL_ZX.q(LLIL_LOW_PART.d(LLIL_REG.q(d7)))),LLIL_FLOAT_CONST.q(2.0)))'),
# vcvt.s16.f32 s0, s0, #8
('A', b'\x44\x0a\xbe\xee', 'LLIL_SET_REG.d(s0,LLIL_SX.d(LLIL_FLOAT_TO_INT.w(LLIL_FTRUNC.d(LLIL_FMUL.d(LLIL_REG.d(s0),LLIL_FLOAT_CONST.d(256.0))))))'),
# vcvt.f32.s16 s1, s1, #8
('A', b'\x44\x0a\xfa\xee', 'LLIL_SET_REG.d(s1,LLIL_FDIV.d(LLIL_INT_TO_FLOAT.d(LLIL_SX.d(LLIL_LOW_PART.w(LLIL_REG.d(s1)))),LLIL_FLOAT_CONST.d(256.0)))'),
# vcvt.u16.f64 d2, d2, #12
('T', b'\xbf\xee\x42\x2b', 'LLIL_SET_REG.q(d2,LLIL_ZX.q(LLIL_FLOAT_TO_INT.w(LLIL_FTRUNC.q(LLIL_FMUL.q(LLIL_REG.q(d2),LLIL_FLOAT_CONST.q(4096.0))))))'),
# vcvt.f64.u16 d3, d3, #12
('T', b'\xbb\xee\x42\x3b', 'LLIL_SET_REG.q(d3,LLIL_FDIV.q(LLIL_INT_TO_FLOAT.q(LLIL_ZX.q(LLIL_LOW_PART.w(LLIL_REG.q(d3)))),LLIL_FLOAT_CONST.q(4096.0)))'),
# vcvt.s32.f32 d0, d1, #16
('A', b'\x11\x0f\xb0\xf2', vector_fixed_convert_intrinsic_expected('d0', 32, 16, 1, 0, 'd1')),
# vcvt.u32.f32 q1, q2, #8
('A', b'\x54\x2f\xb8\xf3', vector_fixed_convert_intrinsic_expected('q1', 32, 8, 1, 1, 'q2')),
# vcvt.f32.s32 d2, d3, #16
('A', b'\x13\x2e\xb0\xf2', vector_fixed_convert_intrinsic_expected('d2', 32, 16, 0, 0, 'd3')),
# vcvt.f32.u32 q3, q4, #8
('A', b'\x58\x6e\xb8\xf3', vector_fixed_convert_intrinsic_expected('q3', 32, 8, 0, 1, 'q4')),
# vcvt.s32.f32 d0, d1, #16
('T', b'\xb0\xef\x11\x0f', vector_fixed_convert_intrinsic_expected('d0', 32, 16, 1, 0, 'd1')),
# vcvt.u32.f32 q1, q2, #8
('T', b'\xb8\xff\x54\x2f', vector_fixed_convert_intrinsic_expected('q1', 32, 8, 1, 1, 'q2')),
# vcvt.f32.s32 d2, d3, #16
('T', b'\xb0\xef\x13\x2e', vector_fixed_convert_intrinsic_expected('d2', 32, 16, 0, 0, 'd3')),
# vcvt.f32.u32 q3, q4, #8
('T', b'\xb8\xff\x58\x6e', vector_fixed_convert_intrinsic_expected('q3', 32, 8, 0, 1, 'q4')),
# vcvt.f64.f32 d3, s4
('T', b'\xb7\xee\xc2\x3a', 'LLIL_SET_REG.q(d3,LLIL_FLOAT_CONV.q(LLIL_REG.d(s4)))'),
# vcvt.f32.f64 s5, d4
('T', b'\xf7\xee\xc4\x2b', 'LLIL_SET_REG.d(s5,LLIL_FLOAT_CONV.d(LLIL_REG.q(d4)))'),
# vcvt.s32.f64 d2, d2, #0x20
('A', b'\xc0\x2b\xbe\xee', 'LLIL_SET_REG.q(d2,LLIL_SX.q(LLIL_FLOAT_TO_INT.d(LLIL_ROUND_TO_INT.q(LLIL_FMUL.q(LLIL_REG.q(d2),LLIL_FLOAT_CONST.q(4294967296.0))))))'),
('A', b'\xc0\x2b\xbe\xee', 'LLIL_SET_REG.q(d2,LLIL_SX.q(LLIL_FLOAT_TO_INT.d(LLIL_FTRUNC.q(LLIL_FMUL.q(LLIL_REG.q(d2),LLIL_FLOAT_CONST.q(4294967296.0))))))'),
# vcvt.u32.f64 d20, d20, #0x20
('A', b'\xc0\x4b\xff\xee', 'LLIL_SET_REG.q(d20,LLIL_ZX.q(LLIL_FLOAT_TO_INT.d(LLIL_ROUND_TO_INT.q(LLIL_FMUL.q(LLIL_REG.q(d20),LLIL_FLOAT_CONST.q(4294967296.0))))))'),
('A', b'\xc0\x4b\xff\xee', 'LLIL_SET_REG.q(d20,LLIL_ZX.q(LLIL_FLOAT_TO_INT.d(LLIL_FTRUNC.q(LLIL_FMUL.q(LLIL_REG.q(d20),LLIL_FLOAT_CONST.q(4294967296.0))))))'),
# vmaxnm.f64 d11, d11, d7
('T', b'\x8b\xfe\x07\xbb', 'LLIL_INTRINSIC([d11],__vmaxnm,[LLIL_REG.q(d11),LLIL_REG.q(d7)])'),
# vminnm.f64 d8, d8, d9
Expand Down
17 changes: 17 additions & 0 deletions arch/armv7/thumb2_disasm/arch_thumb2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1811,6 +1811,10 @@ class Thumb2Architecture: public ArmCommonArchitecture
return "__vrhadd";
case ARMV7_INTRIN_VRECPE:
return "__vrecpe";
case ARMV7_INTRIN_VABS:
return "__vabs";
case ARMV7_INTRIN_VCVT_FIXED:
return "__vcvt_fixed";
case ARMV7_INTRIN_VQSHL:
return "__vqshl";
case ARMV7_INTRIN_VQRSHL:
Expand Down Expand Up @@ -2121,6 +2125,8 @@ class Thumb2Architecture: public ArmCommonArchitecture
ARMV7_INTRIN_VHADD,
ARMV7_INTRIN_VRHADD,
ARMV7_INTRIN_VRECPE,
ARMV7_INTRIN_VABS,
ARMV7_INTRIN_VCVT_FIXED,
ARMV7_INTRIN_VQSHL,
ARMV7_INTRIN_VQRSHL,
ARMV7_INTRIN_VQSHRN,
Expand Down Expand Up @@ -2427,11 +2433,20 @@ class Thumb2Architecture: public ArmCommonArchitecture
NameAndType("source2", Type::IntegerType(8, false)),
};
case ARMV7_INTRIN_VRECPE:
case ARMV7_INTRIN_VABS:
return {
NameAndType("size", Type::IntegerType(1, false)),
NameAndType("is_float", Type::BoolType()),
NameAndType("source", Type::IntegerType(8, false)),
};
case ARMV7_INTRIN_VCVT_FIXED:
return {
NameAndType("size", Type::IntegerType(1, false)),
NameAndType("fractional_bits", Type::IntegerType(1, false)),
NameAndType("to_fixed", Type::BoolType()),
NameAndType("is_unsigned", Type::BoolType()),
NameAndType("source", Type::IntegerType(8, false)),
};
case ARMV7_INTRIN_VREV16:
case ARMV7_INTRIN_VREV32:
case ARMV7_INTRIN_VREV64:
Expand Down Expand Up @@ -2841,6 +2856,8 @@ class Thumb2Architecture: public ArmCommonArchitecture
case ARMV7_INTRIN_VHADD:
case ARMV7_INTRIN_VRHADD:
case ARMV7_INTRIN_VRECPE:
case ARMV7_INTRIN_VABS:
case ARMV7_INTRIN_VCVT_FIXED:
case ARMV7_INTRIN_VQSHL:
case ARMV7_INTRIN_VQRSHL:
case ARMV7_INTRIN_VQSHRN:
Expand Down
Loading
Loading