bpf_jit.S 3.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
/*
 * BPF Jit compiler for s390, help functions.
 *
 * Copyright IBM Corp. 2012
 *
 * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
 */
#include <linux/linkage.h>

/*
 * Calling convention:
 * registers %r2, %r6-%r8, %r10-%r11, %r13, %r15 are call saved
 *   %r2: skb pointer
 *   %r3: offset parameter
 *   %r5: BPF A accumulator
 *   %r8: return address
 *   %r9: save register for skb pointer
 *   %r10: skb->data
 *   %r11: skb->len - skb->data_len (headlen)
 *   %r12: BPF X accumulator
 *
 * skb_copy_bits takes 4 parameters:
 *   %r2 = skb pointer
 *   %r3 = offset into skb data
 *   %r4 = length to copy
 *   %r5 = pointer to temp buffer
 */
#define SKBDATA	%r8

	/* A = *(u32 *) (skb->data+K+X) */
ENTRY(sk_load_word_ind)
	ar	%r3,%r12		# offset += X
	bmr	%r8			# < 0 -> return with cc

	/* A = *(u32 *) (skb->data+K) */
ENTRY(sk_load_word)
	llgfr	%r1,%r3			# extend offset
	ahi	%r3,4			# offset + 4
	clr	%r11,%r3		# hlen <= offset + 4 ?
	jl	sk_load_word_slow
	l	%r5,0(%r1,%r10)		# get word from skb
	xr	%r1,%r1			# set cc to zero
	br	%r8

sk_load_word_slow:
	lgr	%r9,%r2			# save %r2
	lhi	%r4,4			# 4 bytes
	la	%r5,160(%r15)		# pointer to temp buffer
	brasl	%r14,skb_copy_bits	# get data from skb
	l	%r5,160(%r15)		# load result from temp buffer
	ltgr	%r2,%r2			# set cc to (%r2 != 0)
	lgr	%r2,%r9			# restore %r2
	br	%r8

	/* A = *(u16 *) (skb->data+K+X) */
ENTRY(sk_load_half_ind)
	ar	%r3,%r12		# offset += X
	bmr	%r8			# < 0 -> return with cc

	/* A = *(u16 *) (skb->data+K) */
ENTRY(sk_load_half)
	llgfr	%r1,%r3			# extend offset
	ahi	%r3,2			# offset + 2
	clr	%r11,%r3		# hlen <= offset + 2 ?
	jl	sk_load_half_slow
	llgh	%r5,0(%r1,%r10)		# get half from skb
	xr	%r1,%r1			# set cc to zero
	br	%r8

sk_load_half_slow:
	lgr	%r9,%r2			# save %r2
	lhi	%r4,2			# 2 bytes
	la	%r5,162(%r15)		# pointer to temp buffer
	brasl	%r14,skb_copy_bits	# get data from skb
	xc	160(2,%r15),160(%r15)
	l	%r5,160(%r15)		# load result from temp buffer
	ltgr	%r2,%r2			# set cc to (%r2 != 0)
	lgr	%r2,%r9			# restore %r2
	br	%r8

	/* A = *(u8 *) (skb->data+K+X) */
ENTRY(sk_load_byte_ind)
	ar	%r3,%r12		# offset += X
	bmr	%r8			# < 0 -> return with cc

	/* A = *(u8 *) (skb->data+K) */
ENTRY(sk_load_byte)
	llgfr	%r1,%r3			# extend offset
	clr	%r11,%r3		# hlen < offset ?
	jle	sk_load_byte_slow
	lhi	%r5,0
	ic	%r5,0(%r1,%r10)		# get byte from skb
	xr	%r1,%r1			# set cc to zero
	br	%r8

sk_load_byte_slow:
	lgr	%r9,%r2			# save %r2
	lhi	%r4,1			# 1 bytes
	la	%r5,163(%r15)		# pointer to temp buffer
	brasl	%r14,skb_copy_bits	# get data from skb
	xc	160(3,%r15),160(%r15)
	l	%r5,160(%r15)		# load result from temp buffer
	ltgr	%r2,%r2			# set cc to (%r2 != 0)
	lgr	%r2,%r9			# restore %r2
	br	%r8

	/* A = (*(u8 *)(skb->data+K) & 0xf) << 2 */
ENTRY(sk_load_byte_msh)
	llgfr	%r1,%r3			# extend offset
	clr	%r11,%r3		# hlen < offset ?
	jle	sk_load_byte_slow
	lhi	%r12,0
	ic	%r12,0(%r1,%r10)	# get byte from skb
	nill	%r12,0x0f
	sll	%r12,2
	xr	%r1,%r1			# set cc to zero
	br	%r8

sk_load_byte_msh_slow:
	lgr	%r9,%r2			# save %r2
	lhi	%r4,2			# 2 bytes
	la	%r5,162(%r15)		# pointer to temp buffer
	brasl	%r14,skb_copy_bits	# get data from skb
	xc	160(3,%r15),160(%r15)
	l	%r12,160(%r15)		# load result from temp buffer
	nill	%r12,0x0f
	sll	%r12,2
	ltgr	%r2,%r2			# set cc to (%r2 != 0)
	lgr	%r2,%r9			# restore %r2
	br	%r8