riscy_isa/
lib.rs

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    /*
59      183, 2, 1, 0,     // lui t0,0x10
60      147, 130, 2, 24,  // addi t0,t0,384
61      147, 129, 2, 0,   // addi gp,t0,0
62      19, 5, 0, 0,      // addi a0,zero,0
63      147, 8, 96, 13,   // addi a7,zero,214
64      115, 0, 0, 0,     // ecall
65      19, 5, 117, 0,    // addi a0,a0,7
66      147, 2, 128, 0,   // addi t0,zero,8
67      179, 114, 85, 2,  // remu t0,a0,t0
68      51, 5, 85, 64,    // sub a0,a0,t0
69      147, 8, 96, 13,   // addi a7,zero,214
70      115, 0, 0, 0,     // ecall
71      35, 188, 161, 254,// sd a0,-8(gp)
72      19, 5, 0, 0,      // addi a0,zero,0
73      147, 2, 129, 0,   // addi t0,sp,8
74      19, 1, 129, 255,  // addi sp,sp,-8
75      35, 48, 81, 0,    // sd t0,0(sp)
76      239, 0, 64, 15,   // jal ra,61
77      19, 1, 129, 255,  // addi sp,sp,-8
78      35, 48, 161, 0,   // sd a0,0(sp)
79      3, 53, 1, 0,      // ld a0,0(sp)
80      19, 1, 129, 0,    // addi sp,sp,8
81      147, 8, 208, 5,   // addi a7,zero,93
82      115, 0, 0, 0,     // ecall
83      3, 54, 1, 0,      // ld a2,0(sp)
84      19, 1, 129, 0,    // addi sp,sp,8
85      131, 53, 1, 0,    // ld a1,0(sp)
86      19, 1, 129, 0,    // addi sp,sp,8
87      3, 53, 1, 0,      // ld a0,0(sp)
88      19, 1, 129, 0,    // addi sp,sp,8
89      147, 8, 240, 3,   // addi a7,zero,63
90      115, 0, 0, 0,     // ecall
91      103, 128, 0, 0,   // jalr zero,0(ra)
92      3, 54, 1, 0,      // ld a2,0(sp)
93      19, 1, 129, 0,    // addi sp,sp,8
94      131, 53, 1, 0,    // ld a1,0(sp)
95      19, 1, 129, 0,    // addi sp,sp,8
96      3, 53, 1, 0,      // ld a0,0(sp)
97      19, 1, 129, 0,    // addi sp,sp,8
98      147, 8, 0, 4,     // addi a7,zero,64
99      115, 0, 0, 0,     // ecall
100      103, 128, 0, 0,   // jalr zero,0(ra)
101      131, 54, 1, 0,    // ld a3,0(sp)
102      19, 1, 129, 0,    // addi sp,sp,8
103      3, 54, 1, 0,      // ld a2,0(sp)
104      19, 1, 129, 0,    // addi sp,sp,8
105      131, 53, 1, 0,    // ld a1,0(sp)
106      19, 1, 129, 0,    // addi sp,sp,8
107      19, 5, 192, 249,  // addi a0,zero,-100
108      147, 8, 128, 3,   // addi a7,zero,56
109      115, 0, 0, 0,     // ecall
110      103, 128, 0, 0,   // jalr zero,0(ra)
111      131, 50, 1, 0,    // ld t0,0(sp)
112      19, 1, 129, 0,    // addi sp,sp,8
113      147, 130, 114, 0, // addi t0,t0,7
114      19, 3, 128, 0,    // addi t1,zero,8
115      51, 243, 98, 2,   // remu t1,t0,t1
116      179, 130, 98, 64, // sub t0,t0,t1
117      3, 179, 129, 255, // ld t1,-8(gp)
118      51, 5, 83, 0,     // add a0,t1,t0
119      147, 8, 96, 13,   // addi a7,zero,214
120      115, 0, 0, 0,     // ecall
121      99, 4, 101, 0,    // beq a0,t1,2
122      99, 8, 0, 0,      // beq zero,zero,4
123      99, 6, 80, 0,     // beq zero,t0,3
124      19, 5, 0, 0,      // addi a0,zero,0
125      99, 6, 0, 0,      // beq zero,zero,3
126      35, 188, 161, 254,// sd a0,-8(gp)
127      19, 5, 3, 0,      // addi a0,t1,0
128      103, 128, 0, 0,   // jalr zero,0(ra)
129      131, 53, 1, 0,    // ld a1,0(sp)
130      19, 1, 129, 0,    // addi sp,sp,8
131      3, 53, 1, 0,      // ld a0,0(sp)
132      19, 1, 129, 0,    // addi sp,sp,8
133      147, 8, 16, 25,   // addi a7,zero,401
134      115, 0, 0, 0,     // ecall
135      19, 5, 8, 0,      // addi a0,a6,0
136      103, 128, 0, 0,   // jalr zero,0(ra)
137      19, 1, 129, 255,  // addi sp,sp,-8
138      35, 48, 17, 0,    // sd ra,0(sp)
139      19, 1, 129, 255,  // addi sp,sp,-8
140      35, 48, 129, 0,   // sd s0,0(sp)
141      19, 4, 1, 0,      // addi s0,sp,0
142      147, 2, 112, 3,   // addi t0,zero,55
143      19, 3, 160, 2,    // addi t1,zero,42
144      179, 130, 98, 0,  // add t0,t0,t1
145      19, 133, 2, 0,    // addi a0,t0,0
146      111, 0, 64, 0,    // jal zero,1
147      19, 1, 4, 0,      // addi sp,s0,0
148      3, 52, 1, 0,      // ld s0,0(sp)
149      19, 1, 129, 0,    // addi sp,sp,8
150      131, 48, 1, 0,    // ld ra,0(sp)
151      19, 1, 129, 1,    // addi sp,sp,24
152      103, 128, 0, 0,   // jalr zero,0(ra)
153    */
154
155    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, // 0xeba,
240        },
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: /*2?*/ 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}