forked from MightyPork/crsn
Simplify {clz,clo,se}XX parsing and exec, add simple unit test example scripts
This commit is contained in:
+27
-11
@@ -1,4 +1,5 @@
|
||||
use crsn::asm::data::{Rd, Wr};
|
||||
use crsn::builtin::defs::BitSlice;
|
||||
|
||||
/// A low level instruction
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
@@ -8,22 +9,22 @@ pub enum ArithOp {
|
||||
RangeTest { val: Rd, a: Rd, b: Rd },
|
||||
Rng { dst: Wr, min: Rd, max: Rd },
|
||||
|
||||
/// Swap halves
|
||||
Sw32 { dst: Wr, src: Rd },
|
||||
/// Swap adjacent half-words
|
||||
Sw16 { dst: Wr, src: Rd },
|
||||
/// Swap neighbouring bytes
|
||||
Sw8 { dst: Wr, src: Rd },
|
||||
/// Reverse bytes
|
||||
Rev { dst: Wr, src: Rd },
|
||||
/// Reverse bits
|
||||
Rbit { dst: Wr, src: Rd },
|
||||
Clz { dst: Wr, src: Rd },
|
||||
Clz32 { dst: Wr, src: Rd },
|
||||
Clz16 { dst: Wr, src: Rd },
|
||||
Clz8 { dst: Wr, src: Rd },
|
||||
Clo { dst: Wr, src: Rd },
|
||||
Clo32 { dst: Wr, src: Rd },
|
||||
Clo16 { dst: Wr, src: Rd },
|
||||
Clo8 { dst: Wr, src: Rd },
|
||||
SignExtend32 { dst: Wr, src: Rd },
|
||||
SignExtend16 { dst: Wr, src: Rd },
|
||||
SignExtend8 { dst: Wr, src: Rd },
|
||||
/// Count leading zeros in a slice
|
||||
Clz { dst: Wr, src: Rd, slice: BitSlice },
|
||||
/// Count leading ones in a slice
|
||||
Clo { dst: Wr, src: Rd, slice: BitSlice },
|
||||
/// Sign extend a slice (zero aligned)
|
||||
SignExtend { dst: Wr, src: Rd, slice: BitSlice },
|
||||
|
||||
Add { dst: Wr, a: Rd, b: Rd },
|
||||
Sub { dst: Wr, a: Rd, b: Rd },
|
||||
@@ -44,4 +45,19 @@ pub enum ArithOp {
|
||||
// Shift
|
||||
Lsr { dst: Wr, a: Rd, n: Rd },
|
||||
Asr { dst: Wr, a: Rd, n: Rd },
|
||||
|
||||
// IntToFloat { dst: Wr, a: Rd },
|
||||
// FloatToInt { dst: Wr, a: Rd },
|
||||
// FloatTest { a: Rd },
|
||||
// FloatCompare { a: Rd, b: Rd },
|
||||
// FloatRangeTest { val: Rd, a: Rd, b: Rd },
|
||||
// FloatRng { dst: Wr, min: Rd, max: Rd },
|
||||
// FloatRound { dst: Wr, a: Rd, b: Rd },
|
||||
// FloatCeil { dst: Wr, a: Rd, b: Rd },
|
||||
// FloatFloor { dst: Wr, a: Rd, b: Rd },
|
||||
// FloatAdd { dst: Wr, a: Rd, b: Rd },
|
||||
// FloatSub { dst: Wr, a: Rd, b: Rd },
|
||||
// FloatMul { dst: Wr, a: Rd, b: Rd },
|
||||
// FloatDiv { dst: Wr, rem: Wr, a: Rd, div: Rd },
|
||||
// FloatMod { dst: Wr, a: Rd, div: Rd },
|
||||
}
|
||||
|
||||
+18
-83
@@ -250,91 +250,34 @@ impl OpTrait for ArithOp {
|
||||
let res = val.reverse_bits();
|
||||
state.write(dst, res)?;
|
||||
}
|
||||
ArithOp::Clz { dst, src } => {
|
||||
ArithOp::Clz { dst, src, slice } => {
|
||||
state.clear_status();
|
||||
let val = state.read(src)?;
|
||||
let mut val = ((state.read(src)? >> slice.src_pos) << (64 - slice.width));
|
||||
if !slice.is_full() {
|
||||
val |= ((1 << slice.width) - 1);
|
||||
}
|
||||
let res = val.leading_zeros() as u64;
|
||||
state.update_status(res);
|
||||
state.write(dst, res)?;
|
||||
}
|
||||
ArithOp::Clz32 { dst, src } => {
|
||||
ArithOp::Clo { dst, src, slice } => {
|
||||
state.clear_status();
|
||||
let val = state.read(src)?;
|
||||
let res = (((val & 0xFFFF_FFFF) << 32) | 0xFFFF_FFFF).leading_zeros() as u64;
|
||||
state.update_status(res);
|
||||
state.write(dst, res)?;
|
||||
}
|
||||
ArithOp::Clz16 { dst, src } => {
|
||||
state.clear_status();
|
||||
let val = state.read(src)?;
|
||||
let res = (((val & 0xFFFF) << 48) | 0xFFFF_FFFF_FFFF).leading_zeros() as u64;
|
||||
state.update_status(res);
|
||||
state.write(dst, res)?;
|
||||
}
|
||||
ArithOp::Clz8 { dst, src } => {
|
||||
state.clear_status();
|
||||
let val = state.read(src)?;
|
||||
let res = (((val & 0xFF) << 56) | 0x00FF_FFFF_FFFF_FFFF).leading_zeros() as u64;
|
||||
state.update_status(res);
|
||||
state.write(dst, res)?;
|
||||
}
|
||||
ArithOp::Clo { dst, src } => {
|
||||
state.clear_status();
|
||||
let val = state.read(src)?;
|
||||
let mut val = ((state.read(src)? >> slice.src_pos) << (64 - slice.width));
|
||||
if !slice.is_full() {
|
||||
val &= ((1 << slice.width) - 1) << slice.src_pos;
|
||||
}
|
||||
let res = val.leading_ones() as u64;
|
||||
state.update_status(res);
|
||||
state.write(dst, res)?;
|
||||
}
|
||||
ArithOp::Clo32 { dst, src } => {
|
||||
ArithOp::SignExtend { dst, src, slice } => {
|
||||
state.clear_status();
|
||||
let val = state.read(src)?;
|
||||
let res = ((val & 0xFFFF_FFFF) << 32).leading_ones() as u64;
|
||||
state.update_status(res);
|
||||
state.write(dst, res)?;
|
||||
}
|
||||
ArithOp::Clo16 { dst, src } => {
|
||||
state.clear_status();
|
||||
let val = state.read(src)?;
|
||||
let res = ((val & 0xFFFF) << 48).leading_ones() as u64;
|
||||
state.update_status(res);
|
||||
state.write(dst, res)?;
|
||||
}
|
||||
ArithOp::Clo8 { dst, src } => {
|
||||
state.clear_status();
|
||||
let val = state.read(src)?;
|
||||
let res = ((val & 0xFF) << 56).leading_ones() as u64;
|
||||
state.update_status(res);
|
||||
state.write(dst, res)?;
|
||||
}
|
||||
ArithOp::SignExtend32 { dst, src } => {
|
||||
state.clear_status();
|
||||
let val = state.read(src)?;
|
||||
let res = if 0 != (val & 0x8000_0000) {
|
||||
0xFFFF_FFFF_0000_0000 | val
|
||||
|
||||
let res = if 0 != (val & (1 << (slice.width - 1))) {
|
||||
val | (((1 << (64 - slice.width)) - 1) << slice.width)
|
||||
} else {
|
||||
val & 0xFFFF_FFFF
|
||||
};
|
||||
state.update_status(res);
|
||||
state.write(dst, res)?;
|
||||
}
|
||||
ArithOp::SignExtend16 { dst, src } => {
|
||||
state.clear_status();
|
||||
let val = state.read(src)?;
|
||||
let res = if 0 != (val & 0x8000) {
|
||||
0xFFFF_FFFF_FFFF_0000 | val
|
||||
} else {
|
||||
val & 0xFFFF
|
||||
};
|
||||
state.update_status(res);
|
||||
state.write(dst, res)?;
|
||||
}
|
||||
ArithOp::SignExtend8 { dst, src } => {
|
||||
state.clear_status();
|
||||
let val = state.read(src)?;
|
||||
let res = if 0 != (val & 0x80) {
|
||||
0xFFFF_FFFF_FFFF_FF00 | val
|
||||
} else {
|
||||
val & 0xFF
|
||||
val & ((1 << slice.width) - 1)
|
||||
};
|
||||
state.update_status(res);
|
||||
state.write(dst, res)?;
|
||||
@@ -387,17 +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 } => to_sexp_1_or_2("clz", dst, src),
|
||||
ArithOp::Clz32 { dst, src } => to_sexp_1_or_2("clz32", dst, src),
|
||||
ArithOp::Clz16 { dst, src } => to_sexp_1_or_2("clz16", dst, src),
|
||||
ArithOp::Clz8 { dst, src } => to_sexp_1_or_2("clz8", dst, src),
|
||||
ArithOp::Clo { dst, src } => to_sexp_1_or_2("clo", dst, src),
|
||||
ArithOp::Clo32 { dst, src } => to_sexp_1_or_2("clo32", dst, src),
|
||||
ArithOp::Clo16 { dst, src } => to_sexp_1_or_2("clo16", dst, src),
|
||||
ArithOp::Clo8 { dst, src } => to_sexp_1_or_2("clo8", dst, src),
|
||||
ArithOp::SignExtend32 { dst, src } => to_sexp_1_or_2("se32", dst, src),
|
||||
ArithOp::SignExtend16 { dst, src } => to_sexp_1_or_2("se16", dst, src),
|
||||
ArithOp::SignExtend8 { dst, src } => to_sexp_1_or_2("se8", 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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+68
-244
@@ -6,8 +6,9 @@ use crsn::module::ParseRes;
|
||||
use crsn::sexp::SourcePosition;
|
||||
|
||||
use crate::defs::ArithOp;
|
||||
use crsn::builtin::defs::BitSlice;
|
||||
|
||||
pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenParser<'a>) -> Result<ParseRes<'a, OpKind>, CrsnError> {
|
||||
pub(crate) fn parse<'a>(op_pos: &SourcePosition, keyword: &str, mut args: TokenParser<'a>) -> Result<ParseRes<'a, OpKind>, CrsnError> {
|
||||
Ok(ParseRes::ext(match keyword {
|
||||
"cmp" => {
|
||||
ArithOp::Compare {
|
||||
@@ -53,7 +54,7 @@ pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenPars
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(CrsnError::Parse("Rng requires 1, 2 or 3 arguments".into(), pos.clone()));
|
||||
return Err(CrsnError::Parse("Rng requires 1, 2 or 3 arguments".into(), op_pos.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -94,7 +95,7 @@ pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenPars
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(CrsnError::Parse("Add requires 2 or 3 arguments".into(), pos.clone()));
|
||||
return Err(CrsnError::Parse("Add requires 2 or 3 arguments".into(), op_pos.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -117,7 +118,7 @@ pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenPars
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(CrsnError::Parse("Sub requires 2 or 3 arguments".into(), pos.clone()));
|
||||
return Err(CrsnError::Parse("Sub requires 2 or 3 arguments".into(), op_pos.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -140,7 +141,7 @@ pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenPars
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(CrsnError::Parse("Mul requires 2 or 3 arguments".into(), pos.clone()));
|
||||
return Err(CrsnError::Parse("Mul requires 2 or 3 arguments".into(), op_pos.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -167,7 +168,7 @@ pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenPars
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(CrsnError::Parse("DivR requires 3 or 4 arguments".into(), pos.clone()));
|
||||
return Err(CrsnError::Parse("DivR requires 3 or 4 arguments".into(), op_pos.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -193,7 +194,7 @@ pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenPars
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(CrsnError::Parse("Div requires 2 or 3 arguments".into(), pos.clone()));
|
||||
return Err(CrsnError::Parse("Div requires 2 or 3 arguments".into(), op_pos.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -217,7 +218,7 @@ pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenPars
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(CrsnError::Parse("Mod requires 2 or 3 arguments".into(), pos.clone()));
|
||||
return Err(CrsnError::Parse("Mod requires 2 or 3 arguments".into(), op_pos.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -240,7 +241,7 @@ pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenPars
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(CrsnError::Parse("And requires 2 or 3 arguments".into(), pos.clone()));
|
||||
return Err(CrsnError::Parse("And requires 2 or 3 arguments".into(), op_pos.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -263,7 +264,7 @@ pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenPars
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(CrsnError::Parse("Or requires 2 or 3 arguments".into(), pos.clone()));
|
||||
return Err(CrsnError::Parse("Or requires 2 or 3 arguments".into(), op_pos.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -286,7 +287,7 @@ pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenPars
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(CrsnError::Parse("Xor requires 2 or 3 arguments".into(), pos.clone()));
|
||||
return Err(CrsnError::Parse("Xor requires 2 or 3 arguments".into(), op_pos.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -307,7 +308,7 @@ pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenPars
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(CrsnError::Parse("Cpl requires 1 or 2 arguments".into(), pos.clone()));
|
||||
return Err(CrsnError::Parse("Cpl requires 1 or 2 arguments".into(), op_pos.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -338,7 +339,7 @@ pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenPars
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(CrsnError::Parse("Rol requires 1, 2 or 3 arguments".into(), pos.clone()));
|
||||
return Err(CrsnError::Parse("Rol requires 1, 2 or 3 arguments".into(), op_pos.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -369,7 +370,7 @@ pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenPars
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(CrsnError::Parse("Ror requires 1, 2 or 3 arguments".into(), pos.clone()));
|
||||
return Err(CrsnError::Parse("Ror requires 1, 2 or 3 arguments".into(), op_pos.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -400,7 +401,7 @@ pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenPars
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(CrsnError::Parse("Lsl requires 1, 2 or 3 arguments".into(), pos.clone()));
|
||||
return Err(CrsnError::Parse("Lsl requires 1, 2 or 3 arguments".into(), op_pos.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -431,7 +432,7 @@ pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenPars
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(CrsnError::Parse("Lsr requires 1, 2 or 3 arguments".into(), pos.clone()));
|
||||
return Err(CrsnError::Parse("Lsr requires 1, 2 or 3 arguments".into(), op_pos.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -462,7 +463,7 @@ pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenPars
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(CrsnError::Parse("Asr requires 1, 2 or 3 arguments".into(), pos.clone()));
|
||||
return Err(CrsnError::Parse("Asr requires 1, 2 or 3 arguments".into(), op_pos.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -483,7 +484,7 @@ pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenPars
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(CrsnError::Parse("SW32 requires 1 or 2 arguments".into(), pos.clone()));
|
||||
return Err(CrsnError::Parse("SW32 requires 1 or 2 arguments".into(), op_pos.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -504,7 +505,7 @@ pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenPars
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(CrsnError::Parse("SW16 requires 1 or 2 arguments".into(), pos.clone()));
|
||||
return Err(CrsnError::Parse("SW16 requires 1 or 2 arguments".into(), op_pos.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -525,7 +526,7 @@ pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenPars
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(CrsnError::Parse("SW8 requires 1 or 2 arguments".into(), pos.clone()));
|
||||
return Err(CrsnError::Parse("SW8 requires 1 or 2 arguments".into(), op_pos.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -546,7 +547,7 @@ pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenPars
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(CrsnError::Parse("REV requires 1 or 2 arguments".into(), pos.clone()));
|
||||
return Err(CrsnError::Parse("REV requires 1 or 2 arguments".into(), op_pos.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -567,243 +568,66 @@ pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenPars
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(CrsnError::Parse("RBIT requires 1 or 2 arguments".into(), pos.clone()));
|
||||
return Err(CrsnError::Parse("RBIT requires 1 or 2 arguments".into(), op_pos.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"clz" => {
|
||||
match args.len() {
|
||||
2 => {
|
||||
ArithOp::Clz {
|
||||
dst: args.next_wr()?,
|
||||
src: args.next_rd()?,
|
||||
}
|
||||
}
|
||||
1 => {
|
||||
let dst = args.next_rdwr()?;
|
||||
ArithOp::Clz {
|
||||
dst: dst.wr(),
|
||||
src: dst.rd(),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(CrsnError::Parse("Clz requires 1 or 2 arguments".into(), pos.clone()));
|
||||
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()));
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"clz32" => {
|
||||
match args.len() {
|
||||
2 => {
|
||||
ArithOp::Clz32 {
|
||||
dst: args.next_wr()?,
|
||||
src: args.next_rd()?,
|
||||
}
|
||||
}
|
||||
1 => {
|
||||
let dst = args.next_rdwr()?;
|
||||
ArithOp::Clz32 {
|
||||
dst: dst.wr(),
|
||||
src: dst.rd(),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(CrsnError::Parse("Clz32 requires 1 or 2 arguments".into(), pos.clone()));
|
||||
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()));
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"clz16" => {
|
||||
match args.len() {
|
||||
2 => {
|
||||
ArithOp::Clz16 {
|
||||
dst: args.next_wr()?,
|
||||
src: args.next_rd()?,
|
||||
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()));
|
||||
}
|
||||
}
|
||||
1 => {
|
||||
let dst = args.next_rdwr()?;
|
||||
ArithOp::Clz16 {
|
||||
dst: dst.wr(),
|
||||
src: dst.rd(),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(CrsnError::Parse("Clz16 requires 1 or 2 arguments".into(), 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()));
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"clz8" => {
|
||||
match args.len() {
|
||||
2 => {
|
||||
ArithOp::Clz8 {
|
||||
dst: args.next_wr()?,
|
||||
src: args.next_rd()?,
|
||||
}
|
||||
}
|
||||
1 => {
|
||||
let dst = args.next_rdwr()?;
|
||||
ArithOp::Clz8 {
|
||||
dst: dst.wr(),
|
||||
src: dst.rd(),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(CrsnError::Parse("Clz8 requires 1 or 2 arguments".into(), pos.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"clo" => {
|
||||
match args.len() {
|
||||
2 => {
|
||||
ArithOp::Clo {
|
||||
dst: args.next_wr()?,
|
||||
src: args.next_rd()?,
|
||||
}
|
||||
}
|
||||
1 => {
|
||||
let dst = args.next_rdwr()?;
|
||||
ArithOp::Clo {
|
||||
dst: dst.wr(),
|
||||
src: dst.rd(),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(CrsnError::Parse("Clo requires 1 or 2 arguments".into(), pos.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"clo32" => {
|
||||
match args.len() {
|
||||
2 => {
|
||||
ArithOp::Clo32 {
|
||||
dst: args.next_wr()?,
|
||||
src: args.next_rd()?,
|
||||
}
|
||||
}
|
||||
1 => {
|
||||
let dst = args.next_rdwr()?;
|
||||
ArithOp::Clo32 {
|
||||
dst: dst.wr(),
|
||||
src: dst.rd(),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(CrsnError::Parse("Clo32 requires 1 or 2 arguments".into(), pos.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"clo16" => {
|
||||
match args.len() {
|
||||
2 => {
|
||||
ArithOp::Clo16 {
|
||||
dst: args.next_wr()?,
|
||||
src: args.next_rd()?,
|
||||
}
|
||||
}
|
||||
1 => {
|
||||
let dst = args.next_rdwr()?;
|
||||
ArithOp::Clo16 {
|
||||
dst: dst.wr(),
|
||||
src: dst.rd(),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(CrsnError::Parse("Clo16 requires 1 or 2 arguments".into(), pos.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"clo8" => {
|
||||
match args.len() {
|
||||
2 => {
|
||||
ArithOp::Clo8 {
|
||||
dst: args.next_wr()?,
|
||||
src: args.next_rd()?,
|
||||
}
|
||||
}
|
||||
1 => {
|
||||
let dst = args.next_rdwr()?;
|
||||
ArithOp::Clo8 {
|
||||
dst: dst.wr(),
|
||||
src: dst.rd(),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(CrsnError::Parse("Clo8 requires 1 or 2 arguments".into(), pos.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"se32" => {
|
||||
match args.len() {
|
||||
2 => {
|
||||
ArithOp::SignExtend32 {
|
||||
dst: args.next_wr()?,
|
||||
src: args.next_rd()?,
|
||||
}
|
||||
}
|
||||
1 => {
|
||||
let dst = args.next_rdwr()?;
|
||||
ArithOp::SignExtend32 {
|
||||
dst: dst.wr(),
|
||||
src: dst.rd(),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(CrsnError::Parse("SignExtend32 requires 1 or 2 arguments".into(), pos.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"se16" => {
|
||||
match args.len() {
|
||||
2 => {
|
||||
ArithOp::SignExtend16 {
|
||||
dst: args.next_wr()?,
|
||||
src: args.next_rd()?,
|
||||
}
|
||||
}
|
||||
1 => {
|
||||
let dst = args.next_rdwr()?;
|
||||
ArithOp::SignExtend16 {
|
||||
dst: dst.wr(),
|
||||
src: dst.rd(),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(CrsnError::Parse("SignExtend16 requires 1 or 2 arguments".into(), pos.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"se8" => {
|
||||
match args.len() {
|
||||
2 => {
|
||||
ArithOp::SignExtend8 {
|
||||
dst: args.next_wr()?,
|
||||
src: args.next_rd()?,
|
||||
}
|
||||
}
|
||||
1 => {
|
||||
let dst = args.next_rdwr()?;
|
||||
ArithOp::SignExtend8 {
|
||||
dst: dst.wr(),
|
||||
src: dst.rd(),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(CrsnError::Parse("SignExtend8 requires 1 or 2 arguments".into(), pos.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_other => {
|
||||
return Ok(ParseRes::Unknown(args));
|
||||
}
|
||||
}))
|
||||
|
||||
Reference in New Issue
Block a user