Martin Schwidefsky | c10302e | 2012-07-31 16:23:59 +0200 | [diff] [blame] | 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) */ |
| 31 | ENTRY(sk_load_word_ind) |
| 32 | ar %r3,%r12 # offset += X |
| 33 | bmr %r8 # < 0 -> return with cc |
| 34 | |
| 35 | /* A = *(u32 *) (skb->data+K) */ |
| 36 | ENTRY(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 | |
| 45 | sk_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) */ |
| 56 | ENTRY(sk_load_half_ind) |
| 57 | ar %r3,%r12 # offset += X |
| 58 | bmr %r8 # < 0 -> return with cc |
| 59 | |
| 60 | /* A = *(u16 *) (skb->data+K) */ |
| 61 | ENTRY(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 | |
| 70 | sk_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) */ |
| 82 | ENTRY(sk_load_byte_ind) |
| 83 | ar %r3,%r12 # offset += X |
| 84 | bmr %r8 # < 0 -> return with cc |
| 85 | |
| 86 | /* A = *(u8 *) (skb->data+K) */ |
| 87 | ENTRY(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 | |
| 96 | sk_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 */ |
| 108 | ENTRY(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 | |
| 119 | sk_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 |