add the "lds" instruction

pull/21/head
Ondřej Hruška 4 years ago
parent 01ab4e7e1f
commit 5b163e969f
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 6
      README.md
  2. 8
      crsn/src/builtin/defs.rs
  3. 19
      crsn/src/builtin/exec.rs
  4. 41
      crsn/src/builtin/parse.rs
  5. 4
      examples/lds.csn

@ -326,6 +326,12 @@ Jumping to a label is always safer than a manual skip.
; Copy 8 bits of a value ; Copy 8 bits of a value
(ld8 Wr Rd) (ld8 Wr Rd)
; Write a sequence of values, or all codepoints from a string, into the destination.
; This is most useful with object handles, such as a buffer or @cout.
; Functionally, this instruction is equivalent to a sequence of "ld"
(lds Wr (Rd...)) ; example - (lds @cout (65 66 67))
(lds Wr "string")
; Exchange two register's values ; Exchange two register's values
(xch RW RW) (xch RW RW)

@ -30,6 +30,12 @@ impl SleepUnit {
} }
} }
#[derive(Clone, Debug, PartialEq)]
pub enum LdsValue {
Values(Vec<Rd>),
Chars(String),
}
#[derive(Debug)] #[derive(Debug)]
pub enum BuiltinOp { pub enum BuiltinOp {
/// Do nothing (costs one cycle) /// Do nothing (costs one cycle)
@ -80,6 +86,8 @@ pub enum BuiltinOp {
Move8 { dst: RdWr, src: Rd }, Move8 { dst: RdWr, src: Rd },
/// Move N values /// Move N values
MoveMultiple { dst: Wr, src: Rd, count: Rd }, MoveMultiple { dst: Wr, src: Rd, count: Rd },
/// Move values from a string or integer list
MoveSequence { dst: Wr, value: LdsValue },
/// Swap two registers /// Swap two registers
Exchange { a: RdWr, b: RdWr }, Exchange { a: RdWr, b: RdWr },
/// Store runtime status to a register /// Store runtime status to a register

@ -3,8 +3,8 @@ use std::time::Duration;
use sexp::Sexp; use sexp::Sexp;
use crate::asm::data::{Rd, RdData}; use crate::asm::data::{Rd, RdData};
use crate::asm::data::literal::Addr; use crate::asm::data::literal::{Addr, Value};
use crate::builtin::defs::{Barrier, BuiltinOp}; use crate::builtin::defs::{Barrier, BuiltinOp, LdsValue};
use crate::module::{EvalRes, OpTrait}; use crate::module::{EvalRes, OpTrait};
use crate::runtime::fault::Fault; use crate::runtime::fault::Fault;
use crate::runtime::frame::StackFrame; use crate::runtime::frame::StackFrame;
@ -144,6 +144,21 @@ impl OpTrait for BuiltinOp {
state.update_status(val); state.update_status(val);
state.write(dst, val)?; state.write(dst, val)?;
} }
BuiltinOp::MoveSequence { dst, value } => {
match value {
LdsValue::Values(vals) => {
for val in vals {
let v = state.read(val)?;
state.write(dst, v)?;
}
}
LdsValue::Chars(string) => {
for val in string.chars() {
state.write(dst, val as Value)?;
}
}
}
}
BuiltinOp::Exchange { a, b } => { BuiltinOp::Exchange { a, b } => {
let aa = state.read(a)?; let aa = state.read(a)?;
let bb = state.read(b)?; let bb = state.read(b)?;

@ -1,4 +1,4 @@
use sexp::{Atom, Sexp, SourcePosition}; use sexp::{Atom, Sexp, SourcePosition, atom_qs};
use crate::asm::data::literal::{RoutineName}; use crate::asm::data::literal::{RoutineName};
use crate::asm::data::reg::parse_reg; use crate::asm::data::reg::parse_reg;
@ -8,7 +8,7 @@ use crate::asm::parse::arg_parser::TokenParser;
use crate::asm::parse::parse_data::{parse_constant_name, parse_label, parse_label_str, parse_rd, parse_reg_alias, parse_value}; use crate::asm::parse::parse_data::{parse_constant_name, parse_label, parse_label_str, parse_rd, parse_reg_alias, parse_value};
use crate::asm::parse::sexp_expect::{expect_any_string_atom}; use crate::asm::parse::sexp_expect::{expect_any_string_atom};
use crate::asm::patches::ErrWithPos; use crate::asm::patches::ErrWithPos;
use crate::builtin::defs::{Barrier, BuiltinOp, SleepUnit}; use crate::builtin::defs::{Barrier, BuiltinOp, SleepUnit, LdsValue};
use crate::module::ParseRes; use crate::module::ParseRes;
use crate::utils::A; use crate::utils::A;
@ -218,6 +218,28 @@ pub(crate) fn parse_op<'a>(op_pos: &SourcePosition, keyword: &str, mut args: Tok
} }
} }
"lds" => {
let dst = args.next_wr()?;
let value = match args.next_or_err()? {
Sexp::Atom(Atom::QS(s), _) => {
LdsValue::Chars(s)
}
Sexp::List(list, _) => {
let mut vals = vec![];
for v in list {
vals.push(parse_rd(v, args.pcx)?);
}
LdsValue::Values(vals)
}
other => {
return Err(CrsnError::Parse("Expected quoted string or a tuple of values".into(), other.pos().clone()));
}
};
BuiltinOp::MoveSequence { dst, value }
}
"xch" => { "xch" => {
BuiltinOp::Exchange { BuiltinOp::Exchange {
a: args.next_rdwr()?, a: args.next_rdwr()?,
@ -345,6 +367,19 @@ pub(crate) fn to_sexp(op: &BuiltinOp) -> Sexp {
BuiltinOp::Exchange { a, b } => sexp::list(&[A("xch"), A(a), A(b)]), BuiltinOp::Exchange { a, b } => sexp::list(&[A("xch"), A(a), A(b)]),
BuiltinOp::StoreFlags { dst } => sexp::list(&[A("stf"), A(dst)]), BuiltinOp::StoreFlags { dst } => sexp::list(&[A("stf"), A(dst)]),
BuiltinOp::LoadFlags { src } => sexp::list(&[A("ldf"), A(src)]), BuiltinOp::LoadFlags { src } => sexp::list(&[A("ldf"), A(src)]),
BuiltinOp::MoveSequence { dst, value } => {
match value {
LdsValue::Values(vals) => {
let mut vals: Vec<_> = vals.iter().map(A).collect();
vals.insert(0, A(dst));
vals.insert(0, A("lds"));
sexp::list(&vals)
}
LdsValue::Chars(str) => {
sexp::list(&[A("lds"), A(dst), atom_qs(str)])
}
}
}
} }
} }
@ -419,6 +454,8 @@ mod test {
("(ld r0 156)", "(ld r0 156)"), ("(ld r0 156)", "(ld r0 156)"),
("(ld _ -32767)", "(ld _ -32767)"), ("(ld _ -32767)", "(ld _ -32767)"),
("(ldn _ @r0 7)", "(ldn _ @r0 7)"), ("(ldn _ @r0 7)", "(ldn _ @r0 7)"),
("(lds @r0 \"ahoj jak se mas\")", "(lds @r0 \"ahoj jak se mas\")"),
("(lds @r0 (1 2 3 4 0x123 r6))", "(lds @r0 (1 2 3 4 0x123 r6))"),
("(stf r0)", "(stf r0)"), ("(stf r0)", "(stf r0)"),
("(ldf r0)", "(ldf r0)"), ("(ldf r0)", "(ldf r0)"),
("(far :label)", "(far :label)"), ("(far :label)", "(far :label)"),

@ -0,0 +1,4 @@
(
(lds @cout "ahoj jak se mas\n")
(lds @cout (65 66 67 68 69 70 10))
)
Loading…
Cancel
Save