memega/lgp/
asm.rs

1use eyre::{eyre, Result};
2
3use crate::lgp::op::{Op, Opcode, Operand};
4
5fn lgp_asm_op(s: &str) -> Result<Op> {
6    let mut tokens = s.split_whitespace();
7    let mut data = [0, 0, 0];
8    let op = match tokens.next().ok_or_else(|| eyre!("missing token"))? {
9        "nop" => Opcode::Nop,
10        "add" => Opcode::Add,
11        "sub" => Opcode::Sub,
12        "mul" => Opcode::Mul,
13        "div" => Opcode::Div,
14        "abs" => Opcode::Abs,
15        "neg" => Opcode::Neg,
16        "pow" => Opcode::Pow,
17        "ln" => Opcode::Log,
18        "load" => Opcode::Load,
19        "mov" => Opcode::IndirectCopy,
20        "jlt" => Opcode::Jlt,
21        "jle" => Opcode::Jle,
22        "jeq" => Opcode::Jeq,
23        _ => return Err(eyre!("unknown instruction format")),
24    };
25    let mut idx = 0;
26    for i in 0..data.len() {
27        match op.operand(i) {
28            Operand::None => {}
29            Operand::Register => {
30                let tok = tokens.next().ok_or_else(|| eyre!("missing register"))?;
31                data[idx] = tok.replace(&[',', '[', ']'][..], "")[1..].parse()?;
32                idx += 1;
33            }
34            Operand::Immediate => {
35                let tok = tokens.next().ok_or_else(|| eyre!("missing immediate for {:?}", op))?;
36                let tok = tok.parse::<f64>()?;
37                data[idx] = (tok.fract() * 256.0).floor() as u8;
38                idx += 1;
39                data[idx] = tok.floor() as u8;
40                // TODO: Hacky
41                return Ok(Op::new(op, data));
42            }
43            Operand::Relative => {
44                let tok = tokens.next().ok_or_else(|| eyre!("missing relative jump immediate"))?;
45                data[idx] = tok.parse::<i8>()? as u8;
46                idx += 1;
47            }
48        }
49    }
50    Ok(Op::new(op, data))
51}
52
53pub fn lgp_asm(s: &str) -> Result<Vec<Op>> {
54    let mut ops = Vec::new();
55    for line in s.lines() {
56        ops.push(lgp_asm_op(line)?);
57    }
58    Ok(ops)
59}