1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
use crate::{
exec::{Context, PasmResult},
inst::Op,
};
pub type ExecFunc = fn(&mut Context, &Op) -> PasmResult;
pub struct ExecInst {
pub func: ExecFunc,
pub op: Op,
}
impl ExecInst {
pub fn new(inst: ExecFunc, op: Op) -> Self {
Self { func: inst, op }
}
}
#[macro_export]
macro_rules! inst {
($(#[$outer:meta])* $name:ident ($ctx:ident, $op:ident) { $( $code:tt )* }) => {
$(#[$outer])*
pub fn $name($ctx: &mut $crate::exec::Context, $op: & $crate::inst::Op) -> $crate::exec::PasmResult {
use $crate::inst::Op::*;
$( $code )*
Ok(())
}
};
($(#[$outer:meta])* $name:ident ($ctx:ident) { $( $code:tt )* }) => {
$(#[$outer])*
pub fn $name($ctx: &mut $crate::exec::Context, _: & $crate::inst::Op) -> $crate::exec::PasmResult {
$( $code )*
Ok(())
}
};
($(#[$outer:meta])* $name:ident { $( $code:tt )* }) => {
$(#[$outer])*
pub fn $name(_: &mut $crate::exec::Context, _: & $crate::inst::Op) -> $crate::exec::PasmResult {
$( $code )*
Ok(())
}
};
}
#[cfg(test)]
mod tests {
use super::*;
use crate::inst::Op::*;
#[test]
fn op_parsing() {
let ops = [
("200", Addr(200)),
("#x80", Literal(128)),
("#b001", Literal(1)),
("#800", Literal(800)),
(
"200,#8,be",
MultiOp(vec![Addr(200), Literal(8), Fail("be".into())]),
),
("", Null),
("ACC,r10,#x10", MultiOp(vec![Acc, Gpr(10), Literal(16)])),
];
for (op, res) in ops {
assert_eq!(Op::from(op), res);
}
}
}