cfd16_lib/
parse.rs

1use regex::Regex;
2
3use crate::{Argument, CondCode, OpCode, Register};
4
5impl OpCode {
6    /// Parses a mnemonic into an opcode-condition code pair. If no
7    /// possible combination is found for an input value, then the
8    /// method will return None.
9    pub fn parse(mnem: &str) -> Option<(OpCode, bool, CondCode)> {
10        use OpCode::*;
11
12        let mchars = mnem.chars().collect::<Vec<char>>();
13
14        let (mut mnem, cond) = match mchars.as_slice() {
15            [.., 'n', 'z'] => (mnem.strip_suffix("nz"), CondCode::NotZero),
16            [.., 'z'] => (mnem.strip_suffix("z"), CondCode::Zero),
17            ['s', 'c'] => (Some(mnem), CondCode::Always),
18            ['s', 'c', 'c'] => (Some("sc"), CondCode::Carry),
19            [.., 'c'] => (mnem.strip_suffix("c"), CondCode::Carry),
20            [.., 'g', 't'] => (mnem.strip_suffix("gt"), CondCode::Greater),
21            [.., 'g', 'e'] => (mnem.strip_suffix("ge"), CondCode::GreaterEq),
22            [.., 'l', 't'] => (mnem.strip_suffix("lt"), CondCode::Lesser),
23            [.., 'l', 'e'] => (mnem.strip_suffix("le"), CondCode::LesserEq),
24            _ => (Some(mnem), CondCode::Always),
25        };
26
27        let mut sbit = false;
28        if mnem.unwrap().ends_with('s') {
29            sbit = true;
30            mnem = mnem.unwrap().strip_suffix("s");
31        }
32
33        let op = match mnem {
34            Some("add") => Add,
35            Some("and") => And,
36            Some("ashr") => Ashr,
37            Some("br") => Br,
38            Some("cmp") => Cmp,
39            Some("jsr") => Jsr,
40            Some("ldb") => Ldb,
41            Some("ldr") => Ldr,
42            Some("mfhi") => Mfhi,
43            Some("mov") => Mov,
44            Some("movr") => Movr,
45            Some("movt") => Movt,
46            Some("mul") => Mul,
47            Some("not") => Not,
48            Some("or") => Or,
49            Some("pop") => Pop,
50            Some("push") => Push,
51            Some("ret") => Ret,
52            Some("ror") => Ror,
53            Some("sc") => Sc,
54            Some("seg") => Seg,
55            Some("shl") => Shl,
56            Some("shr") => Shr,
57            Some("stb") => Stb,
58            Some("str") => Str,
59            Some("sub") => Sub,
60            Some("uadd") => Uadd,
61            Some("ucmp") => Ucmp,
62            Some("umul") => Umul,
63            Some("usub") => Usub,
64            Some("xor") => Xor,
65            _ => return None,
66        };
67
68        Some((op, sbit, cond))
69    }
70}
71
72impl Argument {
73    /// Parses an argument.
74    pub fn parse(arg: &str) -> Option<Self> {
75        let pattern = Regex::new(r"^[._a-zA-Z][._a-zA-Z0-9]*$").unwrap();
76
77        // Ensure not just '.' and no subsequent dots.
78        if arg == "." || arg.contains("..") {
79            return None;
80        }
81
82        match arg {
83            "%a" => Some(Argument::Reg(Register::A)),
84            "%b" => Some(Argument::Reg(Register::B)),
85            "%c" => Some(Argument::Reg(Register::C)),
86            "%d" => Some(Argument::Reg(Register::D)),
87            "%e" => Some(Argument::Reg(Register::E)),
88            "%f" => Some(Argument::Reg(Register::F)),
89            "%g" => Some(Argument::Reg(Register::G)),
90            "%h" => Some(Argument::Reg(Register::H)),
91            "%r" => Some(Argument::Reg(Register::R)),
92            "%s" => Some(Argument::Reg(Register::S)),
93            "%sp" => Some(Argument::Reg(Register::SP)),
94            "%ip" => Some(Argument::Reg(Register::IP)),
95            i if i.parse::<isize>().is_ok() => Some(Argument::Imm(i.parse::<isize>().unwrap())),
96            l if pattern.is_match(l) => Some(Argument::Label(l.into())),
97            _ => None,
98        }
99    }
100}