From 3a8895b790cdf0a6ba572c3ef1beeb14de93ee7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Sat, 10 Oct 2020 14:31:07 +0200 Subject: [PATCH] add rcmp instr, add rot13 example --- README.md | 6 +++++- crsn_arith/src/defs.rs | 1 + crsn_arith/src/exec.rs | 11 +++++++++++ crsn_arith/src/parse.rs | 8 ++++++++ examples/stdio_rot13.csn | 16 ++++++++++++++++ 5 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 examples/stdio_rot13.csn diff --git a/README.md b/README.md index 4d4905d..98ff01a 100644 --- a/README.md +++ b/README.md @@ -341,9 +341,13 @@ Many instructions have two forms: ; Test properties of a value - zero, positive, negative (tst SRC) -; Compare two values +; Compare two values. Sets EQ, LT, GT, and Z, POS and NEG if the values equal (cmp Rd Rd) +; Check if a value is in a range (inclusive). +; Sets the EQ, LT and GT flags. Also sets Z, POS and NEG based on the value. +(rcmp Rd:val Rd:start Rd:end) + ; Add A+B (add Wr Rd Rd) (add RW Rd) diff --git a/crsn_arith/src/defs.rs b/crsn_arith/src/defs.rs index 134cb0f..f8423a1 100644 --- a/crsn_arith/src/defs.rs +++ b/crsn_arith/src/defs.rs @@ -5,6 +5,7 @@ use crsn::asm::data::{Rd, Wr}; pub enum ArithOp { Test { a: Rd }, Compare { a: Rd, b: Rd }, + RangeTest { val: Rd, a: Rd, b: Rd }, Add { dst: Wr, a: Rd, b: Rd }, Sub { dst: Wr, a: Rd, b: Rd }, diff --git a/crsn_arith/src/exec.rs b/crsn_arith/src/exec.rs index 63278dd..3e86278 100644 --- a/crsn_arith/src/exec.rs +++ b/crsn_arith/src/exec.rs @@ -34,6 +34,16 @@ impl OpTrait for ArithOp { state.update_status(x); } } + ArithOp::RangeTest { val, a, b } => { + state.clear_status(); + let val = state.read(*val)?; + let a = state.read(*a)?; + let b = state.read(*b)?; + state.set_flag(Cond::Equal, val >= a && val <= b); + state.set_flag(Cond::Lower, val < a); + state.set_flag(Cond::Greater, val > b); + state.update_status(val); + } ArithOp::Add { dst, a, b } => { state.clear_status(); let x = state.read(*a)?; @@ -201,6 +211,7 @@ impl OpTrait for ArithOp { ArithOp::Add { dst, a, b } => to_sexp_2_or_3("add", dst, a, b), ArithOp::Test { a } => sexp::list(&[A("test"), A(a)]), ArithOp::Compare { a, b } => sexp::list(&[A("cmp"), A(a), A(b)]), + ArithOp::RangeTest { val, a: start, b: end } => sexp::list(&[A("rcmp"), A(val), A(start), A(end)]), ArithOp::Sub { dst, a, b } => to_sexp_2_or_3("sub", dst, a, b), ArithOp::Mul { dst, a, b } => to_sexp_2_or_3("mul", dst, a, b), ArithOp::Div { dst, rem, a, div } => { diff --git a/crsn_arith/src/parse.rs b/crsn_arith/src/parse.rs index e4a7fb0..626b0bc 100644 --- a/crsn_arith/src/parse.rs +++ b/crsn_arith/src/parse.rs @@ -16,6 +16,14 @@ pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenPars } } + "rcmp" => { + ArithOp::RangeTest { + val: args.next_rd()?, + a: args.next_rd()?, + b: args.next_rd()?, + } + } + "tst" => { let arg = args.next_rd()?; ArithOp::Test { a: arg } diff --git a/examples/stdio_rot13.csn b/examples/stdio_rot13.csn new file mode 100644 index 0000000..6a5d141 --- /dev/null +++ b/examples/stdio_rot13.csn @@ -0,0 +1,16 @@ +( + (:again) + (ld r0 @stdin (inval? (halt))) + (rcmp r0 'A' 'Z' + (eq? (ld r1 'A')) + (ne? (rcmp r0 'a' 'z' + (eq? (ld r1 'a')) + (ne? (j :print))))) + (sub r0 r1) + (add r0 13) + (mod r0 26) + (add r0 r1) + (:print) + (ld @stdout r0) + (j :again) +)