Add some tests; use .foot instead of .asm
This commit is contained in:
parent
96a8152170
commit
2ce34865af
@ -7,7 +7,7 @@
|
|||||||
[r{register: u5}++] => 0b010 @ register
|
[r{register: u5}++] => 0b010 @ register
|
||||||
[r{register: u5}--] => 0b011 @ register
|
[r{register: u5}--] => 0b011 @ register
|
||||||
[r{register: u5}] => 0b100 @ register
|
[r{register: u5}] => 0b100 @ register
|
||||||
[r{register: u5} + {offset: u2} => 0b1 @ offset @ register
|
[r{register: u5} + {offset: u2}] => 0b1 @ offset @ register
|
||||||
}
|
}
|
||||||
|
|
||||||
#subruledef crflags
|
#subruledef crflags
|
@ -1,13 +1,13 @@
|
|||||||
use std::io::{Cursor};
|
use std::io::Cursor;
|
||||||
use std::ops::{Index, IndexMut};
|
use std::ops::{Index, IndexMut};
|
||||||
use AddressingMode::*;
|
use AddressingMode::*;
|
||||||
use ConditionalExecutionFlag::*;
|
use ConditionalExecutionFlag::*;
|
||||||
use Instruction::*;
|
use Instruction::*;
|
||||||
use byteorder::{BigEndian, ReadBytesExt};
|
use byteorder::{BigEndian, ReadBytesExt};
|
||||||
|
|
||||||
const ASM_PREFIX: &str = include_str!("foot.asm");
|
const ASM_PREFIX: &str = include_str!("foot.foot");
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
enum ConditionalExecutionFlag
|
enum ConditionalExecutionFlag
|
||||||
{
|
{
|
||||||
Always,
|
Always,
|
||||||
@ -39,7 +39,7 @@ impl TryFrom<u32> for ConditionalExecutionFlag
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
enum AddressingMode
|
enum AddressingMode
|
||||||
{
|
{
|
||||||
Immediate,
|
Immediate,
|
||||||
@ -101,6 +101,7 @@ enum Instruction
|
|||||||
BWNG(ConditionalExecutionFlag, bool, Operand, Operand),
|
BWNG(ConditionalExecutionFlag, bool, Operand, Operand),
|
||||||
ARNG(ConditionalExecutionFlag, bool, Operand, Operand),
|
ARNG(ConditionalExecutionFlag, bool, Operand, Operand),
|
||||||
LONG(ConditionalExecutionFlag, bool, Operand, Operand),
|
LONG(ConditionalExecutionFlag, bool, Operand, Operand),
|
||||||
|
CONF(ConditionalExecutionFlag, bool, Operand, Operand),
|
||||||
BWOR(ConditionalExecutionFlag, bool, Operand, Operand, Operand),
|
BWOR(ConditionalExecutionFlag, bool, Operand, Operand, Operand),
|
||||||
BAND(ConditionalExecutionFlag, bool, Operand, Operand, Operand),
|
BAND(ConditionalExecutionFlag, bool, Operand, Operand, Operand),
|
||||||
BXOR(ConditionalExecutionFlag, bool, Operand, Operand, Operand),
|
BXOR(ConditionalExecutionFlag, bool, Operand, Operand, Operand),
|
||||||
@ -110,9 +111,9 @@ enum Instruction
|
|||||||
CLSH(ConditionalExecutionFlag, bool, Operand, Operand, Operand),
|
CLSH(ConditionalExecutionFlag, bool, Operand, Operand, Operand),
|
||||||
ADDI(ConditionalExecutionFlag, bool, Operand, Operand, Operand),
|
ADDI(ConditionalExecutionFlag, bool, Operand, Operand, Operand),
|
||||||
SUBT(ConditionalExecutionFlag, bool, Operand, Operand, Operand),
|
SUBT(ConditionalExecutionFlag, bool, Operand, Operand, Operand),
|
||||||
MULL(ConditionalExecutionFlag, bool, Operand, Operand, Operand),
|
|
||||||
MULS(ConditionalExecutionFlag, bool, Operand, Operand, Operand),
|
MULS(ConditionalExecutionFlag, bool, Operand, Operand, Operand),
|
||||||
MULU(ConditionalExecutionFlag, bool, Operand, Operand, Operand),
|
MULU(ConditionalExecutionFlag, bool, Operand, Operand, Operand),
|
||||||
|
MULR(ConditionalExecutionFlag, bool, Operand, Operand, Operand),
|
||||||
DIVI(ConditionalExecutionFlag, bool, Operand, Operand, Operand),
|
DIVI(ConditionalExecutionFlag, bool, Operand, Operand, Operand),
|
||||||
MODU(ConditionalExecutionFlag, bool, Operand, Operand, Operand)
|
MODU(ConditionalExecutionFlag, bool, Operand, Operand, Operand)
|
||||||
}
|
}
|
||||||
@ -124,7 +125,7 @@ impl TryFrom<u32> for Instruction
|
|||||||
fn try_from(value: u32) -> Result<Self, Self::Error>
|
fn try_from(value: u32) -> Result<Self, Self::Error>
|
||||||
{
|
{
|
||||||
let ceflag: ConditionalExecutionFlag = (value >> 29).try_into()?;
|
let ceflag: ConditionalExecutionFlag = (value >> 29).try_into()?;
|
||||||
let rflag: bool = (value >> 28 & 1) == 1;
|
let rflag: bool = ((value >> 28) & 1) == 1;
|
||||||
let dst: Operand = (value >> 16).try_into()?;
|
let dst: Operand = (value >> 16).try_into()?;
|
||||||
let opcode = (value >> 24) & 0xF;
|
let opcode = (value >> 24) & 0xF;
|
||||||
match opcode
|
match opcode
|
||||||
@ -139,10 +140,11 @@ impl TryFrom<u32> for Instruction
|
|||||||
1 => Ok(BWNG(ceflag, rflag, dst, a)),
|
1 => Ok(BWNG(ceflag, rflag, dst, a)),
|
||||||
2 => Ok(ARNG(ceflag, rflag, dst, a)),
|
2 => Ok(ARNG(ceflag, rflag, dst, a)),
|
||||||
3 => Ok(LONG(ceflag, rflag, dst, a)),
|
3 => Ok(LONG(ceflag, rflag, dst, a)),
|
||||||
|
4 => Ok(CONF(ceflag, rflag, dst, a)),
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
2..14 =>
|
2..15 =>
|
||||||
{
|
{
|
||||||
let a: Operand = (value & 0xFF).try_into()?;
|
let a: Operand = (value & 0xFF).try_into()?;
|
||||||
let b: Operand = ((value >> 8) & 0xFF).try_into()?;
|
let b: Operand = ((value >> 8) & 0xFF).try_into()?;
|
||||||
@ -157,9 +159,9 @@ impl TryFrom<u32> for Instruction
|
|||||||
8 => Ok(CLSH(ceflag, rflag, dst, b, a)),
|
8 => Ok(CLSH(ceflag, rflag, dst, b, a)),
|
||||||
9 => Ok(ADDI(ceflag, rflag, dst, b, a)),
|
9 => Ok(ADDI(ceflag, rflag, dst, b, a)),
|
||||||
10 => Ok(SUBT(ceflag, rflag, dst, b, a)),
|
10 => Ok(SUBT(ceflag, rflag, dst, b, a)),
|
||||||
11 => Ok(MULL(ceflag, rflag, dst, b, a)),
|
11 => Ok(MULS(ceflag, rflag, dst, b, a)),
|
||||||
12 => Ok(MULS(ceflag, rflag, dst, b, a)),
|
12 => Ok(MULU(ceflag, rflag, dst, b, a)),
|
||||||
13 => Ok(MULU(ceflag, rflag, dst, b, a)),
|
13 => Ok(MULR(ceflag, rflag, dst, b, a)),
|
||||||
14 => Ok(DIVI(ceflag, rflag, dst, b, a)),
|
14 => Ok(DIVI(ceflag, rflag, dst, b, a)),
|
||||||
15 => Ok(MODU(ceflag, rflag, dst, b, a)),
|
15 => Ok(MODU(ceflag, rflag, dst, b, a)),
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
@ -184,7 +186,8 @@ pub struct FootVM
|
|||||||
{
|
{
|
||||||
memory: [u16; MEMORY_SIZE],
|
memory: [u16; MEMORY_SIZE],
|
||||||
pub registers: [u16; 32],
|
pub registers: [u16; 32],
|
||||||
status: Status
|
status: Status,
|
||||||
|
mult_conf: u8
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for FootVM
|
impl Default for FootVM
|
||||||
@ -249,11 +252,12 @@ impl FootVM
|
|||||||
{
|
{
|
||||||
memory: [0; MEMORY_SIZE],
|
memory: [0; MEMORY_SIZE],
|
||||||
registers: [0; 32],
|
registers: [0; 32],
|
||||||
status: Status::Equal
|
status: Status::Equal,
|
||||||
|
mult_conf: 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load(&mut self, asm_src: &str, write: Option<&mut dyn std::io::Write>) -> Result<(), ()>
|
pub fn load(&mut self, asm_src: &str, write_opt: Option<&mut dyn std::io::Write>) -> Result<(), ()>
|
||||||
{
|
{
|
||||||
let mut asm_src = asm_src.to_owned();
|
let mut asm_src = asm_src.to_owned();
|
||||||
asm_src.insert_str(0, ASM_PREFIX);
|
asm_src.insert_str(0, ASM_PREFIX);
|
||||||
@ -273,12 +277,14 @@ impl FootVM
|
|||||||
&[virtual_filename]
|
&[virtual_filename]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let report = report;
|
||||||
|
|
||||||
let binary = assembly.output.map(|o| o.format_binary()).ok_or_else(
|
let binary = assembly.output.map(|o| o.format_binary()).ok_or_else(
|
||||||
|| {
|
||
|
||||||
match write
|
{
|
||||||
|
if let Some(write) = write_opt
|
||||||
{
|
{
|
||||||
Some(w) => report.print_all(w, &mut fileserver, true),
|
report.print_all(write, &fileserver, true);
|
||||||
None => ()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)?;
|
)?;
|
||||||
@ -286,17 +292,10 @@ impl FootVM
|
|||||||
let mut cursor = Cursor::new(binary);
|
let mut cursor = Cursor::new(binary);
|
||||||
let mut index = 0;
|
let mut index = 0;
|
||||||
|
|
||||||
loop
|
while let Ok(value) = cursor.read_u16::<BigEndian>()
|
||||||
{
|
{
|
||||||
match cursor.read_u16::<BigEndian>()
|
self[index] = value;
|
||||||
{
|
index += 1;
|
||||||
Ok(value) =>
|
|
||||||
{
|
|
||||||
self[index] = value;
|
|
||||||
index += 1;
|
|
||||||
},
|
|
||||||
Err(_) => break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -306,7 +305,7 @@ impl FootVM
|
|||||||
{
|
{
|
||||||
let first_word = self[self.program_counter()];
|
let first_word = self[self.program_counter()];
|
||||||
let second_word = self[self.program_counter() + 1];
|
let second_word = self[self.program_counter() + 1];
|
||||||
let full_instruction_bits = u32::from(second_word) << 16 | u32::from(first_word);
|
let full_instruction_bits = (u32::from(second_word) << 16) | u32::from(first_word);
|
||||||
*self.mut_program_counter() = self.program_counter().wrapping_add(2);
|
*self.mut_program_counter() = self.program_counter().wrapping_add(2);
|
||||||
match full_instruction_bits.try_into()
|
match full_instruction_bits.try_into()
|
||||||
{
|
{
|
||||||
@ -320,6 +319,8 @@ impl FootVM
|
|||||||
run_instruction!(self, cef, rep, arng, dst, src),
|
run_instruction!(self, cef, rep, arng, dst, src),
|
||||||
Ok(LONG(cef, rep, dst, src)) =>
|
Ok(LONG(cef, rep, dst, src)) =>
|
||||||
run_instruction!(self, cef, rep, long, dst, src),
|
run_instruction!(self, cef, rep, long, dst, src),
|
||||||
|
Ok(CONF(cef, rep, dst, src)) =>
|
||||||
|
run_instruction!(self, cef, rep, conf, dst, src),
|
||||||
Ok(BWOR(cef, rep, dst, b, a)) =>
|
Ok(BWOR(cef, rep, dst, b, a)) =>
|
||||||
run_instruction!(self, cef, rep, bwor, dst, a, b),
|
run_instruction!(self, cef, rep, bwor, dst, a, b),
|
||||||
Ok(BAND(cef, rep, dst, b, a)) =>
|
Ok(BAND(cef, rep, dst, b, a)) =>
|
||||||
@ -336,14 +337,14 @@ impl FootVM
|
|||||||
run_instruction!(self, cef, rep, clsh, dst, a, b),
|
run_instruction!(self, cef, rep, clsh, dst, a, b),
|
||||||
Ok(ADDI(cef, rep, dst, b, a)) =>
|
Ok(ADDI(cef, rep, dst, b, a)) =>
|
||||||
run_instruction!(self, cef, rep, addi, dst, a, b),
|
run_instruction!(self, cef, rep, addi, dst, a, b),
|
||||||
Ok(SUBT(cef, rep, dst, b, a)) =>
|
Ok(SUBT(cef, rep, dst, b, a)) =>
|
||||||
run_instruction!(self, cef, rep, subt, dst, a, b),
|
run_instruction!(self, cef, rep, subt, dst, a, b),
|
||||||
Ok(MULL(cef, rep, dst, b, a)) =>
|
|
||||||
run_instruction!(self, cef, rep, mull, dst, a, b),
|
|
||||||
Ok(MULS(cef, rep, dst, b, a)) =>
|
Ok(MULS(cef, rep, dst, b, a)) =>
|
||||||
run_instruction!(self, cef, rep, muls, dst, a, b),
|
run_instruction!(self, cef, rep, muls, dst, a, b),
|
||||||
Ok(MULU(cef, rep, dst, b, a)) =>
|
Ok(MULU(cef, rep, dst, b, a)) =>
|
||||||
run_instruction!(self, cef, rep, mulu, dst, a, b),
|
run_instruction!(self, cef, rep, mulu, dst, a, b),
|
||||||
|
Ok(MULR(cef, rep, dst, b, a)) =>
|
||||||
|
run_instruction!(self, cef, rep, mulr, dst, a, b),
|
||||||
Ok(DIVI(cef, rep, dst, b, a)) =>
|
Ok(DIVI(cef, rep, dst, b, a)) =>
|
||||||
run_instruction!(self, cef, rep, divi, dst, a, b),
|
run_instruction!(self, cef, rep, divi, dst, a, b),
|
||||||
Ok(MODU(cef, rep, dst, b, a)) =>
|
Ok(MODU(cef, rep, dst, b, a)) =>
|
||||||
@ -392,6 +393,14 @@ impl FootVM
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn conf(&mut self, dst: Operand, src: Operand)
|
||||||
|
{
|
||||||
|
self.store_operand(dst, u16::from(self.mult_conf));
|
||||||
|
|
||||||
|
let a = self.load_operand(src);
|
||||||
|
self.mult_conf = (a & 0xF) as u8;
|
||||||
|
}
|
||||||
|
|
||||||
fn bwor(&mut self, dst: Operand, src_a: Operand, src_b: Operand)
|
fn bwor(&mut self, dst: Operand, src_a: Operand, src_b: Operand)
|
||||||
{
|
{
|
||||||
let a = self.load_operand(src_a);
|
let a = self.load_operand(src_a);
|
||||||
@ -455,25 +464,25 @@ impl FootVM
|
|||||||
self.store_operand(dst, a.wrapping_sub(b));
|
self.store_operand(dst, a.wrapping_sub(b));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mull(&mut self, dst: Operand, src_a: Operand, src_b: Operand)
|
|
||||||
{
|
|
||||||
let a = u32::from(self.load_operand(src_a));
|
|
||||||
let b = u32::from(self.load_operand(src_b));
|
|
||||||
self.store_operand(dst, (a * b) as u16);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn muls(&mut self, dst: Operand, src_a: Operand, src_b: Operand)
|
fn muls(&mut self, dst: Operand, src_a: Operand, src_b: Operand)
|
||||||
{
|
{
|
||||||
let a = i32::from(self.load_operand(src_a));
|
let a = i32::from(self.load_operand(src_a));
|
||||||
let b = i32::from(self.load_operand(src_b));
|
let b = i32::from(self.load_operand(src_b));
|
||||||
self.store_operand(dst, ((a * b) >> 16) as u16);
|
self.store_operand(dst, ((a * b) >> self.mult_conf) as u16);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mulu(&mut self, dst: Operand, src_a: Operand, src_b: Operand)
|
fn mulu(&mut self, dst: Operand, src_a: Operand, src_b: Operand)
|
||||||
{
|
{
|
||||||
let a = u32::from(self.load_operand(src_a));
|
let a = u32::from(self.load_operand(src_a));
|
||||||
let b = u32::from(self.load_operand(src_b));
|
let b = u32::from(self.load_operand(src_b));
|
||||||
self.store_operand(dst,((a * b) >> 16) as u16);
|
self.store_operand(dst, ((a * b) >> self.mult_conf) as u16);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mulr(&mut self, dst: Operand, src_a: Operand, src_b: Operand)
|
||||||
|
{
|
||||||
|
let a = u32::from(self.load_operand(src_a));
|
||||||
|
let b = u32::from(self.load_operand(src_b));
|
||||||
|
self.store_operand(dst, (a * b) as u16);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn divi(&mut self, dst: Operand, src_a: Operand, src_b: Operand)
|
fn divi(&mut self, dst: Operand, src_a: Operand, src_b: Operand)
|
||||||
@ -592,3 +601,57 @@ impl IndexMut<u16> for FootVM
|
|||||||
&mut self.memory[index as usize]
|
&mut self.memory[index as usize]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests
|
||||||
|
{
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_conditional_execution_flag_try_from_u32() -> Result<(), ()>
|
||||||
|
{
|
||||||
|
let flag = ConditionalExecutionFlag::try_from(0)?;
|
||||||
|
assert_eq!(flag, Always);
|
||||||
|
|
||||||
|
let flag = ConditionalExecutionFlag::try_from(1)?;
|
||||||
|
assert_eq!(flag, LessThan);
|
||||||
|
|
||||||
|
let flag = ConditionalExecutionFlag::try_from(2)?;
|
||||||
|
assert_eq!(flag, LessThanOrEqual);
|
||||||
|
|
||||||
|
let flag = ConditionalExecutionFlag::try_from(3)?;
|
||||||
|
assert_eq!(flag, Equal);
|
||||||
|
|
||||||
|
let flag = ConditionalExecutionFlag::try_from(4)?;
|
||||||
|
assert_eq!(flag, GreaterThanOrEqual);
|
||||||
|
|
||||||
|
let flag = ConditionalExecutionFlag::try_from(5)?;
|
||||||
|
assert_eq!(flag, GreaterThan);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_addressing_mode_try_from_u32() -> Result<(), ()>
|
||||||
|
{
|
||||||
|
let mode = AddressingMode::try_from(0)?;
|
||||||
|
assert_eq!(mode, Immediate);
|
||||||
|
|
||||||
|
let mode = AddressingMode::try_from(1)?;
|
||||||
|
assert_eq!(mode, Direct);
|
||||||
|
|
||||||
|
let mode = AddressingMode::try_from(2)?;
|
||||||
|
assert_eq!(mode, IndirectAutoIncrement);
|
||||||
|
|
||||||
|
let mode = AddressingMode::try_from(3)?;
|
||||||
|
assert_eq!(mode, IndirectAutoDecrement);
|
||||||
|
|
||||||
|
for i in 4..8
|
||||||
|
{
|
||||||
|
let mode = AddressingMode::try_from(i)?;
|
||||||
|
assert_eq!(mode, Indirect((i - 4) as u8));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
18
src/main.rs
18
src/main.rs
@ -1,9 +1,7 @@
|
|||||||
mod vm;
|
|
||||||
|
|
||||||
use std::{env, fs};
|
use std::{env, fs};
|
||||||
use std::io::{stderr, Write};
|
use std::io::{stderr, Write};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use vm::FootVM;
|
use footvm::FootVM;
|
||||||
|
|
||||||
use pixels::{Pixels, SurfaceTexture};
|
use pixels::{Pixels, SurfaceTexture};
|
||||||
|
|
||||||
@ -58,7 +56,7 @@ impl App
|
|||||||
{
|
{
|
||||||
let pixel_value = ((value & 0xF) * 17) as u8;
|
let pixel_value = ((value & 0xF) * 17) as u8;
|
||||||
let pixel_index = ((ptr * PIXELS_PER_ADDRESS + k) * 4) as usize;
|
let pixel_index = ((ptr * PIXELS_PER_ADDRESS + k) * 4) as usize;
|
||||||
frame[pixel_index + 0] = pixel_value;
|
frame[pixel_index ] = pixel_value;
|
||||||
frame[pixel_index + 1] = pixel_value;
|
frame[pixel_index + 1] = pixel_value;
|
||||||
frame[pixel_index + 2] = pixel_value;
|
frame[pixel_index + 2] = pixel_value;
|
||||||
frame[pixel_index + 3] = 0xFF;
|
frame[pixel_index + 3] = 0xFF;
|
||||||
@ -75,14 +73,10 @@ impl ApplicationHandler for App
|
|||||||
{
|
{
|
||||||
fn new_events(&mut self, _: &ActiveEventLoop, cause: StartCause)
|
fn new_events(&mut self, _: &ActiveEventLoop, cause: StartCause)
|
||||||
{
|
{
|
||||||
match cause
|
if cause == StartCause::Poll
|
||||||
{
|
{
|
||||||
StartCause::Poll =>
|
self.update();
|
||||||
{
|
self.draw()
|
||||||
self.update();
|
|
||||||
self.draw()
|
|
||||||
},
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,7 +113,7 @@ fn main()
|
|||||||
let args: Vec<String> = env::args().collect();
|
let args: Vec<String> = env::args().collect();
|
||||||
if args.len() < 2
|
if args.len() < 2
|
||||||
{
|
{
|
||||||
_ = stderr().write("No filename supplied".as_bytes())
|
_ = stderr().write("No filename supplied\n".as_bytes())
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
12
tests/integration_test.rs
Normal file
12
tests/integration_test.rs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#[test]
|
||||||
|
fn test_basic() -> Result<(), ()>
|
||||||
|
{
|
||||||
|
let mut vm: footvm::FootVM = Default::default();
|
||||||
|
vm.load(include_str!("programs/basic.foot"), None)?;
|
||||||
|
|
||||||
|
vm.cycle();
|
||||||
|
|
||||||
|
assert_eq!(vm.registers[0], 0xFEED);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
1
tests/programs/basic.foot
Normal file
1
tests/programs/basic.foot
Normal file
@ -0,0 +1 @@
|
|||||||
|
CNST. r0, #0xFEED
|
Loading…
x
Reference in New Issue
Block a user