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
|
; 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))
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user