diff --git a/arch/armv7/armv7_disasm/armv7.h b/arch/armv7/armv7_disasm/armv7.h index 14ff191a3c..8f71582057 100644 --- a/arch/armv7/armv7_disasm/armv7.h +++ b/arch/armv7/armv7_disasm/armv7.h @@ -910,15 +910,23 @@ typedef union _ieee754 { float fvalue; }ieee754; -typedef union _ieee754_double { +typedef union _ieee754_double +{ uint64_t value; - struct { - uint64_t fraction:52; - uint64_t exponent:11; - uint64_t sign:1; + struct + { + uint64_t fraction : 52; + uint64_t exponent : 11; + uint64_t sign : 1; }; double fvalue; -}ieee754_double; +} ieee754_double; + +struct DoubleWordRegisterList +{ + uint8_t size; + uint8_t start; +}; #ifndef __cplusplus typedef enum OperandClass OperandClass; diff --git a/arch/armv7/il.cpp b/arch/armv7/il.cpp index 0d79bcf65c..9a5a5d2e07 100644 --- a/arch/armv7/il.cpp +++ b/arch/armv7/il.cpp @@ -123,7 +123,41 @@ static void ConditionExecute(LowLevelILFunction& il, Condition cond, ExprId true il.AddInstruction(trueCase); il.MarkLabel(falseCode); } - +// Returns an instructions datatype size in bits +static size_t GetDataTypeSize(DataType dt) +{ + switch (dt) + { + case DT_P8: + case DT_U8: + case DT_I8: + case DT_8: + return 8; + case DT_P16: + case DT_U16: + case DT_S16: + case DT_F16: + case DT_I16: + case DT_16: + return 16; + case DT_P32: + case DT_U32: + case DT_S32 + case DT_F32: + case DT_I32: + case DT_32: + return 32; + case DT_P64: + case DT_U64: + case DT_S64: + case DT_F64: + case DT_I64: + case DT_64: + return 64; + default: + return 0; + } +} static ExprId GetShifted(LowLevelILFunction& il, Register reg, uint32_t ShiftAmount, Shift shift) { @@ -159,7 +193,22 @@ static ExprId GetShifted(LowLevelILFunction& il, Register reg, uint32_t ShiftAmo return 0; } } - +static DoubleWordRegisterList ReadRegisterList(const InstructionOperand& instr) { + uint32_t val = instr.reg; + DoubleWordRegisterList dwrl; + #ifdef _MSC_VER + dwrl.size = __popcnt(val); + DWORD pos = 0; + _BitScanForward(&pos, val); + dwrl.start = pos; + + #else + dwrl.size = __builtin_popcount(val); + dwrl.start = __builtin_ctz(val); + + #endif + return dwrl; +} static ExprId GetShiftedOffset(LowLevelILFunction& il, InstructionOperand& op) { @@ -5086,6 +5135,34 @@ bool GetLowLevelILForArmInstruction(Architecture* arch, uint64_t addr, LowLevelI ) ); break; + case ARMV7_VLD1: + ConditionExecute(addrSize, instr.cond, instr, il, [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il) { + switch (op1.cls) + { + case OperandClass::REG_LIST_DOUBLE: + DoubleWordRegisterList reglist = ReadRegisterList(op1); + uint32_t dregsize = get_register_size(REG_D0); + uint32_t regsize = get_register_size(op2.reg); + uint32_t dataSizeInBytes = GetDataTypeSize(instr.dataType) / 8; + for (unsigned int i = 0; i < reglist.size; i++) + { + uint32_t curOffset = i * dataSizeInBytes; + uint32_t curregind = REG_D0 + reglist.start + i; + + il.AddInstruction(il.SetRegister(dregsize, curregind, + il.Load(dataSizeInBytes, il.Add(regsize, ILREG(op2), il.Const(regsize, curOffset))))); + } + if (op2.flags.wb) + { + il.AddInstruction(il.SetRegister( + regsize, op2.reg, il.Add(regsize, ILREG(op2), il.Const(regsize, dataSizeInBytes * reglist.size)))); + } + default: + il.AddInstruction(il.Unimplemented()); + break; + } + }); + break; default: //printf("Instruction: %s\n", get_operation(instr.operation)); ConditionExecute(il, instr.cond, il.Unimplemented());