xref: /DragonOS/kernel/crates/rbpf/tests/assembler.rs (revision fae6e9ade46a52976ad5d099643d51cc20876448)
1*fae6e9adSlinfeng // SPDX-License-Identifier: (Apache-2.0 OR MIT)
2*fae6e9adSlinfeng // Copyright 2017 Rich Lane <lanerl@gmail.com>
3*fae6e9adSlinfeng 
4*fae6e9adSlinfeng #![allow(clippy::unreadable_literal)]
5*fae6e9adSlinfeng 
6*fae6e9adSlinfeng extern crate rbpf;
7*fae6e9adSlinfeng mod common;
8*fae6e9adSlinfeng 
9*fae6e9adSlinfeng use common::{TCP_SACK_ASM, TCP_SACK_BIN};
10*fae6e9adSlinfeng use rbpf::{assembler::assemble, ebpf};
11*fae6e9adSlinfeng 
asm(src: &str) -> Result<Vec<ebpf::Insn>, String>12*fae6e9adSlinfeng fn asm(src: &str) -> Result<Vec<ebpf::Insn>, String> {
13*fae6e9adSlinfeng     Ok(ebpf::to_insn_vec(&(assemble(src))?))
14*fae6e9adSlinfeng }
15*fae6e9adSlinfeng 
insn(opc: u8, dst: u8, src: u8, off: i16, imm: i32) -> ebpf::Insn16*fae6e9adSlinfeng fn insn(opc: u8, dst: u8, src: u8, off: i16, imm: i32) -> ebpf::Insn {
17*fae6e9adSlinfeng     ebpf::Insn {
18*fae6e9adSlinfeng         opc,
19*fae6e9adSlinfeng         dst,
20*fae6e9adSlinfeng         src,
21*fae6e9adSlinfeng         off,
22*fae6e9adSlinfeng         imm,
23*fae6e9adSlinfeng     }
24*fae6e9adSlinfeng }
25*fae6e9adSlinfeng 
26*fae6e9adSlinfeng #[test]
test_empty()27*fae6e9adSlinfeng fn test_empty() {
28*fae6e9adSlinfeng     assert_eq!(asm(""), Ok(vec![]));
29*fae6e9adSlinfeng }
30*fae6e9adSlinfeng 
31*fae6e9adSlinfeng // Example for InstructionType::NoOperand.
32*fae6e9adSlinfeng #[test]
test_exit()33*fae6e9adSlinfeng fn test_exit() {
34*fae6e9adSlinfeng     assert_eq!(asm("exit"), Ok(vec![insn(ebpf::EXIT, 0, 0, 0, 0)]));
35*fae6e9adSlinfeng }
36*fae6e9adSlinfeng 
37*fae6e9adSlinfeng // Example for InstructionType::AluBinary.
38*fae6e9adSlinfeng #[test]
test_add64()39*fae6e9adSlinfeng fn test_add64() {
40*fae6e9adSlinfeng     assert_eq!(
41*fae6e9adSlinfeng         asm("add64 r1, r3"),
42*fae6e9adSlinfeng         Ok(vec![insn(ebpf::ADD64_REG, 1, 3, 0, 0)])
43*fae6e9adSlinfeng     );
44*fae6e9adSlinfeng     assert_eq!(
45*fae6e9adSlinfeng         asm("add64 r1, 5"),
46*fae6e9adSlinfeng         Ok(vec![insn(ebpf::ADD64_IMM, 1, 0, 0, 5)])
47*fae6e9adSlinfeng     );
48*fae6e9adSlinfeng }
49*fae6e9adSlinfeng 
50*fae6e9adSlinfeng // Example for InstructionType::AluUnary.
51*fae6e9adSlinfeng #[test]
test_neg64()52*fae6e9adSlinfeng fn test_neg64() {
53*fae6e9adSlinfeng     assert_eq!(asm("neg64 r1"), Ok(vec![insn(ebpf::NEG64, 1, 0, 0, 0)]));
54*fae6e9adSlinfeng }
55*fae6e9adSlinfeng 
56*fae6e9adSlinfeng // Example for InstructionType::LoadReg.
57*fae6e9adSlinfeng #[test]
test_ldxw()58*fae6e9adSlinfeng fn test_ldxw() {
59*fae6e9adSlinfeng     assert_eq!(
60*fae6e9adSlinfeng         asm("ldxw r1, [r2+5]"),
61*fae6e9adSlinfeng         Ok(vec![insn(ebpf::LD_W_REG, 1, 2, 5, 0)])
62*fae6e9adSlinfeng     );
63*fae6e9adSlinfeng }
64*fae6e9adSlinfeng 
65*fae6e9adSlinfeng // Example for InstructionType::StoreImm.
66*fae6e9adSlinfeng #[test]
test_stw()67*fae6e9adSlinfeng fn test_stw() {
68*fae6e9adSlinfeng     assert_eq!(
69*fae6e9adSlinfeng         asm("stw [r2+5], 7"),
70*fae6e9adSlinfeng         Ok(vec![insn(ebpf::ST_W_IMM, 2, 0, 5, 7)])
71*fae6e9adSlinfeng     );
72*fae6e9adSlinfeng }
73*fae6e9adSlinfeng 
74*fae6e9adSlinfeng // Example for InstructionType::StoreReg.
75*fae6e9adSlinfeng #[test]
test_stxw()76*fae6e9adSlinfeng fn test_stxw() {
77*fae6e9adSlinfeng     assert_eq!(
78*fae6e9adSlinfeng         asm("stxw [r2+5], r8"),
79*fae6e9adSlinfeng         Ok(vec![insn(ebpf::ST_W_REG, 2, 8, 5, 0)])
80*fae6e9adSlinfeng     );
81*fae6e9adSlinfeng }
82*fae6e9adSlinfeng 
83*fae6e9adSlinfeng // Example for InstructionType::JumpUnconditional.
84*fae6e9adSlinfeng #[test]
test_ja()85*fae6e9adSlinfeng fn test_ja() {
86*fae6e9adSlinfeng     assert_eq!(asm("ja +8"), Ok(vec![insn(ebpf::JA, 0, 0, 8, 0)]));
87*fae6e9adSlinfeng     assert_eq!(asm("ja -3"), Ok(vec![insn(ebpf::JA, 0, 0, -3, 0)]));
88*fae6e9adSlinfeng }
89*fae6e9adSlinfeng 
90*fae6e9adSlinfeng // Example for InstructionType::JumpConditional.
91*fae6e9adSlinfeng #[test]
test_jeq()92*fae6e9adSlinfeng fn test_jeq() {
93*fae6e9adSlinfeng     assert_eq!(
94*fae6e9adSlinfeng         asm("jeq r1, 4, +8"),
95*fae6e9adSlinfeng         Ok(vec![insn(ebpf::JEQ_IMM, 1, 0, 8, 4)])
96*fae6e9adSlinfeng     );
97*fae6e9adSlinfeng     assert_eq!(
98*fae6e9adSlinfeng         asm("jeq r1, r3, +8"),
99*fae6e9adSlinfeng         Ok(vec![insn(ebpf::JEQ_REG, 1, 3, 8, 0)])
100*fae6e9adSlinfeng     );
101*fae6e9adSlinfeng }
102*fae6e9adSlinfeng 
103*fae6e9adSlinfeng // Example for InstructionType::Call.
104*fae6e9adSlinfeng #[test]
test_call()105*fae6e9adSlinfeng fn test_call() {
106*fae6e9adSlinfeng     assert_eq!(asm("call 300"), Ok(vec![insn(ebpf::CALL, 0, 0, 0, 300)]));
107*fae6e9adSlinfeng }
108*fae6e9adSlinfeng 
109*fae6e9adSlinfeng // Example for InstructionType::Endian.
110*fae6e9adSlinfeng #[test]
test_be32()111*fae6e9adSlinfeng fn test_be32() {
112*fae6e9adSlinfeng     assert_eq!(asm("be32 r1"), Ok(vec![insn(ebpf::BE, 1, 0, 0, 32)]));
113*fae6e9adSlinfeng }
114*fae6e9adSlinfeng 
115*fae6e9adSlinfeng // Example for InstructionType::LoadImm.
116*fae6e9adSlinfeng #[test]
test_lddw()117*fae6e9adSlinfeng fn test_lddw() {
118*fae6e9adSlinfeng     assert_eq!(
119*fae6e9adSlinfeng         asm("lddw r1, 0x1234abcd5678eeff"),
120*fae6e9adSlinfeng         Ok(vec![
121*fae6e9adSlinfeng             insn(ebpf::LD_DW_IMM, 1, 0, 0, 0x5678eeff),
122*fae6e9adSlinfeng             insn(0, 0, 0, 0, 0x1234abcd)
123*fae6e9adSlinfeng         ])
124*fae6e9adSlinfeng     );
125*fae6e9adSlinfeng     assert_eq!(
126*fae6e9adSlinfeng         asm("lddw r1, 0xff11ee22dd33cc44"),
127*fae6e9adSlinfeng         Ok(vec![
128*fae6e9adSlinfeng             insn(ebpf::LD_DW_IMM, 1, 0, 0, 0xdd33cc44u32 as i32),
129*fae6e9adSlinfeng             insn(0, 0, 0, 0, 0xff11ee22u32 as i32)
130*fae6e9adSlinfeng         ])
131*fae6e9adSlinfeng     );
132*fae6e9adSlinfeng }
133*fae6e9adSlinfeng 
134*fae6e9adSlinfeng // Example for InstructionType::LoadAbs.
135*fae6e9adSlinfeng #[test]
test_ldabsw()136*fae6e9adSlinfeng fn test_ldabsw() {
137*fae6e9adSlinfeng     assert_eq!(asm("ldabsw 1"), Ok(vec![insn(ebpf::LD_ABS_W, 0, 0, 0, 1)]));
138*fae6e9adSlinfeng }
139*fae6e9adSlinfeng 
140*fae6e9adSlinfeng // Example for InstructionType::LoadInd.
141*fae6e9adSlinfeng #[test]
test_ldindw()142*fae6e9adSlinfeng fn test_ldindw() {
143*fae6e9adSlinfeng     assert_eq!(
144*fae6e9adSlinfeng         asm("ldindw r1, 2"),
145*fae6e9adSlinfeng         Ok(vec![insn(ebpf::LD_IND_W, 0, 1, 0, 2)])
146*fae6e9adSlinfeng     );
147*fae6e9adSlinfeng }
148*fae6e9adSlinfeng 
149*fae6e9adSlinfeng // Example for InstructionType::LoadReg.
150*fae6e9adSlinfeng #[test]
test_ldxdw()151*fae6e9adSlinfeng fn test_ldxdw() {
152*fae6e9adSlinfeng     assert_eq!(
153*fae6e9adSlinfeng         asm("ldxdw r1, [r2+3]"),
154*fae6e9adSlinfeng         Ok(vec![insn(ebpf::LD_DW_REG, 1, 2, 3, 0)])
155*fae6e9adSlinfeng     );
156*fae6e9adSlinfeng }
157*fae6e9adSlinfeng 
158*fae6e9adSlinfeng // Example for InstructionType::StoreImm.
159*fae6e9adSlinfeng #[test]
test_sth()160*fae6e9adSlinfeng fn test_sth() {
161*fae6e9adSlinfeng     assert_eq!(
162*fae6e9adSlinfeng         asm("sth [r1+2], 3"),
163*fae6e9adSlinfeng         Ok(vec![insn(ebpf::ST_H_IMM, 1, 0, 2, 3)])
164*fae6e9adSlinfeng     );
165*fae6e9adSlinfeng }
166*fae6e9adSlinfeng 
167*fae6e9adSlinfeng // Example for InstructionType::StoreReg.
168*fae6e9adSlinfeng #[test]
test_stxh()169*fae6e9adSlinfeng fn test_stxh() {
170*fae6e9adSlinfeng     assert_eq!(
171*fae6e9adSlinfeng         asm("stxh [r1+2], r3"),
172*fae6e9adSlinfeng         Ok(vec![insn(ebpf::ST_H_REG, 1, 3, 2, 0)])
173*fae6e9adSlinfeng     );
174*fae6e9adSlinfeng }
175*fae6e9adSlinfeng 
176*fae6e9adSlinfeng // Test all supported AluBinary mnemonics.
177*fae6e9adSlinfeng #[test]
test_alu_binary()178*fae6e9adSlinfeng fn test_alu_binary() {
179*fae6e9adSlinfeng     assert_eq!(
180*fae6e9adSlinfeng         asm("add r1, r2
181*fae6e9adSlinfeng                     sub r1, r2
182*fae6e9adSlinfeng                     mul r1, r2
183*fae6e9adSlinfeng                     div r1, r2
184*fae6e9adSlinfeng                     or r1, r2
185*fae6e9adSlinfeng                     and r1, r2
186*fae6e9adSlinfeng                     lsh r1, r2
187*fae6e9adSlinfeng                     rsh r1, r2
188*fae6e9adSlinfeng                     mod r1, r2
189*fae6e9adSlinfeng                     xor r1, r2
190*fae6e9adSlinfeng                     mov r1, r2
191*fae6e9adSlinfeng                     arsh r1, r2"),
192*fae6e9adSlinfeng         Ok(vec![
193*fae6e9adSlinfeng             insn(ebpf::ADD64_REG, 1, 2, 0, 0),
194*fae6e9adSlinfeng             insn(ebpf::SUB64_REG, 1, 2, 0, 0),
195*fae6e9adSlinfeng             insn(ebpf::MUL64_REG, 1, 2, 0, 0),
196*fae6e9adSlinfeng             insn(ebpf::DIV64_REG, 1, 2, 0, 0),
197*fae6e9adSlinfeng             insn(ebpf::OR64_REG, 1, 2, 0, 0),
198*fae6e9adSlinfeng             insn(ebpf::AND64_REG, 1, 2, 0, 0),
199*fae6e9adSlinfeng             insn(ebpf::LSH64_REG, 1, 2, 0, 0),
200*fae6e9adSlinfeng             insn(ebpf::RSH64_REG, 1, 2, 0, 0),
201*fae6e9adSlinfeng             insn(ebpf::MOD64_REG, 1, 2, 0, 0),
202*fae6e9adSlinfeng             insn(ebpf::XOR64_REG, 1, 2, 0, 0),
203*fae6e9adSlinfeng             insn(ebpf::MOV64_REG, 1, 2, 0, 0),
204*fae6e9adSlinfeng             insn(ebpf::ARSH64_REG, 1, 2, 0, 0)
205*fae6e9adSlinfeng         ])
206*fae6e9adSlinfeng     );
207*fae6e9adSlinfeng 
208*fae6e9adSlinfeng     assert_eq!(
209*fae6e9adSlinfeng         asm("add r1, 2
210*fae6e9adSlinfeng                     sub r1, 2
211*fae6e9adSlinfeng                     mul r1, 2
212*fae6e9adSlinfeng                     div r1, 2
213*fae6e9adSlinfeng                     or r1, 2
214*fae6e9adSlinfeng                     and r1, 2
215*fae6e9adSlinfeng                     lsh r1, 2
216*fae6e9adSlinfeng                     rsh r1, 2
217*fae6e9adSlinfeng                     mod r1, 2
218*fae6e9adSlinfeng                     xor r1, 2
219*fae6e9adSlinfeng                     mov r1, 2
220*fae6e9adSlinfeng                     arsh r1, 2"),
221*fae6e9adSlinfeng         Ok(vec![
222*fae6e9adSlinfeng             insn(ebpf::ADD64_IMM, 1, 0, 0, 2),
223*fae6e9adSlinfeng             insn(ebpf::SUB64_IMM, 1, 0, 0, 2),
224*fae6e9adSlinfeng             insn(ebpf::MUL64_IMM, 1, 0, 0, 2),
225*fae6e9adSlinfeng             insn(ebpf::DIV64_IMM, 1, 0, 0, 2),
226*fae6e9adSlinfeng             insn(ebpf::OR64_IMM, 1, 0, 0, 2),
227*fae6e9adSlinfeng             insn(ebpf::AND64_IMM, 1, 0, 0, 2),
228*fae6e9adSlinfeng             insn(ebpf::LSH64_IMM, 1, 0, 0, 2),
229*fae6e9adSlinfeng             insn(ebpf::RSH64_IMM, 1, 0, 0, 2),
230*fae6e9adSlinfeng             insn(ebpf::MOD64_IMM, 1, 0, 0, 2),
231*fae6e9adSlinfeng             insn(ebpf::XOR64_IMM, 1, 0, 0, 2),
232*fae6e9adSlinfeng             insn(ebpf::MOV64_IMM, 1, 0, 0, 2),
233*fae6e9adSlinfeng             insn(ebpf::ARSH64_IMM, 1, 0, 0, 2)
234*fae6e9adSlinfeng         ])
235*fae6e9adSlinfeng     );
236*fae6e9adSlinfeng 
237*fae6e9adSlinfeng     assert_eq!(
238*fae6e9adSlinfeng         asm("add64 r1, r2
239*fae6e9adSlinfeng                     sub64 r1, r2
240*fae6e9adSlinfeng                     mul64 r1, r2
241*fae6e9adSlinfeng                     div64 r1, r2
242*fae6e9adSlinfeng                     or64 r1, r2
243*fae6e9adSlinfeng                     and64 r1, r2
244*fae6e9adSlinfeng                     lsh64 r1, r2
245*fae6e9adSlinfeng                     rsh64 r1, r2
246*fae6e9adSlinfeng                     mod64 r1, r2
247*fae6e9adSlinfeng                     xor64 r1, r2
248*fae6e9adSlinfeng                     mov64 r1, r2
249*fae6e9adSlinfeng                     arsh64 r1, r2"),
250*fae6e9adSlinfeng         Ok(vec![
251*fae6e9adSlinfeng             insn(ebpf::ADD64_REG, 1, 2, 0, 0),
252*fae6e9adSlinfeng             insn(ebpf::SUB64_REG, 1, 2, 0, 0),
253*fae6e9adSlinfeng             insn(ebpf::MUL64_REG, 1, 2, 0, 0),
254*fae6e9adSlinfeng             insn(ebpf::DIV64_REG, 1, 2, 0, 0),
255*fae6e9adSlinfeng             insn(ebpf::OR64_REG, 1, 2, 0, 0),
256*fae6e9adSlinfeng             insn(ebpf::AND64_REG, 1, 2, 0, 0),
257*fae6e9adSlinfeng             insn(ebpf::LSH64_REG, 1, 2, 0, 0),
258*fae6e9adSlinfeng             insn(ebpf::RSH64_REG, 1, 2, 0, 0),
259*fae6e9adSlinfeng             insn(ebpf::MOD64_REG, 1, 2, 0, 0),
260*fae6e9adSlinfeng             insn(ebpf::XOR64_REG, 1, 2, 0, 0),
261*fae6e9adSlinfeng             insn(ebpf::MOV64_REG, 1, 2, 0, 0),
262*fae6e9adSlinfeng             insn(ebpf::ARSH64_REG, 1, 2, 0, 0)
263*fae6e9adSlinfeng         ])
264*fae6e9adSlinfeng     );
265*fae6e9adSlinfeng 
266*fae6e9adSlinfeng     assert_eq!(
267*fae6e9adSlinfeng         asm("add64 r1, 2
268*fae6e9adSlinfeng                     sub64 r1, 2
269*fae6e9adSlinfeng                     mul64 r1, 2
270*fae6e9adSlinfeng                     div64 r1, 2
271*fae6e9adSlinfeng                     or64 r1, 2
272*fae6e9adSlinfeng                     and64 r1, 2
273*fae6e9adSlinfeng                     lsh64 r1, 2
274*fae6e9adSlinfeng                     rsh64 r1, 2
275*fae6e9adSlinfeng                     mod64 r1, 2
276*fae6e9adSlinfeng                     xor64 r1, 2
277*fae6e9adSlinfeng                     mov64 r1, 2
278*fae6e9adSlinfeng                     arsh64 r1, 2"),
279*fae6e9adSlinfeng         Ok(vec![
280*fae6e9adSlinfeng             insn(ebpf::ADD64_IMM, 1, 0, 0, 2),
281*fae6e9adSlinfeng             insn(ebpf::SUB64_IMM, 1, 0, 0, 2),
282*fae6e9adSlinfeng             insn(ebpf::MUL64_IMM, 1, 0, 0, 2),
283*fae6e9adSlinfeng             insn(ebpf::DIV64_IMM, 1, 0, 0, 2),
284*fae6e9adSlinfeng             insn(ebpf::OR64_IMM, 1, 0, 0, 2),
285*fae6e9adSlinfeng             insn(ebpf::AND64_IMM, 1, 0, 0, 2),
286*fae6e9adSlinfeng             insn(ebpf::LSH64_IMM, 1, 0, 0, 2),
287*fae6e9adSlinfeng             insn(ebpf::RSH64_IMM, 1, 0, 0, 2),
288*fae6e9adSlinfeng             insn(ebpf::MOD64_IMM, 1, 0, 0, 2),
289*fae6e9adSlinfeng             insn(ebpf::XOR64_IMM, 1, 0, 0, 2),
290*fae6e9adSlinfeng             insn(ebpf::MOV64_IMM, 1, 0, 0, 2),
291*fae6e9adSlinfeng             insn(ebpf::ARSH64_IMM, 1, 0, 0, 2)
292*fae6e9adSlinfeng         ])
293*fae6e9adSlinfeng     );
294*fae6e9adSlinfeng 
295*fae6e9adSlinfeng     assert_eq!(
296*fae6e9adSlinfeng         asm("add32 r1, r2
297*fae6e9adSlinfeng                     sub32 r1, r2
298*fae6e9adSlinfeng                     mul32 r1, r2
299*fae6e9adSlinfeng                     div32 r1, r2
300*fae6e9adSlinfeng                     or32 r1, r2
301*fae6e9adSlinfeng                     and32 r1, r2
302*fae6e9adSlinfeng                     lsh32 r1, r2
303*fae6e9adSlinfeng                     rsh32 r1, r2
304*fae6e9adSlinfeng                     mod32 r1, r2
305*fae6e9adSlinfeng                     xor32 r1, r2
306*fae6e9adSlinfeng                     mov32 r1, r2
307*fae6e9adSlinfeng                     arsh32 r1, r2"),
308*fae6e9adSlinfeng         Ok(vec![
309*fae6e9adSlinfeng             insn(ebpf::ADD32_REG, 1, 2, 0, 0),
310*fae6e9adSlinfeng             insn(ebpf::SUB32_REG, 1, 2, 0, 0),
311*fae6e9adSlinfeng             insn(ebpf::MUL32_REG, 1, 2, 0, 0),
312*fae6e9adSlinfeng             insn(ebpf::DIV32_REG, 1, 2, 0, 0),
313*fae6e9adSlinfeng             insn(ebpf::OR32_REG, 1, 2, 0, 0),
314*fae6e9adSlinfeng             insn(ebpf::AND32_REG, 1, 2, 0, 0),
315*fae6e9adSlinfeng             insn(ebpf::LSH32_REG, 1, 2, 0, 0),
316*fae6e9adSlinfeng             insn(ebpf::RSH32_REG, 1, 2, 0, 0),
317*fae6e9adSlinfeng             insn(ebpf::MOD32_REG, 1, 2, 0, 0),
318*fae6e9adSlinfeng             insn(ebpf::XOR32_REG, 1, 2, 0, 0),
319*fae6e9adSlinfeng             insn(ebpf::MOV32_REG, 1, 2, 0, 0),
320*fae6e9adSlinfeng             insn(ebpf::ARSH32_REG, 1, 2, 0, 0)
321*fae6e9adSlinfeng         ])
322*fae6e9adSlinfeng     );
323*fae6e9adSlinfeng 
324*fae6e9adSlinfeng     assert_eq!(
325*fae6e9adSlinfeng         asm("add32 r1, 2
326*fae6e9adSlinfeng                     sub32 r1, 2
327*fae6e9adSlinfeng                     mul32 r1, 2
328*fae6e9adSlinfeng                     div32 r1, 2
329*fae6e9adSlinfeng                     or32 r1, 2
330*fae6e9adSlinfeng                     and32 r1, 2
331*fae6e9adSlinfeng                     lsh32 r1, 2
332*fae6e9adSlinfeng                     rsh32 r1, 2
333*fae6e9adSlinfeng                     mod32 r1, 2
334*fae6e9adSlinfeng                     xor32 r1, 2
335*fae6e9adSlinfeng                     mov32 r1, 2
336*fae6e9adSlinfeng                     arsh32 r1, 2"),
337*fae6e9adSlinfeng         Ok(vec![
338*fae6e9adSlinfeng             insn(ebpf::ADD32_IMM, 1, 0, 0, 2),
339*fae6e9adSlinfeng             insn(ebpf::SUB32_IMM, 1, 0, 0, 2),
340*fae6e9adSlinfeng             insn(ebpf::MUL32_IMM, 1, 0, 0, 2),
341*fae6e9adSlinfeng             insn(ebpf::DIV32_IMM, 1, 0, 0, 2),
342*fae6e9adSlinfeng             insn(ebpf::OR32_IMM, 1, 0, 0, 2),
343*fae6e9adSlinfeng             insn(ebpf::AND32_IMM, 1, 0, 0, 2),
344*fae6e9adSlinfeng             insn(ebpf::LSH32_IMM, 1, 0, 0, 2),
345*fae6e9adSlinfeng             insn(ebpf::RSH32_IMM, 1, 0, 0, 2),
346*fae6e9adSlinfeng             insn(ebpf::MOD32_IMM, 1, 0, 0, 2),
347*fae6e9adSlinfeng             insn(ebpf::XOR32_IMM, 1, 0, 0, 2),
348*fae6e9adSlinfeng             insn(ebpf::MOV32_IMM, 1, 0, 0, 2),
349*fae6e9adSlinfeng             insn(ebpf::ARSH32_IMM, 1, 0, 0, 2)
350*fae6e9adSlinfeng         ])
351*fae6e9adSlinfeng     );
352*fae6e9adSlinfeng }
353*fae6e9adSlinfeng 
354*fae6e9adSlinfeng // Test all supported AluUnary mnemonics.
355*fae6e9adSlinfeng #[test]
test_alu_unary()356*fae6e9adSlinfeng fn test_alu_unary() {
357*fae6e9adSlinfeng     assert_eq!(
358*fae6e9adSlinfeng         asm("neg r1
359*fae6e9adSlinfeng                     neg64 r1
360*fae6e9adSlinfeng                     neg32 r1"),
361*fae6e9adSlinfeng         Ok(vec![
362*fae6e9adSlinfeng             insn(ebpf::NEG64, 1, 0, 0, 0),
363*fae6e9adSlinfeng             insn(ebpf::NEG64, 1, 0, 0, 0),
364*fae6e9adSlinfeng             insn(ebpf::NEG32, 1, 0, 0, 0)
365*fae6e9adSlinfeng         ])
366*fae6e9adSlinfeng     );
367*fae6e9adSlinfeng }
368*fae6e9adSlinfeng 
369*fae6e9adSlinfeng // Test all supported LoadAbs mnemonics.
370*fae6e9adSlinfeng #[test]
test_load_abs()371*fae6e9adSlinfeng fn test_load_abs() {
372*fae6e9adSlinfeng     assert_eq!(
373*fae6e9adSlinfeng         asm("ldabsw 1
374*fae6e9adSlinfeng                     ldabsh 1
375*fae6e9adSlinfeng                     ldabsb 1
376*fae6e9adSlinfeng                     ldabsdw 1"),
377*fae6e9adSlinfeng         Ok(vec![
378*fae6e9adSlinfeng             insn(ebpf::LD_ABS_W, 0, 0, 0, 1),
379*fae6e9adSlinfeng             insn(ebpf::LD_ABS_H, 0, 0, 0, 1),
380*fae6e9adSlinfeng             insn(ebpf::LD_ABS_B, 0, 0, 0, 1),
381*fae6e9adSlinfeng             insn(ebpf::LD_ABS_DW, 0, 0, 0, 1)
382*fae6e9adSlinfeng         ])
383*fae6e9adSlinfeng     );
384*fae6e9adSlinfeng }
385*fae6e9adSlinfeng 
386*fae6e9adSlinfeng // Test all supported LoadInd mnemonics.
387*fae6e9adSlinfeng #[test]
test_load_ind()388*fae6e9adSlinfeng fn test_load_ind() {
389*fae6e9adSlinfeng     assert_eq!(
390*fae6e9adSlinfeng         asm("ldindw r1, 2
391*fae6e9adSlinfeng                     ldindh r1, 2
392*fae6e9adSlinfeng                     ldindb r1, 2
393*fae6e9adSlinfeng                     ldinddw r1, 2"),
394*fae6e9adSlinfeng         Ok(vec![
395*fae6e9adSlinfeng             insn(ebpf::LD_IND_W, 0, 1, 0, 2),
396*fae6e9adSlinfeng             insn(ebpf::LD_IND_H, 0, 1, 0, 2),
397*fae6e9adSlinfeng             insn(ebpf::LD_IND_B, 0, 1, 0, 2),
398*fae6e9adSlinfeng             insn(ebpf::LD_IND_DW, 0, 1, 0, 2)
399*fae6e9adSlinfeng         ])
400*fae6e9adSlinfeng     );
401*fae6e9adSlinfeng }
402*fae6e9adSlinfeng 
403*fae6e9adSlinfeng // Test all supported LoadReg mnemonics.
404*fae6e9adSlinfeng #[test]
test_load_reg()405*fae6e9adSlinfeng fn test_load_reg() {
406*fae6e9adSlinfeng     assert_eq!(
407*fae6e9adSlinfeng         asm("ldxw r1, [r2+3]
408*fae6e9adSlinfeng                     ldxh r1, [r2+3]
409*fae6e9adSlinfeng                     ldxb r1, [r2+3]
410*fae6e9adSlinfeng                     ldxdw r1, [r2+3]"),
411*fae6e9adSlinfeng         Ok(vec![
412*fae6e9adSlinfeng             insn(ebpf::LD_W_REG, 1, 2, 3, 0),
413*fae6e9adSlinfeng             insn(ebpf::LD_H_REG, 1, 2, 3, 0),
414*fae6e9adSlinfeng             insn(ebpf::LD_B_REG, 1, 2, 3, 0),
415*fae6e9adSlinfeng             insn(ebpf::LD_DW_REG, 1, 2, 3, 0)
416*fae6e9adSlinfeng         ])
417*fae6e9adSlinfeng     );
418*fae6e9adSlinfeng }
419*fae6e9adSlinfeng 
420*fae6e9adSlinfeng // Test all supported StoreImm mnemonics.
421*fae6e9adSlinfeng #[test]
test_store_imm()422*fae6e9adSlinfeng fn test_store_imm() {
423*fae6e9adSlinfeng     assert_eq!(
424*fae6e9adSlinfeng         asm("stw [r1+2], 3
425*fae6e9adSlinfeng                     sth [r1+2], 3
426*fae6e9adSlinfeng                     stb [r1+2], 3
427*fae6e9adSlinfeng                     stdw [r1+2], 3"),
428*fae6e9adSlinfeng         Ok(vec![
429*fae6e9adSlinfeng             insn(ebpf::ST_W_IMM, 1, 0, 2, 3),
430*fae6e9adSlinfeng             insn(ebpf::ST_H_IMM, 1, 0, 2, 3),
431*fae6e9adSlinfeng             insn(ebpf::ST_B_IMM, 1, 0, 2, 3),
432*fae6e9adSlinfeng             insn(ebpf::ST_DW_IMM, 1, 0, 2, 3)
433*fae6e9adSlinfeng         ])
434*fae6e9adSlinfeng     );
435*fae6e9adSlinfeng }
436*fae6e9adSlinfeng 
437*fae6e9adSlinfeng // Test all supported StoreReg mnemonics.
438*fae6e9adSlinfeng #[test]
test_store_reg()439*fae6e9adSlinfeng fn test_store_reg() {
440*fae6e9adSlinfeng     assert_eq!(
441*fae6e9adSlinfeng         asm("stxw [r1+2], r3
442*fae6e9adSlinfeng                     stxh [r1+2], r3
443*fae6e9adSlinfeng                     stxb [r1+2], r3
444*fae6e9adSlinfeng                     stxdw [r1+2], r3"),
445*fae6e9adSlinfeng         Ok(vec![
446*fae6e9adSlinfeng             insn(ebpf::ST_W_REG, 1, 3, 2, 0),
447*fae6e9adSlinfeng             insn(ebpf::ST_H_REG, 1, 3, 2, 0),
448*fae6e9adSlinfeng             insn(ebpf::ST_B_REG, 1, 3, 2, 0),
449*fae6e9adSlinfeng             insn(ebpf::ST_DW_REG, 1, 3, 2, 0)
450*fae6e9adSlinfeng         ])
451*fae6e9adSlinfeng     );
452*fae6e9adSlinfeng }
453*fae6e9adSlinfeng 
454*fae6e9adSlinfeng // Test all supported JumpConditional mnemonics.
455*fae6e9adSlinfeng #[test]
test_jump_conditional()456*fae6e9adSlinfeng fn test_jump_conditional() {
457*fae6e9adSlinfeng     assert_eq!(
458*fae6e9adSlinfeng         asm("jeq r1, r2, +3
459*fae6e9adSlinfeng                     jgt r1, r2, +3
460*fae6e9adSlinfeng                     jge r1, r2, +3
461*fae6e9adSlinfeng                     jlt r1, r2, +3
462*fae6e9adSlinfeng                     jle r1, r2, +3
463*fae6e9adSlinfeng                     jset r1, r2, +3
464*fae6e9adSlinfeng                     jne r1, r2, +3
465*fae6e9adSlinfeng                     jsgt r1, r2, +3
466*fae6e9adSlinfeng                     jsge r1, r2, +3
467*fae6e9adSlinfeng                     jslt r1, r2, +3
468*fae6e9adSlinfeng                     jsle r1, r2, +3"),
469*fae6e9adSlinfeng         Ok(vec![
470*fae6e9adSlinfeng             insn(ebpf::JEQ_REG, 1, 2, 3, 0),
471*fae6e9adSlinfeng             insn(ebpf::JGT_REG, 1, 2, 3, 0),
472*fae6e9adSlinfeng             insn(ebpf::JGE_REG, 1, 2, 3, 0),
473*fae6e9adSlinfeng             insn(ebpf::JLT_REG, 1, 2, 3, 0),
474*fae6e9adSlinfeng             insn(ebpf::JLE_REG, 1, 2, 3, 0),
475*fae6e9adSlinfeng             insn(ebpf::JSET_REG, 1, 2, 3, 0),
476*fae6e9adSlinfeng             insn(ebpf::JNE_REG, 1, 2, 3, 0),
477*fae6e9adSlinfeng             insn(ebpf::JSGT_REG, 1, 2, 3, 0),
478*fae6e9adSlinfeng             insn(ebpf::JSGE_REG, 1, 2, 3, 0),
479*fae6e9adSlinfeng             insn(ebpf::JSLT_REG, 1, 2, 3, 0),
480*fae6e9adSlinfeng             insn(ebpf::JSLE_REG, 1, 2, 3, 0)
481*fae6e9adSlinfeng         ])
482*fae6e9adSlinfeng     );
483*fae6e9adSlinfeng 
484*fae6e9adSlinfeng     assert_eq!(
485*fae6e9adSlinfeng         asm("jeq r1, 2, +3
486*fae6e9adSlinfeng                     jgt r1, 2, +3
487*fae6e9adSlinfeng                     jge r1, 2, +3
488*fae6e9adSlinfeng                     jlt r1, 2, +3
489*fae6e9adSlinfeng                     jle r1, 2, +3
490*fae6e9adSlinfeng                     jset r1, 2, +3
491*fae6e9adSlinfeng                     jne r1, 2, +3
492*fae6e9adSlinfeng                     jsgt r1, 2, +3
493*fae6e9adSlinfeng                     jsge r1, 2, +3
494*fae6e9adSlinfeng                     jslt r1, 2, +3
495*fae6e9adSlinfeng                     jsle r1, 2, +3"),
496*fae6e9adSlinfeng         Ok(vec![
497*fae6e9adSlinfeng             insn(ebpf::JEQ_IMM, 1, 0, 3, 2),
498*fae6e9adSlinfeng             insn(ebpf::JGT_IMM, 1, 0, 3, 2),
499*fae6e9adSlinfeng             insn(ebpf::JGE_IMM, 1, 0, 3, 2),
500*fae6e9adSlinfeng             insn(ebpf::JLT_IMM, 1, 0, 3, 2),
501*fae6e9adSlinfeng             insn(ebpf::JLE_IMM, 1, 0, 3, 2),
502*fae6e9adSlinfeng             insn(ebpf::JSET_IMM, 1, 0, 3, 2),
503*fae6e9adSlinfeng             insn(ebpf::JNE_IMM, 1, 0, 3, 2),
504*fae6e9adSlinfeng             insn(ebpf::JSGT_IMM, 1, 0, 3, 2),
505*fae6e9adSlinfeng             insn(ebpf::JSGE_IMM, 1, 0, 3, 2),
506*fae6e9adSlinfeng             insn(ebpf::JSLT_IMM, 1, 0, 3, 2),
507*fae6e9adSlinfeng             insn(ebpf::JSLE_IMM, 1, 0, 3, 2)
508*fae6e9adSlinfeng         ])
509*fae6e9adSlinfeng     );
510*fae6e9adSlinfeng 
511*fae6e9adSlinfeng     assert_eq!(
512*fae6e9adSlinfeng         asm("jeq32 r1, r2, +3
513*fae6e9adSlinfeng                     jgt32 r1, r2, +3
514*fae6e9adSlinfeng                     jge32 r1, r2, +3
515*fae6e9adSlinfeng                     jlt32 r1, r2, +3
516*fae6e9adSlinfeng                     jle32 r1, r2, +3
517*fae6e9adSlinfeng                     jset32 r1, r2, +3
518*fae6e9adSlinfeng                     jne32 r1, r2, +3
519*fae6e9adSlinfeng                     jsgt32 r1, r2, +3
520*fae6e9adSlinfeng                     jsge32 r1, r2, +3
521*fae6e9adSlinfeng                     jslt32 r1, r2, +3
522*fae6e9adSlinfeng                     jsle32 r1, r2, +3"),
523*fae6e9adSlinfeng         Ok(vec![
524*fae6e9adSlinfeng             insn(ebpf::JEQ_REG32, 1, 2, 3, 0),
525*fae6e9adSlinfeng             insn(ebpf::JGT_REG32, 1, 2, 3, 0),
526*fae6e9adSlinfeng             insn(ebpf::JGE_REG32, 1, 2, 3, 0),
527*fae6e9adSlinfeng             insn(ebpf::JLT_REG32, 1, 2, 3, 0),
528*fae6e9adSlinfeng             insn(ebpf::JLE_REG32, 1, 2, 3, 0),
529*fae6e9adSlinfeng             insn(ebpf::JSET_REG32, 1, 2, 3, 0),
530*fae6e9adSlinfeng             insn(ebpf::JNE_REG32, 1, 2, 3, 0),
531*fae6e9adSlinfeng             insn(ebpf::JSGT_REG32, 1, 2, 3, 0),
532*fae6e9adSlinfeng             insn(ebpf::JSGE_REG32, 1, 2, 3, 0),
533*fae6e9adSlinfeng             insn(ebpf::JSLT_REG32, 1, 2, 3, 0),
534*fae6e9adSlinfeng             insn(ebpf::JSLE_REG32, 1, 2, 3, 0)
535*fae6e9adSlinfeng         ])
536*fae6e9adSlinfeng     );
537*fae6e9adSlinfeng 
538*fae6e9adSlinfeng     assert_eq!(
539*fae6e9adSlinfeng         asm("jeq32 r1, 2, +3
540*fae6e9adSlinfeng                     jgt32 r1, 2, +3
541*fae6e9adSlinfeng                     jge32 r1, 2, +3
542*fae6e9adSlinfeng                     jlt32 r1, 2, +3
543*fae6e9adSlinfeng                     jle32 r1, 2, +3
544*fae6e9adSlinfeng                     jset32 r1, 2, +3
545*fae6e9adSlinfeng                     jne32 r1, 2, +3
546*fae6e9adSlinfeng                     jsgt32 r1, 2, +3
547*fae6e9adSlinfeng                     jsge32 r1, 2, +3
548*fae6e9adSlinfeng                     jslt32 r1, 2, +3
549*fae6e9adSlinfeng                     jsle32 r1, 2, +3"),
550*fae6e9adSlinfeng         Ok(vec![
551*fae6e9adSlinfeng             insn(ebpf::JEQ_IMM32, 1, 0, 3, 2),
552*fae6e9adSlinfeng             insn(ebpf::JGT_IMM32, 1, 0, 3, 2),
553*fae6e9adSlinfeng             insn(ebpf::JGE_IMM32, 1, 0, 3, 2),
554*fae6e9adSlinfeng             insn(ebpf::JLT_IMM32, 1, 0, 3, 2),
555*fae6e9adSlinfeng             insn(ebpf::JLE_IMM32, 1, 0, 3, 2),
556*fae6e9adSlinfeng             insn(ebpf::JSET_IMM32, 1, 0, 3, 2),
557*fae6e9adSlinfeng             insn(ebpf::JNE_IMM32, 1, 0, 3, 2),
558*fae6e9adSlinfeng             insn(ebpf::JSGT_IMM32, 1, 0, 3, 2),
559*fae6e9adSlinfeng             insn(ebpf::JSGE_IMM32, 1, 0, 3, 2),
560*fae6e9adSlinfeng             insn(ebpf::JSLT_IMM32, 1, 0, 3, 2),
561*fae6e9adSlinfeng             insn(ebpf::JSLE_IMM32, 1, 0, 3, 2)
562*fae6e9adSlinfeng         ])
563*fae6e9adSlinfeng     );
564*fae6e9adSlinfeng }
565*fae6e9adSlinfeng 
566*fae6e9adSlinfeng // Test all supported Endian mnemonics.
567*fae6e9adSlinfeng #[test]
test_endian()568*fae6e9adSlinfeng fn test_endian() {
569*fae6e9adSlinfeng     assert_eq!(
570*fae6e9adSlinfeng         asm("be16 r1
571*fae6e9adSlinfeng                     be32 r1
572*fae6e9adSlinfeng                     be64 r1
573*fae6e9adSlinfeng                     le16 r1
574*fae6e9adSlinfeng                     le32 r1
575*fae6e9adSlinfeng                     le64 r1"),
576*fae6e9adSlinfeng         Ok(vec![
577*fae6e9adSlinfeng             insn(ebpf::BE, 1, 0, 0, 16),
578*fae6e9adSlinfeng             insn(ebpf::BE, 1, 0, 0, 32),
579*fae6e9adSlinfeng             insn(ebpf::BE, 1, 0, 0, 64),
580*fae6e9adSlinfeng             insn(ebpf::LE, 1, 0, 0, 16),
581*fae6e9adSlinfeng             insn(ebpf::LE, 1, 0, 0, 32),
582*fae6e9adSlinfeng             insn(ebpf::LE, 1, 0, 0, 64)
583*fae6e9adSlinfeng         ])
584*fae6e9adSlinfeng     );
585*fae6e9adSlinfeng }
586*fae6e9adSlinfeng 
587*fae6e9adSlinfeng #[test]
test_large_immediate()588*fae6e9adSlinfeng fn test_large_immediate() {
589*fae6e9adSlinfeng     assert_eq!(
590*fae6e9adSlinfeng         asm("add64 r1, 2147483647"),
591*fae6e9adSlinfeng         Ok(vec![insn(ebpf::ADD64_IMM, 1, 0, 0, 2147483647)])
592*fae6e9adSlinfeng     );
593*fae6e9adSlinfeng     assert_eq!(
594*fae6e9adSlinfeng         asm("add64 r1, -2147483648"),
595*fae6e9adSlinfeng         Ok(vec![insn(ebpf::ADD64_IMM, 1, 0, 0, -2147483648)])
596*fae6e9adSlinfeng     );
597*fae6e9adSlinfeng }
598*fae6e9adSlinfeng 
599*fae6e9adSlinfeng #[test]
test_tcp_sack()600*fae6e9adSlinfeng fn test_tcp_sack() {
601*fae6e9adSlinfeng     assert_eq!(assemble(TCP_SACK_ASM), Ok(TCP_SACK_BIN.to_vec()));
602*fae6e9adSlinfeng }
603*fae6e9adSlinfeng 
604*fae6e9adSlinfeng #[test]
test_error_invalid_instruction()605*fae6e9adSlinfeng fn test_error_invalid_instruction() {
606*fae6e9adSlinfeng     assert_eq!(asm("abcd"), Err("Invalid instruction \"abcd\"".to_string()));
607*fae6e9adSlinfeng }
608*fae6e9adSlinfeng 
609*fae6e9adSlinfeng #[test]
test_error_unexpected_operands()610*fae6e9adSlinfeng fn test_error_unexpected_operands() {
611*fae6e9adSlinfeng     assert_eq!(
612*fae6e9adSlinfeng         asm("add 1, 2"),
613*fae6e9adSlinfeng         Err("Failed to encode add: Unexpected operands: [Integer(1), Integer(2)]".to_string())
614*fae6e9adSlinfeng     );
615*fae6e9adSlinfeng }
616*fae6e9adSlinfeng 
617*fae6e9adSlinfeng #[test]
test_error_too_many_operands()618*fae6e9adSlinfeng fn test_error_too_many_operands() {
619*fae6e9adSlinfeng     assert_eq!(
620*fae6e9adSlinfeng         asm("add 1, 2, 3, 4"),
621*fae6e9adSlinfeng         Err("Failed to encode add: Too many operands".to_string())
622*fae6e9adSlinfeng     );
623*fae6e9adSlinfeng }
624*fae6e9adSlinfeng 
625*fae6e9adSlinfeng #[test]
test_error_operands_out_of_range()626*fae6e9adSlinfeng fn test_error_operands_out_of_range() {
627*fae6e9adSlinfeng     assert_eq!(
628*fae6e9adSlinfeng         asm("add r16, r2"),
629*fae6e9adSlinfeng         Err("Failed to encode add: Invalid destination register 16".to_string())
630*fae6e9adSlinfeng     );
631*fae6e9adSlinfeng     assert_eq!(
632*fae6e9adSlinfeng         asm("add r1, r16"),
633*fae6e9adSlinfeng         Err("Failed to encode add: Invalid source register 16".to_string())
634*fae6e9adSlinfeng     );
635*fae6e9adSlinfeng     assert_eq!(
636*fae6e9adSlinfeng         asm("ja -32769"),
637*fae6e9adSlinfeng         Err("Failed to encode ja: Invalid offset -32769".to_string())
638*fae6e9adSlinfeng     );
639*fae6e9adSlinfeng     assert_eq!(
640*fae6e9adSlinfeng         asm("ja 32768"),
641*fae6e9adSlinfeng         Err("Failed to encode ja: Invalid offset 32768".to_string())
642*fae6e9adSlinfeng     );
643*fae6e9adSlinfeng     assert_eq!(
644*fae6e9adSlinfeng         asm("add r1, 4294967296"),
645*fae6e9adSlinfeng         Err("Failed to encode add: Invalid immediate 4294967296".to_string())
646*fae6e9adSlinfeng     );
647*fae6e9adSlinfeng     assert_eq!(
648*fae6e9adSlinfeng         asm("add r1, 2147483648"),
649*fae6e9adSlinfeng         Err("Failed to encode add: Invalid immediate 2147483648".to_string())
650*fae6e9adSlinfeng     );
651*fae6e9adSlinfeng     assert_eq!(
652*fae6e9adSlinfeng         asm("add r1, -2147483649"),
653*fae6e9adSlinfeng         Err("Failed to encode add: Invalid immediate -2147483649".to_string())
654*fae6e9adSlinfeng     );
655*fae6e9adSlinfeng }
656