i386-gen.c revision 1.8 1 1.8 christos /* Copyright (C) 2007-2022 Free Software Foundation, Inc.
2 1.1 christos
3 1.1 christos This file is part of the GNU opcodes library.
4 1.1 christos
5 1.1 christos This library is free software; you can redistribute it and/or modify
6 1.1 christos it under the terms of the GNU General Public License as published by
7 1.1 christos the Free Software Foundation; either version 3, or (at your option)
8 1.1 christos any later version.
9 1.1 christos
10 1.1 christos It is distributed in the hope that it will be useful, but WITHOUT
11 1.1 christos ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 1.1 christos or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
13 1.1 christos License for more details.
14 1.1 christos
15 1.1 christos You should have received a copy of the GNU General Public License
16 1.1 christos along with this program; if not, write to the Free Software
17 1.1 christos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
18 1.1 christos MA 02110-1301, USA. */
19 1.1 christos
20 1.1 christos #include "sysdep.h"
21 1.1 christos #include <stdio.h>
22 1.1 christos #include <errno.h>
23 1.1 christos #include "getopt.h"
24 1.1 christos #include "libiberty.h"
25 1.1 christos #include "hashtab.h"
26 1.1 christos #include "safe-ctype.h"
27 1.1 christos
28 1.1 christos #include "i386-opc.h"
29 1.1 christos
30 1.1 christos #include <libintl.h>
31 1.1 christos #define _(String) gettext (String)
32 1.1 christos
33 1.7 christos /* Build-time checks are preferrable over runtime ones. Use this construct
34 1.7 christos in preference where possible. */
35 1.7 christos #define static_assert(e) ((void)sizeof (struct { int _:1 - 2 * !(e); }))
36 1.7 christos
37 1.1 christos static const char *program_name = NULL;
38 1.1 christos static int debug = 0;
39 1.1 christos
40 1.1 christos typedef struct initializer
41 1.1 christos {
42 1.1 christos const char *name;
43 1.1 christos const char *init;
44 1.1 christos } initializer;
45 1.1 christos
46 1.1 christos static initializer cpu_flag_init[] =
47 1.1 christos {
48 1.1 christos { "CPU_UNKNOWN_FLAGS",
49 1.8 christos "~CpuIAMCU" },
50 1.1 christos { "CPU_GENERIC32_FLAGS",
51 1.1 christos "Cpu186|Cpu286|Cpu386" },
52 1.1 christos { "CPU_GENERIC64_FLAGS",
53 1.5 christos "CPU_PENTIUMPRO_FLAGS|CpuClflush|CpuSYSCALL|CPU_MMX_FLAGS|CPU_SSE2_FLAGS|CpuLM" },
54 1.1 christos { "CPU_NONE_FLAGS",
55 1.1 christos "0" },
56 1.1 christos { "CPU_I186_FLAGS",
57 1.1 christos "Cpu186" },
58 1.1 christos { "CPU_I286_FLAGS",
59 1.5 christos "CPU_I186_FLAGS|Cpu286" },
60 1.1 christos { "CPU_I386_FLAGS",
61 1.5 christos "CPU_I286_FLAGS|Cpu386" },
62 1.1 christos { "CPU_I486_FLAGS",
63 1.5 christos "CPU_I386_FLAGS|Cpu486" },
64 1.1 christos { "CPU_I586_FLAGS",
65 1.6 christos "CPU_I486_FLAGS|Cpu387|Cpu586" },
66 1.1 christos { "CPU_I686_FLAGS",
67 1.7 christos "CPU_I586_FLAGS|Cpu686|Cpu687|CpuCMOV|CpuFXSR" },
68 1.1 christos { "CPU_PENTIUMPRO_FLAGS",
69 1.5 christos "CPU_I686_FLAGS|CpuNop" },
70 1.1 christos { "CPU_P2_FLAGS",
71 1.5 christos "CPU_PENTIUMPRO_FLAGS|CPU_MMX_FLAGS" },
72 1.1 christos { "CPU_P3_FLAGS",
73 1.5 christos "CPU_P2_FLAGS|CPU_SSE_FLAGS" },
74 1.1 christos { "CPU_P4_FLAGS",
75 1.5 christos "CPU_P3_FLAGS|CpuClflush|CPU_SSE2_FLAGS" },
76 1.1 christos { "CPU_NOCONA_FLAGS",
77 1.5 christos "CPU_GENERIC64_FLAGS|CpuFISTTP|CPU_SSE3_FLAGS|CpuCX16" },
78 1.1 christos { "CPU_CORE_FLAGS",
79 1.5 christos "CPU_P4_FLAGS|CpuFISTTP|CPU_SSE3_FLAGS|CpuCX16" },
80 1.1 christos { "CPU_CORE2_FLAGS",
81 1.5 christos "CPU_NOCONA_FLAGS|CPU_SSSE3_FLAGS" },
82 1.1 christos { "CPU_COREI7_FLAGS",
83 1.5 christos "CPU_CORE2_FLAGS|CPU_SSE4_2_FLAGS|CpuRdtscp" },
84 1.1 christos { "CPU_K6_FLAGS",
85 1.5 christos "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuSYSCALL|Cpu387|CPU_MMX_FLAGS" },
86 1.1 christos { "CPU_K6_2_FLAGS",
87 1.5 christos "CPU_K6_FLAGS|Cpu3dnow" },
88 1.1 christos { "CPU_ATHLON_FLAGS",
89 1.5 christos "CPU_K6_2_FLAGS|Cpu686|Cpu687|CpuNop|Cpu3dnowA" },
90 1.1 christos { "CPU_K8_FLAGS",
91 1.5 christos "CPU_ATHLON_FLAGS|CpuRdtscp|CPU_SSE2_FLAGS|CpuLM" },
92 1.1 christos { "CPU_AMDFAM10_FLAGS",
93 1.8 christos "CPU_K8_FLAGS|CpuFISTTP|CPU_SSE4A_FLAGS|CpuLZCNT|CpuPOPCNT" },
94 1.1 christos { "CPU_BDVER1_FLAGS",
95 1.8 christos "CPU_GENERIC64_FLAGS|CpuFISTTP|CpuRdtscp|CpuCX16|CPU_XOP_FLAGS|CpuLZCNT|CpuPOPCNT|CpuLWP|CpuSVME|CpuAES|CpuPCLMUL|CpuPRFCHW" },
96 1.1 christos { "CPU_BDVER2_FLAGS",
97 1.5 christos "CPU_BDVER1_FLAGS|CpuFMA|CpuBMI|CpuTBM|CpuF16C" },
98 1.1 christos { "CPU_BDVER3_FLAGS",
99 1.5 christos "CPU_BDVER2_FLAGS|CpuXsaveopt|CpuFSGSBase" },
100 1.3 christos { "CPU_BDVER4_FLAGS",
101 1.5 christos "CPU_BDVER3_FLAGS|CpuAVX2|CpuMovbe|CpuBMI2|CpuRdRnd|CpuMWAITX" },
102 1.3 christos { "CPU_ZNVER1_FLAGS",
103 1.8 christos "CPU_GENERIC64_FLAGS|CpuFISTTP|CpuRdtscp|CpuCX16|CPU_AVX2_FLAGS|CpuSSE4A|CpuLZCNT|CpuPOPCNT|CpuSVME|CpuAES|CpuPCLMUL|CpuPRFCHW|CpuFMA|CpuBMI|CpuF16C|CpuXsaveopt|CpuFSGSBase|CpuMovbe|CpuBMI2|CpuRdRnd|CpuADX|CpuRdSeed|CpuSMAP|CpuSHA|CpuXSAVEC|CpuXSAVES|CpuClflushOpt|CpuCLZERO|CpuMWAITX" },
104 1.6 christos { "CPU_ZNVER2_FLAGS",
105 1.7 christos "CPU_ZNVER1_FLAGS|CpuCLWB|CpuRDPID|CpuRDPRU|CpuMCOMMIT|CpuWBNOINVD" },
106 1.8 christos { "CPU_ZNVER3_FLAGS",
107 1.8 christos "CPU_ZNVER2_FLAGS|CpuINVLPGB|CpuTLBSYNC|CpuVAES|CpuVPCLMULQDQ|CpuINVPCID|CpuSNP|CpuOSPKE" },
108 1.1 christos { "CPU_BTVER1_FLAGS",
109 1.8 christos "CPU_GENERIC64_FLAGS|CpuFISTTP|CpuCX16|CpuRdtscp|CPU_SSSE3_FLAGS|CpuSSE4A|CpuLZCNT|CpuPOPCNT|CpuPRFCHW|CpuCX16|CpuClflush|CpuFISTTP|CpuSVME" },
110 1.1 christos { "CPU_BTVER2_FLAGS",
111 1.6 christos "CPU_BTVER1_FLAGS|CPU_AVX_FLAGS|CpuBMI|CpuF16C|CpuAES|CpuPCLMUL|CpuMovbe|CpuXsaveopt|CpuPRFCHW" },
112 1.1 christos { "CPU_8087_FLAGS",
113 1.1 christos "Cpu8087" },
114 1.1 christos { "CPU_287_FLAGS",
115 1.6 christos "Cpu287" },
116 1.1 christos { "CPU_387_FLAGS",
117 1.6 christos "Cpu387" },
118 1.5 christos { "CPU_687_FLAGS",
119 1.5 christos "CPU_387_FLAGS|Cpu687" },
120 1.7 christos { "CPU_CMOV_FLAGS",
121 1.7 christos "CpuCMOV" },
122 1.7 christos { "CPU_FXSR_FLAGS",
123 1.7 christos "CpuFXSR" },
124 1.1 christos { "CPU_CLFLUSH_FLAGS",
125 1.1 christos "CpuClflush" },
126 1.1 christos { "CPU_NOP_FLAGS",
127 1.1 christos "CpuNop" },
128 1.1 christos { "CPU_SYSCALL_FLAGS",
129 1.1 christos "CpuSYSCALL" },
130 1.1 christos { "CPU_MMX_FLAGS",
131 1.6 christos "CpuMMX" },
132 1.1 christos { "CPU_SSE_FLAGS",
133 1.6 christos "CpuSSE" },
134 1.1 christos { "CPU_SSE2_FLAGS",
135 1.5 christos "CPU_SSE_FLAGS|CpuSSE2" },
136 1.1 christos { "CPU_SSE3_FLAGS",
137 1.5 christos "CPU_SSE2_FLAGS|CpuSSE3" },
138 1.1 christos { "CPU_SSSE3_FLAGS",
139 1.5 christos "CPU_SSE3_FLAGS|CpuSSSE3" },
140 1.1 christos { "CPU_SSE4_1_FLAGS",
141 1.5 christos "CPU_SSSE3_FLAGS|CpuSSE4_1" },
142 1.1 christos { "CPU_SSE4_2_FLAGS",
143 1.8 christos "CPU_SSE4_1_FLAGS|CpuSSE4_2|CpuPOPCNT" },
144 1.1 christos { "CPU_VMX_FLAGS",
145 1.1 christos "CpuVMX" },
146 1.1 christos { "CPU_SMX_FLAGS",
147 1.1 christos "CpuSMX" },
148 1.1 christos { "CPU_XSAVE_FLAGS",
149 1.1 christos "CpuXsave" },
150 1.1 christos { "CPU_XSAVEOPT_FLAGS",
151 1.5 christos "CPU_XSAVE_FLAGS|CpuXsaveopt" },
152 1.1 christos { "CPU_AES_FLAGS",
153 1.5 christos "CPU_SSE2_FLAGS|CpuAES" },
154 1.1 christos { "CPU_PCLMUL_FLAGS",
155 1.5 christos "CPU_SSE2_FLAGS|CpuPCLMUL" },
156 1.1 christos { "CPU_FMA_FLAGS",
157 1.5 christos "CPU_AVX_FLAGS|CpuFMA" },
158 1.1 christos { "CPU_FMA4_FLAGS",
159 1.5 christos "CPU_AVX_FLAGS|CpuFMA4" },
160 1.1 christos { "CPU_XOP_FLAGS",
161 1.5 christos "CPU_SSE4A_FLAGS|CPU_FMA4_FLAGS|CpuXOP" },
162 1.1 christos { "CPU_LWP_FLAGS",
163 1.6 christos "CPU_XSAVE_FLAGS|CpuLWP" },
164 1.1 christos { "CPU_BMI_FLAGS",
165 1.1 christos "CpuBMI" },
166 1.1 christos { "CPU_TBM_FLAGS",
167 1.1 christos "CpuTBM" },
168 1.1 christos { "CPU_MOVBE_FLAGS",
169 1.1 christos "CpuMovbe" },
170 1.3 christos { "CPU_CX16_FLAGS",
171 1.3 christos "CpuCX16" },
172 1.1 christos { "CPU_RDTSCP_FLAGS",
173 1.1 christos "CpuRdtscp" },
174 1.1 christos { "CPU_EPT_FLAGS",
175 1.1 christos "CpuEPT" },
176 1.1 christos { "CPU_FSGSBASE_FLAGS",
177 1.1 christos "CpuFSGSBase" },
178 1.1 christos { "CPU_RDRND_FLAGS",
179 1.1 christos "CpuRdRnd" },
180 1.1 christos { "CPU_F16C_FLAGS",
181 1.5 christos "CPU_AVX_FLAGS|CpuF16C" },
182 1.1 christos { "CPU_BMI2_FLAGS",
183 1.1 christos "CpuBMI2" },
184 1.1 christos { "CPU_LZCNT_FLAGS",
185 1.1 christos "CpuLZCNT" },
186 1.8 christos { "CPU_POPCNT_FLAGS",
187 1.8 christos "CpuPOPCNT" },
188 1.1 christos { "CPU_HLE_FLAGS",
189 1.1 christos "CpuHLE" },
190 1.1 christos { "CPU_RTM_FLAGS",
191 1.1 christos "CpuRTM" },
192 1.1 christos { "CPU_INVPCID_FLAGS",
193 1.1 christos "CpuINVPCID" },
194 1.1 christos { "CPU_VMFUNC_FLAGS",
195 1.1 christos "CpuVMFUNC" },
196 1.1 christos { "CPU_3DNOW_FLAGS",
197 1.5 christos "CPU_MMX_FLAGS|Cpu3dnow" },
198 1.1 christos { "CPU_3DNOWA_FLAGS",
199 1.5 christos "CPU_3DNOW_FLAGS|Cpu3dnowA" },
200 1.1 christos { "CPU_PADLOCK_FLAGS",
201 1.1 christos "CpuPadLock" },
202 1.1 christos { "CPU_SVME_FLAGS",
203 1.1 christos "CpuSVME" },
204 1.1 christos { "CPU_SSE4A_FLAGS",
205 1.5 christos "CPU_SSE3_FLAGS|CpuSSE4a" },
206 1.1 christos { "CPU_ABM_FLAGS",
207 1.8 christos "CpuLZCNT|CpuPOPCNT" },
208 1.1 christos { "CPU_AVX_FLAGS",
209 1.6 christos "CPU_SSE4_2_FLAGS|CPU_XSAVE_FLAGS|CpuAVX" },
210 1.1 christos { "CPU_AVX2_FLAGS",
211 1.5 christos "CPU_AVX_FLAGS|CpuAVX2" },
212 1.8 christos { "CPU_AVX_VNNI_FLAGS",
213 1.8 christos "CPU_AVX2_FLAGS|CpuAVX_VNNI" },
214 1.3 christos { "CPU_AVX512F_FLAGS",
215 1.7 christos "CPU_AVX2_FLAGS|CpuAVX512F" },
216 1.3 christos { "CPU_AVX512CD_FLAGS",
217 1.5 christos "CPU_AVX512F_FLAGS|CpuAVX512CD" },
218 1.3 christos { "CPU_AVX512ER_FLAGS",
219 1.5 christos "CPU_AVX512F_FLAGS|CpuAVX512ER" },
220 1.3 christos { "CPU_AVX512PF_FLAGS",
221 1.5 christos "CPU_AVX512F_FLAGS|CpuAVX512PF" },
222 1.5 christos { "CPU_AVX512DQ_FLAGS",
223 1.5 christos "CPU_AVX512F_FLAGS|CpuAVX512DQ" },
224 1.5 christos { "CPU_AVX512BW_FLAGS",
225 1.5 christos "CPU_AVX512F_FLAGS|CpuAVX512BW" },
226 1.5 christos { "CPU_AVX512VL_FLAGS",
227 1.6 christos "CPU_AVX512F_FLAGS|CpuAVX512VL" },
228 1.5 christos { "CPU_AVX512IFMA_FLAGS",
229 1.5 christos "CPU_AVX512F_FLAGS|CpuAVX512IFMA" },
230 1.5 christos { "CPU_AVX512VBMI_FLAGS",
231 1.5 christos "CPU_AVX512F_FLAGS|CpuAVX512VBMI" },
232 1.6 christos { "CPU_AVX512_4FMAPS_FLAGS",
233 1.6 christos "CPU_AVX512F_FLAGS|CpuAVX512_4FMAPS" },
234 1.6 christos { "CPU_AVX512_4VNNIW_FLAGS",
235 1.6 christos "CPU_AVX512F_FLAGS|CpuAVX512_4VNNIW" },
236 1.6 christos { "CPU_AVX512_VPOPCNTDQ_FLAGS",
237 1.6 christos "CPU_AVX512F_FLAGS|CpuAVX512_VPOPCNTDQ" },
238 1.6 christos { "CPU_AVX512_VBMI2_FLAGS",
239 1.6 christos "CPU_AVX512F_FLAGS|CpuAVX512_VBMI2" },
240 1.6 christos { "CPU_AVX512_VNNI_FLAGS",
241 1.6 christos "CPU_AVX512F_FLAGS|CpuAVX512_VNNI" },
242 1.6 christos { "CPU_AVX512_BITALG_FLAGS",
243 1.6 christos "CPU_AVX512F_FLAGS|CpuAVX512_BITALG" },
244 1.7 christos { "CPU_AVX512_BF16_FLAGS",
245 1.7 christos "CPU_AVX512F_FLAGS|CpuAVX512_BF16" },
246 1.8 christos { "CPU_AVX512_FP16_FLAGS",
247 1.8 christos "CPU_AVX512BW_FLAGS|CpuAVX512_FP16" },
248 1.3 christos { "CPU_IAMCU_FLAGS",
249 1.8 christos "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuIAMCU" },
250 1.1 christos { "CPU_ADX_FLAGS",
251 1.1 christos "CpuADX" },
252 1.1 christos { "CPU_RDSEED_FLAGS",
253 1.1 christos "CpuRdSeed" },
254 1.1 christos { "CPU_PRFCHW_FLAGS",
255 1.1 christos "CpuPRFCHW" },
256 1.3 christos { "CPU_SMAP_FLAGS",
257 1.3 christos "CpuSMAP" },
258 1.3 christos { "CPU_MPX_FLAGS",
259 1.6 christos "CPU_XSAVE_FLAGS|CpuMPX" },
260 1.3 christos { "CPU_SHA_FLAGS",
261 1.5 christos "CPU_SSE2_FLAGS|CpuSHA" },
262 1.3 christos { "CPU_CLFLUSHOPT_FLAGS",
263 1.3 christos "CpuClflushOpt" },
264 1.3 christos { "CPU_XSAVES_FLAGS",
265 1.5 christos "CPU_XSAVE_FLAGS|CpuXSAVES" },
266 1.3 christos { "CPU_XSAVEC_FLAGS",
267 1.5 christos "CPU_XSAVE_FLAGS|CpuXSAVEC" },
268 1.3 christos { "CPU_PREFETCHWT1_FLAGS",
269 1.3 christos "CpuPREFETCHWT1" },
270 1.3 christos { "CPU_SE1_FLAGS",
271 1.3 christos "CpuSE1" },
272 1.3 christos { "CPU_CLWB_FLAGS",
273 1.3 christos "CpuCLWB" },
274 1.3 christos { "CPU_CLZERO_FLAGS",
275 1.3 christos "CpuCLZERO" },
276 1.3 christos { "CPU_MWAITX_FLAGS",
277 1.3 christos "CpuMWAITX" },
278 1.3 christos { "CPU_OSPKE_FLAGS",
279 1.6 christos "CPU_XSAVE_FLAGS|CpuOSPKE" },
280 1.5 christos { "CPU_RDPID_FLAGS",
281 1.5 christos "CpuRDPID" },
282 1.6 christos { "CPU_PTWRITE_FLAGS",
283 1.6 christos "CpuPTWRITE" },
284 1.6 christos { "CPU_IBT_FLAGS",
285 1.6 christos "CpuIBT" },
286 1.6 christos { "CPU_SHSTK_FLAGS",
287 1.6 christos "CpuSHSTK" },
288 1.6 christos { "CPU_GFNI_FLAGS",
289 1.6 christos "CpuGFNI" },
290 1.6 christos { "CPU_VAES_FLAGS",
291 1.6 christos "CpuVAES" },
292 1.6 christos { "CPU_VPCLMULQDQ_FLAGS",
293 1.6 christos "CpuVPCLMULQDQ" },
294 1.6 christos { "CPU_WBNOINVD_FLAGS",
295 1.6 christos "CpuWBNOINVD" },
296 1.6 christos { "CPU_PCONFIG_FLAGS",
297 1.6 christos "CpuPCONFIG" },
298 1.6 christos { "CPU_WAITPKG_FLAGS",
299 1.6 christos "CpuWAITPKG" },
300 1.8 christos { "CPU_UINTR_FLAGS",
301 1.8 christos "CpuUINTR" },
302 1.6 christos { "CPU_CLDEMOTE_FLAGS",
303 1.6 christos "CpuCLDEMOTE" },
304 1.8 christos { "CPU_AMX_INT8_FLAGS",
305 1.8 christos "CpuAMX_INT8" },
306 1.8 christos { "CPU_AMX_BF16_FLAGS",
307 1.8 christos "CpuAMX_BF16" },
308 1.8 christos { "CPU_AMX_TILE_FLAGS",
309 1.8 christos "CpuAMX_TILE" },
310 1.6 christos { "CPU_MOVDIRI_FLAGS",
311 1.6 christos "CpuMOVDIRI" },
312 1.6 christos { "CPU_MOVDIR64B_FLAGS",
313 1.6 christos "CpuMOVDIR64B" },
314 1.7 christos { "CPU_ENQCMD_FLAGS",
315 1.7 christos "CpuENQCMD" },
316 1.8 christos { "CPU_SERIALIZE_FLAGS",
317 1.8 christos "CpuSERIALIZE" },
318 1.7 christos { "CPU_AVX512_VP2INTERSECT_FLAGS",
319 1.7 christos "CpuAVX512_VP2INTERSECT" },
320 1.8 christos { "CPU_TDX_FLAGS",
321 1.8 christos "CpuTDX" },
322 1.7 christos { "CPU_RDPRU_FLAGS",
323 1.7 christos "CpuRDPRU" },
324 1.7 christos { "CPU_MCOMMIT_FLAGS",
325 1.7 christos "CpuMCOMMIT" },
326 1.8 christos { "CPU_SEV_ES_FLAGS",
327 1.8 christos "CpuSEV_ES" },
328 1.8 christos { "CPU_TSXLDTRK_FLAGS",
329 1.8 christos "CpuTSXLDTRK"},
330 1.8 christos { "CPU_KL_FLAGS",
331 1.8 christos "CpuKL" },
332 1.8 christos { "CPU_WIDEKL_FLAGS",
333 1.8 christos "CpuWideKL" },
334 1.8 christos { "CPU_HRESET_FLAGS",
335 1.8 christos "CpuHRESET"},
336 1.8 christos { "CPU_INVLPGB_FLAGS",
337 1.8 christos "CpuINVLPGB" },
338 1.8 christos { "CPU_TLBSYNC_FLAGS",
339 1.8 christos "CpuTLBSYNC" },
340 1.8 christos { "CPU_SNP_FLAGS",
341 1.8 christos "CpuSNP" },
342 1.5 christos { "CPU_ANY_X87_FLAGS",
343 1.5 christos "CPU_ANY_287_FLAGS|Cpu8087" },
344 1.5 christos { "CPU_ANY_287_FLAGS",
345 1.5 christos "CPU_ANY_387_FLAGS|Cpu287" },
346 1.5 christos { "CPU_ANY_387_FLAGS",
347 1.5 christos "CPU_ANY_687_FLAGS|Cpu387" },
348 1.5 christos { "CPU_ANY_687_FLAGS",
349 1.5 christos "Cpu687|CpuFISTTP" },
350 1.7 christos { "CPU_ANY_CMOV_FLAGS",
351 1.7 christos "CpuCMOV" },
352 1.7 christos { "CPU_ANY_FXSR_FLAGS",
353 1.7 christos "CpuFXSR" },
354 1.5 christos { "CPU_ANY_MMX_FLAGS",
355 1.5 christos "CPU_3DNOWA_FLAGS" },
356 1.5 christos { "CPU_ANY_SSE_FLAGS",
357 1.8 christos "CPU_ANY_SSE2_FLAGS|CpuSSE" },
358 1.5 christos { "CPU_ANY_SSE2_FLAGS",
359 1.5 christos "CPU_ANY_SSE3_FLAGS|CpuSSE2" },
360 1.5 christos { "CPU_ANY_SSE3_FLAGS",
361 1.8 christos "CPU_ANY_SSSE3_FLAGS|CpuSSE3|CpuSSE4a" },
362 1.5 christos { "CPU_ANY_SSSE3_FLAGS",
363 1.5 christos "CPU_ANY_SSE4_1_FLAGS|CpuSSSE3" },
364 1.5 christos { "CPU_ANY_SSE4_1_FLAGS",
365 1.5 christos "CPU_ANY_SSE4_2_FLAGS|CpuSSE4_1" },
366 1.5 christos { "CPU_ANY_SSE4_2_FLAGS",
367 1.5 christos "CpuSSE4_2" },
368 1.8 christos { "CPU_ANY_SSE4A_FLAGS",
369 1.8 christos "CpuSSE4a" },
370 1.5 christos { "CPU_ANY_AVX_FLAGS",
371 1.5 christos "CPU_ANY_AVX2_FLAGS|CpuF16C|CpuFMA|CpuFMA4|CpuXOP|CpuAVX" },
372 1.5 christos { "CPU_ANY_AVX2_FLAGS",
373 1.7 christos "CPU_ANY_AVX512F_FLAGS|CpuAVX2" },
374 1.5 christos { "CPU_ANY_AVX512F_FLAGS",
375 1.8 christos "CpuAVX512F|CpuAVX512CD|CpuAVX512ER|CpuAVX512PF|CpuAVX512DQ|CPU_ANY_AVX512BW_FLAGS|CpuAVX512VL|CpuAVX512IFMA|CpuAVX512VBMI|CpuAVX512_4FMAPS|CpuAVX512_4VNNIW|CpuAVX512_VPOPCNTDQ|CpuAVX512_VBMI2|CpuAVX512_VNNI|CpuAVX512_BITALG|CpuAVX512_BF16|CpuAVX512_VP2INTERSECT" },
376 1.5 christos { "CPU_ANY_AVX512CD_FLAGS",
377 1.5 christos "CpuAVX512CD" },
378 1.5 christos { "CPU_ANY_AVX512ER_FLAGS",
379 1.5 christos "CpuAVX512ER" },
380 1.5 christos { "CPU_ANY_AVX512PF_FLAGS",
381 1.5 christos "CpuAVX512PF" },
382 1.5 christos { "CPU_ANY_AVX512DQ_FLAGS",
383 1.5 christos "CpuAVX512DQ" },
384 1.5 christos { "CPU_ANY_AVX512BW_FLAGS",
385 1.8 christos "CpuAVX512BW|CPU_ANY_AVX512_FP16_FLAGS" },
386 1.5 christos { "CPU_ANY_AVX512VL_FLAGS",
387 1.5 christos "CpuAVX512VL" },
388 1.5 christos { "CPU_ANY_AVX512IFMA_FLAGS",
389 1.5 christos "CpuAVX512IFMA" },
390 1.5 christos { "CPU_ANY_AVX512VBMI_FLAGS",
391 1.5 christos "CpuAVX512VBMI" },
392 1.6 christos { "CPU_ANY_AVX512_4FMAPS_FLAGS",
393 1.6 christos "CpuAVX512_4FMAPS" },
394 1.6 christos { "CPU_ANY_AVX512_4VNNIW_FLAGS",
395 1.6 christos "CpuAVX512_4VNNIW" },
396 1.6 christos { "CPU_ANY_AVX512_VPOPCNTDQ_FLAGS",
397 1.6 christos "CpuAVX512_VPOPCNTDQ" },
398 1.6 christos { "CPU_ANY_IBT_FLAGS",
399 1.6 christos "CpuIBT" },
400 1.6 christos { "CPU_ANY_SHSTK_FLAGS",
401 1.6 christos "CpuSHSTK" },
402 1.6 christos { "CPU_ANY_AVX512_VBMI2_FLAGS",
403 1.6 christos "CpuAVX512_VBMI2" },
404 1.6 christos { "CPU_ANY_AVX512_VNNI_FLAGS",
405 1.6 christos "CpuAVX512_VNNI" },
406 1.6 christos { "CPU_ANY_AVX512_BITALG_FLAGS",
407 1.6 christos "CpuAVX512_BITALG" },
408 1.7 christos { "CPU_ANY_AVX512_BF16_FLAGS",
409 1.7 christos "CpuAVX512_BF16" },
410 1.8 christos { "CPU_ANY_AMX_INT8_FLAGS",
411 1.8 christos "CpuAMX_INT8" },
412 1.8 christos { "CPU_ANY_AMX_BF16_FLAGS",
413 1.8 christos "CpuAMX_BF16" },
414 1.8 christos { "CPU_ANY_AMX_TILE_FLAGS",
415 1.8 christos "CpuAMX_TILE|CpuAMX_INT8|CpuAMX_BF16" },
416 1.8 christos { "CPU_ANY_AVX_VNNI_FLAGS",
417 1.8 christos "CpuAVX_VNNI" },
418 1.6 christos { "CPU_ANY_MOVDIRI_FLAGS",
419 1.6 christos "CpuMOVDIRI" },
420 1.8 christos { "CPU_ANY_UINTR_FLAGS",
421 1.8 christos "CpuUINTR" },
422 1.6 christos { "CPU_ANY_MOVDIR64B_FLAGS",
423 1.6 christos "CpuMOVDIR64B" },
424 1.7 christos { "CPU_ANY_ENQCMD_FLAGS",
425 1.7 christos "CpuENQCMD" },
426 1.8 christos { "CPU_ANY_SERIALIZE_FLAGS",
427 1.8 christos "CpuSERIALIZE" },
428 1.7 christos { "CPU_ANY_AVX512_VP2INTERSECT_FLAGS",
429 1.7 christos "CpuAVX512_VP2INTERSECT" },
430 1.8 christos { "CPU_ANY_TDX_FLAGS",
431 1.8 christos "CpuTDX" },
432 1.8 christos { "CPU_ANY_TSXLDTRK_FLAGS",
433 1.8 christos "CpuTSXLDTRK" },
434 1.8 christos { "CPU_ANY_KL_FLAGS",
435 1.8 christos "CpuKL|CpuWideKL" },
436 1.8 christos { "CPU_ANY_WIDEKL_FLAGS",
437 1.8 christos "CpuWideKL" },
438 1.8 christos { "CPU_ANY_HRESET_FLAGS",
439 1.8 christos "CpuHRESET" },
440 1.8 christos { "CPU_ANY_AVX512_FP16_FLAGS",
441 1.8 christos "CpuAVX512_FP16" },
442 1.1 christos };
443 1.1 christos
444 1.1 christos static initializer operand_type_init[] =
445 1.1 christos {
446 1.1 christos { "OPERAND_TYPE_NONE",
447 1.1 christos "0" },
448 1.1 christos { "OPERAND_TYPE_REG8",
449 1.7 christos "Class=Reg|Byte" },
450 1.1 christos { "OPERAND_TYPE_REG16",
451 1.7 christos "Class=Reg|Word" },
452 1.1 christos { "OPERAND_TYPE_REG32",
453 1.7 christos "Class=Reg|Dword" },
454 1.1 christos { "OPERAND_TYPE_REG64",
455 1.7 christos "Class=Reg|Qword" },
456 1.1 christos { "OPERAND_TYPE_IMM1",
457 1.1 christos "Imm1" },
458 1.1 christos { "OPERAND_TYPE_IMM8",
459 1.1 christos "Imm8" },
460 1.1 christos { "OPERAND_TYPE_IMM8S",
461 1.1 christos "Imm8S" },
462 1.1 christos { "OPERAND_TYPE_IMM16",
463 1.1 christos "Imm16" },
464 1.1 christos { "OPERAND_TYPE_IMM32",
465 1.1 christos "Imm32" },
466 1.1 christos { "OPERAND_TYPE_IMM32S",
467 1.1 christos "Imm32S" },
468 1.1 christos { "OPERAND_TYPE_IMM64",
469 1.1 christos "Imm64" },
470 1.1 christos { "OPERAND_TYPE_BASEINDEX",
471 1.1 christos "BaseIndex" },
472 1.1 christos { "OPERAND_TYPE_DISP8",
473 1.1 christos "Disp8" },
474 1.1 christos { "OPERAND_TYPE_DISP16",
475 1.1 christos "Disp16" },
476 1.1 christos { "OPERAND_TYPE_DISP32",
477 1.1 christos "Disp32" },
478 1.1 christos { "OPERAND_TYPE_DISP64",
479 1.1 christos "Disp64" },
480 1.1 christos { "OPERAND_TYPE_INOUTPORTREG",
481 1.7 christos "Instance=RegD|Word" },
482 1.1 christos { "OPERAND_TYPE_SHIFTCOUNT",
483 1.7 christos "Instance=RegC|Byte" },
484 1.1 christos { "OPERAND_TYPE_CONTROL",
485 1.7 christos "Class=RegCR" },
486 1.1 christos { "OPERAND_TYPE_TEST",
487 1.7 christos "Class=RegTR" },
488 1.1 christos { "OPERAND_TYPE_DEBUG",
489 1.7 christos "Class=RegDR" },
490 1.1 christos { "OPERAND_TYPE_FLOATREG",
491 1.7 christos "Class=Reg|Tbyte" },
492 1.1 christos { "OPERAND_TYPE_FLOATACC",
493 1.7 christos "Instance=Accum|Tbyte" },
494 1.7 christos { "OPERAND_TYPE_SREG",
495 1.7 christos "Class=SReg" },
496 1.1 christos { "OPERAND_TYPE_REGMMX",
497 1.7 christos "Class=RegMMX" },
498 1.1 christos { "OPERAND_TYPE_REGXMM",
499 1.7 christos "Class=RegSIMD|Xmmword" },
500 1.1 christos { "OPERAND_TYPE_REGYMM",
501 1.7 christos "Class=RegSIMD|Ymmword" },
502 1.3 christos { "OPERAND_TYPE_REGZMM",
503 1.7 christos "Class=RegSIMD|Zmmword" },
504 1.8 christos { "OPERAND_TYPE_REGTMM",
505 1.8 christos "Class=RegSIMD|Tmmword" },
506 1.3 christos { "OPERAND_TYPE_REGMASK",
507 1.7 christos "Class=RegMask" },
508 1.7 christos { "OPERAND_TYPE_REGBND",
509 1.7 christos "Class=RegBND" },
510 1.7 christos { "OPERAND_TYPE_ACC8",
511 1.7 christos "Instance=Accum|Byte" },
512 1.7 christos { "OPERAND_TYPE_ACC16",
513 1.7 christos "Instance=Accum|Word" },
514 1.1 christos { "OPERAND_TYPE_ACC32",
515 1.7 christos "Instance=Accum|Dword" },
516 1.1 christos { "OPERAND_TYPE_ACC64",
517 1.7 christos "Instance=Accum|Qword" },
518 1.1 christos { "OPERAND_TYPE_DISP16_32",
519 1.1 christos "Disp16|Disp32" },
520 1.1 christos { "OPERAND_TYPE_ANYDISP",
521 1.8 christos "Disp8|Disp16|Disp32|Disp64" },
522 1.1 christos { "OPERAND_TYPE_IMM16_32",
523 1.1 christos "Imm16|Imm32" },
524 1.1 christos { "OPERAND_TYPE_IMM16_32S",
525 1.1 christos "Imm16|Imm32S" },
526 1.1 christos { "OPERAND_TYPE_IMM16_32_32S",
527 1.1 christos "Imm16|Imm32|Imm32S" },
528 1.3 christos { "OPERAND_TYPE_IMM32_64",
529 1.3 christos "Imm32|Imm64" },
530 1.1 christos { "OPERAND_TYPE_IMM32_32S_DISP32",
531 1.1 christos "Imm32|Imm32S|Disp32" },
532 1.1 christos { "OPERAND_TYPE_IMM64_DISP64",
533 1.1 christos "Imm64|Disp64" },
534 1.1 christos { "OPERAND_TYPE_IMM32_32S_64_DISP32",
535 1.1 christos "Imm32|Imm32S|Imm64|Disp32" },
536 1.1 christos { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
537 1.1 christos "Imm32|Imm32S|Imm64|Disp32|Disp64" },
538 1.7 christos { "OPERAND_TYPE_ANYIMM",
539 1.7 christos "Imm1|Imm8|Imm8S|Imm16|Imm32|Imm32S|Imm64" },
540 1.1 christos };
541 1.1 christos
542 1.1 christos typedef struct bitfield
543 1.1 christos {
544 1.1 christos int position;
545 1.1 christos int value;
546 1.1 christos const char *name;
547 1.1 christos } bitfield;
548 1.1 christos
549 1.1 christos #define BITFIELD(n) { n, 0, #n }
550 1.1 christos
551 1.1 christos static bitfield cpu_flags[] =
552 1.1 christos {
553 1.1 christos BITFIELD (Cpu186),
554 1.1 christos BITFIELD (Cpu286),
555 1.1 christos BITFIELD (Cpu386),
556 1.1 christos BITFIELD (Cpu486),
557 1.1 christos BITFIELD (Cpu586),
558 1.1 christos BITFIELD (Cpu686),
559 1.7 christos BITFIELD (CpuCMOV),
560 1.7 christos BITFIELD (CpuFXSR),
561 1.1 christos BITFIELD (CpuClflush),
562 1.1 christos BITFIELD (CpuNop),
563 1.1 christos BITFIELD (CpuSYSCALL),
564 1.1 christos BITFIELD (Cpu8087),
565 1.1 christos BITFIELD (Cpu287),
566 1.1 christos BITFIELD (Cpu387),
567 1.1 christos BITFIELD (Cpu687),
568 1.1 christos BITFIELD (CpuFISTTP),
569 1.1 christos BITFIELD (CpuMMX),
570 1.1 christos BITFIELD (CpuSSE),
571 1.1 christos BITFIELD (CpuSSE2),
572 1.1 christos BITFIELD (CpuSSE3),
573 1.1 christos BITFIELD (CpuSSSE3),
574 1.1 christos BITFIELD (CpuSSE4_1),
575 1.1 christos BITFIELD (CpuSSE4_2),
576 1.1 christos BITFIELD (CpuAVX),
577 1.1 christos BITFIELD (CpuAVX2),
578 1.3 christos BITFIELD (CpuAVX512F),
579 1.3 christos BITFIELD (CpuAVX512CD),
580 1.3 christos BITFIELD (CpuAVX512ER),
581 1.3 christos BITFIELD (CpuAVX512PF),
582 1.3 christos BITFIELD (CpuAVX512VL),
583 1.3 christos BITFIELD (CpuAVX512DQ),
584 1.3 christos BITFIELD (CpuAVX512BW),
585 1.3 christos BITFIELD (CpuIAMCU),
586 1.1 christos BITFIELD (CpuSSE4a),
587 1.1 christos BITFIELD (Cpu3dnow),
588 1.1 christos BITFIELD (Cpu3dnowA),
589 1.1 christos BITFIELD (CpuPadLock),
590 1.1 christos BITFIELD (CpuSVME),
591 1.1 christos BITFIELD (CpuVMX),
592 1.1 christos BITFIELD (CpuSMX),
593 1.1 christos BITFIELD (CpuXsave),
594 1.1 christos BITFIELD (CpuXsaveopt),
595 1.1 christos BITFIELD (CpuAES),
596 1.1 christos BITFIELD (CpuPCLMUL),
597 1.1 christos BITFIELD (CpuFMA),
598 1.1 christos BITFIELD (CpuFMA4),
599 1.1 christos BITFIELD (CpuXOP),
600 1.1 christos BITFIELD (CpuLWP),
601 1.1 christos BITFIELD (CpuBMI),
602 1.1 christos BITFIELD (CpuTBM),
603 1.1 christos BITFIELD (CpuLM),
604 1.1 christos BITFIELD (CpuMovbe),
605 1.3 christos BITFIELD (CpuCX16),
606 1.1 christos BITFIELD (CpuEPT),
607 1.1 christos BITFIELD (CpuRdtscp),
608 1.1 christos BITFIELD (CpuFSGSBase),
609 1.1 christos BITFIELD (CpuRdRnd),
610 1.1 christos BITFIELD (CpuF16C),
611 1.1 christos BITFIELD (CpuBMI2),
612 1.1 christos BITFIELD (CpuLZCNT),
613 1.8 christos BITFIELD (CpuPOPCNT),
614 1.1 christos BITFIELD (CpuHLE),
615 1.1 christos BITFIELD (CpuRTM),
616 1.1 christos BITFIELD (CpuINVPCID),
617 1.1 christos BITFIELD (CpuVMFUNC),
618 1.1 christos BITFIELD (CpuRDSEED),
619 1.1 christos BITFIELD (CpuADX),
620 1.1 christos BITFIELD (CpuPRFCHW),
621 1.3 christos BITFIELD (CpuSMAP),
622 1.3 christos BITFIELD (CpuSHA),
623 1.3 christos BITFIELD (CpuClflushOpt),
624 1.3 christos BITFIELD (CpuXSAVES),
625 1.3 christos BITFIELD (CpuXSAVEC),
626 1.3 christos BITFIELD (CpuPREFETCHWT1),
627 1.3 christos BITFIELD (CpuSE1),
628 1.3 christos BITFIELD (CpuCLWB),
629 1.3 christos BITFIELD (CpuMPX),
630 1.3 christos BITFIELD (CpuAVX512IFMA),
631 1.3 christos BITFIELD (CpuAVX512VBMI),
632 1.6 christos BITFIELD (CpuAVX512_4FMAPS),
633 1.6 christos BITFIELD (CpuAVX512_4VNNIW),
634 1.6 christos BITFIELD (CpuAVX512_VPOPCNTDQ),
635 1.6 christos BITFIELD (CpuAVX512_VBMI2),
636 1.6 christos BITFIELD (CpuAVX512_VNNI),
637 1.6 christos BITFIELD (CpuAVX512_BITALG),
638 1.7 christos BITFIELD (CpuAVX512_BF16),
639 1.7 christos BITFIELD (CpuAVX512_VP2INTERSECT),
640 1.8 christos BITFIELD (CpuTDX),
641 1.8 christos BITFIELD (CpuAVX_VNNI),
642 1.8 christos BITFIELD (CpuAVX512_FP16),
643 1.3 christos BITFIELD (CpuMWAITX),
644 1.3 christos BITFIELD (CpuCLZERO),
645 1.3 christos BITFIELD (CpuOSPKE),
646 1.5 christos BITFIELD (CpuRDPID),
647 1.6 christos BITFIELD (CpuPTWRITE),
648 1.6 christos BITFIELD (CpuIBT),
649 1.6 christos BITFIELD (CpuSHSTK),
650 1.6 christos BITFIELD (CpuGFNI),
651 1.6 christos BITFIELD (CpuVAES),
652 1.6 christos BITFIELD (CpuVPCLMULQDQ),
653 1.6 christos BITFIELD (CpuWBNOINVD),
654 1.6 christos BITFIELD (CpuPCONFIG),
655 1.6 christos BITFIELD (CpuWAITPKG),
656 1.8 christos BITFIELD (CpuUINTR),
657 1.6 christos BITFIELD (CpuCLDEMOTE),
658 1.8 christos BITFIELD (CpuAMX_INT8),
659 1.8 christos BITFIELD (CpuAMX_BF16),
660 1.8 christos BITFIELD (CpuAMX_TILE),
661 1.6 christos BITFIELD (CpuMOVDIRI),
662 1.6 christos BITFIELD (CpuMOVDIR64B),
663 1.7 christos BITFIELD (CpuENQCMD),
664 1.8 christos BITFIELD (CpuSERIALIZE),
665 1.7 christos BITFIELD (CpuRDPRU),
666 1.7 christos BITFIELD (CpuMCOMMIT),
667 1.8 christos BITFIELD (CpuSEV_ES),
668 1.8 christos BITFIELD (CpuTSXLDTRK),
669 1.8 christos BITFIELD (CpuKL),
670 1.8 christos BITFIELD (CpuWideKL),
671 1.8 christos BITFIELD (CpuHRESET),
672 1.8 christos BITFIELD (CpuINVLPGB),
673 1.8 christos BITFIELD (CpuTLBSYNC),
674 1.8 christos BITFIELD (CpuSNP),
675 1.8 christos BITFIELD (Cpu64),
676 1.8 christos BITFIELD (CpuNo64),
677 1.1 christos #ifdef CpuUnused
678 1.1 christos BITFIELD (CpuUnused),
679 1.1 christos #endif
680 1.1 christos };
681 1.1 christos
682 1.1 christos static bitfield opcode_modifiers[] =
683 1.1 christos {
684 1.1 christos BITFIELD (D),
685 1.1 christos BITFIELD (W),
686 1.6 christos BITFIELD (Load),
687 1.1 christos BITFIELD (Modrm),
688 1.1 christos BITFIELD (Jump),
689 1.1 christos BITFIELD (FloatMF),
690 1.1 christos BITFIELD (FloatR),
691 1.7 christos BITFIELD (Size),
692 1.1 christos BITFIELD (CheckRegSize),
693 1.8 christos BITFIELD (DistinctDest),
694 1.8 christos BITFIELD (MnemonicSize),
695 1.7 christos BITFIELD (Anysize),
696 1.1 christos BITFIELD (No_bSuf),
697 1.1 christos BITFIELD (No_wSuf),
698 1.1 christos BITFIELD (No_lSuf),
699 1.1 christos BITFIELD (No_sSuf),
700 1.1 christos BITFIELD (No_qSuf),
701 1.1 christos BITFIELD (No_ldSuf),
702 1.1 christos BITFIELD (FWait),
703 1.1 christos BITFIELD (IsString),
704 1.7 christos BITFIELD (RegMem),
705 1.3 christos BITFIELD (BNDPrefixOk),
706 1.1 christos BITFIELD (RegKludge),
707 1.1 christos BITFIELD (Implicit1stXmm0),
708 1.8 christos BITFIELD (PrefixOk),
709 1.1 christos BITFIELD (ToDword),
710 1.1 christos BITFIELD (ToQword),
711 1.6 christos BITFIELD (AddrPrefixOpReg),
712 1.1 christos BITFIELD (IsPrefix),
713 1.1 christos BITFIELD (ImmExt),
714 1.1 christos BITFIELD (NoRex64),
715 1.1 christos BITFIELD (Ugh),
716 1.8 christos BITFIELD (PseudoVexPrefix),
717 1.1 christos BITFIELD (Vex),
718 1.1 christos BITFIELD (VexVVVV),
719 1.1 christos BITFIELD (VexW),
720 1.8 christos BITFIELD (OpcodeSpace),
721 1.8 christos BITFIELD (OpcodePrefix),
722 1.1 christos BITFIELD (VexSources),
723 1.8 christos BITFIELD (SIB),
724 1.1 christos BITFIELD (SSE2AVX),
725 1.3 christos BITFIELD (EVex),
726 1.3 christos BITFIELD (Masking),
727 1.3 christos BITFIELD (Broadcast),
728 1.3 christos BITFIELD (StaticRounding),
729 1.3 christos BITFIELD (SAE),
730 1.3 christos BITFIELD (Disp8MemShift),
731 1.3 christos BITFIELD (NoDefMask),
732 1.6 christos BITFIELD (ImplicitQuadGroup),
733 1.8 christos BITFIELD (SwapSources),
734 1.6 christos BITFIELD (Optimize),
735 1.1 christos BITFIELD (ATTMnemonic),
736 1.1 christos BITFIELD (ATTSyntax),
737 1.1 christos BITFIELD (IntelSyntax),
738 1.8 christos BITFIELD (ISA64),
739 1.1 christos };
740 1.1 christos
741 1.7 christos #define CLASS(n) #n, n
742 1.7 christos
743 1.7 christos static const struct {
744 1.7 christos const char *name;
745 1.7 christos enum operand_class value;
746 1.7 christos } operand_classes[] = {
747 1.7 christos CLASS (Reg),
748 1.7 christos CLASS (SReg),
749 1.7 christos CLASS (RegCR),
750 1.7 christos CLASS (RegDR),
751 1.7 christos CLASS (RegTR),
752 1.7 christos CLASS (RegMMX),
753 1.7 christos CLASS (RegSIMD),
754 1.7 christos CLASS (RegMask),
755 1.7 christos CLASS (RegBND),
756 1.7 christos };
757 1.7 christos
758 1.7 christos #undef CLASS
759 1.7 christos
760 1.7 christos #define INSTANCE(n) #n, n
761 1.7 christos
762 1.7 christos static const struct {
763 1.7 christos const char *name;
764 1.7 christos enum operand_instance value;
765 1.7 christos } operand_instances[] = {
766 1.7 christos INSTANCE (Accum),
767 1.7 christos INSTANCE (RegC),
768 1.7 christos INSTANCE (RegD),
769 1.7 christos INSTANCE (RegB),
770 1.7 christos };
771 1.7 christos
772 1.7 christos #undef INSTANCE
773 1.7 christos
774 1.1 christos static bitfield operand_types[] =
775 1.1 christos {
776 1.1 christos BITFIELD (Imm1),
777 1.1 christos BITFIELD (Imm8),
778 1.1 christos BITFIELD (Imm8S),
779 1.1 christos BITFIELD (Imm16),
780 1.1 christos BITFIELD (Imm32),
781 1.1 christos BITFIELD (Imm32S),
782 1.1 christos BITFIELD (Imm64),
783 1.1 christos BITFIELD (BaseIndex),
784 1.1 christos BITFIELD (Disp8),
785 1.1 christos BITFIELD (Disp16),
786 1.1 christos BITFIELD (Disp32),
787 1.1 christos BITFIELD (Disp64),
788 1.1 christos BITFIELD (Byte),
789 1.1 christos BITFIELD (Word),
790 1.1 christos BITFIELD (Dword),
791 1.1 christos BITFIELD (Fword),
792 1.1 christos BITFIELD (Qword),
793 1.1 christos BITFIELD (Tbyte),
794 1.1 christos BITFIELD (Xmmword),
795 1.1 christos BITFIELD (Ymmword),
796 1.3 christos BITFIELD (Zmmword),
797 1.8 christos BITFIELD (Tmmword),
798 1.1 christos BITFIELD (Unspecified),
799 1.1 christos #ifdef OTUnused
800 1.1 christos BITFIELD (OTUnused),
801 1.1 christos #endif
802 1.1 christos };
803 1.1 christos
804 1.1 christos static const char *filename;
805 1.6 christos static i386_cpu_flags active_cpu_flags;
806 1.6 christos static int active_isstring;
807 1.1 christos
808 1.8 christos struct template_arg {
809 1.8 christos const struct template_arg *next;
810 1.8 christos const char *val;
811 1.8 christos };
812 1.8 christos
813 1.8 christos struct template_instance {
814 1.8 christos const struct template_instance *next;
815 1.8 christos const char *name;
816 1.8 christos const struct template_arg *args;
817 1.8 christos };
818 1.8 christos
819 1.8 christos struct template_param {
820 1.8 christos const struct template_param *next;
821 1.8 christos const char *name;
822 1.8 christos };
823 1.8 christos
824 1.8 christos struct template {
825 1.8 christos const struct template *next;
826 1.8 christos const char *name;
827 1.8 christos const struct template_instance *instances;
828 1.8 christos const struct template_param *params;
829 1.8 christos };
830 1.8 christos
831 1.8 christos static const struct template *templates;
832 1.8 christos
833 1.1 christos static int
834 1.1 christos compare (const void *x, const void *y)
835 1.1 christos {
836 1.1 christos const bitfield *xp = (const bitfield *) x;
837 1.1 christos const bitfield *yp = (const bitfield *) y;
838 1.1 christos return xp->position - yp->position;
839 1.1 christos }
840 1.1 christos
841 1.1 christos static void
842 1.1 christos fail (const char *message, ...)
843 1.1 christos {
844 1.1 christos va_list args;
845 1.1 christos
846 1.1 christos va_start (args, message);
847 1.6 christos fprintf (stderr, _("%s: error: "), program_name);
848 1.1 christos vfprintf (stderr, message, args);
849 1.1 christos va_end (args);
850 1.1 christos xexit (1);
851 1.1 christos }
852 1.1 christos
853 1.1 christos static void
854 1.1 christos process_copyright (FILE *fp)
855 1.1 christos {
856 1.1 christos fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
857 1.8 christos /* Copyright (C) 2007-2022 Free Software Foundation, Inc.\n\
858 1.1 christos \n\
859 1.1 christos This file is part of the GNU opcodes library.\n\
860 1.1 christos \n\
861 1.1 christos This library is free software; you can redistribute it and/or modify\n\
862 1.1 christos it under the terms of the GNU General Public License as published by\n\
863 1.1 christos the Free Software Foundation; either version 3, or (at your option)\n\
864 1.1 christos any later version.\n\
865 1.1 christos \n\
866 1.1 christos It is distributed in the hope that it will be useful, but WITHOUT\n\
867 1.1 christos ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
868 1.1 christos or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
869 1.1 christos License for more details.\n\
870 1.1 christos \n\
871 1.1 christos You should have received a copy of the GNU General Public License\n\
872 1.1 christos along with this program; if not, write to the Free Software\n\
873 1.1 christos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
874 1.1 christos MA 02110-1301, USA. */\n");
875 1.1 christos }
876 1.1 christos
877 1.1 christos /* Remove leading white spaces. */
878 1.1 christos
879 1.1 christos static char *
880 1.1 christos remove_leading_whitespaces (char *str)
881 1.1 christos {
882 1.1 christos while (ISSPACE (*str))
883 1.1 christos str++;
884 1.1 christos return str;
885 1.1 christos }
886 1.1 christos
887 1.1 christos /* Remove trailing white spaces. */
888 1.1 christos
889 1.1 christos static void
890 1.1 christos remove_trailing_whitespaces (char *str)
891 1.1 christos {
892 1.1 christos size_t last = strlen (str);
893 1.1 christos
894 1.1 christos if (last == 0)
895 1.1 christos return;
896 1.1 christos
897 1.1 christos do
898 1.1 christos {
899 1.1 christos last--;
900 1.1 christos if (ISSPACE (str [last]))
901 1.1 christos str[last] = '\0';
902 1.1 christos else
903 1.1 christos break;
904 1.1 christos }
905 1.1 christos while (last != 0);
906 1.1 christos }
907 1.1 christos
908 1.1 christos /* Find next field separated by SEP and terminate it. Return a
909 1.1 christos pointer to the one after it. */
910 1.1 christos
911 1.1 christos static char *
912 1.1 christos next_field (char *str, char sep, char **next, char *last)
913 1.1 christos {
914 1.1 christos char *p;
915 1.1 christos
916 1.1 christos p = remove_leading_whitespaces (str);
917 1.1 christos for (str = p; *str != sep && *str != '\0'; str++);
918 1.1 christos
919 1.1 christos *str = '\0';
920 1.1 christos remove_trailing_whitespaces (p);
921 1.1 christos
922 1.1 christos *next = str + 1;
923 1.1 christos
924 1.1 christos if (p >= last)
925 1.1 christos abort ();
926 1.1 christos
927 1.1 christos return p;
928 1.1 christos }
929 1.1 christos
930 1.5 christos static void set_bitfield (char *, bitfield *, int, unsigned int, int);
931 1.5 christos
932 1.5 christos static int
933 1.7 christos set_bitfield_from_cpu_flag_init (char *f, bitfield *array, unsigned int size,
934 1.7 christos int lineno)
935 1.5 christos {
936 1.5 christos char *str, *next, *last;
937 1.5 christos unsigned int i;
938 1.5 christos
939 1.5 christos for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
940 1.5 christos if (strcmp (cpu_flag_init[i].name, f) == 0)
941 1.5 christos {
942 1.5 christos /* Turn on selective bits. */
943 1.5 christos char *init = xstrdup (cpu_flag_init[i].init);
944 1.5 christos last = init + strlen (init);
945 1.5 christos for (next = init; next && next < last; )
946 1.5 christos {
947 1.5 christos str = next_field (next, '|', &next, last);
948 1.5 christos if (str)
949 1.5 christos set_bitfield (str, array, 1, size, lineno);
950 1.5 christos }
951 1.5 christos free (init);
952 1.5 christos return 0;
953 1.5 christos }
954 1.5 christos
955 1.5 christos return -1;
956 1.5 christos }
957 1.5 christos
958 1.1 christos static void
959 1.5 christos set_bitfield (char *f, bitfield *array, int value,
960 1.1 christos unsigned int size, int lineno)
961 1.1 christos {
962 1.1 christos unsigned int i;
963 1.1 christos
964 1.8 christos /* Ignore empty fields; they may result from template expansions. */
965 1.8 christos if (*f == '\0')
966 1.8 christos return;
967 1.1 christos
968 1.1 christos for (i = 0; i < size; i++)
969 1.1 christos if (strcasecmp (array[i].name, f) == 0)
970 1.1 christos {
971 1.1 christos array[i].value = value;
972 1.1 christos return;
973 1.1 christos }
974 1.1 christos
975 1.1 christos if (value)
976 1.1 christos {
977 1.1 christos const char *v = strchr (f, '=');
978 1.1 christos
979 1.1 christos if (v)
980 1.1 christos {
981 1.1 christos size_t n = v - f;
982 1.1 christos char *end;
983 1.1 christos
984 1.1 christos for (i = 0; i < size; i++)
985 1.1 christos if (strncasecmp (array[i].name, f, n) == 0)
986 1.1 christos {
987 1.1 christos value = strtol (v + 1, &end, 0);
988 1.1 christos if (*end == '\0')
989 1.1 christos {
990 1.1 christos array[i].value = value;
991 1.1 christos return;
992 1.1 christos }
993 1.1 christos break;
994 1.1 christos }
995 1.1 christos }
996 1.1 christos }
997 1.1 christos
998 1.7 christos /* Handle CPU_XXX_FLAGS. */
999 1.7 christos if (value == 1 && !set_bitfield_from_cpu_flag_init (f, array, size, lineno))
1000 1.5 christos return;
1001 1.5 christos
1002 1.1 christos if (lineno != -1)
1003 1.6 christos fail (_("%s: %d: unknown bitfield: %s\n"), filename, lineno, f);
1004 1.1 christos else
1005 1.6 christos fail (_("unknown bitfield: %s\n"), f);
1006 1.1 christos }
1007 1.1 christos
1008 1.1 christos static void
1009 1.1 christos output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
1010 1.1 christos int macro, const char *comma, const char *indent)
1011 1.1 christos {
1012 1.1 christos unsigned int i;
1013 1.1 christos
1014 1.6 christos memset (&active_cpu_flags, 0, sizeof(active_cpu_flags));
1015 1.6 christos
1016 1.1 christos fprintf (table, "%s{ { ", indent);
1017 1.1 christos
1018 1.1 christos for (i = 0; i < size - 1; i++)
1019 1.1 christos {
1020 1.3 christos if (((i + 1) % 20) != 0)
1021 1.3 christos fprintf (table, "%d, ", flags[i].value);
1022 1.3 christos else
1023 1.3 christos fprintf (table, "%d,", flags[i].value);
1024 1.1 christos if (((i + 1) % 20) == 0)
1025 1.1 christos {
1026 1.1 christos /* We need \\ for macro. */
1027 1.1 christos if (macro)
1028 1.1 christos fprintf (table, " \\\n %s", indent);
1029 1.1 christos else
1030 1.1 christos fprintf (table, "\n %s", indent);
1031 1.1 christos }
1032 1.6 christos if (flags[i].value)
1033 1.6 christos active_cpu_flags.array[i / 32] |= 1U << (i % 32);
1034 1.1 christos }
1035 1.1 christos
1036 1.1 christos fprintf (table, "%d } }%s\n", flags[i].value, comma);
1037 1.1 christos }
1038 1.1 christos
1039 1.1 christos static void
1040 1.1 christos process_i386_cpu_flag (FILE *table, char *flag, int macro,
1041 1.1 christos const char *comma, const char *indent,
1042 1.1 christos int lineno)
1043 1.1 christos {
1044 1.8 christos char *str, *next = flag, *last;
1045 1.1 christos unsigned int i;
1046 1.8 christos int value = 1;
1047 1.1 christos bitfield flags [ARRAY_SIZE (cpu_flags)];
1048 1.1 christos
1049 1.1 christos /* Copy the default cpu flags. */
1050 1.1 christos memcpy (flags, cpu_flags, sizeof (cpu_flags));
1051 1.1 christos
1052 1.8 christos if (flag[0] == '~')
1053 1.1 christos {
1054 1.1 christos last = flag + strlen (flag);
1055 1.1 christos
1056 1.1 christos if (flag[1] == '(')
1057 1.1 christos {
1058 1.1 christos last -= 1;
1059 1.1 christos next = flag + 2;
1060 1.1 christos if (*last != ')')
1061 1.6 christos fail (_("%s: %d: missing `)' in bitfield: %s\n"), filename,
1062 1.1 christos lineno, flag);
1063 1.1 christos *last = '\0';
1064 1.1 christos }
1065 1.1 christos else
1066 1.1 christos next = flag + 1;
1067 1.1 christos
1068 1.8 christos /* First we turn on everything except for cpu64, cpuno64, and - if
1069 1.8 christos present - the padding field. */
1070 1.1 christos for (i = 0; i < ARRAY_SIZE (flags); i++)
1071 1.8 christos if (flags[i].position < Cpu64)
1072 1.1 christos flags[i].value = 1;
1073 1.1 christos
1074 1.1 christos /* Turn off selective bits. */
1075 1.8 christos value = 0;
1076 1.1 christos }
1077 1.8 christos
1078 1.8 christos if (strcmp (flag, "0"))
1079 1.1 christos {
1080 1.8 christos /* Turn on/off selective bits. */
1081 1.1 christos last = flag + strlen (flag);
1082 1.8 christos for (; next && next < last; )
1083 1.1 christos {
1084 1.1 christos str = next_field (next, '|', &next, last);
1085 1.1 christos if (str)
1086 1.8 christos set_bitfield (str, flags, value, ARRAY_SIZE (flags), lineno);
1087 1.1 christos }
1088 1.1 christos }
1089 1.1 christos
1090 1.1 christos output_cpu_flags (table, flags, ARRAY_SIZE (flags), macro,
1091 1.1 christos comma, indent);
1092 1.1 christos }
1093 1.1 christos
1094 1.1 christos static void
1095 1.1 christos output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
1096 1.1 christos {
1097 1.1 christos unsigned int i;
1098 1.1 christos
1099 1.1 christos fprintf (table, " { ");
1100 1.1 christos
1101 1.1 christos for (i = 0; i < size - 1; i++)
1102 1.1 christos {
1103 1.3 christos if (((i + 1) % 20) != 0)
1104 1.3 christos fprintf (table, "%d, ", modifier[i].value);
1105 1.3 christos else
1106 1.3 christos fprintf (table, "%d,", modifier[i].value);
1107 1.1 christos if (((i + 1) % 20) == 0)
1108 1.1 christos fprintf (table, "\n ");
1109 1.1 christos }
1110 1.1 christos
1111 1.1 christos fprintf (table, "%d },\n", modifier[i].value);
1112 1.1 christos }
1113 1.1 christos
1114 1.7 christos static int
1115 1.7 christos adjust_broadcast_modifier (char **opnd)
1116 1.7 christos {
1117 1.7 christos char *str, *next, *last, *op;
1118 1.7 christos int bcst_type = INT_MAX;
1119 1.7 christos
1120 1.7 christos /* Skip the immediate operand. */
1121 1.7 christos op = opnd[0];
1122 1.7 christos if (strcasecmp(op, "Imm8") == 0)
1123 1.7 christos op = opnd[1];
1124 1.7 christos
1125 1.7 christos op = xstrdup (op);
1126 1.7 christos last = op + strlen (op);
1127 1.7 christos for (next = op; next && next < last; )
1128 1.7 christos {
1129 1.7 christos str = next_field (next, '|', &next, last);
1130 1.7 christos if (str)
1131 1.7 christos {
1132 1.7 christos if (strcasecmp(str, "Byte") == 0)
1133 1.7 christos {
1134 1.7 christos /* The smalest broadcast type, no need to check
1135 1.7 christos further. */
1136 1.7 christos bcst_type = BYTE_BROADCAST;
1137 1.7 christos break;
1138 1.7 christos }
1139 1.7 christos else if (strcasecmp(str, "Word") == 0)
1140 1.7 christos {
1141 1.7 christos if (bcst_type > WORD_BROADCAST)
1142 1.7 christos bcst_type = WORD_BROADCAST;
1143 1.7 christos }
1144 1.7 christos else if (strcasecmp(str, "Dword") == 0)
1145 1.7 christos {
1146 1.7 christos if (bcst_type > DWORD_BROADCAST)
1147 1.7 christos bcst_type = DWORD_BROADCAST;
1148 1.7 christos }
1149 1.7 christos else if (strcasecmp(str, "Qword") == 0)
1150 1.7 christos {
1151 1.7 christos if (bcst_type > QWORD_BROADCAST)
1152 1.7 christos bcst_type = QWORD_BROADCAST;
1153 1.7 christos }
1154 1.7 christos }
1155 1.7 christos }
1156 1.7 christos free (op);
1157 1.7 christos
1158 1.7 christos if (bcst_type == INT_MAX)
1159 1.7 christos fail (_("unknown broadcast operand: %s\n"), op);
1160 1.7 christos
1161 1.7 christos return bcst_type;
1162 1.7 christos }
1163 1.7 christos
1164 1.1 christos static void
1165 1.8 christos process_i386_opcode_modifier (FILE *table, char *mod, unsigned int space,
1166 1.8 christos unsigned int prefix, char **opnd, int lineno)
1167 1.1 christos {
1168 1.1 christos char *str, *next, *last;
1169 1.1 christos bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
1170 1.1 christos
1171 1.6 christos active_isstring = 0;
1172 1.6 christos
1173 1.1 christos /* Copy the default opcode modifier. */
1174 1.1 christos memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
1175 1.1 christos
1176 1.1 christos if (strcmp (mod, "0"))
1177 1.1 christos {
1178 1.7 christos unsigned int have_w = 0, bwlq_suf = 0xf;
1179 1.7 christos
1180 1.1 christos last = mod + strlen (mod);
1181 1.1 christos for (next = mod; next && next < last; )
1182 1.1 christos {
1183 1.1 christos str = next_field (next, '|', &next, last);
1184 1.1 christos if (str)
1185 1.6 christos {
1186 1.7 christos int val = 1;
1187 1.7 christos if (strcasecmp(str, "Broadcast") == 0)
1188 1.8 christos val = adjust_broadcast_modifier (opnd);
1189 1.8 christos
1190 1.7 christos set_bitfield (str, modifiers, val, ARRAY_SIZE (modifiers),
1191 1.8 christos lineno);
1192 1.6 christos if (strcasecmp(str, "IsString") == 0)
1193 1.6 christos active_isstring = 1;
1194 1.7 christos
1195 1.7 christos if (strcasecmp(str, "W") == 0)
1196 1.7 christos have_w = 1;
1197 1.7 christos
1198 1.7 christos if (strcasecmp(str, "No_bSuf") == 0)
1199 1.7 christos bwlq_suf &= ~1;
1200 1.7 christos if (strcasecmp(str, "No_wSuf") == 0)
1201 1.7 christos bwlq_suf &= ~2;
1202 1.7 christos if (strcasecmp(str, "No_lSuf") == 0)
1203 1.7 christos bwlq_suf &= ~4;
1204 1.7 christos if (strcasecmp(str, "No_qSuf") == 0)
1205 1.7 christos bwlq_suf &= ~8;
1206 1.6 christos }
1207 1.1 christos }
1208 1.7 christos
1209 1.8 christos if (space)
1210 1.8 christos {
1211 1.8 christos if (!modifiers[OpcodeSpace].value)
1212 1.8 christos modifiers[OpcodeSpace].value = space;
1213 1.8 christos else if (modifiers[OpcodeSpace].value != space)
1214 1.8 christos fail (_("%s:%d: Conflicting opcode space specifications\n"),
1215 1.8 christos filename, lineno);
1216 1.8 christos else
1217 1.8 christos fprintf (stderr,
1218 1.8 christos _("%s:%d: Warning: redundant opcode space specification\n"),
1219 1.8 christos filename, lineno);
1220 1.8 christos }
1221 1.8 christos
1222 1.8 christos if (prefix)
1223 1.8 christos {
1224 1.8 christos if (!modifiers[OpcodePrefix].value)
1225 1.8 christos modifiers[OpcodePrefix].value = prefix;
1226 1.8 christos else if (modifiers[OpcodePrefix].value != prefix)
1227 1.8 christos fail (_("%s:%d: Conflicting prefix specifications\n"),
1228 1.8 christos filename, lineno);
1229 1.8 christos else
1230 1.8 christos fprintf (stderr,
1231 1.8 christos _("%s:%d: Warning: redundant prefix specification\n"),
1232 1.8 christos filename, lineno);
1233 1.8 christos }
1234 1.8 christos
1235 1.7 christos if (have_w && !bwlq_suf)
1236 1.7 christos fail ("%s: %d: stray W modifier\n", filename, lineno);
1237 1.7 christos if (have_w && !(bwlq_suf & 1))
1238 1.7 christos fprintf (stderr, "%s: %d: W modifier without Byte operand(s)\n",
1239 1.7 christos filename, lineno);
1240 1.7 christos if (have_w && !(bwlq_suf & ~1))
1241 1.7 christos fprintf (stderr,
1242 1.7 christos "%s: %d: W modifier without Word/Dword/Qword operand(s)\n",
1243 1.7 christos filename, lineno);
1244 1.1 christos }
1245 1.1 christos output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
1246 1.1 christos }
1247 1.1 christos
1248 1.6 christos enum stage {
1249 1.6 christos stage_macros,
1250 1.6 christos stage_opcodes,
1251 1.6 christos stage_registers,
1252 1.6 christos };
1253 1.6 christos
1254 1.1 christos static void
1255 1.7 christos output_operand_type (FILE *table, enum operand_class class,
1256 1.7 christos enum operand_instance instance,
1257 1.7 christos const bitfield *types, unsigned int size,
1258 1.6 christos enum stage stage, const char *indent)
1259 1.1 christos {
1260 1.1 christos unsigned int i;
1261 1.1 christos
1262 1.7 christos fprintf (table, "{ { %d, %d, ", class, instance);
1263 1.1 christos
1264 1.1 christos for (i = 0; i < size - 1; i++)
1265 1.1 christos {
1266 1.7 christos if (((i + 3) % 20) != 0)
1267 1.3 christos fprintf (table, "%d, ", types[i].value);
1268 1.3 christos else
1269 1.3 christos fprintf (table, "%d,", types[i].value);
1270 1.7 christos if (((i + 3) % 20) == 0)
1271 1.1 christos {
1272 1.1 christos /* We need \\ for macro. */
1273 1.6 christos if (stage == stage_macros)
1274 1.3 christos fprintf (table, " \\\n%s", indent);
1275 1.1 christos else
1276 1.1 christos fprintf (table, "\n%s", indent);
1277 1.1 christos }
1278 1.1 christos }
1279 1.1 christos
1280 1.1 christos fprintf (table, "%d } }", types[i].value);
1281 1.1 christos }
1282 1.1 christos
1283 1.1 christos static void
1284 1.6 christos process_i386_operand_type (FILE *table, char *op, enum stage stage,
1285 1.1 christos const char *indent, int lineno)
1286 1.1 christos {
1287 1.1 christos char *str, *next, *last;
1288 1.7 christos enum operand_class class = ClassNone;
1289 1.7 christos enum operand_instance instance = InstanceNone;
1290 1.1 christos bitfield types [ARRAY_SIZE (operand_types)];
1291 1.1 christos
1292 1.1 christos /* Copy the default operand type. */
1293 1.1 christos memcpy (types, operand_types, sizeof (types));
1294 1.1 christos
1295 1.1 christos if (strcmp (op, "0"))
1296 1.1 christos {
1297 1.6 christos int baseindex = 0;
1298 1.6 christos
1299 1.1 christos last = op + strlen (op);
1300 1.1 christos for (next = op; next && next < last; )
1301 1.1 christos {
1302 1.1 christos str = next_field (next, '|', &next, last);
1303 1.1 christos if (str)
1304 1.6 christos {
1305 1.7 christos unsigned int i;
1306 1.7 christos
1307 1.7 christos if (!strncmp(str, "Class=", 6))
1308 1.7 christos {
1309 1.7 christos for (i = 0; i < ARRAY_SIZE(operand_classes); ++i)
1310 1.7 christos if (!strcmp(str + 6, operand_classes[i].name))
1311 1.7 christos {
1312 1.7 christos class = operand_classes[i].value;
1313 1.7 christos str = NULL;
1314 1.7 christos break;
1315 1.7 christos }
1316 1.7 christos }
1317 1.7 christos
1318 1.7 christos if (str && !strncmp(str, "Instance=", 9))
1319 1.7 christos {
1320 1.7 christos for (i = 0; i < ARRAY_SIZE(operand_instances); ++i)
1321 1.7 christos if (!strcmp(str + 9, operand_instances[i].name))
1322 1.7 christos {
1323 1.7 christos instance = operand_instances[i].value;
1324 1.7 christos str = NULL;
1325 1.7 christos break;
1326 1.7 christos }
1327 1.7 christos }
1328 1.7 christos }
1329 1.7 christos if (str)
1330 1.7 christos {
1331 1.6 christos set_bitfield (str, types, 1, ARRAY_SIZE (types), lineno);
1332 1.6 christos if (strcasecmp(str, "BaseIndex") == 0)
1333 1.6 christos baseindex = 1;
1334 1.6 christos }
1335 1.6 christos }
1336 1.6 christos
1337 1.6 christos if (stage == stage_opcodes && baseindex && !active_isstring)
1338 1.6 christos {
1339 1.6 christos set_bitfield("Disp8", types, 1, ARRAY_SIZE (types), lineno);
1340 1.6 christos if (!active_cpu_flags.bitfield.cpu64
1341 1.6 christos && !active_cpu_flags.bitfield.cpumpx)
1342 1.6 christos set_bitfield("Disp16", types, 1, ARRAY_SIZE (types), lineno);
1343 1.8 christos set_bitfield("Disp32", types, 1, ARRAY_SIZE (types), lineno);
1344 1.1 christos }
1345 1.1 christos }
1346 1.7 christos output_operand_type (table, class, instance, types, ARRAY_SIZE (types),
1347 1.7 christos stage, indent);
1348 1.1 christos }
1349 1.1 christos
1350 1.1 christos static void
1351 1.1 christos output_i386_opcode (FILE *table, const char *name, char *str,
1352 1.1 christos char *last, int lineno)
1353 1.1 christos {
1354 1.8 christos unsigned int i, length, prefix = 0, space = 0;
1355 1.8 christos char *base_opcode, *extension_opcode, *end;
1356 1.1 christos char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
1357 1.8 christos unsigned long long opcode;
1358 1.1 christos
1359 1.1 christos /* Find base_opcode. */
1360 1.1 christos base_opcode = next_field (str, ',', &str, last);
1361 1.1 christos
1362 1.1 christos /* Find extension_opcode. */
1363 1.1 christos extension_opcode = next_field (str, ',', &str, last);
1364 1.1 christos
1365 1.1 christos /* Find cpu_flags. */
1366 1.1 christos cpu_flags = next_field (str, ',', &str, last);
1367 1.1 christos
1368 1.1 christos /* Find opcode_modifier. */
1369 1.1 christos opcode_modifier = next_field (str, ',', &str, last);
1370 1.1 christos
1371 1.1 christos /* Remove the first {. */
1372 1.1 christos str = remove_leading_whitespaces (str);
1373 1.1 christos if (*str != '{')
1374 1.1 christos abort ();
1375 1.1 christos str = remove_leading_whitespaces (str + 1);
1376 1.8 christos remove_trailing_whitespaces (str);
1377 1.1 christos
1378 1.8 christos /* Remove } and trailing white space. */
1379 1.1 christos i = strlen (str);
1380 1.8 christos if (!i || str[i - 1] != '}')
1381 1.1 christos abort ();
1382 1.8 christos str[--i] = '\0';
1383 1.8 christos remove_trailing_whitespaces (str);
1384 1.1 christos
1385 1.8 christos if (!*str)
1386 1.8 christos operand_types [i = 0] = NULL;
1387 1.8 christos else
1388 1.1 christos {
1389 1.8 christos last = str + strlen (str);
1390 1.8 christos
1391 1.8 christos /* Find operand_types. */
1392 1.8 christos for (i = 0; i < ARRAY_SIZE (operand_types); i++)
1393 1.8 christos {
1394 1.8 christos if (str >= last)
1395 1.8 christos {
1396 1.8 christos operand_types [i] = NULL;
1397 1.8 christos break;
1398 1.8 christos }
1399 1.8 christos
1400 1.8 christos operand_types [i] = next_field (str, ',', &str, last);
1401 1.8 christos }
1402 1.1 christos }
1403 1.1 christos
1404 1.8 christos opcode = strtoull (base_opcode, &end, 0);
1405 1.1 christos
1406 1.8 christos /* Determine opcode length. */
1407 1.8 christos for (length = 1; length < 8; ++length)
1408 1.8 christos if (!(opcode >> (8 * length)))
1409 1.8 christos break;
1410 1.8 christos
1411 1.8 christos /* Transform prefixes encoded in the opcode into opcode modifier
1412 1.8 christos representation. */
1413 1.8 christos if (length > 1)
1414 1.1 christos {
1415 1.8 christos switch (opcode >> (8 * length - 8))
1416 1.1 christos {
1417 1.8 christos case 0x66: prefix = PREFIX_0X66; break;
1418 1.8 christos case 0xF3: prefix = PREFIX_0XF3; break;
1419 1.8 christos case 0xF2: prefix = PREFIX_0XF2; break;
1420 1.1 christos }
1421 1.1 christos
1422 1.8 christos if (prefix)
1423 1.8 christos opcode &= (1ULL << (8 * --length)) - 1;
1424 1.8 christos }
1425 1.8 christos
1426 1.8 christos /* Transform opcode space encoded in the opcode into opcode modifier
1427 1.8 christos representation. */
1428 1.8 christos if (length > 1 && (opcode >> (8 * length - 8)) == 0xf)
1429 1.8 christos {
1430 1.8 christos switch ((opcode >> (8 * length - 16)) & 0xff)
1431 1.1 christos {
1432 1.8 christos default: space = SPACE_0F; break;
1433 1.8 christos case 0x38: space = SPACE_0F38; break;
1434 1.8 christos case 0x3A: space = SPACE_0F3A; break;
1435 1.1 christos }
1436 1.8 christos
1437 1.8 christos if (space != SPACE_0F && --length == 1)
1438 1.8 christos fail (_("%s:%d: %s: unrecognized opcode encoding space\n"),
1439 1.8 christos filename, lineno, name);
1440 1.8 christos opcode &= (1ULL << (8 * --length)) - 1;
1441 1.1 christos }
1442 1.1 christos
1443 1.8 christos if (length > 2)
1444 1.8 christos fail (_("%s:%d: %s: residual opcode (0x%0*llx) too large\n"),
1445 1.8 christos filename, lineno, name, 2 * length, opcode);
1446 1.8 christos
1447 1.8 christos fprintf (table, " { \"%s\", 0x%0*llx%s, %s, %lu,\n",
1448 1.8 christos name, 2 * (int)length, opcode, end, extension_opcode, i);
1449 1.8 christos
1450 1.8 christos process_i386_opcode_modifier (table, opcode_modifier, space, prefix,
1451 1.8 christos operand_types, lineno);
1452 1.1 christos
1453 1.1 christos process_i386_cpu_flag (table, cpu_flags, 0, ",", " ", lineno);
1454 1.1 christos
1455 1.1 christos fprintf (table, " { ");
1456 1.1 christos
1457 1.1 christos for (i = 0; i < ARRAY_SIZE (operand_types); i++)
1458 1.1 christos {
1459 1.8 christos if (!operand_types[i])
1460 1.1 christos {
1461 1.1 christos if (i == 0)
1462 1.6 christos process_i386_operand_type (table, "0", stage_opcodes, "\t ",
1463 1.6 christos lineno);
1464 1.1 christos break;
1465 1.1 christos }
1466 1.1 christos
1467 1.1 christos if (i != 0)
1468 1.1 christos fprintf (table, ",\n ");
1469 1.1 christos
1470 1.6 christos process_i386_operand_type (table, operand_types[i], stage_opcodes,
1471 1.1 christos "\t ", lineno);
1472 1.1 christos }
1473 1.1 christos fprintf (table, " } },\n");
1474 1.1 christos }
1475 1.1 christos
1476 1.1 christos struct opcode_hash_entry
1477 1.1 christos {
1478 1.1 christos struct opcode_hash_entry *next;
1479 1.1 christos char *name;
1480 1.1 christos char *opcode;
1481 1.1 christos int lineno;
1482 1.1 christos };
1483 1.1 christos
1484 1.1 christos /* Calculate the hash value of an opcode hash entry P. */
1485 1.1 christos
1486 1.1 christos static hashval_t
1487 1.1 christos opcode_hash_hash (const void *p)
1488 1.1 christos {
1489 1.1 christos struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
1490 1.1 christos return htab_hash_string (entry->name);
1491 1.1 christos }
1492 1.1 christos
1493 1.1 christos /* Compare a string Q against an opcode hash entry P. */
1494 1.1 christos
1495 1.1 christos static int
1496 1.1 christos opcode_hash_eq (const void *p, const void *q)
1497 1.1 christos {
1498 1.1 christos struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
1499 1.1 christos const char *name = (const char *) q;
1500 1.1 christos return strcmp (name, entry->name) == 0;
1501 1.1 christos }
1502 1.1 christos
1503 1.1 christos static void
1504 1.8 christos parse_template (char *buf, int lineno)
1505 1.8 christos {
1506 1.8 christos char sep, *end, *name;
1507 1.8 christos struct template *tmpl = xmalloc (sizeof (*tmpl));
1508 1.8 christos struct template_instance *last_inst = NULL;
1509 1.8 christos
1510 1.8 christos buf = remove_leading_whitespaces (buf + 1);
1511 1.8 christos end = strchr (buf, ':');
1512 1.8 christos if (end == NULL)
1513 1.8 christos fail ("%s: %d: missing ':'\n", filename, lineno);
1514 1.8 christos *end++ = '\0';
1515 1.8 christos remove_trailing_whitespaces (buf);
1516 1.8 christos
1517 1.8 christos if (*buf == '\0')
1518 1.8 christos fail ("%s: %d: missing template identifier\n", filename, lineno);
1519 1.8 christos tmpl->name = xstrdup (buf);
1520 1.8 christos
1521 1.8 christos tmpl->params = NULL;
1522 1.8 christos do {
1523 1.8 christos struct template_param *param;
1524 1.8 christos
1525 1.8 christos buf = remove_leading_whitespaces (end);
1526 1.8 christos end = strpbrk (buf, ":,");
1527 1.8 christos if (end == NULL)
1528 1.8 christos fail ("%s: %d: missing ':' or ','\n", filename, lineno);
1529 1.8 christos
1530 1.8 christos sep = *end;
1531 1.8 christos *end++ = '\0';
1532 1.8 christos remove_trailing_whitespaces (buf);
1533 1.8 christos
1534 1.8 christos param = xmalloc (sizeof (*param));
1535 1.8 christos param->name = xstrdup (buf);
1536 1.8 christos param->next = tmpl->params;
1537 1.8 christos tmpl->params = param;
1538 1.8 christos } while (sep == ':');
1539 1.8 christos
1540 1.8 christos tmpl->instances = NULL;
1541 1.8 christos do {
1542 1.8 christos struct template_instance *inst;
1543 1.8 christos char *cur, *next;
1544 1.8 christos const struct template_param *param;
1545 1.8 christos
1546 1.8 christos buf = remove_leading_whitespaces (end);
1547 1.8 christos end = strpbrk (buf, ",>");
1548 1.8 christos if (end == NULL)
1549 1.8 christos fail ("%s: %d: missing ',' or '>'\n", filename, lineno);
1550 1.8 christos
1551 1.8 christos sep = *end;
1552 1.8 christos *end++ = '\0';
1553 1.8 christos
1554 1.8 christos inst = xmalloc (sizeof (*inst));
1555 1.8 christos inst->next = NULL;
1556 1.8 christos inst->args = NULL;
1557 1.8 christos
1558 1.8 christos cur = next_field (buf, ':', &next, end);
1559 1.8 christos inst->name = *cur != '$' ? xstrdup (cur) : "";
1560 1.8 christos
1561 1.8 christos for (param = tmpl->params; param; param = param->next)
1562 1.8 christos {
1563 1.8 christos struct template_arg *arg = xmalloc (sizeof (*arg));
1564 1.8 christos
1565 1.8 christos cur = next_field (next, ':', &next, end);
1566 1.8 christos if (next > end)
1567 1.8 christos fail ("%s: %d: missing argument for '%s'\n", filename, lineno, param->name);
1568 1.8 christos arg->val = xstrdup (cur);
1569 1.8 christos arg->next = inst->args;
1570 1.8 christos inst->args = arg;
1571 1.8 christos }
1572 1.8 christos
1573 1.8 christos if (tmpl->instances)
1574 1.8 christos last_inst->next = inst;
1575 1.8 christos else
1576 1.8 christos tmpl->instances = inst;
1577 1.8 christos last_inst = inst;
1578 1.8 christos } while (sep == ',');
1579 1.8 christos
1580 1.8 christos buf = remove_leading_whitespaces (end);
1581 1.8 christos if (*buf)
1582 1.8 christos fprintf(stderr, "%s: %d: excess characters '%s'\n",
1583 1.8 christos filename, lineno, buf);
1584 1.8 christos
1585 1.8 christos tmpl->next = templates;
1586 1.8 christos templates = tmpl;
1587 1.8 christos }
1588 1.8 christos
1589 1.8 christos static unsigned int
1590 1.8 christos expand_templates (char *name, const char *str, htab_t opcode_hash_table,
1591 1.8 christos struct opcode_hash_entry ***opcode_array_p, int lineno)
1592 1.8 christos {
1593 1.8 christos static unsigned int idx, opcode_array_size;
1594 1.8 christos struct opcode_hash_entry **opcode_array = *opcode_array_p;
1595 1.8 christos struct opcode_hash_entry **hash_slot, **entry;
1596 1.8 christos char *ptr1 = strchr(name, '<'), *ptr2;
1597 1.8 christos
1598 1.8 christos if (ptr1 == NULL)
1599 1.8 christos {
1600 1.8 christos /* Get the slot in hash table. */
1601 1.8 christos hash_slot = (struct opcode_hash_entry **)
1602 1.8 christos htab_find_slot_with_hash (opcode_hash_table, name,
1603 1.8 christos htab_hash_string (name),
1604 1.8 christos INSERT);
1605 1.8 christos
1606 1.8 christos if (*hash_slot == NULL)
1607 1.8 christos {
1608 1.8 christos /* It is the new one. Put it on opcode array. */
1609 1.8 christos if (idx >= opcode_array_size)
1610 1.8 christos {
1611 1.8 christos /* Grow the opcode array when needed. */
1612 1.8 christos opcode_array_size += 1024;
1613 1.8 christos opcode_array = (struct opcode_hash_entry **)
1614 1.8 christos xrealloc (opcode_array,
1615 1.8 christos sizeof (*opcode_array) * opcode_array_size);
1616 1.8 christos *opcode_array_p = opcode_array;
1617 1.8 christos }
1618 1.8 christos
1619 1.8 christos opcode_array[idx] = (struct opcode_hash_entry *)
1620 1.8 christos xmalloc (sizeof (struct opcode_hash_entry));
1621 1.8 christos opcode_array[idx]->next = NULL;
1622 1.8 christos opcode_array[idx]->name = xstrdup (name);
1623 1.8 christos opcode_array[idx]->opcode = xstrdup (str);
1624 1.8 christos opcode_array[idx]->lineno = lineno;
1625 1.8 christos *hash_slot = opcode_array[idx];
1626 1.8 christos idx++;
1627 1.8 christos }
1628 1.8 christos else
1629 1.8 christos {
1630 1.8 christos /* Append it to the existing one. */
1631 1.8 christos entry = hash_slot;
1632 1.8 christos while ((*entry) != NULL)
1633 1.8 christos entry = &(*entry)->next;
1634 1.8 christos *entry = (struct opcode_hash_entry *)
1635 1.8 christos xmalloc (sizeof (struct opcode_hash_entry));
1636 1.8 christos (*entry)->next = NULL;
1637 1.8 christos (*entry)->name = (*hash_slot)->name;
1638 1.8 christos (*entry)->opcode = xstrdup (str);
1639 1.8 christos (*entry)->lineno = lineno;
1640 1.8 christos }
1641 1.8 christos }
1642 1.8 christos else if ((ptr2 = strchr(ptr1 + 1, '>')) == NULL)
1643 1.8 christos fail ("%s: %d: missing '>'\n", filename, lineno);
1644 1.8 christos else
1645 1.8 christos {
1646 1.8 christos const struct template *tmpl;
1647 1.8 christos const struct template_instance *inst;
1648 1.8 christos
1649 1.8 christos *ptr1 = '\0';
1650 1.8 christos ptr1 = remove_leading_whitespaces (ptr1 + 1);
1651 1.8 christos remove_trailing_whitespaces (ptr1);
1652 1.8 christos
1653 1.8 christos *ptr2++ = '\0';
1654 1.8 christos
1655 1.8 christos for ( tmpl = templates; tmpl; tmpl = tmpl->next )
1656 1.8 christos if (!strcmp(ptr1, tmpl->name))
1657 1.8 christos break;
1658 1.8 christos if (!tmpl)
1659 1.8 christos fail ("reference to unknown template '%s'\n", ptr1);
1660 1.8 christos
1661 1.8 christos for (inst = tmpl->instances; inst; inst = inst->next)
1662 1.8 christos {
1663 1.8 christos char *name2 = xmalloc(strlen(name) + strlen(inst->name) + strlen(ptr2) + 1);
1664 1.8 christos char *str2 = xmalloc(2 * strlen(str));
1665 1.8 christos const char *src;
1666 1.8 christos
1667 1.8 christos strcpy (name2, name);
1668 1.8 christos strcat (name2, inst->name);
1669 1.8 christos strcat (name2, ptr2);
1670 1.8 christos
1671 1.8 christos for (ptr1 = str2, src = str; *src; )
1672 1.8 christos {
1673 1.8 christos const char *ident = tmpl->name, *end;
1674 1.8 christos const struct template_param *param;
1675 1.8 christos const struct template_arg *arg;
1676 1.8 christos
1677 1.8 christos if ((*ptr1 = *src++) != '<')
1678 1.8 christos {
1679 1.8 christos ++ptr1;
1680 1.8 christos continue;
1681 1.8 christos }
1682 1.8 christos while (ISSPACE(*src))
1683 1.8 christos ++src;
1684 1.8 christos while (*ident && *src == *ident)
1685 1.8 christos ++src, ++ident;
1686 1.8 christos while (ISSPACE(*src))
1687 1.8 christos ++src;
1688 1.8 christos if (*src != ':' || *ident != '\0')
1689 1.8 christos {
1690 1.8 christos memcpy (++ptr1, tmpl->name, ident - tmpl->name);
1691 1.8 christos ptr1 += ident - tmpl->name;
1692 1.8 christos continue;
1693 1.8 christos }
1694 1.8 christos while (ISSPACE(*++src))
1695 1.8 christos ;
1696 1.8 christos
1697 1.8 christos end = src;
1698 1.8 christos while (*end != '\0' && !ISSPACE(*end) && *end != '>')
1699 1.8 christos ++end;
1700 1.8 christos
1701 1.8 christos for (param = tmpl->params, arg = inst->args; param;
1702 1.8 christos param = param->next, arg = arg->next)
1703 1.8 christos {
1704 1.8 christos if (end - src == strlen (param->name)
1705 1.8 christos && !memcmp (src, param->name, end - src))
1706 1.8 christos {
1707 1.8 christos src = end;
1708 1.8 christos break;
1709 1.8 christos }
1710 1.8 christos }
1711 1.8 christos
1712 1.8 christos if (param == NULL)
1713 1.8 christos fail ("template '%s' has no parameter '%.*s'\n",
1714 1.8 christos tmpl->name, (int)(end - src), src);
1715 1.8 christos
1716 1.8 christos while (ISSPACE(*src))
1717 1.8 christos ++src;
1718 1.8 christos if (*src != '>')
1719 1.8 christos fail ("%s: %d: missing '>'\n", filename, lineno);
1720 1.8 christos
1721 1.8 christos memcpy(ptr1, arg->val, strlen(arg->val));
1722 1.8 christos ptr1 += strlen(arg->val);
1723 1.8 christos ++src;
1724 1.8 christos }
1725 1.8 christos
1726 1.8 christos *ptr1 = '\0';
1727 1.8 christos
1728 1.8 christos expand_templates (name2, str2, opcode_hash_table, opcode_array_p,
1729 1.8 christos lineno);
1730 1.8 christos
1731 1.8 christos free (str2);
1732 1.8 christos free (name2);
1733 1.8 christos }
1734 1.8 christos }
1735 1.8 christos
1736 1.8 christos return idx;
1737 1.8 christos }
1738 1.8 christos
1739 1.8 christos static void
1740 1.1 christos process_i386_opcodes (FILE *table)
1741 1.1 christos {
1742 1.1 christos FILE *fp;
1743 1.1 christos char buf[2048];
1744 1.1 christos unsigned int i, j;
1745 1.1 christos char *str, *p, *last, *name;
1746 1.1 christos htab_t opcode_hash_table;
1747 1.8 christos struct opcode_hash_entry **opcode_array = NULL;
1748 1.7 christos int lineno = 0, marker = 0;
1749 1.1 christos
1750 1.1 christos filename = "i386-opc.tbl";
1751 1.7 christos fp = stdin;
1752 1.1 christos
1753 1.1 christos i = 0;
1754 1.1 christos opcode_hash_table = htab_create_alloc (16, opcode_hash_hash,
1755 1.1 christos opcode_hash_eq, NULL,
1756 1.1 christos xcalloc, free);
1757 1.1 christos
1758 1.1 christos fprintf (table, "\n/* i386 opcode table. */\n\n");
1759 1.1 christos fprintf (table, "const insn_template i386_optab[] =\n{\n");
1760 1.1 christos
1761 1.1 christos /* Put everything on opcode array. */
1762 1.1 christos while (!feof (fp))
1763 1.1 christos {
1764 1.1 christos if (fgets (buf, sizeof (buf), fp) == NULL)
1765 1.1 christos break;
1766 1.1 christos
1767 1.1 christos lineno++;
1768 1.1 christos
1769 1.1 christos p = remove_leading_whitespaces (buf);
1770 1.1 christos
1771 1.1 christos /* Skip comments. */
1772 1.1 christos str = strstr (p, "//");
1773 1.1 christos if (str != NULL)
1774 1.1 christos str[0] = '\0';
1775 1.1 christos
1776 1.1 christos /* Remove trailing white spaces. */
1777 1.1 christos remove_trailing_whitespaces (p);
1778 1.1 christos
1779 1.1 christos switch (p[0])
1780 1.1 christos {
1781 1.1 christos case '#':
1782 1.7 christos if (!strcmp("### MARKER ###", buf))
1783 1.7 christos marker = 1;
1784 1.7 christos else
1785 1.7 christos {
1786 1.7 christos /* Since we ignore all included files (we only care about their
1787 1.7 christos #define-s here), we don't need to monitor filenames. The final
1788 1.7 christos line number directive is going to refer to the main source file
1789 1.7 christos again. */
1790 1.7 christos char *end;
1791 1.7 christos unsigned long ln;
1792 1.7 christos
1793 1.7 christos p = remove_leading_whitespaces (p + 1);
1794 1.7 christos if (!strncmp(p, "line", 4))
1795 1.7 christos p += 4;
1796 1.7 christos ln = strtoul (p, &end, 10);
1797 1.7 christos if (ln > 1 && ln < INT_MAX
1798 1.7 christos && *remove_leading_whitespaces (end) == '"')
1799 1.7 christos lineno = ln - 1;
1800 1.7 christos }
1801 1.1 christos /* Ignore comments. */
1802 1.1 christos case '\0':
1803 1.1 christos continue;
1804 1.1 christos break;
1805 1.8 christos case '<':
1806 1.8 christos parse_template (p, lineno);
1807 1.8 christos continue;
1808 1.1 christos default:
1809 1.7 christos if (!marker)
1810 1.7 christos continue;
1811 1.1 christos break;
1812 1.1 christos }
1813 1.1 christos
1814 1.1 christos last = p + strlen (p);
1815 1.1 christos
1816 1.1 christos /* Find name. */
1817 1.1 christos name = next_field (p, ',', &str, last);
1818 1.1 christos
1819 1.8 christos i = expand_templates (name, str, opcode_hash_table, &opcode_array,
1820 1.8 christos lineno);
1821 1.1 christos }
1822 1.1 christos
1823 1.1 christos /* Process opcode array. */
1824 1.1 christos for (j = 0; j < i; j++)
1825 1.1 christos {
1826 1.8 christos struct opcode_hash_entry *next;
1827 1.8 christos
1828 1.1 christos for (next = opcode_array[j]; next; next = next->next)
1829 1.1 christos {
1830 1.1 christos name = next->name;
1831 1.1 christos str = next->opcode;
1832 1.1 christos lineno = next->lineno;
1833 1.1 christos last = str + strlen (str);
1834 1.1 christos output_i386_opcode (table, name, str, last, lineno);
1835 1.1 christos }
1836 1.1 christos }
1837 1.1 christos
1838 1.1 christos fclose (fp);
1839 1.1 christos
1840 1.8 christos fprintf (table, " { NULL, 0, 0, 0,\n");
1841 1.8 christos
1842 1.8 christos process_i386_opcode_modifier (table, "0", 0, 0, NULL, -1);
1843 1.1 christos
1844 1.1 christos process_i386_cpu_flag (table, "0", 0, ",", " ", -1);
1845 1.1 christos
1846 1.1 christos fprintf (table, " { ");
1847 1.6 christos process_i386_operand_type (table, "0", stage_opcodes, "\t ", -1);
1848 1.1 christos fprintf (table, " } }\n");
1849 1.1 christos
1850 1.1 christos fprintf (table, "};\n");
1851 1.1 christos }
1852 1.1 christos
1853 1.1 christos static void
1854 1.1 christos process_i386_registers (FILE *table)
1855 1.1 christos {
1856 1.1 christos FILE *fp;
1857 1.1 christos char buf[2048];
1858 1.1 christos char *str, *p, *last;
1859 1.1 christos char *reg_name, *reg_type, *reg_flags, *reg_num;
1860 1.1 christos char *dw2_32_num, *dw2_64_num;
1861 1.1 christos int lineno = 0;
1862 1.1 christos
1863 1.1 christos filename = "i386-reg.tbl";
1864 1.1 christos fp = fopen (filename, "r");
1865 1.1 christos if (fp == NULL)
1866 1.1 christos fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1867 1.1 christos xstrerror (errno));
1868 1.1 christos
1869 1.1 christos fprintf (table, "\n/* i386 register table. */\n\n");
1870 1.1 christos fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
1871 1.1 christos
1872 1.1 christos while (!feof (fp))
1873 1.1 christos {
1874 1.1 christos if (fgets (buf, sizeof (buf), fp) == NULL)
1875 1.1 christos break;
1876 1.1 christos
1877 1.1 christos lineno++;
1878 1.1 christos
1879 1.1 christos p = remove_leading_whitespaces (buf);
1880 1.1 christos
1881 1.1 christos /* Skip comments. */
1882 1.1 christos str = strstr (p, "//");
1883 1.1 christos if (str != NULL)
1884 1.1 christos str[0] = '\0';
1885 1.1 christos
1886 1.1 christos /* Remove trailing white spaces. */
1887 1.1 christos remove_trailing_whitespaces (p);
1888 1.1 christos
1889 1.1 christos switch (p[0])
1890 1.1 christos {
1891 1.1 christos case '#':
1892 1.1 christos fprintf (table, "%s\n", p);
1893 1.1 christos case '\0':
1894 1.1 christos continue;
1895 1.1 christos break;
1896 1.1 christos default:
1897 1.1 christos break;
1898 1.1 christos }
1899 1.1 christos
1900 1.1 christos last = p + strlen (p);
1901 1.1 christos
1902 1.1 christos /* Find reg_name. */
1903 1.1 christos reg_name = next_field (p, ',', &str, last);
1904 1.1 christos
1905 1.1 christos /* Find reg_type. */
1906 1.1 christos reg_type = next_field (str, ',', &str, last);
1907 1.1 christos
1908 1.1 christos /* Find reg_flags. */
1909 1.1 christos reg_flags = next_field (str, ',', &str, last);
1910 1.1 christos
1911 1.1 christos /* Find reg_num. */
1912 1.1 christos reg_num = next_field (str, ',', &str, last);
1913 1.1 christos
1914 1.1 christos fprintf (table, " { \"%s\",\n ", reg_name);
1915 1.1 christos
1916 1.6 christos process_i386_operand_type (table, reg_type, stage_registers, "\t",
1917 1.6 christos lineno);
1918 1.1 christos
1919 1.1 christos /* Find 32-bit Dwarf2 register number. */
1920 1.1 christos dw2_32_num = next_field (str, ',', &str, last);
1921 1.1 christos
1922 1.1 christos /* Find 64-bit Dwarf2 register number. */
1923 1.1 christos dw2_64_num = next_field (str, ',', &str, last);
1924 1.1 christos
1925 1.1 christos fprintf (table, ",\n %s, %s, { %s, %s } },\n",
1926 1.1 christos reg_flags, reg_num, dw2_32_num, dw2_64_num);
1927 1.1 christos }
1928 1.1 christos
1929 1.1 christos fclose (fp);
1930 1.1 christos
1931 1.1 christos fprintf (table, "};\n");
1932 1.1 christos
1933 1.1 christos fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1934 1.1 christos }
1935 1.1 christos
1936 1.1 christos static void
1937 1.1 christos process_i386_initializers (void)
1938 1.1 christos {
1939 1.1 christos unsigned int i;
1940 1.1 christos FILE *fp = fopen ("i386-init.h", "w");
1941 1.1 christos char *init;
1942 1.1 christos
1943 1.1 christos if (fp == NULL)
1944 1.1 christos fail (_("can't create i386-init.h, errno = %s\n"),
1945 1.1 christos xstrerror (errno));
1946 1.1 christos
1947 1.1 christos process_copyright (fp);
1948 1.1 christos
1949 1.1 christos for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
1950 1.1 christos {
1951 1.1 christos fprintf (fp, "\n#define %s \\\n", cpu_flag_init[i].name);
1952 1.1 christos init = xstrdup (cpu_flag_init[i].init);
1953 1.1 christos process_i386_cpu_flag (fp, init, 1, "", " ", -1);
1954 1.1 christos free (init);
1955 1.1 christos }
1956 1.1 christos
1957 1.1 christos for (i = 0; i < ARRAY_SIZE (operand_type_init); i++)
1958 1.1 christos {
1959 1.1 christos fprintf (fp, "\n\n#define %s \\\n ", operand_type_init[i].name);
1960 1.1 christos init = xstrdup (operand_type_init[i].init);
1961 1.6 christos process_i386_operand_type (fp, init, stage_macros, " ", -1);
1962 1.1 christos free (init);
1963 1.1 christos }
1964 1.1 christos fprintf (fp, "\n");
1965 1.1 christos
1966 1.1 christos fclose (fp);
1967 1.1 christos }
1968 1.1 christos
1969 1.1 christos /* Program options. */
1970 1.1 christos #define OPTION_SRCDIR 200
1971 1.1 christos
1972 1.1 christos struct option long_options[] =
1973 1.1 christos {
1974 1.1 christos {"srcdir", required_argument, NULL, OPTION_SRCDIR},
1975 1.1 christos {"debug", no_argument, NULL, 'd'},
1976 1.1 christos {"version", no_argument, NULL, 'V'},
1977 1.1 christos {"help", no_argument, NULL, 'h'},
1978 1.1 christos {0, no_argument, NULL, 0}
1979 1.1 christos };
1980 1.1 christos
1981 1.1 christos static void
1982 1.1 christos print_version (void)
1983 1.1 christos {
1984 1.1 christos printf ("%s: version 1.0\n", program_name);
1985 1.1 christos xexit (0);
1986 1.1 christos }
1987 1.1 christos
1988 1.1 christos static void
1989 1.1 christos usage (FILE * stream, int status)
1990 1.1 christos {
1991 1.1 christos fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1992 1.1 christos program_name);
1993 1.1 christos xexit (status);
1994 1.1 christos }
1995 1.1 christos
1996 1.1 christos int
1997 1.1 christos main (int argc, char **argv)
1998 1.1 christos {
1999 1.1 christos extern int chdir (char *);
2000 1.1 christos char *srcdir = NULL;
2001 1.1 christos int c;
2002 1.5 christos unsigned int i, cpumax;
2003 1.1 christos FILE *table;
2004 1.1 christos
2005 1.1 christos program_name = *argv;
2006 1.1 christos xmalloc_set_program_name (program_name);
2007 1.1 christos
2008 1.1 christos while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
2009 1.1 christos switch (c)
2010 1.1 christos {
2011 1.1 christos case OPTION_SRCDIR:
2012 1.1 christos srcdir = optarg;
2013 1.1 christos break;
2014 1.1 christos case 'V':
2015 1.1 christos case 'v':
2016 1.1 christos print_version ();
2017 1.1 christos break;
2018 1.1 christos case 'd':
2019 1.1 christos debug = 1;
2020 1.1 christos break;
2021 1.1 christos case 'h':
2022 1.1 christos case '?':
2023 1.1 christos usage (stderr, 0);
2024 1.1 christos default:
2025 1.1 christos case 0:
2026 1.1 christos break;
2027 1.1 christos }
2028 1.1 christos
2029 1.1 christos if (optind != argc)
2030 1.1 christos usage (stdout, 1);
2031 1.1 christos
2032 1.1 christos if (srcdir != NULL)
2033 1.1 christos if (chdir (srcdir) != 0)
2034 1.1 christos fail (_("unable to change directory to \"%s\", errno = %s\n"),
2035 1.1 christos srcdir, xstrerror (errno));
2036 1.1 christos
2037 1.5 christos /* cpu_flags isn't sorted by position. */
2038 1.5 christos cpumax = 0;
2039 1.5 christos for (i = 0; i < ARRAY_SIZE (cpu_flags); i++)
2040 1.5 christos if (cpu_flags[i].position > cpumax)
2041 1.5 christos cpumax = cpu_flags[i].position;
2042 1.5 christos
2043 1.1 christos /* Check the unused bitfield in i386_cpu_flags. */
2044 1.5 christos #ifdef CpuUnused
2045 1.7 christos static_assert (ARRAY_SIZE (cpu_flags) == CpuMax + 2);
2046 1.7 christos
2047 1.5 christos if ((cpumax - 1) != CpuMax)
2048 1.5 christos fail (_("CpuMax != %d!\n"), cpumax);
2049 1.5 christos #else
2050 1.7 christos static_assert (ARRAY_SIZE (cpu_flags) == CpuMax + 1);
2051 1.7 christos
2052 1.5 christos if (cpumax != CpuMax)
2053 1.5 christos fail (_("CpuMax != %d!\n"), cpumax);
2054 1.5 christos
2055 1.1 christos c = CpuNumOfBits - CpuMax - 1;
2056 1.1 christos if (c)
2057 1.1 christos fail (_("%d unused bits in i386_cpu_flags.\n"), c);
2058 1.1 christos #endif
2059 1.1 christos
2060 1.7 christos static_assert (ARRAY_SIZE (opcode_modifiers) == Opcode_Modifier_Num);
2061 1.7 christos
2062 1.1 christos /* Check the unused bitfield in i386_operand_type. */
2063 1.7 christos #ifdef OTUnused
2064 1.7 christos static_assert (ARRAY_SIZE (operand_types) + CLASS_WIDTH + INSTANCE_WIDTH
2065 1.7 christos == OTNum + 1);
2066 1.7 christos #else
2067 1.7 christos static_assert (ARRAY_SIZE (operand_types) + CLASS_WIDTH + INSTANCE_WIDTH
2068 1.7 christos == OTNum);
2069 1.7 christos
2070 1.7 christos c = OTNumOfBits - OTNum;
2071 1.1 christos if (c)
2072 1.1 christos fail (_("%d unused bits in i386_operand_type.\n"), c);
2073 1.1 christos #endif
2074 1.1 christos
2075 1.1 christos qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
2076 1.1 christos compare);
2077 1.1 christos
2078 1.1 christos qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
2079 1.1 christos sizeof (opcode_modifiers [0]), compare);
2080 1.1 christos
2081 1.1 christos qsort (operand_types, ARRAY_SIZE (operand_types),
2082 1.1 christos sizeof (operand_types [0]), compare);
2083 1.1 christos
2084 1.1 christos table = fopen ("i386-tbl.h", "w");
2085 1.1 christos if (table == NULL)
2086 1.1 christos fail (_("can't create i386-tbl.h, errno = %s\n"),
2087 1.1 christos xstrerror (errno));
2088 1.1 christos
2089 1.1 christos process_copyright (table);
2090 1.1 christos
2091 1.1 christos process_i386_opcodes (table);
2092 1.1 christos process_i386_registers (table);
2093 1.1 christos process_i386_initializers ();
2094 1.1 christos
2095 1.1 christos fclose (table);
2096 1.1 christos
2097 1.1 christos exit (0);
2098 1.1 christos }
2099