def __init__(self, encoding, length, instructionSet): self.length = length self.encoding = encoding self.instructionSet = instructionSet self.condition = Condition(Condition.AL) self.width = '' self.shiftType = 0 self.shiftAmount = Constant(0)
def setShift(self, shiftTypeAndAmount): 'Set the :attr:`shiftType` and :attr:`shiftAmount`. Returns ``self``.' self.shiftType = shiftTypeAndAmount[0] shiftAmount = shiftTypeAndAmount[1] if not isinstance(shiftAmount, Operand): shiftAmount = Constant(shiftAmount) self.shiftAmount = shiftAmount return self
def __init__(self, encoding, length, instructionSet): self.length = length self.encoding = encoding self.instructionSet = instructionSet self.condition = Condition(Condition.AL) self.width = "" self.shiftType = 0 self.shiftAmount = Constant(0)
class Instruction(metaclass=ABCMeta): ''' The base class for all ARM and Thumb instructions. .. attribute:: encoding The encoding (as a little-endian integer) of this instruction. .. attribute:: length The length of this instruction. .. attribute:: instructionSet The instruction set of this instruction. +-------+-----------------+ | Value | Instruction set | +=======+=================+ | 0 | ARM | +-------+-----------------+ | 1 | Thumb | +-------+-----------------+ | 2 | Jazelle | +-------+-----------------+ | 3 | ThumbEE | +-------+-----------------+ .. attribute:: condition The :class:`Condition` of this instruction. .. attribute:: width The instruction width. This field only affects the disassembly. +----------+--------------+ | Width | Meaning | +==========+==============+ | ``''`` | Default | +----------+--------------+ | ``'.n'`` | Force narrow | +----------+--------------+ | ``'.w'`` | Force wide | +----------+--------------+ .. attribute:: shiftType shiftAmount The shift type and amount to be applied to the last operand. +--------------------------------------------+---------------------------------+ | Shift type | Meaning | +============================================+=================================+ | :const:`~cpu.arm.functions.SRTYPE_LSL` (0) | Left shift | +--------------------------------------------+---------------------------------+ | :const:`~cpu.arm.functions.SRTYPE_LSR` (1) | Logical (unsigned) right shift | +--------------------------------------------+---------------------------------+ | :const:`~cpu.arm.functions.SRTYPE_ASR` (2) | Arithmetic (signed) right shift | +--------------------------------------------+---------------------------------+ | :const:`~cpu.arm.functions.SRTYPE_ROR` (3) | Rotate bits right | +--------------------------------------------+---------------------------------+ | :const:`~cpu.arm.functions.SRTYPE_RRX` (4) | Rotate bits right with carry | +--------------------------------------------+---------------------------------+ ''' def __init__(self, encoding, length, instructionSet): self.length = length self.encoding = encoding self.instructionSet = instructionSet self.condition = Condition(Condition.AL) self.width = '' self.shiftType = 0 self.shiftAmount = Constant(0) @abstractmethod def mainOpcode(self): # pragma: no cover "Return the instruction's opcode without conditions." return '<unk{0:0{1}x}>'.format(self.encoding, self.length * 2) @property def opcode(self): '''Return the instruction's opcode (including condition code). Subclasses should overload the :meth:`mainOpcode` method to provide the actual opcode.''' return self.mainOpcode() + str(self.condition) + self.width def forceWide(self): '''Force the ".w" qualifier to show in the disassembly of this instruction. Returns ``self``.''' self.width = '.w' return self def setShift(self, shiftTypeAndAmount): 'Set the :attr:`shiftType` and :attr:`shiftAmount`. Returns ``self``.' self.shiftType = shiftTypeAndAmount[0] shiftAmount = shiftTypeAndAmount[1] if not isinstance(shiftAmount, Operand): shiftAmount = Constant(shiftAmount) self.shiftAmount = shiftAmount return self def execute(self, thread): 'Execute the instruction with a *thread*' location = thread.pcRaw if self.condition.check(thread.cpsr): self.exec(thread) if thread.pcRaw != location: thread.onBranch(location, self, thread) return thread.pc = location + self.length @abstractmethod def exec(self, thread): # pragma: no cover '''Execute the instruction with a *thread* after passing the conditions. Subclasses should override this method to provide the actual implementation of this instruction.''' assert False @abstractproperty def operands(self): # pragma: no cover 'Return a list of :class:`~cpu.arm.operand.Operand`\s of the instruction.' return [] def applyShift(self, thread, value, carry): 'Apply shift to an integer. Return the shifted value.' return Shift(0xffffffff, value, self.shiftType, self.shiftAmount.get(thread), carry) def applyShift_C(self, thread, value, carry): 'Apply shift to an integer. Return the shifted value and carry.' return Shift_C(0xffffffff, value, self.shiftType, self.shiftAmount.get(thread), carry) def __str__(self): 'Disassemble this instruction.' opcode = self.opcode operands = ', '.join(map(str, self.operands)) if self.shiftType or self.shiftAmount: operands += _formatShift(self.shiftType, self.shiftAmount) return '{0}\t{1}'.format(opcode, operands)
class Instruction(metaclass=ABCMeta): """ The base class for all ARM and Thumb instructions. .. attribute:: encoding The encoding (as a little-endian integer) of this instruction. .. attribute:: length The length of this instruction. .. attribute:: instructionSet The instruction set of this instruction. +-------+-----------------+ | Value | Instruction set | +=======+=================+ | 0 | ARM | +-------+-----------------+ | 1 | Thumb | +-------+-----------------+ | 2 | Jazelle | +-------+-----------------+ | 3 | ThumbEE | +-------+-----------------+ .. attribute:: condition The :class:`Condition` of this instruction. .. attribute:: width The instruction width. This field only affects the disassembly. +----------+--------------+ | Width | Meaning | +==========+==============+ | ``''`` | Default | +----------+--------------+ | ``'.n'`` | Force narrow | +----------+--------------+ | ``'.w'`` | Force wide | +----------+--------------+ .. attribute:: shiftType shiftAmount The shift type and amount to be applied to the last operand. +--------------------------------------------+---------------------------------+ | Shift type | Meaning | +============================================+=================================+ | :const:`~cpu.arm.functions.SRTYPE_LSL` (0) | Left shift | +--------------------------------------------+---------------------------------+ | :const:`~cpu.arm.functions.SRTYPE_LSR` (1) | Logical (unsigned) right shift | +--------------------------------------------+---------------------------------+ | :const:`~cpu.arm.functions.SRTYPE_ASR` (2) | Arithmetic (signed) right shift | +--------------------------------------------+---------------------------------+ | :const:`~cpu.arm.functions.SRTYPE_ROR` (3) | Rotate bits right | +--------------------------------------------+---------------------------------+ | :const:`~cpu.arm.functions.SRTYPE_RRX` (4) | Rotate bits right with carry | +--------------------------------------------+---------------------------------+ """ def __init__(self, encoding, length, instructionSet): self.length = length self.encoding = encoding self.instructionSet = instructionSet self.condition = Condition(Condition.AL) self.width = "" self.shiftType = 0 self.shiftAmount = Constant(0) @abstractmethod def mainOpcode(self): # pragma: no cover "Return the instruction's opcode without conditions." return "<unk{0:0{1}x}>".format(self.encoding, self.length * 2) @property def opcode(self): """Return the instruction's opcode (including condition code). Subclasses should overload the :meth:`mainOpcode` method to provide the actual opcode.""" return self.mainOpcode() + str(self.condition) + self.width def forceWide(self): """Force the ".w" qualifier to show in the disassembly of this instruction. Returns ``self``.""" self.width = ".w" return self def setShift(self, shiftTypeAndAmount): "Set the :attr:`shiftType` and :attr:`shiftAmount`. Returns ``self``." self.shiftType = shiftTypeAndAmount[0] shiftAmount = shiftTypeAndAmount[1] if not isinstance(shiftAmount, Operand): shiftAmount = Constant(shiftAmount) self.shiftAmount = shiftAmount return self def execute(self, thread): "Execute the instruction with a *thread*" location = thread.pcRaw if self.condition.check(thread.cpsr): self.exec(thread) if thread.pcRaw != location: thread.onBranch(location, self, thread) return thread.pc = location + self.length @abstractmethod def exec(self, thread): # pragma: no cover """Execute the instruction with a *thread* after passing the conditions. Subclasses should override this method to provide the actual implementation of this instruction.""" assert False @abstractproperty def operands(self): # pragma: no cover "Return a list of :class:`~cpu.arm.operand.Operand`\s of the instruction." return [] def applyShift(self, thread, value, carry): "Apply shift to an integer. Return the shifted value." return Shift(0xFFFFFFFF, value, self.shiftType, self.shiftAmount.get(thread), carry) def applyShift_C(self, thread, value, carry): "Apply shift to an integer. Return the shifted value and carry." return Shift_C(0xFFFFFFFF, value, self.shiftType, self.shiftAmount.get(thread), carry) def __str__(self): "Disassemble this instruction." opcode = self.opcode operands = ", ".join(map(str, self.operands)) if self.shiftType or self.shiftAmount: operands += _formatShift(self.shiftType, self.shiftAmount) return "{0}\t{1}".format(opcode, operands)