Git add src

This commit is contained in:
Curt Spark 2025-12-06 03:53:51 +00:00
parent f84ee341a4
commit 520561dade
5 changed files with 336 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

16
Cargo.lock generated Normal file
View File

@ -0,0 +1,16 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "bitflags"
version = "2.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
[[package]]
name = "overture_cpu_emulator"
version = "0.1.0"
dependencies = [
"bitflags",
]

7
Cargo.toml Normal file
View File

@ -0,0 +1,7 @@
[package]
name = "overture_cpu_emulator"
version = "0.1.0"
edition = "2024"
[dependencies]
bitflags = "2.10.0"

2
Makefile Normal file
View File

@ -0,0 +1,2 @@
run:
cargo run

310
src/main.rs Normal file
View File

@ -0,0 +1,310 @@
use std::{thread, time, io, io::Read};
use bitflags::bitflags;
bitflags! {
struct Instruction: u8 {
const immediate = 0b00111111;
const left_args = 0b00111000;
const right_args = 0b00000111;
const mode = 0b11000000;
}
}
enum Register {
R0,
R1,
R2,
R3,
R4,
R5,
IO,
}
impl From<u8> for Register {
fn from(value: u8) -> Self {
match value {
0 => Self::R0,
1 => Self::R1,
2 => Self::R2,
3 => Self::R3,
4 => Self::R4,
5 => Self::R5,
6 => Self::IO,
_ => Self::R0,
}
}
}
enum CalculateOperation {
OR,
NAND,
NOR,
AND,
ADD,
SUB,
}
impl From<u8> for CalculateOperation {
fn from(value: u8) -> Self {
match value {
0 => Self::OR,
1 => Self::NAND,
2 => Self::NOR,
3 => Self::AND,
4 => Self::ADD,
5 => Self::SUB,
_ => Self::OR,
}
}
}
enum ConditionOperation {
NEVER,
EQZ,
LTZ,
LTEQZ,
ALWAYS,
NEQZ,
GTEQZ,
GTZ,
}
impl From<u8> for ConditionOperation {
fn from(value: u8) -> Self {
match value {
0 => Self::NEVER,
1 => Self::EQZ,
2 => Self::LTZ,
3 => Self::LTEQZ,
4 => Self::ALWAYS,
5 => Self::NEQZ,
6 => Self::GTEQZ,
7 => Self::GTZ,
_ => Self::NEVER,
}
}
}
enum DecodedInstruction {
Immediate (u8),
Calculate (CalculateOperation),
Copy (Register, Register),
Condition (ConditionOperation),
}
struct Overture<'a> {
rom: &'a [u8],
current_instruction: &'a u8,
program_counter: u8,
clock_rate_duration: time::Duration,
step_mode: bool,
r0: u8,
r1: u8,
r2: u8,
r3: u8,
r4: u8,
r5: u8,
io: u8,
input_enable: bool,
output_enable: bool,
}
impl<'a> Overture<'a> {
pub fn new(rom: &'a [u8], clock_rate_hertz: u32, step_mode: bool) -> Self {
Overture {
rom: rom,
current_instruction: &rom[0],
program_counter: 0x00,
clock_rate_duration: Overture::from_hertz(clock_rate_hertz),
step_mode: step_mode,
r0: 0x00,
r1: 0x00,
r2: 0x00,
r3: 0x00,
r4: 0x00,
r5: 0x00,
io: 0x00,
input_enable: false,
output_enable: false,
}
}
fn start(&mut self) {
let mut io_stdin = io::stdin();
loop {
self.program_counter = match self.program_counter.checked_add(1) {
Some(new) => new,
None => break
};
self.current_instruction = match self.rom.get(usize::from(self.program_counter - 1)) {
Some(instruction) => instruction,
None => break
};
self.input_enable = false;
self.output_enable = false;
// Decode Instruction
let decoded_instruction: DecodedInstruction = match self.get_instruction_operand(Instruction::mode) {
0b0000_0000 => DecodedInstruction::Immediate(
self.get_instruction_operand(Instruction::immediate)
),
0b0100_0000 => DecodedInstruction::Calculate(
self.get_instruction_operand(Instruction::right_args).into()
),
0b1000_0000 => DecodedInstruction::Copy(
(self.get_instruction_operand(Instruction::left_args) >> 3).into(),
self.get_instruction_operand(Instruction::right_args).into()
),
0b1100_0000 => DecodedInstruction::Condition(
self.get_instruction_operand(Instruction::right_args).into()
),
_ => DecodedInstruction::Immediate(
self.get_instruction_operand(Instruction::immediate)
),
};
// Execute Instruction
match decoded_instruction {
DecodedInstruction::Immediate(value) => {
self.r0 = value;
}
DecodedInstruction::Calculate(operation) => {
match operation {
CalculateOperation::OR => self.r3 = self.r1 | self.r2,
CalculateOperation::NAND => self.r3 = !(self.r1 & self.r2),
CalculateOperation::NOR => self.r3 = !(self.r1 | self.r2),
CalculateOperation::AND => self.r3 = self.r1 & self.r2,
CalculateOperation::ADD => self.r3 = self.r1 + self.r2,
CalculateOperation::SUB => self.r3 = self.r1 - self.r2,
}
}
DecodedInstruction::Copy(source, destination) => {
let multiplexed_source = match source {
Register::R0 => self.r0,
Register::R1 => self.r1,
Register::R2 => self.r2,
Register::R3 => self.r3,
Register::R4 => self.r4,
Register::R5 => self.r5,
Register::IO => {
self.input_enable = true;
self.io
}
};
match destination {
Register::R0 => self.r0 = multiplexed_source,
Register::R1 => self.r1 = multiplexed_source,
Register::R2 => self.r2 = multiplexed_source,
Register::R3 => self.r3 = multiplexed_source,
Register::R4 => self.r4 = multiplexed_source,
Register::R5 => self.r5 = multiplexed_source,
Register::IO => self.io = {
self.output_enable = true;
multiplexed_source
}
};
}
DecodedInstruction::Condition(operation) => {
match operation {
ConditionOperation::NEVER => {}
ConditionOperation::EQZ => {
if self.r3 == 0 {
self.program_counter = self.r0
}
}
ConditionOperation::LTZ => {
if self.r3 < 0 {
self.program_counter = self.r0
}
}
ConditionOperation::LTEQZ => {
if self.r3 <= 0 {
self.program_counter = self.r0
}
}
ConditionOperation::ALWAYS => {
self.program_counter = self.r0
}
ConditionOperation::NEQZ => {
if self.r3 != 0 {
self.program_counter = self.r0
}
}
ConditionOperation::GTEQZ => {
if self.r3 >= 0 {
self.program_counter = self.r0
}
}
ConditionOperation::GTZ => {
if self.r3 > 0 {
self.program_counter = self.r0
}
}
}
}
}
self.print_diagnostics();
if self.step_mode {
match io_stdin.read(&mut [0]) {
Ok(_) => continue,
Err(_) => break
}
} else {
thread::sleep(self.clock_rate_duration);
}
}
}
fn print_diagnostics(&self) {
println!("");
println!("Program counter: {:x} ({})", self.program_counter, self.program_counter);
println!("Current instruction: {:x} ({})", self.current_instruction, self.current_instruction);
println!("r0: {:x} ({})", self.r0, self.r0);
println!("r1: {:x} ({})", self.r1, self.r1);
println!("r2: {:x} ({})", self.r2, self.r2);
println!("r3: {:x} ({})", self.r3, self.r3);
println!("r4: {:x} ({})", self.r4, self.r4);
println!("r5: {:x} ({})", self.r5, self.r5);
println!("io: {:x} ({})", self.io, self.io);
println!("input: {}", self.input_enable);
println!("output: {}", self.output_enable);
}
fn from_hertz(hertz: u32) -> time::Duration {
let second = time::Duration::from_secs(1);
match second.checked_div(hertz) {
Some(hertz) => hertz,
None => second
}
}
fn get_instruction_operand(&self, operand_type: Instruction) -> u8 {
self.current_instruction & operand_type.bits()
}
}
fn main() {
let rom: [u8; _] = [
0x3f, // immediate 63
0x81, // mov r0 r1
0x07, // immediate 7
0x82, // mov r0 r2
0x44, // add
0x9e, // mov r3 out
];
let mut cpu = Overture::new(
&rom,
4,
false
);
cpu.start();
}