#!/usr/bin/env python3 class MC6800: def __init__(self, memory_size=0xFFFF): # 8-bit registers self.A = 0 # Accumulator A self.B = 0 # Accumulator B self.CCR = 0b00000000 # Condition Code Register (flags) # 16-bit registers self.X = 0 # Index register X self.PC = 0 # Program counter self.SP = 0xFF # Stack pointer (default 0xFF) # Memory (64KB) self.memory = [0] * memory_size def load_program(self, program, start_address=0x0000): for i, byte in enumerate(program): self.memory[start_address + i] = byte self.PC = start_address def fetch(self): # Fetches the next byte of data from memory byte = self.memory[self.PC] self.PC += 1 return byte def execute(self): opcode = self.fetch() if opcode == 0xCE: # LDX Immediate (3 bytes) high_byte = self.fetch() low_byte = self.fetch() self.X = (high_byte << 8) | low_byte elif opcode == 0x86: # LDA Immediate (2 bytes) immediate_value = self.fetch() self.A = immediate_value elif opcode == 0xA7: # STA ,X (Indexed, 2 bytes) addr = self.X self.memory[addr] = self.A self.PC += 1 # Increment PC by an additional byte for the 2-byte instruction length elif opcode == 0xA6: # LDA ,X (Indexed, 2 bytes) addr = self.X self.A = self.memory[addr] self.PC += 1 # Increment PC by an additional byte for the 2-byte instruction length elif opcode == 0x8B: # ADDA Immediate (2 bytes) immediate_value = self.fetch() self.A = (self.A + immediate_value) & 0xFF self.update_flags(self.A) elif opcode == 0x81: # CMPA Immediate (2 bytes) immediate_value = self.fetch() result = self.A - immediate_value self.update_flags(result) elif opcode == 0x26: # BNE (Relative, 2 bytes) offset = self.fetch() if not (self.CCR & 0b00000100): # Check if zero flag is clear self.PC += offset if offset < 0x80 else offset - 0x100 elif opcode == 0x7E: # JMP (Extended, 3 bytes) high_byte = self.fetch() low_byte = self.fetch() self.PC = (high_byte << 8) | low_byte else: print(f"Unknown opcode: {hex(opcode)}") # Print all registers after each instruction self.print_registers() def update_flags(self, result): # Update flags in CCR based on result self.CCR = 0b00000000 if result == 0: self.CCR |= 0b00000100 # Set Zero flag if result & 0x80: self.CCR |= 0b00001000 # Set Negative flag def print_registers(self): # Display the current state of all registers print(f"A: {self.A:02X} B: {self.B:02X} X: {self.X:04X} PC: {self.PC:04X} SP: {self.SP:02X} CCR: {self.CCR:08b}") def run(self, cycles=None): executed_cycles = 0 while cycles is None or executed_cycles < cycles: self.execute() executed_cycles += 1 program = [ 0xCE, 0x00, 0xFF, # LDX #$00FF 0x86, 0x00, # LDA #$00 0xA7, 0x00, # STA ,X 0xA6, 0x00, # LDA ,X 0x8B, 0x01, # ADDA #$01 0x81, 0x0A, # CMPA #$0A 0x26, 0x02, # BNE store_counter 0x86, 0x00, # LDA #$00 0xA7, 0x00, # STA ,X 0x7E, 0x01, 0x07 # JMP counter_loop ] cpu = MC6800() cpu.load_program(program, start_address=0x0100) cpu.run(cycles=20) # Run a limited number of cycles to prevent infinite loop