|
|
@@ -13,11 +13,9 @@ pub type Result<T> = std::result::Result<T, CeresAsmError>; |
|
|
|
/// ceres-asm error type |
|
|
|
#[derive(Debug, thiserror::Error)] |
|
|
|
pub enum CeresAsmError { |
|
|
|
#[error("wrong token found:\nexpected: {expected:?}\n found: {found:?}")] |
|
|
|
BadToken { expected: Token, found: Token }, |
|
|
|
#[error("bad token: {token:?}")] |
|
|
|
LazyBadToken { token: Token }, |
|
|
|
#[error("was looking for token, found nothing ???")] |
|
|
|
#[error("wrong token found:\nexpected: {expected}\n found: {found:?}")] |
|
|
|
BadToken { expected: String, found: Token }, |
|
|
|
#[error("was looking for token, found nothing")] |
|
|
|
NoToken, |
|
|
|
#[error(transparent)] |
|
|
|
StdIo(#[from] std::io::Error), |
|
|
@@ -49,9 +47,19 @@ impl<'a> Assembler<'a> { |
|
|
|
Token::Add => machine_code.push(self.register_instruction(0b00010u32)?), |
|
|
|
Token::Sub => machine_code.push(self.register_instruction(0b00011u32)?), |
|
|
|
// cases that should straight up not happen |
|
|
|
_ => return Err(CeresAsmError::LazyBadToken { token }), |
|
|
|
_ => { |
|
|
|
return Err(CeresAsmError::BadToken { |
|
|
|
expected: "an instruction".to_owned(), |
|
|
|
found: token, |
|
|
|
}) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// pad with empty space |
|
|
|
(0..(((std::u16::MAX / 2) as usize) - machine_code.len())) |
|
|
|
.for_each(|_| machine_code.push(0x0000_0000u32)); |
|
|
|
|
|
|
|
Ok(MachineCode(machine_code)) |
|
|
|
} |
|
|
|
|
|
|
@@ -76,7 +84,7 @@ impl<'a> Assembler<'a> { |
|
|
|
|
|
|
|
fn immediate_instruction(&mut self, opcode: u32) -> Result<u32> { |
|
|
|
let token = self.next()?; |
|
|
|
let signifier = Signifier::from_token(&token)?.as_bits() as u32; |
|
|
|
let signifier = token.signifier_bits()? as u32; |
|
|
|
let token = self.next()?; |
|
|
|
let register = token.register_index()? as u32; |
|
|
|
let token = self.next()?; |
|
|
@@ -108,32 +116,6 @@ impl MachineCode { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
enum Signifier { |
|
|
|
VideoMemory, |
|
|
|
CartMemory, |
|
|
|
Immediate, |
|
|
|
} |
|
|
|
|
|
|
|
impl Signifier { |
|
|
|
fn from_token(token: &Token) -> Result<Self> { |
|
|
|
match token { |
|
|
|
Token::VideoMemory => Ok(Self::VideoMemory), |
|
|
|
Token::CartMemory => Ok(Self::CartMemory), |
|
|
|
Token::Immediate => Ok(Self::Immediate), |
|
|
|
_ => Err(CeresAsmError::LazyBadToken { token: token.clone() }), |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// returns the signifier as bits stored in a u8 |
|
|
|
fn as_bits(self) -> u8 { |
|
|
|
match self { |
|
|
|
Self::VideoMemory => 0b010, |
|
|
|
Self::CartMemory => 0b001, |
|
|
|
Self::Immediate => 0b100, |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// token |
|
|
|
#[derive(Logos, Debug, PartialEq, Clone, Copy)] |
|
|
|
pub enum Token { |
|
|
@@ -199,10 +181,10 @@ pub enum Token { |
|
|
|
|
|
|
|
impl Token { |
|
|
|
// returns the index of a register |
|
|
|
fn register_index(&self) -> Result<u8> { |
|
|
|
fn register_index(self) -> Result<u8> { |
|
|
|
match self { |
|
|
|
Self::RegisterIndex(index) => Ok(index.clone() as u8), |
|
|
|
Self::TemporaryRegister(index) => Ok(index.clone() as u8 + 9), |
|
|
|
Self::RegisterIndex(index) => Ok(index as u8), |
|
|
|
Self::TemporaryRegister(index) => Ok(index as u8 + 9), |
|
|
|
Self::ZeroRegister => Ok(0), |
|
|
|
Self::ProgramCounter => Ok(1), |
|
|
|
Self::StackPointer => Ok(2), |
|
|
@@ -212,17 +194,27 @@ impl Token { |
|
|
|
Self::ArgumentTwo => Ok(6), |
|
|
|
Self::ReturnZero => Ok(7), |
|
|
|
Self::ReturnOne => Ok(8), |
|
|
|
_ => return Err(CeresAsmError::LazyBadToken { token: self.clone() }), |
|
|
|
_ => Err(CeresAsmError::BadToken { expected: "a register".to_owned(), found: self }), |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// returns literals as a u16 |
|
|
|
fn literal(&self) -> Result<u16> { |
|
|
|
fn literal(self) -> Result<u16> { |
|
|
|
match self { |
|
|
|
Self::HexLiteral(val) => Ok(val), |
|
|
|
Self::BinaryLiteral(val) => Ok(val), |
|
|
|
Self::DecimalLiteral(val) => Ok(val), |
|
|
|
_ => Err(CeresAsmError::BadToken { expected: "a literal".to_owned(), found: self }), |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// if the token is a signifier return it's bits |
|
|
|
fn signifier_bits(self) -> Result<u8> { |
|
|
|
match self { |
|
|
|
Self::HexLiteral(val) => Ok(*val), |
|
|
|
Self::BinaryLiteral(val) => Ok(*val), |
|
|
|
Self::DecimalLiteral(val) => Ok(*val), |
|
|
|
_ => Err(CeresAsmError::LazyBadToken { token: self.clone() }), |
|
|
|
Self::CartMemory => Ok(0b001u8), |
|
|
|
Self::VideoMemory => Ok(0b010u8), |
|
|
|
Self::Immediate => Ok(0b100u8), |
|
|
|
_ => Err(CeresAsmError::BadToken { expected: "a signifier".to_owned(), found: self }), |
|
|
|
} |
|
|
|
} |
|
|
|
} |