1/*
2 * BPF Jit compiler for s390, help functions.
3 *
4 * Copyright IBM Corp. 2012
5 *
6 * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
7 */
8#include <linux/linkage.h>
9
10/*
11 * Calling convention:
12 * registers %r2, %r6-%r8, %r10-%r11, %r13, %r15 are call saved
13 *   %r2: skb pointer
14 *   %r3: offset parameter
15 *   %r5: BPF A accumulator
16 *   %r8: return address
17 *   %r9: save register for skb pointer
18 *   %r10: skb->data
19 *   %r11: skb->len - skb->data_len (headlen)
20 *   %r12: BPF X accumulator
21 *
22 * skb_copy_bits takes 4 parameters:
23 *   %r2 = skb pointer
24 *   %r3 = offset into skb data
25 *   %r4 = length to copy
26 *   %r5 = pointer to temp buffer
27 */
28#define SKBDATA	%r8
29
30	/* A = *(u32 *) (skb->data+K+X) */
31ENTRY(sk_load_word_ind)
32	ar	%r3,%r12		# offset += X
33	bmr	%r8			# < 0 -> return with cc
34
35	/* A = *(u32 *) (skb->data+K) */
36ENTRY(sk_load_word)
37	llgfr	%r1,%r3			# extend offset
38	ahi	%r3,4			# offset + 4
39	clr	%r11,%r3		# hlen <= offset + 4 ?
40	jl	sk_load_word_slow
41	l	%r5,0(%r1,%r10)		# get word from skb
42	xr	%r1,%r1			# set cc to zero
43	br	%r8
44
45sk_load_word_slow:
46	lgr	%r9,%r2			# save %r2
47	lhi	%r4,4			# 4 bytes
48	la	%r5,160(%r15)		# pointer to temp buffer
49	brasl	%r14,skb_copy_bits	# get data from skb
50	l	%r5,160(%r15)		# load result from temp buffer
51	ltgr	%r2,%r2			# set cc to (%r2 != 0)
52	lgr	%r2,%r9			# restore %r2
53	br	%r8
54
55	/* A = *(u16 *) (skb->data+K+X) */
56ENTRY(sk_load_half_ind)
57	ar	%r3,%r12		# offset += X
58	bmr	%r8			# < 0 -> return with cc
59
60	/* A = *(u16 *) (skb->data+K) */
61ENTRY(sk_load_half)
62	llgfr	%r1,%r3			# extend offset
63	ahi	%r3,2			# offset + 2
64	clr	%r11,%r3		# hlen <= offset + 2 ?
65	jl	sk_load_half_slow
66	llgh	%r5,0(%r1,%r10)		# get half from skb
67	xr	%r1,%r1			# set cc to zero
68	br	%r8
69
70sk_load_half_slow:
71	lgr	%r9,%r2			# save %r2
72	lhi	%r4,2			# 2 bytes
73	la	%r5,162(%r15)		# pointer to temp buffer
74	brasl	%r14,skb_copy_bits	# get data from skb
75	xc	160(2,%r15),160(%r15)
76	l	%r5,160(%r15)		# load result from temp buffer
77	ltgr	%r2,%r2			# set cc to (%r2 != 0)
78	lgr	%r2,%r9			# restore %r2
79	br	%r8
80
81	/* A = *(u8 *) (skb->data+K+X) */
82ENTRY(sk_load_byte_ind)
83	ar	%r3,%r12		# offset += X
84	bmr	%r8			# < 0 -> return with cc
85
86	/* A = *(u8 *) (skb->data+K) */
87ENTRY(sk_load_byte)
88	llgfr	%r1,%r3			# extend offset
89	clr	%r11,%r3		# hlen < offset ?
90	jle	sk_load_byte_slow
91	lhi	%r5,0
92	ic	%r5,0(%r1,%r10)		# get byte from skb
93	xr	%r1,%r1			# set cc to zero
94	br	%r8
95
96sk_load_byte_slow:
97	lgr	%r9,%r2			# save %r2
98	lhi	%r4,1			# 1 bytes
99	la	%r5,163(%r15)		# pointer to temp buffer
100	brasl	%r14,skb_copy_bits	# get data from skb
101	xc	160(3,%r15),160(%r15)
102	l	%r5,160(%r15)		# load result from temp buffer
103	ltgr	%r2,%r2			# set cc to (%r2 != 0)
104	lgr	%r2,%r9			# restore %r2
105	br	%r8
106
107	/* A = (*(u8 *)(skb->data+K) & 0xf) << 2 */
108ENTRY(sk_load_byte_msh)
109	llgfr	%r1,%r3			# extend offset
110	clr	%r11,%r3		# hlen < offset ?
111	jle	sk_load_byte_slow
112	lhi	%r12,0
113	ic	%r12,0(%r1,%r10)	# get byte from skb
114	nill	%r12,0x0f
115	sll	%r12,2
116	xr	%r1,%r1			# set cc to zero
117	br	%r8
118
119sk_load_byte_msh_slow:
120	lgr	%r9,%r2			# save %r2
121	lhi	%r4,2			# 2 bytes
122	la	%r5,162(%r15)		# pointer to temp buffer
123	brasl	%r14,skb_copy_bits	# get data from skb
124	xc	160(3,%r15),160(%r15)
125	l	%r12,160(%r15)		# load result from temp buffer
126	nill	%r12,0x0f
127	sll	%r12,2
128	ltgr	%r2,%r2			# set cc to (%r2 != 0)
129	lgr	%r2,%r9			# restore %r2
130	br	%r8
131