Update multiply instructions
This commit is contained in:
parent
8bdd8a47f6
commit
96a8152170
@ -1,11 +1,7 @@
|
|||||||
;#include "../src/foot.asm"
|
;#include "../src/foot.asm"
|
||||||
|
|
||||||
label:
|
label:
|
||||||
CNST. r0, 0xFBFF
|
CNST. r0, #0xFBFF
|
||||||
CNST. r29, 0x400
|
CNST. r30, #0x400
|
||||||
|
|
||||||
ADDI.r [r0++], [r0], r0
|
ADDI.r [r0++], [r0], r0
|
||||||
|
CNST. r31, #label
|
||||||
CNST. r31, label
|
|
||||||
|
|
||||||
data:
|
|
18
examples/mandelbrot.asm
Normal file
18
examples/mandelbrot.asm
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
;#include "../src/foot.asm"
|
||||||
|
|
||||||
|
value_count = 1024
|
||||||
|
|
||||||
|
; generate starting values
|
||||||
|
CNST. r30, #value_count
|
||||||
|
CNST. r0, #xvals
|
||||||
|
ADDI.r [r0++], r30, #0
|
||||||
|
|
||||||
|
|
||||||
|
end:
|
||||||
|
CNST
|
||||||
|
|
||||||
|
xvals:
|
||||||
|
#res value_count
|
||||||
|
|
||||||
|
yvals:
|
||||||
|
#res value_count
|
12
src/foot.asm
12
src/foot.asm
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#subruledef operand
|
#subruledef operand
|
||||||
{
|
{
|
||||||
#{immediate: u5} => 0b000 @ immediate
|
#{immediate: i5} => 0b000 @ immediate
|
||||||
r{register: u5} => 0b001 @ register
|
r{register: u5} => 0b001 @ register
|
||||||
[r{register: u5}++] => 0b010 @ register
|
[r{register: u5}++] => 0b010 @ register
|
||||||
[r{register: u5}--] => 0b011 @ register
|
[r{register: u5}--] => 0b011 @ register
|
||||||
@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
#ruledef
|
#ruledef
|
||||||
{
|
{
|
||||||
CNST{flags: crflags} {dst: operand}, {imm: i16} => imm @ flags @ 0b0000 @ dst
|
CNST{flags: crflags} {dst: operand}, #{imm: i16} => imm @ flags @ 0b0000 @ dst
|
||||||
CMPR{flags: crflags} {dst: operand}, {a: operand} => 0x00 @ a @ flags @ 0b0001 @ dst
|
CMPR{flags: crflags} {dst: operand}, {a: operand} => 0x00 @ a @ flags @ 0b0001 @ dst
|
||||||
BWNG{flags: crflags} {dst: operand}, {a: operand} => 0x01 @ a @ flags @ 0b0001 @ dst
|
BWNG{flags: crflags} {dst: operand}, {a: operand} => 0x01 @ a @ flags @ 0b0001 @ dst
|
||||||
ARNG{flags: crflags} {dst: operand}, {a: operand} => 0x02 @ a @ flags @ 0b0001 @ dst
|
ARNG{flags: crflags} {dst: operand}, {a: operand} => 0x02 @ a @ flags @ 0b0001 @ dst
|
||||||
@ -44,9 +44,11 @@
|
|||||||
CLSH{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b1000 @ dst
|
CLSH{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b1000 @ dst
|
||||||
ADDI{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b1001 @ dst
|
ADDI{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b1001 @ dst
|
||||||
SUBT{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b1010 @ dst
|
SUBT{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b1010 @ dst
|
||||||
MULT{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b1011 @ dst
|
MULL{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b1011 @ dst
|
||||||
DIVI{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b1100 @ dst
|
MULS{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b1100 @ dst
|
||||||
MODU{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b1101 @ dst
|
MULU{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b1101 @ dst
|
||||||
|
DIVI{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b1110 @ dst
|
||||||
|
MODU{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b1111 @ dst
|
||||||
}
|
}
|
||||||
|
|
||||||
#bankdef mem
|
#bankdef mem
|
||||||
|
31
src/main.rs
31
src/main.rs
@ -13,6 +13,14 @@ use winit::event::{StartCause, WindowEvent};
|
|||||||
use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop};
|
use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop};
|
||||||
use winit::window::{Window, WindowAttributes, WindowButtons, WindowId};
|
use winit::window::{Window, WindowAttributes, WindowButtons, WindowId};
|
||||||
|
|
||||||
|
const WIDTH: u32 = 64;
|
||||||
|
const HEIGHT: u32 = 64;
|
||||||
|
const BITS_PER_PIXEL: u32 = 4;
|
||||||
|
const PIXELS_PER_ADDRESS: u32 = 16 / BITS_PER_PIXEL;
|
||||||
|
const MEMORY_SLOTS: u32 = WIDTH * HEIGHT / PIXELS_PER_ADDRESS;
|
||||||
|
const BASE_ADDRESS: u32 = 0xFFFF - MEMORY_SLOTS;
|
||||||
|
const PIXEL_SCALE: u32 = 8;
|
||||||
|
|
||||||
pub struct App
|
pub struct App
|
||||||
{
|
{
|
||||||
vm: FootVM,
|
vm: FootVM,
|
||||||
@ -42,24 +50,20 @@ impl App
|
|||||||
let pixels = &mut self.pixels.as_mut().unwrap();
|
let pixels = &mut self.pixels.as_mut().unwrap();
|
||||||
let frame = pixels.frame_mut();
|
let frame = pixels.frame_mut();
|
||||||
|
|
||||||
for i in 0u16..32u16
|
for ptr in 0..MEMORY_SLOTS
|
||||||
{
|
{
|
||||||
for j in 0u16..32u16
|
let mut value = self.vm[(ptr + BASE_ADDRESS) as u16];
|
||||||
{
|
|
||||||
let index = i + j * 32;
|
|
||||||
let mut value = self.vm[index + 0xFBFF];
|
|
||||||
|
|
||||||
for k in 0..16
|
for k in 0..PIXELS_PER_ADDRESS
|
||||||
{
|
{
|
||||||
let pixel_value = ((value & 1) * 255) as u8;
|
let pixel_value = ((value & 0xF) * 17) as u8;
|
||||||
let pixel_index = (index as usize * 64) + k * 4;
|
let pixel_index = ((ptr * PIXELS_PER_ADDRESS + k) * 4) as usize;
|
||||||
frame[pixel_index + 0] = pixel_value;
|
frame[pixel_index + 0] = 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;
|
||||||
|
|
||||||
value >>= 1;
|
value >>= BITS_PER_PIXEL;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,21 +88,18 @@ impl ApplicationHandler for App
|
|||||||
|
|
||||||
fn resumed(&mut self, event_loop: &ActiveEventLoop)
|
fn resumed(&mut self, event_loop: &ActiveEventLoop)
|
||||||
{
|
{
|
||||||
const WIDTH: u32 = 128;
|
|
||||||
const HEIGHT: u32 = 128;
|
|
||||||
|
|
||||||
let window = event_loop.create_window(
|
let window = event_loop.create_window(
|
||||||
WindowAttributes::default()
|
WindowAttributes::default()
|
||||||
.with_resizable(false)
|
.with_resizable(false)
|
||||||
.with_enabled_buttons(WindowButtons::CLOSE | WindowButtons::MINIMIZE)
|
.with_enabled_buttons(WindowButtons::CLOSE | WindowButtons::MINIMIZE)
|
||||||
.with_inner_size(LogicalSize::new(WIDTH * 4, HEIGHT * 4))
|
.with_inner_size(LogicalSize::new(WIDTH * PIXEL_SCALE, HEIGHT * PIXEL_SCALE))
|
||||||
.with_title("foot vm")
|
.with_title("foot vm")
|
||||||
).unwrap();
|
).unwrap();
|
||||||
let window = Arc::new(window);
|
let window = Arc::new(window);
|
||||||
|
|
||||||
self.window = Some(window);
|
self.window = Some(window);
|
||||||
|
|
||||||
let surface_texture = SurfaceTexture::new(WIDTH * 4, HEIGHT * 4, self.window.as_ref().unwrap().clone());
|
let surface_texture = SurfaceTexture::new(WIDTH * PIXEL_SCALE, HEIGHT * PIXEL_SCALE, self.window.as_ref().unwrap().clone());
|
||||||
self.pixels = Some(Pixels::new(WIDTH, HEIGHT, surface_texture).unwrap());
|
self.pixels = Some(Pixels::new(WIDTH, HEIGHT, surface_texture).unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
78
src/vm.rs
78
src/vm.rs
@ -110,7 +110,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),
|
||||||
MULT(ConditionalExecutionFlag, bool, Operand, Operand, Operand),
|
MULL(ConditionalExecutionFlag, bool, Operand, Operand, Operand),
|
||||||
|
MULS(ConditionalExecutionFlag, bool, Operand, Operand, Operand),
|
||||||
|
MULU(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)
|
||||||
}
|
}
|
||||||
@ -144,7 +146,7 @@ impl TryFrom<u32> for Instruction
|
|||||||
{
|
{
|
||||||
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()?;
|
||||||
match (value >> 24) & 0xF
|
match opcode
|
||||||
{
|
{
|
||||||
2 => Ok(BWOR(ceflag, rflag, dst, b, a)),
|
2 => Ok(BWOR(ceflag, rflag, dst, b, a)),
|
||||||
3 => Ok(BAND(ceflag, rflag, dst, b, a)),
|
3 => Ok(BAND(ceflag, rflag, dst, b, a)),
|
||||||
@ -155,9 +157,11 @@ 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(MULT(ceflag, rflag, dst, b, a)),
|
11 => Ok(MULL(ceflag, rflag, dst, b, a)),
|
||||||
12 => Ok(DIVI(ceflag, rflag, dst, b, a)),
|
12 => Ok(MULS(ceflag, rflag, dst, b, a)),
|
||||||
13 => Ok(MODU(ceflag, rflag, dst, b, a)),
|
13 => Ok(MULU(ceflag, rflag, dst, b, a)),
|
||||||
|
14 => Ok(DIVI(ceflag, rflag, dst, b, a)),
|
||||||
|
15 => Ok(MODU(ceflag, rflag, dst, b, a)),
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -197,13 +201,17 @@ macro_rules! run_instruction
|
|||||||
{
|
{
|
||||||
if $rep
|
if $rep
|
||||||
{
|
{
|
||||||
while $self.should_repeat()
|
let loop_count = $self.loop_count();
|
||||||
|
for i in 0..loop_count
|
||||||
{
|
{
|
||||||
|
*$self.mut_loop_count() = i;
|
||||||
if $self.check($cef)
|
if $self.check($cef)
|
||||||
{
|
{
|
||||||
$self.$name($d, $a)
|
$self.$name($d, $a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*$self.mut_loop_count() = loop_count;
|
||||||
}
|
}
|
||||||
else if $self.check($cef)
|
else if $self.check($cef)
|
||||||
{
|
{
|
||||||
@ -214,13 +222,17 @@ macro_rules! run_instruction
|
|||||||
{
|
{
|
||||||
if $rep
|
if $rep
|
||||||
{
|
{
|
||||||
while $self.should_repeat()
|
let loop_count = $self.loop_count();
|
||||||
|
for i in 0..loop_count
|
||||||
{
|
{
|
||||||
|
*$self.mut_loop_count() = i;
|
||||||
if $self.check($cef)
|
if $self.check($cef)
|
||||||
{
|
{
|
||||||
$self.$name($d, $a, $b)
|
$self.$name($d, $a, $b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*$self.mut_loop_count() = loop_count;
|
||||||
}
|
}
|
||||||
else if $self.check($cef)
|
else if $self.check($cef)
|
||||||
{
|
{
|
||||||
@ -294,7 +306,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 = (second_word as u32) << 16 | first_word as u32;
|
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()
|
||||||
{
|
{
|
||||||
@ -326,8 +338,12 @@ impl FootVM
|
|||||||
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(MULT(cef, rep, dst, b, a)) =>
|
Ok(MULL(cef, rep, dst, b, a)) =>
|
||||||
run_instruction!(self, cef, rep, mult, dst, a, b),
|
run_instruction!(self, cef, rep, mull, dst, a, b),
|
||||||
|
Ok(MULS(cef, rep, dst, b, a)) =>
|
||||||
|
run_instruction!(self, cef, rep, muls, dst, a, b),
|
||||||
|
Ok(MULU(cef, rep, dst, b, a)) =>
|
||||||
|
run_instruction!(self, cef, rep, mulu, 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)) =>
|
||||||
@ -422,7 +438,7 @@ impl FootVM
|
|||||||
{
|
{
|
||||||
let a = self.load_operand(src_a);
|
let a = self.load_operand(src_a);
|
||||||
let b = self.load_operand(src_b);
|
let b = self.load_operand(src_b);
|
||||||
self.store_operand(dst, a.rotate_left(b as u32));
|
self.store_operand(dst, a.rotate_left(u32::from(b)));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn addi(&mut self, dst: Operand, src_a: Operand, src_b: Operand)
|
fn addi(&mut self, dst: Operand, src_a: Operand, src_b: Operand)
|
||||||
@ -439,11 +455,25 @@ impl FootVM
|
|||||||
self.store_operand(dst, a.wrapping_sub(b));
|
self.store_operand(dst, a.wrapping_sub(b));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mult(&mut self, dst: Operand, src_a: Operand, src_b: Operand)
|
fn mull(&mut self, dst: Operand, src_a: Operand, src_b: Operand)
|
||||||
{
|
{
|
||||||
let a = self.load_operand(src_a);
|
let a = u32::from(self.load_operand(src_a));
|
||||||
let b = self.load_operand(src_b);
|
let b = u32::from(self.load_operand(src_b));
|
||||||
self.store_operand(dst, a.wrapping_mul(b));
|
self.store_operand(dst, (a * b) as u16);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn muls(&mut self, dst: Operand, src_a: Operand, src_b: Operand)
|
||||||
|
{
|
||||||
|
let a = i32::from(self.load_operand(src_a));
|
||||||
|
let b = i32::from(self.load_operand(src_b));
|
||||||
|
self.store_operand(dst, ((a * b) >> 16) as u16);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mulu(&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) >> 16) 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)
|
||||||
@ -522,26 +552,12 @@ impl FootVM
|
|||||||
|
|
||||||
fn loop_count(&self) -> u16
|
fn loop_count(&self) -> u16
|
||||||
{
|
{
|
||||||
self.registers[29]
|
self.registers[30]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mut_loop_count(&mut self) -> &mut u16
|
fn mut_loop_count(&mut self) -> &mut u16
|
||||||
{
|
{
|
||||||
&mut self.registers[29]
|
&mut self.registers[30]
|
||||||
}
|
|
||||||
|
|
||||||
fn should_repeat(&mut self) -> bool
|
|
||||||
{
|
|
||||||
if self.loop_count() > 0
|
|
||||||
{
|
|
||||||
*self.mut_loop_count() -= 1;
|
|
||||||
|
|
||||||
true
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check(&self, cef: ConditionalExecutionFlag) -> bool
|
fn check(&self, cef: ConditionalExecutionFlag) -> bool
|
||||||
|
Loading…
x
Reference in New Issue
Block a user