Skip to content

Commit

Permalink
Merge pull request #615 from powdr-labs/fence-instruction
Browse files Browse the repository at this point in the history
Implementing fence and fence.i instructions.
  • Loading branch information
lvella authored Sep 25, 2023
2 parents b0a3869 + 7bf8d50 commit 118a401
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 13 deletions.
6 changes: 6 additions & 0 deletions asm_utils/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! Common crate for generalized assembly handling.
use ast::{Argument, FunctionOpKind, Register};

pub mod ast;
pub mod data_parser;
pub mod data_storage;
Expand All @@ -9,4 +11,8 @@ pub mod utils;

pub trait Architecture {
fn instruction_ends_control_flow(instr: &str) -> bool;
fn get_references<'a, R: Register, F: FunctionOpKind>(
instr: &str,
args: &'a [Argument<R, F>],
) -> Vec<&'a str>;
}
27 changes: 17 additions & 10 deletions asm_utils/src/reachability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,25 +168,32 @@ pub fn extract_label_offsets<R: Register, F: FunctionOpKind>(
})
}

pub fn references_in_statement<R: Register, F: FunctionOpKind>(
pub fn references_in_statement<R: Register, F: FunctionOpKind, A: Architecture>(
statement: &Statement<R, F>,
) -> BTreeSet<&str> {
let mut ret = BTreeSet::new();
match statement {
Statement::Label(_) | Statement::Directive(_, _) => (),
Statement::Instruction(_, args) => {
for arg in args {
arg.post_visit_expressions(&mut |expr| {
if let Expression::Symbol(sym) = expr {
ret.insert(sym.as_str());
}
});
}
Statement::Instruction(name, args) => {
ret.extend(A::get_references(name, args));
}
};
ret
}

pub fn symbols_in_args<R: Register, F: FunctionOpKind>(args: &[Argument<R, F>]) -> Vec<&str> {
let mut ret = Vec::new();
for arg in args {
arg.post_visit_expressions(&mut |expr| {
if let Expression::Symbol(sym) = expr {
ret.push(sym.as_str());
}
});
}

ret
}

fn basic_block_references_starting_from<R: Register, F: FunctionOpKind, A: Architecture>(
statements: &[Statement<R, F>],
) -> (Vec<&str>, Vec<&str>) {
Expand All @@ -196,7 +203,7 @@ fn basic_block_references_starting_from<R: Register, F: FunctionOpKind, A: Archi
if let Statement::Label(l) = s {
seen_labels.push(l.as_str());
} else {
referenced_labels.extend(references_in_statement(s))
referenced_labels.extend(references_in_statement::<R, F, A>(s))
}
});
(referenced_labels.into_iter().collect(), seen_labels)
Expand Down
24 changes: 21 additions & 3 deletions riscv/src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use asm_utils::{
data_parser::{self, DataValue},
data_storage::{store_data_objects, SingleDataValue},
parser::parse_asm,
reachability,
reachability::{self, symbols_in_args},
utils::{
argument_to_escaped_symbol, argument_to_number, escape_label, expression_to_number, quote,
},
Expand Down Expand Up @@ -70,13 +70,28 @@ impl Architecture for RiscvArchitecture {
| "srli" | "srl" | "srai" | "seqz" | "snez" | "slt" | "slti" | "sltu" | "sltiu"
| "sgtz" | "beq" | "beqz" | "bgeu" | "bltu" | "blt" | "bge" | "bltz" | "blez"
| "bgtz" | "bgez" | "bne" | "bnez" | "jal" | "jalr" | "call" | "ecall" | "ebreak"
| "lw" | "lb" | "lbu" | "lhu" | "sw" | "sh" | "sb" | "nop" => false,
| "lw" | "lb" | "lbu" | "lhu" | "sw" | "sh" | "sb" | "nop" | "fence" | "fence.i" => {
false
}
"j" | "jr" | "tail" | "ret" | "unimp" => true,
_ => {
panic!("Unknown instruction: {instr}");
}
}
}

fn get_references<'a, R: asm_utils::ast::Register, F: asm_utils::ast::FunctionOpKind>(
instr: &str,
args: &'a [asm_utils::ast::Argument<R, F>],
) -> Vec<&'a str> {
// fence arguments are not symbols, they are like reserved
// keywords affecting the instruction behavior
if instr.starts_with("fence") {
Vec::new()
} else {
symbols_in_args(args)
}
}
}

pub fn machine_decls() -> Vec<&'static str> {
Expand Down Expand Up @@ -670,7 +685,7 @@ fn preamble() -> String {
wrap_bit * (1 - wrap_bit) = 0;
}
// Input is a 32 bit unsigned number. We check the 7th bit and set all higher bits to that value.
// Input is a 32 bit unsigned number. We check bit 7 and set all higher bits to that value.
instr sign_extend_byte Y -> X {
// wrap_bit is used as sign_bit here.
Y = Y_7bit + wrap_bit * 0x80 + X_b2 * 0x100 + X_b3 * 0x10000 + X_b4 * 0x1000000,
Expand Down Expand Up @@ -1346,6 +1361,9 @@ fn process_instruction(instr: &str, args: &[Argument]) -> Vec<String> {
only_if_no_write_to_zero(format!("{rd} <== load_label({label});"), rd)
}

// atomic and synchronization
"fence" | "fence.i" => vec![],

_ => {
panic!("Unknown instruction: {instr}");
}
Expand Down

0 comments on commit 118a401

Please sign in to comment.