VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMAll/IEMAllInstructionsPython.py@ 67042

Last change on this file since 67042 was 67042, checked in by vboxsync, 8 years ago

IEM: Implemented (but not tested) vmovntdqa Vx,Mx (VEX.66.0F38 2a mod!=3).

  • Property svn:eol-style set to LF
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 147.0 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# $Id: IEMAllInstructionsPython.py 67042 2017-05-23 13:44:16Z vboxsync $
4
5"""
6IEM instruction extractor.
7
8This script/module parses the IEMAllInstruction*.cpp.h files next to it and
9collects information about the instructions. It can then be used to generate
10disassembler tables and tests.
11"""
12
13__copyright__ = \
14"""
15Copyright (C) 2017 Oracle Corporation
16
17This file is part of VirtualBox Open Source Edition (OSE), as
18available from http://www.virtualbox.org. This file is free software;
19you can redistribute it and/or modify it under the terms of the GNU
20General Public License (GPL) as published by the Free Software
21Foundation, in version 2 as it comes in the "COPYING" file of the
22VirtualBox OSE distribution. VirtualBox OSE is distributed in the
23hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
24
25The contents of this file may alternatively be used under the terms
26of the Common Development and Distribution License Version 1.0
27(CDDL) only, as it comes in the "COPYING.CDDL" file of the
28VirtualBox OSE distribution, in which case the provisions of the
29CDDL are applicable instead of those of the GPL.
30
31You may elect to license modified versions of this file under the
32terms and conditions of either the GPL or the CDDL or both.
33"""
34__version__ = "$Revision: 67042 $"
35
36# pylint: disable=anomalous-backslash-in-string
37
38# Standard python imports.
39import os
40import re
41import sys
42
43## Only the main script needs to modify the path.
44#g_ksValidationKitDir = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))),
45# 'ValidationKit');
46#sys.path.append(g_ksValidationKitDir);
47#
48#from common import utils; - Windows build boxes doesn't have pywin32.
49
50# Python 3 hacks:
51if sys.version_info[0] >= 3:
52 long = int; # pylint: disable=redefined-builtin,invalid-name
53
54
55g_kdX86EFlagsConstants = {
56 'X86_EFL_CF': 0x00000001, # RT_BIT_32(0)
57 'X86_EFL_1': 0x00000002, # RT_BIT_32(1)
58 'X86_EFL_PF': 0x00000004, # RT_BIT_32(2)
59 'X86_EFL_AF': 0x00000010, # RT_BIT_32(4)
60 'X86_EFL_ZF': 0x00000040, # RT_BIT_32(6)
61 'X86_EFL_SF': 0x00000080, # RT_BIT_32(7)
62 'X86_EFL_TF': 0x00000100, # RT_BIT_32(8)
63 'X86_EFL_IF': 0x00000200, # RT_BIT_32(9)
64 'X86_EFL_DF': 0x00000400, # RT_BIT_32(10)
65 'X86_EFL_OF': 0x00000800, # RT_BIT_32(11)
66 'X86_EFL_IOPL': 0x00003000, # (RT_BIT_32(12) | RT_BIT_32(13))
67 'X86_EFL_NT': 0x00004000, # RT_BIT_32(14)
68 'X86_EFL_RF': 0x00010000, # RT_BIT_32(16)
69 'X86_EFL_VM': 0x00020000, # RT_BIT_32(17)
70 'X86_EFL_AC': 0x00040000, # RT_BIT_32(18)
71 'X86_EFL_VIF': 0x00080000, # RT_BIT_32(19)
72 'X86_EFL_VIP': 0x00100000, # RT_BIT_32(20)
73 'X86_EFL_ID': 0x00200000, # RT_BIT_32(21)
74 'X86_EFL_LIVE_MASK': 0x003f7fd5, # UINT32_C(0x003f7fd5)
75 'X86_EFL_RA1_MASK': 0x00000002, # RT_BIT_32(1)
76};
77
78## EFlags values allowed in \@opfltest, \@opflmodify, \@opflundef, \@opflset, and \@opflclear.
79g_kdEFlagsMnemonics = {
80 # Debugger flag notation (sorted by value):
81 'cf': 'X86_EFL_CF', ##< Carry Flag.
82 'nc': '!X86_EFL_CF', ##< No Carry.
83
84 'po': 'X86_EFL_PF', ##< Parity Pdd.
85 'pe': '!X86_EFL_PF', ##< Parity Even.
86
87 'af': 'X86_EFL_AF', ##< Aux Flag.
88 'na': '!X86_EFL_AF', ##< No Aux.
89
90 'zr': 'X86_EFL_ZF', ##< ZeRo.
91 'nz': '!X86_EFL_ZF', ##< No Zero.
92
93 'ng': 'X86_EFL_SF', ##< NeGative (sign).
94 'pl': '!X86_EFL_SF', ##< PLuss (sign).
95
96 'tf': 'X86_EFL_TF', ##< Trap flag.
97
98 'ei': 'X86_EFL_IF', ##< Enabled Interrupts.
99 'di': '!X86_EFL_IF', ##< Disabled Interrupts.
100
101 'dn': 'X86_EFL_DF', ##< DowN (string op direction).
102 'up': '!X86_EFL_DF', ##< UP (string op direction).
103
104 'ov': 'X86_EFL_OF', ##< OVerflow.
105 'nv': '!X86_EFL_OF', ##< No Overflow.
106
107 'nt': 'X86_EFL_NT', ##< Nested Task.
108 'rf': 'X86_EFL_RF', ##< Resume Flag.
109 'vm': 'X86_EFL_VM', ##< Virtual-8086 Mode.
110 'ac': 'X86_EFL_AC', ##< Alignment Check.
111 'vif': 'X86_EFL_VIF', ##< Virtual Interrupt Flag.
112 'vip': 'X86_EFL_VIP', ##< Virtual Interrupt Pending.
113
114 # Reference manual notation not covered above (sorted by value):
115 'pf': 'X86_EFL_PF',
116 'zf': 'X86_EFL_ZF',
117 'sf': 'X86_EFL_SF',
118 'if': 'X86_EFL_IF',
119 'df': 'X86_EFL_DF',
120 'of': 'X86_EFL_OF',
121 'iopl': 'X86_EFL_IOPL',
122 'id': 'X86_EFL_ID',
123};
124
125## Constants and values for CR0.
126g_kdX86Cr0Constants = {
127 'X86_CR0_PE': 0x00000001, # RT_BIT_32(0)
128 'X86_CR0_MP': 0x00000002, # RT_BIT_32(1)
129 'X86_CR0_EM': 0x00000004, # RT_BIT_32(2)
130 'X86_CR0_TS': 0x00000008, # RT_BIT_32(3)
131 'X86_CR0_ET': 0x00000010, # RT_BIT_32(4)
132 'X86_CR0_NE': 0x00000020, # RT_BIT_32(5)
133 'X86_CR0_WP': 0x00010000, # RT_BIT_32(16)
134 'X86_CR0_AM': 0x00040000, # RT_BIT_32(18)
135 'X86_CR0_NW': 0x20000000, # RT_BIT_32(29)
136 'X86_CR0_CD': 0x40000000, # RT_BIT_32(30)
137 'X86_CR0_PG': 0x80000000, # RT_BIT_32(31)
138};
139
140## Constants and values for CR4.
141g_kdX86Cr4Constants = {
142 'X86_CR4_VME': 0x00000001, # RT_BIT_32(0)
143 'X86_CR4_PVI': 0x00000002, # RT_BIT_32(1)
144 'X86_CR4_TSD': 0x00000004, # RT_BIT_32(2)
145 'X86_CR4_DE': 0x00000008, # RT_BIT_32(3)
146 'X86_CR4_PSE': 0x00000010, # RT_BIT_32(4)
147 'X86_CR4_PAE': 0x00000020, # RT_BIT_32(5)
148 'X86_CR4_MCE': 0x00000040, # RT_BIT_32(6)
149 'X86_CR4_PGE': 0x00000080, # RT_BIT_32(7)
150 'X86_CR4_PCE': 0x00000100, # RT_BIT_32(8)
151 'X86_CR4_OSFXSR': 0x00000200, # RT_BIT_32(9)
152 'X86_CR4_OSXMMEEXCPT': 0x00000400, # RT_BIT_32(10)
153 'X86_CR4_VMXE': 0x00002000, # RT_BIT_32(13)
154 'X86_CR4_SMXE': 0x00004000, # RT_BIT_32(14)
155 'X86_CR4_PCIDE': 0x00020000, # RT_BIT_32(17)
156 'X86_CR4_OSXSAVE': 0x00040000, # RT_BIT_32(18)
157 'X86_CR4_SMEP': 0x00100000, # RT_BIT_32(20)
158 'X86_CR4_SMAP': 0x00200000, # RT_BIT_32(21)
159 'X86_CR4_PKE': 0x00400000, # RT_BIT_32(22)
160};
161
162## XSAVE components (XCR0).
163g_kdX86XSaveCConstants = {
164 'XSAVE_C_X87': 0x00000001,
165 'XSAVE_C_SSE': 0x00000002,
166 'XSAVE_C_YMM': 0x00000004,
167 'XSAVE_C_BNDREGS': 0x00000008,
168 'XSAVE_C_BNDCSR': 0x00000010,
169 'XSAVE_C_OPMASK': 0x00000020,
170 'XSAVE_C_ZMM_HI256': 0x00000040,
171 'XSAVE_C_ZMM_16HI': 0x00000080,
172 'XSAVE_C_PKRU': 0x00000200,
173 'XSAVE_C_LWP': 0x4000000000000000,
174 'XSAVE_C_X': 0x8000000000000000,
175 'XSAVE_C_ALL_AVX': 0x000000c4, # For clearing all AVX bits.
176 'XSAVE_C_ALL_AVX_SSE': 0x000000c6, # For clearing all AVX and SSE bits.
177};
178
179
180## \@op[1-4] locations
181g_kdOpLocations = {
182 'reg': [], ## modrm.reg
183 'rm': [], ## modrm.rm
184 'imm': [], ## immediate instruction data
185 'vvvv': [], ## VEX.vvvv
186
187 # fixed registers.
188 'AL': [],
189 'rAX': [],
190 'rSI': [],
191 'rDI': [],
192 'rFLAGS': [],
193 'CS': [],
194 'DS': [],
195 'ES': [],
196 'FS': [],
197 'GS': [],
198 'SS': [],
199};
200
201## \@op[1-4] types
202##
203## Value fields:
204## - 0: the normal IDX_ParseXXX handler (IDX_UseModRM == IDX_ParseModRM).
205## - 1: the location (g_kdOpLocations).
206## - 2: disassembler format string version of the type.
207## - 3: disassembler OP_PARAM_XXX (XXX only).
208##
209## Note! See the A.2.1 in SDM vol 2 for the type names.
210g_kdOpTypes = {
211 # Fixed addresses
212 'Ap': ( 'IDX_ParseImmAddrF', 'imm', '%Ap', 'Ap', ),
213
214 # ModR/M.rm
215 'Eb': ( 'IDX_UseModRM', 'rm', '%Eb', 'Eb', ),
216 'Ed': ( 'IDX_UseModRM', 'rm', '%Ed', 'Ed', ),
217 'Ed_WO': ( 'IDX_UseModRM', 'rm', '%Ed', 'Ed', ),
218 'Eq': ( 'IDX_UseModRM', 'rm', '%Eq', 'Eq', ),
219 'Eq_WO': ( 'IDX_UseModRM', 'rm', '%Eq', 'Eq', ),
220 'Ew': ( 'IDX_UseModRM', 'rm', '%Ew', 'Ew', ),
221 'Ev': ( 'IDX_UseModRM', 'rm', '%Ev', 'Ev', ),
222 'Qq': ( 'IDX_UseModRM', 'rm', '%Qq', 'Qq', ),
223 'Qq_WO': ( 'IDX_UseModRM', 'rm', '%Qq', 'Qq', ),
224 'Wss': ( 'IDX_UseModRM', 'rm', '%Wss', 'Wss', ),
225 'Wss_WO': ( 'IDX_UseModRM', 'rm', '%Wss', 'Wss', ),
226 'Wsd': ( 'IDX_UseModRM', 'rm', '%Wsd', 'Wsd', ),
227 'Wsd_WO': ( 'IDX_UseModRM', 'rm', '%Wsd', 'Wsd', ),
228 'Wps': ( 'IDX_UseModRM', 'rm', '%Wps', 'Wps', ),
229 'Wps_WO': ( 'IDX_UseModRM', 'rm', '%Wps', 'Wps', ),
230 'Wpd': ( 'IDX_UseModRM', 'rm', '%Wpd', 'Wpd', ),
231 'Wpd_WO': ( 'IDX_UseModRM', 'rm', '%Wpd', 'Wpd', ),
232 'Wdq': ( 'IDX_UseModRM', 'rm', '%Wdq', 'Wdq', ),
233 'Wdq_WO': ( 'IDX_UseModRM', 'rm', '%Wdq', 'Wdq', ),
234 'Wq': ( 'IDX_UseModRM', 'rm', '%Wq', 'Wq', ),
235 'Wq_WO': ( 'IDX_UseModRM', 'rm', '%Wq', 'Wq', ),
236 'WqZxReg_WO': ( 'IDX_UseModRM', 'rm', '%Wq', 'Wq', ),
237 'Wx': ( 'IDX_UseModRM', 'rm', '%Wx', 'Wx', ),
238 'Wx_WO': ( 'IDX_UseModRM', 'rm', '%Wx', 'Wx', ),
239
240 # ModR/M.rm - register only.
241 'Uq': ( 'IDX_UseModRM', 'rm', '%Uq', 'Uq', ),
242 'UqHi': ( 'IDX_UseModRM', 'rm', '%Uq', 'UqHi', ),
243 'Uss': ( 'IDX_UseModRM', 'rm', '%Uss', 'Uss', ),
244 'Uss_WO': ( 'IDX_UseModRM', 'rm', '%Uss', 'Uss', ),
245 'Usd': ( 'IDX_UseModRM', 'rm', '%Usd', 'Usd', ),
246 'Usd_WO': ( 'IDX_UseModRM', 'rm', '%Usd', 'Usd', ),
247 'Nq': ( 'IDX_UseModRM', 'rm', '%Qq', 'Nq', ),
248
249 # ModR/M.rm - memory only.
250 'Ma': ( 'IDX_UseModRM', 'rm', '%Ma', 'Ma', ), ##< Only used by BOUND.
251 'Mb_RO': ( 'IDX_UseModRM', 'rm', '%Mb', 'Mb', ),
252 'Md': ( 'IDX_UseModRM', 'rm', '%Md', 'Md', ),
253 'Md_RO': ( 'IDX_UseModRM', 'rm', '%Md', 'Md', ),
254 'Md_WO': ( 'IDX_UseModRM', 'rm', '%Md', 'Md', ),
255 'Mdq': ( 'IDX_UseModRM', 'rm', '%Mdq', 'Mdq', ),
256 'Mdq_WO': ( 'IDX_UseModRM', 'rm', '%Mdq', 'Mdq', ),
257 'Mq': ( 'IDX_UseModRM', 'rm', '%Mq', 'Mq', ),
258 'Mq_WO': ( 'IDX_UseModRM', 'rm', '%Mq', 'Mq', ),
259 'Mps_WO': ( 'IDX_UseModRM', 'rm', '%Mps', 'Mps', ),
260 'Mpd_WO': ( 'IDX_UseModRM', 'rm', '%Mpd', 'Mpd', ),
261 'Mx': ( 'IDX_UseModRM', 'rm', '%Mx', 'Mx', ),
262 'Mx_WO': ( 'IDX_UseModRM', 'rm', '%Mx', 'Mx', ),
263 'M_RO': ( 'IDX_UseModRM', 'rm', '%M', 'M', ),
264 'M_RW': ( 'IDX_UseModRM', 'rm', '%M', 'M', ),
265
266 # ModR/M.reg
267 'Gb': ( 'IDX_UseModRM', 'reg', '%Gb', 'Gb', ),
268 'Gw': ( 'IDX_UseModRM', 'reg', '%Gw', 'Gw', ),
269 'Gv': ( 'IDX_UseModRM', 'reg', '%Gv', 'Gv', ),
270 'Gv_RO': ( 'IDX_UseModRM', 'reg', '%Gv', 'Gv', ),
271 'Pd': ( 'IDX_UseModRM', 'reg', '%Pd', 'Pd', ),
272 'PdZx_WO': ( 'IDX_UseModRM', 'reg', '%Pd', 'PdZx', ),
273 'Pq': ( 'IDX_UseModRM', 'reg', '%Pq', 'Pq', ),
274 'Pq_WO': ( 'IDX_UseModRM', 'reg', '%Pq', 'Pq', ),
275 'Vd': ( 'IDX_UseModRM', 'reg', '%Vd', 'Vd', ),
276 'Vd_WO': ( 'IDX_UseModRM', 'reg', '%Vd', 'Vd', ),
277 'VdZx_WO': ( 'IDX_UseModRM', 'reg', '%Vd', 'Vd', ),
278 'Vdq': ( 'IDX_UseModRM', 'reg', '%Vdq', 'Vdq', ),
279 'Vss': ( 'IDX_UseModRM', 'reg', '%Vss', 'Vss', ),
280 'Vss_WO': ( 'IDX_UseModRM', 'reg', '%Vss', 'Vss', ),
281 'VssZx_WO': ( 'IDX_UseModRM', 'reg', '%Vss', 'Vss', ),
282 'Vsd': ( 'IDX_UseModRM', 'reg', '%Vsd', 'Vsd', ),
283 'Vsd_WO': ( 'IDX_UseModRM', 'reg', '%Vsd', 'Vsd', ),
284 'VsdZx_WO': ( 'IDX_UseModRM', 'reg', '%Vsd', 'Vsd', ),
285 'Vps': ( 'IDX_UseModRM', 'reg', '%Vps', 'Vps', ),
286 'Vps_WO': ( 'IDX_UseModRM', 'reg', '%Vps', 'Vps', ),
287 'Vpd': ( 'IDX_UseModRM', 'reg', '%Vpd', 'Vpd', ),
288 'Vpd_WO': ( 'IDX_UseModRM', 'reg', '%Vpd', 'Vpd', ),
289 'Vq': ( 'IDX_UseModRM', 'reg', '%Vq', 'Vq', ),
290 'Vq_WO': ( 'IDX_UseModRM', 'reg', '%Vq', 'Vq', ),
291 'Vdq_WO': ( 'IDX_UseModRM', 'reg', '%Vdq', 'Vdq', ),
292 'VqHi': ( 'IDX_UseModRM', 'reg', '%Vdq', 'VdqHi', ),
293 'VqHi_WO': ( 'IDX_UseModRM', 'reg', '%Vdq', 'VdqHi', ),
294 'VqZx_WO': ( 'IDX_UseModRM', 'reg', '%Vq', 'VqZx', ),
295 'Vx': ( 'IDX_UseModRM', 'reg', '%Vx', 'Vx', ),
296 'Vx_WO': ( 'IDX_UseModRM', 'reg', '%Vx', 'Vx', ),
297
298 # VEX.vvvv
299 'HssHi': ( 'IDX_UseModRM', 'vvvv', '%Hx', 'HssHi', ),
300 'HsdHi': ( 'IDX_UseModRM', 'vvvv', '%Hx', 'HsdHi', ),
301 'HqHi': ( 'IDX_UseModRM', 'vvvv', '%Hq', 'HqHi', ),
302
303 # Immediate values.
304 'Ib': ( 'IDX_ParseImmByte', 'imm', '%Ib', 'Ib', ), ##< NB! Could be IDX_ParseImmByteSX for some instrs.
305 'Iw': ( 'IDX_ParseImmUshort', 'imm', '%Iw', 'Iw', ),
306 'Id': ( 'IDX_ParseImmUlong', 'imm', '%Id', 'Id', ),
307 'Iq': ( 'IDX_ParseImmQword', 'imm', '%Iq', 'Iq', ),
308 'Iv': ( 'IDX_ParseImmV', 'imm', '%Iv', 'Iv', ), ##< o16: word, o32: dword, o64: qword
309 'Iz': ( 'IDX_ParseImmZ', 'imm', '%Iz', 'Iz', ), ##< o16: word, o32|o64:dword
310
311 # Address operands (no ModR/M).
312 'Ob': ( 'IDX_ParseImmAddr', 'imm', '%Ob', 'Ob', ),
313 'Ov': ( 'IDX_ParseImmAddr', 'imm', '%Ov', 'Ov', ),
314
315 # Relative jump targets
316 'Jb': ( 'IDX_ParseImmBRel', 'imm', '%Jb', 'Jb', ),
317 'Jv': ( 'IDX_ParseImmVRel', 'imm', '%Jv', 'Jv', ),
318
319 # DS:rSI
320 'Xb': ( 'IDX_ParseXb', 'rSI', '%eSI', 'Xb', ),
321 'Xv': ( 'IDX_ParseXv', 'rSI', '%eSI', 'Xv', ),
322 # ES:rDI
323 'Yb': ( 'IDX_ParseYb', 'rDI', '%eDI', 'Yb', ),
324 'Yv': ( 'IDX_ParseYv', 'rDI', '%eDI', 'Yv', ),
325
326 'Fv': ( 'IDX_ParseFixedReg', 'rFLAGS', '%Fv', 'Fv', ),
327
328 # Fixed registers.
329 'AL': ( 'IDX_ParseFixedReg', 'AL', 'al', 'REG_AL', ),
330 'rAX': ( 'IDX_ParseFixedReg', 'rAX', '%eAX', 'REG_EAX', ),
331 'CS': ( 'IDX_ParseFixedReg', 'CS', 'cs', 'REG_CS', ), # 8086: push CS
332 'DS': ( 'IDX_ParseFixedReg', 'DS', 'ds', 'REG_DS', ),
333 'ES': ( 'IDX_ParseFixedReg', 'ES', 'es', 'REG_ES', ),
334 'FS': ( 'IDX_ParseFixedReg', 'FS', 'fs', 'REG_FS', ),
335 'GS': ( 'IDX_ParseFixedReg', 'GS', 'gs', 'REG_GS', ),
336 'SS': ( 'IDX_ParseFixedReg', 'SS', 'ss', 'REG_SS', ),
337};
338
339# IDX_ParseFixedReg
340# IDX_ParseVexDest
341
342
343## IEMFORM_XXX mappings.
344g_kdIemForms = { # sEncoding, [ sWhere1, ... ]
345 'RM': ( 'ModR/M', [ 'reg', 'rm' ], ),
346 'RM_REG': ( 'ModR/M', [ 'reg', 'rm' ], ),
347 'RM_MEM': ( 'ModR/M', [ 'reg', 'rm' ], ),
348 'MR': ( 'ModR/M', [ 'rm', 'reg' ], ),
349 'MR_REG': ( 'ModR/M', [ 'rm', 'reg' ], ),
350 'MR_MEM': ( 'ModR/M', [ 'rm', 'reg' ], ),
351 'M': ( 'ModR/M', [ 'rm', ], ),
352 'M_REG': ( 'ModR/M', [ 'rm', ], ),
353 'M_MEM': ( 'ModR/M', [ 'rm', ], ),
354 'R': ( 'ModR/M', [ 'reg', ], ),
355
356 'VEX_RM': ( 'VEX.ModR/M', [ 'reg', 'rm' ], ),
357 'VEX_RM_REG': ( 'VEX.ModR/M', [ 'reg', 'rm' ], ),
358 'VEX_RM_MEM': ( 'VEX.ModR/M', [ 'reg', 'rm' ], ),
359 'VEX_XM': ( 'VEX.ModR/M', [ 'reg', 'rm' ], ), # same as VEX_RM_MEM, typo?
360 'VEX_MR': ( 'VEX.ModR/M', [ 'rm', 'reg' ], ),
361 'VEX_MR_REG': ( 'VEX.ModR/M', [ 'rm', 'reg' ], ),
362 'VEX_MR_MEM': ( 'VEX.ModR/M', [ 'rm', 'reg' ], ),
363 'VEX_M': ( 'VEX.ModR/M', [ 'rm', ], ),
364 'VEX_M_REG': ( 'VEX.ModR/M', [ 'rm', ], ),
365 'VEX_M_MEM': ( 'VEX.ModR/M', [ 'rm', ], ),
366 'VEX_R': ( 'VEX.ModR/M', [ 'reg', ], ),
367 'VEX_RVM': ( 'VEX.ModR/M', [ 'reg', 'vvvv', 'rm'], ),
368 'VEX_RVM_REG': ( 'VEX.ModR/M', [ 'reg', 'vvvv', 'rm'], ),
369 'VEX_RVM_MEM': ( 'VEX.ModR/M', [ 'reg', 'vvvv', 'rm'], ),
370 'VEX_MVR': ( 'VEX.ModR/M', [ 'rm', 'vvvv', 'reg'], ),
371 'VEX_MVR_REG': ( 'VEX.ModR/M', [ 'rm', 'vvvv', 'reg'], ),
372 'VEX_MVR_MEM': ( 'VEX.ModR/M', [ 'rm', 'vvvv', 'reg'], ),
373
374 'FIXED': ( 'fixed', None, )
375};
376
377## \@oppfx values.
378g_kdPrefixes = {
379 'none': [],
380 '0x66': [],
381 '0xf3': [],
382 '0xf2': [],
383};
384
385## Special \@opcode tag values.
386g_kdSpecialOpcodes = {
387 '/reg': [],
388 'mr/reg': [],
389 '11 /reg': [],
390 '!11 /reg': [],
391 '11 mr/reg': [],
392 '!11 mr/reg': [],
393};
394
395## Special \@opcodesub tag values.
396g_kdSubOpcodes = {
397 'none': [ None, ],
398 '11 mr/reg': [ '11 mr/reg', ],
399 '11': [ '11 mr/reg', ], ##< alias
400 '!11 mr/reg': [ '!11 mr/reg', ],
401 '!11': [ '!11 mr/reg', ], ##< alias
402 'rex.w=0': [ 'rex.w=0', ],
403 'w=0': [ 'rex.w=0', ], ##< alias
404 'rex.w=1': [ 'rex.w=1', ],
405 'w=1': [ 'rex.w=1', ], ##< alias
406};
407
408## Valid values for \@openc
409g_kdEncodings = {
410 'ModR/M': [ 'BS3CG1ENC_MODRM', ], ##< ModR/M
411 'VEX.ModR/M': [ 'BS3CG1ENC_VEX_MODRM', ], ##< VEX...ModR/M
412 'fixed': [ 'BS3CG1ENC_FIXED', ], ##< Fixed encoding (address, registers, unused, etc).
413 'VEX.fixed': [ 'BS3CG1ENC_VEX_FIXED', ], ##< VEX + fixed encoding (address, registers, unused, etc).
414 'prefix': [ None, ], ##< Prefix
415};
416
417## \@opunused, \@opinvalid, \@opinvlstyle
418g_kdInvalidStyles = {
419 'immediate': [], ##< CPU stops decoding immediately after the opcode.
420 'vex.modrm': [], ##< VEX+ModR/M, everyone.
421 'intel-modrm': [], ##< Intel decodes ModR/M.
422 'intel-modrm-imm8': [], ##< Intel decodes ModR/M and an 8-byte immediate.
423 'intel-opcode-modrm': [], ##< Intel decodes another opcode byte followed by ModR/M. (Unused extension tables.)
424 'intel-opcode-modrm-imm8': [], ##< Intel decodes another opcode byte followed by ModR/M and an 8-byte immediate.
425};
426
427g_kdCpuNames = {
428 '8086': (),
429 '80186': (),
430 '80286': (),
431 '80386': (),
432 '80486': (),
433};
434
435## \@opcpuid
436g_kdCpuIdFlags = {
437 'vme': 'X86_CPUID_FEATURE_EDX_VME',
438 'tsc': 'X86_CPUID_FEATURE_EDX_TSC',
439 'msr': 'X86_CPUID_FEATURE_EDX_MSR',
440 'cx8': 'X86_CPUID_FEATURE_EDX_CX8',
441 'sep': 'X86_CPUID_FEATURE_EDX_SEP',
442 'cmov': 'X86_CPUID_FEATURE_EDX_CMOV',
443 'clfsh': 'X86_CPUID_FEATURE_EDX_CLFSH',
444 'clflushopt': 'X86_CPUID_STEXT_FEATURE_EBX_CLFLUSHOPT',
445 'mmx': 'X86_CPUID_FEATURE_EDX_MMX',
446 'fxsr': 'X86_CPUID_FEATURE_EDX_FXSR',
447 'sse': 'X86_CPUID_FEATURE_EDX_SSE',
448 'sse2': 'X86_CPUID_FEATURE_EDX_SSE2',
449 'sse3': 'X86_CPUID_FEATURE_ECX_SSE3',
450 'pclmul': 'X86_CPUID_FEATURE_ECX_DTES64',
451 'monitor': 'X86_CPUID_FEATURE_ECX_CPLDS',
452 'vmx': 'X86_CPUID_FEATURE_ECX_VMX',
453 'smx': 'X86_CPUID_FEATURE_ECX_TM2',
454 'ssse3': 'X86_CPUID_FEATURE_ECX_SSSE3',
455 'fma': 'X86_CPUID_FEATURE_ECX_FMA',
456 'cx16': 'X86_CPUID_FEATURE_ECX_CX16',
457 'pcid': 'X86_CPUID_FEATURE_ECX_PCID',
458 'sse4.1': 'X86_CPUID_FEATURE_ECX_SSE4_1',
459 'sse4.2': 'X86_CPUID_FEATURE_ECX_SSE4_2',
460 'movbe': 'X86_CPUID_FEATURE_ECX_MOVBE',
461 'popcnt': 'X86_CPUID_FEATURE_ECX_POPCNT',
462 'aes': 'X86_CPUID_FEATURE_ECX_AES',
463 'xsave': 'X86_CPUID_FEATURE_ECX_XSAVE',
464 'avx': 'X86_CPUID_FEATURE_ECX_AVX',
465 'f16c': 'X86_CPUID_FEATURE_ECX_F16C',
466 'rdrand': 'X86_CPUID_FEATURE_ECX_RDRAND',
467
468 'axmmx': 'X86_CPUID_AMD_FEATURE_EDX_AXMMX',
469 '3dnowext': 'X86_CPUID_AMD_FEATURE_EDX_3DNOW_EX',
470 '3dnow': 'X86_CPUID_AMD_FEATURE_EDX_3DNOW',
471 'svm': 'X86_CPUID_AMD_FEATURE_ECX_SVM',
472 'cr8l': 'X86_CPUID_AMD_FEATURE_ECX_CR8L',
473 'abm': 'X86_CPUID_AMD_FEATURE_ECX_ABM',
474 'sse4a': 'X86_CPUID_AMD_FEATURE_ECX_SSE4A',
475 '3dnowprf': 'X86_CPUID_AMD_FEATURE_ECX_3DNOWPRF',
476 'xop': 'X86_CPUID_AMD_FEATURE_ECX_XOP',
477 'fma4': 'X86_CPUID_AMD_FEATURE_ECX_FMA4',
478};
479
480## \@ophints values.
481g_kdHints = {
482 'invalid': 'DISOPTYPE_INVALID', ##<
483 'harmless': 'DISOPTYPE_HARMLESS', ##<
484 'controlflow': 'DISOPTYPE_CONTROLFLOW', ##<
485 'potentially_dangerous': 'DISOPTYPE_POTENTIALLY_DANGEROUS', ##<
486 'dangerous': 'DISOPTYPE_DANGEROUS', ##<
487 'portio': 'DISOPTYPE_PORTIO', ##<
488 'privileged': 'DISOPTYPE_PRIVILEGED', ##<
489 'privileged_notrap': 'DISOPTYPE_PRIVILEGED_NOTRAP', ##<
490 'uncond_controlflow': 'DISOPTYPE_UNCOND_CONTROLFLOW', ##<
491 'relative_controlflow': 'DISOPTYPE_RELATIVE_CONTROLFLOW', ##<
492 'cond_controlflow': 'DISOPTYPE_COND_CONTROLFLOW', ##<
493 'interrupt': 'DISOPTYPE_INTERRUPT', ##<
494 'illegal': 'DISOPTYPE_ILLEGAL', ##<
495 'rrm_dangerous': 'DISOPTYPE_RRM_DANGEROUS', ##< Some additional dangerous ones when recompiling raw r0.
496 'rrm_dangerous_16': 'DISOPTYPE_RRM_DANGEROUS_16', ##< Some additional dangerous ones when recompiling 16-bit raw r0.
497 'inhibit_irqs': 'DISOPTYPE_INHIBIT_IRQS', ##< Will or can inhibit irqs (sti, pop ss, mov ss) */
498 'portio_read': 'DISOPTYPE_PORTIO_READ', ##<
499 'portio_write': 'DISOPTYPE_PORTIO_WRITE', ##<
500 'invalid_64': 'DISOPTYPE_INVALID_64', ##< Invalid in 64 bits mode
501 'only_64': 'DISOPTYPE_ONLY_64', ##< Only valid in 64 bits mode
502 'default_64_op_size': 'DISOPTYPE_DEFAULT_64_OP_SIZE', ##< Default 64 bits operand size
503 'forced_64_op_size': 'DISOPTYPE_FORCED_64_OP_SIZE', ##< Forced 64 bits operand size; regardless of prefix bytes
504 'rexb_extends_opreg': 'DISOPTYPE_REXB_EXTENDS_OPREG', ##< REX.B extends the register field in the opcode byte
505 'mod_fixed_11': 'DISOPTYPE_MOD_FIXED_11', ##< modrm.mod is always 11b
506 'forced_32_op_size_x86': 'DISOPTYPE_FORCED_32_OP_SIZE_X86', ##< Forced 32 bits operand size; regardless of prefix bytes
507 ## (only in 16 & 32 bits mode!)
508 'sse': 'DISOPTYPE_SSE', ##< SSE,SSE2,SSE3,AVX,++ instruction. Not implemented yet!
509 'mmx': 'DISOPTYPE_MMX', ##< MMX,MMXExt,3DNow,++ instruction. Not implemented yet!
510 'fpu': 'DISOPTYPE_FPU', ##< FPU instruction. Not implemented yet!
511 'ignores_oz_pfx': '', ##< Ignores operand size prefix 66h.
512 'ignores_rexw': '', ##< Ignores REX.W.
513 'ignores_op_sizes': '', ##< Shorthand for "ignores_oz_pfx | ignores_op_sizes".
514 'ignores_vex_l': '', ##< Ignores VEX.L.
515 'vex_l_zero': '', ##< VEX.L must be 0.
516 'lock_allowed': '', ##< Lock prefix allowed.
517};
518
519## \@opxcpttype values (see SDMv2 2.4, 2.7).
520g_kdXcptTypes = {
521 'none': [],
522 '1': [],
523 '2': [],
524 '3': [],
525 '4': [],
526 '4UA': [],
527 '5': [],
528 '5LZ': [], # LZ = VEX.L must be zero.
529 '6': [],
530 '7': [],
531 '7LZ': [],
532 '8': [],
533 '11': [],
534 '12': [],
535 'E1': [],
536 'E1NF': [],
537 'E2': [],
538 'E3': [],
539 'E3NF': [],
540 'E4': [],
541 'E4NF': [],
542 'E5': [],
543 'E5NF': [],
544 'E6': [],
545 'E6NF': [],
546 'E7NF': [],
547 'E9': [],
548 'E9NF': [],
549 'E10': [],
550 'E11': [],
551 'E12': [],
552 'E12NF': [],
553};
554
555
556def _isValidOpcodeByte(sOpcode):
557 """
558 Checks if sOpcode is a valid lower case opcode byte.
559 Returns true/false.
560 """
561 if len(sOpcode) == 4:
562 if sOpcode[:2] == '0x':
563 if sOpcode[2] in '0123456789abcdef':
564 if sOpcode[3] in '0123456789abcdef':
565 return True;
566 return False;
567
568
569class InstructionMap(object):
570 """
571 Instruction map.
572
573 The opcode map provides the lead opcode bytes (empty for the one byte
574 opcode map). An instruction can be member of multiple opcode maps as long
575 as it uses the same opcode value within the map (because of VEX).
576 """
577
578 kdEncodings = {
579 'legacy': [],
580 'vex1': [], ##< VEX or EVEX prefix with vvvvv = 1
581 'vex2': [], ##< VEX or EVEX prefix with vvvvv = 2
582 'vex3': [], ##< VEX or EVEX prefix with vvvvv = 3
583 'xop8': [], ##< XOP prefix with vvvvv = 8
584 'xop9': [], ##< XOP prefix with vvvvv = 9
585 'xop10': [], ##< XOP prefix with vvvvv = 10
586 };
587 ## Selectors.
588 ## The first value is the number of table entries required by a
589 ## decoder or disassembler for this type of selector.
590 kdSelectors = {
591 'byte': [ 256, ], ##< next opcode byte selects the instruction (default).
592 '/r': [ 8, ], ##< modrm.reg selects the instruction.
593 'memreg /r':[ 16, ], ##< modrm.reg and (modrm.mod == 3) selects the instruction.
594 'mod /r': [ 32, ], ##< modrm.reg and modrm.mod selects the instruction.
595 '!11 /r': [ 8, ], ##< modrm.reg selects the instruction with modrm.mod != 0y11.
596 '11 /r': [ 8, ], ##< modrm.reg select the instruction with modrm.mod == 0y11.
597 '11': [ 64, ], ##< modrm.reg and modrm.rm select the instruction with modrm.mod == 0y11.
598 };
599
600 def __init__(self, sName, asLeadOpcodes = None, sSelector = 'byte', sEncoding = 'legacy', sDisParse = None):
601 assert sSelector in self.kdSelectors;
602 assert sEncoding in self.kdEncodings;
603 if asLeadOpcodes is None:
604 asLeadOpcodes = [];
605 else:
606 for sOpcode in asLeadOpcodes:
607 assert _isValidOpcodeByte(sOpcode);
608 assert sDisParse is None or sDisParse.startswith('IDX_Parse');
609
610 self.sName = sName;
611 self.asLeadOpcodes = asLeadOpcodes; ##< Lead opcode bytes formatted as hex strings like '0x0f'.
612 self.sSelector = sSelector; ##< The member selector, see kdSelectors.
613 self.sEncoding = sEncoding; ##< The encoding, see kdSelectors.
614 self.aoInstructions = []; # type: Instruction
615 self.sDisParse = sDisParse; ##< IDX_ParseXXX.
616
617 def getTableSize(self):
618 """
619 Number of table entries. This corresponds directly to the selector.
620 """
621 return self.kdSelectors[self.sSelector][0];
622
623 def getInstructionIndex(self, oInstr):
624 """
625 Returns the table index for the instruction.
626 """
627 bOpcode = oInstr.getOpcodeByte();
628
629 # The byte selector is simple. We need a full opcode byte and need just return it.
630 if self.sSelector == 'byte':
631 assert oInstr.sOpcode[:2] == '0x' and len(oInstr.sOpcode) == 4, str(oInstr);
632 return bOpcode;
633
634 # The other selectors needs masking and shifting.
635 if self.sSelector == '/r':
636 return (bOpcode >> 3) & 0x7;
637
638 if self.sSelector == 'mod /r':
639 return (bOpcode >> 3) & 0x1f;
640
641 if self.sSelector == 'memreg /r':
642 return ((bOpcode >> 3) & 0x7) | (int((bOpcode >> 6) == 3) << 3);
643
644 if self.sSelector == '!11 /r':
645 assert (bOpcode & 0xc0) != 0xc, str(oInstr);
646 return (bOpcode >> 3) & 0x7;
647
648 if self.sSelector == '11 /r':
649 assert (bOpcode & 0xc0) == 0xc, str(oInstr);
650 return (bOpcode >> 3) & 0x7;
651
652 if self.sSelector == '11':
653 assert (bOpcode & 0xc0) == 0xc, str(oInstr);
654 return bOpcode & 0x3f;
655
656 assert False, self.sSelector;
657 return -1;
658
659 def getInstructionsInTableOrder(self):
660 """
661 Get instructions in table order.
662
663 Returns array of instructions. Normally there is exactly one
664 instruction per entry. However the entry could also be None if
665 not instruction was specified for that opcode value. Or there
666 could be a list of instructions to deal with special encodings
667 where for instance prefix (e.g. REX.W) encodes a different
668 instruction or different CPUs have different instructions or
669 prefixes in the same place.
670 """
671 # Start with empty table.
672 cTable = self.getTableSize();
673 aoTable = [None] * cTable;
674
675 # Insert the instructions.
676 for oInstr in self.aoInstructions:
677 if oInstr.sOpcode:
678 idxOpcode = self.getInstructionIndex(oInstr);
679 assert idxOpcode < cTable, str(idxOpcode);
680
681 oExisting = aoTable[idxOpcode];
682 if oExisting is None:
683 aoTable[idxOpcode] = oInstr;
684 elif not isinstance(oExisting, list):
685 aoTable[idxOpcode] = list([oExisting, oInstr]);
686 else:
687 oExisting.append(oInstr);
688
689 return aoTable;
690
691
692 def getDisasTableName(self):
693 """
694 Returns the disassembler table name for this map.
695 """
696 sName = 'g_aDisas';
697 for sWord in self.sName.split('_'):
698 if sWord == 'm': # suffix indicating modrm.mod==mem
699 sName += '_m';
700 elif sWord == 'r': # suffix indicating modrm.mod==reg
701 sName += '_r';
702 elif len(sWord) == 2 and re.match('^[a-f0-9][a-f0-9]$', sWord):
703 sName += '_' + sWord;
704 else:
705 sWord = sWord.replace('grp', 'Grp');
706 sWord = sWord.replace('map', 'Map');
707 sName += sWord[0].upper() + sWord[1:];
708 return sName;
709
710
711 def isVexMap(self):
712 """ Returns True if a VEX map. """
713 return self.sEncoding.startswith('vex');
714
715
716class TestType(object):
717 """
718 Test value type.
719
720 This base class deals with integer like values. The fUnsigned constructor
721 parameter indicates the default stance on zero vs sign extending. It is
722 possible to override fUnsigned=True by prefixing the value with '+' or '-'.
723 """
724 def __init__(self, sName, acbSizes = None, fUnsigned = True):
725 self.sName = sName;
726 self.acbSizes = [1, 2, 4, 8, 16, 32] if acbSizes is None else acbSizes; # Normal sizes.
727 self.fUnsigned = fUnsigned;
728
729 class BadValue(Exception):
730 """ Bad value exception. """
731 def __init__(self, sMessage):
732 Exception.__init__(self, sMessage);
733 self.sMessage = sMessage;
734
735 ## For ascii ~ operator.
736 kdHexInv = {
737 '0': 'f',
738 '1': 'e',
739 '2': 'd',
740 '3': 'c',
741 '4': 'b',
742 '5': 'a',
743 '6': '9',
744 '7': '8',
745 '8': '7',
746 '9': '6',
747 'a': '5',
748 'b': '4',
749 'c': '3',
750 'd': '2',
751 'e': '1',
752 'f': '0',
753 };
754
755 def get(self, sValue):
756 """
757 Get the shortest normal sized byte representation of oValue.
758
759 Returns ((fSignExtend, bytearray), ) or ((fSignExtend, bytearray), (fSignExtend, bytearray), ).
760 The latter form is for AND+OR pairs where the first entry is what to
761 AND with the field and the second the one or OR with.
762
763 Raises BadValue if invalid value.
764 """
765 if not sValue:
766 raise TestType.BadValue('empty value');
767
768 # Deal with sign and detect hexadecimal or decimal.
769 fSignExtend = not self.fUnsigned;
770 if sValue[0] == '-' or sValue[0] == '+':
771 fSignExtend = True;
772 fHex = len(sValue) > 3 and sValue[1:3].lower() == '0x';
773 else:
774 fHex = len(sValue) > 2 and sValue[0:2].lower() == '0x';
775
776 # try convert it to long integer.
777 try:
778 iValue = long(sValue, 16 if fHex else 10);
779 except Exception as oXcpt:
780 raise TestType.BadValue('failed to convert "%s" to integer (%s)' % (sValue, oXcpt));
781
782 # Convert the hex string and pad it to a decent value. Negative values
783 # needs to be manually converted to something non-negative (~-n + 1).
784 if iValue >= 0:
785 sHex = hex(iValue);
786 if sys.version_info[0] < 3:
787 assert sHex[-1] == 'L';
788 sHex = sHex[:-1];
789 assert sHex[:2] == '0x';
790 sHex = sHex[2:];
791 else:
792 sHex = hex(-iValue - 1);
793 if sys.version_info[0] < 3:
794 assert sHex[-1] == 'L';
795 sHex = sHex[:-1];
796 assert sHex[:2] == '0x';
797 sHex = ''.join([self.kdHexInv[sDigit] for sDigit in sHex[2:]]);
798 if fSignExtend and sHex[0] not in [ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f']:
799 sHex = 'f' + sHex;
800
801 cDigits = len(sHex);
802 if cDigits <= self.acbSizes[-1] * 2:
803 for cb in self.acbSizes:
804 cNaturalDigits = cb * 2;
805 if cDigits <= cNaturalDigits:
806 break;
807 else:
808 cNaturalDigits = self.acbSizes[-1] * 2;
809 cNaturalDigits = int((cDigits + cNaturalDigits - 1) / cNaturalDigits) * cNaturalDigits;
810 assert isinstance(cNaturalDigits, int)
811
812 if cNaturalDigits != cDigits:
813 cNeeded = cNaturalDigits - cDigits;
814 if iValue >= 0:
815 sHex = ('0' * cNeeded) + sHex;
816 else:
817 sHex = ('f' * cNeeded) + sHex;
818
819 # Invert and convert to bytearray and return it.
820 abValue = bytearray([int(sHex[offHex - 2 : offHex], 16) for offHex in range(len(sHex), 0, -2)]);
821
822 return ((fSignExtend, abValue),);
823
824 def validate(self, sValue):
825 """
826 Returns True if value is okay, error message on failure.
827 """
828 try:
829 self.get(sValue);
830 except TestType.BadValue as oXcpt:
831 return oXcpt.sMessage;
832 return True;
833
834 def isAndOrPair(self, sValue):
835 """
836 Checks if sValue is a pair.
837 """
838 _ = sValue;
839 return False;
840
841
842class TestTypeEflags(TestType):
843 """
844 Special value parsing for EFLAGS/RFLAGS/FLAGS.
845 """
846
847 kdZeroValueFlags = { 'nv': 0, 'pl': 0, 'nz': 0, 'na': 0, 'pe': 0, 'nc': 0, 'di': 0, 'up': 0 };
848
849 def __init__(self, sName):
850 TestType.__init__(self, sName, acbSizes = [1, 2, 4, 8], fUnsigned = True);
851
852 def get(self, sValue):
853 fClear = 0;
854 fSet = 0;
855 for sFlag in sValue.split(','):
856 sConstant = g_kdEFlagsMnemonics.get(sFlag, None);
857 if sConstant is None:
858 raise self.BadValue('Unknown flag "%s" in "%s"' % (sFlag, sValue))
859 if sConstant[0] == '!':
860 fClear |= g_kdX86EFlagsConstants[sConstant[1:]];
861 else:
862 fSet |= g_kdX86EFlagsConstants[sConstant];
863
864 aoSet = TestType.get(self, '0x%x' % (fSet,));
865 if fClear != 0:
866 aoClear = TestType.get(self, '%#x' % (fClear,))
867 assert self.isAndOrPair(sValue) is True;
868 return (aoClear[0], aoSet[0]);
869 assert self.isAndOrPair(sValue) is False;
870 return aoSet;
871
872 def isAndOrPair(self, sValue):
873 for sZeroFlag in self.kdZeroValueFlags:
874 if sValue.find(sZeroFlag) >= 0:
875 return True;
876 return False;
877
878class TestTypeFromDict(TestType):
879 """
880 Special value parsing for CR0.
881 """
882
883 kdZeroValueFlags = { 'nv': 0, 'pl': 0, 'nz': 0, 'na': 0, 'pe': 0, 'nc': 0, 'di': 0, 'up': 0 };
884
885 def __init__(self, sName, kdConstantsAndValues, sConstantPrefix):
886 TestType.__init__(self, sName, acbSizes = [1, 2, 4, 8], fUnsigned = True);
887 self.kdConstantsAndValues = kdConstantsAndValues;
888 self.sConstantPrefix = sConstantPrefix;
889
890 def get(self, sValue):
891 fValue = 0;
892 for sFlag in sValue.split(','):
893 fFlagValue = self.kdConstantsAndValues.get(self.sConstantPrefix + sFlag.upper(), None);
894 if fFlagValue is None:
895 raise self.BadValue('Unknown flag "%s" in "%s"' % (sFlag, sValue))
896 fValue |= fFlagValue;
897 return TestType.get(self, '0x%x' % (fValue,));
898
899
900class TestInOut(object):
901 """
902 One input or output state modifier.
903
904 This should be thought as values to modify BS3REGCTX and extended (needs
905 to be structured) state.
906 """
907 ## Assigned operators.
908 kasOperators = [
909 '&|=', # Special AND(INV)+OR operator for use with EFLAGS.
910 '&~=',
911 '&=',
912 '|=',
913 '='
914 ];
915 ## Types
916 kdTypes = {
917 'uint': TestType('uint', fUnsigned = True),
918 'int': TestType('int'),
919 'efl': TestTypeEflags('efl'),
920 'cr0': TestTypeFromDict('cr0', g_kdX86Cr0Constants, 'X86_CR0_'),
921 'cr4': TestTypeFromDict('cr4', g_kdX86Cr4Constants, 'X86_CR4_'),
922 'xcr0': TestTypeFromDict('xcr0', g_kdX86XSaveCConstants, 'XSAVE_C_'),
923 };
924 ## CPU context fields.
925 kdFields = {
926 # name: ( default type, [both|input|output], )
927 # Operands.
928 'op1': ( 'uint', 'both', ), ## \@op1
929 'op2': ( 'uint', 'both', ), ## \@op2
930 'op3': ( 'uint', 'both', ), ## \@op3
931 'op4': ( 'uint', 'both', ), ## \@op4
932 # Flags.
933 'efl': ( 'efl', 'both', ),
934 'efl_undef': ( 'uint', 'output', ),
935 # 8-bit GPRs.
936 'al': ( 'uint', 'both', ),
937 'cl': ( 'uint', 'both', ),
938 'dl': ( 'uint', 'both', ),
939 'bl': ( 'uint', 'both', ),
940 'ah': ( 'uint', 'both', ),
941 'ch': ( 'uint', 'both', ),
942 'dh': ( 'uint', 'both', ),
943 'bh': ( 'uint', 'both', ),
944 'r8l': ( 'uint', 'both', ),
945 'r9l': ( 'uint', 'both', ),
946 'r10l': ( 'uint', 'both', ),
947 'r11l': ( 'uint', 'both', ),
948 'r12l': ( 'uint', 'both', ),
949 'r13l': ( 'uint', 'both', ),
950 'r14l': ( 'uint', 'both', ),
951 'r15l': ( 'uint', 'both', ),
952 # 16-bit GPRs.
953 'ax': ( 'uint', 'both', ),
954 'dx': ( 'uint', 'both', ),
955 'cx': ( 'uint', 'both', ),
956 'bx': ( 'uint', 'both', ),
957 'sp': ( 'uint', 'both', ),
958 'bp': ( 'uint', 'both', ),
959 'si': ( 'uint', 'both', ),
960 'di': ( 'uint', 'both', ),
961 'r8w': ( 'uint', 'both', ),
962 'r9w': ( 'uint', 'both', ),
963 'r10w': ( 'uint', 'both', ),
964 'r11w': ( 'uint', 'both', ),
965 'r12w': ( 'uint', 'both', ),
966 'r13w': ( 'uint', 'both', ),
967 'r14w': ( 'uint', 'both', ),
968 'r15w': ( 'uint', 'both', ),
969 # 32-bit GPRs.
970 'eax': ( 'uint', 'both', ),
971 'edx': ( 'uint', 'both', ),
972 'ecx': ( 'uint', 'both', ),
973 'ebx': ( 'uint', 'both', ),
974 'esp': ( 'uint', 'both', ),
975 'ebp': ( 'uint', 'both', ),
976 'esi': ( 'uint', 'both', ),
977 'edi': ( 'uint', 'both', ),
978 'r8d': ( 'uint', 'both', ),
979 'r9d': ( 'uint', 'both', ),
980 'r10d': ( 'uint', 'both', ),
981 'r11d': ( 'uint', 'both', ),
982 'r12d': ( 'uint', 'both', ),
983 'r13d': ( 'uint', 'both', ),
984 'r14d': ( 'uint', 'both', ),
985 'r15d': ( 'uint', 'both', ),
986 # 64-bit GPRs.
987 'rax': ( 'uint', 'both', ),
988 'rdx': ( 'uint', 'both', ),
989 'rcx': ( 'uint', 'both', ),
990 'rbx': ( 'uint', 'both', ),
991 'rsp': ( 'uint', 'both', ),
992 'rbp': ( 'uint', 'both', ),
993 'rsi': ( 'uint', 'both', ),
994 'rdi': ( 'uint', 'both', ),
995 'r8': ( 'uint', 'both', ),
996 'r9': ( 'uint', 'both', ),
997 'r10': ( 'uint', 'both', ),
998 'r11': ( 'uint', 'both', ),
999 'r12': ( 'uint', 'both', ),
1000 'r13': ( 'uint', 'both', ),
1001 'r14': ( 'uint', 'both', ),
1002 'r15': ( 'uint', 'both', ),
1003 # 16-bit, 32-bit or 64-bit registers according to operand size.
1004 'oz.rax': ( 'uint', 'both', ),
1005 'oz.rdx': ( 'uint', 'both', ),
1006 'oz.rcx': ( 'uint', 'both', ),
1007 'oz.rbx': ( 'uint', 'both', ),
1008 'oz.rsp': ( 'uint', 'both', ),
1009 'oz.rbp': ( 'uint', 'both', ),
1010 'oz.rsi': ( 'uint', 'both', ),
1011 'oz.rdi': ( 'uint', 'both', ),
1012 'oz.r8': ( 'uint', 'both', ),
1013 'oz.r9': ( 'uint', 'both', ),
1014 'oz.r10': ( 'uint', 'both', ),
1015 'oz.r11': ( 'uint', 'both', ),
1016 'oz.r12': ( 'uint', 'both', ),
1017 'oz.r13': ( 'uint', 'both', ),
1018 'oz.r14': ( 'uint', 'both', ),
1019 'oz.r15': ( 'uint', 'both', ),
1020 # Control registers.
1021 'cr0': ( 'cr0', 'both', ),
1022 'cr4': ( 'cr4', 'both', ),
1023 'xcr0': ( 'xcr0', 'both', ),
1024 # FPU Registers
1025 'fcw': ( 'uint', 'both', ),
1026 'fsw': ( 'uint', 'both', ),
1027 'ftw': ( 'uint', 'both', ),
1028 'fop': ( 'uint', 'both', ),
1029 'fpuip': ( 'uint', 'both', ),
1030 'fpucs': ( 'uint', 'both', ),
1031 'fpudp': ( 'uint', 'both', ),
1032 'fpuds': ( 'uint', 'both', ),
1033 'mxcsr': ( 'uint', 'both', ),
1034 'st0': ( 'uint', 'both', ),
1035 'st1': ( 'uint', 'both', ),
1036 'st2': ( 'uint', 'both', ),
1037 'st3': ( 'uint', 'both', ),
1038 'st4': ( 'uint', 'both', ),
1039 'st5': ( 'uint', 'both', ),
1040 'st6': ( 'uint', 'both', ),
1041 'st7': ( 'uint', 'both', ),
1042 # MMX registers.
1043 'mm0': ( 'uint', 'both', ),
1044 'mm1': ( 'uint', 'both', ),
1045 'mm2': ( 'uint', 'both', ),
1046 'mm3': ( 'uint', 'both', ),
1047 'mm4': ( 'uint', 'both', ),
1048 'mm5': ( 'uint', 'both', ),
1049 'mm6': ( 'uint', 'both', ),
1050 'mm7': ( 'uint', 'both', ),
1051 # SSE registers.
1052 'xmm0': ( 'uint', 'both', ),
1053 'xmm1': ( 'uint', 'both', ),
1054 'xmm2': ( 'uint', 'both', ),
1055 'xmm3': ( 'uint', 'both', ),
1056 'xmm4': ( 'uint', 'both', ),
1057 'xmm5': ( 'uint', 'both', ),
1058 'xmm6': ( 'uint', 'both', ),
1059 'xmm7': ( 'uint', 'both', ),
1060 'xmm8': ( 'uint', 'both', ),
1061 'xmm9': ( 'uint', 'both', ),
1062 'xmm10': ( 'uint', 'both', ),
1063 'xmm11': ( 'uint', 'both', ),
1064 'xmm12': ( 'uint', 'both', ),
1065 'xmm13': ( 'uint', 'both', ),
1066 'xmm14': ( 'uint', 'both', ),
1067 'xmm15': ( 'uint', 'both', ),
1068 'xmm0.lo': ( 'uint', 'both', ),
1069 'xmm1.lo': ( 'uint', 'both', ),
1070 'xmm2.lo': ( 'uint', 'both', ),
1071 'xmm3.lo': ( 'uint', 'both', ),
1072 'xmm4.lo': ( 'uint', 'both', ),
1073 'xmm5.lo': ( 'uint', 'both', ),
1074 'xmm6.lo': ( 'uint', 'both', ),
1075 'xmm7.lo': ( 'uint', 'both', ),
1076 'xmm8.lo': ( 'uint', 'both', ),
1077 'xmm9.lo': ( 'uint', 'both', ),
1078 'xmm10.lo': ( 'uint', 'both', ),
1079 'xmm11.lo': ( 'uint', 'both', ),
1080 'xmm12.lo': ( 'uint', 'both', ),
1081 'xmm13.lo': ( 'uint', 'both', ),
1082 'xmm14.lo': ( 'uint', 'both', ),
1083 'xmm15.lo': ( 'uint', 'both', ),
1084 'xmm0.hi': ( 'uint', 'both', ),
1085 'xmm1.hi': ( 'uint', 'both', ),
1086 'xmm2.hi': ( 'uint', 'both', ),
1087 'xmm3.hi': ( 'uint', 'both', ),
1088 'xmm4.hi': ( 'uint', 'both', ),
1089 'xmm5.hi': ( 'uint', 'both', ),
1090 'xmm6.hi': ( 'uint', 'both', ),
1091 'xmm7.hi': ( 'uint', 'both', ),
1092 'xmm8.hi': ( 'uint', 'both', ),
1093 'xmm9.hi': ( 'uint', 'both', ),
1094 'xmm10.hi': ( 'uint', 'both', ),
1095 'xmm11.hi': ( 'uint', 'both', ),
1096 'xmm12.hi': ( 'uint', 'both', ),
1097 'xmm13.hi': ( 'uint', 'both', ),
1098 'xmm14.hi': ( 'uint', 'both', ),
1099 'xmm15.hi': ( 'uint', 'both', ),
1100 'xmm0.lo.zx': ( 'uint', 'both', ),
1101 'xmm1.lo.zx': ( 'uint', 'both', ),
1102 'xmm2.lo.zx': ( 'uint', 'both', ),
1103 'xmm3.lo.zx': ( 'uint', 'both', ),
1104 'xmm4.lo.zx': ( 'uint', 'both', ),
1105 'xmm5.lo.zx': ( 'uint', 'both', ),
1106 'xmm6.lo.zx': ( 'uint', 'both', ),
1107 'xmm7.lo.zx': ( 'uint', 'both', ),
1108 'xmm8.lo.zx': ( 'uint', 'both', ),
1109 'xmm9.lo.zx': ( 'uint', 'both', ),
1110 'xmm10.lo.zx': ( 'uint', 'both', ),
1111 'xmm11.lo.zx': ( 'uint', 'both', ),
1112 'xmm12.lo.zx': ( 'uint', 'both', ),
1113 'xmm13.lo.zx': ( 'uint', 'both', ),
1114 'xmm14.lo.zx': ( 'uint', 'both', ),
1115 'xmm15.lo.zx': ( 'uint', 'both', ),
1116 'xmm0.dw0': ( 'uint', 'both', ),
1117 'xmm1.dw0': ( 'uint', 'both', ),
1118 'xmm2.dw0': ( 'uint', 'both', ),
1119 'xmm3.dw0': ( 'uint', 'both', ),
1120 'xmm4.dw0': ( 'uint', 'both', ),
1121 'xmm5.dw0': ( 'uint', 'both', ),
1122 'xmm6.dw0': ( 'uint', 'both', ),
1123 'xmm7.dw0': ( 'uint', 'both', ),
1124 'xmm8.dw0': ( 'uint', 'both', ),
1125 'xmm9.dw0': ( 'uint', 'both', ),
1126 'xmm10.dw0': ( 'uint', 'both', ),
1127 'xmm11.dw0': ( 'uint', 'both', ),
1128 'xmm12.dw0': ( 'uint', 'both', ),
1129 'xmm13.dw0': ( 'uint', 'both', ),
1130 'xmm14.dw0': ( 'uint', 'both', ),
1131 'xmm15_dw0': ( 'uint', 'both', ),
1132 # AVX registers.
1133 'ymm0': ( 'uint', 'both', ),
1134 'ymm1': ( 'uint', 'both', ),
1135 'ymm2': ( 'uint', 'both', ),
1136 'ymm3': ( 'uint', 'both', ),
1137 'ymm4': ( 'uint', 'both', ),
1138 'ymm5': ( 'uint', 'both', ),
1139 'ymm6': ( 'uint', 'both', ),
1140 'ymm7': ( 'uint', 'both', ),
1141 'ymm8': ( 'uint', 'both', ),
1142 'ymm9': ( 'uint', 'both', ),
1143 'ymm10': ( 'uint', 'both', ),
1144 'ymm11': ( 'uint', 'both', ),
1145 'ymm12': ( 'uint', 'both', ),
1146 'ymm13': ( 'uint', 'both', ),
1147 'ymm14': ( 'uint', 'both', ),
1148 'ymm15': ( 'uint', 'both', ),
1149
1150 # Special ones.
1151 'value.xcpt': ( 'uint', 'output', ),
1152 };
1153
1154 def __init__(self, sField, sOp, sValue, sType):
1155 assert sField in self.kdFields;
1156 assert sOp in self.kasOperators;
1157 self.sField = sField;
1158 self.sOp = sOp;
1159 self.sValue = sValue;
1160 self.sType = sType;
1161 assert isinstance(sField, str);
1162 assert isinstance(sOp, str);
1163 assert isinstance(sType, str);
1164 assert isinstance(sValue, str);
1165
1166
1167class TestSelector(object):
1168 """
1169 One selector for an instruction test.
1170 """
1171 ## Selector compare operators.
1172 kasCompareOps = [ '==', '!=' ];
1173 ## Selector variables and their valid values.
1174 kdVariables = {
1175 # Operand size.
1176 'size': {
1177 'o16': 'size_o16',
1178 'o32': 'size_o32',
1179 'o64': 'size_o64',
1180 },
1181 # VEX.L value.
1182 'vex.l': {
1183 '0': 'vexl_0',
1184 '1': 'vexl_1',
1185 },
1186 # Execution ring.
1187 'ring': {
1188 '0': 'ring_0',
1189 '1': 'ring_1',
1190 '2': 'ring_2',
1191 '3': 'ring_3',
1192 '0..2': 'ring_0_thru_2',
1193 '1..3': 'ring_1_thru_3',
1194 },
1195 # Basic code mode.
1196 'codebits': {
1197 '64': 'code_64bit',
1198 '32': 'code_32bit',
1199 '16': 'code_16bit',
1200 },
1201 # cpu modes.
1202 'mode': {
1203 'real': 'mode_real',
1204 'prot': 'mode_prot',
1205 'long': 'mode_long',
1206 'v86': 'mode_v86',
1207 'smm': 'mode_smm',
1208 'vmx': 'mode_vmx',
1209 'svm': 'mode_svm',
1210 },
1211 # paging on/off
1212 'paging': {
1213 'on': 'paging_on',
1214 'off': 'paging_off',
1215 },
1216 # CPU vendor
1217 'vendor': {
1218 'amd': 'vendor_amd',
1219 'intel': 'vendor_intel',
1220 'via': 'vendor_via',
1221 },
1222 };
1223 ## Selector shorthand predicates.
1224 ## These translates into variable expressions.
1225 kdPredicates = {
1226 'o16': 'size==o16',
1227 'o32': 'size==o32',
1228 'o64': 'size==o64',
1229 'ring0': 'ring==0',
1230 '!ring0': 'ring==1..3',
1231 'ring1': 'ring==1',
1232 'ring2': 'ring==2',
1233 'ring3': 'ring==3',
1234 'user': 'ring==3',
1235 'supervisor': 'ring==0..2',
1236 '16-bit': 'codebits==16',
1237 '32-bit': 'codebits==32',
1238 '64-bit': 'codebits==64',
1239 'real': 'mode==real',
1240 'prot': 'mode==prot',
1241 'long': 'mode==long',
1242 'v86': 'mode==v86',
1243 'smm': 'mode==smm',
1244 'vmx': 'mode==vmx',
1245 'svm': 'mode==svm',
1246 'paging': 'paging==on',
1247 '!paging': 'paging==off',
1248 'amd': 'vendor==amd',
1249 '!amd': 'vendor!=amd',
1250 'intel': 'vendor==intel',
1251 '!intel': 'vendor!=intel',
1252 'via': 'vendor==via',
1253 '!via': 'vendor!=via',
1254 };
1255
1256 def __init__(self, sVariable, sOp, sValue):
1257 assert sVariable in self.kdVariables;
1258 assert sOp in self.kasCompareOps;
1259 assert sValue in self.kdVariables[sVariable];
1260 self.sVariable = sVariable;
1261 self.sOp = sOp;
1262 self.sValue = sValue;
1263
1264
1265class InstructionTest(object):
1266 """
1267 Instruction test.
1268 """
1269
1270 def __init__(self, oInstr): # type: (InstructionTest, Instruction)
1271 self.oInstr = oInstr; # type: InstructionTest
1272 self.aoInputs = []; # type: list(TestInOut)
1273 self.aoOutputs = []; # type: list(TestInOut)
1274 self.aoSelectors = []; # type: list(TestSelector)
1275
1276 def toString(self, fRepr = False):
1277 """
1278 Converts it to string representation.
1279 """
1280 asWords = [];
1281 if self.aoSelectors:
1282 for oSelector in self.aoSelectors:
1283 asWords.append('%s%s%s' % (oSelector.sVariable, oSelector.sOp, oSelector.sValue,));
1284 asWords.append('/');
1285
1286 for oModifier in self.aoInputs:
1287 asWords.append('%s%s%s:%s' % (oModifier.sField, oModifier.sOp, oModifier.sValue, oModifier.sType,));
1288
1289 asWords.append('->');
1290
1291 for oModifier in self.aoOutputs:
1292 asWords.append('%s%s%s:%s' % (oModifier.sField, oModifier.sOp, oModifier.sValue, oModifier.sType,));
1293
1294 if fRepr:
1295 return '<' + ' '.join(asWords) + '>';
1296 return ' '.join(asWords);
1297
1298 def __str__(self):
1299 """ Provide string represenation. """
1300 return self.toString(False);
1301
1302 def __repr__(self):
1303 """ Provide unambigious string representation. """
1304 return self.toString(True);
1305
1306class Operand(object):
1307 """
1308 Instruction operand.
1309 """
1310
1311 def __init__(self, sWhere, sType):
1312 assert sWhere in g_kdOpLocations, sWhere;
1313 assert sType in g_kdOpTypes, sType;
1314 self.sWhere = sWhere; ##< g_kdOpLocations
1315 self.sType = sType; ##< g_kdOpTypes
1316
1317 def usesModRM(self):
1318 """ Returns True if using some form of ModR/M encoding. """
1319 return self.sType[0] in ['E', 'G', 'M'];
1320
1321
1322
1323class Instruction(object): # pylint: disable=too-many-instance-attributes
1324 """
1325 Instruction.
1326 """
1327
1328 def __init__(self, sSrcFile, iLine):
1329 ## @name Core attributes.
1330 ## @{
1331 self.sMnemonic = None;
1332 self.sBrief = None;
1333 self.asDescSections = []; # type: list(str)
1334 self.aoMaps = []; # type: list(InstructionMap)
1335 self.aoOperands = []; # type: list(Operand)
1336 self.sPrefix = None; ##< Single prefix: None, 'none', 0x66, 0xf3, 0xf2
1337 self.sOpcode = None; # type: str
1338 self.sSubOpcode = None; # type: str
1339 self.sEncoding = None;
1340 self.asFlTest = None;
1341 self.asFlModify = None;
1342 self.asFlUndefined = None;
1343 self.asFlSet = None;
1344 self.asFlClear = None;
1345 self.dHints = {}; ##< Dictionary of instruction hints, flags, whatnot. (Dictionary for speed; dummy value).
1346 self.sDisEnum = None; ##< OP_XXXX value. Default is based on the uppercased mnemonic.
1347 self.asCpuIds = []; ##< The CPUID feature bit names for this instruction. If multiple, assume AND.
1348 self.asReqFeatures = []; ##< Which features are required to be enabled to run this instruction.
1349 self.aoTests = []; # type: list(InstructionTest)
1350 self.sMinCpu = None; ##< Indicates the minimum CPU required for the instruction. Not set when oCpuExpr is.
1351 self.oCpuExpr = None; ##< Some CPU restriction expression...
1352 self.sGroup = None;
1353 self.fUnused = False; ##< Unused instruction.
1354 self.fInvalid = False; ##< Invalid instruction (like UD2).
1355 self.sInvalidStyle = None; ##< Invalid behviour style (g_kdInvalidStyles),
1356 self.sXcptType = None; ##< Exception type (g_kdXcptTypes).
1357 ## @}
1358
1359 ## @name Implementation attributes.
1360 ## @{
1361 self.sStats = None;
1362 self.sFunction = None;
1363 self.fStub = False;
1364 self.fUdStub = False;
1365 ## @}
1366
1367 ## @name Decoding info
1368 ## @{
1369 self.sSrcFile = sSrcFile;
1370 self.iLineCreated = iLine;
1371 self.iLineCompleted = None;
1372 self.cOpTags = 0;
1373 self.iLineFnIemOpMacro = -1;
1374 self.iLineMnemonicMacro = -1;
1375 ## @}
1376
1377 ## @name Intermediate input fields.
1378 ## @{
1379 self.sRawDisOpNo = None;
1380 self.asRawDisParams = [];
1381 self.sRawIemOpFlags = None;
1382 self.sRawOldOpcodes = None;
1383 self.asCopyTests = [];
1384 ## @}
1385
1386 def toString(self, fRepr = False):
1387 """ Turn object into a string. """
1388 aasFields = [];
1389
1390 aasFields.append(['opcode', self.sOpcode]);
1391 aasFields.append(['mnemonic', self.sMnemonic]);
1392 for iOperand, oOperand in enumerate(self.aoOperands):
1393 aasFields.append(['op%u' % (iOperand + 1,), '%s:%s' % (oOperand.sWhere, oOperand.sType,)]);
1394 if self.aoMaps: aasFields.append(['maps', ','.join([oMap.sName for oMap in self.aoMaps])]);
1395 aasFields.append(['encoding', self.sEncoding]);
1396 if self.dHints: aasFields.append(['hints', ','.join(self.dHints.keys())]);
1397 aasFields.append(['disenum', self.sDisEnum]);
1398 if self.asCpuIds: aasFields.append(['cpuid', ','.join(self.asCpuIds)]);
1399 aasFields.append(['group', self.sGroup]);
1400 if self.fUnused: aasFields.append(['unused', 'True']);
1401 if self.fInvalid: aasFields.append(['invalid', 'True']);
1402 aasFields.append(['invlstyle', self.sInvalidStyle]);
1403 aasFields.append(['fltest', self.asFlTest]);
1404 aasFields.append(['flmodify', self.asFlModify]);
1405 aasFields.append(['flundef', self.asFlUndefined]);
1406 aasFields.append(['flset', self.asFlSet]);
1407 aasFields.append(['flclear', self.asFlClear]);
1408 aasFields.append(['mincpu', self.sMinCpu]);
1409 aasFields.append(['stats', self.sStats]);
1410 aasFields.append(['sFunction', self.sFunction]);
1411 if self.fStub: aasFields.append(['fStub', 'True']);
1412 if self.fUdStub: aasFields.append(['fUdStub', 'True']);
1413 if self.cOpTags: aasFields.append(['optags', str(self.cOpTags)]);
1414 if self.iLineFnIemOpMacro != -1: aasFields.append(['FNIEMOP_XXX', str(self.iLineFnIemOpMacro)]);
1415 if self.iLineMnemonicMacro != -1: aasFields.append(['IEMOP_MNEMMONICn', str(self.iLineMnemonicMacro)]);
1416
1417 sRet = '<' if fRepr else '';
1418 for sField, sValue in aasFields:
1419 if sValue != None:
1420 if len(sRet) > 1:
1421 sRet += '; ';
1422 sRet += '%s=%s' % (sField, sValue,);
1423 if fRepr:
1424 sRet += '>';
1425
1426 return sRet;
1427
1428 def __str__(self):
1429 """ Provide string represenation. """
1430 return self.toString(False);
1431
1432 def __repr__(self):
1433 """ Provide unambigious string representation. """
1434 return self.toString(True);
1435
1436 def getOpcodeByte(self):
1437 """
1438 Decodes sOpcode into a byte range integer value.
1439 Raises exception if sOpcode is None or invalid.
1440 """
1441 if self.sOpcode is None:
1442 raise Exception('No opcode byte for %s!' % (self,));
1443 sOpcode = str(self.sOpcode); # pylint type confusion workaround.
1444
1445 # Full hex byte form.
1446 if sOpcode[:2] == '0x':
1447 return int(sOpcode, 16);
1448
1449 # The /r form:
1450 if len(sOpcode) == 4 and sOpcode.startswith('/') and sOpcode[-1].isdigit():
1451 return int(sOpcode[-1:]) << 3;
1452
1453 # The 11/r form:
1454 if len(sOpcode) == 4 and sOpcode.startswith('11/') and sOpcode[-1].isdigit():
1455 return (int(sOpcode[-1:]) << 3) | 0xc0;
1456
1457 # The !11/r form (returns mod=1):
1458 ## @todo this doesn't really work...
1459 if len(sOpcode) == 5 and sOpcode.startswith('!11/') and sOpcode[-1].isdigit():
1460 return (int(sOpcode[-1:]) << 3) | 0x80;
1461
1462 raise Exception('unsupported opcode byte spec "%s" for %s' % (sOpcode, self,));
1463
1464 @staticmethod
1465 def _flagsToIntegerMask(asFlags):
1466 """
1467 Returns the integer mask value for asFlags.
1468 """
1469 uRet = 0;
1470 if asFlags:
1471 for sFlag in asFlags:
1472 sConstant = g_kdEFlagsMnemonics[sFlag];
1473 assert sConstant[0] != '!', sConstant
1474 uRet |= g_kdX86EFlagsConstants[sConstant];
1475 return uRet;
1476
1477 def getTestedFlagsMask(self):
1478 """ Returns asFlTest into a integer mask value """
1479 return self._flagsToIntegerMask(self.asFlTest);
1480
1481 def getModifiedFlagsMask(self):
1482 """ Returns asFlModify into a integer mask value """
1483 return self._flagsToIntegerMask(self.asFlModify);
1484
1485 def getUndefinedFlagsMask(self):
1486 """ Returns asFlUndefined into a integer mask value """
1487 return self._flagsToIntegerMask(self.asFlUndefined);
1488
1489 def getSetFlagsMask(self):
1490 """ Returns asFlSet into a integer mask value """
1491 return self._flagsToIntegerMask(self.asFlSet);
1492
1493 def getClearedFlagsMask(self):
1494 """ Returns asFlClear into a integer mask value """
1495 return self._flagsToIntegerMask(self.asFlClear);
1496
1497 def onlyInVexMaps(self):
1498 """ Returns True if only in VEX maps, otherwise False. (No maps -> False) """
1499 if not self.aoMaps:
1500 return False;
1501 for oMap in self.aoMaps:
1502 if not oMap.isVexMap():
1503 return False;
1504 return True;
1505
1506
1507
1508## All the instructions.
1509g_aoAllInstructions = []; # type: list(Instruction)
1510
1511## All the instructions indexed by statistics name (opstat).
1512g_dAllInstructionsByStat = {}; # type: dict(Instruction)
1513
1514## All the instructions indexed by function name (opfunction).
1515g_dAllInstructionsByFunction = {}; # type: dict(list(Instruction))
1516
1517## Instructions tagged by oponlytest
1518g_aoOnlyTestInstructions = []; # type: list(Instruction)
1519
1520## Instruction maps.
1521g_dInstructionMaps = {
1522 'one': InstructionMap('one'),
1523 'grp1_80': InstructionMap('grp1_80', asLeadOpcodes = ['0x80',]),
1524 'grp1_81': InstructionMap('grp1_81', asLeadOpcodes = ['0x81',], sSelector = '/r'),
1525 'grp1_82': InstructionMap('grp1_82', asLeadOpcodes = ['0x82',], sSelector = '/r'),
1526 'grp1_83': InstructionMap('grp1_83', asLeadOpcodes = ['0x83',], sSelector = '/r'),
1527 'grp1a': InstructionMap('grp1a', asLeadOpcodes = ['0x8f',], sSelector = '/r'),
1528 'grp2_c0': InstructionMap('grp2_c0', asLeadOpcodes = ['0xc0',], sSelector = '/r'),
1529 'grp2_c1': InstructionMap('grp2_c1', asLeadOpcodes = ['0xc1',], sSelector = '/r'),
1530 'grp2_d0': InstructionMap('grp2_d0', asLeadOpcodes = ['0xd0',], sSelector = '/r'),
1531 'grp2_d1': InstructionMap('grp2_d1', asLeadOpcodes = ['0xd1',], sSelector = '/r'),
1532 'grp2_d2': InstructionMap('grp2_d2', asLeadOpcodes = ['0xd2',], sSelector = '/r'),
1533 'grp2_d3': InstructionMap('grp2_d3', asLeadOpcodes = ['0xd3',], sSelector = '/r'),
1534 'grp3_f6': InstructionMap('grp3_f6', asLeadOpcodes = ['0xf6',], sSelector = '/r'),
1535 'grp3_f7': InstructionMap('grp3_f7', asLeadOpcodes = ['0xf7',], sSelector = '/r'),
1536 'grp4': InstructionMap('grp4', asLeadOpcodes = ['0xfe',], sSelector = '/r'),
1537 'grp5': InstructionMap('grp5', asLeadOpcodes = ['0xff',], sSelector = '/r'),
1538 'grp11_c6_m': InstructionMap('grp11_c6_m',asLeadOpcodes = ['0xc6',], sSelector = '!11 /r'),
1539 'grp11_c6_r': InstructionMap('grp11_c6_r',asLeadOpcodes = ['0xc6',], sSelector = '11'), # xabort
1540 'grp11_c7_m': InstructionMap('grp11_c7_m',asLeadOpcodes = ['0xc7',], sSelector = '!11 /r'),
1541 'grp11_c7_r': InstructionMap('grp11_c7_r',asLeadOpcodes = ['0xc7',], sSelector = '11'), # xbegin
1542
1543 'two0f': InstructionMap('two0f', asLeadOpcodes = ['0x0f',], sDisParse = 'IDX_ParseTwoByteEsc'),
1544 'grp6': InstructionMap('grp6', asLeadOpcodes = ['0x0f', '0x00',], sSelector = '/r'),
1545 'grp7_m': InstructionMap('grp7_m', asLeadOpcodes = ['0x0f', '0x01',], sSelector = '!11 /r'),
1546 'grp7_r': InstructionMap('grp7_r', asLeadOpcodes = ['0x0f', '0x01',], sSelector = '11'),
1547 'grp8': InstructionMap('grp8', asLeadOpcodes = ['0x0f', '0xba',], sSelector = '/r'),
1548 'grp9': InstructionMap('grp9', asLeadOpcodes = ['0x0f', '0xc7',], sSelector = 'mod /r'),
1549 'grp10': InstructionMap('grp10', asLeadOpcodes = ['0x0f', '0xb9',], sSelector = '/r'), # UD1 /w modr/m
1550 'grp12': InstructionMap('grp12', asLeadOpcodes = ['0x0f', '0x71',], sSelector = 'mod /r'),
1551 'grp13': InstructionMap('grp13', asLeadOpcodes = ['0x0f', '0x72',], sSelector = 'mod /r'),
1552 'grp14': InstructionMap('grp14', asLeadOpcodes = ['0x0f', '0x73',], sSelector = 'mod /r'),
1553 'grp15': InstructionMap('grp15', asLeadOpcodes = ['0x0f', '0xae',], sSelector = 'memreg /r'),
1554 'grp16': InstructionMap('grp16', asLeadOpcodes = ['0x0f', '0x18',], sSelector = 'mod /r'),
1555 'grpA17': InstructionMap('grpA17', asLeadOpcodes = ['0x0f', '0x78',], sSelector = '/r'), # AMD: EXTRQ weirdness
1556 'grpP': InstructionMap('grpP', asLeadOpcodes = ['0x0f', '0x0d',], sSelector = '/r'), # AMD: prefetch
1557
1558 'three0f38': InstructionMap('three0f38', asLeadOpcodes = ['0x0f', '0x38',]),
1559 'three0f3a': InstructionMap('three0f3a', asLeadOpcodes = ['0x0f', '0x3a',]),
1560
1561 'vexmap1': InstructionMap('vexmap1', sEncoding = 'vex1'),
1562 'vexgrp12': InstructionMap('vexgrp12', sEncoding = 'vex1', asLeadOpcodes = ['0x71',], sSelector = 'mod /r'),
1563 'vexgrp13': InstructionMap('vexgrp13', sEncoding = 'vex1', asLeadOpcodes = ['0x72',], sSelector = 'mod /r'),
1564 'vexgrp14': InstructionMap('vexgrp14', sEncoding = 'vex1', asLeadOpcodes = ['0x73',], sSelector = 'mod /r'),
1565 'vexgrp15': InstructionMap('vexgrp15', sEncoding = 'vex1', asLeadOpcodes = ['0xae',], sSelector = 'memreg /r'),
1566 'vexgrp17': InstructionMap('vexgrp17', sEncoding = 'vex1', asLeadOpcodes = ['0xf3',], sSelector = '/r'),
1567
1568 'vexmap2': InstructionMap('vexmap2', sEncoding = 'vex2'),
1569 'vexmap3': InstructionMap('vexmap3', sEncoding = 'vex3'),
1570
1571 '3dnow': InstructionMap('3dnow', asLeadOpcodes = ['0x0f', '0x0f',]),
1572 'xopmap8': InstructionMap('xopmap8', sEncoding = 'xop8'),
1573 'xopmap9': InstructionMap('xopmap9', sEncoding = 'xop9'),
1574 'xopgrp1': InstructionMap('xopgrp1', sEncoding = 'xop9', asLeadOpcodes = ['0x01'], sSelector = '/r'),
1575 'xopgrp2': InstructionMap('xopgrp2', sEncoding = 'xop9', asLeadOpcodes = ['0x02'], sSelector = '/r'),
1576 'xopgrp3': InstructionMap('xopgrp3', sEncoding = 'xop9', asLeadOpcodes = ['0x12'], sSelector = '/r'),
1577 'xopmap10': InstructionMap('xopmap10', sEncoding = 'xop10'),
1578 'xopgrp4': InstructionMap('xopgrp4', sEncoding = 'xop10', asLeadOpcodes = ['0x12'], sSelector = '/r'),
1579};
1580
1581
1582
1583class ParserException(Exception):
1584 """ Parser exception """
1585 def __init__(self, sMessage):
1586 Exception.__init__(self, sMessage);
1587
1588
1589class SimpleParser(object):
1590 """
1591 Parser of IEMAllInstruction*.cpp.h instruction specifications.
1592 """
1593
1594 ## @name Parser state.
1595 ## @{
1596 kiCode = 0;
1597 kiCommentMulti = 1;
1598 ## @}
1599
1600 def __init__(self, sSrcFile, asLines, sDefaultMap):
1601 self.sSrcFile = sSrcFile;
1602 self.asLines = asLines;
1603 self.iLine = 0;
1604 self.iState = self.kiCode;
1605 self.sComment = '';
1606 self.iCommentLine = 0;
1607 self.aoCurInstrs = [];
1608
1609 assert sDefaultMap in g_dInstructionMaps;
1610 self.oDefaultMap = g_dInstructionMaps[sDefaultMap];
1611
1612 self.cTotalInstr = 0;
1613 self.cTotalStubs = 0;
1614 self.cTotalTagged = 0;
1615
1616 self.oReMacroName = re.compile('^[A-Za-z_][A-Za-z0-9_]*$');
1617 self.oReMnemonic = re.compile('^[A-Za-z_][A-Za-z0-9_]*$');
1618 self.oReStatsName = re.compile('^[A-Za-z_][A-Za-z0-9_]*$');
1619 self.oReFunctionName= re.compile('^iemOp_[A-Za-z_][A-Za-z0-9_]*$');
1620 self.oReGroupName = re.compile('^og_[a-z0-9]+(|_[a-z0-9]+|_[a-z0-9]+_[a-z0-9]+)$');
1621 self.oReDisEnum = re.compile('^OP_[A-Z0-9_]+$');
1622 self.fDebug = True;
1623
1624 self.dTagHandlers = {
1625 '@opbrief': self.parseTagOpBrief,
1626 '@opdesc': self.parseTagOpDesc,
1627 '@opmnemonic': self.parseTagOpMnemonic,
1628 '@op1': self.parseTagOpOperandN,
1629 '@op2': self.parseTagOpOperandN,
1630 '@op3': self.parseTagOpOperandN,
1631 '@op4': self.parseTagOpOperandN,
1632 '@oppfx': self.parseTagOpPfx,
1633 '@opmaps': self.parseTagOpMaps,
1634 '@opcode': self.parseTagOpcode,
1635 '@opcodesub': self.parseTagOpcodeSub,
1636 '@openc': self.parseTagOpEnc,
1637 '@opfltest': self.parseTagOpEFlags,
1638 '@opflmodify': self.parseTagOpEFlags,
1639 '@opflundef': self.parseTagOpEFlags,
1640 '@opflset': self.parseTagOpEFlags,
1641 '@opflclear': self.parseTagOpEFlags,
1642 '@ophints': self.parseTagOpHints,
1643 '@opdisenum': self.parseTagOpDisEnum,
1644 '@opmincpu': self.parseTagOpMinCpu,
1645 '@opcpuid': self.parseTagOpCpuId,
1646 '@opgroup': self.parseTagOpGroup,
1647 '@opunused': self.parseTagOpUnusedInvalid,
1648 '@opinvalid': self.parseTagOpUnusedInvalid,
1649 '@opinvlstyle': self.parseTagOpUnusedInvalid,
1650 '@optest': self.parseTagOpTest,
1651 '@optestign': self.parseTagOpTestIgnore,
1652 '@optestignore': self.parseTagOpTestIgnore,
1653 '@opcopytests': self.parseTagOpCopyTests,
1654 '@oponly': self.parseTagOpOnlyTest,
1655 '@oponlytest': self.parseTagOpOnlyTest,
1656 '@opxcpttype': self.parseTagOpXcptType,
1657 '@opstats': self.parseTagOpStats,
1658 '@opfunction': self.parseTagOpFunction,
1659 '@opdone': self.parseTagOpDone,
1660 };
1661 for i in range(48):
1662 self.dTagHandlers['@optest%u' % (i,)] = self.parseTagOpTestNum;
1663 self.dTagHandlers['@optest[%u]' % (i,)] = self.parseTagOpTestNum;
1664
1665 self.asErrors = [];
1666
1667 def raiseError(self, sMessage):
1668 """
1669 Raise error prefixed with the source and line number.
1670 """
1671 raise ParserException("%s:%d: error: %s" % (self.sSrcFile, self.iLine, sMessage,));
1672
1673 def raiseCommentError(self, iLineInComment, sMessage):
1674 """
1675 Similar to raiseError, but the line number is iLineInComment + self.iCommentLine.
1676 """
1677 raise ParserException("%s:%d: error: %s" % (self.sSrcFile, self.iCommentLine + iLineInComment, sMessage,));
1678
1679 def error(self, sMessage):
1680 """
1681 Adds an error.
1682 returns False;
1683 """
1684 self.asErrors.append(u'%s:%d: error: %s\n' % (self.sSrcFile, self.iLine, sMessage,));
1685 return False;
1686
1687 def errorComment(self, iLineInComment, sMessage):
1688 """
1689 Adds a comment error.
1690 returns False;
1691 """
1692 self.asErrors.append(u'%s:%d: error: %s\n' % (self.sSrcFile, self.iCommentLine + iLineInComment, sMessage,));
1693 return False;
1694
1695 def printErrors(self):
1696 """
1697 Print the errors to stderr.
1698 Returns number of errors.
1699 """
1700 if self.asErrors:
1701 sys.stderr.write(u''.join(self.asErrors));
1702 return len(self.asErrors);
1703
1704 def debug(self, sMessage):
1705 """
1706 For debugging.
1707 """
1708 if self.fDebug:
1709 print('debug: %s' % (sMessage,));
1710
1711
1712 def addInstruction(self, iLine = None):
1713 """
1714 Adds an instruction.
1715 """
1716 oInstr = Instruction(self.sSrcFile, self.iLine if iLine is None else iLine);
1717 g_aoAllInstructions.append(oInstr);
1718 self.aoCurInstrs.append(oInstr);
1719 return oInstr;
1720
1721 def deriveMnemonicAndOperandsFromStats(self, oInstr, sStats):
1722 """
1723 Derives the mnemonic and operands from a IEM stats base name like string.
1724 """
1725 if oInstr.sMnemonic is None:
1726 asWords = sStats.split('_');
1727 oInstr.sMnemonic = asWords[0].lower();
1728 if len(asWords) > 1 and not oInstr.aoOperands:
1729 for sType in asWords[1:]:
1730 if sType in g_kdOpTypes:
1731 oInstr.aoOperands.append(Operand(g_kdOpTypes[sType][1], sType));
1732 else:
1733 #return self.error('unknown operand type: %s (instruction: %s)' % (sType, oInstr))
1734 return False;
1735 return True;
1736
1737 def doneInstructionOne(self, oInstr, iLine):
1738 """
1739 Complete the parsing by processing, validating and expanding raw inputs.
1740 """
1741 assert oInstr.iLineCompleted is None;
1742 oInstr.iLineCompleted = iLine;
1743
1744 #
1745 # Specified instructions.
1746 #
1747 if oInstr.cOpTags > 0:
1748 if oInstr.sStats is None:
1749 pass;
1750
1751 #
1752 # Unspecified legacy stuff. We generally only got a few things to go on here.
1753 # /** Opcode 0x0f 0x00 /0. */
1754 # FNIEMOPRM_DEF(iemOp_Grp6_sldt)
1755 #
1756 else:
1757 #if oInstr.sRawOldOpcodes:
1758 #
1759 #if oInstr.sMnemonic:
1760 pass;
1761
1762 #
1763 # Common defaults.
1764 #
1765
1766 # Guess mnemonic and operands from stats if the former is missing.
1767 if oInstr.sMnemonic is None:
1768 if oInstr.sStats is not None:
1769 self.deriveMnemonicAndOperandsFromStats(oInstr, oInstr.sStats);
1770 elif oInstr.sFunction is not None:
1771 self.deriveMnemonicAndOperandsFromStats(oInstr, oInstr.sFunction.replace('iemOp_', ''));
1772
1773 # Derive the disassembler op enum constant from the mnemonic.
1774 if oInstr.sDisEnum is None and oInstr.sMnemonic is not None:
1775 oInstr.sDisEnum = 'OP_' + oInstr.sMnemonic.upper();
1776
1777 # Derive the IEM statistics base name from mnemonic and operand types.
1778 if oInstr.sStats is None:
1779 if oInstr.sFunction is not None:
1780 oInstr.sStats = oInstr.sFunction.replace('iemOp_', '');
1781 elif oInstr.sMnemonic is not None:
1782 oInstr.sStats = oInstr.sMnemonic;
1783 for oOperand in oInstr.aoOperands:
1784 if oOperand.sType:
1785 oInstr.sStats += '_' + oOperand.sType;
1786
1787 # Derive the IEM function name from mnemonic and operand types.
1788 if oInstr.sFunction is None:
1789 if oInstr.sMnemonic is not None:
1790 oInstr.sFunction = 'iemOp_' + oInstr.sMnemonic;
1791 for oOperand in oInstr.aoOperands:
1792 if oOperand.sType:
1793 oInstr.sFunction += '_' + oOperand.sType;
1794 elif oInstr.sStats:
1795 oInstr.sFunction = 'iemOp_' + oInstr.sStats;
1796
1797 #
1798 # Apply default map and then add the instruction to all it's groups.
1799 #
1800 if not oInstr.aoMaps:
1801 oInstr.aoMaps = [ self.oDefaultMap, ];
1802 for oMap in oInstr.aoMaps:
1803 oMap.aoInstructions.append(oInstr);
1804
1805 #
1806 # Derive encoding from operands and maps.
1807 #
1808 if oInstr.sEncoding is None:
1809 if not oInstr.aoOperands:
1810 if oInstr.fUnused and oInstr.sSubOpcode:
1811 oInstr.sEncoding = 'VEX.ModR/M' if oInstr.onlyInVexMaps() else 'ModR/M';
1812 else:
1813 oInstr.sEncoding = 'VEX.fixed' if oInstr.onlyInVexMaps() else 'fixed';
1814 elif oInstr.aoOperands[0].usesModRM():
1815 if (len(oInstr.aoOperands) >= 2 and oInstr.aoOperands[1].sWhere == 'vvvv') \
1816 or oInstr.onlyInVexMaps():
1817 oInstr.sEncoding = 'VEX.ModR/M';
1818 else:
1819 oInstr.sEncoding = 'ModR/M';
1820
1821 #
1822 # Check the opstat value and add it to the opstat indexed dictionary.
1823 #
1824 if oInstr.sStats:
1825 if oInstr.sStats not in g_dAllInstructionsByStat:
1826 g_dAllInstructionsByStat[oInstr.sStats] = oInstr;
1827 else:
1828 self.error('Duplicate opstat value "%s"\nnew: %s\nold: %s'
1829 % (oInstr.sStats, oInstr, g_dAllInstructionsByStat[oInstr.sStats],));
1830
1831 #
1832 # Add to function indexed dictionary. We allow multiple instructions per function.
1833 #
1834 if oInstr.sFunction:
1835 if oInstr.sFunction not in g_dAllInstructionsByFunction:
1836 g_dAllInstructionsByFunction[oInstr.sFunction] = [oInstr,];
1837 else:
1838 g_dAllInstructionsByFunction[oInstr.sFunction].append(oInstr);
1839
1840 #self.debug('%d..%d: %s; %d @op tags' % (oInstr.iLineCreated, oInstr.iLineCompleted, oInstr.sFunction, oInstr.cOpTags));
1841 return True;
1842
1843 def doneInstructions(self, iLineInComment = None):
1844 """
1845 Done with current instruction.
1846 """
1847 for oInstr in self.aoCurInstrs:
1848 self.doneInstructionOne(oInstr, self.iLine if iLineInComment is None else self.iCommentLine + iLineInComment);
1849 if oInstr.fStub:
1850 self.cTotalStubs += 1;
1851
1852 self.cTotalInstr += len(self.aoCurInstrs);
1853
1854 self.sComment = '';
1855 self.aoCurInstrs = [];
1856 return True;
1857
1858 def setInstrunctionAttrib(self, sAttrib, oValue, fOverwrite = False):
1859 """
1860 Sets the sAttrib of all current instruction to oValue. If fOverwrite
1861 is False, only None values and empty strings are replaced.
1862 """
1863 for oInstr in self.aoCurInstrs:
1864 if fOverwrite is not True:
1865 oOldValue = getattr(oInstr, sAttrib);
1866 if oOldValue is not None:
1867 continue;
1868 setattr(oInstr, sAttrib, oValue);
1869
1870 def setInstrunctionArrayAttrib(self, sAttrib, iEntry, oValue, fOverwrite = False):
1871 """
1872 Sets the iEntry of the array sAttrib of all current instruction to oValue.
1873 If fOverwrite is False, only None values and empty strings are replaced.
1874 """
1875 for oInstr in self.aoCurInstrs:
1876 aoArray = getattr(oInstr, sAttrib);
1877 while len(aoArray) <= iEntry:
1878 aoArray.append(None);
1879 if fOverwrite is True or aoArray[iEntry] is None:
1880 aoArray[iEntry] = oValue;
1881
1882 def parseCommentOldOpcode(self, asLines):
1883 """ Deals with 'Opcode 0xff /4' like comments """
1884 asWords = asLines[0].split();
1885 if len(asWords) >= 2 \
1886 and asWords[0] == 'Opcode' \
1887 and ( asWords[1].startswith('0x')
1888 or asWords[1].startswith('0X')):
1889 asWords = asWords[:1];
1890 for iWord, sWord in enumerate(asWords):
1891 if sWord.startswith('0X'):
1892 sWord = '0x' + sWord[:2];
1893 asWords[iWord] = asWords;
1894 self.setInstrunctionAttrib('sRawOldOpcodes', ' '.join(asWords));
1895
1896 return False;
1897
1898 def ensureInstructionForOpTag(self, iTagLine):
1899 """ Ensure there is an instruction for the op-tag being parsed. """
1900 if not self.aoCurInstrs:
1901 self.addInstruction(self.iCommentLine + iTagLine);
1902 for oInstr in self.aoCurInstrs:
1903 oInstr.cOpTags += 1;
1904 if oInstr.cOpTags == 1:
1905 self.cTotalTagged += 1;
1906 return self.aoCurInstrs[-1];
1907
1908 @staticmethod
1909 def flattenSections(aasSections):
1910 """
1911 Flattens multiline sections into stripped single strings.
1912 Returns list of strings, on section per string.
1913 """
1914 asRet = [];
1915 for asLines in aasSections:
1916 if asLines:
1917 asRet.append(' '.join([sLine.strip() for sLine in asLines]));
1918 return asRet;
1919
1920 @staticmethod
1921 def flattenAllSections(aasSections, sLineSep = ' ', sSectionSep = '\n'):
1922 """
1923 Flattens sections into a simple stripped string with newlines as
1924 section breaks. The final section does not sport a trailing newline.
1925 """
1926 # Typical: One section with a single line.
1927 if len(aasSections) == 1 and len(aasSections[0]) == 1:
1928 return aasSections[0][0].strip();
1929
1930 sRet = '';
1931 for iSection, asLines in enumerate(aasSections):
1932 if asLines:
1933 if iSection > 0:
1934 sRet += sSectionSep;
1935 sRet += sLineSep.join([sLine.strip() for sLine in asLines]);
1936 return sRet;
1937
1938
1939
1940 ## @name Tag parsers
1941 ## @{
1942
1943 def parseTagOpBrief(self, sTag, aasSections, iTagLine, iEndLine):
1944 """
1945 Tag: \@opbrief
1946 Value: Text description, multiple sections, appended.
1947
1948 Brief description. If not given, it's the first sentence from @opdesc.
1949 """
1950 oInstr = self.ensureInstructionForOpTag(iTagLine);
1951
1952 # Flatten and validate the value.
1953 sBrief = self.flattenAllSections(aasSections);
1954 if not sBrief:
1955 return self.errorComment(iTagLine, '%s: value required' % (sTag,));
1956 if sBrief[-1] != '.':
1957 sBrief = sBrief + '.';
1958 if len(sBrief) > 180:
1959 return self.errorComment(iTagLine, '%s: value too long (max 180 chars): %s' % (sTag, sBrief));
1960 offDot = sBrief.find('.');
1961 while offDot >= 0 and offDot < len(sBrief) - 1 and sBrief[offDot + 1] != ' ':
1962 offDot = sBrief.find('.', offDot + 1);
1963 if offDot >= 0 and offDot != len(sBrief) - 1:
1964 return self.errorComment(iTagLine, '%s: only one sentence: %s' % (sTag, sBrief));
1965
1966 # Update the instruction.
1967 if oInstr.sBrief is not None:
1968 return self.errorComment(iTagLine, '%s: attempting to overwrite brief "%s" with "%s"'
1969 % (sTag, oInstr.sBrief, sBrief,));
1970 _ = iEndLine;
1971 return True;
1972
1973 def parseTagOpDesc(self, sTag, aasSections, iTagLine, iEndLine):
1974 """
1975 Tag: \@opdesc
1976 Value: Text description, multiple sections, appended.
1977
1978 It is used to describe instructions.
1979 """
1980 oInstr = self.ensureInstructionForOpTag(iTagLine);
1981 if aasSections:
1982 oInstr.asDescSections.extend(self.flattenSections(aasSections));
1983 return True;
1984
1985 _ = sTag; _ = iEndLine;
1986 return True;
1987
1988 def parseTagOpMnemonic(self, sTag, aasSections, iTagLine, iEndLine):
1989 """
1990 Tag: @opmenmonic
1991 Value: mnemonic
1992
1993 The 'mnemonic' value must be a valid C identifier string. Because of
1994 prefixes, groups and whatnot, there times when the mnemonic isn't that
1995 of an actual assembler mnemonic.
1996 """
1997 oInstr = self.ensureInstructionForOpTag(iTagLine);
1998
1999 # Flatten and validate the value.
2000 sMnemonic = self.flattenAllSections(aasSections);
2001 if not self.oReMnemonic.match(sMnemonic):
2002 return self.errorComment(iTagLine, '%s: invalid menmonic name: "%s"' % (sTag, sMnemonic,));
2003 if oInstr.sMnemonic is not None:
2004 return self.errorComment(iTagLine, '%s: attempting to overwrite menmonic "%s" with "%s"'
2005 % (sTag, oInstr.sMnemonic, sMnemonic,));
2006 oInstr.sMnemonic = sMnemonic
2007
2008 _ = iEndLine;
2009 return True;
2010
2011 def parseTagOpOperandN(self, sTag, aasSections, iTagLine, iEndLine):
2012 """
2013 Tags: \@op1, \@op2, \@op3, \@op4
2014 Value: [where:]type
2015
2016 The 'where' value indicates where the operand is found, like the 'reg'
2017 part of the ModR/M encoding. See Instruction.kdOperandLocations for
2018 a list.
2019
2020 The 'type' value indicates the operand type. These follow the types
2021 given in the opcode tables in the CPU reference manuals.
2022 See Instruction.kdOperandTypes for a list.
2023
2024 """
2025 oInstr = self.ensureInstructionForOpTag(iTagLine);
2026 idxOp = int(sTag[-1]) - 1;
2027 assert idxOp >= 0 and idxOp < 4;
2028
2029 # flatten, split up, and validate the "where:type" value.
2030 sFlattened = self.flattenAllSections(aasSections);
2031 asSplit = sFlattened.split(':');
2032 if len(asSplit) == 1:
2033 sType = asSplit[0];
2034 sWhere = None;
2035 elif len(asSplit) == 2:
2036 (sWhere, sType) = asSplit;
2037 else:
2038 return self.errorComment(iTagLine, 'expected %s value on format "[<where>:]<type>" not "%s"' % (sTag, sFlattened,));
2039
2040 if sType not in g_kdOpTypes:
2041 return self.errorComment(iTagLine, '%s: invalid where value "%s", valid: %s'
2042 % (sTag, sType, ', '.join(g_kdOpTypes.keys()),));
2043 if sWhere is None:
2044 sWhere = g_kdOpTypes[sType][1];
2045 elif sWhere not in g_kdOpLocations:
2046 return self.errorComment(iTagLine, '%s: invalid where value "%s", valid: %s'
2047 % (sTag, sWhere, ', '.join(g_kdOpLocations.keys()),));
2048
2049 # Insert the operand, refusing to overwrite an existing one.
2050 while idxOp >= len(oInstr.aoOperands):
2051 oInstr.aoOperands.append(None);
2052 if oInstr.aoOperands[idxOp] is not None:
2053 return self.errorComment(iTagLine, '%s: attempting to overwrite "%s:%s" with "%s:%s"'
2054 % ( sTag, oInstr.aoOperands[idxOp].sWhere, oInstr.aoOperands[idxOp].sType,
2055 sWhere, sType,));
2056 oInstr.aoOperands[idxOp] = Operand(sWhere, sType);
2057
2058 _ = iEndLine;
2059 return True;
2060
2061 def parseTagOpMaps(self, sTag, aasSections, iTagLine, iEndLine):
2062 """
2063 Tag: \@opmaps
2064 Value: map[,map2]
2065
2066 Indicates which maps the instruction is in. There is a default map
2067 associated with each input file.
2068 """
2069 oInstr = self.ensureInstructionForOpTag(iTagLine);
2070
2071 # Flatten, split up and validate the value.
2072 sFlattened = self.flattenAllSections(aasSections, sLineSep = ',', sSectionSep = ',');
2073 asMaps = sFlattened.split(',');
2074 if not asMaps:
2075 return self.errorComment(iTagLine, '%s: value required' % (sTag,));
2076 for sMap in asMaps:
2077 if sMap not in g_dInstructionMaps:
2078 return self.errorComment(iTagLine, '%s: invalid map value: %s (valid values: %s)'
2079 % (sTag, sMap, ', '.join(g_dInstructionMaps.keys()),));
2080
2081 # Add the maps to the current list. Throw errors on duplicates.
2082 for oMap in oInstr.aoMaps:
2083 if oMap.sName in asMaps:
2084 return self.errorComment(iTagLine, '%s: duplicate map assignment: %s' % (sTag, oMap.sName));
2085
2086 for sMap in asMaps:
2087 oMap = g_dInstructionMaps[sMap];
2088 if oMap not in oInstr.aoMaps:
2089 oInstr.aoMaps.append(oMap);
2090 else:
2091 self.errorComment(iTagLine, '%s: duplicate map assignment (input): %s' % (sTag, sMap));
2092
2093 _ = iEndLine;
2094 return True;
2095
2096 def parseTagOpPfx(self, sTag, aasSections, iTagLine, iEndLine):
2097 """
2098 Tag: \@oppfx
2099 Value: n/a|none|0x66|0xf3|0xf2
2100
2101 Required prefix for the instruction. (In a (E)VEX context this is the
2102 value of the 'pp' field rather than an actual prefix.)
2103 """
2104 oInstr = self.ensureInstructionForOpTag(iTagLine);
2105
2106 # Flatten and validate the value.
2107 sFlattened = self.flattenAllSections(aasSections);
2108 asPrefixes = sFlattened.split();
2109 if len(asPrefixes) > 1:
2110 return self.errorComment(iTagLine, '%s: max one prefix: %s' % (sTag, asPrefixes,));
2111
2112 sPrefix = asPrefixes[0].lower();
2113 if sPrefix == 'none':
2114 sPrefix = 'none';
2115 elif sPrefix == 'n/a':
2116 sPrefix = None;
2117 else:
2118 if len(sPrefix) == 2:
2119 sPrefix = '0x' + sPrefix;
2120 if not _isValidOpcodeByte(sPrefix):
2121 return self.errorComment(iTagLine, '%s: invalid prefix: %s' % (sTag, sPrefix,));
2122
2123 if sPrefix is not None and sPrefix not in g_kdPrefixes:
2124 return self.errorComment(iTagLine, '%s: invalid prefix: %s (valid %s)' % (sTag, sPrefix, g_kdPrefixes,));
2125
2126 # Set it.
2127 if oInstr.sPrefix is not None:
2128 return self.errorComment(iTagLine, '%s: attempting to overwrite "%s" with "%s"' % ( sTag, oInstr.sPrefix, sPrefix,));
2129 oInstr.sPrefix = sPrefix;
2130
2131 _ = iEndLine;
2132 return True;
2133
2134 def parseTagOpcode(self, sTag, aasSections, iTagLine, iEndLine):
2135 """
2136 Tag: \@opcode
2137 Value: 0x?? | /reg (TODO: | mr/reg | 11 /reg | !11 /reg | 11 mr/reg | !11 mr/reg)
2138
2139 The opcode byte or sub-byte for the instruction in the context of a map.
2140 """
2141 oInstr = self.ensureInstructionForOpTag(iTagLine);
2142
2143 # Flatten and validate the value.
2144 sOpcode = self.flattenAllSections(aasSections);
2145 if _isValidOpcodeByte(sOpcode):
2146 pass;
2147 elif len(sOpcode) == 2 and sOpcode.startswith('/') and sOpcode[-1] in '012345678':
2148 pass;
2149 elif len(sOpcode) == 4 and sOpcode.startswith('11/') and sOpcode[-1] in '012345678':
2150 pass;
2151 elif len(sOpcode) == 5 and sOpcode.startswith('!11/') and sOpcode[-1] in '012345678':
2152 pass;
2153 else:
2154 return self.errorComment(iTagLine, '%s: invalid opcode: %s' % (sTag, sOpcode,));
2155
2156 # Set it.
2157 if oInstr.sOpcode is not None:
2158 return self.errorComment(iTagLine, '%s: attempting to overwrite "%s" with "%s"' % ( sTag, oInstr.sOpcode, sOpcode,));
2159 oInstr.sOpcode = sOpcode;
2160
2161 _ = iEndLine;
2162 return True;
2163
2164 def parseTagOpcodeSub(self, sTag, aasSections, iTagLine, iEndLine):
2165 """
2166 Tag: \@opcodesub
2167 Value: none | 11 mr/reg | !11 mr/reg
2168
2169 This is a simple way of dealing with encodings where the mod=3 and mod!=3
2170 represents exactly two different instructions. The more proper way would
2171 be to go via maps with two members, but this is faster.
2172 """
2173 oInstr = self.ensureInstructionForOpTag(iTagLine);
2174
2175 # Flatten and validate the value.
2176 sSubOpcode = self.flattenAllSections(aasSections);
2177 if sSubOpcode not in g_kdSubOpcodes:
2178 return self.errorComment(iTagLine, '%s: invalid sub opcode: %s (valid: 11, !11, none)' % (sTag, sSubOpcode,));
2179 sSubOpcode = g_kdSubOpcodes[sSubOpcode][0];
2180
2181 # Set it.
2182 if oInstr.sSubOpcode is not None:
2183 return self.errorComment(iTagLine, '%s: attempting to overwrite "%s" with "%s"'
2184 % ( sTag, oInstr.sSubOpcode, sSubOpcode,));
2185 oInstr.sSubOpcode = sSubOpcode;
2186
2187 _ = iEndLine;
2188 return True;
2189
2190 def parseTagOpEnc(self, sTag, aasSections, iTagLine, iEndLine):
2191 """
2192 Tag: \@openc
2193 Value: ModR/M|fixed|prefix|<map name>
2194
2195 The instruction operand encoding style.
2196 """
2197 oInstr = self.ensureInstructionForOpTag(iTagLine);
2198
2199 # Flatten and validate the value.
2200 sEncoding = self.flattenAllSections(aasSections);
2201 if sEncoding in g_kdEncodings:
2202 pass;
2203 elif sEncoding in g_dInstructionMaps:
2204 pass;
2205 elif not _isValidOpcodeByte(sEncoding):
2206 return self.errorComment(iTagLine, '%s: invalid encoding: %s' % (sTag, sEncoding,));
2207
2208 # Set it.
2209 if oInstr.sEncoding is not None:
2210 return self.errorComment(iTagLine, '%s: attempting to overwrite "%s" with "%s"'
2211 % ( sTag, oInstr.sEncoding, sEncoding,));
2212 oInstr.sEncoding = sEncoding;
2213
2214 _ = iEndLine;
2215 return True;
2216
2217 ## EFlags tag to Instruction attribute name.
2218 kdOpFlagToAttr = {
2219 '@opfltest': 'asFlTest',
2220 '@opflmodify': 'asFlModify',
2221 '@opflundef': 'asFlUndefined',
2222 '@opflset': 'asFlSet',
2223 '@opflclear': 'asFlClear',
2224 };
2225
2226 def parseTagOpEFlags(self, sTag, aasSections, iTagLine, iEndLine):
2227 """
2228 Tags: \@opfltest, \@opflmodify, \@opflundef, \@opflset, \@opflclear
2229 Value: <eflags specifier>
2230
2231 """
2232 oInstr = self.ensureInstructionForOpTag(iTagLine);
2233
2234 # Flatten, split up and validate the values.
2235 asFlags = self.flattenAllSections(aasSections, sLineSep = ',', sSectionSep = ',').split(',');
2236 if len(asFlags) == 1 and asFlags[0].lower() == 'none':
2237 asFlags = [];
2238 else:
2239 fRc = True;
2240 for iFlag, sFlag in enumerate(asFlags):
2241 if sFlag not in g_kdEFlagsMnemonics:
2242 if sFlag.strip() in g_kdEFlagsMnemonics:
2243 asFlags[iFlag] = sFlag.strip();
2244 else:
2245 fRc = self.errorComment(iTagLine, '%s: invalid EFLAGS value: %s' % (sTag, sFlag,));
2246 if not fRc:
2247 return False;
2248
2249 # Set them.
2250 asOld = getattr(oInstr, self.kdOpFlagToAttr[sTag]);
2251 if asOld is not None:
2252 return self.errorComment(iTagLine, '%s: attempting to overwrite "%s" with "%s"' % ( sTag, asOld, asFlags,));
2253 setattr(oInstr, self.kdOpFlagToAttr[sTag], asFlags);
2254
2255 _ = iEndLine;
2256 return True;
2257
2258 def parseTagOpHints(self, sTag, aasSections, iTagLine, iEndLine):
2259 """
2260 Tag: \@ophints
2261 Value: Comma or space separated list of flags and hints.
2262
2263 This covers the disassembler flags table and more.
2264 """
2265 oInstr = self.ensureInstructionForOpTag(iTagLine);
2266
2267 # Flatten as a space separated list, split it up and validate the values.
2268 asHints = self.flattenAllSections(aasSections, sLineSep = ' ', sSectionSep = ' ').replace(',', ' ').split();
2269 if len(asHints) == 1 and asHints[0].lower() == 'none':
2270 asHints = [];
2271 else:
2272 fRc = True;
2273 for iHint, sHint in enumerate(asHints):
2274 if sHint not in g_kdHints:
2275 if sHint.strip() in g_kdHints:
2276 sHint[iHint] = sHint.strip();
2277 else:
2278 fRc = self.errorComment(iTagLine, '%s: invalid hint value: %s' % (sTag, sHint,));
2279 if not fRc:
2280 return False;
2281
2282 # Append them.
2283 for sHint in asHints:
2284 if sHint not in oInstr.dHints:
2285 oInstr.dHints[sHint] = True; # (dummy value, using dictionary for speed)
2286 else:
2287 self.errorComment(iTagLine, '%s: duplicate hint: %s' % ( sTag, sHint,));
2288
2289 _ = iEndLine;
2290 return True;
2291
2292 def parseTagOpDisEnum(self, sTag, aasSections, iTagLine, iEndLine):
2293 """
2294 Tag: \@opdisenum
2295 Value: OP_XXXX
2296
2297 This is for select a specific (legacy) disassembler enum value for the
2298 instruction.
2299 """
2300 oInstr = self.ensureInstructionForOpTag(iTagLine);
2301
2302 # Flatten and split.
2303 asWords = self.flattenAllSections(aasSections).split();
2304 if len(asWords) != 1:
2305 self.errorComment(iTagLine, '%s: expected exactly one value: %s' % (sTag, asWords,));
2306 if not asWords:
2307 return False;
2308 sDisEnum = asWords[0];
2309 if not self.oReDisEnum.match(sDisEnum):
2310 return self.errorComment(iTagLine, '%s: invalid disassembler OP_XXXX enum: %s (pattern: %s)'
2311 % (sTag, sDisEnum, self.oReDisEnum.pattern));
2312
2313 # Set it.
2314 if oInstr.sDisEnum is not None:
2315 return self.errorComment(iTagLine, '%s: attempting to overwrite "%s" with "%s"' % (sTag, oInstr.sDisEnum, sDisEnum,));
2316 oInstr.sDisEnum = sDisEnum;
2317
2318 _ = iEndLine;
2319 return True;
2320
2321 def parseTagOpMinCpu(self, sTag, aasSections, iTagLine, iEndLine):
2322 """
2323 Tag: \@opmincpu
2324 Value: <simple CPU name>
2325
2326 Indicates when this instruction was introduced.
2327 """
2328 oInstr = self.ensureInstructionForOpTag(iTagLine);
2329
2330 # Flatten the value, split into words, make sure there's just one, valid it.
2331 asCpus = self.flattenAllSections(aasSections).split();
2332 if len(asCpus) > 1:
2333 self.errorComment(iTagLine, '%s: exactly one CPU name, please: %s' % (sTag, ' '.join(asCpus),));
2334
2335 sMinCpu = asCpus[0];
2336 if sMinCpu in g_kdCpuNames:
2337 oInstr.sMinCpu = sMinCpu;
2338 else:
2339 return self.errorComment(iTagLine, '%s: invalid CPU name: %s (names: %s)'
2340 % (sTag, sMinCpu, ','.join(sorted(g_kdCpuNames)),));
2341
2342 # Set it.
2343 if oInstr.sMinCpu is None:
2344 oInstr.sMinCpu = sMinCpu;
2345 elif oInstr.sMinCpu != sMinCpu:
2346 self.errorComment(iTagLine, '%s: attemting to overwrite "%s" with "%s"' % (sTag, oInstr.sMinCpu, sMinCpu,));
2347
2348 _ = iEndLine;
2349 return True;
2350
2351 def parseTagOpCpuId(self, sTag, aasSections, iTagLine, iEndLine):
2352 """
2353 Tag: \@opcpuid
2354 Value: none | <CPUID flag specifier>
2355
2356 CPUID feature bit which is required for the instruction to be present.
2357 """
2358 oInstr = self.ensureInstructionForOpTag(iTagLine);
2359
2360 # Flatten as a space separated list, split it up and validate the values.
2361 asCpuIds = self.flattenAllSections(aasSections, sLineSep = ' ', sSectionSep = ' ').replace(',', ' ').split();
2362 if len(asCpuIds) == 1 and asCpuIds[0].lower() == 'none':
2363 asCpuIds = [];
2364 else:
2365 fRc = True;
2366 for iCpuId, sCpuId in enumerate(asCpuIds):
2367 if sCpuId not in g_kdCpuIdFlags:
2368 if sCpuId.strip() in g_kdCpuIdFlags:
2369 sCpuId[iCpuId] = sCpuId.strip();
2370 else:
2371 fRc = self.errorComment(iTagLine, '%s: invalid CPUID value: %s' % (sTag, sCpuId,));
2372 if not fRc:
2373 return False;
2374
2375 # Append them.
2376 for sCpuId in asCpuIds:
2377 if sCpuId not in oInstr.asCpuIds:
2378 oInstr.asCpuIds.append(sCpuId);
2379 else:
2380 self.errorComment(iTagLine, '%s: duplicate CPUID: %s' % ( sTag, sCpuId,));
2381
2382 _ = iEndLine;
2383 return True;
2384
2385 def parseTagOpGroup(self, sTag, aasSections, iTagLine, iEndLine):
2386 """
2387 Tag: \@opgroup
2388 Value: op_grp1[_subgrp2[_subsubgrp3]]
2389
2390 Instruction grouping.
2391 """
2392 oInstr = self.ensureInstructionForOpTag(iTagLine);
2393
2394 # Flatten as a space separated list, split it up and validate the values.
2395 asGroups = self.flattenAllSections(aasSections).split();
2396 if len(asGroups) != 1:
2397 return self.errorComment(iTagLine, '%s: exactly one group, please: %s' % (sTag, asGroups,));
2398 sGroup = asGroups[0];
2399 if not self.oReGroupName.match(sGroup):
2400 return self.errorComment(iTagLine, '%s: invalid group name: %s (valid: %s)'
2401 % (sTag, sGroup, self.oReGroupName.pattern));
2402
2403 # Set it.
2404 if oInstr.sGroup is not None:
2405 return self.errorComment(iTagLine, '%s: attempting to overwrite "%s" with "%s"' % ( sTag, oInstr.sGroup, sGroup,));
2406 oInstr.sGroup = sGroup;
2407
2408 _ = iEndLine;
2409 return True;
2410
2411 def parseTagOpUnusedInvalid(self, sTag, aasSections, iTagLine, iEndLine):
2412 """
2413 Tag: \@opunused, \@opinvalid, \@opinvlstyle
2414 Value: <invalid opcode behaviour style>
2415
2416 The \@opunused indicates the specification is for a currently unused
2417 instruction encoding.
2418
2419 The \@opinvalid indicates the specification is for an invalid currently
2420 instruction encoding (like UD2).
2421
2422 The \@opinvlstyle just indicates how CPUs decode the instruction when
2423 not supported (\@opcpuid, \@opmincpu) or disabled.
2424 """
2425 oInstr = self.ensureInstructionForOpTag(iTagLine);
2426
2427 # Flatten as a space separated list, split it up and validate the values.
2428 asStyles = self.flattenAllSections(aasSections).split();
2429 if len(asStyles) != 1:
2430 return self.errorComment(iTagLine, '%s: exactly one invalid behviour style, please: %s' % (sTag, asStyles,));
2431 sStyle = asStyles[0];
2432 if sStyle not in g_kdInvalidStyles:
2433 return self.errorComment(iTagLine, '%s: invalid invalid behaviour style: %s (valid: %s)'
2434 % (sTag, sStyle, g_kdInvalidStyles.keys(),));
2435 # Set it.
2436 if oInstr.sInvalidStyle is not None:
2437 return self.errorComment(iTagLine,
2438 '%s: attempting to overwrite "%s" with "%s" (only one @opunused, @opinvalid, @opinvlstyle)'
2439 % ( sTag, oInstr.sInvalidStyle, sStyle,));
2440 oInstr.sInvalidStyle = sStyle;
2441 if sTag == '@opunused':
2442 oInstr.fUnused = True;
2443 elif sTag == '@opinvalid':
2444 oInstr.fInvalid = True;
2445
2446 _ = iEndLine;
2447 return True;
2448
2449 def parseTagOpTest(self, sTag, aasSections, iTagLine, iEndLine): # pylint: disable=too-many-locals
2450 """
2451 Tag: \@optest
2452 Value: [<selectors>[ ]?] <inputs> -> <outputs>
2453 Example: mode==64bit / in1=0xfffffffe:dw in2=1:dw -> out1=0xffffffff:dw outfl=a?,p?
2454
2455 The main idea here is to generate basic instruction tests.
2456
2457 The probably simplest way of handling the diverse input, would be to use
2458 it to produce size optimized byte code for a simple interpreter that
2459 modifies the register input and output states.
2460
2461 An alternative to the interpreter would be creating multiple tables,
2462 but that becomes rather complicated wrt what goes where and then to use
2463 them in an efficient manner.
2464 """
2465 oInstr = self.ensureInstructionForOpTag(iTagLine);
2466
2467 #
2468 # Do it section by section.
2469 #
2470 for asSectionLines in aasSections:
2471 #
2472 # Sort the input into outputs, inputs and selector conditions.
2473 #
2474 sFlatSection = self.flattenAllSections([asSectionLines,]);
2475 if not sFlatSection:
2476 self.errorComment(iTagLine, '%s: missing value (dbg: aasSections=%s)' % ( sTag, aasSections));
2477 continue;
2478 oTest = InstructionTest(oInstr);
2479
2480 asSelectors = [];
2481 asInputs = [];
2482 asOutputs = [];
2483 asCur = asOutputs;
2484 fRc = True;
2485 asWords = sFlatSection.split();
2486 for iWord in range(len(asWords) - 1, -1, -1):
2487 sWord = asWords[iWord];
2488 # Check for array switchers.
2489 if sWord == '->':
2490 if asCur != asOutputs:
2491 fRc = self.errorComment(iTagLine, '%s: "->" shall only occure once: %s' % (sTag, sFlatSection,));
2492 break;
2493 asCur = asInputs;
2494 elif sWord == '/':
2495 if asCur != asInputs:
2496 fRc = self.errorComment(iTagLine, '%s: "/" shall only occure once: %s' % (sTag, sFlatSection,));
2497 break;
2498 asCur = asSelectors;
2499 else:
2500 asCur.insert(0, sWord);
2501
2502 #
2503 # Validate and add selectors.
2504 #
2505 for sCond in asSelectors:
2506 sCondExp = TestSelector.kdPredicates.get(sCond, sCond);
2507 oSelector = None;
2508 for sOp in TestSelector.kasCompareOps:
2509 off = sCondExp.find(sOp);
2510 if off >= 0:
2511 sVariable = sCondExp[:off];
2512 sValue = sCondExp[off + len(sOp):];
2513 if sVariable in TestSelector.kdVariables:
2514 if sValue in TestSelector.kdVariables[sVariable]:
2515 oSelector = TestSelector(sVariable, sOp, sValue);
2516 else:
2517 self.errorComment(iTagLine, '%s: invalid condition value "%s" in "%s" (valid: %s)'
2518 % ( sTag, sValue, sCond,
2519 TestSelector.kdVariables[sVariable].keys(),));
2520 else:
2521 self.errorComment(iTagLine, '%s: invalid condition variable "%s" in "%s" (valid: %s)'
2522 % ( sTag, sVariable, sCond, TestSelector.kdVariables.keys(),));
2523 break;
2524 if oSelector is not None:
2525 for oExisting in oTest.aoSelectors:
2526 if oExisting.sVariable == oSelector.sVariable:
2527 self.errorComment(iTagLine, '%s: already have a selector for variable "%s" (existing: %s, new: %s)'
2528 % ( sTag, oSelector.sVariable, oExisting, oSelector,));
2529 oTest.aoSelectors.append(oSelector);
2530 else:
2531 fRc = self.errorComment(iTagLine, '%s: failed to parse selector: %s' % ( sTag, sCond,));
2532
2533 #
2534 # Validate outputs and inputs, adding them to the test as we go along.
2535 #
2536 for asItems, sDesc, aoDst in [ (asInputs, 'input', oTest.aoInputs), (asOutputs, 'output', oTest.aoOutputs)]:
2537 asValidFieldKinds = [ 'both', sDesc, ];
2538 for sItem in asItems:
2539 oItem = None;
2540 for sOp in TestInOut.kasOperators:
2541 off = sItem.find(sOp);
2542 if off < 0:
2543 continue;
2544 sField = sItem[:off];
2545 sValueType = sItem[off + len(sOp):];
2546 if sField in TestInOut.kdFields \
2547 and TestInOut.kdFields[sField][1] in asValidFieldKinds:
2548 asSplit = sValueType.split(':', 1);
2549 sValue = asSplit[0];
2550 sType = asSplit[1] if len(asSplit) > 1 else TestInOut.kdFields[sField][0];
2551 if sType in TestInOut.kdTypes:
2552 oValid = TestInOut.kdTypes[sType].validate(sValue);
2553 if oValid is True:
2554 if not TestInOut.kdTypes[sType].isAndOrPair(sValue) or sOp == '&|=':
2555 oItem = TestInOut(sField, sOp, sValue, sType);
2556 else:
2557 self.errorComment(iTagLine, '%s: and-or %s value "%s" can only be used with "&|="'
2558 % ( sTag, sDesc, sItem, ));
2559 else:
2560 self.errorComment(iTagLine, '%s: invalid %s value "%s" in "%s" (type: %s): %s'
2561 % ( sTag, sDesc, sValue, sItem, sType, oValid, ));
2562 else:
2563 self.errorComment(iTagLine, '%s: invalid %s type "%s" in "%s" (valid types: %s)'
2564 % ( sTag, sDesc, sType, sItem, TestInOut.kdTypes.keys(),));
2565 else:
2566 self.errorComment(iTagLine, '%s: invalid %s field "%s" in "%s"\nvalid fields: %s'
2567 % ( sTag, sDesc, sField, sItem,
2568 ', '.join([sKey for sKey in TestInOut.kdFields.keys()
2569 if TestInOut.kdFields[sKey][1] in asValidFieldKinds]),));
2570 break;
2571 if oItem is not None:
2572 for oExisting in aoDst:
2573 if oExisting.sField == oItem.sField and oExisting.sOp == oItem.sOp:
2574 self.errorComment(iTagLine,
2575 '%s: already have a "%s" assignment for field "%s" (existing: %s, new: %s)'
2576 % ( sTag, oItem.sOp, oItem.sField, oExisting, oItem,));
2577 aoDst.append(oItem);
2578 else:
2579 fRc = self.errorComment(iTagLine, '%s: failed to parse assignment: %s' % ( sTag, sItem,));
2580
2581 #
2582 # .
2583 #
2584 if fRc:
2585 oInstr.aoTests.append(oTest);
2586 else:
2587 self.errorComment(iTagLine, '%s: failed to parse test: %s' % (sTag, ' '.join(asWords),));
2588 self.errorComment(iTagLine, '%s: asSelectors=%s / asInputs=%s -> asOutputs=%s'
2589 % (sTag, asSelectors, asInputs, asOutputs,));
2590
2591 _ = iEndLine;
2592 return True;
2593
2594 def parseTagOpTestNum(self, sTag, aasSections, iTagLine, iEndLine):
2595 """
2596 Numbered \@optest tag. Either \@optest42 or \@optest[42].
2597 """
2598 oInstr = self.ensureInstructionForOpTag(iTagLine);
2599
2600 iTest = 0;
2601 if sTag[-1] == ']':
2602 iTest = int(sTag[8:-1]);
2603 else:
2604 iTest = int(sTag[7:]);
2605
2606 if iTest != len(oInstr.aoTests):
2607 self.errorComment(iTagLine, '%s: incorrect test number: %u, actual %u' % (sTag, iTest, len(oInstr.aoTests),));
2608 return self.parseTagOpTest(sTag, aasSections, iTagLine, iEndLine);
2609
2610 def parseTagOpTestIgnore(self, sTag, aasSections, iTagLine, iEndLine):
2611 """
2612 Tag: \@optestign | \@optestignore
2613 Value: <value is ignored>
2614
2615 This is a simple trick to ignore a test while debugging another.
2616
2617 See also \@oponlytest.
2618 """
2619 _ = sTag; _ = aasSections; _ = iTagLine; _ = iEndLine;
2620 return True;
2621
2622 def parseTagOpCopyTests(self, sTag, aasSections, iTagLine, iEndLine):
2623 """
2624 Tag: \@opcopytests
2625 Value: <opstat | function> [..]
2626 Example: \@opcopytests add_Eb_Gb
2627
2628 Trick to avoid duplicating tests for different encodings of the same
2629 operation.
2630 """
2631 oInstr = self.ensureInstructionForOpTag(iTagLine);
2632
2633 # Flatten, validate and append the copy job to the instruction. We execute
2634 # them after parsing all the input so we can handle forward references.
2635 asToCopy = self.flattenAllSections(aasSections).split();
2636 if not asToCopy:
2637 return self.errorComment(iTagLine, '%s: requires at least on reference value' % (sTag,));
2638 for sToCopy in asToCopy:
2639 if sToCopy not in oInstr.asCopyTests:
2640 if self.oReStatsName.match(sToCopy) or self.oReFunctionName.match(sToCopy):
2641 oInstr.asCopyTests.append(sToCopy);
2642 else:
2643 self.errorComment(iTagLine, '%s: invalid instruction reference (opstat or function) "%s" (valid: %s or %s)'
2644 % (sTag, sToCopy, self.oReStatsName.pattern, self.oReFunctionName.pattern));
2645 else:
2646 self.errorComment(iTagLine, '%s: ignoring duplicate "%s"' % (sTag, sToCopy,));
2647
2648 _ = iEndLine;
2649 return True;
2650
2651 def parseTagOpOnlyTest(self, sTag, aasSections, iTagLine, iEndLine):
2652 """
2653 Tag: \@oponlytest | \@oponly
2654 Value: none
2655
2656 Only test instructions with this tag. This is a trick that is handy
2657 for singling out one or two new instructions or tests.
2658
2659 See also \@optestignore.
2660 """
2661 oInstr = self.ensureInstructionForOpTag(iTagLine);
2662
2663 # Validate and add instruction to only test dictionary.
2664 sValue = self.flattenAllSections(aasSections).strip();
2665 if sValue:
2666 return self.errorComment(iTagLine, '%s: does not take any value: %s' % (sTag, sValue));
2667
2668 if oInstr not in g_aoOnlyTestInstructions:
2669 g_aoOnlyTestInstructions.append(oInstr);
2670
2671 _ = iEndLine;
2672 return True;
2673
2674 def parseTagOpXcptType(self, sTag, aasSections, iTagLine, iEndLine):
2675 """
2676 Tag: \@opxcpttype
2677 Value: [none|1|2|3|4|4UA|5|6|7|8|11|12|E1|E1NF|E2|E3|E3NF|E4|E4NF|E5|E5NF|E6|E6NF|E7NF|E9|E9NF|E10|E11|E12|E12NF]
2678
2679 Sets the SSE or AVX exception type (see SDMv2 2.4, 2.7).
2680 """
2681 oInstr = self.ensureInstructionForOpTag(iTagLine);
2682
2683 # Flatten as a space separated list, split it up and validate the values.
2684 asTypes = self.flattenAllSections(aasSections).split();
2685 if len(asTypes) != 1:
2686 return self.errorComment(iTagLine, '%s: exactly one invalid exception type, please: %s' % (sTag, asTypes,));
2687 sType = asTypes[0];
2688 if sType not in g_kdXcptTypes:
2689 return self.errorComment(iTagLine, '%s: invalid invalid exception type: %s (valid: %s)'
2690 % (sTag, sType, sorted(g_kdXcptTypes.keys()),));
2691 # Set it.
2692 if oInstr.sXcptType is not None:
2693 return self.errorComment(iTagLine,
2694 '%s: attempting to overwrite "%s" with "%s" (only one @opxcpttype)'
2695 % ( sTag, oInstr.sXcptType, sType,));
2696 oInstr.sXcptType = sType;
2697
2698 _ = iEndLine;
2699 return True;
2700
2701 def parseTagOpFunction(self, sTag, aasSections, iTagLine, iEndLine):
2702 """
2703 Tag: \@opfunction
2704 Value: <VMM function name>
2705
2706 This is for explicitly setting the IEM function name. Normally we pick
2707 this up from the FNIEMOP_XXX macro invocation after the description, or
2708 generate it from the mnemonic and operands.
2709
2710 It it thought it maybe necessary to set it when specifying instructions
2711 which implementation isn't following immediately or aren't implemented yet.
2712 """
2713 oInstr = self.ensureInstructionForOpTag(iTagLine);
2714
2715 # Flatten and validate the value.
2716 sFunction = self.flattenAllSections(aasSections);
2717 if not self.oReFunctionName.match(sFunction):
2718 return self.errorComment(iTagLine, '%s: invalid VMM function name: "%s" (valid: %s)'
2719 % (sTag, sFunction, self.oReFunctionName.pattern));
2720
2721 if oInstr.sFunction is not None:
2722 return self.errorComment(iTagLine, '%s: attempting to overwrite VMM function name "%s" with "%s"'
2723 % (sTag, oInstr.sFunction, sFunction,));
2724 oInstr.sFunction = sFunction;
2725
2726 _ = iEndLine;
2727 return True;
2728
2729 def parseTagOpStats(self, sTag, aasSections, iTagLine, iEndLine):
2730 """
2731 Tag: \@opstats
2732 Value: <VMM statistics base name>
2733
2734 This is for explicitly setting the statistics name. Normally we pick
2735 this up from the IEMOP_MNEMONIC macro invocation, or generate it from
2736 the mnemonic and operands.
2737
2738 It it thought it maybe necessary to set it when specifying instructions
2739 which implementation isn't following immediately or aren't implemented yet.
2740 """
2741 oInstr = self.ensureInstructionForOpTag(iTagLine);
2742
2743 # Flatten and validate the value.
2744 sStats = self.flattenAllSections(aasSections);
2745 if not self.oReStatsName.match(sStats):
2746 return self.errorComment(iTagLine, '%s: invalid VMM statistics name: "%s" (valid: %s)'
2747 % (sTag, sStats, self.oReStatsName.pattern));
2748
2749 if oInstr.sStats is not None:
2750 return self.errorComment(iTagLine, '%s: attempting to overwrite VMM statistics base name "%s" with "%s"'
2751 % (sTag, oInstr.sStats, sStats,));
2752 oInstr.sStats = sStats;
2753
2754 _ = iEndLine;
2755 return True;
2756
2757 def parseTagOpDone(self, sTag, aasSections, iTagLine, iEndLine):
2758 """
2759 Tag: \@opdone
2760 Value: none
2761
2762 Used to explictily flush the instructions that have been specified.
2763 """
2764 sFlattened = self.flattenAllSections(aasSections);
2765 if sFlattened != '':
2766 return self.errorComment(iTagLine, '%s: takes no value, found: "%s"' % (sTag, sFlattened,));
2767 _ = sTag; _ = iEndLine;
2768 return self.doneInstructions();
2769
2770 ## @}
2771
2772
2773 def parseComment(self):
2774 """
2775 Parse the current comment (self.sComment).
2776
2777 If it's a opcode specifiying comment, we reset the macro stuff.
2778 """
2779 #
2780 # Reject if comment doesn't seem to contain anything interesting.
2781 #
2782 if self.sComment.find('Opcode') < 0 \
2783 and self.sComment.find('@') < 0:
2784 return False;
2785
2786 #
2787 # Split the comment into lines, removing leading asterisks and spaces.
2788 # Also remove leading and trailing empty lines.
2789 #
2790 asLines = self.sComment.split('\n');
2791 for iLine, sLine in enumerate(asLines):
2792 asLines[iLine] = sLine.lstrip().lstrip('*').lstrip();
2793
2794 while asLines and not asLines[0]:
2795 self.iCommentLine += 1;
2796 asLines.pop(0);
2797
2798 while asLines and not asLines[-1]:
2799 asLines.pop(len(asLines) - 1);
2800
2801 #
2802 # Check for old style: Opcode 0x0f 0x12
2803 #
2804 if asLines[0].startswith('Opcode '):
2805 self.parseCommentOldOpcode(asLines);
2806
2807 #
2808 # Look for @op* tagged data.
2809 #
2810 cOpTags = 0;
2811 sFlatDefault = None;
2812 sCurTag = '@default';
2813 iCurTagLine = 0;
2814 asCurSection = [];
2815 aasSections = [ asCurSection, ];
2816 for iLine, sLine in enumerate(asLines):
2817 if not sLine.startswith('@'):
2818 if sLine:
2819 asCurSection.append(sLine);
2820 elif asCurSection:
2821 asCurSection = [];
2822 aasSections.append(asCurSection);
2823 else:
2824 #
2825 # Process the previous tag.
2826 #
2827 if not asCurSection and len(aasSections) > 1:
2828 aasSections.pop(-1);
2829 if sCurTag in self.dTagHandlers:
2830 self.dTagHandlers[sCurTag](sCurTag, aasSections, iCurTagLine, iLine);
2831 cOpTags += 1;
2832 elif sCurTag.startswith('@op'):
2833 self.errorComment(iCurTagLine, 'Unknown tag: %s' % (sCurTag));
2834 elif sCurTag == '@default':
2835 sFlatDefault = self.flattenAllSections(aasSections);
2836 elif '@op' + sCurTag[1:] in self.dTagHandlers:
2837 self.errorComment(iCurTagLine, 'Did you mean "@op%s" rather than "%s"?' % (sCurTag[1:], sCurTag));
2838 elif sCurTag in ['@encoding', '@opencoding']:
2839 self.errorComment(iCurTagLine, 'Did you mean "@openc" rather than "%s"?' % (sCurTag,));
2840
2841 #
2842 # New tag.
2843 #
2844 asSplit = sLine.split(None, 1);
2845 sCurTag = asSplit[0].lower();
2846 if len(asSplit) > 1:
2847 asCurSection = [asSplit[1],];
2848 else:
2849 asCurSection = [];
2850 aasSections = [asCurSection, ];
2851 iCurTagLine = iLine;
2852
2853 #
2854 # Process the final tag.
2855 #
2856 if not asCurSection and len(aasSections) > 1:
2857 aasSections.pop(-1);
2858 if sCurTag in self.dTagHandlers:
2859 self.dTagHandlers[sCurTag](sCurTag, aasSections, iCurTagLine, iLine);
2860 cOpTags += 1;
2861 elif sCurTag.startswith('@op'):
2862 self.errorComment(iCurTagLine, 'Unknown tag: %s' % (sCurTag));
2863 elif sCurTag == '@default':
2864 sFlatDefault = self.flattenAllSections(aasSections);
2865
2866 #
2867 # Don't allow default text in blocks containing @op*.
2868 #
2869 if cOpTags > 0 and sFlatDefault:
2870 self.errorComment(0, 'Untagged comment text is not allowed with @op*: %s' % (sFlatDefault,));
2871
2872 return True;
2873
2874 def parseMacroInvocation(self, sInvocation):
2875 """
2876 Parses a macro invocation.
2877
2878 Returns a tuple, first element is the offset following the macro
2879 invocation. The second element is a list of macro arguments, where the
2880 zero'th is the macro name.
2881 """
2882 # First the name.
2883 offOpen = sInvocation.find('(');
2884 if offOpen <= 0:
2885 self.raiseError("macro invocation open parenthesis not found");
2886 sName = sInvocation[:offOpen].strip();
2887 if not self.oReMacroName.match(sName):
2888 return self.error("invalid macro name '%s'" % (sName,));
2889 asRet = [sName, ];
2890
2891 # Arguments.
2892 iLine = self.iLine;
2893 cDepth = 1;
2894 off = offOpen + 1;
2895 offStart = off;
2896 while cDepth > 0:
2897 if off >= len(sInvocation):
2898 if iLine >= len(self.asLines):
2899 return self.error('macro invocation beyond end of file');
2900 sInvocation += self.asLines[iLine];
2901 iLine += 1;
2902 ch = sInvocation[off];
2903
2904 if ch == ',' or ch == ')':
2905 if cDepth == 1:
2906 asRet.append(sInvocation[offStart:off].strip());
2907 offStart = off + 1;
2908 if ch == ')':
2909 cDepth -= 1;
2910 elif ch == '(':
2911 cDepth += 1;
2912 off += 1;
2913
2914 return (off, asRet);
2915
2916 def findAndParseMacroInvocationEx(self, sCode, sMacro):
2917 """
2918 Returns (len(sCode), None) if not found, parseMacroInvocation result if found.
2919 """
2920 offHit = sCode.find(sMacro);
2921 if offHit >= 0 and sCode[offHit + len(sMacro):].strip()[0] == '(':
2922 offAfter, asRet = self.parseMacroInvocation(sCode[offHit:])
2923 return (offHit + offAfter, asRet);
2924 return (len(sCode), None);
2925
2926 def findAndParseMacroInvocation(self, sCode, sMacro):
2927 """
2928 Returns None if not found, arguments as per parseMacroInvocation if found.
2929 """
2930 return self.findAndParseMacroInvocationEx(sCode, sMacro)[1];
2931
2932 def findAndParseFirstMacroInvocation(self, sCode, asMacro):
2933 """
2934 Returns same as findAndParseMacroInvocation.
2935 """
2936 for sMacro in asMacro:
2937 asRet = self.findAndParseMacroInvocation(sCode, sMacro);
2938 if asRet is not None:
2939 return asRet;
2940 return None;
2941
2942 def workerIemOpMnemonicEx(self, sMacro, sStats, sAsm, sForm, sUpper, sLower, # pylint: disable=too-many-arguments
2943 sDisHints, sIemHints, asOperands):
2944 """
2945 Processes one of the a IEMOP_MNEMONIC0EX, IEMOP_MNEMONIC1EX, IEMOP_MNEMONIC2EX,
2946 IEMOP_MNEMONIC3EX, and IEMOP_MNEMONIC4EX macros.
2947 """
2948 #
2949 # Some invocation checks.
2950 #
2951 if sUpper != sUpper.upper():
2952 self.error('%s: bad a_Upper parameter: %s' % (sMacro, sUpper,));
2953 if sLower != sLower.lower():
2954 self.error('%s: bad a_Lower parameter: %s' % (sMacro, sLower,));
2955 if sUpper.lower() != sLower:
2956 self.error('%s: a_Upper and a_Lower parameters does not match: %s vs %s' % (sMacro, sUpper, sLower,));
2957 if not self.oReMnemonic.match(sLower):
2958 self.error('%s: invalid a_Lower: %s (valid: %s)' % (sMacro, sLower, self.oReMnemonic.pattern,));
2959
2960 #
2961 # Check if sIemHints tells us to not consider this macro invocation.
2962 #
2963 if sIemHints.find('IEMOPHINT_SKIP_PYTHON') >= 0:
2964 return True;
2965
2966 # Apply to the last instruction only for now.
2967 if not self.aoCurInstrs:
2968 self.addInstruction();
2969 oInstr = self.aoCurInstrs[-1];
2970 if oInstr.iLineMnemonicMacro == -1:
2971 oInstr.iLineMnemonicMacro = self.iLine;
2972 else:
2973 self.error('%s: already saw a IEMOP_MNEMONIC* macro on line %u for this instruction'
2974 % (sMacro, oInstr.iLineMnemonicMacro,));
2975
2976 # Mnemonic
2977 if oInstr.sMnemonic is None:
2978 oInstr.sMnemonic = sLower;
2979 elif oInstr.sMnemonic != sLower:
2980 self.error('%s: current instruction and a_Lower does not match: %s vs %s' % (sMacro, oInstr.sMnemonic, sLower,));
2981
2982 # Process operands.
2983 if len(oInstr.aoOperands) not in [0, len(asOperands)]:
2984 self.error('%s: number of operands given by @opN does not match macro: %s vs %s'
2985 % (sMacro, len(oInstr.aoOperands), len(asOperands),));
2986 for iOperand, sType in enumerate(asOperands):
2987 sWhere = g_kdOpTypes.get(sType, [None, None])[1];
2988 if sWhere is None:
2989 self.error('%s: unknown a_Op%u value: %s' % (sMacro, iOperand + 1, sType));
2990 if iOperand < len(oInstr.aoOperands): # error recovery.
2991 sWhere = oInstr.aoOperands[iOperand].sWhere;
2992 sType = oInstr.aoOperands[iOperand].sType;
2993 else:
2994 sWhere = 'reg';
2995 sType = 'Gb';
2996 if iOperand == len(oInstr.aoOperands):
2997 oInstr.aoOperands.append(Operand(sWhere, sType))
2998 elif oInstr.aoOperands[iOperand].sWhere != sWhere or oInstr.aoOperands[iOperand].sType != sType:
2999 self.error('%s: @op%u and a_Op%u mismatch: %s:%s vs %s:%s'
3000 % (sMacro, iOperand + 1, iOperand + 1, oInstr.aoOperands[iOperand].sWhere,
3001 oInstr.aoOperands[iOperand].sType, sWhere, sType,));
3002
3003 # Encoding.
3004 if sForm not in g_kdIemForms:
3005 self.error('%s: unknown a_Form value: %s' % (sMacro, sForm,));
3006 else:
3007 if oInstr.sEncoding is None:
3008 oInstr.sEncoding = g_kdIemForms[sForm][0];
3009 elif g_kdIemForms[sForm][0] != oInstr.sEncoding:
3010 self.error('%s: current instruction @openc and a_Form does not match: %s vs %s (%s)'
3011 % (sMacro, oInstr.sEncoding, g_kdIemForms[sForm], sForm));
3012
3013 # Check the parameter locations for the encoding.
3014 if g_kdIemForms[sForm][1] is not None:
3015 if len(g_kdIemForms[sForm][1]) != len(oInstr.aoOperands):
3016 self.error('%s: The a_Form=%s has a different operand count: %s (form) vs %s'
3017 % (sMacro, sForm, len(g_kdIemForms[sForm][1]), len(oInstr.aoOperands) ));
3018 else:
3019 for iOperand, sWhere in enumerate(g_kdIemForms[sForm][1]):
3020 if oInstr.aoOperands[iOperand].sWhere != sWhere:
3021 self.error('%s: current instruction @op%u and a_Form location does not match: %s vs %s (%s)'
3022 % (sMacro, iOperand + 1, oInstr.aoOperands[iOperand].sWhere, sWhere, sForm,));
3023
3024 # Stats.
3025 if not self.oReStatsName.match(sStats):
3026 self.error('%s: invalid a_Stats value: %s' % (sMacro, sStats,));
3027 elif oInstr.sStats is None:
3028 oInstr.sStats = sStats;
3029 elif oInstr.sStats != sStats:
3030 self.error('%s: mismatching @opstats and a_Stats value: %s vs %s'
3031 % (sMacro, oInstr.sStats, sStats,));
3032
3033 # Process the hints (simply merge with @ophints w/o checking anything).
3034 for sHint in sDisHints.split('|'):
3035 sHint = sHint.strip();
3036 if sHint.startswith('DISOPTYPE_'):
3037 sShortHint = sHint[len('DISOPTYPE_'):].lower();
3038 if sShortHint in g_kdHints:
3039 oInstr.dHints[sShortHint] = True; # (dummy value, using dictionary for speed)
3040 else:
3041 self.error('%s: unknown a_fDisHints value: %s' % (sMacro, sHint,));
3042 elif sHint != '0':
3043 self.error('%s: expected a_fDisHints value: %s' % (sMacro, sHint,));
3044
3045 for sHint in sIemHints.split('|'):
3046 sHint = sHint.strip();
3047 if sHint.startswith('IEMOPHINT_'):
3048 sShortHint = sHint[len('IEMOPHINT_'):].lower();
3049 if sShortHint in g_kdHints:
3050 oInstr.dHints[sShortHint] = True; # (dummy value, using dictionary for speed)
3051 else:
3052 self.error('%s: unknown a_fIemHints value: %s' % (sMacro, sHint,));
3053 elif sHint != '0':
3054 self.error('%s: expected a_fIemHints value: %s' % (sMacro, sHint,));
3055
3056
3057 _ = sAsm;
3058 return True;
3059
3060 def workerIemOpMnemonic(self, sMacro, sForm, sUpper, sLower, sDisHints, sIemHints, asOperands):
3061 """
3062 Processes one of the a IEMOP_MNEMONIC0, IEMOP_MNEMONIC1, IEMOP_MNEMONIC2,
3063 IEMOP_MNEMONIC3, and IEMOP_MNEMONIC4 macros.
3064 """
3065 if not asOperands:
3066 return self.workerIemOpMnemonicEx(sMacro, sLower, sLower, sForm, sUpper, sLower, sDisHints, sIemHints, asOperands);
3067 return self.workerIemOpMnemonicEx(sMacro, sLower + '_' + '_'.join(asOperands), sLower + ' ' + ','.join(asOperands),
3068 sForm, sUpper, sLower, sDisHints, sIemHints, asOperands);
3069
3070 def checkCodeForMacro(self, sCode):
3071 """
3072 Checks code for relevant macro invocation.
3073 """
3074 #
3075 # Scan macro invocations.
3076 #
3077 if sCode.find('(') > 0:
3078 # Look for instruction decoder function definitions. ASSUME single line.
3079 asArgs = self.findAndParseFirstMacroInvocation(sCode,
3080 [ 'FNIEMOP_DEF',
3081 'FNIEMOP_STUB',
3082 'FNIEMOP_STUB_1',
3083 'FNIEMOP_UD_STUB',
3084 'FNIEMOP_UD_STUB_1' ]);
3085 if asArgs is not None:
3086 sFunction = asArgs[1];
3087
3088 if not self.aoCurInstrs:
3089 self.addInstruction();
3090 for oInstr in self.aoCurInstrs:
3091 if oInstr.iLineFnIemOpMacro == -1:
3092 oInstr.iLineFnIemOpMacro = self.iLine;
3093 else:
3094 self.error('%s: already seen a FNIEMOP_XXX macro for %s' % (asArgs[0], oInstr,) );
3095 self.setInstrunctionAttrib('sFunction', sFunction);
3096 self.setInstrunctionAttrib('fStub', asArgs[0].find('STUB') > 0, fOverwrite = True);
3097 self.setInstrunctionAttrib('fUdStub', asArgs[0].find('UD_STUB') > 0, fOverwrite = True);
3098 if asArgs[0].find('STUB') > 0:
3099 self.doneInstructions();
3100 return True;
3101
3102 # IEMOP_MNEMONIC(a_Stats, a_szMnemonic) IEMOP_INC_STATS(a_Stats)
3103 asArgs = self.findAndParseMacroInvocation(sCode, 'IEMOP_MNEMONIC');
3104 if asArgs is not None:
3105 if len(self.aoCurInstrs) == 1:
3106 oInstr = self.aoCurInstrs[0];
3107 if oInstr.sStats is None:
3108 oInstr.sStats = asArgs[1];
3109 self.deriveMnemonicAndOperandsFromStats(oInstr, asArgs[1]);
3110
3111 # IEMOP_MNEMONIC0EX(a_Stats, a_szMnemonic, a_Form, a_Upper, a_Lower, a_fDisHints, a_fIemHints)
3112 asArgs = self.findAndParseMacroInvocation(sCode, 'IEMOP_MNEMONIC0EX');
3113 if asArgs is not None:
3114 self.workerIemOpMnemonicEx(asArgs[0], asArgs[1], asArgs[2], asArgs[3], asArgs[4], asArgs[5], asArgs[6], asArgs[7],
3115 []);
3116 # IEMOP_MNEMONIC1EX(a_Stats, a_szMnemonic, a_Form, a_Upper, a_Lower, a_Op1, a_fDisHints, a_fIemHints)
3117 asArgs = self.findAndParseMacroInvocation(sCode, 'IEMOP_MNEMONIC1EX');
3118 if asArgs is not None:
3119 self.workerIemOpMnemonicEx(asArgs[0], asArgs[1], asArgs[2], asArgs[3], asArgs[4], asArgs[5], asArgs[7], asArgs[8],
3120 [asArgs[6],]);
3121 # IEMOP_MNEMONIC2EX(a_Stats, a_szMnemonic, a_Form, a_Upper, a_Lower, a_Op1, a_Op2, a_fDisHints, a_fIemHints)
3122 asArgs = self.findAndParseMacroInvocation(sCode, 'IEMOP_MNEMONIC2EX');
3123 if asArgs is not None:
3124 self.workerIemOpMnemonicEx(asArgs[0], asArgs[1], asArgs[2], asArgs[3], asArgs[4], asArgs[5], asArgs[8], asArgs[9],
3125 [asArgs[6], asArgs[7]]);
3126 # IEMOP_MNEMONIC3EX(a_Stats, a_szMnemonic, a_Form, a_Upper, a_Lower, a_Op1, a_Op2, a_Op3, a_fDisHints, a_fIemHints)
3127 asArgs = self.findAndParseMacroInvocation(sCode, 'IEMOP_MNEMONIC3EX');
3128 if asArgs is not None:
3129 self.workerIemOpMnemonicEx(asArgs[0], asArgs[1], asArgs[2], asArgs[3], asArgs[4], asArgs[5], asArgs[9],
3130 asArgs[10], [asArgs[6], asArgs[7], asArgs[8],]);
3131 # IEMOP_MNEMONIC4EX(a_Stats, a_szMnemonic, a_Form, a_Upper, a_Lower, a_Op1, a_Op2, a_Op3, a_Op4, a_fDisHints,
3132 # a_fIemHints)
3133 asArgs = self.findAndParseMacroInvocation(sCode, 'IEMOP_MNEMONIC4EX');
3134 if asArgs is not None:
3135 self.workerIemOpMnemonicEx(asArgs[0], asArgs[1], asArgs[2], asArgs[3], asArgs[4], asArgs[5], asArgs[10],
3136 asArgs[11], [asArgs[6], asArgs[7], asArgs[8], asArgs[9],]);
3137
3138 # IEMOP_MNEMONIC0(a_Form, a_Upper, a_Lower, a_fDisHints, a_fIemHints)
3139 asArgs = self.findAndParseMacroInvocation(sCode, 'IEMOP_MNEMONIC0');
3140 if asArgs is not None:
3141 self.workerIemOpMnemonic(asArgs[0], asArgs[1], asArgs[2], asArgs[3], asArgs[4], asArgs[5], []);
3142 # IEMOP_MNEMONIC1(a_Form, a_Upper, a_Lower, a_Op1, a_fDisHints, a_fIemHints)
3143 asArgs = self.findAndParseMacroInvocation(sCode, 'IEMOP_MNEMONIC1');
3144 if asArgs is not None:
3145 self.workerIemOpMnemonic(asArgs[0], asArgs[1], asArgs[2], asArgs[3], asArgs[5], asArgs[6], [asArgs[4],]);
3146 # IEMOP_MNEMONIC2(a_Form, a_Upper, a_Lower, a_Op1, a_Op2, a_fDisHints, a_fIemHints)
3147 asArgs = self.findAndParseMacroInvocation(sCode, 'IEMOP_MNEMONIC2');
3148 if asArgs is not None:
3149 self.workerIemOpMnemonic(asArgs[0], asArgs[1], asArgs[2], asArgs[3], asArgs[6], asArgs[7],
3150 [asArgs[4], asArgs[5],]);
3151 # IEMOP_MNEMONIC3(a_Form, a_Upper, a_Lower, a_Op1, a_Op2, a_Op3, a_fDisHints, a_fIemHints)
3152 asArgs = self.findAndParseMacroInvocation(sCode, 'IEMOP_MNEMONIC3');
3153 if asArgs is not None:
3154 self.workerIemOpMnemonic(asArgs[0], asArgs[1], asArgs[2], asArgs[3], asArgs[7], asArgs[8],
3155 [asArgs[4], asArgs[5], asArgs[6],]);
3156 # IEMOP_MNEMONIC4(a_Form, a_Upper, a_Lower, a_Op1, a_Op2, a_Op3, a_Op4, a_fDisHints, a_fIemHints)
3157 asArgs = self.findAndParseMacroInvocation(sCode, 'IEMOP_MNEMONIC4');
3158 if asArgs is not None:
3159 self.workerIemOpMnemonic(asArgs[0], asArgs[1], asArgs[2], asArgs[3], asArgs[8], asArgs[9],
3160 [asArgs[4], asArgs[5], asArgs[6], asArgs[7],]);
3161
3162 return False;
3163
3164
3165 def parse(self):
3166 """
3167 Parses the given file.
3168 Returns number or errors.
3169 Raises exception on fatal trouble.
3170 """
3171 #self.debug('Parsing %s' % (self.sSrcFile,));
3172
3173 while self.iLine < len(self.asLines):
3174 sLine = self.asLines[self.iLine];
3175 self.iLine += 1;
3176
3177 # We only look for comments, so only lines with a slash might possibly
3178 # influence the parser state.
3179 offSlash = sLine.find('/');
3180 if offSlash >= 0:
3181 if offSlash + 1 >= len(sLine) or sLine[offSlash + 1] != '/' or self.iState != self.kiCode:
3182 offLine = 0;
3183 while offLine < len(sLine):
3184 if self.iState == self.kiCode:
3185 offHit = sLine.find('/*', offLine); # only multiline comments for now.
3186 if offHit >= 0:
3187 self.checkCodeForMacro(sLine[offLine:offHit]);
3188 self.sComment = '';
3189 self.iCommentLine = self.iLine;
3190 self.iState = self.kiCommentMulti;
3191 offLine = offHit + 2;
3192 else:
3193 self.checkCodeForMacro(sLine[offLine:]);
3194 offLine = len(sLine);
3195
3196 elif self.iState == self.kiCommentMulti:
3197 offHit = sLine.find('*/', offLine);
3198 if offHit >= 0:
3199 self.sComment += sLine[offLine:offHit];
3200 self.iState = self.kiCode;
3201 offLine = offHit + 2;
3202 self.parseComment();
3203 else:
3204 self.sComment += sLine[offLine:];
3205 offLine = len(sLine);
3206 else:
3207 assert False;
3208 # C++ line comment.
3209 elif offSlash > 0:
3210 self.checkCodeForMacro(sLine[:offSlash]);
3211
3212 # No slash, but append the line if in multi-line comment.
3213 elif self.iState == self.kiCommentMulti:
3214 #self.debug('line %d: multi' % (self.iLine,));
3215 self.sComment += sLine;
3216
3217 # No slash, but check code line for relevant macro.
3218 elif self.iState == self.kiCode and sLine.find('IEMOP_') >= 0:
3219 #self.debug('line %d: macro' % (self.iLine,));
3220 self.checkCodeForMacro(sLine);
3221
3222 # If the line is a '}' in the first position, complete the instructions.
3223 elif self.iState == self.kiCode and sLine[0] == '}':
3224 #self.debug('line %d: }' % (self.iLine,));
3225 self.doneInstructions();
3226
3227 self.doneInstructions();
3228 self.debug('%3s stubs out of %3s instructions in %s'
3229 % (self.cTotalStubs, self.cTotalInstr, os.path.basename(self.sSrcFile),));
3230 return self.printErrors();
3231
3232
3233def __parseFileByName(sSrcFile, sDefaultMap):
3234 """
3235 Parses one source file for instruction specfications.
3236 """
3237 #
3238 # Read sSrcFile into a line array.
3239 #
3240 try:
3241 oFile = open(sSrcFile, "r");
3242 except Exception as oXcpt:
3243 raise Exception("failed to open %s for reading: %s" % (sSrcFile, oXcpt,));
3244 try:
3245 asLines = oFile.readlines();
3246 except Exception as oXcpt:
3247 raise Exception("failed to read %s: %s" % (sSrcFile, oXcpt,));
3248 finally:
3249 oFile.close();
3250
3251 #
3252 # Do the parsing.
3253 #
3254 try:
3255 cErrors = SimpleParser(sSrcFile, asLines, sDefaultMap).parse();
3256 except ParserException as oXcpt:
3257 print(str(oXcpt));
3258 raise;
3259 except Exception as oXcpt:
3260 raise;
3261
3262 return cErrors;
3263
3264
3265def __doTestCopying():
3266 """
3267 Executes the asCopyTests instructions.
3268 """
3269 asErrors = [];
3270 for oDstInstr in g_aoAllInstructions:
3271 if oDstInstr.asCopyTests:
3272 for sSrcInstr in oDstInstr.asCopyTests:
3273 oSrcInstr = g_dAllInstructionsByStat.get(sSrcInstr, None);
3274 if oSrcInstr:
3275 aoSrcInstrs = [oSrcInstr,];
3276 else:
3277 aoSrcInstrs = g_dAllInstructionsByFunction.get(sSrcInstr, []);
3278 if aoSrcInstrs:
3279 for oSrcInstr in aoSrcInstrs:
3280 if oSrcInstr != oDstInstr:
3281 oDstInstr.aoTests.extend(oSrcInstr.aoTests);
3282 else:
3283 asErrors.append('%s:%s: error: @opcopytests reference "%s" matches the destination\n'
3284 % ( oDstInstr.sSrcFile, oDstInstr.iLineCreated, sSrcInstr));
3285 else:
3286 asErrors.append('%s:%s: error: @opcopytests reference "%s" not found\n'
3287 % ( oDstInstr.sSrcFile, oDstInstr.iLineCreated, sSrcInstr));
3288
3289 if asErrors:
3290 sys.stderr.write(u''.join(asErrors));
3291 return len(asErrors);
3292
3293
3294def __applyOnlyTest():
3295 """
3296 If g_aoOnlyTestInstructions contains any instructions, drop aoTests from
3297 all other instructions so that only these get tested.
3298 """
3299 if g_aoOnlyTestInstructions:
3300 for oInstr in g_aoAllInstructions:
3301 if oInstr.aoTests:
3302 if oInstr not in g_aoOnlyTestInstructions:
3303 oInstr.aoTests = [];
3304 return 0;
3305
3306def __parseAll():
3307 """
3308 Parses all the IEMAllInstruction*.cpp.h files.
3309
3310 Raises exception on failure.
3311 """
3312 sSrcDir = os.path.dirname(os.path.abspath(__file__));
3313 cErrors = 0;
3314 for sDefaultMap, sName in [
3315 ( 'one', 'IEMAllInstructionsOneByte.cpp.h'),
3316 ( 'two0f', 'IEMAllInstructionsTwoByte0f.cpp.h'),
3317 ( 'three0f38', 'IEMAllInstructionsThree0f38.cpp.h'),
3318 ( 'three0f3a', 'IEMAllInstructionsThree0f3a.cpp.h'),
3319 ( 'vexmap1', 'IEMAllInstructionsVexMap1.cpp.h'),
3320 ( 'vexmap2', 'IEMAllInstructionsVexMap2.cpp.h'),
3321 ( 'vexmap3', 'IEMAllInstructionsVexMap3.cpp.h'),
3322 ( '3dnow', 'IEMAllInstructions3DNow.cpp.h'),
3323 ]:
3324 cErrors += __parseFileByName(os.path.join(sSrcDir, sName), sDefaultMap);
3325 cErrors += __doTestCopying();
3326 cErrors += __applyOnlyTest();
3327
3328 if cErrors != 0:
3329 #raise Exception('%d parse errors' % (cErrors,));
3330 sys.exit(1);
3331 return True;
3332
3333
3334
3335__parseAll();
3336
3337
3338#
3339# Generators (may perhaps move later).
3340#
3341def generateDisassemblerTables(oDstFile = sys.stdout):
3342 """
3343 Generates disassembler tables.
3344 """
3345
3346 for sName, oMap in sorted(iter(g_dInstructionMaps.items()),
3347 key = lambda aKV: aKV[1].sEncoding + ''.join(aKV[1].asLeadOpcodes)):
3348 assert oMap.sName == sName;
3349 asLines = [];
3350
3351 asLines.append('/* Generated from: %-11s Selector: %-7s Encoding: %-7s Lead bytes opcodes: %s */'
3352 % ( oMap.sName, oMap.sSelector, oMap.sEncoding, ' '.join(oMap.asLeadOpcodes), ));
3353 asLines.append('const DISOPCODE %s[] =' % (oMap.getDisasTableName(),));
3354 asLines.append('{');
3355
3356 aoffColumns = [4, 29, 49, 65, 77, 89, 109, 125, 141, 157, 183, 199];
3357
3358 aoTableOrder = oMap.getInstructionsInTableOrder();
3359 for iInstr, oInstr in enumerate(aoTableOrder):
3360
3361 if (iInstr & 0xf) == 0:
3362 if iInstr != 0:
3363 asLines.append('');
3364 asLines.append(' /* %x */' % (iInstr >> 4,));
3365
3366 if oInstr is None:
3367 pass;#asLines.append(' /* %#04x */ None,' % (iInstr));
3368 elif isinstance(oInstr, list):
3369 asLines.append(' /* %#04x */ ComplicatedListStuffNeedingWrapper,' % (iInstr));
3370 else:
3371 sMacro = 'OP';
3372 cMaxOperands = 3;
3373 if len(oInstr.aoOperands) > 3:
3374 sMacro = 'OPVEX'
3375 cMaxOperands = 4;
3376 assert len(oInstr.aoOperands) <= cMaxOperands;
3377
3378 #
3379 # Format string.
3380 #
3381 sTmp = '%s("%s' % (sMacro, oInstr.sMnemonic,);
3382 for iOperand, oOperand in enumerate(oInstr.aoOperands):
3383 sTmp += ' ' if iOperand == 0 else ',';
3384 if g_kdOpTypes[oOperand.sType][2][0] != '%': ## @todo remove upper() later.
3385 sTmp += g_kdOpTypes[oOperand.sType][2].upper(); ## @todo remove upper() later.
3386 else:
3387 sTmp += g_kdOpTypes[oOperand.sType][2];
3388 sTmp += '",';
3389 asColumns = [ sTmp, ];
3390
3391 #
3392 # Decoders.
3393 #
3394 iStart = len(asColumns);
3395 if oInstr.sEncoding is None:
3396 pass;
3397 elif oInstr.sEncoding == 'ModR/M':
3398 # ASSUME the first operand is using the ModR/M encoding
3399 assert len(oInstr.aoOperands) >= 1 and oInstr.aoOperands[0].usesModRM();
3400 asColumns.append('IDX_ParseModRM,');
3401 ## @todo IDX_ParseVexDest
3402 # Is second operand using ModR/M too?
3403 if len(oInstr.aoOperands) > 1 and oInstr.aoOperands[1].usesModRM():
3404 asColumns.append('IDX_UseModRM,')
3405 elif oInstr.sEncoding in [ 'prefix', ]:
3406 for oOperand in oInstr.aoOperands:
3407 asColumns.append('0,');
3408 elif oInstr.sEncoding in [ 'fixed' ]:
3409 pass;
3410 elif oInstr.sEncoding == 'vex2':
3411 asColumns.append('IDX_ParseVex2b,')
3412 elif oInstr.sEncoding == 'vex3':
3413 asColumns.append('IDX_ParseVex3b,')
3414 elif oInstr.sEncoding in g_dInstructionMaps:
3415 asColumns.append(g_dInstructionMaps[oInstr.sEncoding].sDisParse + ',');
3416 else:
3417 ## @todo
3418 #IDX_ParseTwoByteEsc,
3419 #IDX_ParseGrp1,
3420 #IDX_ParseShiftGrp2,
3421 #IDX_ParseGrp3,
3422 #IDX_ParseGrp4,
3423 #IDX_ParseGrp5,
3424 #IDX_Parse3DNow,
3425 #IDX_ParseGrp6,
3426 #IDX_ParseGrp7,
3427 #IDX_ParseGrp8,
3428 #IDX_ParseGrp9,
3429 #IDX_ParseGrp10,
3430 #IDX_ParseGrp12,
3431 #IDX_ParseGrp13,
3432 #IDX_ParseGrp14,
3433 #IDX_ParseGrp15,
3434 #IDX_ParseGrp16,
3435 #IDX_ParseThreeByteEsc4,
3436 #IDX_ParseThreeByteEsc5,
3437 #IDX_ParseModFence,
3438 #IDX_ParseEscFP,
3439 #IDX_ParseNopPause,
3440 #IDX_ParseInvOpModRM,
3441 assert False, str(oInstr);
3442
3443 # Check for immediates and stuff in the remaining operands.
3444 for oOperand in oInstr.aoOperands[len(asColumns) - iStart:]:
3445 sIdx = g_kdOpTypes[oOperand.sType][0];
3446 if sIdx != 'IDX_UseModRM':
3447 asColumns.append(sIdx + ',');
3448 asColumns.extend(['0,'] * (cMaxOperands - (len(asColumns) - iStart)));
3449
3450 #
3451 # Opcode and operands.
3452 #
3453 assert oInstr.sDisEnum, str(oInstr);
3454 asColumns.append(oInstr.sDisEnum + ',');
3455 iStart = len(asColumns)
3456 for oOperand in oInstr.aoOperands:
3457 asColumns.append('OP_PARM_' + g_kdOpTypes[oOperand.sType][3] + ',');
3458 asColumns.extend(['OP_PARM_NONE,'] * (cMaxOperands - (len(asColumns) - iStart)));
3459
3460 #
3461 # Flags.
3462 #
3463 sTmp = '';
3464 for sHint in sorted(oInstr.dHints.keys()):
3465 sDefine = g_kdHints[sHint];
3466 if sDefine.startswith('DISOPTYPE_'):
3467 if sTmp:
3468 sTmp += ' | ' + sDefine;
3469 else:
3470 sTmp += sDefine;
3471 if sTmp:
3472 sTmp += '),';
3473 else:
3474 sTmp += '0),';
3475 asColumns.append(sTmp);
3476
3477 #
3478 # Format the columns into a line.
3479 #
3480 sLine = '';
3481 for i, s in enumerate(asColumns):
3482 if len(sLine) < aoffColumns[i]:
3483 sLine += ' ' * (aoffColumns[i] - len(sLine));
3484 else:
3485 sLine += ' ';
3486 sLine += s;
3487
3488 # OP("psrlw %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSRLW, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE,
3489 # DISOPTYPE_HARMLESS),
3490 # define OP(pszOpcode, idxParse1, idxParse2, idxParse3, opcode, param1, param2, param3, optype) \
3491 # { pszOpcode, idxParse1, idxParse2, idxParse3, 0, opcode, param1, param2, param3, 0, 0, optype }
3492
3493 asLines.append(sLine);
3494
3495 asLines.append('};');
3496 asLines.append('AssertCompile(RT_ELEMENTS(%s) == %s);' % (oMap.getDisasTableName(), oMap.getTableSize(),));
3497
3498 #
3499 # Write out the lines.
3500 #
3501 oDstFile.write('\n'.join(asLines));
3502 oDstFile.write('\n');
3503 break; #for now
3504
3505if __name__ == '__main__':
3506 generateDisassemblerTables();
3507
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette