add PowerISA decoder #7
2 changed files with 73168 additions and 130361 deletions
|
|
@ -20,14 +20,9 @@ use crate::{
|
|||
array_vec::{ArrayVec, Length},
|
||||
},
|
||||
};
|
||||
use fayalite::{
|
||||
int::{BoolOrIntType, UIntInRange},
|
||||
module::wire_with_loc,
|
||||
prelude::*,
|
||||
ty::StaticType,
|
||||
};
|
||||
use fayalite::{int::UIntInRange, module::wire_with_loc, prelude::*, ty::StaticType};
|
||||
use std::{
|
||||
collections::{BTreeMap, btree_map::Entry},
|
||||
collections::{BTreeMap, HashMap, hash_map::Entry},
|
||||
ops::RangeInclusive,
|
||||
};
|
||||
|
||||
|
|
@ -136,7 +131,7 @@ const VSX_MNEMONICS: &[&str] = &[
|
|||
];
|
||||
|
||||
#[derive(Debug)]
|
||||
struct DecodeState {
|
||||
struct DecodeState<'a> {
|
||||
mnemonic: &'static str,
|
||||
arguments: Option<&'static str>,
|
||||
conditions: Option<&'static str>,
|
||||
|
|
@ -147,6 +142,7 @@ struct DecodeState {
|
|||
first_input: Expr<UInt<32>>,
|
||||
second_input: Expr<HdlOption<UInt<32>>>,
|
||||
second_input_used: Expr<Bool>,
|
||||
field_wires: &'a mut HashMap<String, HashMap<Expr<UInt>, Expr<UInt>>>,
|
||||
}
|
||||
|
||||
trait FieldSet {
|
||||
|
|
@ -320,7 +316,7 @@ fn cr_bit_flag_index(
|
|||
(MOpRegNum::power_isa_cr_reg(field_num), flag_index)
|
||||
}
|
||||
|
||||
impl DecodeState {
|
||||
impl DecodeState<'_> {
|
||||
fn form(&self) -> &'static str {
|
||||
let mut title_words = self
|
||||
.header
|
||||
|
|
@ -399,6 +395,26 @@ impl DecodeState {
|
|||
(var.trim(), value.trim())
|
||||
})
|
||||
}
|
||||
fn get_field_wire(&mut self, value: Expr<UInt>, name: &str) -> Expr<UInt> {
|
||||
let form = self.form();
|
||||
let width = value.ty().width();
|
||||
let wire_name =
|
||||
format!("{form}_{name}_{width}").replace(|c: char| !c.is_ascii_alphanumeric(), "_");
|
||||
match self
|
||||
.field_wires
|
||||
.entry(wire_name.clone())
|
||||
.or_default()
|
||||
.entry(value)
|
||||
{
|
||||
Entry::Vacant(entry) => {
|
||||
let wire = wire_with_loc(&wire_name, SourceLocation::caller(), value.ty());
|
||||
connect(wire, value);
|
||||
entry.insert(wire);
|
||||
wire
|
||||
}
|
||||
Entry::Occupied(entry) => *entry.get(),
|
||||
}
|
||||
}
|
||||
#[hdl]
|
||||
fn decode_word(
|
||||
&mut self,
|
||||
|
|
@ -478,27 +494,19 @@ impl DecodeState {
|
|||
};
|
||||
field_pieces.filled_pieces.push(field);
|
||||
if field_pieces.filled_pieces.len() == field_pieces.piece_count {
|
||||
let wire = wire_with_loc(
|
||||
&format!("{}_{name}", self.mnemonic)
|
||||
.replace(|c: char| !c.is_ascii_alphanumeric(), "_"),
|
||||
SourceLocation::caller(),
|
||||
UInt[field_pieces
|
||||
.filled_pieces
|
||||
.iter()
|
||||
.map(|v| v.ty().width())
|
||||
.sum::<usize>()],
|
||||
);
|
||||
let filled_pieces = std::mem::take(&mut field_pieces.filled_pieces);
|
||||
// filled_pieces are in lsb to msb order
|
||||
let mut filled_pieces = field_pieces.filled_pieces.drain(..);
|
||||
let mut filled_pieces = filled_pieces.into_iter();
|
||||
let Some(mut value) = filled_pieces.next() else {
|
||||
unreachable!();
|
||||
};
|
||||
let mut shift = value.ty().width();
|
||||
let mut value_width = value.ty().width();
|
||||
for next_value in filled_pieces {
|
||||
value = value | (next_value << shift);
|
||||
shift += next_value.ty().width();
|
||||
value = value | (next_value << value_width);
|
||||
value_width += next_value.ty().width();
|
||||
}
|
||||
connect(wire, value);
|
||||
value = value.cast_to(UInt[value_width]);
|
||||
let wire = self.get_field_wire(value, name);
|
||||
fields.insert(name, wire);
|
||||
}
|
||||
} else {
|
||||
|
|
@ -523,8 +531,8 @@ impl DecodeState {
|
|||
let mut f = Some(f);
|
||||
#[hdl]
|
||||
#[track_caller]
|
||||
fn run<FS: FieldSet, F: FnOnce(&mut DecodeState, FS)>(
|
||||
this: &mut DecodeState,
|
||||
fn run<'a, FS: FieldSet, F: FnOnce(&mut DecodeState<'a>, FS)>(
|
||||
this: &mut DecodeState<'a>,
|
||||
matches: Expr<Bool>,
|
||||
fields: &mut BTreeMap<&str, Expr<UInt>>,
|
||||
f: &mut Option<F>,
|
||||
|
|
@ -2082,23 +2090,25 @@ impl DecodeState {
|
|||
}
|
||||
}
|
||||
|
||||
type DecodeFn = fn(&mut DecodeState);
|
||||
type DecodeFn = fn(&mut DecodeState<'_>);
|
||||
|
||||
const DECODE_FNS: &[(&[&str], DecodeFn)] = &[
|
||||
(&["b", "ba", "bl", "bla"], DecodeState::decode_b_ba_bl_bla),
|
||||
(&["b", "ba", "bl", "bla"], |state| {
|
||||
DecodeState::decode_b_ba_bl_bla(state)
|
||||
}),
|
||||
(
|
||||
&[
|
||||
"bc", "bca", "bcl", "bcla", "bclr", "bclrl", "bcctr", "bcctrl", "bctar", "bctarl",
|
||||
],
|
||||
DecodeState::decode_bc_bclr_bcctr_bctar,
|
||||
|state| DecodeState::decode_bc_bclr_bcctr_bctar(state),
|
||||
),
|
||||
(
|
||||
&[
|
||||
"crand", "crnand", "cror", "crxor", "crnor", "creqv", "crandc", "crorc",
|
||||
],
|
||||
DecodeState::decode_crand_crnand_cror_crxor_crnor_creqv_crandc_crorc,
|
||||
|state| DecodeState::decode_crand_crnand_cror_crxor_crnor_creqv_crandc_crorc(state),
|
||||
),
|
||||
(&["mcrf"], DecodeState::decode_mcrf),
|
||||
(&["mcrf"], |state| DecodeState::decode_mcrf(state)),
|
||||
(&["sc", "scv"], |_state| {
|
||||
// TODO
|
||||
}),
|
||||
|
|
@ -2108,14 +2118,14 @@ const DECODE_FNS: &[(&[&str], DecodeFn)] = &[
|
|||
"plha", "lhax", "lhau", "lhaux", "lwz", "plwz", "lwzx", "lwzu", "lwzux", "lwa", "plwa",
|
||||
"lwax", "lwaux", "ld", "pld", "ldx", "ldu", "ldux",
|
||||
],
|
||||
DecodeState::decode_load_8_16_32_64_bit,
|
||||
|state| DecodeState::decode_load_8_16_32_64_bit(state),
|
||||
),
|
||||
(
|
||||
&[
|
||||
"stb", "pstb", "stbx", "stbu", "stbux", "sth", "psth", "sthx", "sthu", "sthux", "stw",
|
||||
"pstw", "stwx", "stwu", "stwux", "std", "pstd", "stdx", "stdu", "stdux",
|
||||
],
|
||||
DecodeState::decode_store_8_16_32_64_bit,
|
||||
|state| DecodeState::decode_store_8_16_32_64_bit(state),
|
||||
),
|
||||
(&["lq", "plq", "stq", "pstq"], |_state| {
|
||||
// TODO
|
||||
|
|
@ -2132,43 +2142,46 @@ const DECODE_FNS: &[(&[&str], DecodeFn)] = &[
|
|||
(&["lswi", "lswx", "stswi", "stswx"], |_state| {
|
||||
// load/store string are intentionally not implemented
|
||||
}),
|
||||
(&["addi", "paddi"], DecodeState::decode_addi_paddi),
|
||||
(&["addis"], DecodeState::decode_addis),
|
||||
(&["addpcis"], DecodeState::decode_addpcis),
|
||||
(&["add", "add.", "addo", "addo."], DecodeState::decode_add),
|
||||
(&["addic", "addic."], DecodeState::decode_addic),
|
||||
(
|
||||
&["subf", "subf.", "subfo", "subfo."],
|
||||
DecodeState::decode_subf_subfc,
|
||||
),
|
||||
(&["subfic"], DecodeState::decode_subfic),
|
||||
(
|
||||
&["addc", "addc.", "addco", "addco."],
|
||||
DecodeState::decode_addc,
|
||||
),
|
||||
(
|
||||
&["subfc", "subfc.", "subfco", "subfco."],
|
||||
DecodeState::decode_subf_subfc,
|
||||
),
|
||||
(
|
||||
&["adde", "adde.", "addeo", "addeo."],
|
||||
DecodeState::decode_adde,
|
||||
),
|
||||
(
|
||||
&["subfe", "subfe.", "subfeo", "subfeo."],
|
||||
DecodeState::decode_subfe,
|
||||
),
|
||||
(&["addi", "paddi"], |state| {
|
||||
DecodeState::decode_addi_paddi(state)
|
||||
}),
|
||||
(&["addis"], |state| DecodeState::decode_addis(state)),
|
||||
(&["addpcis"], |state| DecodeState::decode_addpcis(state)),
|
||||
(&["add", "add.", "addo", "addo."], |state| {
|
||||
DecodeState::decode_add(state)
|
||||
}),
|
||||
(&["addic", "addic."], |state| {
|
||||
DecodeState::decode_addic(state)
|
||||
}),
|
||||
(&["subf", "subf.", "subfo", "subfo."], |state| {
|
||||
DecodeState::decode_subf_subfc(state)
|
||||
}),
|
||||
(&["subfic"], |state| DecodeState::decode_subfic(state)),
|
||||
(&["addc", "addc.", "addco", "addco."], |state| {
|
||||
DecodeState::decode_addc(state)
|
||||
}),
|
||||
(&["subfc", "subfc.", "subfco", "subfco."], |state| {
|
||||
DecodeState::decode_subf_subfc(state)
|
||||
}),
|
||||
(&["adde", "adde.", "addeo", "addeo."], |state| {
|
||||
DecodeState::decode_adde(state)
|
||||
}),
|
||||
(&["subfe", "subfe.", "subfeo", "subfeo."], |state| {
|
||||
DecodeState::decode_subfe(state)
|
||||
}),
|
||||
(
|
||||
&[
|
||||
"addme", "addme.", "addmeo", "addmeo.", "addze", "addze.", "addzeo", "addzeo.",
|
||||
"subfme", "subfme.", "subfmeo", "subfmeo.", "subfze", "subfze.", "subfzeo", "subfzeo.",
|
||||
],
|
||||
DecodeState::decode_addme_subfme_addze_subfze,
|
||||
|state| DecodeState::decode_addme_subfme_addze_subfze(state),
|
||||
),
|
||||
(&["addex"], |_state| {
|
||||
// TODO
|
||||
}),
|
||||
(&["neg", "neg.", "nego", "nego."], DecodeState::decode_neg),
|
||||
(&["neg", "neg.", "nego", "nego."], |state| {
|
||||
DecodeState::decode_neg(state)
|
||||
}),
|
||||
(
|
||||
&[
|
||||
"mulli", "mullw", "mullw.", "mullwo", "mullwo.", "mulhw", "mulhw.", "mulhwu", "mulhwu.",
|
||||
|
|
@ -2209,12 +2222,12 @@ const DECODE_FNS: &[(&[&str], DecodeFn)] = &[
|
|||
// TODO
|
||||
},
|
||||
),
|
||||
(&["cmpi"], DecodeState::decode_cmpi),
|
||||
(&["cmp"], DecodeState::decode_cmp),
|
||||
(&["cmpli"], DecodeState::decode_cmpli),
|
||||
(&["cmpl"], DecodeState::decode_cmpl),
|
||||
(&["cmprb"], DecodeState::decode_cmprb),
|
||||
(&["cmpeqb"], DecodeState::decode_cmpeqb),
|
||||
(&["cmpi"], |state| DecodeState::decode_cmpi(state)),
|
||||
(&["cmp"], |state| DecodeState::decode_cmp(state)),
|
||||
(&["cmpli"], |state| DecodeState::decode_cmpli(state)),
|
||||
(&["cmpl"], |state| DecodeState::decode_cmpl(state)),
|
||||
(&["cmprb"], |state| DecodeState::decode_cmprb(state)),
|
||||
(&["cmpeqb"], |state| DecodeState::decode_cmpeqb(state)),
|
||||
(&["twi", "tw", "tdi", "td"], |_state| {
|
||||
// TODO
|
||||
}),
|
||||
|
|
@ -2223,18 +2236,18 @@ const DECODE_FNS: &[(&[&str], DecodeFn)] = &[
|
|||
}),
|
||||
(
|
||||
&["andi.", "andis.", "ori", "oris", "xori", "xoris"],
|
||||
DecodeState::decode_andis_oris_xoris,
|
||||
|state| DecodeState::decode_andis_oris_xoris(state),
|
||||
),
|
||||
(
|
||||
&[
|
||||
"and", "and.", "xor", "xor.", "nand", "nand.", "or", "or.", "orc", "orc.", "nor",
|
||||
"nor.", "eqv", "eqv.", "andc", "andc.",
|
||||
],
|
||||
DecodeState::decode_and_xor_nand_or_orc_nor_eqv_andc,
|
||||
|state| DecodeState::decode_and_xor_nand_or_orc_nor_eqv_andc(state),
|
||||
),
|
||||
(
|
||||
&["extsb", "extsb.", "extsh", "extsh.", "extsw", "extsw."],
|
||||
DecodeState::decode_extsb_extsh_extsw,
|
||||
|state| DecodeState::decode_extsb_extsh_extsw(state),
|
||||
),
|
||||
(&["cmpb"], |_state| {
|
||||
// TODO
|
||||
|
|
@ -2264,7 +2277,7 @@ const DECODE_FNS: &[(&[&str], DecodeFn)] = &[
|
|||
"slw", "slw.", "srw", "srw.", "srawi", "srawi.", "sraw", "sraw.", "sld", "sld.",
|
||||
"sradi", "sradi.", "srd", "srd.", "srad", "srad.",
|
||||
],
|
||||
DecodeState::decode_shift,
|
||||
|state| DecodeState::decode_shift(state),
|
||||
),
|
||||
(&["extswsli", "extswsli."], |_state| {
|
||||
// TODO
|
||||
|
|
@ -2292,7 +2305,7 @@ const DECODE_FNS: &[(&[&str], DecodeFn)] = &[
|
|||
// TODO
|
||||
},
|
||||
),
|
||||
(&["mcrxrx"], DecodeState::decode_mcrxrx),
|
||||
(&["mcrxrx"], |state| DecodeState::decode_mcrxrx(state)),
|
||||
(
|
||||
&[
|
||||
"mtocrf", "mtcrf", "mfocrf", "mfcr", "setb", "setbc", "setbcr", "setnbc", "setnbcr",
|
||||
|
|
@ -2301,7 +2314,7 @@ const DECODE_FNS: &[(&[&str], DecodeFn)] = &[
|
|||
// TODO
|
||||
},
|
||||
),
|
||||
(&["pnop"], DecodeState::decode_pnop),
|
||||
(&["pnop"], |state| DecodeState::decode_pnop(state)),
|
||||
(FP_MNEMONICS, |_state| {
|
||||
// TODO(FP)
|
||||
}),
|
||||
|
|
@ -2395,6 +2408,7 @@ pub fn decode_one_insn() {
|
|||
assert!(!duplicate, "duplicate mnemonic in DECODE_FNS: {mnemonic:?}");
|
||||
}
|
||||
}
|
||||
let mut field_wires = Default::default();
|
||||
for insn in Instructions::get().instructions() {
|
||||
for header in insn.header() {
|
||||
for mnemonic_line in header.mnemonics().lines() {
|
||||
|
|
@ -2438,6 +2452,7 @@ pub fn decode_one_insn() {
|
|||
first_input,
|
||||
second_input,
|
||||
second_input_used,
|
||||
field_wires: &mut field_wires,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue