summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorGalen Williamson <galen@vector35.com>2025-08-08 14:30:49 -0400
committerGalen Williamson <galen@vector35.com>2025-08-14 14:06:49 -0400
commit2aa2a28a341a2290fe0328a46dbe8e3d7bb3ba4d (patch)
tree54cb1a70bf0f99889fa18b2905b4f897d5460b6d /arch
parent193450bcf90800753aec316322ee651c5520ea57 (diff)
Corrected python docstring for LowLevelILFunction.float_convert
[thumb2] removed redundant format suffixes from disassembly of VFP instruction [thumb2] Corrected lifting of VCVT instruction
Diffstat (limited to 'arch')
-rw-r--r--arch/armv7/thumb2_disasm/disassembler.cpp19
-rw-r--r--arch/armv7/thumb2_disasm/il_thumb2.cpp154
2 files changed, 135 insertions, 38 deletions
diff --git a/arch/armv7/thumb2_disasm/disassembler.cpp b/arch/armv7/thumb2_disasm/disassembler.cpp
index 8c7902b7..6910307f 100644
--- a/arch/armv7/thumb2_disasm/disassembler.cpp
+++ b/arch/armv7/thumb2_disasm/disassembler.cpp
@@ -317,15 +317,16 @@ std::string get_thumb_operation_name(struct decomp_result* result)
contents += tlookup[tindex];
contents += slookup[sindex];
}
- if (format->operationFlags & INSTR_FORMAT_FLAG_F16) {
- contents += ".F16";
- }
- if (format->operationFlags & INSTR_FORMAT_FLAG_F32) {
- contents += ".F32";
- }
- if (format->operationFlags & INSTR_FORMAT_FLAG_F64) {
- contents += ".F64";
- }
+ // These are obviated by the type specifier being included in the instruction_format.operation field in spec.cpp
+ // if (format->operationFlags & INSTR_FORMAT_FLAG_F16) {
+ // contents += ".F16";
+ // }
+ // if (format->operationFlags & INSTR_FORMAT_FLAG_F32) {
+ // contents += ".F32";
+ // }
+ // if (format->operationFlags & INSTR_FORMAT_FLAG_F64) {
+ // contents += ".F64";
+ // }
if (format->operationFlags & INSTR_FORMAT_FLAG_WIDE) {
contents += ".w";
diff --git a/arch/armv7/thumb2_disasm/il_thumb2.cpp b/arch/armv7/thumb2_disasm/il_thumb2.cpp
index 48dcf4ac..a9205b39 100644
--- a/arch/armv7/thumb2_disasm/il_thumb2.cpp
+++ b/arch/armv7/thumb2_disasm/il_thumb2.cpp
@@ -1821,47 +1821,143 @@ 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 (instr->format->operandCount == 3)
+ if (IS_FIELD_PRESENT(instr, FIELD_to_fixed))
{
- // TODO: Fixed point unsupported.
+ if (IS_FIELD_PRESENT(instr, FIELD_imm))
+ {
+ // VCVT (between floating-point and fixed-point, Floating-point)
+ /* VCVT<c>.F32.<dt> <Sd>,<Sd>,#<imm> */
+ /* VCVT<c>.F64.<dt> <Dd>,<Dd>,#<imm> */
+ /* VCVT<c>.<dt> <Sd>,<Sd>,#<imm> */
+ /* VCVT<c>.<dt> <Dd>,<Dd>,#<imm> */
+ // TODO: fixed-point unsupported.
+ il.AddInstruction(il.Unimplemented());
+ }
+ else if (IS_FIELD_PRESENT(instr, FIELD_fbits))
+ {
+ // VCVT (between floating-point and fixed-point, Advanced SIMD)
+ /* VCVT<c>.<dt> <Dd>,<Dm>,#<fbits> */
+ /* VCVT<c>.<dt> <Qd>,<Qm>,#<fbits> */
+ // TODO: vector and fixed-point unsupported.
+ }
+ }
+ else if (IS_FIELD_PRESENT(instr, FIELD_half_to_single))
+ {
+ // VCVT (between half-precision and single-precision, Advanced SIMD)
+ /* VCVT<c>.F16.F32 <Dd>,<Qm> */
+ /* VCVT<c>.F32.F16 <Qd>,<Dm> */
+ // TODO: vector and half-precision unsupported.
il.AddInstruction(il.Unimplemented());
}
- else if (instr->format->operationFlags & (INSTR_FORMAT_FLAG_F32 | INSTR_FORMAT_FLAG_F64))
+ else if (IS_FIELD_PRESENT(instr, FIELD_double_to_single))
{
- il.AddInstruction(
- WriteILOperand(il, instr, 0, il.FloatConvert(GetRegisterSize(instr, 1), ReadILOperand(il, instr, 1))));
+ // VCVT (between double-precision and single-precision)
+ /* VCVT<c>.F64.F32 <Dd>,<Sm> */
+ /* VCVT<c>.F32.F64 <Sd>,<Dm> */
+ il.AddInstruction(WriteILOperand(
+ il, instr, 0, il.FloatConvert(GetRegisterSize(instr, 1), ReadILOperand(il, instr, 1))));
+ break;
}
- else if (IS_FIELD_PRESENT(instr, FIELD_td))
+ else if (IS_FIELD_PRESENT(instr, FIELD_to_integer))
{
- switch (instr->fields[FIELD_dt])
+ if (IS_FIELD_PRESENT(instr, FIELD_td))
{
- case VFP_DATA_SIZE_S32F32:
- case VFP_DATA_SIZE_U32F32:
- 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:
- il.AddInstruction(WriteILOperand(
- il, instr, 0, il.FloatToInt(GetRegisterSize(instr, 1), ReadILOperand(il, instr, 1))));
- break;
- default:
- il.AddInstruction(il.Unimplemented());
+ // VCVT (between floating-point and integer, Advanced SIMD)
+ /* VCVT<c>.<dt> <Dd>,<Dm> */ // instr->fields[FIELD_regs] = 1
+ /* VCVT<c>.<dt> <Qd>,<Qm> */ // 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.
+ il.AddInstruction(il.Unimplemented());
+ }
}
- }
- else
- {
- switch (instr->fields[FIELD_dt])
+ else if (instr->format->operationFlags & (INSTR_FORMAT_FLAG_F32 | INSTR_FORMAT_FLAG_F64))
{
- case VFP_DATA_SIZE_F32:
- case VFP_DATA_SIZE_S32:
+ switch (instr->fields[FIELD_dt])
+ {
+ case VFP_DATA_SIZE_S32:
+ il.AddInstruction(WriteILOperand(
+ il, instr, 0, il.IntToFloat(GetRegisterSize(instr, 0),
+ il.SignExtend(GetRegisterSize(instr, 0),
+ ReadILOperand(il, instr, 1)))));
+ break;
+ case VFP_DATA_SIZE_U32:
+ il.AddInstruction(WriteILOperand(
+ il, instr, 0, il.IntToFloat(GetRegisterSize(instr, 0),
+ il.ZeroExtend(GetRegisterSize(instr, 0),
+ ReadILOperand(il, instr, 1)))));
+ break;
+ }
+ // 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:
+ 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.FloatConvert(GetRegisterSize(instr, 1), ReadILOperand(il, instr, 1))));
- break;
- default:
- il.AddInstruction(il.Unimplemented());
+ 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)))));
+ break;
+ case VFP_DATA_SIZE_F32S32:
+ case VFP_DATA_SIZE_F32U32:
+ il.AddInstruction(WriteILOperand(
+ il, instr, 0, il.IntToFloat(GetRegisterSize(instr, 0), ReadILOperand(il, instr, 1))));
+ break;
+ default:
+ // Invalid
+ il.AddInstruction(il.Unimplemented());
+ }
}
}
+ // 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;
case armv7::ARMV7_VMOV:
if (instr->format->operandCount == 4)