mirror of
https://github.com/powdr-labs/powdr.git
synced 2026-05-13 03:00:26 -04:00
Merge pull request #615 from powdr-labs/fence-instruction
Implementing fence and fence.i instructions.
This commit is contained in:
@@ -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;
|
||||
@@ -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>;
|
||||
}
|
||||
|
||||
@@ -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>) {
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
@@ -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> {
|
||||
@@ -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,
|
||||
@@ -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}");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user