Skip to content

Commit

Permalink
Refactored the assembler to use the new instr_codegen
Browse files Browse the repository at this point in the history
  • Loading branch information
rope-hmg committed May 1, 2024
1 parent 34d9294 commit 65ead32
Show file tree
Hide file tree
Showing 3 changed files with 8,321 additions and 3,411 deletions.
133 changes: 56 additions & 77 deletions apps/assembler/build.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use instr_codegen::{make_name_good, Instr, INSTRUCTIONS};
use instr_codegen::{instr::Instr_Field, INSTRUCTIONS};
use quote::{format_ident, quote};

macro_rules! write_file {
Expand All @@ -11,6 +11,16 @@ macro_rules! write_file {
}};
}

macro_rules! quote_if {
($cond:expr, $($tokens:tt)*) => {
if $cond {
quote!($($tokens)*)
} else {
quote!()
}
};
}

fn main() {
println!("cargo:rerun-if-changed=../../libs/instr_codegen/src/lib.rs");

Expand All @@ -19,76 +29,48 @@ fn main() {
let mut parsers_fns = Vec::new();
let mut index_to_parser = Vec::new();

for (index, (name, instr)) in INSTRUCTIONS.iter().enumerate() {
for (index, descriptor) in INSTRUCTIONS.iter().enumerate() {
let instr = descriptor.parse();
let index = index as u64;

let instr_name = format_ident!("{}", make_name_good(name));
let token_name = instr.name;
let instr_name = format_ident!("{}", instr.ident);
let parser_ident = format_ident!("parse_{}", instr_name.to_string().to_lowercase());

let instr = match instr {
Instr::V_Type { .. } => quote!(Instruction::#instr_name),

Instr::R_Type { fields, .. } => {
let mut body = quote!();

if fields.rd {
body = if fields.rs1 || fields.rs2 {
quote!(#body rd: parse_register_comma(asm),)
} else {
quote!(#body rd: parse_register(asm),)
};
}

if fields.rs1 {
body = if fields.rs2 {
quote!(#body rs1: parse_register_comma(asm),)
} else {
quote!(#body rs1: parse_register(asm),)
};
}

if fields.rs2 {
body = quote!(#body rs2: parse_register(asm),);
}

quote! {
Instruction::#instr_name {
#body
}
}
},

Instr::I_Type {
fields, conditions, ..
} => {
let mut body = quote!();

// TODO: Generalise this.
if fields.rd {
body = if fields.imm {
quote!(#body rd: parse_register_comma(asm),)
} else {
quote!(#body rd: parse_register(asm),)
};
}

if fields.imm {
body = if conditions.sign {
quote!(#body imm: parse_imm(asm),)
} else {
quote!(#body imm: parse_imm(asm) as u16,)
};
}
let instr_instantiation = if instr.fields.is_empty() {
quote!(Instruction::#instr_name)
} else {
let mut items = quote!();
let mut body = quote!();

for (index, Instr_Field { name, master, .. }) in instr.fields.iter().enumerate() {
let name = format_ident!("{}", name);

let parse_function = format_ident!("parse_{}", master.ty.to_lowercase());
let parse_comma =
quote_if!(index < instr.fields.len() - 1, asm.expects(Token_Kind::Comma););

items = quote! {
#items
let #name = #parse_function(asm);
#parse_comma
};

body = quote! {
#body
#name,
};
}

quote! {
Instruction::#instr_name {
#body
}
quote! {
#items
Instruction::#instr_name {
#body
}
},
}
};

token_definitions.push(quote!(#[token(#name)] #instr_name,));
token_definitions.push(quote!(#[token(#token_name)] #instr_name,));

token_to_token.push(quote! {
Lexed_Token::#instr_name => (
Expand All @@ -98,11 +80,12 @@ fn main() {
),
});

// TODO: Reduce the amount of code generated by unifying like parsers.
parsers_fns.push(quote! {
fn #parser_ident<'source>(asm: &mut Assembler<'source>) {
let instr = #instr;
asm.expects(Token_Kind::Newline);
let instr = { #instr_instantiation };
asm.object.code_instrs.push(instr.encode());
asm.expects(Token_Kind::Newline);
}
});

Expand Down Expand Up @@ -263,27 +246,23 @@ fn main() {
}

#[inline(always)]
fn parse_register_comma<'source>(asm: &mut Assembler<'source>) -> Register {
asm.expects(Token_Kind::Register);
let index = unsafe { asm.entry().value.integer };
asm.expects(Token_Kind::Comma);
Register::from_index(index as u8)
}

#[inline(always)]
fn parse_imm<'source>(asm: &mut Assembler<'source>) -> i16 {
fn parse_imm<'source>(asm: &mut Assembler<'source>) -> u64 {
if asm.matches(Token_Kind::Colon) {
asm.expects(Token_Kind::Identifier);
asm.patch_label()
asm.patch_label() as u64
} else if asm.matches(Token_Kind::Ampersand) {
asm.expects(Token_Kind::Identifier);
asm.patch_address()
asm.patch_address() as u64
} else {
asm.expects(Token_Kind::Number);
unsafe { asm.entry().value.integer as i16 }
unsafe { asm.entry().value.integer }
}
}

#[inline(always)] fn parse_u16<'source>(asm: &mut Assembler<'source>) -> u16 { parse_imm(asm) as u16 }
#[inline(always)] fn parse_i16<'source>(asm: &mut Assembler<'source>) -> i16 { parse_imm(asm) as i16 }
#[inline(always)] fn parse_i32<'source>(asm: &mut Assembler<'source>) -> i32 { parse_imm(asm) as i32 }

#(#parsers_fns)*
};

Expand Down
Loading

0 comments on commit 65ead32

Please sign in to comment.