1mod display;
36pub mod error;
37pub mod instruction;
38
39pub use error::*;
40pub use instruction::*;
41
42#[cfg(test)]
43mod tests {
44 use crate::instruction::{Instruction, MemoryOpLoadType, MemoryOpSize, Register};
45
46 fn decode_encode_compare(instruction: &Instruction) {
47 let encoded = instruction.encode();
48
49 let mut raw_instructions = vec![encoded.0];
50 if let Some(n) = encoded.1 {
51 raw_instructions.push(n);
52 }
53
54 let decoded = Instruction::decode(&raw_instructions);
55 if let Ok(new_instruction) = decoded {
56 let reencoded = new_instruction.encode();
57 assert_eq!(encoded, reencoded);
58 } else {
59 panic!("failed to reencode instruction");
60 }
61 }
62
63 #[test]
64 fn arithmetic_add32() {
65 for i in 0..10 {
66 let reg = Register::from_num(i).unwrap();
67
68 let ins = Instruction::add32(reg, i32::min_value());
69 decode_encode_compare(&ins);
70
71 let ins = Instruction::add32(reg, 0);
72 decode_encode_compare(&ins);
73
74 let ins = Instruction::add32(reg, i32::max_value());
75 decode_encode_compare(&ins);
76 }
77 }
78
79 #[test]
80 fn arithmetic_add64() {
81 for i in 0..10 {
82 let reg = Register::from_num(i).unwrap();
83
84 let ins = Instruction::add64(reg, i32::min_value());
85 decode_encode_compare(&ins);
86
87 let ins = Instruction::add64(reg, 0);
88 decode_encode_compare(&ins);
89
90 let ins = Instruction::add64(reg, i32::max_value());
91 decode_encode_compare(&ins);
92 }
93 }
94
95 #[test]
96 fn arithmetic_addx32() {
97 for i in 0..10 {
98 for j in 0..10 {
99 let dst_reg = Register::from_num(i).unwrap();
100 let src_reg = Register::from_num(j).unwrap();
101
102 let ins = Instruction::addx32(dst_reg, src_reg);
103 decode_encode_compare(&ins);
104 }
105 }
106 }
107
108 #[test]
109 fn arithmetic_addx64() {
110 for i in 0..10 {
111 for j in 0..10 {
112 let dst_reg = Register::from_num(i).unwrap();
113 let src_reg = Register::from_num(j).unwrap();
114
115 let ins = Instruction::addx64(dst_reg, src_reg);
116 decode_encode_compare(&ins);
117 }
118 }
119 }
120
121 #[test]
122 fn arithmetic_mov32() {
123 for i in 0..10 {
124 let reg = Register::from_num(i).unwrap();
125
126 let ins = Instruction::mov32(reg, i32::min_value());
127 decode_encode_compare(&ins);
128
129 let ins = Instruction::mov32(reg, 0);
130 decode_encode_compare(&ins);
131
132 let ins = Instruction::mov32(reg, i32::max_value());
133 decode_encode_compare(&ins);
134 }
135 }
136
137 #[test]
138 fn arithmetic_mov64() {
139 for i in 0..10 {
140 let reg = Register::from_num(i).unwrap();
141
142 let ins = Instruction::mov64(reg, i32::min_value());
143 decode_encode_compare(&ins);
144
145 let ins = Instruction::mov64(reg, 0);
146 decode_encode_compare(&ins);
147
148 let ins = Instruction::mov64(reg, i32::max_value());
149 decode_encode_compare(&ins);
150 }
151 }
152
153 #[test]
154 fn arithmetic_movx32() {
155 for i in 0..10 {
156 for j in 0..10 {
157 let dst_reg = Register::from_num(i).unwrap();
158 let src_reg = Register::from_num(j).unwrap();
159
160 let ins = Instruction::movx32(dst_reg, src_reg);
161 decode_encode_compare(&ins);
162 }
163 }
164 }
165
166 #[test]
167 fn arithmetic_movx64() {
168 for i in 0..10 {
169 for j in 0..10 {
170 let dst_reg = Register::from_num(i).unwrap();
171 let src_reg = Register::from_num(j).unwrap();
172
173 let ins = Instruction::movx64(dst_reg, src_reg);
174 decode_encode_compare(&ins);
175 }
176 }
177 }
178
179 #[test]
180 fn memory_load() {
181 for i in 0..10 {
182 let reg = Register::from_num(i).unwrap();
183
184 let ins = Instruction::load(reg, i64::min_value(), MemoryOpSize::Byte);
185 decode_encode_compare(&ins);
186
187 let ins = Instruction::load(reg, i64::max_value(), crate::MemoryOpSize::HalfWord);
188 decode_encode_compare(&ins);
189
190 let ins = Instruction::load(reg, 0, MemoryOpSize::Word);
191 decode_encode_compare(&ins);
192
193 let ins = Instruction::load(reg, 1, MemoryOpSize::DoubleWord);
194 decode_encode_compare(&ins);
195 }
196 }
197
198 #[test]
199 fn memory_loadx() {
200 for i in 0..10 {
201 for j in 0..10 {
202 let dst_reg = Register::from_num(i).unwrap();
203 let src_reg = Register::from_num(j).unwrap();
204
205 let ins = Instruction::loadx8(dst_reg, src_reg, i16::min_value());
206 decode_encode_compare(&ins);
207
208 let ins = Instruction::loadx8(dst_reg, src_reg, 0);
209 decode_encode_compare(&ins);
210
211 let ins = Instruction::loadx8(dst_reg, src_reg, i16::max_value());
212 decode_encode_compare(&ins);
213
214 let ins = Instruction::loadx16(dst_reg, src_reg, i16::min_value());
215 decode_encode_compare(&ins);
216
217 let ins = Instruction::loadx16(dst_reg, src_reg, 0);
218 decode_encode_compare(&ins);
219
220 let ins = Instruction::loadx16(dst_reg, src_reg, i16::max_value());
221 decode_encode_compare(&ins);
222
223 let ins = Instruction::loadx32(dst_reg, src_reg, i16::min_value());
224 decode_encode_compare(&ins);
225
226 let ins = Instruction::loadx32(dst_reg, src_reg, 0);
227 decode_encode_compare(&ins);
228
229 let ins = Instruction::loadx32(dst_reg, src_reg, i16::max_value());
230 decode_encode_compare(&ins);
231
232 let ins = Instruction::loadx64(dst_reg, src_reg, i16::min_value());
233 decode_encode_compare(&ins);
234
235 let ins = Instruction::loadx64(dst_reg, src_reg, 0);
236 decode_encode_compare(&ins);
237
238 let ins = Instruction::loadx64(dst_reg, src_reg, i16::max_value());
239 decode_encode_compare(&ins);
240 }
241 }
242 }
243
244 #[test]
245 fn memory_store() {
246 for i in 0..10 {
247 let reg = Register::from_num(i).unwrap();
248
249 let ins = Instruction::store8(reg, i16::min_value(), i8::min_value());
250 decode_encode_compare(&ins);
251
252 let ins = Instruction::store8(reg, 0, 0);
253 decode_encode_compare(&ins);
254
255 let ins = Instruction::store8(reg, i16::max_value(), i8::max_value());
256 decode_encode_compare(&ins);
257
258 let ins = Instruction::store16(reg, i16::min_value(), i16::min_value());
259 decode_encode_compare(&ins);
260
261 let ins = Instruction::store16(reg, 0, 0);
262 decode_encode_compare(&ins);
263
264 let ins = Instruction::store16(reg, i16::max_value(), i16::max_value());
265 decode_encode_compare(&ins);
266
267 let ins = Instruction::store32(reg, i16::min_value(), i32::min_value());
268 decode_encode_compare(&ins);
269
270 let ins = Instruction::store32(reg, 0, 0);
271 decode_encode_compare(&ins);
272
273 let ins = Instruction::store32(reg, i16::max_value(), i32::max_value());
274 decode_encode_compare(&ins);
275
276 let ins = Instruction::store64(reg, i16::min_value(), i64::min_value());
277 decode_encode_compare(&ins);
278
279 let ins = Instruction::store64(reg, 0, 0);
280 decode_encode_compare(&ins);
281
282 let ins = Instruction::store64(reg, i16::max_value(), i64::max_value());
283 decode_encode_compare(&ins);
284 }
285 }
286
287 #[test]
288 fn memory_storex() {
289 for i in 0..10 {
290 for j in 0..10 {
291 let dst_reg = Register::from_num(i).unwrap();
292 let src_reg = Register::from_num(j).unwrap();
293
294 let ins = Instruction::storex8(dst_reg, i16::min_value(), src_reg);
295 decode_encode_compare(&ins);
296
297 let ins = Instruction::storex8(dst_reg, 0, src_reg);
298 decode_encode_compare(&ins);
299
300 let ins = Instruction::storex8(dst_reg, i16::max_value(), src_reg);
301 decode_encode_compare(&ins);
302
303 let ins = Instruction::storex16(dst_reg, i16::min_value(), src_reg);
304 decode_encode_compare(&ins);
305
306 let ins = Instruction::storex16(dst_reg, 0, src_reg);
307 decode_encode_compare(&ins);
308
309 let ins = Instruction::storex16(dst_reg, i16::max_value(), src_reg);
310 decode_encode_compare(&ins);
311
312 let ins = Instruction::storex32(dst_reg, i16::min_value(), src_reg);
313 decode_encode_compare(&ins);
314
315 let ins = Instruction::storex32(dst_reg, 0, src_reg);
316 decode_encode_compare(&ins);
317
318 let ins = Instruction::storex32(dst_reg, i16::max_value(), src_reg);
319 decode_encode_compare(&ins);
320
321 let ins = Instruction::storex64(dst_reg, i16::min_value(), src_reg);
322 decode_encode_compare(&ins);
323
324 let ins = Instruction::storex64(dst_reg, 0, src_reg);
325 decode_encode_compare(&ins);
326
327 let ins = Instruction::storex64(dst_reg, i16::max_value(), src_reg);
328 decode_encode_compare(&ins);
329 }
330 }
331 }
332
333 #[test]
334 fn loadtype() {
335 for i in 0..10 {
336 let reg = Register::from_num(i).unwrap();
337
338 let ins = Instruction::loadtype(reg, i64::min_value(), MemoryOpLoadType::Void);
339 decode_encode_compare(&ins);
340
341 let ins = Instruction::loadtype(reg, 0, MemoryOpLoadType::Void);
342 decode_encode_compare(&ins);
343
344 let ins = Instruction::loadtype(reg, i64::max_value(), MemoryOpLoadType::Void);
345 decode_encode_compare(&ins);
346
347 let ins = Instruction::loadtype(reg, i64::min_value(), MemoryOpLoadType::Map);
348 decode_encode_compare(&ins);
349
350 let ins = Instruction::loadtype(reg, 0, MemoryOpLoadType::Map);
351 decode_encode_compare(&ins);
352
353 let ins = Instruction::loadtype(reg, i64::max_value(), MemoryOpLoadType::Map);
354 decode_encode_compare(&ins);
355
356 let ins = Instruction::loadtype(reg, i64::min_value(), MemoryOpLoadType::MapValue);
357 decode_encode_compare(&ins);
358
359 let ins = Instruction::loadtype(reg, 0, MemoryOpLoadType::MapValue);
360 decode_encode_compare(&ins);
361
362 let ins = Instruction::loadtype(reg, i64::max_value(), MemoryOpLoadType::MapValue);
363 decode_encode_compare(&ins);
364
365 let ins = Instruction::loadtype(reg, i64::min_value(), MemoryOpLoadType::BtfId);
366 decode_encode_compare(&ins);
367
368 let ins = Instruction::loadtype(reg, 0, MemoryOpLoadType::BtfId);
369 decode_encode_compare(&ins);
370
371 let ins = Instruction::loadtype(reg, i64::max_value(), MemoryOpLoadType::BtfId);
372 decode_encode_compare(&ins);
373
374 let ins = Instruction::loadtype(reg, i64::min_value(), MemoryOpLoadType::Function);
375 decode_encode_compare(&ins);
376
377 let ins = Instruction::loadtype(reg, 0, MemoryOpLoadType::Function);
378 decode_encode_compare(&ins);
379
380 let ins = Instruction::loadtype(reg, i64::max_value(), MemoryOpLoadType::Function);
381 decode_encode_compare(&ins);
382
383 let ins = Instruction::loadtype(reg, i64::min_value(), MemoryOpLoadType::MapIndex);
384 decode_encode_compare(&ins);
385
386 let ins = Instruction::loadtype(reg, 0, MemoryOpLoadType::MapIndex);
387 decode_encode_compare(&ins);
388
389 let ins = Instruction::loadtype(reg, i64::max_value(), MemoryOpLoadType::MapIndex);
390 decode_encode_compare(&ins);
391
392 let ins = Instruction::loadtype(reg, i64::min_value(), MemoryOpLoadType::MapIndexValue);
393 decode_encode_compare(&ins);
394
395 let ins = Instruction::loadtype(reg, 0, MemoryOpLoadType::MapIndexValue);
396 decode_encode_compare(&ins);
397
398 let ins = Instruction::loadtype(reg, i64::max_value(), MemoryOpLoadType::MapIndexValue);
399 decode_encode_compare(&ins);
400 }
401 }
402
403 #[test]
404 fn call() {
405 let ins = Instruction::call(0);
406 decode_encode_compare(&ins);
407
408 let ins = Instruction::call(u32::max_value());
409 decode_encode_compare(&ins);
410 }
411
412 #[test]
413 fn exit() {
414 let ins = Instruction::exit();
415 decode_encode_compare(&ins);
416 }
417}