|
|
|
@ -289,6 +289,10 @@ pub(crate) fn parse_op<'a>(op_pos: &SourcePosition, keyword: &str, mut args: Tok |
|
|
|
|
return Ok(ParseRes::builtin(BuiltinOp::Exchange { a, b, mask })); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if let Some((dst, expected, src, mask)) = args.parse_masked_rdwr_rd_rd(other, "cas")? { |
|
|
|
|
return Ok(ParseRes::builtin(BuiltinOp::CompareSwap { dst, expected, src, mask })); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if other.starts_with(':') { |
|
|
|
|
BuiltinOp::Label(parse_label_str(other, &op_pos)?) |
|
|
|
|
} else { |
|
|
|
@ -389,6 +393,13 @@ pub(crate) fn to_sexp(op: &BuiltinOp) -> Sexp { |
|
|
|
|
sexp::list(&[A(format!("xch{}", mask.width)), AM(a, mask.dst_pos), AM(b, mask.src_pos)]) |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
BuiltinOp::CompareSwap { dst, expected, src, mask } => { |
|
|
|
|
if mask.is_full() { |
|
|
|
|
sexp::list(&[A("cas"), A(dst), A(expected), A(src)]) |
|
|
|
|
} else { |
|
|
|
|
sexp::list(&[A(format!("cas{}", mask.width)), AM(dst, mask.dst_pos), AM(expected, mask.src_pos), AM(src, mask.src2_pos)]) |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
BuiltinOp::StoreFlags { dst } => sexp::list(&[A("stf"), A(dst)]), |
|
|
|
|
BuiltinOp::LoadFlags { src } => sexp::list(&[A("ldf"), A(src)]), |
|
|
|
|
BuiltinOp::LoadSequence { dst, value } => { |
|
|
|
@ -474,6 +485,8 @@ mod test { |
|
|
|
|
("(xch r0 r1)", "(xch r0 r1)"), |
|
|
|
|
("(xch32 r0 r1)", "(xch32 r0 r1)"), |
|
|
|
|
("(xch32 r0:8 r1:16)", "(xch32 r0:8 r1:16)"), |
|
|
|
|
("(cas r0 r1 r2)", "(cas r0 r1 r2)"), |
|
|
|
|
("(cas8 r0:8 r1:16 r2:24)", "(cas8 r0:8 r1:16 r2:24)"), |
|
|
|
|
("(ld r0 r0)", "(ld r0 r0)"), |
|
|
|
|
("(ld8 r0 r1)", "(ld8 r0 r1)"), |
|
|
|
|
("(ld16 r0 r1)", "(ld16 r0 r1)"), |
|
|
|
|