mirror of
https://github.com/powdr-labs/powdr.git
synced 2026-05-13 03:00:26 -04:00
Parsing .insn assembly directive.
This commit is contained in:
@@ -12,7 +12,10 @@ fn main() {
|
||||
}
|
||||
|
||||
fn build_lalrpop() {
|
||||
lalrpop::process_root().unwrap();
|
||||
lalrpop::Configuration::new()
|
||||
.emit_rerun_directives(true)
|
||||
.process_current_dir()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn build_instruction_tests() {
|
||||
|
||||
@@ -329,3 +329,74 @@ fn output_files_from_cargo_build_plan(
|
||||
|
||||
assemblies
|
||||
}
|
||||
|
||||
/// Maps an instruction in .insn syntax to Statement::Instruction() in the expected format.
|
||||
///
|
||||
/// See https://www.rowleydownload.co.uk/arm/documentation/gnu/as/RISC_002dV_002dFormats.html
|
||||
pub fn map_insn_i(
|
||||
opcode6: Expression,
|
||||
func3: Expression,
|
||||
rd: Register,
|
||||
rs1: Register,
|
||||
simm12: Expression,
|
||||
) -> Statement {
|
||||
let (Expression::Number(opcode6), Expression::Number(func3)) = (opcode6, func3) else {
|
||||
panic!("Only literal opcode and function are supported in .insn syntax");
|
||||
};
|
||||
|
||||
// These are almost all instructions in RISC-V Instruction Set Manual that
|
||||
// we are supposed to implement and roughly fits the pattern of the I-type
|
||||
// instruction. Only "csr*i" instructions are missing.
|
||||
|
||||
// First we try to match the instructions that uses the I-type encoding
|
||||
// ordinarily, i.e. where all fields are what they are supposed to be:
|
||||
let name = match (opcode6, func3) {
|
||||
(0b1100111, 0b000) => "jalr",
|
||||
(0b0000011, 0b000) => "lb",
|
||||
(0b0000011, 0b001) => "lh",
|
||||
(0b0000011, 0b010) => "lw",
|
||||
(0b0000011, 0b100) => "lbu",
|
||||
(0b0000011, 0b101) => "lhu",
|
||||
(0b0010011, 0b000) => "addi",
|
||||
(0b0010011, 0b010) => "slti",
|
||||
(0b0010011, 0b011) => "sltiu",
|
||||
(0b0010011, 0b100) => "xori",
|
||||
(0b0010011, 0b110) => "ori",
|
||||
(0b0010011, 0b111) => "andi",
|
||||
(0b1110011, 0b001) => "csrrw",
|
||||
(0b1110011, 0b010) => "csrrs",
|
||||
(0b1110011, 0b011) => "csrrc",
|
||||
// won't interpret "csr*i" instructions because it is too weird to
|
||||
// encode an immediate as a register
|
||||
opfunc => {
|
||||
// We now try the instructions that take certain liberties with the
|
||||
// I-type encoding, and don't use the standard arguments for it.
|
||||
let name = match opfunc {
|
||||
(0b0001111, 0b000) => "fence",
|
||||
(0b0001111, 0b001) => "fence.i",
|
||||
(0b1110011, 0b000) => {
|
||||
let Expression::Number(simm12) = simm12 else {
|
||||
panic!(
|
||||
"Only literal simm12 is supported for ecall and ebreak instructions"
|
||||
);
|
||||
};
|
||||
match simm12 {
|
||||
0 => "ecall",
|
||||
1 => "ebreak",
|
||||
_ => panic!("unknown instruction"),
|
||||
}
|
||||
}
|
||||
_ => panic!("unsupported .insn instruction"),
|
||||
};
|
||||
return Statement::Instruction(name.to_string(), Vec::new());
|
||||
}
|
||||
};
|
||||
|
||||
let args = vec![
|
||||
Argument::Register(rd),
|
||||
Argument::Register(rs1),
|
||||
Argument::Expression(simm12),
|
||||
];
|
||||
|
||||
Statement::Instruction(name.to_string(), args)
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
use std::str::FromStr;
|
||||
use asm_utils::ast::{unescape_string, BinaryOpKind as BOp, UnaryOpKind as UOp,
|
||||
new_binary_op as bin_op, new_unary_op as un_op, new_function_op as fn_op};
|
||||
use crate::{Argument, Register, Statement, FunctionKind as FOp, Expression};
|
||||
use crate::{Argument, Register, Statement, FunctionKind as FOp, Expression, map_insn_i};
|
||||
|
||||
grammar;
|
||||
|
||||
@@ -67,9 +67,17 @@ Directive: Statement = {
|
||||
}
|
||||
|
||||
Instruction: Statement = {
|
||||
<InsnDirective>,
|
||||
<DotlessSymbol> <Arguments> => Statement::Instruction(<>)
|
||||
}
|
||||
|
||||
InsnDirective: Statement = {
|
||||
".insn" "i" <opcode6:Expression> "," <func3:Expression> "," <rd:Register> "," <rs1:Register> "," <simm12:Expression> => map_insn_i(opcode6, func3, rd, rs1, simm12),
|
||||
".insn" "i" <opcode6:Expression> "," <func3:Expression> "," <rd:Register> "," <simm12:Expression> "(" <rs1:Register> ")" => map_insn_i(opcode6, func3, rd, rs1, simm12)
|
||||
// TODO: implement the other kinds of .insn instructions.
|
||||
// See https://www.rowleydownload.co.uk/arm/documentation/gnu/as/RISC_002dV_002dFormats.html
|
||||
}
|
||||
|
||||
Arguments: Vec<Argument> = {
|
||||
=> vec![],
|
||||
<mut list:( <Argument> "," )*> <end:Argument> => { list.push(end); list }
|
||||
|
||||
Reference in New Issue
Block a user