Browse Source

added add instruction assembly

master
Isabelle L. 5 years ago
parent
commit
62a7c80ea7
5 changed files with 67 additions and 24 deletions
  1. +1
    -0
      .gitignore
  2. +8
    -7
      README.md
  3. +53
    -15
      ceres-asm/src/lib.rs
  4. +2
    -1
      src/main.rs
  5. +3
    -1
      test.asm

+ 1
- 0
.gitignore View File

@@ -1,2 +1,3 @@
/target
**/*.rs.bk
out.bin

+ 8
- 7
README.md View File

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


+ 53
- 15
ceres-asm/src/lib.rs View File

@@ -5,6 +5,7 @@

// namespacing
use logos::{Lexer, Logos};
use std::{fs::File, io::prelude::*, path::PathBuf};

/// ceres-asm result type
pub type Result<T> = std::result::Result<T, CeresAsmError>;
@@ -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<Vec<u32>> {
pub fn assemble(&mut self) -> Result<MachineCode> {
let mut machine_code: Vec<u32> = 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<u32> {
let opcode = 0b00001 as u32;
let signifier = signifier.as_bits() as u32;
fn load(&mut self) -> Result<u32> {
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<u32> {
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<u32>);

impl MachineCode {
/// write the machine code to a file
pub fn write_to_file(&self, dest: Option<PathBuf>) -> 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<u8> {
let mut data: Vec<u8> = 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(),
}


+ 2
- 1
src/main.rs View File

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


+ 3
- 1
test.asm View File

@@ -1,2 +1,4 @@
; a simple test
ld:immd $t6 0xffff
ld:immd $t1 0x3333
ld:immd $t2 0x1111
add $t1 $t2 $t3

Loading…
Cancel
Save