assembler
This commit is contained in:
parent
63f3139c75
commit
a7402461e8
5 changed files with 137 additions and 14 deletions
47
Cargo.lock
generated
47
Cargo.lock
generated
|
@ -2,6 +2,53 @@
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aho-corasick"
|
||||||
|
version = "1.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.7.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex"
|
||||||
|
version = "1.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-automata",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-automata"
|
||||||
|
version = "0.4.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-syntax"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sysforge"
|
name = "sysforge"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"regex",
|
||||||
|
]
|
||||||
|
|
|
@ -4,3 +4,4 @@ version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
regex = "1.11.1"
|
||||||
|
|
58
src/assembler.rs
Normal file
58
src/assembler.rs
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
use regex::Regex;
|
||||||
|
use std::{collections::HashMap, str::FromStr};
|
||||||
|
|
||||||
|
pub struct Opcode<T: Clone + ToString + FromStr> {
|
||||||
|
pub key: String,
|
||||||
|
pub value: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Clone + ToString + FromStr> Opcode<T> {
|
||||||
|
pub fn create(key: &str, value: T) -> Opcode<T> {
|
||||||
|
return Opcode {
|
||||||
|
key: key.to_string(),
|
||||||
|
value: value,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Assembler<T: Clone + ToString + FromStr> {
|
||||||
|
opcodes: Vec<Opcode<T>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Clone + ToString + FromStr> Assembler<T> {
|
||||||
|
pub fn create(opcodes: Vec<Opcode<T>>) -> Assembler<T> {
|
||||||
|
return Assembler { opcodes: opcodes };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn assemble(&mut self, source: &mut String) -> Vec<T> {
|
||||||
|
let mut map: HashMap<String, T> = HashMap::new();
|
||||||
|
|
||||||
|
for opcode in &self.opcodes {
|
||||||
|
map.insert(opcode.key.clone(), opcode.value.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
return Regex::new(r"[\s]+") // create regex
|
||||||
|
.unwrap()
|
||||||
|
.split(source) // split by regex
|
||||||
|
.filter(|s: &&str| !s.is_empty()) // remove empty entries
|
||||||
|
.map(|s| match map.get(&s.to_lowercase()) {
|
||||||
|
Some(opcode) => opcode.to_string(),
|
||||||
|
None => s.to_string(),
|
||||||
|
}) // converts opcode strings to numbers
|
||||||
|
.filter_map(|s| {
|
||||||
|
if s.starts_with("0x") {
|
||||||
|
// converts hexadecimals to decimal, then parses them
|
||||||
|
u128::from_str_radix(&s[2..], 16)
|
||||||
|
.ok()
|
||||||
|
.unwrap()
|
||||||
|
.to_string()
|
||||||
|
.parse::<T>()
|
||||||
|
.ok()
|
||||||
|
} else {
|
||||||
|
// parses all other decimals
|
||||||
|
s.parse::<T>().ok()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,7 +12,7 @@ pub struct ExampleCPU {
|
||||||
|
|
||||||
impl ExampleCPU {
|
impl ExampleCPU {
|
||||||
// Here is where you can create your own CPU Instance.
|
// Here is where you can create your own CPU Instance.
|
||||||
pub fn create_instance(debug: bool, initial_state: [u8; 256]) -> ExampleCPU {
|
pub fn create(debug: bool, initial_state: [u8; 256]) -> ExampleCPU {
|
||||||
return ExampleCPU {
|
return ExampleCPU {
|
||||||
debug: debug,
|
debug: debug,
|
||||||
execution_pointer: 0,
|
execution_pointer: 0,
|
||||||
|
@ -22,8 +22,14 @@ impl ExampleCPU {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn start(&mut self) {
|
||||||
|
loop {
|
||||||
|
self.fetch_and_decode()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// This fetches the operands, based on the position of the execution_pointer, then runs the selected instruction.
|
// This fetches the operands, based on the position of the execution_pointer, then runs the selected instruction.
|
||||||
pub fn fetch_and_decode(&mut self) {
|
fn fetch_and_decode(&mut self) {
|
||||||
self.operands[0] = self.ram[self.execution_pointer as usize];
|
self.operands[0] = self.ram[self.execution_pointer as usize];
|
||||||
self.operands[1] = self.ram[(self.execution_pointer + 1) as usize];
|
self.operands[1] = self.ram[(self.execution_pointer + 1) as usize];
|
||||||
self.operands[2] = self.ram[(self.execution_pointer + 2) as usize];
|
self.operands[2] = self.ram[(self.execution_pointer + 2) as usize];
|
||||||
|
@ -34,13 +40,13 @@ impl ExampleCPU {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
match self.operands[0] {
|
match self.operands[0] {
|
||||||
0x00 => self.nop(),
|
0 => self.nop(),
|
||||||
0x01 => self.load(),
|
1 => self.load(),
|
||||||
0x02 => self.store(),
|
2 => self.store(),
|
||||||
0x03 => self.add(),
|
3 => self.add(),
|
||||||
0x04 => self.sub(),
|
4 => self.sub(),
|
||||||
0x05 => self.jump(),
|
5 => self.jump(),
|
||||||
0x06 => self.jpiz(),
|
6 => self.jpiz(),
|
||||||
_ => self.nop(),
|
_ => self.nop(),
|
||||||
};
|
};
|
||||||
}
|
}
|
21
src/main.rs
21
src/main.rs
|
@ -1,12 +1,23 @@
|
||||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
// Copyright (c) 2024 Patrick_Pluto
|
// Copyright (c) 2024 Patrick_Pluto
|
||||||
|
|
||||||
mod devices;
|
mod assembler;
|
||||||
|
mod cpu;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut instance: devices::ExampleCPU = devices::ExampleCPU::create_instance(true, [0; 256]);
|
let mut assembler: assembler::Assembler<u8> = assembler::Assembler::create(vec![
|
||||||
|
assembler::Opcode::create("nop", 0),
|
||||||
|
assembler::Opcode::create("load", 1),
|
||||||
|
assembler::Opcode::create("store", 2),
|
||||||
|
assembler::Opcode::create("add", 3),
|
||||||
|
assembler::Opcode::create("sub", 4),
|
||||||
|
assembler::Opcode::create("jump", 5),
|
||||||
|
assembler::Opcode::create("jpiz", 6),
|
||||||
|
]);
|
||||||
|
|
||||||
|
let final_result: Vec<u8> = assembler.assemble(&mut "nop 0x00 0x22".to_string());
|
||||||
|
dbg!(final_result);
|
||||||
|
// let mut instance: cpu::ExampleCPU = cpu::ExampleCPU::create_instance(true, [0; 256]);
|
||||||
// change the instructions here
|
// change the instructions here
|
||||||
loop {
|
// instance.start_emulation();
|
||||||
instance.fetch_and_decode();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue