]> Witch of Git - jade-rose/blob - toolchain/src/inst/decode.rs
Update ISA spec to v0.2.2
[jade-rose] / toolchain / src / inst / decode.rs
1 use super::{AddImm, AluI, Data, Inst, LdSt, Op1, OpI3, OpR, Reg, Special, U3};
2 use std::io::{self, Read};
3
4 pub trait Decode: Sized {
5 fn decode(reader: &mut impl Read) -> io::Result<Self>;
6 }
7
8 fn reg(x: u8) -> Reg {
9 Reg::new(x & 0x7).unwrap()
10 }
11
12 fn special(x: u8) -> io::Result<Special> {
13 match x {
14 0b000 => Ok(Special::Data(Data::D1)),
15 0b001 => Ok(Special::Data(Data::D2)),
16 0b010 => Ok(Special::Code),
17 0b011 => Err(io::Error::new(
18 io::ErrorKind::InvalidInput,
19 "Reserved special register",
20 )),
21 _ => Err(io::Error::new(
22 io::ErrorKind::InvalidInput,
23 "Invalid special register",
24 )),
25 }
26 }
27
28 fn op1(x: u8) -> Op1 {
29 match x {
30 0b000 => Op1::Zero,
31 0b001 => Op1::Lsl1,
32 0b010 => Op1::Lsr1,
33 0b011 => Op1::Asr1,
34 0b100 => Op1::Incr,
35 0b101 => Op1::Decr,
36 0b110 => Op1::Comp,
37 0b111 => Op1::Negt,
38 _ => unreachable!(),
39 }
40 }
41
42 fn op_r(x: u8) -> OpR {
43 match x & 7 {
44 0b000 => OpR::Add,
45 0b001 => OpR::Sub,
46 0b010 => OpR::And,
47 0b011 => OpR::Ior,
48 0b100 => OpR::Xor,
49 0b101 => OpR::Lsl,
50 0b110 => OpR::Lsr,
51 0b111 => OpR::Asr,
52 _ => unreachable!(),
53 }
54 }
55
56 fn flag(x: u8) -> bool {
57 x & 2 != 0
58 }
59
60 fn op_compact(x: u8) -> OpI3 {
61 match (x >> 3) & 7 {
62 0b000 => OpI3::Rol,
63 0b001 => OpI3::Lsl,
64 0b010 => OpI3::Lsr,
65 0b011 => OpI3::Asr,
66 0b100 => OpI3::Clr,
67 0b101 => OpI3::Ins,
68 0b110 => OpI3::Tog,
69 0b111 => OpI3::Ext,
70 _ => unreachable!(),
71 }
72 }
73
74 fn ldst(o: u8) -> LdSt {
75 if o & 0x1 == 0 {
76 LdSt::Ld
77 } else {
78 LdSt::St
79 }
80 }
81
82 fn data(o: u8) -> Data {
83 if o & 0x4 == 0 {
84 Data::D1
85 } else {
86 Data::D2
87 }
88 }
89
90 impl Decode for Inst {
91 fn decode(reader: &mut impl Read) -> io::Result<Self> {
92 let mut op_byte = [0];
93 reader.read_exact(&mut op_byte)?;
94 Ok(match (op_byte[0] >> 3, op_byte[0] & 7) {
95 (0b0000_0, 0b000) => Inst::Stop,
96 (0b0000_0, 0b001) => Inst::Nope,
97 (0b0000_0, 0b010) => Inst::Prnt,
98 (0b0000_0, 0b110) => Inst::CAbA,
99 (0b0000_0, 0b111) => Inst::COfA,
100 (0b0000_1, o) => Inst::Alu1(op1(o)),
101 (0b0001_0, s) => Inst::Get(special(s)?),
102 (0b0001_1, s) => Inst::Set(special(s)?),
103 (0b0010_0, r) => Inst::GetR(reg(r)),
104 (0b0010_1, r) => Inst::SetR(reg(r)),
105 (0b0011_0, r) => Inst::Swap(reg(r)),
106 (0b0011_1, r) => Inst::IsLt(reg(r)),
107 (o @ 0b0100_0..=0b0111_1, r) => Inst::AluR(op_r(o), reg(r)),
108 (o @ 0b1000_0..=0b1011_1, r) => Inst::Mem(ldst(o), data(o), reg(r), flag(o)),
109 (0b1111_0..=0b1111_1, _) => {
110 let mut imm_byte = [0];
111 reader
112 .read_exact(&mut imm_byte)
113 .map_err(|e| match e.kind() {
114 io::ErrorKind::UnexpectedEof => io::Error::new(
115 io::ErrorKind::InvalidInput,
116 "Extended instruction missing operand",
117 ),
118 _ => e,
119 })?;
120 let imm = imm_byte[0];
121 match op_byte[0] & 0xf {
122 0b0000 => Inst::AluI(AluI::And(imm)),
123 0b0001 => Inst::AluI(AluI::Ior(imm)),
124 0b0010 => Inst::AluI(AluI::Xor(imm)),
125 0b0011 => match imm >> 6 {
126 0b00 | 0b01 | 0b11 => {
127 Inst::AluI(AluI::Add(AddImm::new(imm as i8).unwrap()))
128 }
129 0b10 => {
130 let imm3 = U3::new(imm & 7).unwrap();
131 Inst::AluI(AluI::Compact(op_compact(imm), imm3))
132 }
133 _ => unreachable!(),
134 },
135 0b0100 => Inst::BEzI(imm as i8),
136 0b0101 => Inst::JOfI(imm as i8), /* reserved branch */
137 0b0110 => Inst::CAbI(imm),
138 0b0111 => Inst::COfI(imm as i8),
139 0b1110 => Inst::GetI(imm),
140 0b1111 => {
141 return Err(io::Error::new(
142 io::ErrorKind::InvalidInput,
143 "reserved extended EXT1",
144 ))
145 } /* reserved with immediate */
146 _ => {
147 return Err(io::Error::new(
148 io::ErrorKind::InvalidInput,
149 "reseved with immediate",
150 ))
151 } /* reserved with immediate */
152 }
153 }
154 _ => {
155 return Err(io::Error::new(
156 io::ErrorKind::InvalidInput,
157 "invalid instruction",
158 ))
159 }
160 })
161 }
162 }