Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(9)

Side by Side Diff: src/trusted/validator_ragel/decoding.h

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

Powered by Google App Engine
This is Rietveld 408576698