from __future__ import annotations
from ._isa import Encoding
[docs]
class Instruction:
[docs]
def __init__(self, pc : int, encoding_bytes : int) -> None:
"""
Constructor
:param pc: Program counter
:type pc: int
:param encoding_bytes: Instruction encoding
:type encoding_bytes: int
"""
self.pc = pc
self.encoding_bytes = encoding_bytes
self.encoding = None
self.operands = {}
self.prev = None
self.next = None
self.decode()
def __str__(self) -> str:
"""
Return a string representation of the Instruction.
:return: String representation of the Instruction.
:rtype: str
"""
s = f"{self.pc:016x} : "
s += f"{self.prev.encoding.mnemonic}" if self.prev is not None else "None"
s += " -> "
s += f"\033[31m{self.encoding.mnemonic}\033[0m"
s += " -> "
s += f"{self.next.encoding.mnemonic}" if self.next is not None else "None"
return s
[docs]
def link(self, next : Instruction) -> None:
"""
Create 2 way link to next instruction (if you can)
Next / Prev refers to location in program (i.e. pc +/- one instruction)
not location in trace
:param next: Next instruction
:type next: Instruction
"""
if next is not None:
self.next = next
self.next.prev = self
[docs]
def decode(self) -> None:
"""
Decode instruction to get mnemonic and operands
"""
# Determine size (compressed or standard)
if (self.encoding_bytes & 0b11) != 0b11:
self.size = 2
instr_code = self.encoding_bytes & 0xFFFF
else:
self.size = 4
instr_code = self.encoding_bytes & 0xFFFFFFFF
self.encoding = Encoding.get_encoding(instr_code)
# Extract Operand Values
for k in self.encoding.operands.keys():
self.operands[k] = Encoding.get_operand(instr_code, k)
__all__ = [
"Instruction"
]