Update multiply instructions

This commit is contained in:
shylie 2025-03-16 10:22:45 -04:00
parent 8bdd8a47f6
commit 96a8152170
5 changed files with 96 additions and 63 deletions

View File

@ -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
View 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

View File

@ -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

View File

@ -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];
for k in 0..PIXELS_PER_ADDRESS
{ {
let index = i + j * 32; let pixel_value = ((value & 0xF) * 17) as u8;
let mut value = self.vm[index + 0xFBFF]; 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 value >>= BITS_PER_PIXEL;
{
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;
}
} }
} }
@ -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());
} }

View File

@ -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