class Register: registers = [] def __init__(self, n_bits, name=None): self.n_bits = n_bits if name is None: self.name = "r{}".format(len(Register.registers)) else: self.name = name self.value = 0 Register.registers.append(self) def truncate_val(self, value, bits=None): if bits is None: bits = self.n_bits return value & ((1 << bits) - 1) def truncate(self): self.value = self.truncate_val(self.value) def set(self, value): if value < 0: self.value = self.truncate_val(abs(value), self.n_bits - 1) self.negate() else: self.value = value self.truncate() def get(self): return self.value def get_signed(self): if self.value & (1 << (self.n_bits - 1)) == 0: return self.value else: return self.value - (1 << self.n_bits) def complement(self): self.value = self.value ^ ((1 << self.n_bits) - 1) def negate(self): self.complement() self.value += 1 def __str__(self): return "{:08b}".format(self.value) def __repr__(self): return "{} ({})".format(self, self.n_bits) class Accumulator(Register): negative_flag = False zero_flag = False carry_flag = False parity_flag = False def set_flags(self): "Set accumulator flags after an arithmetic operation" self.negative_flag = False self.zero_flag = False if self.get_signed() < 0: self.negative_flag = True if self.get() == 0: self.zero_flag = True v = self.get() self.parity_flag = True while v > 0: if (v & 1) == 1: self.parity_flag = not self.parity_flag v >>= 1 def add(self, register: Register): self.value += register.value if self.value.bit_length() > self.n_bits: self.carry_flag = True self.truncate() self.set_flags() def sub(self, register: Register): self.negate() self.add(register) self.negate() self.set_flags() def shift_right(self, through_carry=True): was_one = (self.get() & 1) == 1 if through_carry: add_bit = self.carry_flag else: add_bit = was_one if add_bit: self.value |= 1 << (self.n_bits) self.value >>= 1 self.carry_flag = was_one self.set_flags() def shift_left(self, through_carry=True): was_one = (self.get() & (1 << (self.n_bits - 1))) != 0 if through_carry: add_bit = self.carry_flag else: add_bit = was_one self.value <<= 1 if add_bit: self.value |= 1 self.carry_flag = was_one self.set_flags()