add the "lds" instruction
This commit is contained in:
@@ -326,6 +326,12 @@ Jumping to a label is always safer than a manual skip.
|
||||
; Copy 8 bits of a value
|
||||
(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
|
||||
(xch RW RW)
|
||||
|
||||
|
||||
@@ -30,6 +30,12 @@ impl SleepUnit {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum LdsValue {
|
||||
Values(Vec<Rd>),
|
||||
Chars(String),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum BuiltinOp {
|
||||
/// Do nothing (costs one cycle)
|
||||
@@ -80,6 +86,8 @@ pub enum BuiltinOp {
|
||||
Move8 { dst: RdWr, src: Rd },
|
||||
/// Move N values
|
||||
MoveMultiple { dst: Wr, src: Rd, count: Rd },
|
||||
/// Move values from a string or integer list
|
||||
MoveSequence { dst: Wr, value: LdsValue },
|
||||
/// Swap two registers
|
||||
Exchange { a: RdWr, b: RdWr },
|
||||
/// Store runtime status to a register
|
||||
|
||||
@@ -3,8 +3,8 @@ use std::time::Duration;
|
||||
use sexp::Sexp;
|
||||
|
||||
use crate::asm::data::{Rd, RdData};
|
||||
use crate::asm::data::literal::Addr;
|
||||
use crate::builtin::defs::{Barrier, BuiltinOp};
|
||||
use crate::asm::data::literal::{Addr, Value};
|
||||
use crate::builtin::defs::{Barrier, BuiltinOp, LdsValue};
|
||||
use crate::module::{EvalRes, OpTrait};
|
||||
use crate::runtime::fault::Fault;
|
||||
use crate::runtime::frame::StackFrame;
|
||||
@@ -144,6 +144,21 @@ impl OpTrait for BuiltinOp {
|
||||
state.update_status(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 } => {
|
||||
let aa = state.read(a)?;
|
||||
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::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::sexp_expect::{expect_any_string_atom};
|
||||
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::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" => {
|
||||
BuiltinOp::Exchange {
|
||||
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::StoreFlags { dst } => sexp::list(&[A("stf"), A(dst)]),
|
||||
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 _ -32767)", "(ld _ -32767)"),
|
||||
("(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)"),
|
||||
("(ldf r0)", "(ldf r0)"),
|
||||
("(far :label)", "(far :label)"),
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
(
|
||||
(lds @cout "ahoj jak se mas\n")
|
||||
(lds @cout (65 66 67 68 69 70 10))
|
||||
)
|
||||
Reference in New Issue
Block a user