From 62a7c80ea796b82ee8a994416bd452bc2a5aeee1 Mon Sep 17 00:00:00 2001 From: Isabelle L Date: Mon, 22 Jun 2020 03:24:25 -0500 Subject: [PATCH] added add instruction assembly --- .gitignore | 1 + README.md | 15 +++++----- ceres-asm/src/lib.rs | 68 ++++++++++++++++++++++++++++++++++---------- src/main.rs | 3 +- test.asm | 4 ++- 5 files changed, 67 insertions(+), 24 deletions(-) diff --git a/.gitignore b/.gitignore index 53eaa21..d2c03d8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target **/*.rs.bk +out.bin diff --git a/README.md b/README.md index 2fdb97b..cff59a2 100644 --- a/README.md +++ b/README.md @@ -29,14 +29,15 @@ god oh fuck what am i even doing ### instructions -##### load - ld:signifier +##### load - `ld:signifier $dest immediate/address` -can be vram/cram/imed +| opcode | signifier | destination | padding | immediate/address | +| ------- | --------- | ----------- | ------- | ------------------ | +| `00001` | `100` | `0000` | `0000` | `0000000000000000` | -- immediate `ld:immd $dest immediate` +##### add - `add $src1 $src2 $dest` - | opcode | signifier | destination | padding | immediate | - | ------- | --------- | ----------- | ------- | ------------------ | - | `00001` | `100` | `0000` | `0000` | `0000000000000000` | +| opcode | padding | source1 | source2 | dest | +| ------- | ----------------- | ------- | ------- | ------ | +| `00010` | `000000000000000` | `0000` | `0000` | `0000` | - \ No newline at end of file diff --git a/ceres-asm/src/lib.rs b/ceres-asm/src/lib.rs index 73eba5f..6ca2483 100644 --- a/ceres-asm/src/lib.rs +++ b/ceres-asm/src/lib.rs @@ -5,6 +5,7 @@ // namespacing use logos::{Lexer, Logos}; +use std::{fs::File, io::prelude::*, path::PathBuf}; /// ceres-asm result type pub type Result = std::result::Result; @@ -18,6 +19,8 @@ pub enum CeresAsmError { LazyBadToken { token: Token }, #[error("was looking for token, found nothing ???")] NoToken, + #[error(transparent)] + StdIo(#[from] std::io::Error), } /// assembler struct @@ -33,7 +36,7 @@ impl<'a> Assembler<'a> { } /// assemble - pub fn assemble(&mut self) -> Result> { + pub fn assemble(&mut self) -> Result { let mut machine_code: Vec = Vec::new(); while let Some(token) = self.lexer.next() { @@ -42,20 +45,13 @@ impl<'a> Assembler<'a> { Token::Comment => continue, Token::Newline => continue, // cases that like, actually make sense to process - Token::Load => { - if let Some(new_token) = self.lexer.next() { - let signifier = Signifier::from_token(&new_token)?; - machine_code.push(self.load(signifier)?); - } else { - return Err(CeresAsmError::NoToken); - } - } + Token::Load => machine_code.push(self.load()?), + Token::Add => machine_code.push(self.add()?), // cases that should straight up not happen _ => return Err(CeresAsmError::LazyBadToken { token }), } } - - Ok(machine_code) + Ok(MachineCode(machine_code)) } // wrapping for lexer.next() with changing to result @@ -68,16 +64,55 @@ impl<'a> Assembler<'a> { } // load instruction assembly - fn load(&mut self, signifier: Signifier) -> Result { - let opcode = 0b00001 as u32; - let signifier = signifier.as_bits() as u32; + fn load(&mut self) -> Result { + let opcode = 0b00001u32; + + let token = self.next()?; + let signifier = Signifier::from_token(&token)?.as_bits() as u32; let token = self.next()?; let register = token.register_index()? as u32; let token = self.next()?; let literal = token.literal()? as u32; - Ok((opcode << 27) | (signifier << 24) | (register << 20) | (0b0000u32 << 16) | literal) + Ok((opcode << 27) | (signifier << 24) | (register << 20) | literal) + } + + // add instruction assembly + fn add(&mut self) -> Result { + let opcode = 0b00010u32; + + let token = self.next()?; + let source_one = token.register_index()? as u32; + let token = self.next()?; + let source_two = token.register_index()? as u32; + let token = self.next()?; + let dest = token.register_index()? as u32; + + Ok((opcode << 27) | (source_one << 8) | (source_two << 4) | dest) + } +} + +/// assembled machine code +pub struct MachineCode(pub Vec); + +impl MachineCode { + /// write the machine code to a file + pub fn write_to_file(&self, dest: Option) -> Result<()> { + let dest = if let Some(path) = dest { path } else { PathBuf::from("out.bin") }; + let mut file = File::create(dest)?; + let data = self.as_u8_vec(); + file.write_all(&data)?; + Ok(()) + } + + // return the machine code as a vec of u8 + fn as_u8_vec(&self) -> Vec { + let mut data: Vec = Vec::new(); + self.0.iter().for_each(|instruction| { + data.extend_from_slice(&instruction.to_le_bytes()); + }); + data } } @@ -159,6 +194,8 @@ pub enum Token { // instructions #[token("ld:")] Load, + #[token("add")] + Add, // logos error #[error] @@ -195,6 +232,7 @@ impl Token { Self::DecimalLiteral(_) => "dec lit".to_owned(), // instructions Self::Load => "ld:".to_owned(), + Self::Add => "add".to_owned(), // errors Self::Error => "ERR".to_owned(), } diff --git a/src/main.rs b/src/main.rs index cb1750e..f44eba4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,7 +19,8 @@ fn wrapper() -> Result<()> { let data = std::fs::read_to_string("test.asm").unwrap(); let mut assembler = ceres_asm::Assembler::new(&data); let asm = assembler.assemble().unwrap(); - asm.iter().for_each(|instruction| println!("ob{:032b}", instruction)); + asm.0.iter().for_each(|instruction| println!("0b{:032b}", instruction)); + asm.write_to_file(None).unwrap(); /* // create a new graphics context diff --git a/test.asm b/test.asm index adca895..6c1316a 100644 --- a/test.asm +++ b/test.asm @@ -1,2 +1,4 @@ ; a simple test -ld:immd $t6 0xffff +ld:immd $t1 0x3333 +ld:immd $t2 0x1111 +add $t1 $t2 $t3