def _translate_lsl(self, tb, instruction): # LSL (register) if len(instruction.operands) == 3 and isinstance(instruction.operands[1], ArmRegisterOperand): sh_op = ArmShiftedRegisterOperand(instruction.operands[1], "lsl", instruction.operands[2], instruction.operands[1].size) disp = tb._compute_shifted_register(sh_op) tb.write(instruction.operands[0], disp) return if len(instruction.operands) == 2 and isinstance(instruction.operands[1], ArmShiftedRegisterOperand): # Capstone is incorrectly packing <Rm>, #<imm5> into a shifted register, unpack it instruction.operands.append(instruction.operands[1]._shift_amount) instruction.operands[1] = instruction.operands[1]._base_reg oprnd1 = tb.read(instruction.operands[1]) oprnd2 = tb.read(instruction.operands[2]) result = tb.temporal(oprnd1.size) tb.add(self._builder.gen_bsh(oprnd1, oprnd2, result)) tb.write(instruction.operands[0], result) if instruction.update_flags: self._update_zf(tb, oprnd1, oprnd2, result) self._update_nf(tb, oprnd1, oprnd2, result) # TODO: Encapsulate this new kind of flag update (different from the data proc instructions like add, and, orr) if oprnd2.immediate == 0: return else: # carry_out = Rm[32 - shift_imm] shift_carry_out = tb._extract_bit(oprnd1, 32 - oprnd2.immediate) tb.add(self._builder.gen_str(shift_carry_out, self._flags["cf"]))
def process_shifted_register(tokens): base = process_register(tokens["base"]) sh_type = tokens["type"] amount = tokens.get("amount", None) if amount: if "imm" in amount: amount = ArmImmediateOperand("".join(amount["imm"]), arch_info.operand_size) elif "reg" in amount: amount = process_register(amount["reg"]) else: raise Exception("Unknown amount type.") return ArmShiftedRegisterOperand(base, sh_type, amount, base.size)
def __cs_shift_to_arm_op(self, cs_op, cs_insn, arm_base): if cs_op.shift.type == 0: raise Exception("Invalid shift type.") cs_shift_mapper = { ARM_SFT_ASR: "asr", ARM_SFT_LSL: "lsl", ARM_SFT_LSR: "lsr", ARM_SFT_ROR: "ror", ARM_SFT_RRX: "rrx", ARM_SFT_ASR_REG: "asr", ARM_SFT_LSL_REG: "lsl", ARM_SFT_LSR_REG: "lsr", ARM_SFT_ROR_REG: "ror", ARM_SFT_RRX_REG: "rrx", } # The base register (arm_base) is not included in the shift # struct in Capstone, so it's provided separately. sh_type = cs_shift_mapper[cs_op.shift.type] if cs_op.shift.type <= ARM_SFT_RRX: amount = ArmImmediateOperand(cs_op.shift.value, self._arch_info.operand_size) # TODO: check if this is a valid case. if cs_op.shift.value == 0: raise Exception("Shift value is zero.") elif cs_op.shift.type <= ARM_SFT_RRX_REG: amount = self.__cs_reg_idx_to_arm_op_reg(cs_op.shift.value, cs_insn) else: raise Exception("Unknown shift type.") return ArmShiftedRegisterOperand(arm_base, sh_type, amount, arm_base.size)