Update multiply instructions
This commit is contained in:
parent
8bdd8a47f6
commit
96a8152170
@ -1,11 +1,7 @@
|
||||
;#include "../src/foot.asm"
|
||||
|
||||
label:
|
||||
CNST. r0, 0xFBFF
|
||||
CNST. r29, 0x400
|
||||
|
||||
CNST. r0, #0xFBFF
|
||||
CNST. r30, #0x400
|
||||
ADDI.r [r0++], [r0], r0
|
||||
|
||||
CNST. r31, label
|
||||
|
||||
data:
|
||||
CNST. r31, #label
|
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
|
||||
{
|
||||
#{immediate: u5} => 0b000 @ immediate
|
||||
#{immediate: i5} => 0b000 @ immediate
|
||||
r{register: u5} => 0b001 @ register
|
||||
[r{register: u5}++] => 0b010 @ register
|
||||
[r{register: u5}--] => 0b011 @ register
|
||||
@ -30,7 +30,7 @@
|
||||
|
||||
#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
|
||||
BWNG{flags: crflags} {dst: operand}, {a: operand} => 0x01 @ 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
|
||||
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
|
||||
MULT{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
|
||||
MODU{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b1101 @ dst
|
||||
MULL{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b1011 @ dst
|
||||
MULS{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b1100 @ 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
|
||||
|
41
src/main.rs
41
src/main.rs
@ -13,6 +13,14 @@ use winit::event::{StartCause, WindowEvent};
|
||||
use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop};
|
||||
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
|
||||
{
|
||||
vm: FootVM,
|
||||
@ -42,24 +50,20 @@ impl App
|
||||
let pixels = &mut self.pixels.as_mut().unwrap();
|
||||
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];
|
||||
|
||||
for k in 0..PIXELS_PER_ADDRESS
|
||||
{
|
||||
let index = i + j * 32;
|
||||
let mut value = self.vm[index + 0xFBFF];
|
||||
let pixel_value = ((value & 0xF) * 17) as u8;
|
||||
let pixel_index = ((ptr * PIXELS_PER_ADDRESS + k) * 4) as usize;
|
||||
frame[pixel_index + 0] = pixel_value;
|
||||
frame[pixel_index + 1] = pixel_value;
|
||||
frame[pixel_index + 2] = pixel_value;
|
||||
frame[pixel_index + 3] = 0xFF;
|
||||
|
||||
for k in 0..16
|
||||
{
|
||||
let pixel_value = ((value & 1) * 255) as u8;
|
||||
let pixel_index = (index as usize * 64) + k * 4;
|
||||
frame[pixel_index + 0] = pixel_value;
|
||||
frame[pixel_index + 1] = pixel_value;
|
||||
frame[pixel_index + 2] = pixel_value;
|
||||
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)
|
||||
{
|
||||
const WIDTH: u32 = 128;
|
||||
const HEIGHT: u32 = 128;
|
||||
|
||||
let window = event_loop.create_window(
|
||||
WindowAttributes::default()
|
||||
.with_resizable(false)
|
||||
.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")
|
||||
).unwrap();
|
||||
let window = Arc::new(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());
|
||||
}
|
||||
|
||||
|
78
src/vm.rs
78
src/vm.rs
@ -110,7 +110,9 @@ enum Instruction
|
||||
CLSH(ConditionalExecutionFlag, bool, Operand, Operand, Operand),
|
||||
ADDI(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),
|
||||
MODU(ConditionalExecutionFlag, bool, Operand, Operand, Operand)
|
||||
}
|
||||
@ -144,7 +146,7 @@ impl TryFrom<u32> for Instruction
|
||||
{
|
||||
let a: Operand = (value & 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)),
|
||||
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)),
|
||||
9 => Ok(ADDI(ceflag, rflag, dst, b, a)),
|
||||
10 => Ok(SUBT(ceflag, rflag, dst, b, a)),
|
||||
11 => Ok(MULT(ceflag, rflag, dst, b, a)),
|
||||
12 => Ok(DIVI(ceflag, rflag, dst, b, a)),
|
||||
13 => Ok(MODU(ceflag, rflag, dst, b, a)),
|
||||
11 => Ok(MULL(ceflag, rflag, dst, b, a)),
|
||||
12 => Ok(MULS(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(())
|
||||
}
|
||||
},
|
||||
@ -197,13 +201,17 @@ macro_rules! run_instruction
|
||||
{
|
||||
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)
|
||||
{
|
||||
$self.$name($d, $a)
|
||||
}
|
||||
}
|
||||
|
||||
*$self.mut_loop_count() = loop_count;
|
||||
}
|
||||
else if $self.check($cef)
|
||||
{
|
||||
@ -214,13 +222,17 @@ macro_rules! run_instruction
|
||||
{
|
||||
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)
|
||||
{
|
||||
$self.$name($d, $a, $b)
|
||||
}
|
||||
}
|
||||
|
||||
*$self.mut_loop_count() = loop_count;
|
||||
}
|
||||
else if $self.check($cef)
|
||||
{
|
||||
@ -294,7 +306,7 @@ impl FootVM
|
||||
{
|
||||
let first_word = self[self.program_counter()];
|
||||
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);
|
||||
match full_instruction_bits.try_into()
|
||||
{
|
||||
@ -326,8 +338,12 @@ impl FootVM
|
||||
run_instruction!(self, cef, rep, addi, dst, a, b),
|
||||
Ok(SUBT(cef, rep, dst, b, a)) =>
|
||||
run_instruction!(self, cef, rep, subt, dst, a, b),
|
||||
Ok(MULT(cef, rep, dst, b, a)) =>
|
||||
run_instruction!(self, cef, rep, mult, 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)) =>
|
||||
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)) =>
|
||||
run_instruction!(self, cef, rep, divi, dst, a, b),
|
||||
Ok(MODU(cef, rep, dst, b, a)) =>
|
||||
@ -422,7 +438,7 @@ impl FootVM
|
||||
{
|
||||
let a = self.load_operand(src_a);
|
||||
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)
|
||||
@ -439,11 +455,25 @@ impl FootVM
|
||||
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 b = self.load_operand(src_b);
|
||||
self.store_operand(dst, a.wrapping_mul(b));
|
||||
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)
|
||||
{
|
||||
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)
|
||||
@ -522,26 +552,12 @@ impl FootVM
|
||||
|
||||
fn loop_count(&self) -> u16
|
||||
{
|
||||
self.registers[29]
|
||||
self.registers[30]
|
||||
}
|
||||
|
||||
fn mut_loop_count(&mut self) -> &mut u16
|
||||
{
|
||||
&mut self.registers[29]
|
||||
}
|
||||
|
||||
fn should_repeat(&mut self) -> bool
|
||||
{
|
||||
if self.loop_count() > 0
|
||||
{
|
||||
*self.mut_loop_count() -= 1;
|
||||
|
||||
true
|
||||
}
|
||||
else
|
||||
{
|
||||
false
|
||||
}
|
||||
&mut self.registers[30]
|
||||
}
|
||||
|
||||
fn check(&self, cef: ConditionalExecutionFlag) -> bool
|
||||
|
Loading…
x
Reference in New Issue
Block a user