You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

109 lines
2.8 KiB

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()