]> Witch of Git - jade-mouse/blob - toolchain/src/inst/encode.rs
[WIP] Implementing encoding
[jade-mouse] / toolchain / src / inst / encode.rs
1 use crate::inst::{Addr, Cond, Inst, Reg, I7, U4};
2 use std::io::{self, Write};
3
4 pub trait Encode {
5 fn encode(&self, out: &mut impl Write) -> io::Result<()>;
6 }
7
8 fn unpack_cond(c: Cond) -> (u8, u8, Reg, Reg) {
9 use Cond::*;
10 let (o2, o1, ra, rb) = match c {
11 Eql(ra, rb) => (0, 0, ra.min(rb), ra.max(rb)),
12 Neq(ra, rb) => (0, 0, ra.max(rb), ra.min(rb)),
13 Test(ra, rb) => (0, 1, ra.min(rb), ra.max(rb)),
14 TestNot(ra, rb) => (0, 1, ra.min(rb), ra.max(rb)),
15 Lt(ra, rb) => (1, 0, ra, rb),
16 Ult(ra, rb) => (1, 1, ra, rb),
17 };
18 debug_assert_ne!(ra, rb, "ra == rb reserved for fixed addressing");
19 (o2, o1, ra, rb)
20 }
21
22 impl Encode for Inst {
23 fn encode(&self, out: &mut impl Write) -> io::Result<()> {
24 use Inst::*;
25 match *self {
26 Halt => out.write_all(&[0x00])?,
27 Nope => out.write_all(&[0x01])?,
28 Alu2(rd, op, r2) => {
29 out.write_all(&[0x00 | (op as u8) << 4 | (rd as u8) << 2 | r2 as u8])?
30 }
31 Jalr(r) => out.write_all(&[0x80 | (r as u8) << 2 | r as u8])?,
32 Move(rd, r2) => {
33 debug_assert_ne!(rd, r2, "Can't move to self");
34 out.write_all(&[0x00, (rd as u8) << 2 | r2 as u8])?
35 }
36 Alu1(r, op) => out.write_all(&[0x90 | (r as u8) << 2 | op as u8])?,
37 Mem(op, r_data, Addr::Reg(r_addr)) => {
38 out.write_all(&[0xa0 | (op as u8) << 4 | (r_data as u8) << 2 | r_addr as u8])?
39 }
40 Branch(cond, I7(off)) => {
41 let (o2, o1, ra, rb) = unpack_cond(cond);
42 out.write_all(&[
43 0xc0 | o2 << 4 | (ra as u8) << 2 | rb as u8,
44 o1 << 7 | off as u8,
45 ])?
46 }
47 JumpI(off) => out.write_all(&[0xc0, off as u8])?,
48 Mem(op, rd, Addr::Fixed(addr)) => out.write_all(&[])?,
49 AddI(rd, imm) => out.write_all(&[0xe0 | (rd as u8) << 2, imm as u8])?,
50 AluCompact(rd, op, U4(imm)) => {
51 out.write_all(&[0xe1 | (rd as u8) << 2, (op as u8) << 4 | imm as u8])?
52 }
53 LdImm(h, rd, imm) => out.write_all(&[0xe2 | (h as u8) << 1, imm])?,
54 Mem(
55 op,
56 rd,
57 Addr::Extended {
58 base,
59 offset,
60 stack,
61 size,
62 },
63 ) => out.write_all(&[])?,
64 }
65 Ok(())
66 }
67 }