summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/luma.rs14
-rw-r--r--src/luma/application.rs2
-rw-r--r--src/luma/application/decode.rs22
-rw-r--r--src/luma/application/drop.rs4
-rw-r--r--src/luma/application/end.rs17
-rw-r--r--src/luma/application/initialise.rs2
-rw-r--r--src/luma/application/log.rs30
-rw-r--r--src/luma/application/run.rs6
-rw-r--r--src/luma/application/trap.rs41
-rw-r--r--src/luma/configuration.rs1
-rw-r--r--src/luma/configuration/create.rs28
-rw-r--r--src/luma/configuration/load.rs108
-rw-r--r--src/luma/configuration/path.rs2
13 files changed, 133 insertions, 144 deletions
diff --git a/src/luma.rs b/src/luma.rs
index 88eb255..222e97e 100644
--- a/src/luma.rs
+++ b/src/luma.rs
@@ -10,9 +10,21 @@ pub struct VersionType<T> {
pub const VERSION: VersionType::<u32> = VersionType::<u32> {
major: 0x0,
- minor: 0x23,
+ minor: 0x24,
};
+#[allow(dead_code)]
+pub enum LogType {
+ Branch( i32, u32),
+ Continue( u32),
+ Link( u32),
+ Load( u8, u32),
+ MoveRegister( u8, u8),
+ MoveImmediate(u8, u32),
+ Store( u32, u8),
+}
+
+#[allow(dead_code)]
pub enum TrapKind {
BadAlignment( u32, u32),
InvalidOpcode(u32, u32),
diff --git a/src/luma/application.rs b/src/luma/application.rs
index efb4beb..4c34c9d 100644
--- a/src/luma/application.rs
+++ b/src/luma/application.rs
@@ -11,10 +11,10 @@ use std::sync::atomic::AtomicBool;
pub mod bootloader;
pub mod decode;
pub mod drop;
-pub mod end;
pub mod image;
pub mod initialise;
pub mod load;
+pub mod log;
pub mod read;
pub mod run;
pub mod trap;
diff --git a/src/luma/application/decode.rs b/src/luma/application/decode.rs
index fb57e44..bfb7765 100644
--- a/src/luma/application/decode.rs
+++ b/src/luma/application/decode.rs
@@ -1,7 +1,7 @@
// Copyright 2021-2023 Gabriel Jensen.
use crate::luma::application::Application;
-use crate::luma::TrapKind;
+use crate::luma::{LogType, TrapKind};
impl Application {
pub fn decode(&mut self, opcode: u32) {
@@ -21,25 +21,25 @@ impl Application {
0b11000000000000000000000000000 => self.psr & 0b01000000000000000000000000000000 == 0x00 && self.psr & 0b00010000000000000000000000000000 >> 0x1C == self.psr & 0b10000000000000000000000000000000 >> 0x1F,
0b11010000000000000000000000000 => self.psr & 0b01000000000000000000000000000000 != 0x00 || self.psr & 0b00010000000000000000000000000000 >> 0x1C != self.psr & 0b10000000000000000000000000000000 >> 0x1F,
0b11100000000000000000000000000 => true,
- _ => { self.trap(TrapKind::InvalidOpcode(self.registers[0xF] - 0x8, opcode)); false },
+ _ => return self.trap(TrapKind::InvalidOpcode(self.registers[0xF] - 0x8, opcode)),
};
if !condition { return }
if opcode & 0b00001110000000000000000000000000 == 0b00001010000000000000000000000000 {
- let off = opcode & 0b00000000111111111111111111111111; // Offset from pc.
- let inv = !(opcode - 0x1) & 0b00000000111111111111111111111111; // Inverted offset.
-
- if opcode & 0b00000001000000000000000000000000 != 0x0 {
+ if opcode & 0b00000001000000000000000000000000 != 0x0 { // Check the L flag.
self.registers[0xE] = self.registers[0xF] - 0x4;
- eprintln!("link: lr => {}", self.registers[0xE]);
+
+ self.log(LogType::Link(self.registers[0xE]));
}
- self.registers[0xF] = match (off & 0b00000000100000000000000000000000) != 0x0 { // If negative...
- false => self.registers[0xF] + off * 0x4 + 0x8,
- true => self.registers[0xF] - inv * 0x4 + 0x8,
+ let offset = match opcode & 0b00000000100000000000000000000000 != 0x0 {
+ false => (opcode & 0b00000000111111111111111111111111) as i32,
+ true => 0x0 - (!(opcode - 0x1) & 0b00000000111111111111111111111111) as i32, // Inverted (absolute) offset.
};
- eprintln!("branch: {off:024b} => {:08X}", self.registers[0xF] - 0x8);
+ (self.registers[0xF], _) = self.registers[0xF].overflowing_add_signed(offset * 0x4 + 0x8);
+
+ self.log(LogType::Branch(offset, self.registers[0xF] - 0x8));
return;
}
diff --git a/src/luma/application/drop.rs b/src/luma/application/drop.rs
index 711e994..5652610 100644
--- a/src/luma/application/drop.rs
+++ b/src/luma/application/drop.rs
@@ -8,8 +8,8 @@ use std::mem::size_of;
impl Drop for Application {
fn drop(&mut self) {
- unsafe { dealloc(self.memory, Layout::new::<[u32; MEMORY_SIZE / size_of::<u32>()]>()) };
+ eprintln!("ending");
- self.end(0x0,None);
+ unsafe { dealloc(self.memory, Layout::new::<[u32; MEMORY_SIZE / size_of::<u32>()]>()) };
}
}
diff --git a/src/luma/application/end.rs b/src/luma/application/end.rs
deleted file mode 100644
index 4e6f4fa..0000000
--- a/src/luma/application/end.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2021-2023 Gabriel Jensen.
-
-use crate::luma::application::Application;
-
-use std::process::exit;
-
-impl Application {
- pub fn end(&mut self, cod: u8, msg: Option<&str>) {
- if cod != 0x0 {
- eprintln!("error: {}", msg.unwrap());
- }
-
- eprintln!("ending");
-
- exit(cod as i32);
- }
-}
diff --git a/src/luma/application/initialise.rs b/src/luma/application/initialise.rs
index 67b0133..4777e51 100644
--- a/src/luma/application/initialise.rs
+++ b/src/luma/application/initialise.rs
@@ -37,7 +37,7 @@ impl Application {
let memory = unsafe { alloc_zeroed(Layout::new::<[u32; MEMORY_SIZE / size_of::<u32>()]>()) };
if memory.is_null() { panic!("unable to allocate memory buffer") }
- eprintln!("allocated memory buffer at 0x{:0X}", memory as usize);
+ eprintln!("allocated memory buffer at {:#0X}", memory as usize);
return Application {
configuration: configuration.clone(),
diff --git a/src/luma/application/log.rs b/src/luma/application/log.rs
new file mode 100644
index 0000000..4e0eb88
--- /dev/null
+++ b/src/luma/application/log.rs
@@ -0,0 +1,30 @@
+// Copyright 2021-2023 Gabriel Jensen.
+
+use crate::luma::LogType;
+use crate::luma::application::Application;
+
+impl Application {
+ pub fn log(&mut self, log_type: LogType) {
+ let type_string = match log_type {
+ LogType::Branch( _, _) => "branch ",
+ LogType::Continue( _) => "continue",
+ LogType::Link( _) => "link ",
+ LogType::Load( _, _) => "load ",
+ LogType::MoveRegister( _, _) => "move ",
+ LogType::MoveImmediate(_, _) => "move ",
+ LogType::Store( _, _) => "store ",
+ };
+
+ let message = match log_type {
+ LogType::Branch( offset, address) => format!("pc{offset:+} => {address:#010X}"),
+ LogType::Continue( address) => format!("pc => {address:#010X}"),
+ LogType::Link( address) => format!("lr => {address:#010X}"),
+ LogType::Load( register, address) => format!("r{register} => {address:#010X}"),
+ LogType::MoveRegister( destination, source) => format!("r{destination} => r{source}"),
+ LogType::MoveImmediate(register, immediate) => format!("r{register} => {immediate:#X}"),
+ LogType::Store( address, register) => format!("{address:#010X} => r{register}"),
+ };
+
+ eprintln!("{type_string} : {message}");
+ }
+}
diff --git a/src/luma/application/run.rs b/src/luma/application/run.rs
index 59f2144..8f7368a 100644
--- a/src/luma/application/run.rs
+++ b/src/luma/application/run.rs
@@ -1,6 +1,6 @@
// Copyright 2021-2023 Gabriel Jensen.
-use crate::luma::VERSION;
+use crate::luma::{LogType, VERSION};
use crate::luma::application::{Application, GOT_SIGNAL};
use sdl2::event::Event;
@@ -19,7 +19,7 @@ impl Application {
let mut event_pump = self.sdl.event_pump().expect("unable to get event pump");
- eprintln!("starting emulation at 0x{:08X}",self.registers[0xF] - 0x8);
+ eprintln!("starting emulation at {:#010X}",self.registers[0xF] - 0x8);
'main_loop: loop {
// Check if we have recieved a signal:
@@ -42,7 +42,7 @@ impl Application {
// Continue:
self.registers[0xF] += 0x4;
- eprintln!("continue: pc => {:08X}", self.registers[0xF]);
+ self.log(LogType::Continue(self.registers[0xF]));
sleep(Duration::from_secs(0x1));
}
diff --git a/src/luma/application/trap.rs b/src/luma/application/trap.rs
index 1d38610..f96ccbc 100644
--- a/src/luma/application/trap.rs
+++ b/src/luma/application/trap.rs
@@ -6,29 +6,28 @@ use crate::luma::application::Application;
impl Application {
pub fn trap(&mut self, kind: TrapKind) {
let message = match kind {
- TrapKind::BadAlignment( address, alignment) => format!("bad alignment of address 0x{address:08X} (should be {alignment}-byte aligned)"),
- TrapKind::InvalidOpcode(address, opcode) => format!("invalid opcode 0x{opcode:08X} at 0x{address:08X}"),
- TrapKind::OutOfBounds( address) => format!("out-of-bounds address 0x{address:08X} (limit is 0x{MEMORY_SIZE:08X})"),
+ TrapKind::BadAlignment( address, alignment) => format!("bad alignment of address {address:#010X} (should be {alignment}-byte aligned)"),
+ TrapKind::InvalidOpcode(address, opcode) => format!("invalid opcode {opcode:#010X} at {address:#010X}"),
+ TrapKind::OutOfBounds( address) => format!("out-of-bounds address {address:#010X} (limit is {MEMORY_SIZE:#010X})"),
};
eprintln!("trap - {message}");
- eprintln!();
- eprintln!("\tr0: {:08X}", self.registers[0x0]);
- eprintln!("\tr1: {:08X}", self.registers[0x1]);
- eprintln!("\tr2: {:08X}", self.registers[0x2]);
- eprintln!("\tr3: {:08X}", self.registers[0x3]);
- eprintln!("\tr4: {:08X}", self.registers[0x4]);
- eprintln!("\tr5: {:08X}", self.registers[0x5]);
- eprintln!("\tr6: {:08X}", self.registers[0x6]);
- eprintln!("\tr7: {:08X}", self.registers[0x7]);
- eprintln!("\tr8: {:08X}", self.registers[0x8]);
- eprintln!("\tr9: {:08X}", self.registers[0x9]);
- eprintln!("\tr10: {:08X}", self.registers[0xA]);
- eprintln!("\tr11: {:08X}", self.registers[0xB]);
- eprintln!("\tr12: {:08X}", self.registers[0xC]);
- eprintln!("\tsp: {:08X}", self.registers[0xD]);
- eprintln!("\tlr: {:08X}", self.registers[0xE]);
- eprintln!("\tpc: {:08X}", self.registers[0xF]);
- eprintln!("\tcpsr: {:032b}", self.psr);
+ eprintln!("\tr0: {:#010X}", self.registers[0x0]);
+ eprintln!("\tr1: {:#010X}", self.registers[0x1]);
+ eprintln!("\tr2: {:#010X}", self.registers[0x2]);
+ eprintln!("\tr3: {:#010X}", self.registers[0x3]);
+ eprintln!("\tr4: {:#010X}", self.registers[0x4]);
+ eprintln!("\tr5: {:#010X}", self.registers[0x5]);
+ eprintln!("\tr6: {:#010X}", self.registers[0x6]);
+ eprintln!("\tr7: {:#010X}", self.registers[0x7]);
+ eprintln!("\tr8: {:#010X}", self.registers[0x8]);
+ eprintln!("\tr9: {:#010X}", self.registers[0x9]);
+ eprintln!("\tr10: {:#010X}", self.registers[0xA]);
+ eprintln!("\tr11: {:#010X}", self.registers[0xB]);
+ eprintln!("\tr12: {:#010X}", self.registers[0xC]);
+ eprintln!("\tsp: {:#010X}", self.registers[0xD]);
+ eprintln!("\tlr: {:#010X}", self.registers[0xE]);
+ eprintln!("\tpc: {:#010X}", self.registers[0xF]);
+ eprintln!("\tcpsr: {:#034b}", self.psr);
}
}
diff --git a/src/luma/configuration.rs b/src/luma/configuration.rs
index 045e897..efad017 100644
--- a/src/luma/configuration.rs
+++ b/src/luma/configuration.rs
@@ -1,6 +1,5 @@
// Copyright 2021-2023 Gabriel Jensen.
-pub mod create;
pub mod load;
pub mod new;
pub mod overwrite;
diff --git a/src/luma/configuration/create.rs b/src/luma/configuration/create.rs
deleted file mode 100644
index b5f2312..0000000
--- a/src/luma/configuration/create.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2021-2023 Gabriel Jensen.
-
-use crate::luma::CONFIGURATION_VERSION;
-use crate::luma::configuration::Configuration;
-
-use std::fs::write;
-
-impl Configuration {
- pub(super) fn create(&mut self) {
- let configuration_path = Configuration::path();
-
- eprintln!("creating configuration at {configuration_path}");
-
- let default_configuration = format!(
- "[luma]\n\
- version = {CONFIGURATION_VERSION}\n\
- \n\
- [device]\n\
- #bootloader = \n\
- #image = \n\
- \n\
- [video]\n\
- scale = 1\n"
- );
-
- write(configuration_path, default_configuration).unwrap();
- }
-}
diff --git a/src/luma/configuration/load.rs b/src/luma/configuration/load.rs
index a3fe455..fd425d4 100644
--- a/src/luma/configuration/load.rs
+++ b/src/luma/configuration/load.rs
@@ -3,8 +3,35 @@
use crate::luma::CONFIGURATION_VERSION;
use crate::luma::configuration::Configuration;
-use configparser::ini::Ini;
+extern crate serde;
+extern crate toml;
+
use std::env::var;
+use std::fs::read_to_string;
+use serde::Deserialize;
+
+#[derive(Deserialize)]
+struct Container {
+ luma: Luma,
+ device: Device,
+ video: Video,
+}
+
+#[derive(Deserialize)]
+struct Luma {
+ version: Option<u32>,
+}
+
+#[derive(Deserialize)]
+struct Device {
+ bootloader: Option<String>,
+ image: Option<String>,
+}
+
+#[derive(Deserialize)]
+struct Video {
+ scale: Option<u32>,
+}
impl Configuration {
pub(super) fn load(&mut self) {
@@ -12,69 +39,36 @@ impl Configuration {
eprintln!("loading configuration \"{configuration_path}\"");
- let mut configuration = Ini::new();
+ let contents = read_to_string(configuration_path).expect("unable to read configuration file");
- match configuration.load(configuration_path) {
- Ok( _) => {},
- Err(_) => {
- eprintln!("unable to read configuration");
+ let configuration: Container = toml::from_str(contents.as_str()).expect("unable to parse configuration file");
- return self.create();
- },
- }
+ let version = configuration.luma.version.expect("missing value 'version' under 'luma'");
+ if version < CONFIGURATION_VERSION { panic!("ancient version: downgrade configuration") }
+ if version > CONFIGURATION_VERSION { panic!("out-of-date version: upgrade configuration") }
- let get_path = |configuration: &mut Ini, section: &str, entry: &str| -> Option<String> {
- match configuration.get(section, entry) {
+ let get_path = |output_path: &mut String, input_path: Option<String>| {
+ match input_path {
Some(path) => {
- if path.chars().nth(0x0).unwrap() != '/' {
- let home_directory = match var("HOME") {
- Ok( path) => path,
- Err(_) => { eprintln!("unable to get home directory"); "".to_string() },
- };
-
- return Some(home_directory + "/" + &path)
- }
-
- return Some(path);
- },
- None => None,
- }
+ *output_path = if path.chars().nth(0x0).unwrap() != '/' {
+ let home_directory = match var("HOME") {
+ Ok( path) => path,
+ Err(_) => { eprintln!("unable to get home directory"); "".to_string() },
+ };
+
+ home_directory + "/" + &path
+ } else { path }
+ },
+ None => {},
+ };
};
- let get_unsigned = |configuration: &mut Ini, section: &str, entry: &str| -> Option<u64> {
- match configuration.getuint(section, entry) {
- Ok( optional) => optional,
- Err(_) => panic!("invalid format of '{entry}' in configuration under '{section}"),
- }
- };
-
- let version = get_unsigned(&mut configuration, "luma", "version").expect("'version' field not defined in configuration under 'luma'") as u32;
-
- if version < CONFIGURATION_VERSION { panic!("out-of-date configuration - please upgrade") };
- if version > CONFIGURATION_VERSION { panic!("future configuration - please downgrade") };
-
- match get_path(&mut configuration, "device", "bootloader") {
- Some(path) => {
- self.bootloader = path;
- },
- None => {},
- }
-
- match get_path(&mut configuration, "device", "image") {
- Some(path) => {
- self.image = path;
- },
- None => {},
- }
-
- match get_unsigned(&mut configuration, "video", "scale") {
- Some(value) => {
- assert!(value >= 0x1);
- assert!(value <= 0xFFFFFFFF);
+ get_path(&mut self.bootloader, configuration.device.bootloader);
+ get_path(&mut self.image, configuration.device.image);
- self.scale = value as u32;
- },
- None => {},
+ if configuration.video.scale.is_some() {
+ self.scale = configuration.video.scale.unwrap();
+ assert!(self.scale >= 0x1);
}
}
}
diff --git a/src/luma/configuration/path.rs b/src/luma/configuration/path.rs
index 0db3d98..a1ff3fd 100644
--- a/src/luma/configuration/path.rs
+++ b/src/luma/configuration/path.rs
@@ -9,6 +9,6 @@ impl Configuration {
return match var("HOME") {
Ok( path) => path,
Err(_) => panic!("unable to get home directory"),
- } + "/.luma.ini";
+ } + "/.luma.toml";
}
}