forked from MightyPork/crsn
implement a more readable bit mask syntax, add (ldXX Wr Rd Rd) with separate dest and both sources
This commit is contained in:
@@ -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 },
|
||||
|
||||
@@ -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
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user