first instructiom

This commit is contained in:
Richard 2025-08-25 21:29:13 +02:00
parent 3181d2c80d
commit f74be7dbbf
7 changed files with 689 additions and 20 deletions

245
Cargo.lock generated
View File

@ -1,16 +1,251 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
version = 4
[[package]]
name = "anstream"
version = "0.6.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd"
[[package]]
name = "anstyle-parse"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2"
dependencies = [
"windows-sys",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a"
dependencies = [
"anstyle",
"once_cell_polyfill",
"windows-sys",
]
[[package]]
name = "clap"
version = "4.5.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fc0e74a703892159f5ae7d3aac52c8e6c392f5ae5f359c70b5881d60aaac318"
dependencies = [
"clap_builder",
"clap_derive",
]
[[package]]
name = "clap_builder"
version = "4.5.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3e7f4214277f3c7aa526a59dd3fbe306a370daee1f8b7b8c987069cd8e888a8"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
"strsim",
]
[[package]]
name = "clap_derive"
version = "4.5.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14cb31bb0a7d536caef2639baa7fad459e15c3144efefa6dbd1c84562c4739f6"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675"
[[package]]
name = "colorchoice"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "is_terminal_polyfill"
version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]]
name = "once_cell_polyfill"
version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
[[package]]
name = "proc-macro2"
version = "1.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
dependencies = [
"proc-macro2",
]
[[package]]
name = "strsim"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "syn"
version = "2.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "um"
version = "0.1.0"
dependencies = [
"ux",
"clap",
]
[[package]]
name = "ux"
version = "0.1.6"
name = "unicode-ident"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b59fc5417e036e53226bbebd90196825d358624fd5577432c4e486c95b1b096"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
[[package]]
name = "utf8parse"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "windows-link"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
[[package]]
name = "windows-sys"
version = "0.60.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.53.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91"
dependencies = [
"windows-link",
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
[[package]]
name = "windows_aarch64_msvc"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
[[package]]
name = "windows_i686_gnu"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3"
[[package]]
name = "windows_i686_gnullvm"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
[[package]]
name = "windows_i686_msvc"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
[[package]]
name = "windows_x86_64_gnu"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
[[package]]
name = "windows_x86_64_msvc"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"

View File

@ -4,4 +4,4 @@ version = "0.1.0"
edition = "2021"
[dependencies]
ux = "0.1.6"
clap = { version = "4.5.45", features = [ "derive" ] }

256
data/um.asm Normal file
View File

@ -0,0 +1,256 @@
ORT r5=0x12
CMV r0=r0 if r0
CMV r0=r0 if r0
CMV r0=r0 if r0
CMV r0=r0 if r0
CMV r0=r0 if r0
CMV r0=r0 if r0
CMV r0=r0 if r0
ORT r0=0x100
ORT r2=0x7
ORT r3=0x1ffffff
ADD r4=r3+r7
NAD r3=r1 nand r3
NAD r3=r3 nand r3
DIV r1=r1/r4
NAD r1=r2 nand r1
NAD r1=r1 nand r1
AMD r6[r1]=r3
IDX r1=r6[r0]
ORT r7=0x1
ADD r0=r7+r0
ORT r3=0xff
IDX r3=r6[r3]
DIV r3=r1/r3
ORT r4=0x1c
ADD r4=r4+r3
IDX r4=r6[r4]
LOD r6@r4
CMV r0=r5 if r2
CMV r0=r7 if r1
CMV r1=r3 if r2
CMV r1=r7 if r3
CMV r2=r1 if r1
CMV r2=r2 if r7
CMV r2=r4 if r5
CMV r2=r6 if r3
CMV r2=r6 if r4
CMV r3=r0 if r0
CMV r3=r0 if r5
CMV r3=r1 if r2
CMV r3=r1 if r7
CMV r0=r1 if r2
ORT r7=0x8
DIV r4=r1/r7
DIV r3=r4/r7
NAD r4=r4 nand r2
NAD r4=r4 nand r4
NAD r3=r3 nand r2
NAD r3=r3 nand r3
NAD r7=r1 nand r2
NAD r7=r7 nand r7
IDX r7=r6[r7]
IDX r1=r6[r3]
IDX r4=r6[r4]
CMV r1=r4 if r7
AMD r6[r3]=r1
LOD r6@r5
ORT r3=0x8
DIV r3=r1/r3
NAD r3=r2 nand r3
NAD r3=r3 nand r3
IDX r3=r6[r3]
ORT r4=0x4e
ORT r7=0x42
CMV r7=r4 if r3
LOD r6@r7
NAD r3=r1 nand r2
NAD r3=r3 nand r3
IDX r3=r6[r3]
ORT r7=0x100
ADD r3=r7+r3
IDX r3=r6[r3]
ORT r4=0x40
DIV r4=r1/r4
NAD r4=r2 nand r4
NAD r4=r4 nand r4
AMD r6[r4]=r3
LOD r6@r5
NAD r4=r1 nand r2
NAD r4=r4 nand r4
IDX r4=r6[r4]
ORT r7=0x1
ADD r4=r7+r4
IDX r3=r3[r4]
ORT r4=0x40
DIV r4=r1/r4
NAD r4=r2 nand r4
NAD r4=r4 nand r4
AMD r6[r4]=r3
LOD r6@r5
ORT r3=0x40
DIV r3=r1/r3
NAD r3=r2 nand r3
NAD r3=r3 nand r3
IDX r3=r6[r3]
ORT r4=0x6f
ORT r7=0x63
CMV r7=r4 if r3
LOD r6@r7
NAD r3=r1 nand r2
NAD r3=r3 nand r3
IDX r3=r6[r3]
ORT r4=0x8
DIV r4=r1/r4
NAD r4=r2 nand r4
NAD r4=r4 nand r4
IDX r4=r6[r4]
ORT r7=0x100
ADD r4=r7+r4
AMD r6[r4]=r3
LOD r6@r5
ORT r4=0x8
DIV r4=r1/r4
NAD r4=r2 nand r4
NAD r4=r4 nand r4
IDX r4=r6[r4]
ORT r7=0x1
ADD r4=r7+r4
NAD r7=r1 nand r2
NAD r7=r7 nand r7
IDX r7=r6[r7]
AMD r3[r4]=r7
LOD r6@r5
ORT r7=0x8
DIV r4=r1/r7
DIV r3=r4/r7
NAD r4=r4 nand r2
NAD r4=r4 nand r4
NAD r3=r3 nand r2
NAD r3=r3 nand r3
IDX r4=r6[r4]
NAD r7=r1 nand r2
NAD r7=r7 nand r7
IDX r7=r6[r7]
ADD r4=r4+r7
AMD r6[r3]=r4
LOD r6@r5
ORT r7=0x8
DIV r4=r1/r7
DIV r3=r4/r7
NAD r4=r4 nand r2
NAD r4=r4 nand r4
NAD r3=r3 nand r2
NAD r3=r3 nand r3
IDX r4=r6[r4]
NAD r7=r1 nand r2
NAD r7=r7 nand r7
IDX r7=r6[r7]
MUL r4=r4*r7
AMD r6[r3]=r4
LOD r6@r5
ORT r7=0x8
DIV r4=r1/r7
DIV r3=r4/r7
NAD r4=r4 nand r2
NAD r4=r4 nand r4
NAD r3=r3 nand r2
NAD r3=r3 nand r3
IDX r4=r6[r4]
NAD r7=r1 nand r2
NAD r7=r7 nand r7
IDX r7=r6[r7]
DIV r4=r4/r7
AMD r6[r3]=r4
LOD r6@r5
ORT r7=0x8
DIV r4=r1/r7
DIV r3=r4/r7
NAD r4=r4 nand r2
NAD r4=r4 nand r4
NAD r3=r3 nand r2
NAD r3=r3 nand r3
IDX r4=r6[r4]
NAD r7=r1 nand r2
NAD r7=r7 nand r7
IDX r7=r6[r7]
NAD r4=r4 nand r7
AMD r6[r3]=r4
LOD r6@r5
HLT
NAD r3=r1 nand r2
NAD r3=r3 nand r3
IDX r3=r6[r3]
ADD r7=r7+r3
ALC r4 r7
AMD r4[r6]=r3
ORT r3=0x8
DIV r3=r1/r3
NAD r3=r2 nand r3
NAD r3=r3 nand r3
AMD r6[r3]=r4
LOD r6@r5
NAD r3=r1 nand r2
NAD r3=r3 nand r3
IDX r3=r6[r3]
ABN r3
LOD r6@r5
NAD r4=r1 nand r2
NAD r4=r4 nand r4
IDX r4=r6[r4]
OUT r4
LOD r6@r5
INP r4
NAD r3=r1 nand r2
NAD r3=r3 nand r3
AMD r6[r3]=r4
LOD r6@r5
ORT r4=0x8
DIV r4=r1/r4
NAD r4=r2 nand r4
NAD r4=r4 nand r4
IDX r4=r6[r4]
ORT r0=0xde
ORT r3=0xd8
CMV r3=r0 if r4
LOD r6@r3
NAD r0=r1 nand r2
NAD r0=r0 nand r0
IDX r0=r6[r0]
ORT r7=0x100
ADD r0=r0+r7
LOD r6@r5
ORT r2=0x100
IDX r5=r4[r6]
ADD r3=r5+r2
ALC r3 r3
ORT r0=0xec
ORT r7=0xe6
CMV r0=r7 if r2
LOD r6@r0
NAD r7=r6 nand r6
ADD r2=r7+r2
IDX r0=r6[r2]
AMD r3[r2]=r0
ORT r0=0xe2
LOD r6@r0
ORT r0=0xf8
ORT r2=0xf0
CMV r0=r2 if r5
LOD r6@r0
IDX r0=r4[r5]
NAD r7=r6 nand r6
ADD r5=r7+r5
ORT r7=0x100
ADD r7=r5+r7
AMD r3[r7]=r0
ORT r0=0xec
LOD r6@r0
ORT r2=0x7
NAD r0=r1 nand r2
NAD r0=r0 nand r0
IDX r0=r6[r0]
ADD r0=r0+r7
ORT r5=0x12
LOD r3@r5
IDX r0=r0[r0]

56
src/bin/um.rs Normal file
View File

@ -0,0 +1,56 @@
extern crate um;
use um::cpu::{Cpu};
use std::io;
use std::io::prelude::*;
use std::fs::File;
use std::vec::Vec;
use clap::Parser;
/// Run a um program
#[derive(Parser)]
struct Cli {
/// The path to the program to load
program: std::path::PathBuf,
}
fn main() -> io::Result<()> {
let args = Cli::parse();
let mut pgm = Vec::new();
let mut f = File::open(args.program)?;
let mut cont = true;
while cont {
let mut buffer = [0u8; 4];
cont = match f.read(&mut buffer) {
Ok(4) => {
let num = u32::from_be_bytes(
buffer.try_into().unwrap());
pgm.push(num);
true
},
Ok(_) => false,
Err(_) => false,
};
}
let mut c = Cpu::new(pgm);
cont = true;
println!("start\n{}", c.state());
while cont {
let r = c.step();
cont = match r {
Ok(_) => {
println!("ok\n{}", c.state());
true
},
Err(e) => {
println!("Error {:?}", e);
false
}
};
}
Ok(())
}

124
src/cpu.rs Normal file
View File

@ -0,0 +1,124 @@
use std::collections::HashMap;
use std::vec::Vec;
use crate::instruction::{Instruction, NormalInstruction, SpecialInstruction};
#[derive(Debug)]
pub enum CpuError {
ProgramEnd,
InvalidInstruction,
UnexpectedInput
}
#[derive(Debug)]
pub struct Cpu {
reg: [u32; 8],
arr: HashMap<u32, Vec<u32>>,
finger: u32,
out: Option<u8>,
in_reg: Option<u8>
}
impl Cpu {
pub fn new(pgm: Vec<u32>) -> Cpu {
let mut arrays = HashMap::new();
arrays.insert(0, pgm);
Cpu {
reg: [0;8],
arr: arrays,
finger: 0,
in_reg: None,
out: None
}
}
fn ins(&self) -> Result<Instruction,CpuError> {
if self.finger as usize >= self.arr[&0].len() {
return Err(CpuError::ProgramEnd);
}
let d = self.arr[&0][self.finger as usize];
if let Ok(i) = Instruction::parse(d) {
Ok(i)
} else {
Err(CpuError::InvalidInstruction)
}
}
pub fn output(&self) -> Option<u8> {
self.out
}
pub fn expecting_input(&self) -> bool {
match self.in_reg {
None => false,
Some(_) => true
}
}
pub fn set_in(&mut self, value: u8) -> Result<(), CpuError> {
match self.in_reg {
None => Err(CpuError::UnexpectedInput),
Some(i) => {
self.reg[i as usize] = value as u32;
Ok(())
}
}
}
pub fn state(&self) -> String {
let istr = match self.ins() {
Ok(i) => i.fmt(),
Err(e) => format!("{:?}", e)
};
format!("CPU Reg {:?}\nCPU Finger {}\nCPU Ins {}", self.reg, self.finger, istr)
}
fn handle_ortho(&mut self, i:SpecialInstruction) -> Result<(), CpuError>{
self.reg[i.a as usize] = i.v as u32;
Ok(())
}
fn exec(&mut self, instruction: Instruction)-> Result<(), CpuError>{
println!("{:?}", instruction);
match instruction {
Instruction::Ortho(i) => self.handle_ortho(i),
_ => Err(CpuError::InvalidInstruction)
}
}
pub fn step(&mut self) -> Result<(), CpuError>{
self.out = None;
self.in_reg = None;
let i = self.ins()?;
self.exec(i)?;
self.finger += 1;
Ok(())
}
}
#[cfg(test)]
mod tests{
use super::*;
fn ezop(op:u32, a:u32, b:u32, c:u32) -> u32 {
match op {
13 => (op & 0xf) << 28 | (a & 7) << 25 | (b & 0x1ffffff),
_ => (op & 0xf) << 28 | (a & 7) << 6 | (b & 7) << 3 | (c & 7)
}
}
#[test]
fn test_ortho() -> Result<(), String> {
let pgm = vec!(ezop(13, 3, 1337, 0));
let mut c = Cpu::new(pgm);
let result = c.step();
assert!(matches!(result, Ok(_)));
assert_eq!(c.reg[0], 0);
assert_eq!(c.reg[3], 1337);
Ok(())
}
}

View File

@ -1,19 +1,16 @@
use ux::{u3, u25};
pub struct ParsingError;
#[derive(Debug)]
pub struct NormalInstruction {
pub a: u3,
pub b: u3,
pub c: u3
pub a: u8,
pub b: u8,
pub c: u8
}
#[derive(Debug)]
pub struct SpecialInstruction {
pub a: u3,
pub v: u25
pub a: u8,
pub v: u32
}
#[derive(Debug)]
@ -34,8 +31,8 @@ pub enum Instruction {
Ortho(SpecialInstruction)
}
const fn u3at(d: u32, pos: u8) -> u3 {
u3::new(((d >> pos) & 7) as u8)
const fn u3at(d: u32, pos: u8) -> u8 {
((d >> pos) & 7) as u8
}
impl Instruction {
@ -49,21 +46,21 @@ a, i.b, i.c),
Instruction::Multiply(i) => format!("MUL r{}=r{}*r{}", i.a, i.b, i.c),
Instruction::Divide(i) => format!("DIV r{}=r{}/r{}", i.a, i.b, i.c),
Instruction::NotAnd(i) => format!("NAD r{}=r{} nand r{}", i.a, i.b, i.c),
Instruction::Halt(i) => format!("HLT"),
Instruction::Halt(_i) => format!("HLT"),
Instruction::Allocate(i) => format!("ALC r{} r{}", i.b, i.c),
Instruction::Abandon(i) => format!("ABN r{}", i.c),
Instruction::Output(i) => format!("OUT r{}", i.c),
Instruction::Input(i) => format!("INP r{}", i.c),
Instruction::Load(i) => format!("LOD r{}@r{}", i.b, i.c),
Instruction::Ortho(i) => format!("ORT r{}={}", i.a, i.v)
Instruction::Ortho(i) => format!("ORT r{}=0x{:x}", i.a, i.v)
}
}
pub const fn parse(d: u32) -> Result<Instruction, ParsingError> {
let itype = d >> 28;
let (a, b, c, v) = match itype {
13 => (u3at(d, 25), u3::new(0), u3::new(0), u25::new(d & 0x1ffffff)),
_ => (u3at(d, 6), u3at(d, 3), u3at(d, 0), u25::new(0))
13 => (u3at(d, 25), 0, 0, d & 0x1ffffff),
_ => (u3at(d, 6), u3at(d, 3), u3at(d, 0), 0)
};
match itype {
0 => Ok(Instruction::ConditionalMove(NormalInstruction{a: a, b: b, c: c})),

View File

@ -1 +1,2 @@
pub mod instruction;
pub mod cpu;