2 * Copyright 2008, Google Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
15 * * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 * ncdecode.h - table driven decoder for Native Client.
35 * This header file contains type declarations and constants
36 * used by the decoder input table
38 #ifndef __NCDECODE_H__
39 #define __NCDECODE_H__
40 #include "native_client/include/portability.h"
42 struct NCDecoderState
;
43 struct NCValidatorState
;
44 /* Function type for a decoder action */
45 typedef void (*NCDecoderAction
)(const struct NCDecoderState
*mstate
);
46 typedef void (*NCDecoderStats
)(struct NCValidatorState
*vstate
);
48 /* Using a bit mask here. Hopefully nobody will be offended.
49 * Prefix usage: 0x2e and 0x3e are used as branch prediction hints
50 * 0x64 and 0x65 needed for TLS
51 * 0x26 and 0x36 shouldn't be needed
52 * These are #defines, not const ints, because they are used
53 * for array initialization
55 #define kPrefixSEGCS 0x0001 /* 0x2e */
56 #define kPrefixSEGSS 0x0002 /* 0x36 */
57 #define kPrefixSEGFS 0x0004 /* 0x64 */
58 #define kPrefixSEGGS 0x0008 /* 0x65 */
59 #define kPrefixDATA16 0x0010 /* 0x66 - OKAY */
60 #define kPrefixADDR16 0x0020 /* 0x67 - disallowed */
61 #define kPrefixREPNE 0x0040 /* 0xf2 - OKAY */
62 #define kPrefixREP 0x0080 /* 0xf3 - OKAY */
63 #define kPrefixLOCK 0x0100 /* 0xf0 - OKAY */
64 #define kPrefixSEGES 0x0200 /* 0x26 - disallowed */
65 #define kPrefixSEGDS 0x0400 /* 0x3e - disallowed */
67 /* a new enumerated type for instructions */
69 NACLi_UNDEFINED
=0, /* uninitialized space; should never happen */
70 NACLi_ILLEGAL
, /* not allowed in NaCl */
71 NACLi_INVALID
, /* not valid on any known x86 */
72 NACLi_SYSTEM
, /* ring-0 instruction, not allowed in NaCl */
73 NACLi_386
, /* an allowed instruction on all i386 implementations */
74 NACLi_386L
, /* subset of i386 that allows LOCK prefix */
75 NACLi_386R
, /* subset of i386 that allow REP prefix */
76 NACLi_386RE
, /* subset of i386 that allow REPE/REPZ prefixes */
84 NACLi_CMPXCHG16B
, /* 64-bit mode only, illegal for NaCl */
88 NACLi_RDTSCP
, /* AMD only */
89 NACLi_SYSCALL
, /* AMD only; equivalent to SYSENTER */
93 NACLi_MMXSSE2
, /* MMX with no prefix, SSE2 with 0x66 prefix */
94 NACLi_3DNOW
, /* AMD only */
95 NACLi_EMMX
, /* Cyrix only; not supported yet */
96 NACLi_E3DNOW
, /* AMD only */
98 NACLi_SSE2
, /* no prefix => MMX; prefix 66 => SSE; */
99 /* f2, f3 not allowed unless used for opcode selection */
100 NACLi_SSE2x
, /* SSE2; prefix 66 required!!! */
102 NACLi_SSE4A
, /* AMD only */
108 NACLi_LONGMODE
,/* AMD only? */
109 NACLi_SVM
, /* AMD only */
113 /* NOTE: This enum must be kept consistent with kNaClInstTypeRange */
114 /* (defined below) and with the string constants in ncdecode_table.c */
116 #define kNaClInstTypeRange 43
117 #ifdef NEEDSNACLINSTTYPESTRING
118 static const char *kNaClInstTypeString
[kNaClInstTypeRange
] = {
163 #define NaClInstTypeString(itype) (kNaClInstTypeString[itype])
164 #endif /* ifdef NEEDSNACLINSTTYPESTRING */
172 /* these comments facilitate counting */
178 /* these comments facilitate counting */
184 /* these comments facilitate counting */
191 /* kModRMOpcodeGroups doesn't work as a const int since it is used */
192 /* as an array dimension */
193 #define kNaClMRMGroupsRange 20
194 #define kModRMOpcodeGroupSize 8
196 /* information derived from the opcode, wherever it happens to be */
209 /* Don't add to this enum without update kNCDecodeImmediateTypeRange */
210 /* and updating the tables below which are sized using this constant */
211 } NCDecodeImmediateType
;
212 #define kNCDecodeImmediateTypeRange 11
214 /* 255 will force an error */
215 static const uint8_t kImmTypeToSize66
[kNCDecodeImmediateTypeRange
] =
216 { 0, 0, 1, 2, 3, 4, 2, 4, 0, 0, 6 };
217 static const uint8_t kImmTypeToSize67
[kNCDecodeImmediateTypeRange
] =
218 { 0, 0, 1, 2, 3, 4, 4, 2, 0, 0, 4 };
219 static const uint8_t kImmTypeToSize
[kNCDecodeImmediateTypeRange
] =
220 { 0, 0, 1, 2, 3, 4, 4, 4, 0, 0, 6 };
222 #define NCDTABLESIZE 256
224 NaClInstType insttype
;
225 uint8_t hasmrmbyte
; /* 1 if this inst has an mrm byte, else 0 */
226 uint8_t immtype
; /* IMM_NONE, IMM_FIXED1, etc. */
227 uint8_t opinmrm
; /* set to 1..8 if you must find opcode in MRM byte */
233 uint8_t prefixbytes
; /* 0..4 */
244 struct NCDecoderState
{
247 uint8_t dbindex
; /* index into decodebuffer */
249 const struct OpInfo
*opinfo
;
250 struct InstInfo inst
;
251 struct NCValidatorState
*vstate
;
252 /* The decodebuffer is an array of size kDecodeBufferSize */
253 /* of NCDecoderState records, used to allow the validator */
254 /* to inspect a small number of previous instructions. */
255 /* It is allocated on the stack to make it thread-local, */
256 /* and included here for use by PreviousInst(). */
257 struct NCDecoderState
*decodebuffer
;
260 /* We track machine state in a three-entry circular buffer,
261 * allowing us to see the two previous instructions and to
262 * check the safe call sequence. I rounded up to a power of
263 * four so we can use a mask, even though we only need to
264 * remember three instructions.
265 * This is #defined rather than const int because it is used
266 * as an array dimension
268 #define kDecodeBufferSize 4
269 static const int kTwoByteOpcodeByte1
= 0x0f;
270 static const int k3DNowOpcodeByte2
= 0x0f;
271 static const int kMaxPrefixBytes
= 4;
273 /* Some essential non-macros... */
274 static INLINE
uint8_t modrm_mod(uint8_t modrm
) { return ((modrm
>> 6) & 0x03);}
275 static INLINE
uint8_t modrm_rm(uint8_t modrm
) { return (modrm
& 0x07); }
276 static INLINE
uint8_t modrm_reg(uint8_t modrm
) { return ((modrm
>> 3) & 0x07); }
277 static INLINE
uint8_t modrm_opcode(uint8_t modrm
) { return modrm_reg(modrm
); }
278 static INLINE
uint8_t sib_ss(uint8_t sib
) { return ((sib
>> 6) & 0x03); }
279 static INLINE
uint8_t sib_index(uint8_t sib
) { return ((sib
>> 3) & 0x07); }
280 static INLINE
uint8_t sib_base(uint8_t sib
) { return (sib
& 0x07); }
282 extern void NCDecodeRegisterCallbacks(NCDecoderAction decoderaction
,
283 NCDecoderStats newsegment
,
284 NCDecoderStats segmentationerror
,
285 NCDecoderStats internalerror
);
287 extern void NCDecodeSegment(uint8_t *mbase
, uint32_t vbase
, size_t sz
,
288 struct NCValidatorState
*vstate
);
290 extern struct NCDecoderState
*PreviousInst(const struct NCDecoderState
*mstate
,
293 #endif /* __NCDECODE_H__ */