1mod decoding_stream;
2mod encoding_stream;
3mod fp_register;
4mod instruction;
5mod opcode;
6mod register;
7
8pub use self::{
9 decoding_stream::DecodingStream, encoding_stream::EncodingStream, instruction::Instruction,
10 opcode::*, register::Register,
11};
12
13#[derive(Debug)]
14pub enum ReadError {
15 InvalidInstruction,
16}
17
18#[test]
19pub fn test_stream_decoding_add() {
20 let input = [
21 183, 2, 1, 0, 147, 130, 2, 24, 147, 129, 2, 0, 19, 5, 0, 0, 147, 8, 96, 13, 115, 0, 0, 0,
22 19, 5, 117, 0, 147, 2, 128, 0, 179, 114, 85, 2, 51, 5, 85, 64, 147, 8, 96, 13, 115, 0, 0,
23 0, 35, 188, 161, 254, 19, 5, 0, 0, 147, 2, 129, 0, 19, 1, 129, 255, 35, 48, 81, 0, 239, 0,
24 64, 15, 19, 1, 129, 255, 35, 48, 161, 0, 3, 53, 1, 0, 19, 1, 129, 0, 147, 8, 208, 5, 115,
25 0, 0, 0, 3, 54, 1, 0, 19, 1, 129, 0, 131, 53, 1, 0, 19, 1, 129, 0, 3, 53, 1, 0, 19, 1, 129,
26 0, 147, 8, 240, 3, 115, 0, 0, 0, 103, 128, 0, 0, 3, 54, 1, 0, 19, 1, 129, 0, 131, 53, 1, 0,
27 19, 1, 129, 0, 3, 53, 1, 0, 19, 1, 129, 0, 147, 8, 0, 4, 115, 0, 0, 0, 103, 128, 0, 0, 131,
28 54, 1, 0, 19, 1, 129, 0, 3, 54, 1, 0, 19, 1, 129, 0, 131, 53, 1, 0, 19, 1, 129, 0, 19, 5,
29 192, 249, 147, 8, 128, 3, 115, 0, 0, 0, 103, 128, 0, 0, 131, 50, 1, 0, 19, 1, 129, 0, 147,
30 130, 114, 0, 19, 3, 128, 0, 51, 243, 98, 2, 179, 130, 98, 64, 3, 179, 129, 255, 51, 5, 83,
31 0, 147, 8, 96, 13, 115, 0, 0, 0, 99, 4, 101, 0, 99, 8, 0, 0, 99, 6, 80, 0, 19, 5, 0, 0, 99,
32 6, 0, 0, 35, 188, 161, 254, 19, 5, 3, 0, 103, 128, 0, 0, 131, 53, 1, 0, 19, 1, 129, 0, 3,
33 53, 1, 0, 19, 1, 129, 0, 147, 8, 16, 25, 115, 0, 0, 0, 19, 5, 8, 0, 103, 128, 0, 0, 19, 1,
34 129, 255, 35, 48, 17, 0, 19, 1, 129, 255, 35, 48, 129, 0, 19, 4, 1, 0, 147, 2, 112, 3, 19,
35 3, 160, 2, 179, 130, 98, 0, 19, 133, 2, 0, 111, 0, 64, 0, 19, 1, 4, 0, 3, 52, 1, 0, 19, 1,
36 129, 0, 131, 48, 1, 0, 19, 1, 129, 1, 103, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
37 ];
38 let stream = DecodingStream::new(&input);
39
40 let instructions = stream.collect::<Vec<Instruction>>();
41
42 assert_eq!(instructions.len(), 94);
43}
44
45#[test]
46pub fn test_instruction_encoding() {
47 fn encoding_test(bytes: &[u8], instruction: Instruction) {
48 let mut stream = DecodingStream::new(bytes);
49 let actual = stream.next().unwrap();
50 assert_eq!(actual, instruction);
51
52 let mut stream = EncodingStream::new();
53 stream.push(&instruction);
54 let actual = stream.bytes();
55 assert_eq!(actual, bytes);
56 }
57
58 encoding_test(
156 &[183, 2, 1, 0],
157 Instruction::U {
158 opcode: Opcode::Lui,
159 imm: 0x10000,
160 rd: Register::T0,
161 },
162 );
163 encoding_test(
164 &[147, 130, 2, 24],
165 Instruction::I {
166 opcode: Opcode::OpImm(OpImmFunction::ADDI),
167 rd: Register::T0,
168 rs1: Register::T0,
169 imm: 384,
170 },
171 );
172 encoding_test(
173 &[19, 5, 0, 0],
174 Instruction::I {
175 opcode: Opcode::OpImm(OpImmFunction::ADDI),
176 rd: Register::A0,
177 rs1: Register::Zero,
178 imm: 0,
179 },
180 );
181 encoding_test(
182 &[147, 8, 96, 13],
183 Instruction::I {
184 opcode: Opcode::OpImm(OpImmFunction::ADDI),
185 rd: Register::A7,
186 rs1: Register::Zero,
187 imm: 214,
188 },
189 );
190 encoding_test(
191 &[0x93, 0x87, 0xe0, 0xFC],
192 Instruction::I {
193 opcode: Opcode::OpImm(OpImmFunction::ADDI),
194 rd: Register::A5,
195 rs1: Register::ReturnAddress,
196 imm: -50,
197 },
198 );
199 encoding_test(
200 &[115, 0, 0, 0],
201 Instruction::IS {
202 opcode: Opcode::System(opcode::SystemFunction::Environment(
203 opcode::EnvironmentFunction::ECALL,
204 )),
205 rd: Register::Zero,
206 rs1: Register::Zero,
207 imm: 0,
208 },
209 );
210 encoding_test(
211 &[239, 0, 64, 15],
212 Instruction::J {
213 opcode: Opcode::JAl,
214 rd: Register::ReturnAddress,
215 imm: 244,
216 },
217 );
218 encoding_test(
219 &[0x6f, 0x00, 0x80, 0x04],
220 Instruction::J {
221 opcode: Opcode::JAl,
222 rd: Register::Zero,
223 imm: 72,
224 },
225 );
226 encoding_test(
227 &[0x6f, 0x10, 0xf0, 0x67],
228 Instruction::J {
229 opcode: Opcode::JAl,
230 rd: Register::Zero,
231 imm: 7806,
232 },
233 );
234 encoding_test(
235 &0x946ff0efu32.to_le_bytes(),
236 Instruction::J {
237 opcode: Opcode::JAl,
238 rd: Register::ReturnAddress,
239 imm: -0xeba, },
241 );
242
243 encoding_test(
244 &[99, 4, 101, 0],
245 Instruction::B { opcode: Opcode::Branch(BranchOperation::Equal), rs1: Register::A0, rs2: Register::T1, imm: 8},
246 );
247 encoding_test(
248 &[0x83, 0x21, 0x72, 0x03],
249 Instruction::I {
250 opcode: Opcode::Load(LoadWidth::Word),
251 imm: 55,
252 rs1: Register::ThreadPointer,
253 rd: Register::GlobalPointer,
254 },
255 );
256 encoding_test(
257 &[35, 48, 81, 0],
258 Instruction::S {
259 opcode: Opcode::Store(StoreWidth::DoubleWord),
260 rs2: Register::T0,
261 rs1: Register::StackPointer,
262 imm: 0,
263 },
264 );
265 encoding_test(
266 &[179, 130, 98, 64],
267 Instruction::R {
268 opcode: Opcode::Op(OpFunction::SUB),
269 rs1: Register::T0,
270 rs2: Register::T1,
271 rd: Register::T0,
272 },
273 );
274}
275
276#[test]
277pub fn test_instruction_roundtrip() {
278 fn roundtrip_test(input: &[u8]) {
279 let mut stream = DecodingStream::new(input);
280 let instruction = stream.next().unwrap();
281
282 let mut stream = EncodingStream::new();
283 stream.push(&instruction);
284
285 let output = stream.bytes();
286 assert_eq!(output, input);
287 }
288
289 roundtrip_test(&[183, 2, 1, 0]);
290 roundtrip_test(&[147, 130, 2, 24]);
291 roundtrip_test(&[19, 5, 0, 0]);
292 roundtrip_test(&[147, 8, 96, 13]);
293 roundtrip_test(&[0x93, 0x87, 0xe0, 0xFC]);
294 roundtrip_test(&[115, 0, 0, 0]);
295 roundtrip_test(&[239, 0, 64, 15]);
296 roundtrip_test(&[99, 4, 101, 0]);
297 roundtrip_test(&[0x83, 0x21, 0x72, 0x03]);
298 roundtrip_test(&[35, 48, 81, 0]);
299 roundtrip_test(&[179, 130, 98, 64]);
300}