Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Speed up ArmV7Operand.type assertions #1313

Merged
merged 4 commits into from
Dec 20, 2018
Merged
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
47 changes: 26 additions & 21 deletions manticore/native/cpu/arm.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,25 +53,30 @@ def instruction_implementation(cpu, *args, **kwargs):
return abstract_instruction(instruction_implementation)


_TYPE_MAP = {
cs.arm.ARM_OP_REG: 'register',
cs.arm.ARM_OP_MEM: 'memory',
cs.arm.ARM_OP_IMM: 'immediate',
cs.arm.ARM_OP_PIMM: 'coprocessor',
cs.arm.ARM_OP_CIMM: 'immediate'
}


class Armv7Operand(Operand):
def __init__(self, cpu, op, **kwargs):
super().__init__(cpu, op, **kwargs)
self.__type = _TYPE_MAP[self.op.type]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

jw, why two underscores? maybe just 1 is fine

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly to be more bullet proof against future changes of Operand - e.g. if it ever get a _type attribute, having a _type here would overwrite it. Using __type prevents it.

But I guess it doesn't have a _type and we can do it for now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah i see. either way is fine with me then!


@property
def type(self):
type_map = {
cs.arm.ARM_OP_REG: 'register',
cs.arm.ARM_OP_MEM: 'memory',
cs.arm.ARM_OP_IMM: 'immediate',
cs.arm.ARM_OP_PIMM: 'coprocessor',
cs.arm.ARM_OP_CIMM: 'immediate'
}

return type_map[self.op.type]
"""
Corresponds to capstone's `operand.type` (cs.arm.ARM_OP_*).
"""
return self.__type

@property
def size(self):
assert self.type == 'register'
assert self.__type == 'register'
if cs.arm.ARM_REG_D0 <= self.op.reg <= cs.arm.ARM_REG_D31:
return 64
else:
Expand All @@ -80,7 +85,7 @@ def size(self):

def read(self, nbits=None, with_carry=False):
carry = self.cpu.regfile.read('APSR_C')
if self.type == 'register':
if self.__type == 'register':
value = self.cpu.regfile.read(self.reg)
# PC in this case has to be set to the instruction after next. PC at this point
# is already pointing to next instruction; we bump it one more.
Expand All @@ -94,17 +99,17 @@ def read(self, nbits=None, with_carry=False):
if with_carry:
return value, carry
return value
elif self.type == 'immediate':
elif self.__type == 'immediate':
imm = self.op.imm
if self.op.subtracted:
imm = -imm
if with_carry:
return imm, self._get_expand_imm_carry(carry)
return imm
elif self.type == 'coprocessor':
elif self.__type == 'coprocessor':
imm = self.op.imm
return imm
elif self.type == 'memory':
elif self.__type == 'memory':
val = self.cpu.read_int(self.address(), nbits)
if with_carry:
return val, carry
Expand All @@ -113,17 +118,17 @@ def read(self, nbits=None, with_carry=False):
raise NotImplementedError("readOperand unknown type", self.op.type)

def write(self, value, nbits=None):
if self.type == 'register':
if self.__type == 'register':
self.cpu.regfile.write(self.reg, value)
elif self.type == 'memory':
elif self.__type == 'memory':
raise NotImplementedError('need to impl arm store mem')
else:
raise NotImplementedError("writeOperand unknown type", self.op.type)

def writeback(self, value):
if self.type == 'register':
if self.__type == 'register':
self.write(value)
elif self.type == 'memory':
elif self.__type == 'memory':
self.cpu.regfile.write(self.mem.base, value)
else:
raise NotImplementedError("writeback Operand unknown type", self.op.type)
Expand All @@ -144,12 +149,12 @@ def is_shifted(self):
return self.op.shift.type != cs.arm.ARM_SFT_INVALID

def address(self):
assert self.type == 'memory'
assert self.__type == 'memory'
addr = self.get_mem_base_addr() + self.get_mem_offset()
return addr & Mask(self.cpu.address_bit_size)

def get_mem_offset(self):
assert self.type == 'memory'
assert self.__type == 'memory'

off = 0
if self.mem.index is not None:
Expand All @@ -164,7 +169,7 @@ def get_mem_offset(self):
return off

def get_mem_base_addr(self):
assert self.type == 'memory'
assert self.__type == 'memory'

base = self.cpu.regfile.read(self.mem.base)

Expand Down