From 0becd045c5e3e0997c30cb64f19fe21b2b3c421f Mon Sep 17 00:00:00 2001 From: Galen Williamson Date: Fri, 8 Aug 2025 19:08:54 -0400 Subject: [thumb2] improved disassembly and lifting of VCVT instruction for scalar floating-point/integer cases --- arch/armv7/thumb2_disasm/il_thumb2.cpp | 97 +++++++++++++++------------------- 1 file changed, 42 insertions(+), 55 deletions(-) (limited to 'arch/armv7/thumb2_disasm/il_thumb2.cpp') diff --git a/arch/armv7/thumb2_disasm/il_thumb2.cpp b/arch/armv7/thumb2_disasm/il_thumb2.cpp index a9205b39..cc3856c9 100644 --- a/arch/armv7/thumb2_disasm/il_thumb2.cpp +++ b/arch/armv7/thumb2_disasm/il_thumb2.cpp @@ -1821,7 +1821,6 @@ bool GetLowLevelILForNEONInstruction(Architecture* arch, LowLevelILFunction& il, il.AddInstruction(WriteILOperand(il, instr, 0, ReadILOperand(il, instr, 1), GetRegisterSize(instr, 1))); break; case armv7::ARMV7_VCVT: - // if (instr->format->operandCount == 3) if (IS_FIELD_PRESENT(instr, FIELD_to_fixed)) { if (IS_FIELD_PRESENT(instr, FIELD_imm)) @@ -1864,78 +1863,79 @@ bool GetLowLevelILForNEONInstruction(Architecture* arch, LowLevelILFunction& il, if (IS_FIELD_PRESENT(instr, FIELD_td)) { // VCVT (between floating-point and integer, Advanced SIMD) - /* VCVT.
, */ // instr->fields[FIELD_regs] = 1 - /* VCVT.
, */ // instr->fields[FIELD_regs] = 2 + /* VCVT.
, */ // instr->fields[FIELD_regs] = 1 + /* VCVT.
, */ // instr->fields[FIELD_regs] = 2 switch (instr->fields[FIELD_dt]) { case VFP_DATA_SIZE_S32F32: case VFP_DATA_SIZE_U32F32: // TODO: iterate over vector components - // il.AddInstruction(WriteILOperand( - // il, instr, 0, il.IntToFloat(GetRegisterSize(instr, 1), ReadILOperand(il, instr, 1)))); // break; case VFP_DATA_SIZE_F32S32: case VFP_DATA_SIZE_F32U32: // TODO: iterate over vector components - // il.AddInstruction(WriteILOperand( - // il, instr, 0, il.FloatToInt(GetRegisterSize(instr, 1), - // il.RoundToInt(GetRegisterSize(instr, 1), - // ReadILOperand(il, instr, 1))))); // break; default: - // TODO: vector unsupported. + // Invalid il.AddInstruction(il.Unimplemented()); } } - else if (instr->format->operationFlags & (INSTR_FORMAT_FLAG_F32 | INSTR_FORMAT_FLAG_F64)) + else if (instr->fields[FIELD_to_integer]) { + // VCVT, VCVTR (between floating-point and integer, Floating-point) + // TODO: handle distinction of VCVTR: + // If R is specified, the operation uses the rounding mode specified by the FPSCR. + // If R is omitted. the operation uses the Round towards Zero rounding mode. + // (Note: Binary Ninja does not currently support specifying any particular rounding mode, so it doesn't matter.) switch (instr->fields[FIELD_dt]) { - case VFP_DATA_SIZE_S32: + case VFP_DATA_SIZE_S32F32: + case VFP_DATA_SIZE_S32F64: + /* VCVT.S32.F32 , */ + /* VCVT.S32.F64 , */ + /* VCVTR.S32.F32 , */ + /* VCVTR.S32.F64 , */ il.AddInstruction(WriteILOperand( - il, instr, 0, il.IntToFloat(GetRegisterSize(instr, 0), - il.SignExtend(GetRegisterSize(instr, 0), - ReadILOperand(il, instr, 1))))); + il, instr, 0, il.SignExtend(GetRegisterSize(instr, 0), + il.FloatToInt(GetRegisterSize(instr, 0), + il.RoundToInt(GetRegisterSize(instr, 0), + ReadILOperand(il, instr, 1)))))); break; - case VFP_DATA_SIZE_U32: + case VFP_DATA_SIZE_U32F32: + case VFP_DATA_SIZE_U32F64: + /* VCVT.U32.F32 , */ + /* VCVT.U32.F64 , */ + /* VCVTR.U32.F32 , */ + /* VCVTR.U32.F64 , */ il.AddInstruction(WriteILOperand( - il, instr, 0, il.IntToFloat(GetRegisterSize(instr, 0), - il.ZeroExtend(GetRegisterSize(instr, 0), - ReadILOperand(il, instr, 1))))); + il, instr, 0, il.ZeroExtend(GetRegisterSize(instr, 0), + il.FloatToInt(GetRegisterSize(instr, 0), + il.RoundToInt(GetRegisterSize(instr, 0), + ReadILOperand(il, instr, 1)))))); break; + default: + // Invalid + il.AddInstruction(il.Unimplemented()); } - // il.AddInstruction(WriteILOperand( - // il, instr, 0, il.IntToFloat(GetRegisterSize(instr, 0), ReadILOperand(il, instr, 1)))); } else { // VCVT, VCVTR (between floating-point and integer, Floating-point) switch (instr->fields[FIELD_dt]) { - case VFP_DATA_SIZE_S32F32: + case VFP_DATA_SIZE_S32: + /* VCVT.F32.
, */ il.AddInstruction(WriteILOperand( - il, instr, 0, il.SignExtend(GetRegisterSize(instr, 0), - il.FloatToInt(GetRegisterSize(instr, 0), - il.RoundToInt(GetRegisterSize(instr, 0), - ReadILOperand(il, instr, 1)))))); - break; - case VFP_DATA_SIZE_U32F32: - // case VFP_DATA_SIZE_S32F64: - // case VFP_DATA_SIZE_U32F64: - il.AddInstruction(WriteILOperand( - il, instr, 0, il.ZeroExtend(GetRegisterSize(instr, 0), - il.FloatToInt(GetRegisterSize(instr, 0), - il.RoundToInt(GetRegisterSize(instr, 0), - ReadILOperand(il, instr, 1)))))); - // il.AddInstruction(WriteILOperand( - // il, instr, 0, il.FloatToInt(GetRegisterSize(instr, 1), - // il.RoundToInt(GetRegisterSize(instr, 1), - // ReadILOperand(il, instr, 1))))); + il, instr, 0, il.IntToFloat(GetRegisterSize(instr, 0), + il.SignExtend(GetRegisterSize(instr, 0), + ReadILOperand(il, instr, 1))))); break; - case VFP_DATA_SIZE_F32S32: - case VFP_DATA_SIZE_F32U32: + case VFP_DATA_SIZE_U32: + /* VCVT.F64.
, */ il.AddInstruction(WriteILOperand( - il, instr, 0, il.IntToFloat(GetRegisterSize(instr, 0), ReadILOperand(il, instr, 1)))); + il, instr, 0, il.IntToFloat(GetRegisterSize(instr, 0), + il.ZeroExtend(GetRegisterSize(instr, 0), + ReadILOperand(il, instr, 1))))); break; default: // Invalid @@ -1943,19 +1943,6 @@ bool GetLowLevelILForNEONInstruction(Architecture* arch, LowLevelILFunction& il, } } } - // else if (IS_FIELD_PRESENT(instr, FIELD_dt)) - // { - // switch (instr->fields[FIELD_dt]) - // { - // case VFP_DATA_SIZE_F32: - // case VFP_DATA_SIZE_S32: - // il.AddInstruction(WriteILOperand( - // il, instr, 0, il.FloatConvert(GetRegisterSize(instr, 1), ReadILOperand(il, instr, 1)))); - // break; - // default: - // il.AddInstruction(il.Unimplemented()); - // } - // } else il.AddInstruction(il.Unimplemented()); break; -- cgit v1.3.1