implement a more readable bit mask syntax, add (ldXX Wr Rd Rd) with separate dest and both sources

This commit is contained in:
2020-10-17 14:54:51 +02:00
parent 26616e20cb
commit 3999c51eb7
19 changed files with 602 additions and 310 deletions
+4 -4
View File
@@ -1,5 +1,5 @@
use crsn::asm::data::{Rd, Wr};
use crsn::builtin::defs::BitSlice;
use crsn::builtin::defs::BitMask;
/// A low level instruction
#[derive(Clone, Debug, Eq, PartialEq)]
@@ -20,11 +20,11 @@ pub enum ArithOp {
/// Reverse bits
Rbit { dst: Wr, src: Rd },
/// Count leading zeros in a slice
Clz { dst: Wr, src: Rd, slice: BitSlice },
Clz { dst: Wr, src: Rd, mask: BitMask },
/// Count leading ones in a slice
Clo { dst: Wr, src: Rd, slice: BitSlice },
Clo { dst: Wr, src: Rd, mask: BitMask },
/// Sign extend a slice (zero aligned)
SignExtend { dst: Wr, src: Rd, slice: BitSlice },
SignExtend { dst: Wr, src: Rd, mask: BitMask },
Add { dst: Wr, a: Rd, b: Rd },
Sub { dst: Wr, a: Rd, b: Rd },
+9 -9
View File
@@ -250,19 +250,19 @@ impl OpTrait for ArithOp {
let res = val.reverse_bits();
state.write(dst, res)?;
}
ArithOp::Clz { dst, src, slice } => {
ArithOp::Clz { dst, src, mask: slice } => {
state.clear_status();
let mut val = ((state.read(src)? >> slice.src_pos) << (64 - slice.width));
let mut val = (state.read(src)? >> slice.src_pos) << (64 - slice.width);
if !slice.is_full() {
val |= ((1 << slice.width) - 1);
val |= (1 << slice.width) - 1;
}
let res = val.leading_zeros() as u64;
state.update_status(res);
state.write(dst, res)?;
}
ArithOp::Clo { dst, src, slice } => {
ArithOp::Clo { dst, src, mask: slice } => {
state.clear_status();
let mut val = ((state.read(src)? >> slice.src_pos) << (64 - slice.width));
let mut val = (state.read(src)? >> slice.src_pos) << (64 - slice.width);
if !slice.is_full() {
val &= ((1 << slice.width) - 1) << slice.src_pos;
}
@@ -270,7 +270,7 @@ impl OpTrait for ArithOp {
state.update_status(res);
state.write(dst, res)?;
}
ArithOp::SignExtend { dst, src, slice } => {
ArithOp::SignExtend { dst, src, mask: slice } => {
state.clear_status();
let val = state.read(src)?;
@@ -330,9 +330,9 @@ impl OpTrait for ArithOp {
ArithOp::Sw8 { dst, src } => to_sexp_1_or_2("sw8", dst, src),
ArithOp::Rev { dst, src } => to_sexp_1_or_2("rev", dst, src),
ArithOp::Rbit { dst, src } => to_sexp_1_or_2("rbit", dst, src),
ArithOp::Clz { dst, src, slice } => to_sexp_1_or_2(&format!("clz{}", slice), dst, src),
ArithOp::Clo { dst, src, slice } => to_sexp_1_or_2(&format!("clo{}", slice), dst, src),
ArithOp::SignExtend { dst, src, slice } => to_sexp_1_or_2(&format!("se{}", slice), dst, src),
ArithOp::Clz { dst, src, mask: slice } => to_sexp_1_or_2(&format!("clz{}", slice), dst, src),
ArithOp::Clo { dst, src, mask: slice } => to_sexp_1_or_2(&format!("clo{}", slice), dst, src),
ArithOp::SignExtend { dst, src, mask: slice } => to_sexp_1_or_2(&format!("se{}", slice), dst, src),
}
}
}
+32 -47
View File
@@ -1,4 +1,4 @@
use crsn::asm::data::{Rd, Wr};
use crsn::asm::data::{Rd, Wr, DataDispEquals};
use crsn::asm::error::CrsnError;
use crsn::asm::instr::op::OpKind;
use crsn::asm::parse::arg_parser::TokenParser;
@@ -6,7 +6,7 @@ use crsn::module::ParseRes;
use crsn::sexp::SourcePosition;
use crate::defs::ArithOp;
use crsn::builtin::defs::BitSlice;
pub(crate) fn parse<'a>(op_pos: &SourcePosition, keyword: &str, mut args: TokenParser<'a>) -> Result<ParseRes<'a, OpKind>, CrsnError> {
Ok(ParseRes::ext(match keyword {
@@ -574,58 +574,43 @@ pub(crate) fn parse<'a>(op_pos: &SourcePosition, keyword: &str, mut args: TokenP
}
other => {
if let Some(s) = other.strip_prefix("clz") {
if let Some(slice) = BitSlice::parse2(s, op_pos)? {
return Ok(ParseRes::ext(match args.len() {
2 => {
ArithOp::Clz { dst: args.next_wr()?, src: args.next_rd()?, slice }
}
1 => {
let dst = args.next_rdwr()?;
ArithOp::Clz { dst: dst.wr(), src: dst.rd(), slice }
}
_ => {
return Err(CrsnError::Parse("Clz requires 1 or 2 arguments".into(), op_pos.clone()));
}
}));
if let Some((dst, src, mask)) = args.parse_masked_wr_rd(other, "clz")? {
if !dst.disp_equals(src) && mask.dst_pos != 0 {
return Err(CrsnError::Parse(
"Invalid offsets - permissible formats are (RW:src_offs) and (Wr Rd:src_offs) ".into(),
op_pos.clone()));
}
return Ok(ParseRes::ext(ArithOp::Clz {
dst,
src,
mask
}));
}
if let Some(s) = other.strip_prefix("clo") {
if let Some(slice) = BitSlice::parse2(s, op_pos)? {
return Ok(ParseRes::ext(match args.len() {
2 => {
ArithOp::Clo { dst: args.next_wr()?, src: args.next_rd()?, slice }
}
1 => {
let dst = args.next_rdwr()?;
ArithOp::Clo { dst: dst.wr(), src: dst.rd(), slice }
}
_ => {
return Err(CrsnError::Parse("Clz requires 1 or 2 arguments".into(), op_pos.clone()));
}
}));
if let Some((dst, src, mask)) = args.parse_masked_wr_rd(other, "clo")? {
if !dst.disp_equals(src) && mask.dst_pos != 0 {
return Err(CrsnError::Parse(
"Invalid offsets - permissible formats are (RW:src_offs) and (Wr Rd:src_offs)".into(),
op_pos.clone()));
}
return Ok(ParseRes::ext(ArithOp::Clo {
dst,
src,
mask
}));
}
if let Some(s) = other.strip_prefix("se") {
if let Some(slice) = BitSlice::parse1(s, op_pos)? {
if slice.is_full() {
return Err(CrsnError::Parse("Sign extend requires a bit size (< 64)".into(), op_pos.clone()));
}
return Ok(ParseRes::ext(match args.len() {
2 => {
ArithOp::SignExtend { dst: args.next_wr()?, src: args.next_rd()?, slice }
}
1 => {
let dst = args.next_rdwr()?;
ArithOp::SignExtend { dst: dst.wr(), src: dst.rd(), slice }
}
_ => {
return Err(CrsnError::Parse("Sign extend requires 1 or 2 arguments".into(), op_pos.clone()));
}
}));
if let Some((dst, src, mask)) = args.parse_masked_wr_rd(other, "se")? {
if mask.src_pos != 0 || mask.dst_pos != 0 {
return Err(CrsnError::Parse(
"Offsets do not make sense for SignExtend".into(),
op_pos.clone()));
}
return Ok(ParseRes::ext(ArithOp::SignExtend {
dst,
src,
mask
}));
}
return Ok(ParseRes::Unknown(args));