OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / net / bpf / vm_instructions.go
1 // Copyright 2016 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package bpf
6
7 import (
8         "encoding/binary"
9         "fmt"
10 )
11
12 func aluOpConstant(ins ALUOpConstant, regA uint32) uint32 {
13         return aluOpCommon(ins.Op, regA, ins.Val)
14 }
15
16 func aluOpX(ins ALUOpX, regA uint32, regX uint32) (uint32, bool) {
17         // Guard against division or modulus by zero by terminating
18         // the program, as the OS BPF VM does
19         if regX == 0 {
20                 switch ins.Op {
21                 case ALUOpDiv, ALUOpMod:
22                         return 0, false
23                 }
24         }
25
26         return aluOpCommon(ins.Op, regA, regX), true
27 }
28
29 func aluOpCommon(op ALUOp, regA uint32, value uint32) uint32 {
30         switch op {
31         case ALUOpAdd:
32                 return regA + value
33         case ALUOpSub:
34                 return regA - value
35         case ALUOpMul:
36                 return regA * value
37         case ALUOpDiv:
38                 // Division by zero not permitted by NewVM and aluOpX checks
39                 return regA / value
40         case ALUOpOr:
41                 return regA | value
42         case ALUOpAnd:
43                 return regA & value
44         case ALUOpShiftLeft:
45                 return regA << value
46         case ALUOpShiftRight:
47                 return regA >> value
48         case ALUOpMod:
49                 // Modulus by zero not permitted by NewVM and aluOpX checks
50                 return regA % value
51         case ALUOpXor:
52                 return regA ^ value
53         default:
54                 return regA
55         }
56 }
57
58 func jumpIf(ins JumpIf, value uint32) int {
59         var ok bool
60         inV := uint32(ins.Val)
61
62         switch ins.Cond {
63         case JumpEqual:
64                 ok = value == inV
65         case JumpNotEqual:
66                 ok = value != inV
67         case JumpGreaterThan:
68                 ok = value > inV
69         case JumpLessThan:
70                 ok = value < inV
71         case JumpGreaterOrEqual:
72                 ok = value >= inV
73         case JumpLessOrEqual:
74                 ok = value <= inV
75         case JumpBitsSet:
76                 ok = (value & inV) != 0
77         case JumpBitsNotSet:
78                 ok = (value & inV) == 0
79         }
80
81         if ok {
82                 return int(ins.SkipTrue)
83         }
84
85         return int(ins.SkipFalse)
86 }
87
88 func loadAbsolute(ins LoadAbsolute, in []byte) (uint32, bool) {
89         offset := int(ins.Off)
90         size := int(ins.Size)
91
92         return loadCommon(in, offset, size)
93 }
94
95 func loadConstant(ins LoadConstant, regA uint32, regX uint32) (uint32, uint32) {
96         switch ins.Dst {
97         case RegA:
98                 regA = ins.Val
99         case RegX:
100                 regX = ins.Val
101         }
102
103         return regA, regX
104 }
105
106 func loadExtension(ins LoadExtension, in []byte) uint32 {
107         switch ins.Num {
108         case ExtLen:
109                 return uint32(len(in))
110         default:
111                 panic(fmt.Sprintf("unimplemented extension: %d", ins.Num))
112         }
113 }
114
115 func loadIndirect(ins LoadIndirect, in []byte, regX uint32) (uint32, bool) {
116         offset := int(ins.Off) + int(regX)
117         size := int(ins.Size)
118
119         return loadCommon(in, offset, size)
120 }
121
122 func loadMemShift(ins LoadMemShift, in []byte) (uint32, bool) {
123         offset := int(ins.Off)
124
125         if !inBounds(len(in), offset, 0) {
126                 return 0, false
127         }
128
129         // Mask off high 4 bits and multiply low 4 bits by 4
130         return uint32(in[offset]&0x0f) * 4, true
131 }
132
133 func inBounds(inLen int, offset int, size int) bool {
134         return offset+size <= inLen
135 }
136
137 func loadCommon(in []byte, offset int, size int) (uint32, bool) {
138         if !inBounds(len(in), offset, size) {
139                 return 0, false
140         }
141
142         switch size {
143         case 1:
144                 return uint32(in[offset]), true
145         case 2:
146                 return uint32(binary.BigEndian.Uint16(in[offset : offset+size])), true
147         case 4:
148                 return uint32(binary.BigEndian.Uint32(in[offset : offset+size])), true
149         default:
150                 panic(fmt.Sprintf("invalid load size: %d", size))
151         }
152 }
153
154 func loadScratch(ins LoadScratch, regScratch [16]uint32, regA uint32, regX uint32) (uint32, uint32) {
155         switch ins.Dst {
156         case RegA:
157                 regA = regScratch[ins.N]
158         case RegX:
159                 regX = regScratch[ins.N]
160         }
161
162         return regA, regX
163 }
164
165 func storeScratch(ins StoreScratch, regScratch [16]uint32, regA uint32, regX uint32) [16]uint32 {
166         switch ins.Src {
167         case RegA:
168                 regScratch[ins.N] = regA
169         case RegX:
170                 regScratch[ins.N] = regX
171         }
172
173         return regScratch
174 }