def branch(cpu, oper, mode): """ See :data:`~mach8.operations.BCS`, :data:`~mach8.operations.BCC`, :data:`~mach8.operations.BEQ`, :data:`~mach8.operations.BMI`, :data:`~mach8.operations.BNE`, :data:`~mach8.operations.BPL`, :data:`~mach8.operations.BRA`, :data:`~mach8.operations.BVC`, :data:`~mach8.operations.BVS`. """ displacement = cpu.fetch() branch = False if oper == op.BCS: branch = cpu.c elif oper == op.BCC: branch = not cpu.c elif oper == op.BEQ: branch = cpu.z elif oper == op.BMI: branch = cpu.n elif oper == op.BNE: branch = not cpu.z elif oper == op.BPL: branch = not cpu.n elif oper == op.BRA: branch = True elif oper == op.BVC: branch = not cpu.v elif oper == op.BVS: branch = cpu.v else: assert False if branch: cpu.pc += vm.twos_inverse(displacement)
def add(cpu, oper, mode): """ See :data:`~mach8.operations.ADC`. """ operand = _load_am(cpu, mode) carry = 1 if cpu.c else 0 if cpu.d: b1 = vm.bcd_inverse(cpu.a) b2 = vm.bcd_inverse(operand) bcd = b1 + b2 + carry cpu.c = bcd > vm.DIGITS2 if bcd > vm.DIGITS2: bcd -= vm.DIGITS2 + 1 result = vm.bcd_forward(bcd) & vm.BITS8 else: value = cpu.a + operand + carry cpu.c = value > vm.BITS8 result = value & vm.BITS8 signed = vm.twos_inverse(cpu.a) + vm.twos_inverse(operand) cpu.v = signed > vm.SBYTE_MAX or signed < vm.SBYTE_MIN _flags(cpu, result) cpu.a = result
def sub(cpu, oper, mode): """ See :data:`~mach8.operations.SBC`, """ operand = _load_am(cpu, mode) carry = 0 if cpu.c else 1 if cpu.d: b1 = vm.bcd_inverse(cpu.a) b2 = vm.bcd_inverse(operand) value = b1 - b2 - carry cpu.c = not value < 0 if value < 0: value += 100 result = vm.bcd_forward(value) & vm.BITS8 else: value = cpu.a - operand - carry cpu.c = not value < 0 result = value & vm.BITS8 signed = vm.twos_inverse(cpu.a) - vm.twos_inverse(operand) cpu.v = signed > vm.SBYTE_MAX or signed < vm.SBYTE_MIN _flags(cpu, result) cpu.a = result
def next(self): """ Description """ d = Disassembled() d.address = vm.size16(self.position) d.labels = self.meta.get_labels(d.address) d.remarks = self.meta.get_remarks(d.address) d.argument = self.meta.get_argument(d.address) d.data = self.meta.get_data(d.address) if d.data is not None: self.position = d.data.address + d.data.length return d opcode = self.pc.load() if opcode in self._opcodes: i = self._opcodes[opcode] else: op = '?{:02X}'.format(opcode) i = x6502.Instruction(opcode, op, am.IMP, None) d.instruction = i if i.addressing_mode in AM_ADDRESS_16: arg = self.pc.load2() d.bytes = [opcode, vm.lb(arg), vm.hb(arg)] elif (i.addressing_mode in AM_ADDRESS_8 or i.addressing_mode in (am.REL, am.IMM)): arg = self.pc.load() if i.addressing_mode == am.REL and d.argument is None: # Branch is displacement after consuming bytes, therefore # add two. d.argument = vm.hex16(d.address + vm.twos_inverse(arg) + 2) d.bytes = [opcode, arg] elif i.addressing_mode in AM_NO_ARGUMENT: d.bytes = [opcode] else: assert False return d
def test_twos_inverse_max(self): self.assertEquals(127, vm.twos_inverse(0x7f))
def test_twos_inverse_min(self): self.assertEquals(-128, vm.twos_inverse(0x80))
def test_twos_inverse_negative(self): self.assertEquals(-1, vm.twos_inverse(0xff))
def test_twos_inverse(self): self.assertEquals(2, vm.twos_inverse(0x02))