baby_emulator/lib.rs
1//! # Manchester Small-Scale Experimental Machine "Baby" Emulator Library
2//!
3//! [](https://crates.io/crates/baby-emulator)
4//! [](https://docs.rs/baby-emulator)
5//! [](./LICENCE)
6//!
7//! This library provides a collections of types and methods for emulating & assembling code for
8//! the [Machester Baby](https://www.scienceandindustrymuseum.org.uk/objects-and-stories/baby-and-modern-computing), the first program stored
9//! computer.
10//!
11//! ## Explaination
12//!
13//! The Manchester "Baby" was the first computer to store both its program
14//! code and data in a common randomly-accessible memory, it is for this
15//! reason the Baby is considered the first machine to run "true" software,
16//! providing a familiar (abeit, primitive) programming environment to anyone
17//! familiar with assembly, this library can be included in a variety of
18//! software and platforms allowing emulation functionality of this historic machine.
19//!
20//! This library provides an interface for emulating the Baby as a bytecode
21//! interpreter ([baby_emulator::core][crate::core]), and also a library for assembling
22//! asm using both modern and original asm notations into a format that
23//! can be ran by the emulator ([baby_emulator::assmebler][crate::assembler]).
24//!
25//! Please log any questions or issues to the [GitHub repo](https://github.com/jasonalexander-ja/SSEMBabyEmulator).
26//!
27//! ## Installation
28//!
29//! Command line:
30//! ```bash
31//! cargo add baby-emulator
32//! ```
33//!
34//! Cargo.toml:
35//! ```toml
36//! baby-emulator = "0.2.2"
37//! ```
38//!
39//! ### Features
40//!
41//! As of version 2.1, variable bit lengths are supported on both the simulator and assembler,
42//! by default both work on signed 32 bit integers as per the original machine, and `i16` and `i8` are
43//! available by importing the library the correspondingly named feature.
44//!
45//! ```toml
46//! baby-emulator = { version = "0.2.2", features = ["i16"] }
47//! baby-emulator = { version = "0.2.2", features = ["i8"] }
48//! ```
49//!
50//! ## Example
51//!
52//! This shows a few short examples of what this library is capable of, designed to be a
53//! starting point allowing further experimentation by the "user".
54//! See [baby_emulator::core][crate::core] and [baby_emulator::assembler][crate::assembler]
55//! for further examples and info.
56//!
57//! ### Bytecode Interpreter Emulation
58//!
59//! The core of this library is [baby_emulator::core::BabyModel][crate::core::BabyModel],
60//! this struct has fields representing all of the Baby's internal
61//! registers and 32 word memory, you can initialise this struct with
62//! an array of `[WORD; 32]`, this array can contain the program code
63//! instructions starting at position 0.
64//!
65//! This example runs an example program that adds 5 to 5 and stores
66//! the result in the accumulator. Running here is done with the [BabyModel::run_loop][crate::core::BabyModel::run_loop]
67//! method, this method will simply execute sucessive instructions until
68//! either an error is thrown (like a stop instruction), or the number
69//! os iterations exceeds the specified limmit.
70//!
71//! ```rust
72//! use baby_emulator::core::BabyModel;
73//! use baby_emulator::core::errors::BabyErrors;
74//! use baby_emulator::core::errors::BabyError;
75//!
76//! let model = BabyModel::new_example_program();
77//! match model.run_loop(100) {
78//! (model, BabyErrors::Stop(_)) => println!("{}", model.core_dump()),
79//! (_, err) => println!("{}", err.get_descriptor())
80//! }
81//! ```
82//!
83//! You can also single set through an emulation, executing a single
84//! instruction at a time using the `execute` method and seeing the
85//! direct result.
86//!
87//! ```rust
88//! use baby_emulator::core::BabyModel;
89//! use baby_emulator::core::errors::BabyError;
90//!
91//! let model = BabyModel::new_example_program();
92//! match model.execute() {
93//! Ok(m) => println!("{}", m.core_dump()),
94//! Err(e) => println!("Error {}", e.get_descriptor())
95//! }
96//! ```
97//!
98//! ### Assembly
99//!
100//! Here is an example of assembling a Baby asm string using
101//! modern notation, then running the resultant program,
102//! see the [baby_emulator::assembler][crate::assembler] docs for more information:
103//!
104//! ```rust
105//! use baby_emulator::assembler::{assemble, linker::LinkerData};
106//! use baby_emulator::core::{BabyModel, instructions::BabyInstruction};
107//!
108//!
109//! const ASM: &str =
110//! "
111//! ldn $start_value ; Loads 10 into the accumulator
112//!
113//! :loop_start_value ; The memory address the loop should return to
114//! sub $subtract_val ; Subtract 1 from the accumulator
115//! cmp ; Skip the next jump instruction if the accumulator is negative
116//! jmp $loop_start ; Jump to the start of the loop
117//! stp ; Program stops when the accumulator is negative
118//!
119//! :loop_start ; Pointer to the memory address the loop should return to
120//! abs $loop_start_value
121//!
122//! :subtract_val ; Value to be subtracted
123//! abs 0d1
124//!
125//! :start_value ; Value to start in the accumulator
126//! abs 0d-10
127//! ";
128//!
129//! fn main() {
130//! let instructions = match assemble(&String::from(ASM), false) {
131//! Ok(LinkerData(v, _)) => v,
132//! Err(e) => { println!("{}", e.describe(true)); return; }
133//! };
134//! let main_store = BabyInstruction::to_numbers(instructions);
135//!
136//! let mut model = BabyModel::new_with_program(main_store);
137//! loop {
138//! model = match model.execute() {
139//! Ok(m) => m,
140//! Err(_) => break
141//! };
142//! }
143//! println!("{}", model.core_dump());
144//! }
145//! ```
146//!
147
148/// Contains the core models and emulation functionality.
149pub mod core;
150/// Contains types and functionality for assembling Baby asm.
151pub mod assembler;