OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. | |
3 * Use of this source code is governed by a BSD-style license that can be | |
4 * found in the LICENSE file. | |
5 */ | |
6 | |
7 /* | |
8 * This file contains common parts of x86-32 and x86-64 internals (inline | |
9 * functions and defines). | |
10 * | |
11 * We only include simple schematic diagrams here. For full description see | |
12 * AMD/Intel manuals. | |
13 */ | |
14 | |
15 #ifndef NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_RAGEL_DECODING_H_ | |
16 #define NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_RAGEL_DECODING_H_ | |
17 | |
18 #include "native_client/src/trusted/validator_ragel/decoder.h" | |
19 | |
20 #if NACL_WINDOWS | |
21 # define FORCEINLINE __forceinline | |
22 #else | |
23 # define FORCEINLINE __inline __attribute__ ((always_inline)) | |
24 #endif | |
25 | |
26 | |
27 /* | |
28 * Opcode with register number embedded: | |
29 * | |
30 * 7 6 5 4 3 2 1 0 | |
31 * ┌───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┒ | |
32 * │ Opcode │ register number ┃ | |
33 * ┕━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┛ | |
34 */ | |
35 static FORCEINLINE uint8_t RegFromOpcode(uint8_t modrm) { | |
36 return modrm & 0x07; | |
37 } | |
38 | |
39 /* | |
40 * ModRM byte format: | |
41 * | |
42 * 7 6 5 4 3 2 1 0 | |
43 * ┌───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┒ | |
44 * │ mod │ reg │ r/m ┃ | |
45 * ┕━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┛ | |
46 */ | |
47 static FORCEINLINE uint8_t ModFromModRM(uint8_t modrm) { | |
48 return modrm >> 6; | |
49 } | |
50 | |
51 static FORCEINLINE uint8_t RegFromModRM(uint8_t modrm) { | |
52 return (modrm & 0x38) >> 3; | |
53 } | |
54 | |
55 static FORCEINLINE uint8_t RMFromModRM(uint8_t modrm) { | |
56 return modrm & 0x07; | |
57 } | |
58 | |
59 /* | |
60 * SIB byte format: | |
61 * | |
62 * 7 6 5 4 3 2 1 0 | |
63 * ┌───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┒ | |
64 * │ scale │ index │ base ┃ | |
65 * ┕━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┛ | |
66 */ | |
67 static FORCEINLINE uint8_t ScaleFromSIB(uint8_t sib) { | |
68 return sib >> 6; | |
69 } | |
70 | |
71 static FORCEINLINE uint8_t IndexFromSIB(uint8_t sib) { | |
72 return (sib & 0x38) >> 3; | |
73 } | |
74 | |
75 static FORCEINLINE uint8_t BaseFromSIB(uint8_t sib) { | |
76 return sib & 0x07; | |
77 } | |
78 | |
79 /* | |
80 * REX byte format: | |
81 * | |
82 * 7 6 5 4 3 2 1 0 | |
83 * ┌───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┒ | |
84 * │ 0 │ 1 │ 0 │ 0 │ W │ R │ X │ B ┃ | |
85 * ┕━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┛ | |
86 */ | |
87 | |
88 enum { | |
89 REX_B = 1, | |
90 REX_X = 2, | |
91 REX_R = 4, | |
92 REX_W = 8 | |
93 }; | |
94 | |
95 static FORCEINLINE uint8_t BaseExtentionFromREX(uint8_t rex) { | |
96 return (rex & REX_B) << 3; | |
97 } | |
98 | |
99 static FORCEINLINE uint8_t IndexExtentionFromREX(uint8_t rex) { | |
100 return (rex & REX_X) << 2; | |
101 } | |
102 | |
103 static FORCEINLINE uint8_t RegisterExtentionFromREX(uint8_t rex) { | |
104 return (rex & REX_R) << 1; | |
105 } | |
106 | |
107 /* | |
108 * VEX 2nd byte format: | |
109 * | |
110 * 7 6 5 4 3 2 1 0 | |
111 * ┌───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┒ | |
112 * │ ¬R │ ¬X │ ¬B │ opcode map selector ┃ | |
113 * ┕━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┛ | |
114 */ | |
115 | |
116 enum { | |
117 VEX_MAP1 = 0x01, | |
118 VEX_MAP2 = 0x02, | |
119 VEX_MAP3 = 0x03, | |
120 VEX_MAP8 = 0x08, | |
121 VEX_MAP9 = 0x09, | |
122 VEX_MAPA = 0x0a, | |
123 VEX_B = 0x20, | |
124 VEX_X = 0x40, | |
125 VEX_R = 0x80, | |
126 VEX_W = 0x80 | |
127 }; | |
128 | |
129 static FORCEINLINE uint8_t BaseExtentionFromVEX(uint8_t vex2) { | |
130 return ((~vex2) & VEX_B) >> 2; | |
131 } | |
132 | |
133 static FORCEINLINE uint8_t IndexExtentionFromVEX(uint8_t vex2) { | |
134 return ((~vex2) & VEX_X) >> 3; | |
135 } | |
136 | |
137 static FORCEINLINE uint8_t RegisterExtentionFromVEX(uint8_t vex2) { | |
138 return ((~vex2) & VEX_R) >> 4; | |
139 } | |
140 | |
141 /* | |
142 * VEX 3rd byte format: | |
143 * | |
144 * 7 6 5 4 3 2 1 0 | |
145 * ┌───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┒ | |
146 * │ W │ ¬vvvv (register number) │ L │ pp ┃ | |
147 * ┕━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┛ | |
148 */ | |
149 | |
150 static FORCEINLINE uint8_t GetOperandFromVexIA32(uint8_t vex3) { | |
151 return ((~vex3) & 0x38) >> 3; | |
152 } | |
153 | |
154 static FORCEINLINE uint8_t GetOperandFromVexAMD64(uint8_t vex3) { | |
155 return ((~vex3) & 0x78) >> 3; | |
156 } | |
157 | |
158 /* | |
159 * is4 byte format: | |
160 * | |
161 * 7 6 5 4 3 2 1 0 | |
162 * ┌───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┒ | |
163 * │ vvvv (register number) │ 0 │ 0 │ imm2 or zero ┃ | |
164 * ┕━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┛ | |
165 */ | |
166 static FORCEINLINE uint8_t RegisterFromIS4(uint8_t is4) { | |
167 return is4 >> 4; | |
168 } | |
169 | |
170 /* | |
171 * SignExtendXXBit is used to sign-extend XX-bit value to unsigned 64-bit value. | |
172 * | |
173 * To do that you need to pass unsigned value of smaller then 64-bit size | |
174 * to this function: it will be converted to signed value and then | |
175 * sign-extended to become 64-bit value. | |
176 * | |
177 * Smaller values can be obtained by restricting this value further (which is | |
178 * safe according to the C language specification: see 6.2.1.2 in C90 and | |
179 * 6.3.1.3.2 in C99 specification). | |
180 * | |
181 * Note that these operations are safe but slightly unusual: they come very | |
182 * close to the edge of what "well-behaved C program is not supposed to do", | |
183 * but they stay on the "safe" side of this boundary. Specifically: this | |
184 * behavior triggers "implementation-defined behavior" (see 6.2.1.2 in C90 | |
185 * specification and 6.3.1.3.3 in C99 specification) which sounds suspiciously | |
186 * similar to the dreaded "undefined behavior", but in reality these two are | |
187 * quite different: any program which triggers "undefined behavior" is not a | |
188 * valid C program at all, but program which triggers "implementation-defined | |
189 * behavior" is quite valid C program. What this program actually *does* | |
190 * depends on the specification of a given C compiler: each particular | |
191 * implementation must decide for itself what it'll do in this particular case | |
192 * and *stick* *to* *it*. If the implementation uses two's-complement negative | |
193 * numbers (and all the implementation which can compile this code *must* | |
194 * support two's-complement arythmetic - see 7.18.1.1 in C99 specification) then | |
195 * the easiest thing to do is to do what we need here - this is what all known | |
196 * compilers for all known platforms are actually doing. | |
197 */ | |
198 static FORCEINLINE uint64_t SignExtend8Bit(uint64_t value) { | |
199 return (int8_t)value; | |
200 } | |
201 | |
202 static FORCEINLINE uint64_t SignExtend16Bit(uint64_t value) { | |
203 return (int16_t)value; | |
204 } | |
205 | |
206 static FORCEINLINE uint64_t SignExtend32Bit(uint64_t value) { | |
207 return (int32_t)value; | |
208 } | |
209 | |
210 static FORCEINLINE uint64_t AnyFieldValue8bit(const uint8_t *start) { | |
211 return *start; | |
212 } | |
213 | |
214 static FORCEINLINE uint64_t AnyFieldValue16bit(const uint8_t *start) { | |
215 return (start[0] + 256U * start[1]); | |
216 } | |
217 | |
218 static FORCEINLINE uint64_t AnyFieldValue32bit(const uint8_t *start) { | |
219 return (start[0] + 256U * (start[1] + 256U * (start[2] + 256U * (start[3])))); | |
220 } | |
221 static FORCEINLINE uint64_t AnyFieldValue64bit(const uint8_t *start) { | |
222 return (*start + 256ULL * (start[1] + 256ULL * (start[2] + 256ULL * | |
223 (start[3] + 256ULL * (start[4] + 256ULL * (start[5] + 256ULL * | |
224 (start[6] + 256ULL * start[7]))))))); | |
225 } | |
226 | |
227 static const uint8_t index_registers[] = { | |
228 /* Note how REG_RIZ falls out of the pattern. */ | |
229 REG_RAX, REG_RCX, REG_RDX, REG_RBX, | |
230 REG_RIZ, REG_RBP, REG_RSI, REG_RDI, | |
231 REG_R8, REG_R9, REG_R10, REG_R11, | |
232 REG_R12, REG_R13, REG_R14, REG_R15 | |
233 }; | |
234 | |
235 #endif /* NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_RAGEL_DECODING_H_ */ | |
OLD | NEW |