2 个稳定版本
1.0.1 | 2023年3月31日 |
---|---|
1.0.0 | 2023年3月29日 |
#647 在 嵌入式开发
73KB
1.5K SLoC
Rust 中的 NMOS 6502
另一个 6502 模拟器吗?
是的!但等等,这是你为什么可能想要这个的原因
no_std
兼容- 最小依赖(仅
num_enum
作为操作码的预处理器) - 在 Big Endian 和 Little Endian 环境中均能工作
- 通过了 Klaus2m5 6502 处理器功能测试套件
- 支持
IRQ
和NMI
中断 - 在包括 Mac、PC 和嵌入式 RP2040 在内的各种系统上进行了测试
- 每条指令执行后都会公开准确的周期计数
此实现涵盖了所有标准 NMOS 6502 操作码以及所有 "非法" NOP 等效操作码。未识别的操作码公开用于调试目的,将在以后实现。
快速入门
此库仅是 CPU。在 6502 系统中,CPU 始终负责总线当前地址。基本用法如下
let cpu = Nmos6502::new();
loop {
// "bus" is any struct
// that implements: BusInterface
cpu.tick(&mut bus);
}
CPU 通过 BusInterface
发送和接收数据,该接口由包用户自行实现。在最基本的情况下,实现可以简单地分配一个空的 64k u8
数组,并返回/写入索引值。
BusInterface 必须基本提供
fn get_byte_at(&mut self, addr:u16) -> u8;
fn set_byte_at(&mut self, addr:u16, byte: u8);
更多细节
6502 将使用默认的 RESET 向量 0xFFFC-0xFFFD
。也就是说,BusInterface
为该地址返回的任何值都将被 cpu 设置为程序计数器。
在更复杂的系统中,例如 Apple][ 模拟器,您可能可以实施任何您喜欢的系统,通过 BusInterface
来拦截/分配任何请求到各种子系统。
为了效率/速度,您可以可选地覆盖
fn get_pipelined_bytes(&mut self, addr:u16) -> (u8, u8, u8)
这用于检索当前操作码和下两个字节作为可能的操作数。这仅在您有实际管道这些字节的方法(例如,一个可以在一条指令中发送 24 位 + 单词的系统)或您需要避免可能触发例如软开关的外部内存访问时才有用。默认实现简单地使用 get_byte_at
并在地址上循环增加。
依赖项
~1.5MB
~36K SLoC