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