xref: /linux/tools/testing/selftests/bpf/libarena/include/bpf_may_goto.h (revision 8c1e1c33fe5ad867bc0b6ba121911d70e7881d88)
1 #pragma once
2 
3 /*
4  * Note that cond_break can only be portably used in the body of a breakable
5  * construct, whereas can_loop can be used anywhere.
6  */
7 #ifdef __BPF_FEATURE_MAY_GOTO
8 #define can_loop					\
9 	({ __label__ l_break, l_continue;		\
10 	bool ret = true;				\
11 	asm volatile goto("may_goto %l[l_break]"	\
12 		      :::: l_break);			\
13 	goto l_continue;				\
14 	l_break: ret = false;				\
15 	l_continue:;					\
16 	ret;						\
17 	})
18 
19 #define __cond_break(expr)				\
20 	({ __label__ l_break, l_continue;		\
21 	asm volatile goto("may_goto %l[l_break]"	\
22 		      :::: l_break);			\
23 	goto l_continue;				\
24 	l_break: expr;					\
25 	l_continue:;					\
26 	})
27 #else
28 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
29 #define can_loop					\
30 	({ __label__ l_break, l_continue;		\
31 	bool ret = true;				\
32 	asm volatile goto("1:.byte 0xe5;		\
33 		      .byte 0;				\
34 		      .long ((%l[l_break] - 1b - 8) / 8) & 0xffff;	\
35 		      .short 0"				\
36 		      :::: l_break);			\
37 	goto l_continue;				\
38 	l_break: ret = false;				\
39 	l_continue:;					\
40 	ret;						\
41 	})
42 
43 #define __cond_break(expr)				\
44 	({ __label__ l_break, l_continue;		\
45 	asm volatile goto("1:.byte 0xe5;		\
46 		      .byte 0;				\
47 		      .long ((%l[l_break] - 1b - 8) / 8) & 0xffff;	\
48 		      .short 0"				\
49 		      :::: l_break);			\
50 	goto l_continue;				\
51 	l_break: expr;					\
52 	l_continue:;					\
53 	})
54 #else
55 #define can_loop					\
56 	({ __label__ l_break, l_continue;		\
57 	bool ret = true;				\
58 	asm volatile goto("1:.byte 0xe5;		\
59 		      .byte 0;				\
60 		      .long (((%l[l_break] - 1b - 8) / 8) & 0xffff) << 16;	\
61 		      .short 0"				\
62 		      :::: l_break);			\
63 	goto l_continue;				\
64 	l_break: ret = false;				\
65 	l_continue:;					\
66 	ret;						\
67 	})
68 
69 #define __cond_break(expr)				\
70 	({ __label__ l_break, l_continue;		\
71 	asm volatile goto("1:.byte 0xe5;		\
72 		      .byte 0;				\
73 		      .long (((%l[l_break] - 1b - 8) / 8) & 0xffff) << 16;	\
74 		      .short 0"				\
75 		      :::: l_break);			\
76 	goto l_continue;				\
77 	l_break: expr;					\
78 	l_continue:;					\
79 	})
80 #endif
81 #endif
82 
83 #define cond_break __cond_break(break)
84 #define cond_break_label(label) __cond_break(goto label)
85