vasm now supports files
This commit is contained in:
@@ -10,3 +10,4 @@ mod vasm_parser;
|
|||||||
mod vasm_preprocessor;
|
mod vasm_preprocessor;
|
||||||
|
|
||||||
pub use vasm_assembler::assemble_snippet;
|
pub use vasm_assembler::assemble_snippet;
|
||||||
|
pub use vasm_assembler::assemble_file;
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ pub enum AssembleError {
|
|||||||
ArgError(usize, EvalError),
|
ArgError(usize, EvalError),
|
||||||
NoCode,
|
NoCode,
|
||||||
IncludeError(usize, String),
|
IncludeError(usize, String),
|
||||||
|
FileError(String),
|
||||||
MacroError(usize),
|
MacroError(usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,6 +64,9 @@ impl Display for AssembleError {
|
|||||||
AssembleError::MacroError(line) => {
|
AssembleError::MacroError(line) => {
|
||||||
write!(f, "Malformed macro control structure on line {}", line)
|
write!(f, "Malformed macro control structure on line {}", line)
|
||||||
}
|
}
|
||||||
|
AssembleError::FileError(file) => {
|
||||||
|
write!(f, "File read error in {}", file)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ use crate::parse_error::AssembleError;
|
|||||||
use crate::vasm_evaluator::eval;
|
use crate::vasm_evaluator::eval;
|
||||||
use crate::vasm_preprocessor::{Line, LineSource};
|
use crate::vasm_preprocessor::{Line, LineSource};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
use std::fs;
|
||||||
|
|
||||||
/// This will solve all the .equ directives and return a symbol table of them.
|
/// This will solve all the .equ directives and return a symbol table of them.
|
||||||
/// .equ directives must be able to be solved in order, that is, in terms of
|
/// .equ directives must be able to be solved in order, that is, in terms of
|
||||||
@@ -162,14 +163,14 @@ fn code_bounds(
|
|||||||
/// bytes long and index 0 will represent 0x400.
|
/// bytes long and index 0 will represent 0x400.
|
||||||
/// ```
|
/// ```
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// vasm::assemble_snippet(vec![".org 0x400", "push 5", "add 7"]),
|
/// vasm::assemble_snippet(".org 0x400 \n push 5 \n add 7".lines().map(String::from)),
|
||||||
/// Ok(vec![0x01, 0x05, 0x05, 0x07])
|
/// Ok(vec![0x01, 0x05, 0x05, 0x07])
|
||||||
/// )
|
/// )
|
||||||
/// ```
|
/// ```
|
||||||
pub fn assemble_snippet<'a, T: IntoIterator<Item = &'a str>>(
|
pub fn assemble_snippet<T: IntoIterator<Item = String>>(
|
||||||
lines: T,
|
lines: T,
|
||||||
) -> Result<Vec<u8>, AssembleError> {
|
) -> Result<Vec<u8>, AssembleError> {
|
||||||
let mut line_results: Vec<Result<Line, AssembleError>> =
|
let line_results: Vec<Result<Line, AssembleError>> =
|
||||||
LineSource::new("_snippet", lines, |_file| {
|
LineSource::new("_snippet", lines, |_file| {
|
||||||
Err(AssembleError::IncludeError(
|
Err(AssembleError::IncludeError(
|
||||||
0,
|
0,
|
||||||
@@ -178,6 +179,19 @@ pub fn assemble_snippet<'a, T: IntoIterator<Item = &'a str>>(
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
assemble_line_results(line_results)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn assemble_file(filename: &str) -> Result<Vec<u8>, AssembleError> {
|
||||||
|
let lines = lines_from_file(filename)?;
|
||||||
|
let line_results: Vec<Result<Line, AssembleError>> = LineSource::new(filename, lines, |file| {
|
||||||
|
lines_from_file(file.as_str())
|
||||||
|
}).collect();
|
||||||
|
|
||||||
|
assemble_line_results(line_results)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn assemble_line_results(mut line_results: Vec<Result<Line, AssembleError>>) -> Result<Vec<u8>, AssembleError> {
|
||||||
if let Some(Err(error)) = line_results.iter().find(|line| line.is_err()) {
|
if let Some(Err(error)) = line_results.iter().find(|line| line.is_err()) {
|
||||||
Err(error.clone())
|
Err(error.clone())
|
||||||
} else {
|
} else {
|
||||||
@@ -189,6 +203,11 @@ pub fn assemble_snippet<'a, T: IntoIterator<Item = &'a str>>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn lines_from_file(filename: &str) -> Result<Vec<String>, AssembleError> {
|
||||||
|
let file = fs::read_to_string(filename).map_err(|_e| AssembleError::FileError(filename.into()))?;
|
||||||
|
Ok(file.lines().map(String::from).collect())
|
||||||
|
}
|
||||||
|
|
||||||
/// At this point all lines have addresses and lengths, and all arguments are reduced to
|
/// At this point all lines have addresses and lengths, and all arguments are reduced to
|
||||||
/// numeric constants. It's time to generate code.
|
/// numeric constants. It's time to generate code.
|
||||||
///
|
///
|
||||||
@@ -474,9 +493,9 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_assemble_snippet() {
|
fn test_assemble_snippet() {
|
||||||
assert_eq!(assemble_snippet(["add"]), Ok(vec![4]));
|
assert_eq!(assemble_snippet(["add"].map(String::from)), Ok(vec![4]));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
assemble_snippet(["apple"]),
|
assemble_snippet(["apple"].map(String::from)),
|
||||||
Err(ParseError(
|
Err(ParseError(
|
||||||
1,
|
1,
|
||||||
parse_error::ParseError::InvalidInstruction("apple".into())
|
parse_error::ParseError::InvalidInstruction("apple".into())
|
||||||
@@ -491,7 +510,7 @@ mod test {
|
|||||||
hlt
|
hlt
|
||||||
blah: mul 2
|
blah: mul 2
|
||||||
ret"
|
ret"
|
||||||
.lines()
|
.lines().map(String::from)
|
||||||
),
|
),
|
||||||
Ok(vec![
|
Ok(vec![
|
||||||
0x01, 0x03, // nop 3
|
0x01, 0x03, // nop 3
|
||||||
@@ -509,7 +528,7 @@ mod test {
|
|||||||
nop $+2
|
nop $+2
|
||||||
|
|
||||||
nop 0x111111
|
nop 0x111111
|
||||||
nop 0x222222".lines()),
|
nop 0x222222".lines().map(String::from)),
|
||||||
Ok(vec![
|
Ok(vec![
|
||||||
0x03, 0x08, 0x04, 0x00,
|
0x03, 0x08, 0x04, 0x00,
|
||||||
0x03, 0x11, 0x11, 0x11,
|
0x03, 0x11, 0x11, 0x11,
|
||||||
|
|||||||
@@ -35,8 +35,7 @@ enum ControlStructure {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct LineSource<
|
pub struct LineSource<
|
||||||
'a,
|
T: IntoIterator<Item = String>,
|
||||||
T: IntoIterator<Item = &'a str>,
|
|
||||||
F: Fn(String) -> Result<T, AssembleError>,
|
F: Fn(String) -> Result<T, AssembleError>,
|
||||||
> {
|
> {
|
||||||
generated_lines: VecDeque<Line>,
|
generated_lines: VecDeque<Line>,
|
||||||
@@ -48,8 +47,8 @@ pub struct LineSource<
|
|||||||
include: F,
|
include: F,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: IntoIterator<Item = &'a str>, F: Fn(String) -> Result<T, AssembleError>> Iterator
|
impl<T: IntoIterator<Item = String>, F: Fn(String) -> Result<T, AssembleError>> Iterator
|
||||||
for LineSource<'a, T, F>
|
for LineSource<T, F>
|
||||||
{
|
{
|
||||||
type Item = Result<Line, AssembleError>;
|
type Item = Result<Line, AssembleError>;
|
||||||
|
|
||||||
@@ -68,7 +67,7 @@ impl<'a, T: IntoIterator<Item = &'a str>, F: Fn(String) -> Result<T, AssembleErr
|
|||||||
if let Some((line_idx, line)) = self.iter_stack.last_mut().unwrap().next() {
|
if let Some((line_idx, line)) = self.iter_stack.last_mut().unwrap().next() {
|
||||||
self.current_line = line_idx + 1;
|
self.current_line = line_idx + 1;
|
||||||
// Try and parse it
|
// Try and parse it
|
||||||
return match parse_vasm_line(line) {
|
return match parse_vasm_line(line.as_str()) {
|
||||||
// We failed to parse it
|
// We failed to parse it
|
||||||
Err(err) => Some(Err(AssembleError::ParseError(self.current_line, err))),
|
Err(err) => Some(Err(AssembleError::ParseError(self.current_line, err))),
|
||||||
|
|
||||||
@@ -99,9 +98,10 @@ impl<'a, T: IntoIterator<Item = &'a str>, F: Fn(String) -> Result<T, AssembleErr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: IntoIterator<Item = &'a str>, F: Fn(String) -> Result<T, AssembleError>>
|
impl<T: IntoIterator<Item = String>, F: Fn(String) -> Result<T, AssembleError>>
|
||||||
LineSource<'a, T, F>
|
LineSource<T, F>
|
||||||
{
|
{
|
||||||
|
// TODO: linesource should take a deref instead so it accepts either str or string.
|
||||||
pub fn new(file: &str, lines: T, include: F) -> Self {
|
pub fn new(file: &str, lines: T, include: F) -> Self {
|
||||||
LineSource {
|
LineSource {
|
||||||
generated_lines: VecDeque::new(),
|
generated_lines: VecDeque::new(),
|
||||||
@@ -206,16 +206,20 @@ mod tests {
|
|||||||
use crate::ast::{Label, Node};
|
use crate::ast::{Label, Node};
|
||||||
use vcore::opcodes::Opcode::*;
|
use vcore::opcodes::Opcode::*;
|
||||||
|
|
||||||
fn lines_for(source: Vec<&str>) -> Vec<VASMLine> {
|
fn lines_for(source: Vec<String>) -> Vec<VASMLine> {
|
||||||
let include = |_name: String| panic!();
|
let include = |_name: String| panic!();
|
||||||
let src = LineSource::new("blah", source, include);
|
let src = LineSource::new("blah", source, include);
|
||||||
src.map(|line| line.unwrap().line).collect()
|
src.map(|line| line.unwrap().line).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn stringify(a: Vec<&str>) -> Vec<String> {
|
||||||
|
a.into_iter().map(String::from).collect()
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_preprocess() {
|
fn test_preprocess() {
|
||||||
let include = |_name: String| panic!();
|
let include = |_name: String| panic!();
|
||||||
let lines = vec!["add"];
|
let lines = stringify(vec!["add"]);
|
||||||
let mut src = LineSource::new("blah", lines, include);
|
let mut src = LineSource::new("blah", lines, include);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
src.next(),
|
src.next(),
|
||||||
@@ -230,8 +234,8 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_preprocess_include() {
|
fn test_preprocess_include() {
|
||||||
let include = |_name: String| Ok(vec!["sub"]);
|
let include = |_name: String| Ok(stringify(vec!["sub"]));
|
||||||
let lines = vec!["#include \"foo\"", "add"];
|
let lines = stringify(vec!["#include \"foo\"", "add"]);
|
||||||
let src = LineSource::new("blah", lines, include);
|
let src = LineSource::new("blah", lines, include);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
src.collect::<Vec<Result<Line, AssembleError>>>(),
|
src.collect::<Vec<Result<Line, AssembleError>>>(),
|
||||||
@@ -253,7 +257,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_preprocess_if_end() {
|
fn test_preprocess_if_end() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
lines_for(vec!["#if", "#end"]),
|
lines_for(stringify(vec!["#if", "#end"])),
|
||||||
vec![
|
vec![
|
||||||
VASMLine::Instruction(None, Brz, Some(Node::relative_label("__gensym_1"))),
|
VASMLine::Instruction(None, Brz, Some(Node::relative_label("__gensym_1"))),
|
||||||
VASMLine::LabelDef(Label::from("__gensym_1"))
|
VASMLine::LabelDef(Label::from("__gensym_1"))
|
||||||
@@ -264,7 +268,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_preprocess_else() {
|
fn test_preprocess_else() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
lines_for(vec!["#if", "add", "#else", "sub", "#end"]),
|
lines_for(stringify(vec!["#if", "add", "#else", "sub", "#end"])),
|
||||||
vec![
|
vec![
|
||||||
VASMLine::Instruction(None, Brz, Some(Node::relative_label("__gensym_1"))),
|
VASMLine::Instruction(None, Brz, Some(Node::relative_label("__gensym_1"))),
|
||||||
VASMLine::Instruction(None, Add, None),
|
VASMLine::Instruction(None, Add, None),
|
||||||
@@ -279,7 +283,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_preprocess_do_end() {
|
fn test_preprocess_do_end() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
lines_for(vec!["#while", "#do", "#end"]),
|
lines_for(stringify(vec!["#while", "#do", "#end"])),
|
||||||
vec![
|
vec![
|
||||||
VASMLine::LabelDef(Label("__gensym_1".to_string())),
|
VASMLine::LabelDef(Label("__gensym_1".to_string())),
|
||||||
VASMLine::Instruction(
|
VASMLine::Instruction(
|
||||||
|
|||||||
+6
-4
@@ -43,7 +43,7 @@ fn main() {
|
|||||||
let memory = Memory::from(rng);
|
let memory = Memory::from(rng);
|
||||||
let mut cpu = CPU::new(memory);
|
let mut cpu = CPU::new(memory);
|
||||||
display::reset(&mut cpu);
|
display::reset(&mut cpu);
|
||||||
let code = assemble_snippet(include_str!("typewriter.asm").lines()).expect("Assemble error");
|
let code = assemble_snippet(include_str!("typewriter.asm").lines().map(String::from)).expect("Assemble error");
|
||||||
println!("ROM size: {} bytes", code.len());
|
println!("ROM size: {} bytes", code.len());
|
||||||
cpu.poke_slice(0x400.into(), code.as_slice());
|
cpu.poke_slice(0x400.into(), code.as_slice());
|
||||||
cpu.start();
|
cpu.start();
|
||||||
@@ -103,12 +103,14 @@ fn window_loop(event_loop: EventLoop<()>, window: Window, mut pixels: Pixels, mu
|
|||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
draw(pixels.get_frame(), &mut cpu);
|
draw(pixels.get_frame(), &mut cpu);
|
||||||
pixels.render().expect("Problem displaying framebuffer");
|
pixels.render().expect("Problem displaying framebuffer");
|
||||||
loop {
|
loop { // TODO: this will run the CPU at 100%, need to not spin while halted
|
||||||
if let Some((int, arg)) = interrupt_events.pop_front() {
|
if let Some((int, arg)) = interrupt_events.pop_front() {
|
||||||
cpu.interrupt(int, arg)
|
cpu.interrupt(int, arg)
|
||||||
}
|
}
|
||||||
for _ in 1..1000 {
|
if cpu.running() {
|
||||||
cpu.tick()
|
for _ in 1..1000 {
|
||||||
|
cpu.tick()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if Instant::now() > start + Duration::from_millis(25) {
|
if Instant::now() > start + Duration::from_millis(25) {
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -4,19 +4,19 @@ use vcore::memory::{Memory, PeekPokeExt};
|
|||||||
use vcore::word::Word;
|
use vcore::word::Word;
|
||||||
use vcore::CPU;
|
use vcore::CPU;
|
||||||
|
|
||||||
fn cpu_test<'a, T: IntoIterator<Item = &'a str>>(code: T) -> CPU {
|
fn cpu_test<T: IntoIterator<Item = String>>(code: T) -> CPU {
|
||||||
let bin = assemble_snippet(code).unwrap();
|
let bin = assemble_snippet(code).unwrap();
|
||||||
let mut cpu = vcore::cpu::CPU::new(Memory::with_program(bin));
|
let mut cpu = vcore::cpu::CPU::new(Memory::with_program(bin));
|
||||||
cpu.run_to_halt();
|
cpu.run_to_halt();
|
||||||
cpu
|
cpu
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_stack<'a, T: IntoIterator<Item = &'a str>>(code: T, expected_stack: Vec<i32>) {
|
fn test_stack<T: IntoIterator<Item = String>>(code: T, expected_stack: Vec<i32>) {
|
||||||
let cpu = cpu_test(code);
|
let cpu = cpu_test(code);
|
||||||
assert_eq!(cpu.get_stack(), expected_stack);
|
assert_eq!(cpu.get_stack(), expected_stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_rstack<'a, T: IntoIterator<Item = &'a str>>(
|
fn test_rstack<T: IntoIterator<Item = String>>(
|
||||||
code: T,
|
code: T,
|
||||||
expected_stack: Vec<i32>,
|
expected_stack: Vec<i32>,
|
||||||
expected_rstack: Vec<i32>,
|
expected_rstack: Vec<i32>,
|
||||||
@@ -26,7 +26,7 @@ fn test_rstack<'a, T: IntoIterator<Item = &'a str>>(
|
|||||||
assert_eq!(cpu.get_call(), expected_rstack);
|
assert_eq!(cpu.get_call(), expected_rstack);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_mem<'a, T: IntoIterator<Item = &'a str>>(
|
fn test_mem<T: IntoIterator<Item = String>>(
|
||||||
code: T,
|
code: T,
|
||||||
expected_memory: BTreeMap<u32, u8>,
|
expected_memory: BTreeMap<u32, u8>,
|
||||||
) -> CPU {
|
) -> CPU {
|
||||||
@@ -45,7 +45,7 @@ fn test_arithmetic() {
|
|||||||
push 2
|
push 2
|
||||||
add 3
|
add 3
|
||||||
hlt"
|
hlt"
|
||||||
.lines(),
|
.lines().map(String::from),
|
||||||
vec![5],
|
vec![5],
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ fn test_arithmetic() {
|
|||||||
push 7
|
push 7
|
||||||
mul 1000
|
mul 1000
|
||||||
hlt"
|
hlt"
|
||||||
.lines(),
|
.lines().map(String::from),
|
||||||
vec![7000],
|
vec![7000],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -69,7 +69,7 @@ fn test_call_stack() {
|
|||||||
hlt
|
hlt
|
||||||
blah: mul 2
|
blah: mul 2
|
||||||
ret"
|
ret"
|
||||||
.lines(),
|
.lines().map(String::from),
|
||||||
vec![6],
|
vec![6],
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -81,7 +81,7 @@ fn test_call_stack() {
|
|||||||
pushr
|
pushr
|
||||||
pushr
|
pushr
|
||||||
hlt"
|
hlt"
|
||||||
.lines(),
|
.lines().map(String::from),
|
||||||
vec![10],
|
vec![10],
|
||||||
vec![3, 4],
|
vec![3, 4],
|
||||||
);
|
);
|
||||||
@@ -95,7 +95,7 @@ fn test_call_stack() {
|
|||||||
popr
|
popr
|
||||||
add
|
add
|
||||||
hlt"
|
hlt"
|
||||||
.lines(),
|
.lines().map(String::from),
|
||||||
vec![10, 7],
|
vec![10, 7],
|
||||||
vec![20],
|
vec![20],
|
||||||
);
|
);
|
||||||
@@ -106,7 +106,7 @@ fn test_call_stack() {
|
|||||||
call blah
|
call blah
|
||||||
blah: pushr 3
|
blah: pushr 3
|
||||||
hlt"
|
hlt"
|
||||||
.lines(),
|
.lines().map(String::from),
|
||||||
vec![],
|
vec![],
|
||||||
vec![5, 0x406, 3],
|
vec![5, 0x406, 3],
|
||||||
);
|
);
|
||||||
@@ -120,7 +120,7 @@ fn test_call_stack() {
|
|||||||
popr
|
popr
|
||||||
popr
|
popr
|
||||||
hlt"
|
hlt"
|
||||||
.lines(),
|
.lines().map(String::from),
|
||||||
vec![5, 20, 20, 10],
|
vec![5, 20, 20, 10],
|
||||||
vec![],
|
vec![],
|
||||||
)
|
)
|
||||||
@@ -139,7 +139,7 @@ fn test_comparison() {
|
|||||||
push 10
|
push 10
|
||||||
lt 5
|
lt 5
|
||||||
hlt"
|
hlt"
|
||||||
.lines(),
|
.lines().map(String::from),
|
||||||
vec![0, 1, 1, 0],
|
vec![0, 1, 1, 0],
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -155,7 +155,7 @@ fn test_comparison() {
|
|||||||
push 10
|
push 10
|
||||||
alt -5
|
alt -5
|
||||||
hlt"
|
hlt"
|
||||||
.lines(),
|
.lines().map(String::from),
|
||||||
vec![0, 1, 1, 0],
|
vec![0, 1, 1, 0],
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -164,7 +164,7 @@ fn test_comparison() {
|
|||||||
not 10
|
not 10
|
||||||
not 0
|
not 0
|
||||||
hlt"
|
hlt"
|
||||||
.lines(),
|
.lines().map(String::from),
|
||||||
vec![0, 1],
|
vec![0, 1],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -177,7 +177,7 @@ fn test_pick() {
|
|||||||
nop 20
|
nop 20
|
||||||
pick 1
|
pick 1
|
||||||
hlt"
|
hlt"
|
||||||
.lines(),
|
.lines().map(String::from),
|
||||||
vec![10, 20, 10],
|
vec![10, 20, 10],
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -188,7 +188,7 @@ fn test_pick() {
|
|||||||
pick 2
|
pick 2
|
||||||
pick 5
|
pick 5
|
||||||
hlt"
|
hlt"
|
||||||
.lines(),
|
.lines().map(String::from),
|
||||||
vec![10, 20, 0, 0],
|
vec![10, 20, 0, 0],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -202,7 +202,7 @@ fn test_store() {
|
|||||||
push 0x123456
|
push 0x123456
|
||||||
storew 203
|
storew 203
|
||||||
hlt"
|
hlt"
|
||||||
.lines(),
|
.lines().map(String::from),
|
||||||
[(201, 10), (203, 0x56), (204, 0x34), (205, 0x12)].into(),
|
[(201, 10), (203, 0x56), (204, 0x34), (205, 0x12)].into(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -216,7 +216,7 @@ fn test_load() {
|
|||||||
hlt
|
hlt
|
||||||
.org 0x500
|
.org 0x500
|
||||||
.db 0x123456"
|
.db 0x123456"
|
||||||
.lines(),
|
.lines().map(String::from),
|
||||||
vec![0x34, 0x123456],
|
vec![0x34, 0x123456],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -231,7 +231,7 @@ fn test_rotate() {
|
|||||||
push 300
|
push 300
|
||||||
rot
|
rot
|
||||||
hlt"
|
hlt"
|
||||||
.lines(),
|
.lines().map(String::from),
|
||||||
vec![10, 200, 300, 100],
|
vec![10, 200, 300, 100],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -244,7 +244,7 @@ fn test_sdp() {
|
|||||||
pushr 20
|
pushr 20
|
||||||
sdp
|
sdp
|
||||||
hlt"
|
hlt"
|
||||||
.lines(),
|
.lines().map(String::from),
|
||||||
vec![10, 1021, 265],
|
vec![10, 1021, 265],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -262,7 +262,7 @@ fn test_underflow() {
|
|||||||
onunder: push 200
|
onunder: push 200
|
||||||
store 10
|
store 10
|
||||||
hlt"
|
hlt"
|
||||||
.lines(),
|
.lines().map(String::from),
|
||||||
[(10, 200)].into(),
|
[(10, 200)].into(),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -277,7 +277,7 @@ fn test_underflow() {
|
|||||||
onrunder: push 200
|
onrunder: push 200
|
||||||
store 10
|
store 10
|
||||||
hlt"
|
hlt"
|
||||||
.lines(),
|
.lines().map(String::from),
|
||||||
[(10, 200)].into(),
|
[(10, 200)].into(),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -292,7 +292,7 @@ fn test_underflow() {
|
|||||||
onunder: push 200
|
onunder: push 200
|
||||||
store 10
|
store 10
|
||||||
hlt"
|
hlt"
|
||||||
.lines(),
|
.lines().map(String::from),
|
||||||
[(10, 200)].into(),
|
[(10, 200)].into(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -311,7 +311,7 @@ fn test_div_zero() {
|
|||||||
ondiv0: push 200
|
ondiv0: push 200
|
||||||
store 10
|
store 10
|
||||||
hlt"
|
hlt"
|
||||||
.lines(),
|
.lines().map(String::from),
|
||||||
[(10, 200)].into(),
|
[(10, 200)].into(),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -327,7 +327,7 @@ fn test_div_zero() {
|
|||||||
ondiv0: push 200
|
ondiv0: push 200
|
||||||
store 10
|
store 10
|
||||||
hlt"
|
hlt"
|
||||||
.lines(),
|
.lines().map(String::from),
|
||||||
[(10, 200)].into(),
|
[(10, 200)].into(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -348,7 +348,7 @@ fn test_overflow() {
|
|||||||
push 3 ; boom!
|
push 3 ; boom!
|
||||||
store ; never happens
|
store ; never happens
|
||||||
onover: hlt"
|
onover: hlt"
|
||||||
.lines(),
|
.lines().map(String::from),
|
||||||
[(16, 1), (19, 2)].into(), // expect the two successful pushes to be still there
|
[(16, 1), (19, 2)].into(), // expect the two successful pushes to be still there
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -378,7 +378,7 @@ fn test_simple_overflow() {
|
|||||||
add 5 ; full stack + argument!
|
add 5 ; full stack + argument!
|
||||||
store ; never happens
|
store ; never happens
|
||||||
onover: hlt"
|
onover: hlt"
|
||||||
.lines(),
|
.lines().map(String::from),
|
||||||
[(16, 1), (19, 2)].into(), // expect the two successful pushes to be still there
|
[(16, 1), (19, 2)].into(), // expect the two successful pushes to be still there
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -408,7 +408,7 @@ fn test_overflow_promotion() {
|
|||||||
div ; This is a div 0, but there's no room to handle it, so it's promoted to overflow
|
div ; This is a div 0, but there's no room to handle it, so it's promoted to overflow
|
||||||
store ; never happens
|
store ; never happens
|
||||||
onover: hlt"
|
onover: hlt"
|
||||||
.lines(),
|
.lines().map(String::from),
|
||||||
[(16, 1), (19, 0)].into(), // expect the two successful pushes to be still there
|
[(16, 1), (19, 0)].into(), // expect the two successful pushes to be still there
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -434,7 +434,7 @@ fn test_invalid_opcode() {
|
|||||||
.db 0xf6 ; this isn't an instruction!
|
.db 0xf6 ; this isn't an instruction!
|
||||||
store ; never happens
|
store ; never happens
|
||||||
onop: hlt"
|
onop: hlt"
|
||||||
.lines(),
|
.lines().map(String::from),
|
||||||
[(256, 1), (259, 2)].into(), // expect the two successful pushes to be still there
|
[(256, 1), (259, 2)].into(), // expect the two successful pushes to be still there
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user