i386-gen.c revision 1.9 1 1.9 christos /* Copyright (C) 2007-2024 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.9 christos #include <stdbool.h>
22 1.1 christos #include <stdio.h>
23 1.1 christos #include <errno.h>
24 1.1 christos #include "getopt.h"
25 1.1 christos #include "libiberty.h"
26 1.1 christos #include "hashtab.h"
27 1.1 christos #include "safe-ctype.h"
28 1.1 christos
29 1.1 christos #include "i386-opc.h"
30 1.1 christos
31 1.7 christos /* Build-time checks are preferrable over runtime ones. Use this construct
32 1.7 christos in preference where possible. */
33 1.7 christos #define static_assert(e) ((void)sizeof (struct { int _:1 - 2 * !(e); }))
34 1.7 christos
35 1.1 christos static const char *program_name = NULL;
36 1.1 christos static int debug = 0;
37 1.1 christos
38 1.9 christos typedef struct dependency
39 1.1 christos {
40 1.1 christos const char *name;
41 1.9 christos /* Note: Only direct dependencies should be enumerated. */
42 1.9 christos const char *deps;
43 1.9 christos } dependency;
44 1.9 christos
45 1.9 christos static const dependency isa_dependencies[] =
46 1.9 christos {
47 1.9 christos { "UNKNOWN",
48 1.9 christos "~IAMCU" },
49 1.9 christos { "GENERIC32",
50 1.9 christos "386" },
51 1.9 christos { "GENERIC64",
52 1.9 christos "PENTIUMPRO|Clflush|SYSCALL|MMX|SSE2|LM" },
53 1.9 christos { "NONE",
54 1.9 christos "0" },
55 1.9 christos { "PENTIUMPRO",
56 1.9 christos "686|Nop" },
57 1.9 christos { "P2",
58 1.9 christos "PENTIUMPRO|MMX" },
59 1.9 christos { "P3",
60 1.9 christos "P2|SSE" },
61 1.9 christos { "P4",
62 1.9 christos "P3|Clflush|SSE2" },
63 1.9 christos { "NOCONA",
64 1.9 christos "GENERIC64|FISTTP|SSE3|MONITOR|CX16" },
65 1.9 christos { "CORE",
66 1.9 christos "P4|FISTTP|SSE3|MONITOR" },
67 1.9 christos { "CORE2",
68 1.9 christos "NOCONA|SSSE3" },
69 1.9 christos { "COREI7",
70 1.9 christos "CORE2|SSE4_2|Rdtscp|LAHF_SAHF" },
71 1.9 christos { "K6",
72 1.9 christos "186|286|386|486|586|SYSCALL|387|MMX" },
73 1.9 christos { "K6_2",
74 1.9 christos "K6|3dnow" },
75 1.9 christos { "ATHLON",
76 1.9 christos "K6_2|686:min|687|Nop|3dnowA" },
77 1.9 christos { "K8",
78 1.9 christos "ATHLON|Rdtscp|SSE2|LM" },
79 1.9 christos { "AMDFAM10",
80 1.9 christos "K8|FISTTP|SSE4A|ABM|MONITOR" },
81 1.9 christos { "BDVER1",
82 1.9 christos "GENERIC64|FISTTP|Rdtscp|MONITOR|CX16|LAHF_SAHF|XOP|ABM|LWP|SVME|AES|PCLMULQDQ|PRFCHW" },
83 1.9 christos { "BDVER2",
84 1.9 christos "BDVER1|FMA|BMI|TBM|F16C" },
85 1.9 christos { "BDVER3",
86 1.9 christos "BDVER2|Xsaveopt|FSGSBase" },
87 1.9 christos { "BDVER4",
88 1.9 christos "BDVER3|AVX2|Movbe|BMI2|RdRnd|MWAITX" },
89 1.9 christos { "ZNVER1",
90 1.9 christos "GENERIC64|FISTTP|Rdtscp|MONITOR|CX16|LAHF_SAHF|AVX2|SSE4A|ABM|SVME|AES|PCLMULQDQ|PRFCHW|FMA|BMI|F16C|Xsaveopt|FSGSBase|Movbe|BMI2|RdRnd|ADX|RdSeed|SMAP|SHA|XSAVEC|XSAVES|ClflushOpt|CLZERO|MWAITX" },
91 1.9 christos { "ZNVER2",
92 1.9 christos "ZNVER1|CLWB|RDPID|RDPRU|MCOMMIT|WBNOINVD" },
93 1.9 christos { "ZNVER3",
94 1.9 christos "ZNVER2|INVLPGB|TLBSYNC|VAES|VPCLMULQDQ|INVPCID|SNP|OSPKE" },
95 1.9 christos { "ZNVER4",
96 1.9 christos "ZNVER3|AVX512F|AVX512DQ|AVX512IFMA|AVX512CD|AVX512BW|AVX512VL|AVX512_BF16|AVX512VBMI|AVX512_VBMI2|AVX512_VNNI|AVX512_BITALG|AVX512_VPOPCNTDQ|GFNI|RMPQUERY" },
97 1.9 christos { "ZNVER5",
98 1.9 christos "ZNVER4|AVX_VNNI|MOVDIRI|MOVDIR64B|AVX512_VP2INTERSECT|PREFETCHI" },
99 1.9 christos { "BTVER1",
100 1.9 christos "GENERIC64|FISTTP|MONITOR|CX16|LAHF_SAHF|Rdtscp|SSSE3|SSE4A|ABM|PRFCHW|Clflush|FISTTP|SVME" },
101 1.9 christos { "BTVER2",
102 1.9 christos "BTVER1|AVX|BMI|F16C|AES|PCLMULQDQ|Movbe|Xsaveopt|PRFCHW" },
103 1.9 christos { "286",
104 1.9 christos "186" },
105 1.9 christos { "386",
106 1.9 christos "286" },
107 1.9 christos { "486",
108 1.9 christos "386" },
109 1.9 christos { "586",
110 1.9 christos "486|387" },
111 1.9 christos { "586:nofpu",
112 1.9 christos "486" },
113 1.9 christos { "686",
114 1.9 christos "586|687|CMOV|FXSR" },
115 1.9 christos { "686:min",
116 1.9 christos "586|687" },
117 1.9 christos { "687",
118 1.9 christos "387" },
119 1.9 christos { "FISTTP",
120 1.9 christos "687" },
121 1.9 christos { "SSE",
122 1.9 christos "FXSR" },
123 1.9 christos { "SSE2",
124 1.9 christos "SSE" },
125 1.9 christos { "SSE3",
126 1.9 christos "SSE2" },
127 1.9 christos { "SSSE3",
128 1.9 christos "SSE3" },
129 1.9 christos { "SSE4_1",
130 1.9 christos "SSSE3" },
131 1.9 christos { "SSE4_2",
132 1.9 christos "SSE4_1|POPCNT" },
133 1.9 christos { "Xsaveopt",
134 1.9 christos "XSAVE" },
135 1.9 christos { "AES",
136 1.9 christos "SSE2" },
137 1.9 christos { "PCLMULQDQ",
138 1.9 christos "SSE2" },
139 1.9 christos { "FMA",
140 1.9 christos "AVX" },
141 1.9 christos { "FMA4",
142 1.9 christos "AVX" },
143 1.9 christos { "XOP",
144 1.9 christos "SSE4A|FMA4" },
145 1.9 christos { "LWP",
146 1.9 christos "XSAVE" },
147 1.9 christos { "F16C",
148 1.9 christos "AVX" },
149 1.9 christos { "3dnow",
150 1.9 christos "MMX" },
151 1.9 christos { "3dnowA",
152 1.9 christos "3dnow" },
153 1.9 christos { "SSE4a",
154 1.9 christos "SSE3" },
155 1.9 christos { "ABM",
156 1.9 christos "LZCNT|POPCNT" },
157 1.9 christos { "AVX",
158 1.9 christos "SSE4_2|XSAVE" },
159 1.9 christos { "AVX2",
160 1.9 christos "AVX" },
161 1.9 christos { "AVX_VNNI",
162 1.9 christos "AVX2" },
163 1.9 christos { "AVX_IFMA",
164 1.9 christos "AVX2" },
165 1.9 christos { "AVX_VNNI_INT8",
166 1.9 christos "AVX2" },
167 1.9 christos { "AVX_VNNI_INT16",
168 1.9 christos "AVX2" },
169 1.9 christos { "AVX_NE_CONVERT",
170 1.9 christos "AVX2" },
171 1.9 christos { "CX16",
172 1.9 christos "64" },
173 1.9 christos { "LKGS",
174 1.9 christos "64" },
175 1.9 christos { "FRED",
176 1.9 christos "LKGS" },
177 1.9 christos { "AVX512F",
178 1.9 christos "AVX2" },
179 1.9 christos { "AVX512CD",
180 1.9 christos "AVX512F" },
181 1.9 christos { "AVX512ER",
182 1.9 christos "AVX512F" },
183 1.9 christos { "AVX512PF",
184 1.9 christos "AVX512F" },
185 1.9 christos { "AVX512DQ",
186 1.9 christos "AVX512F" },
187 1.9 christos { "AVX512BW",
188 1.9 christos "AVX512F" },
189 1.9 christos { "AVX512VL",
190 1.9 christos "AVX512F" },
191 1.9 christos { "AVX512IFMA",
192 1.9 christos "AVX512F" },
193 1.9 christos { "AVX512VBMI",
194 1.9 christos "AVX512BW" },
195 1.9 christos { "AVX512_4FMAPS",
196 1.9 christos "AVX512F" },
197 1.9 christos { "AVX512_4VNNIW",
198 1.9 christos "AVX512F" },
199 1.9 christos { "AVX512_VPOPCNTDQ",
200 1.9 christos "AVX512F" },
201 1.9 christos { "AVX512_VBMI2",
202 1.9 christos "AVX512BW" },
203 1.9 christos { "AVX512_VNNI",
204 1.9 christos "AVX512F" },
205 1.9 christos { "AVX512_BITALG",
206 1.9 christos "AVX512BW" },
207 1.9 christos { "AVX512_VP2INTERSECT",
208 1.9 christos "AVX512F" },
209 1.9 christos { "AVX512_BF16",
210 1.9 christos "AVX512BW" },
211 1.9 christos { "AVX512_FP16",
212 1.9 christos "AVX512BW" },
213 1.9 christos { "IAMCU",
214 1.9 christos "586:nofpu" },
215 1.9 christos { "EPT",
216 1.9 christos "VMX" },
217 1.9 christos { "VMFUNC",
218 1.9 christos "VMX" },
219 1.9 christos { "MPX",
220 1.9 christos "XSAVE" },
221 1.9 christos { "SHA",
222 1.9 christos "SSE2" },
223 1.9 christos { "SHA512",
224 1.9 christos "AVX2" },
225 1.9 christos { "SM3",
226 1.9 christos "AVX" },
227 1.9 christos { "SM4",
228 1.9 christos "AVX2" },
229 1.9 christos { "XSAVES",
230 1.9 christos "XSAVEC" },
231 1.9 christos { "XSAVEC",
232 1.9 christos "XSAVE" },
233 1.9 christos { "OSPKE",
234 1.9 christos "XSAVE" },
235 1.9 christos { "GFNI",
236 1.9 christos "SSE2" },
237 1.9 christos { "VAES",
238 1.9 christos "AVX2|AES" },
239 1.9 christos { "VPCLMULQDQ",
240 1.9 christos "AVX2|PCLMULQDQ" },
241 1.9 christos { "AVX10_1",
242 1.9 christos "AVX512VL|AVX512DQ|AVX512CD|AVX512VBMI|AVX512_VBMI2|AVX512IFMA"
243 1.9 christos "|AVX512_VNNI|AVX512_BF16|AVX512_FP16|AVX512_VPOPCNTDQ|AVX512_BITALG" },
244 1.9 christos { "SEV_ES",
245 1.9 christos "SVME" },
246 1.9 christos { "SNP",
247 1.9 christos "SEV_ES" },
248 1.9 christos { "RMPQUERY",
249 1.9 christos "SNP|64" },
250 1.9 christos { "TSX",
251 1.9 christos "RTM|HLE" },
252 1.9 christos { "TSXLDTRK",
253 1.9 christos "RTM" },
254 1.9 christos { "AMX_TILE",
255 1.9 christos "XSAVE|64" },
256 1.9 christos { "AMX_INT8",
257 1.9 christos "AMX_TILE" },
258 1.9 christos { "AMX_BF16",
259 1.9 christos "AMX_TILE" },
260 1.9 christos { "AMX_FP16",
261 1.9 christos "AMX_TILE" },
262 1.9 christos { "AMX_COMPLEX",
263 1.9 christos "AMX_TILE" },
264 1.9 christos { "KL",
265 1.9 christos "SSE2" },
266 1.9 christos { "WIDEKL",
267 1.9 christos "KL" },
268 1.9 christos { "PBNDKB",
269 1.9 christos "64" },
270 1.9 christos { "UINTR",
271 1.9 christos "64" },
272 1.9 christos { "PREFETCHI",
273 1.9 christos "64" },
274 1.9 christos { "CMPCCXADD",
275 1.9 christos "64" },
276 1.9 christos { "MSRLIST",
277 1.9 christos "64" },
278 1.9 christos { "USER_MSR",
279 1.9 christos "64" },
280 1.9 christos { "APX_F",
281 1.9 christos "XSAVE|64" },
282 1.1 christos };
283 1.1 christos
284 1.9 christos /* This array is populated as process_i386_initializers() walks cpu_flags[]. */
285 1.9 christos static unsigned char isa_reverse_deps[CpuMax][CpuMax];
286 1.1 christos
287 1.1 christos typedef struct bitfield
288 1.1 christos {
289 1.1 christos int position;
290 1.1 christos int value;
291 1.1 christos const char *name;
292 1.1 christos } bitfield;
293 1.1 christos
294 1.9 christos #define BITFIELD(n) { Cpu##n, 0, #n }
295 1.1 christos
296 1.1 christos static bitfield cpu_flags[] =
297 1.1 christos {
298 1.9 christos BITFIELD (186),
299 1.9 christos BITFIELD (286),
300 1.9 christos BITFIELD (386),
301 1.9 christos BITFIELD (486),
302 1.9 christos BITFIELD (586),
303 1.9 christos BITFIELD (686),
304 1.9 christos BITFIELD (CMOV),
305 1.9 christos BITFIELD (FXSR),
306 1.9 christos BITFIELD (Clflush),
307 1.9 christos BITFIELD (Nop),
308 1.9 christos BITFIELD (SYSCALL),
309 1.9 christos BITFIELD (8087),
310 1.9 christos BITFIELD (287),
311 1.9 christos BITFIELD (387),
312 1.9 christos BITFIELD (687),
313 1.9 christos BITFIELD (FISTTP),
314 1.9 christos BITFIELD (MMX),
315 1.9 christos BITFIELD (SSE),
316 1.9 christos BITFIELD (SSE2),
317 1.9 christos BITFIELD (SSE3),
318 1.9 christos BITFIELD (SSSE3),
319 1.9 christos BITFIELD (SSE4_1),
320 1.9 christos BITFIELD (SSE4_2),
321 1.9 christos BITFIELD (AVX),
322 1.9 christos BITFIELD (AVX2),
323 1.9 christos BITFIELD (AVX512F),
324 1.9 christos BITFIELD (AVX512CD),
325 1.9 christos BITFIELD (AVX512ER),
326 1.9 christos BITFIELD (AVX512PF),
327 1.9 christos BITFIELD (AVX512VL),
328 1.9 christos BITFIELD (AVX512DQ),
329 1.9 christos BITFIELD (AVX512BW),
330 1.9 christos BITFIELD (IAMCU),
331 1.9 christos BITFIELD (SSE4a),
332 1.9 christos BITFIELD (3dnow),
333 1.9 christos BITFIELD (3dnowA),
334 1.9 christos BITFIELD (PadLock),
335 1.9 christos BITFIELD (SVME),
336 1.9 christos BITFIELD (VMX),
337 1.9 christos BITFIELD (SMX),
338 1.9 christos BITFIELD (Xsave),
339 1.9 christos BITFIELD (Xsaveopt),
340 1.9 christos BITFIELD (AES),
341 1.9 christos BITFIELD (PCLMULQDQ),
342 1.9 christos BITFIELD (FMA),
343 1.9 christos BITFIELD (FMA4),
344 1.9 christos BITFIELD (XOP),
345 1.9 christos BITFIELD (LWP),
346 1.9 christos BITFIELD (BMI),
347 1.9 christos BITFIELD (TBM),
348 1.9 christos BITFIELD (Movbe),
349 1.9 christos BITFIELD (CX16),
350 1.9 christos BITFIELD (LAHF_SAHF),
351 1.9 christos BITFIELD (EPT),
352 1.9 christos BITFIELD (Rdtscp),
353 1.9 christos BITFIELD (FSGSBase),
354 1.9 christos BITFIELD (RdRnd),
355 1.9 christos BITFIELD (F16C),
356 1.9 christos BITFIELD (BMI2),
357 1.9 christos BITFIELD (LZCNT),
358 1.9 christos BITFIELD (POPCNT),
359 1.9 christos BITFIELD (MONITOR),
360 1.9 christos BITFIELD (HLE),
361 1.9 christos BITFIELD (RTM),
362 1.9 christos BITFIELD (INVPCID),
363 1.9 christos BITFIELD (VMFUNC),
364 1.9 christos BITFIELD (RDSEED),
365 1.9 christos BITFIELD (ADX),
366 1.9 christos BITFIELD (PRFCHW),
367 1.9 christos BITFIELD (SMAP),
368 1.9 christos BITFIELD (SHA),
369 1.9 christos BITFIELD (SHA512),
370 1.9 christos BITFIELD (SM3),
371 1.9 christos BITFIELD (SM4),
372 1.9 christos BITFIELD (ClflushOpt),
373 1.9 christos BITFIELD (XSAVES),
374 1.9 christos BITFIELD (XSAVEC),
375 1.9 christos BITFIELD (PREFETCHWT1),
376 1.9 christos BITFIELD (SE1),
377 1.9 christos BITFIELD (CLWB),
378 1.9 christos BITFIELD (MPX),
379 1.9 christos BITFIELD (AVX512IFMA),
380 1.9 christos BITFIELD (AVX512VBMI),
381 1.9 christos BITFIELD (AVX512_4FMAPS),
382 1.9 christos BITFIELD (AVX512_4VNNIW),
383 1.9 christos BITFIELD (AVX512_VPOPCNTDQ),
384 1.9 christos BITFIELD (AVX512_VBMI2),
385 1.9 christos BITFIELD (AVX512_VNNI),
386 1.9 christos BITFIELD (AVX512_BITALG),
387 1.9 christos BITFIELD (AVX512_BF16),
388 1.9 christos BITFIELD (AVX512_VP2INTERSECT),
389 1.9 christos BITFIELD (TDX),
390 1.9 christos BITFIELD (AVX_VNNI),
391 1.9 christos BITFIELD (AVX512_FP16),
392 1.9 christos BITFIELD (PREFETCHI),
393 1.9 christos BITFIELD (AVX_IFMA),
394 1.9 christos BITFIELD (AVX_VNNI_INT8),
395 1.9 christos BITFIELD (AVX_VNNI_INT16),
396 1.9 christos BITFIELD (CMPCCXADD),
397 1.9 christos BITFIELD (WRMSRNS),
398 1.9 christos BITFIELD (MSRLIST),
399 1.9 christos BITFIELD (AVX_NE_CONVERT),
400 1.9 christos BITFIELD (RAO_INT),
401 1.9 christos BITFIELD (FRED),
402 1.9 christos BITFIELD (LKGS),
403 1.9 christos BITFIELD (USER_MSR),
404 1.9 christos BITFIELD (APX_F),
405 1.9 christos BITFIELD (MWAITX),
406 1.9 christos BITFIELD (CLZERO),
407 1.9 christos BITFIELD (OSPKE),
408 1.9 christos BITFIELD (RDPID),
409 1.9 christos BITFIELD (PTWRITE),
410 1.9 christos BITFIELD (IBT),
411 1.9 christos BITFIELD (SHSTK),
412 1.9 christos BITFIELD (GFNI),
413 1.9 christos BITFIELD (VAES),
414 1.9 christos BITFIELD (VPCLMULQDQ),
415 1.9 christos BITFIELD (WBNOINVD),
416 1.9 christos BITFIELD (PCONFIG),
417 1.9 christos BITFIELD (PBNDKB),
418 1.9 christos BITFIELD (WAITPKG),
419 1.9 christos BITFIELD (UINTR),
420 1.9 christos BITFIELD (CLDEMOTE),
421 1.9 christos BITFIELD (AMX_INT8),
422 1.9 christos BITFIELD (AMX_BF16),
423 1.9 christos BITFIELD (AMX_FP16),
424 1.9 christos BITFIELD (AMX_COMPLEX),
425 1.9 christos BITFIELD (AMX_TILE),
426 1.9 christos BITFIELD (MOVDIRI),
427 1.9 christos BITFIELD (MOVDIR64B),
428 1.9 christos BITFIELD (ENQCMD),
429 1.9 christos BITFIELD (SERIALIZE),
430 1.9 christos BITFIELD (RDPRU),
431 1.9 christos BITFIELD (MCOMMIT),
432 1.9 christos BITFIELD (SEV_ES),
433 1.9 christos BITFIELD (TSXLDTRK),
434 1.9 christos BITFIELD (KL),
435 1.9 christos BITFIELD (WideKL),
436 1.9 christos BITFIELD (HRESET),
437 1.9 christos BITFIELD (INVLPGB),
438 1.9 christos BITFIELD (TLBSYNC),
439 1.9 christos BITFIELD (SNP),
440 1.9 christos BITFIELD (RMPQUERY),
441 1.9 christos BITFIELD (64),
442 1.9 christos BITFIELD (No64),
443 1.1 christos #ifdef CpuUnused
444 1.9 christos BITFIELD (Unused),
445 1.1 christos #endif
446 1.1 christos };
447 1.1 christos
448 1.9 christos #undef BITFIELD
449 1.9 christos #define BITFIELD(n) { n, 0, #n }
450 1.9 christos
451 1.1 christos static bitfield opcode_modifiers[] =
452 1.1 christos {
453 1.1 christos BITFIELD (D),
454 1.1 christos BITFIELD (W),
455 1.6 christos BITFIELD (Load),
456 1.1 christos BITFIELD (Modrm),
457 1.1 christos BITFIELD (Jump),
458 1.1 christos BITFIELD (FloatMF),
459 1.7 christos BITFIELD (Size),
460 1.9 christos BITFIELD (CheckOperandSize),
461 1.9 christos BITFIELD (OperandConstraint),
462 1.8 christos BITFIELD (MnemonicSize),
463 1.1 christos BITFIELD (No_bSuf),
464 1.1 christos BITFIELD (No_wSuf),
465 1.1 christos BITFIELD (No_lSuf),
466 1.1 christos BITFIELD (No_sSuf),
467 1.1 christos BITFIELD (No_qSuf),
468 1.1 christos BITFIELD (FWait),
469 1.1 christos BITFIELD (IsString),
470 1.7 christos BITFIELD (RegMem),
471 1.3 christos BITFIELD (BNDPrefixOk),
472 1.8 christos BITFIELD (PrefixOk),
473 1.1 christos BITFIELD (IsPrefix),
474 1.1 christos BITFIELD (ImmExt),
475 1.1 christos BITFIELD (NoRex64),
476 1.1 christos BITFIELD (Vex),
477 1.1 christos BITFIELD (VexVVVV),
478 1.1 christos BITFIELD (VexW),
479 1.8 christos BITFIELD (OpcodePrefix),
480 1.8 christos BITFIELD (SIB),
481 1.1 christos BITFIELD (SSE2AVX),
482 1.3 christos BITFIELD (EVex),
483 1.3 christos BITFIELD (Masking),
484 1.3 christos BITFIELD (Broadcast),
485 1.3 christos BITFIELD (StaticRounding),
486 1.3 christos BITFIELD (SAE),
487 1.3 christos BITFIELD (Disp8MemShift),
488 1.6 christos BITFIELD (Optimize),
489 1.9 christos BITFIELD (Dialect),
490 1.8 christos BITFIELD (ISA64),
491 1.9 christos BITFIELD (NoEgpr),
492 1.9 christos BITFIELD (NF),
493 1.9 christos BITFIELD (Rex2),
494 1.1 christos };
495 1.1 christos
496 1.7 christos #define CLASS(n) #n, n
497 1.7 christos
498 1.7 christos static const struct {
499 1.7 christos const char *name;
500 1.7 christos enum operand_class value;
501 1.7 christos } operand_classes[] = {
502 1.7 christos CLASS (Reg),
503 1.7 christos CLASS (SReg),
504 1.7 christos CLASS (RegCR),
505 1.7 christos CLASS (RegDR),
506 1.7 christos CLASS (RegTR),
507 1.7 christos CLASS (RegMMX),
508 1.7 christos CLASS (RegSIMD),
509 1.7 christos CLASS (RegMask),
510 1.7 christos CLASS (RegBND),
511 1.7 christos };
512 1.7 christos
513 1.7 christos #undef CLASS
514 1.7 christos
515 1.7 christos #define INSTANCE(n) #n, n
516 1.7 christos
517 1.7 christos static const struct {
518 1.7 christos const char *name;
519 1.7 christos enum operand_instance value;
520 1.7 christos } operand_instances[] = {
521 1.7 christos INSTANCE (Accum),
522 1.7 christos INSTANCE (RegC),
523 1.7 christos INSTANCE (RegD),
524 1.7 christos INSTANCE (RegB),
525 1.7 christos };
526 1.7 christos
527 1.7 christos #undef INSTANCE
528 1.7 christos
529 1.1 christos static bitfield operand_types[] =
530 1.1 christos {
531 1.1 christos BITFIELD (Imm1),
532 1.1 christos BITFIELD (Imm8),
533 1.1 christos BITFIELD (Imm8S),
534 1.1 christos BITFIELD (Imm16),
535 1.1 christos BITFIELD (Imm32),
536 1.1 christos BITFIELD (Imm32S),
537 1.1 christos BITFIELD (Imm64),
538 1.1 christos BITFIELD (BaseIndex),
539 1.1 christos BITFIELD (Disp8),
540 1.1 christos BITFIELD (Disp16),
541 1.1 christos BITFIELD (Disp32),
542 1.1 christos BITFIELD (Disp64),
543 1.1 christos BITFIELD (Byte),
544 1.1 christos BITFIELD (Word),
545 1.1 christos BITFIELD (Dword),
546 1.1 christos BITFIELD (Fword),
547 1.1 christos BITFIELD (Qword),
548 1.1 christos BITFIELD (Tbyte),
549 1.1 christos BITFIELD (Xmmword),
550 1.1 christos BITFIELD (Ymmword),
551 1.3 christos BITFIELD (Zmmword),
552 1.8 christos BITFIELD (Tmmword),
553 1.1 christos BITFIELD (Unspecified),
554 1.1 christos #ifdef OTUnused
555 1.1 christos BITFIELD (OTUnused),
556 1.1 christos #endif
557 1.1 christos };
558 1.1 christos
559 1.1 christos static const char *filename;
560 1.6 christos static i386_cpu_flags active_cpu_flags;
561 1.6 christos static int active_isstring;
562 1.1 christos
563 1.8 christos struct template_arg {
564 1.8 christos const struct template_arg *next;
565 1.8 christos const char *val;
566 1.8 christos };
567 1.8 christos
568 1.8 christos struct template_instance {
569 1.8 christos const struct template_instance *next;
570 1.8 christos const char *name;
571 1.8 christos const struct template_arg *args;
572 1.8 christos };
573 1.8 christos
574 1.8 christos struct template_param {
575 1.8 christos const struct template_param *next;
576 1.8 christos const char *name;
577 1.8 christos };
578 1.8 christos
579 1.8 christos struct template {
580 1.9 christos struct template *next;
581 1.8 christos const char *name;
582 1.8 christos const struct template_instance *instances;
583 1.8 christos const struct template_param *params;
584 1.8 christos };
585 1.8 christos
586 1.9 christos static struct template *templates;
587 1.8 christos
588 1.1 christos static int
589 1.1 christos compare (const void *x, const void *y)
590 1.1 christos {
591 1.1 christos const bitfield *xp = (const bitfield *) x;
592 1.1 christos const bitfield *yp = (const bitfield *) y;
593 1.1 christos return xp->position - yp->position;
594 1.1 christos }
595 1.1 christos
596 1.1 christos static void
597 1.1 christos fail (const char *message, ...)
598 1.1 christos {
599 1.1 christos va_list args;
600 1.1 christos
601 1.1 christos va_start (args, message);
602 1.9 christos fprintf (stderr, "%s: error: ", program_name);
603 1.1 christos vfprintf (stderr, message, args);
604 1.1 christos va_end (args);
605 1.1 christos xexit (1);
606 1.1 christos }
607 1.1 christos
608 1.1 christos static void
609 1.1 christos process_copyright (FILE *fp)
610 1.1 christos {
611 1.1 christos fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
612 1.9 christos /* Copyright (C) 2007-2024 Free Software Foundation, Inc.\n\
613 1.1 christos \n\
614 1.1 christos This file is part of the GNU opcodes library.\n\
615 1.1 christos \n\
616 1.1 christos This library is free software; you can redistribute it and/or modify\n\
617 1.1 christos it under the terms of the GNU General Public License as published by\n\
618 1.1 christos the Free Software Foundation; either version 3, or (at your option)\n\
619 1.1 christos any later version.\n\
620 1.1 christos \n\
621 1.1 christos It is distributed in the hope that it will be useful, but WITHOUT\n\
622 1.1 christos ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
623 1.1 christos or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
624 1.1 christos License for more details.\n\
625 1.1 christos \n\
626 1.1 christos You should have received a copy of the GNU General Public License\n\
627 1.1 christos along with this program; if not, write to the Free Software\n\
628 1.1 christos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
629 1.1 christos MA 02110-1301, USA. */\n");
630 1.1 christos }
631 1.1 christos
632 1.1 christos /* Remove leading white spaces. */
633 1.1 christos
634 1.1 christos static char *
635 1.1 christos remove_leading_whitespaces (char *str)
636 1.1 christos {
637 1.1 christos while (ISSPACE (*str))
638 1.1 christos str++;
639 1.1 christos return str;
640 1.1 christos }
641 1.1 christos
642 1.1 christos /* Remove trailing white spaces. */
643 1.1 christos
644 1.1 christos static void
645 1.1 christos remove_trailing_whitespaces (char *str)
646 1.1 christos {
647 1.1 christos size_t last = strlen (str);
648 1.1 christos
649 1.1 christos if (last == 0)
650 1.1 christos return;
651 1.1 christos
652 1.1 christos do
653 1.1 christos {
654 1.1 christos last--;
655 1.1 christos if (ISSPACE (str [last]))
656 1.1 christos str[last] = '\0';
657 1.1 christos else
658 1.1 christos break;
659 1.1 christos }
660 1.1 christos while (last != 0);
661 1.1 christos }
662 1.1 christos
663 1.1 christos /* Find next field separated by SEP and terminate it. Return a
664 1.1 christos pointer to the one after it. */
665 1.1 christos
666 1.1 christos static char *
667 1.1 christos next_field (char *str, char sep, char **next, char *last)
668 1.1 christos {
669 1.1 christos char *p;
670 1.1 christos
671 1.1 christos p = remove_leading_whitespaces (str);
672 1.1 christos for (str = p; *str != sep && *str != '\0'; str++);
673 1.1 christos
674 1.1 christos *str = '\0';
675 1.1 christos remove_trailing_whitespaces (p);
676 1.1 christos
677 1.1 christos *next = str + 1;
678 1.1 christos
679 1.1 christos if (p >= last)
680 1.1 christos abort ();
681 1.1 christos
682 1.1 christos return p;
683 1.1 christos }
684 1.1 christos
685 1.5 christos static void set_bitfield (char *, bitfield *, int, unsigned int, int);
686 1.5 christos
687 1.1 christos static void
688 1.5 christos set_bitfield (char *f, bitfield *array, int value,
689 1.1 christos unsigned int size, int lineno)
690 1.1 christos {
691 1.1 christos unsigned int i;
692 1.1 christos
693 1.8 christos /* Ignore empty fields; they may result from template expansions. */
694 1.8 christos if (*f == '\0')
695 1.8 christos return;
696 1.1 christos
697 1.1 christos for (i = 0; i < size; i++)
698 1.1 christos if (strcasecmp (array[i].name, f) == 0)
699 1.1 christos {
700 1.1 christos array[i].value = value;
701 1.1 christos return;
702 1.1 christos }
703 1.1 christos
704 1.1 christos if (value)
705 1.1 christos {
706 1.1 christos const char *v = strchr (f, '=');
707 1.1 christos
708 1.1 christos if (v)
709 1.1 christos {
710 1.1 christos size_t n = v - f;
711 1.1 christos char *end;
712 1.1 christos
713 1.1 christos for (i = 0; i < size; i++)
714 1.1 christos if (strncasecmp (array[i].name, f, n) == 0)
715 1.1 christos {
716 1.1 christos value = strtol (v + 1, &end, 0);
717 1.1 christos if (*end == '\0')
718 1.1 christos {
719 1.1 christos array[i].value = value;
720 1.1 christos return;
721 1.1 christos }
722 1.1 christos break;
723 1.1 christos }
724 1.1 christos }
725 1.1 christos }
726 1.1 christos
727 1.1 christos if (lineno != -1)
728 1.9 christos fail ("%s: %d: unknown bitfield: %s\n", filename, lineno, f);
729 1.1 christos else
730 1.9 christos fail ("unknown bitfield: %s\n", f);
731 1.9 christos }
732 1.9 christos
733 1.9 christos static void
734 1.9 christos add_isa_dependencies (bitfield *flags, const char *f, int value,
735 1.9 christos unsigned int reverse)
736 1.9 christos {
737 1.9 christos unsigned int i;
738 1.9 christos char *str = NULL;
739 1.9 christos const char *isa = f;
740 1.9 christos static bool is_avx;
741 1.9 christos bool is_isa = false, orig_is_avx = is_avx;
742 1.9 christos
743 1.9 christos /* Need to find base entry for references to auxiliary ones. */
744 1.9 christos if (strchr (f, ':'))
745 1.9 christos {
746 1.9 christos str = xstrdup (f);
747 1.9 christos *strchr (str, ':') = '\0';
748 1.9 christos isa = str;
749 1.9 christos }
750 1.9 christos /* isa_dependencies[] prefers "LM" over "64". */
751 1.9 christos else if (!strcmp (f, "LM"))
752 1.9 christos isa = "64";
753 1.9 christos for (i = 0; i < CpuMax; ++i)
754 1.9 christos if (strcasecmp (flags[i].name, isa) == 0)
755 1.9 christos {
756 1.9 christos flags[i].value = value;
757 1.9 christos if (reverse < ARRAY_SIZE (isa_reverse_deps[0])
758 1.9 christos /* Don't record the feature itself here. */
759 1.9 christos && reverse != i
760 1.9 christos /* Don't record base architectures. */
761 1.9 christos && reverse > Cpu686)
762 1.9 christos isa_reverse_deps[i][reverse] = 1;
763 1.9 christos is_isa = true;
764 1.9 christos if (i == CpuAVX || i == CpuXOP || i == CpuVAES || i == CpuVPCLMULQDQ)
765 1.9 christos is_avx = true;
766 1.9 christos break;
767 1.9 christos }
768 1.9 christos free (str);
769 1.9 christos
770 1.9 christos /* Do not turn off dependencies. */
771 1.9 christos if (is_isa && !value)
772 1.9 christos {
773 1.9 christos is_avx = orig_is_avx;
774 1.9 christos return;
775 1.9 christos }
776 1.9 christos
777 1.9 christos for (i = 0; i < ARRAY_SIZE (isa_dependencies); ++i)
778 1.9 christos if (strcasecmp (isa_dependencies[i].name, f) == 0)
779 1.9 christos {
780 1.9 christos char *deps = xstrdup (isa_dependencies[i].deps);
781 1.9 christos char *next = deps;
782 1.9 christos char *last = deps + strlen (deps);
783 1.9 christos
784 1.9 christos for (; next && next < last; )
785 1.9 christos {
786 1.9 christos char *str = next_field (next, '|', &next, last);
787 1.9 christos
788 1.9 christos /* No AVX/XOP -> SSE reverse dependencies. */
789 1.9 christos if (is_avx && strncmp (str, "SSE", 3) == 0)
790 1.9 christos add_isa_dependencies (flags, str, value, CpuMax);
791 1.9 christos else
792 1.9 christos add_isa_dependencies (flags, str, value, reverse);
793 1.9 christos }
794 1.9 christos free (deps);
795 1.9 christos
796 1.9 christos /* ISA extensions with dependencies need CPU_ANY_*_FLAGS emitted,
797 1.9 christos unless the sole dependency is the "64-bit mode only" one. */
798 1.9 christos if (reverse < ARRAY_SIZE (isa_reverse_deps[0])
799 1.9 christos && strcmp (isa_dependencies[i].deps, "64"))
800 1.9 christos isa_reverse_deps[reverse][reverse] = 1;
801 1.9 christos
802 1.9 christos is_avx = orig_is_avx;
803 1.9 christos return;
804 1.9 christos }
805 1.9 christos
806 1.9 christos if (!is_isa)
807 1.9 christos fail ("unknown bitfield: %s\n", f);
808 1.9 christos
809 1.9 christos is_avx = orig_is_avx;
810 1.1 christos }
811 1.1 christos
812 1.1 christos static void
813 1.1 christos output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
814 1.9 christos int mode, const char *comma, const char *indent, int lineno)
815 1.1 christos {
816 1.9 christos unsigned int i = 0, j = 0;
817 1.1 christos
818 1.9 christos if (mode < 0)
819 1.9 christos memset (&active_cpu_flags, 0, sizeof(active_cpu_flags));
820 1.6 christos
821 1.1 christos fprintf (table, "%s{ { ", indent);
822 1.1 christos
823 1.9 christos if (mode <= 0)
824 1.9 christos {
825 1.9 christos for (j = ~0u; i < CpuAttrEnums; i++)
826 1.9 christos {
827 1.9 christos if (!flags[i].value)
828 1.9 christos continue;
829 1.9 christos
830 1.9 christos if (j < ~0u)
831 1.9 christos fail ("%s: %d: invalid combination of CPU identifiers\n",
832 1.9 christos filename, lineno);
833 1.9 christos j = i;
834 1.9 christos if (mode)
835 1.9 christos active_cpu_flags.array[i / 32] |= 1U << (i % 32);
836 1.9 christos }
837 1.9 christos
838 1.9 christos /* Write 0 to indicate "no associated flag". */
839 1.9 christos fprintf (table, "%u, ", j + 1);
840 1.9 christos
841 1.9 christos j = 1;
842 1.9 christos }
843 1.9 christos
844 1.9 christos for (; i < size - 1; i++, j++)
845 1.1 christos {
846 1.9 christos if (((j + 1) % 20) != 0)
847 1.3 christos fprintf (table, "%d, ", flags[i].value);
848 1.3 christos else
849 1.3 christos fprintf (table, "%d,", flags[i].value);
850 1.9 christos if (((j + 1) % 20) == 0)
851 1.1 christos {
852 1.1 christos /* We need \\ for macro. */
853 1.9 christos if (mode > 0)
854 1.1 christos fprintf (table, " \\\n %s", indent);
855 1.1 christos else
856 1.1 christos fprintf (table, "\n %s", indent);
857 1.1 christos }
858 1.9 christos if (mode < 0 && flags[i].value)
859 1.6 christos active_cpu_flags.array[i / 32] |= 1U << (i % 32);
860 1.1 christos }
861 1.1 christos
862 1.9 christos #if defined(CpuAttrUnused) != defined(CpuUnused)
863 1.9 christos if (mode <= 0)
864 1.9 christos # ifdef CpuUnused
865 1.9 christos fprintf (table, " } }%s\n", comma);
866 1.9 christos # else
867 1.9 christos fprintf (table, "%d, 0 } }%s\n", flags[i].value, comma);
868 1.9 christos # endif
869 1.9 christos else
870 1.9 christos #endif
871 1.9 christos fprintf (table, "%d } }%s\n", flags[i].value, comma);
872 1.1 christos }
873 1.1 christos
874 1.1 christos static void
875 1.9 christos process_i386_cpu_flag (FILE *table, char *flag,
876 1.9 christos const char *name,
877 1.1 christos const char *comma, const char *indent,
878 1.9 christos int lineno, unsigned int reverse)
879 1.1 christos {
880 1.8 christos char *str, *next = flag, *last;
881 1.1 christos unsigned int i;
882 1.8 christos int value = 1;
883 1.9 christos bool is_isa = false;
884 1.9 christos bitfield all [ARRAY_SIZE (cpu_flags)];
885 1.9 christos bitfield any [ARRAY_SIZE (cpu_flags)];
886 1.1 christos
887 1.1 christos /* Copy the default cpu flags. */
888 1.9 christos memcpy (all, cpu_flags, sizeof (cpu_flags));
889 1.9 christos memcpy (any, cpu_flags, sizeof (cpu_flags));
890 1.9 christos
891 1.9 christos if (flag == NULL)
892 1.9 christos {
893 1.9 christos for (i = 0; i < ARRAY_SIZE (isa_reverse_deps[0]); ++i)
894 1.9 christos any[i].value = isa_reverse_deps[reverse][i];
895 1.9 christos goto output;
896 1.9 christos }
897 1.1 christos
898 1.8 christos if (flag[0] == '~')
899 1.1 christos {
900 1.1 christos last = flag + strlen (flag);
901 1.1 christos
902 1.1 christos if (flag[1] == '(')
903 1.1 christos {
904 1.1 christos last -= 1;
905 1.1 christos next = flag + 2;
906 1.1 christos if (*last != ')')
907 1.9 christos fail ("%s: %d: missing `)' in bitfield: %s\n", filename,
908 1.1 christos lineno, flag);
909 1.1 christos *last = '\0';
910 1.1 christos }
911 1.1 christos else
912 1.1 christos next = flag + 1;
913 1.1 christos
914 1.9 christos /* First we turn on everything except for cpuno64 and - if
915 1.8 christos present - the padding field. */
916 1.9 christos for (i = 0; i < ARRAY_SIZE (any); i++)
917 1.9 christos if (any[i].position < CpuNo64)
918 1.9 christos any[i].value = 1;
919 1.1 christos
920 1.1 christos /* Turn off selective bits. */
921 1.8 christos value = 0;
922 1.1 christos }
923 1.8 christos
924 1.9 christos if (name != NULL && value != 0)
925 1.9 christos {
926 1.9 christos for (i = 0; i < ARRAY_SIZE (any); i++)
927 1.9 christos if (strcasecmp (any[i].name, name) == 0)
928 1.9 christos {
929 1.9 christos add_isa_dependencies (any, name, 1, reverse);
930 1.9 christos is_isa = true;
931 1.9 christos break;
932 1.9 christos }
933 1.9 christos }
934 1.9 christos
935 1.8 christos if (strcmp (flag, "0"))
936 1.1 christos {
937 1.9 christos bool combined = false;
938 1.9 christos
939 1.9 christos if (is_isa)
940 1.9 christos return;
941 1.9 christos
942 1.8 christos /* Turn on/off selective bits. */
943 1.1 christos last = flag + strlen (flag);
944 1.9 christos if (name == NULL && strchr (flag, '&'))
945 1.9 christos {
946 1.9 christos for (; next < last && *next != '('; )
947 1.9 christos {
948 1.9 christos str = next_field (next, '&', &next, last);
949 1.9 christos set_bitfield (str, all, value, ARRAY_SIZE (all), lineno);
950 1.9 christos }
951 1.9 christos if (*next == '(')
952 1.9 christos {
953 1.9 christos if (*--last != ')')
954 1.9 christos fail ("%s: %d: missing `)' in bitfield: %s\n", filename,
955 1.9 christos lineno, flag);
956 1.9 christos ++next;
957 1.9 christos *last = '\0';
958 1.9 christos }
959 1.9 christos combined = true;
960 1.9 christos }
961 1.8 christos for (; next && next < last; )
962 1.1 christos {
963 1.1 christos str = next_field (next, '|', &next, last);
964 1.9 christos if (name)
965 1.9 christos add_isa_dependencies (any, str, value, reverse);
966 1.9 christos else if (combined || next < last)
967 1.9 christos set_bitfield (str, any, value, ARRAY_SIZE (any), lineno);
968 1.9 christos else /* Singular specifiers go into "all". */
969 1.9 christos set_bitfield (str, all, value, ARRAY_SIZE (all), lineno);
970 1.9 christos combined = true;
971 1.1 christos }
972 1.1 christos }
973 1.1 christos
974 1.9 christos output:
975 1.9 christos if (name != NULL)
976 1.9 christos {
977 1.9 christos size_t len = strlen (name);
978 1.9 christos char *upper = xmalloc (len + 1);
979 1.9 christos
980 1.9 christos /* Cpu64 is special: It specifies a mode dependency, not an ISA one. Zap
981 1.9 christos the flag from ISA initializer macros (and from CPU_ANY_64_FLAGS
982 1.9 christos itself we only care about tracking its dependents. Also don't emit the
983 1.9 christos (otherwise all zero) CPU_64_FLAGS. */
984 1.9 christos if (flag != NULL && reverse == Cpu64)
985 1.9 christos return;
986 1.9 christos if (is_isa || flag == NULL)
987 1.9 christos any[Cpu64].value = 0;
988 1.9 christos
989 1.9 christos for (i = 0; i < len; ++i)
990 1.9 christos {
991 1.9 christos /* Don't emit #define-s for auxiliary entries. */
992 1.9 christos if (name[i] == ':')
993 1.9 christos return;
994 1.9 christos upper[i] = TOUPPER (name[i]);
995 1.9 christos }
996 1.9 christos upper[i] = '\0';
997 1.9 christos fprintf (table, "\n#define CPU_%s%s_FLAGS \\\n",
998 1.9 christos flag != NULL ? "": "ANY_", upper);
999 1.9 christos free (upper);
1000 1.9 christos }
1001 1.9 christos else
1002 1.9 christos {
1003 1.9 christos /* Synthesize "64-bit mode only" dependencies from the dependencies we
1004 1.9 christos have accumulated. */
1005 1.9 christos for (i = 0; i < ARRAY_SIZE (isa_reverse_deps[0]); ++i)
1006 1.9 christos if (all[i].value && isa_reverse_deps[Cpu64][i])
1007 1.9 christos all[Cpu64].value = 1;
1008 1.9 christos
1009 1.9 christos output_cpu_flags(table, all, ARRAY_SIZE (all), -1, comma, indent, lineno);
1010 1.9 christos }
1011 1.9 christos
1012 1.9 christos output_cpu_flags (table, any, ARRAY_SIZE (any), name != NULL,
1013 1.9 christos comma, indent, lineno);
1014 1.1 christos }
1015 1.1 christos
1016 1.1 christos static void
1017 1.1 christos output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
1018 1.1 christos {
1019 1.1 christos unsigned int i;
1020 1.1 christos
1021 1.1 christos fprintf (table, " { ");
1022 1.1 christos
1023 1.1 christos for (i = 0; i < size - 1; i++)
1024 1.1 christos {
1025 1.3 christos if (((i + 1) % 20) != 0)
1026 1.3 christos fprintf (table, "%d, ", modifier[i].value);
1027 1.3 christos else
1028 1.3 christos fprintf (table, "%d,", modifier[i].value);
1029 1.1 christos if (((i + 1) % 20) == 0)
1030 1.1 christos fprintf (table, "\n ");
1031 1.1 christos }
1032 1.1 christos
1033 1.1 christos fprintf (table, "%d },\n", modifier[i].value);
1034 1.1 christos }
1035 1.1 christos
1036 1.9 christos /* Returns LOG2 of element size. */
1037 1.7 christos static int
1038 1.9 christos get_element_size (char **opnd, int lineno)
1039 1.7 christos {
1040 1.7 christos char *str, *next, *last, *op;
1041 1.9 christos const char *full = opnd[0];
1042 1.9 christos int elem_size = INT_MAX;
1043 1.7 christos
1044 1.9 christos /* Find the memory operand. */
1045 1.9 christos while (full != NULL && strstr(full, "BaseIndex") == NULL)
1046 1.9 christos full = *++opnd;
1047 1.9 christos if (full == NULL)
1048 1.9 christos fail ("%s: %d: no memory operand\n", filename, lineno);
1049 1.7 christos
1050 1.9 christos op = xstrdup (full);
1051 1.7 christos last = op + strlen (op);
1052 1.7 christos for (next = op; next && next < last; )
1053 1.7 christos {
1054 1.7 christos str = next_field (next, '|', &next, last);
1055 1.7 christos if (str)
1056 1.7 christos {
1057 1.7 christos if (strcasecmp(str, "Byte") == 0)
1058 1.7 christos {
1059 1.9 christos /* The smallest element size, no need to check
1060 1.7 christos further. */
1061 1.9 christos elem_size = 0;
1062 1.7 christos break;
1063 1.7 christos }
1064 1.7 christos else if (strcasecmp(str, "Word") == 0)
1065 1.7 christos {
1066 1.9 christos if (elem_size > 1)
1067 1.9 christos elem_size = 1;
1068 1.7 christos }
1069 1.7 christos else if (strcasecmp(str, "Dword") == 0)
1070 1.7 christos {
1071 1.9 christos if (elem_size > 2)
1072 1.9 christos elem_size = 2;
1073 1.7 christos }
1074 1.7 christos else if (strcasecmp(str, "Qword") == 0)
1075 1.7 christos {
1076 1.9 christos if (elem_size > 3)
1077 1.9 christos elem_size = 3;
1078 1.7 christos }
1079 1.7 christos }
1080 1.7 christos }
1081 1.7 christos free (op);
1082 1.7 christos
1083 1.9 christos if (elem_size == INT_MAX)
1084 1.9 christos fail ("%s: %d: unknown element size: %s\n", filename, lineno, full);
1085 1.9 christos
1086 1.9 christos return elem_size;
1087 1.9 christos }
1088 1.9 christos
1089 1.9 christos static bool
1090 1.9 christos rex2_disallowed (const unsigned long long opcode, unsigned int length,
1091 1.9 christos unsigned int space, const char *cpu_flags)
1092 1.9 christos {
1093 1.9 christos /* Some opcodes encode a ModR/M-like byte directly in the opcode. */
1094 1.9 christos unsigned int base_opcode = opcode >> (8 * length - 8);
1095 1.9 christos
1096 1.9 christos /* All opcodes listed map0 0x4*, 0x7*, 0xa*, 0xe* and map1 0x3*, 0x8*
1097 1.9 christos are reserved under REX2 and triggers #UD when prefixed with REX2 */
1098 1.9 christos if (space == 0)
1099 1.9 christos switch (base_opcode >> 4)
1100 1.9 christos {
1101 1.9 christos case 0x4:
1102 1.9 christos case 0x7:
1103 1.9 christos case 0xA:
1104 1.9 christos case 0xE:
1105 1.9 christos return true;
1106 1.9 christos default:
1107 1.9 christos return false;
1108 1.9 christos }
1109 1.7 christos
1110 1.9 christos if (space == SPACE_0F)
1111 1.9 christos switch (base_opcode >> 4)
1112 1.9 christos {
1113 1.9 christos case 0x3:
1114 1.9 christos case 0x8:
1115 1.9 christos return true;
1116 1.9 christos default:
1117 1.9 christos return false;
1118 1.9 christos }
1119 1.9 christos
1120 1.9 christos return false;
1121 1.7 christos }
1122 1.7 christos
1123 1.1 christos static void
1124 1.8 christos process_i386_opcode_modifier (FILE *table, char *mod, unsigned int space,
1125 1.9 christos unsigned int prefix, const char *extension_opcode,
1126 1.9 christos char **opnd, int lineno, bool rex2_disallowed)
1127 1.1 christos {
1128 1.1 christos char *str, *next, *last;
1129 1.1 christos bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
1130 1.9 christos static const char *const spaces[] = {
1131 1.9 christos #define SPACE(n) [SPACE_##n] = #n
1132 1.9 christos SPACE(BASE),
1133 1.9 christos SPACE(0F),
1134 1.9 christos SPACE(0F38),
1135 1.9 christos SPACE(0F3A),
1136 1.9 christos SPACE(EVEXMAP4),
1137 1.9 christos SPACE(EVEXMAP5),
1138 1.9 christos SPACE(EVEXMAP6),
1139 1.9 christos SPACE(VEXMAP7),
1140 1.9 christos SPACE(XOP08),
1141 1.9 christos SPACE(XOP09),
1142 1.9 christos SPACE(XOP0A),
1143 1.9 christos #undef SPACE
1144 1.9 christos };
1145 1.1 christos
1146 1.6 christos active_isstring = 0;
1147 1.6 christos
1148 1.1 christos /* Copy the default opcode modifier. */
1149 1.1 christos memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
1150 1.1 christos
1151 1.1 christos if (strcmp (mod, "0"))
1152 1.1 christos {
1153 1.7 christos unsigned int have_w = 0, bwlq_suf = 0xf;
1154 1.7 christos
1155 1.1 christos last = mod + strlen (mod);
1156 1.1 christos for (next = mod; next && next < last; )
1157 1.1 christos {
1158 1.1 christos str = next_field (next, '|', &next, last);
1159 1.1 christos if (str)
1160 1.6 christos {
1161 1.7 christos int val = 1;
1162 1.9 christos
1163 1.9 christos if (strncmp(str, "OpcodeSpace", 11) == 0)
1164 1.9 christos {
1165 1.9 christos char *end;
1166 1.9 christos
1167 1.9 christos if (str[11] != '=')
1168 1.9 christos fail ("%s:%d: Missing value for `OpcodeSpace'\n",
1169 1.9 christos filename, lineno);
1170 1.9 christos
1171 1.9 christos val = strtol (str + 12, &end, 0);
1172 1.9 christos if (*end)
1173 1.9 christos fail ("%s:%d: Bogus value `%s' for `OpcodeSpace'\n",
1174 1.9 christos filename, lineno, end);
1175 1.9 christos
1176 1.9 christos if (space)
1177 1.9 christos {
1178 1.9 christos if (val != space)
1179 1.9 christos fail ("%s:%d: Conflicting opcode space specifications\n",
1180 1.9 christos filename, lineno);
1181 1.9 christos fprintf (stderr,
1182 1.9 christos "%s:%d: Warning: redundant opcode space specification\n",
1183 1.9 christos filename, lineno);
1184 1.9 christos }
1185 1.9 christos
1186 1.9 christos space = val;
1187 1.9 christos continue;
1188 1.9 christos }
1189 1.9 christos
1190 1.7 christos if (strcasecmp(str, "Broadcast") == 0)
1191 1.9 christos val = get_element_size (opnd, lineno) + BYTE_BROADCAST;
1192 1.9 christos else if (strcasecmp(str, "Disp8MemShift") == 0)
1193 1.9 christos val = get_element_size (opnd, lineno);
1194 1.8 christos
1195 1.7 christos set_bitfield (str, modifiers, val, ARRAY_SIZE (modifiers),
1196 1.8 christos lineno);
1197 1.6 christos if (strcasecmp(str, "IsString") == 0)
1198 1.6 christos active_isstring = 1;
1199 1.7 christos
1200 1.7 christos if (strcasecmp(str, "W") == 0)
1201 1.7 christos have_w = 1;
1202 1.7 christos
1203 1.7 christos if (strcasecmp(str, "No_bSuf") == 0)
1204 1.7 christos bwlq_suf &= ~1;
1205 1.7 christos if (strcasecmp(str, "No_wSuf") == 0)
1206 1.7 christos bwlq_suf &= ~2;
1207 1.7 christos if (strcasecmp(str, "No_lSuf") == 0)
1208 1.7 christos bwlq_suf &= ~4;
1209 1.7 christos if (strcasecmp(str, "No_qSuf") == 0)
1210 1.7 christos bwlq_suf &= ~8;
1211 1.6 christos }
1212 1.1 christos }
1213 1.7 christos
1214 1.8 christos if (prefix)
1215 1.8 christos {
1216 1.8 christos if (!modifiers[OpcodePrefix].value)
1217 1.8 christos modifiers[OpcodePrefix].value = prefix;
1218 1.8 christos else if (modifiers[OpcodePrefix].value != prefix)
1219 1.9 christos fail ("%s:%d: Conflicting prefix specifications\n",
1220 1.8 christos filename, lineno);
1221 1.8 christos else
1222 1.8 christos fprintf (stderr,
1223 1.9 christos "%s:%d: Warning: redundant prefix specification\n",
1224 1.8 christos filename, lineno);
1225 1.8 christos }
1226 1.8 christos
1227 1.7 christos if (have_w && !bwlq_suf)
1228 1.7 christos fail ("%s: %d: stray W modifier\n", filename, lineno);
1229 1.7 christos if (have_w && !(bwlq_suf & 1))
1230 1.7 christos fprintf (stderr, "%s: %d: W modifier without Byte operand(s)\n",
1231 1.7 christos filename, lineno);
1232 1.7 christos if (have_w && !(bwlq_suf & ~1))
1233 1.7 christos fprintf (stderr,
1234 1.7 christos "%s: %d: W modifier without Word/Dword/Qword operand(s)\n",
1235 1.7 christos filename, lineno);
1236 1.1 christos }
1237 1.9 christos
1238 1.9 christos if (space >= ARRAY_SIZE (spaces) || !spaces[space])
1239 1.9 christos fail ("%s:%d: Unknown opcode space %u\n", filename, lineno, space);
1240 1.9 christos
1241 1.9 christos fprintf (table, " SPACE_%s, %s,\n",
1242 1.9 christos spaces[space], extension_opcode ? extension_opcode : "None");
1243 1.9 christos
1244 1.9 christos /* Rather than evaluating multiple conditions at runtime to determine
1245 1.9 christos whether an EVEX encoding is being dealt with, derive that information
1246 1.9 christos right here. A missing EVex attribute means "dynamic". */
1247 1.9 christos if (!modifiers[EVex].value
1248 1.9 christos && (modifiers[Disp8MemShift].value
1249 1.9 christos || modifiers[Broadcast].value
1250 1.9 christos || modifiers[Masking].value
1251 1.9 christos || modifiers[SAE].value))
1252 1.9 christos modifiers[EVex].value = EVEXDYN;
1253 1.9 christos
1254 1.9 christos /* Vex, legacy map2 and map3 and rex2_disallowed do not support EGPR.
1255 1.9 christos For templates supporting both Vex and EVex allowing EGPR. */
1256 1.9 christos if ((modifiers[Vex].value || space > SPACE_0F || rex2_disallowed)
1257 1.9 christos && !modifiers[EVex].value)
1258 1.9 christos modifiers[NoEgpr].value = 1;
1259 1.9 christos
1260 1.1 christos output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
1261 1.1 christos }
1262 1.1 christos
1263 1.6 christos enum stage {
1264 1.6 christos stage_macros,
1265 1.6 christos stage_opcodes,
1266 1.6 christos stage_registers,
1267 1.6 christos };
1268 1.6 christos
1269 1.1 christos static void
1270 1.7 christos output_operand_type (FILE *table, enum operand_class class,
1271 1.7 christos enum operand_instance instance,
1272 1.7 christos const bitfield *types, unsigned int size,
1273 1.6 christos enum stage stage, const char *indent)
1274 1.1 christos {
1275 1.1 christos unsigned int i;
1276 1.1 christos
1277 1.7 christos fprintf (table, "{ { %d, %d, ", class, instance);
1278 1.1 christos
1279 1.1 christos for (i = 0; i < size - 1; i++)
1280 1.1 christos {
1281 1.7 christos if (((i + 3) % 20) != 0)
1282 1.3 christos fprintf (table, "%d, ", types[i].value);
1283 1.3 christos else
1284 1.3 christos fprintf (table, "%d,", types[i].value);
1285 1.7 christos if (((i + 3) % 20) == 0)
1286 1.1 christos {
1287 1.1 christos /* We need \\ for macro. */
1288 1.6 christos if (stage == stage_macros)
1289 1.3 christos fprintf (table, " \\\n%s", indent);
1290 1.1 christos else
1291 1.1 christos fprintf (table, "\n%s", indent);
1292 1.1 christos }
1293 1.1 christos }
1294 1.1 christos
1295 1.1 christos fprintf (table, "%d } }", types[i].value);
1296 1.1 christos }
1297 1.1 christos
1298 1.1 christos static void
1299 1.6 christos process_i386_operand_type (FILE *table, char *op, enum stage stage,
1300 1.1 christos const char *indent, int lineno)
1301 1.1 christos {
1302 1.1 christos char *str, *next, *last;
1303 1.7 christos enum operand_class class = ClassNone;
1304 1.7 christos enum operand_instance instance = InstanceNone;
1305 1.1 christos bitfield types [ARRAY_SIZE (operand_types)];
1306 1.1 christos
1307 1.1 christos /* Copy the default operand type. */
1308 1.1 christos memcpy (types, operand_types, sizeof (types));
1309 1.1 christos
1310 1.1 christos if (strcmp (op, "0"))
1311 1.1 christos {
1312 1.6 christos int baseindex = 0;
1313 1.6 christos
1314 1.1 christos last = op + strlen (op);
1315 1.1 christos for (next = op; next && next < last; )
1316 1.1 christos {
1317 1.1 christos str = next_field (next, '|', &next, last);
1318 1.1 christos if (str)
1319 1.6 christos {
1320 1.7 christos unsigned int i;
1321 1.7 christos
1322 1.7 christos if (!strncmp(str, "Class=", 6))
1323 1.7 christos {
1324 1.7 christos for (i = 0; i < ARRAY_SIZE(operand_classes); ++i)
1325 1.7 christos if (!strcmp(str + 6, operand_classes[i].name))
1326 1.7 christos {
1327 1.7 christos class = operand_classes[i].value;
1328 1.7 christos str = NULL;
1329 1.7 christos break;
1330 1.7 christos }
1331 1.7 christos }
1332 1.7 christos
1333 1.7 christos if (str && !strncmp(str, "Instance=", 9))
1334 1.7 christos {
1335 1.7 christos for (i = 0; i < ARRAY_SIZE(operand_instances); ++i)
1336 1.7 christos if (!strcmp(str + 9, operand_instances[i].name))
1337 1.7 christos {
1338 1.7 christos instance = operand_instances[i].value;
1339 1.7 christos str = NULL;
1340 1.7 christos break;
1341 1.7 christos }
1342 1.7 christos }
1343 1.7 christos }
1344 1.7 christos if (str)
1345 1.7 christos {
1346 1.6 christos set_bitfield (str, types, 1, ARRAY_SIZE (types), lineno);
1347 1.6 christos if (strcasecmp(str, "BaseIndex") == 0)
1348 1.6 christos baseindex = 1;
1349 1.6 christos }
1350 1.6 christos }
1351 1.6 christos
1352 1.6 christos if (stage == stage_opcodes && baseindex && !active_isstring)
1353 1.6 christos {
1354 1.6 christos set_bitfield("Disp8", types, 1, ARRAY_SIZE (types), lineno);
1355 1.6 christos if (!active_cpu_flags.bitfield.cpu64
1356 1.6 christos && !active_cpu_flags.bitfield.cpumpx)
1357 1.6 christos set_bitfield("Disp16", types, 1, ARRAY_SIZE (types), lineno);
1358 1.8 christos set_bitfield("Disp32", types, 1, ARRAY_SIZE (types), lineno);
1359 1.1 christos }
1360 1.1 christos }
1361 1.7 christos output_operand_type (table, class, instance, types, ARRAY_SIZE (types),
1362 1.7 christos stage, indent);
1363 1.1 christos }
1364 1.1 christos
1365 1.9 christos static char *mkident (const char *mnem)
1366 1.9 christos {
1367 1.9 christos char *ident = xstrdup (mnem), *p = ident;
1368 1.9 christos
1369 1.9 christos do
1370 1.9 christos {
1371 1.9 christos if (!ISALNUM (*p))
1372 1.9 christos *p = '_';
1373 1.9 christos }
1374 1.9 christos while (*++p);
1375 1.9 christos
1376 1.9 christos return ident;
1377 1.9 christos }
1378 1.9 christos
1379 1.1 christos static void
1380 1.1 christos output_i386_opcode (FILE *table, const char *name, char *str,
1381 1.1 christos char *last, int lineno)
1382 1.1 christos {
1383 1.8 christos unsigned int i, length, prefix = 0, space = 0;
1384 1.9 christos char *base_opcode, *extension_opcode, *end, *ident;
1385 1.1 christos char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
1386 1.8 christos unsigned long long opcode;
1387 1.1 christos
1388 1.1 christos /* Find base_opcode. */
1389 1.1 christos base_opcode = next_field (str, ',', &str, last);
1390 1.1 christos
1391 1.9 christos /* Find extension_opcode, if any. */
1392 1.9 christos extension_opcode = strchr (base_opcode, '/');
1393 1.9 christos if (extension_opcode)
1394 1.9 christos *extension_opcode++ = '\0';
1395 1.1 christos
1396 1.1 christos /* Find cpu_flags. */
1397 1.1 christos cpu_flags = next_field (str, ',', &str, last);
1398 1.1 christos
1399 1.1 christos /* Find opcode_modifier. */
1400 1.1 christos opcode_modifier = next_field (str, ',', &str, last);
1401 1.1 christos
1402 1.1 christos /* Remove the first {. */
1403 1.1 christos str = remove_leading_whitespaces (str);
1404 1.1 christos if (*str != '{')
1405 1.1 christos abort ();
1406 1.1 christos str = remove_leading_whitespaces (str + 1);
1407 1.8 christos remove_trailing_whitespaces (str);
1408 1.1 christos
1409 1.8 christos /* Remove } and trailing white space. */
1410 1.1 christos i = strlen (str);
1411 1.8 christos if (!i || str[i - 1] != '}')
1412 1.1 christos abort ();
1413 1.8 christos str[--i] = '\0';
1414 1.8 christos remove_trailing_whitespaces (str);
1415 1.1 christos
1416 1.8 christos if (!*str)
1417 1.8 christos operand_types [i = 0] = NULL;
1418 1.8 christos else
1419 1.1 christos {
1420 1.8 christos last = str + strlen (str);
1421 1.8 christos
1422 1.8 christos /* Find operand_types. */
1423 1.8 christos for (i = 0; i < ARRAY_SIZE (operand_types); i++)
1424 1.8 christos {
1425 1.8 christos if (str >= last)
1426 1.8 christos {
1427 1.8 christos operand_types [i] = NULL;
1428 1.8 christos break;
1429 1.8 christos }
1430 1.8 christos
1431 1.8 christos operand_types [i] = next_field (str, ',', &str, last);
1432 1.8 christos }
1433 1.1 christos }
1434 1.1 christos
1435 1.8 christos opcode = strtoull (base_opcode, &end, 0);
1436 1.1 christos
1437 1.8 christos /* Determine opcode length. */
1438 1.8 christos for (length = 1; length < 8; ++length)
1439 1.8 christos if (!(opcode >> (8 * length)))
1440 1.8 christos break;
1441 1.8 christos
1442 1.8 christos /* Transform prefixes encoded in the opcode into opcode modifier
1443 1.8 christos representation. */
1444 1.8 christos if (length > 1)
1445 1.1 christos {
1446 1.8 christos switch (opcode >> (8 * length - 8))
1447 1.1 christos {
1448 1.8 christos case 0x66: prefix = PREFIX_0X66; break;
1449 1.8 christos case 0xF3: prefix = PREFIX_0XF3; break;
1450 1.8 christos case 0xF2: prefix = PREFIX_0XF2; break;
1451 1.1 christos }
1452 1.1 christos
1453 1.8 christos if (prefix)
1454 1.8 christos opcode &= (1ULL << (8 * --length)) - 1;
1455 1.8 christos }
1456 1.8 christos
1457 1.8 christos /* Transform opcode space encoded in the opcode into opcode modifier
1458 1.8 christos representation. */
1459 1.8 christos if (length > 1 && (opcode >> (8 * length - 8)) == 0xf)
1460 1.8 christos {
1461 1.8 christos switch ((opcode >> (8 * length - 16)) & 0xff)
1462 1.1 christos {
1463 1.8 christos default: space = SPACE_0F; break;
1464 1.8 christos case 0x38: space = SPACE_0F38; break;
1465 1.8 christos case 0x3A: space = SPACE_0F3A; break;
1466 1.1 christos }
1467 1.8 christos
1468 1.8 christos if (space != SPACE_0F && --length == 1)
1469 1.9 christos fail ("%s:%d: %s: unrecognized opcode encoding space\n",
1470 1.8 christos filename, lineno, name);
1471 1.8 christos opcode &= (1ULL << (8 * --length)) - 1;
1472 1.1 christos }
1473 1.1 christos
1474 1.8 christos if (length > 2)
1475 1.9 christos fail ("%s:%d: %s: residual opcode (0x%0*llx) too large\n",
1476 1.8 christos filename, lineno, name, 2 * length, opcode);
1477 1.8 christos
1478 1.9 christos ident = mkident (name);
1479 1.9 christos fprintf (table, " { MN_%s, 0x%0*llx%s, %u,",
1480 1.9 christos ident, 2 * (int)length, opcode, end, i);
1481 1.9 christos free (ident);
1482 1.8 christos
1483 1.8 christos process_i386_opcode_modifier (table, opcode_modifier, space, prefix,
1484 1.9 christos extension_opcode, operand_types, lineno,
1485 1.9 christos rex2_disallowed (opcode, length, space,
1486 1.9 christos cpu_flags));
1487 1.1 christos
1488 1.9 christos process_i386_cpu_flag (table, cpu_flags, NULL, ",", " ", lineno, CpuMax);
1489 1.1 christos
1490 1.1 christos fprintf (table, " { ");
1491 1.1 christos
1492 1.1 christos for (i = 0; i < ARRAY_SIZE (operand_types); i++)
1493 1.1 christos {
1494 1.8 christos if (!operand_types[i])
1495 1.1 christos {
1496 1.1 christos if (i == 0)
1497 1.6 christos process_i386_operand_type (table, "0", stage_opcodes, "\t ",
1498 1.6 christos lineno);
1499 1.1 christos break;
1500 1.1 christos }
1501 1.1 christos
1502 1.1 christos if (i != 0)
1503 1.1 christos fprintf (table, ",\n ");
1504 1.1 christos
1505 1.6 christos process_i386_operand_type (table, operand_types[i], stage_opcodes,
1506 1.1 christos "\t ", lineno);
1507 1.1 christos }
1508 1.1 christos fprintf (table, " } },\n");
1509 1.1 christos }
1510 1.1 christos
1511 1.1 christos struct opcode_hash_entry
1512 1.1 christos {
1513 1.9 christos const char *name;
1514 1.9 christos struct opcode_entry
1515 1.9 christos {
1516 1.9 christos struct opcode_entry *next;
1517 1.9 christos char *opcode;
1518 1.9 christos int lineno;
1519 1.9 christos } entry;
1520 1.1 christos };
1521 1.1 christos
1522 1.1 christos /* Calculate the hash value of an opcode hash entry P. */
1523 1.1 christos
1524 1.1 christos static hashval_t
1525 1.1 christos opcode_hash_hash (const void *p)
1526 1.1 christos {
1527 1.1 christos struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
1528 1.1 christos return htab_hash_string (entry->name);
1529 1.1 christos }
1530 1.1 christos
1531 1.1 christos /* Compare a string Q against an opcode hash entry P. */
1532 1.1 christos
1533 1.1 christos static int
1534 1.1 christos opcode_hash_eq (const void *p, const void *q)
1535 1.1 christos {
1536 1.1 christos struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
1537 1.1 christos const char *name = (const char *) q;
1538 1.1 christos return strcmp (name, entry->name) == 0;
1539 1.1 christos }
1540 1.1 christos
1541 1.1 christos static void
1542 1.8 christos parse_template (char *buf, int lineno)
1543 1.8 christos {
1544 1.8 christos char sep, *end, *name;
1545 1.9 christos struct template *tmpl;
1546 1.8 christos struct template_instance *last_inst = NULL;
1547 1.8 christos
1548 1.8 christos buf = remove_leading_whitespaces (buf + 1);
1549 1.8 christos end = strchr (buf, ':');
1550 1.8 christos if (end == NULL)
1551 1.9 christos {
1552 1.9 christos struct template *prev = NULL;
1553 1.9 christos
1554 1.9 christos end = strchr (buf, '>');
1555 1.9 christos if (end == NULL)
1556 1.9 christos fail ("%s: %d: missing ':' or '>'\n", filename, lineno);
1557 1.9 christos if (*remove_leading_whitespaces (end + 1))
1558 1.9 christos fail ("%s: %d: malformed template purge\n", filename, lineno);
1559 1.9 christos *end = '\0';
1560 1.9 christos remove_trailing_whitespaces (buf);
1561 1.9 christos /* Don't bother freeing the various structures. */
1562 1.9 christos for (tmpl = templates; tmpl != NULL; tmpl = (prev = tmpl)->next)
1563 1.9 christos if (!strcmp (buf, tmpl->name))
1564 1.9 christos break;
1565 1.9 christos if (tmpl == NULL)
1566 1.9 christos fail ("%s: %d: no template '%s'\n", filename, lineno, buf);
1567 1.9 christos if (prev)
1568 1.9 christos prev->next = tmpl->next;
1569 1.9 christos else
1570 1.9 christos templates = tmpl->next;
1571 1.9 christos return;
1572 1.9 christos }
1573 1.8 christos *end++ = '\0';
1574 1.8 christos remove_trailing_whitespaces (buf);
1575 1.8 christos
1576 1.8 christos if (*buf == '\0')
1577 1.8 christos fail ("%s: %d: missing template identifier\n", filename, lineno);
1578 1.9 christos tmpl = xmalloc (sizeof (*tmpl));
1579 1.8 christos tmpl->name = xstrdup (buf);
1580 1.8 christos
1581 1.8 christos tmpl->params = NULL;
1582 1.8 christos do {
1583 1.8 christos struct template_param *param;
1584 1.8 christos
1585 1.8 christos buf = remove_leading_whitespaces (end);
1586 1.8 christos end = strpbrk (buf, ":,");
1587 1.8 christos if (end == NULL)
1588 1.8 christos fail ("%s: %d: missing ':' or ','\n", filename, lineno);
1589 1.8 christos
1590 1.8 christos sep = *end;
1591 1.8 christos *end++ = '\0';
1592 1.8 christos remove_trailing_whitespaces (buf);
1593 1.8 christos
1594 1.8 christos param = xmalloc (sizeof (*param));
1595 1.8 christos param->name = xstrdup (buf);
1596 1.8 christos param->next = tmpl->params;
1597 1.8 christos tmpl->params = param;
1598 1.8 christos } while (sep == ':');
1599 1.8 christos
1600 1.8 christos tmpl->instances = NULL;
1601 1.8 christos do {
1602 1.8 christos struct template_instance *inst;
1603 1.8 christos char *cur, *next;
1604 1.8 christos const struct template_param *param;
1605 1.8 christos
1606 1.8 christos buf = remove_leading_whitespaces (end);
1607 1.8 christos end = strpbrk (buf, ",>");
1608 1.8 christos if (end == NULL)
1609 1.8 christos fail ("%s: %d: missing ',' or '>'\n", filename, lineno);
1610 1.8 christos
1611 1.8 christos sep = *end;
1612 1.8 christos *end++ = '\0';
1613 1.8 christos
1614 1.8 christos inst = xmalloc (sizeof (*inst));
1615 1.8 christos inst->next = NULL;
1616 1.8 christos inst->args = NULL;
1617 1.8 christos
1618 1.8 christos cur = next_field (buf, ':', &next, end);
1619 1.8 christos inst->name = *cur != '$' ? xstrdup (cur) : "";
1620 1.8 christos
1621 1.8 christos for (param = tmpl->params; param; param = param->next)
1622 1.8 christos {
1623 1.8 christos struct template_arg *arg = xmalloc (sizeof (*arg));
1624 1.8 christos
1625 1.8 christos cur = next_field (next, ':', &next, end);
1626 1.8 christos if (next > end)
1627 1.8 christos fail ("%s: %d: missing argument for '%s'\n", filename, lineno, param->name);
1628 1.8 christos arg->val = xstrdup (cur);
1629 1.8 christos arg->next = inst->args;
1630 1.8 christos inst->args = arg;
1631 1.8 christos }
1632 1.8 christos
1633 1.8 christos if (tmpl->instances)
1634 1.8 christos last_inst->next = inst;
1635 1.8 christos else
1636 1.8 christos tmpl->instances = inst;
1637 1.8 christos last_inst = inst;
1638 1.8 christos } while (sep == ',');
1639 1.8 christos
1640 1.8 christos buf = remove_leading_whitespaces (end);
1641 1.8 christos if (*buf)
1642 1.8 christos fprintf(stderr, "%s: %d: excess characters '%s'\n",
1643 1.8 christos filename, lineno, buf);
1644 1.8 christos
1645 1.8 christos tmpl->next = templates;
1646 1.8 christos templates = tmpl;
1647 1.8 christos }
1648 1.8 christos
1649 1.8 christos static unsigned int
1650 1.8 christos expand_templates (char *name, const char *str, htab_t opcode_hash_table,
1651 1.8 christos struct opcode_hash_entry ***opcode_array_p, int lineno)
1652 1.8 christos {
1653 1.8 christos static unsigned int idx, opcode_array_size;
1654 1.8 christos struct opcode_hash_entry **opcode_array = *opcode_array_p;
1655 1.9 christos struct opcode_hash_entry **hash_slot;
1656 1.9 christos struct opcode_entry *entry;
1657 1.8 christos char *ptr1 = strchr(name, '<'), *ptr2;
1658 1.8 christos
1659 1.8 christos if (ptr1 == NULL)
1660 1.8 christos {
1661 1.8 christos /* Get the slot in hash table. */
1662 1.8 christos hash_slot = (struct opcode_hash_entry **)
1663 1.8 christos htab_find_slot_with_hash (opcode_hash_table, name,
1664 1.8 christos htab_hash_string (name),
1665 1.8 christos INSERT);
1666 1.8 christos
1667 1.8 christos if (*hash_slot == NULL)
1668 1.8 christos {
1669 1.8 christos /* It is the new one. Put it on opcode array. */
1670 1.8 christos if (idx >= opcode_array_size)
1671 1.8 christos {
1672 1.8 christos /* Grow the opcode array when needed. */
1673 1.8 christos opcode_array_size += 1024;
1674 1.8 christos opcode_array = (struct opcode_hash_entry **)
1675 1.8 christos xrealloc (opcode_array,
1676 1.8 christos sizeof (*opcode_array) * opcode_array_size);
1677 1.8 christos *opcode_array_p = opcode_array;
1678 1.8 christos }
1679 1.8 christos
1680 1.8 christos opcode_array[idx] = (struct opcode_hash_entry *)
1681 1.8 christos xmalloc (sizeof (struct opcode_hash_entry));
1682 1.8 christos opcode_array[idx]->name = xstrdup (name);
1683 1.8 christos *hash_slot = opcode_array[idx];
1684 1.9 christos entry = &opcode_array[idx]->entry;
1685 1.8 christos idx++;
1686 1.8 christos }
1687 1.8 christos else
1688 1.8 christos {
1689 1.8 christos /* Append it to the existing one. */
1690 1.9 christos struct opcode_entry **entryp = &(*hash_slot)->entry.next;
1691 1.9 christos
1692 1.9 christos while (*entryp != NULL)
1693 1.9 christos entryp = &(*entryp)->next;
1694 1.9 christos entry = (struct opcode_entry *)xmalloc (sizeof (struct opcode_entry));
1695 1.9 christos *entryp = entry;
1696 1.8 christos }
1697 1.9 christos
1698 1.9 christos entry->next = NULL;
1699 1.9 christos entry->opcode = xstrdup (str);
1700 1.9 christos entry->lineno = lineno;
1701 1.8 christos }
1702 1.8 christos else if ((ptr2 = strchr(ptr1 + 1, '>')) == NULL)
1703 1.8 christos fail ("%s: %d: missing '>'\n", filename, lineno);
1704 1.8 christos else
1705 1.8 christos {
1706 1.8 christos const struct template *tmpl;
1707 1.8 christos const struct template_instance *inst;
1708 1.8 christos
1709 1.8 christos *ptr1 = '\0';
1710 1.8 christos ptr1 = remove_leading_whitespaces (ptr1 + 1);
1711 1.8 christos remove_trailing_whitespaces (ptr1);
1712 1.8 christos
1713 1.8 christos *ptr2++ = '\0';
1714 1.8 christos
1715 1.8 christos for ( tmpl = templates; tmpl; tmpl = tmpl->next )
1716 1.8 christos if (!strcmp(ptr1, tmpl->name))
1717 1.8 christos break;
1718 1.8 christos if (!tmpl)
1719 1.8 christos fail ("reference to unknown template '%s'\n", ptr1);
1720 1.8 christos
1721 1.8 christos for (inst = tmpl->instances; inst; inst = inst->next)
1722 1.8 christos {
1723 1.8 christos char *name2 = xmalloc(strlen(name) + strlen(inst->name) + strlen(ptr2) + 1);
1724 1.8 christos char *str2 = xmalloc(2 * strlen(str));
1725 1.8 christos const char *src;
1726 1.8 christos
1727 1.8 christos strcpy (name2, name);
1728 1.8 christos strcat (name2, inst->name);
1729 1.8 christos strcat (name2, ptr2);
1730 1.8 christos
1731 1.8 christos for (ptr1 = str2, src = str; *src; )
1732 1.8 christos {
1733 1.8 christos const char *ident = tmpl->name, *end;
1734 1.8 christos const struct template_param *param;
1735 1.8 christos const struct template_arg *arg;
1736 1.8 christos
1737 1.8 christos if ((*ptr1 = *src++) != '<')
1738 1.8 christos {
1739 1.8 christos ++ptr1;
1740 1.8 christos continue;
1741 1.8 christos }
1742 1.8 christos while (ISSPACE(*src))
1743 1.8 christos ++src;
1744 1.8 christos while (*ident && *src == *ident)
1745 1.8 christos ++src, ++ident;
1746 1.8 christos while (ISSPACE(*src))
1747 1.8 christos ++src;
1748 1.8 christos if (*src != ':' || *ident != '\0')
1749 1.8 christos {
1750 1.8 christos memcpy (++ptr1, tmpl->name, ident - tmpl->name);
1751 1.8 christos ptr1 += ident - tmpl->name;
1752 1.8 christos continue;
1753 1.8 christos }
1754 1.8 christos while (ISSPACE(*++src))
1755 1.8 christos ;
1756 1.8 christos
1757 1.8 christos end = src;
1758 1.8 christos while (*end != '\0' && !ISSPACE(*end) && *end != '>')
1759 1.8 christos ++end;
1760 1.8 christos
1761 1.8 christos for (param = tmpl->params, arg = inst->args; param;
1762 1.8 christos param = param->next, arg = arg->next)
1763 1.8 christos {
1764 1.8 christos if (end - src == strlen (param->name)
1765 1.8 christos && !memcmp (src, param->name, end - src))
1766 1.8 christos {
1767 1.8 christos src = end;
1768 1.8 christos break;
1769 1.8 christos }
1770 1.8 christos }
1771 1.8 christos
1772 1.8 christos if (param == NULL)
1773 1.8 christos fail ("template '%s' has no parameter '%.*s'\n",
1774 1.8 christos tmpl->name, (int)(end - src), src);
1775 1.8 christos
1776 1.8 christos while (ISSPACE(*src))
1777 1.8 christos ++src;
1778 1.8 christos if (*src != '>')
1779 1.8 christos fail ("%s: %d: missing '>'\n", filename, lineno);
1780 1.8 christos
1781 1.8 christos memcpy(ptr1, arg->val, strlen(arg->val));
1782 1.8 christos ptr1 += strlen(arg->val);
1783 1.8 christos ++src;
1784 1.8 christos }
1785 1.8 christos
1786 1.8 christos *ptr1 = '\0';
1787 1.8 christos
1788 1.8 christos expand_templates (name2, str2, opcode_hash_table, opcode_array_p,
1789 1.8 christos lineno);
1790 1.8 christos
1791 1.8 christos free (str2);
1792 1.8 christos free (name2);
1793 1.8 christos }
1794 1.8 christos }
1795 1.8 christos
1796 1.8 christos return idx;
1797 1.8 christos }
1798 1.8 christos
1799 1.9 christos static int mnemonic_cmp(const void *p1, const void *p2)
1800 1.9 christos {
1801 1.9 christos const struct opcode_hash_entry *const *e1 = p1, *const *e2 = p2;
1802 1.9 christos const char *s1 = (*e1)->name, *s2 = (*e2)->name;
1803 1.9 christos unsigned int i;
1804 1.9 christos size_t l1 = strlen (s1), l2 = strlen (s2);
1805 1.9 christos
1806 1.9 christos for (i = 1; i <= l1 && i <= l2; ++i)
1807 1.9 christos {
1808 1.9 christos if (s1[l1 - i] != s2[l2 - i])
1809 1.9 christos return (unsigned char)s1[l1 - i] - (unsigned char)s2[l2 - i];
1810 1.9 christos }
1811 1.9 christos
1812 1.9 christos return (int)(l1 - l2);
1813 1.9 christos }
1814 1.9 christos
1815 1.8 christos static void
1816 1.1 christos process_i386_opcodes (FILE *table)
1817 1.1 christos {
1818 1.1 christos FILE *fp;
1819 1.1 christos char buf[2048];
1820 1.9 christos unsigned int i, j, nr, offs;
1821 1.9 christos size_t l;
1822 1.9 christos char *str, *p, *last;
1823 1.1 christos htab_t opcode_hash_table;
1824 1.8 christos struct opcode_hash_entry **opcode_array = NULL;
1825 1.7 christos int lineno = 0, marker = 0;
1826 1.1 christos
1827 1.1 christos filename = "i386-opc.tbl";
1828 1.7 christos fp = stdin;
1829 1.1 christos
1830 1.1 christos i = 0;
1831 1.1 christos opcode_hash_table = htab_create_alloc (16, opcode_hash_hash,
1832 1.1 christos opcode_hash_eq, NULL,
1833 1.1 christos xcalloc, free);
1834 1.1 christos
1835 1.9 christos fprintf (table, "\n#include \"i386-mnem.h\"\n");
1836 1.1 christos fprintf (table, "\n/* i386 opcode table. */\n\n");
1837 1.9 christos fprintf (table, "static const insn_template i386_optab[] =\n{\n");
1838 1.1 christos
1839 1.1 christos /* Put everything on opcode array. */
1840 1.1 christos while (!feof (fp))
1841 1.1 christos {
1842 1.9 christos char *name;
1843 1.9 christos
1844 1.1 christos if (fgets (buf, sizeof (buf), fp) == NULL)
1845 1.1 christos break;
1846 1.1 christos
1847 1.9 christos p = remove_leading_whitespaces (buf);
1848 1.9 christos
1849 1.9 christos for ( ; ; )
1850 1.9 christos {
1851 1.9 christos lineno++;
1852 1.1 christos
1853 1.9 christos /* Skip comments. */
1854 1.9 christos str = strstr (p, "//");
1855 1.9 christos if (str != NULL)
1856 1.9 christos {
1857 1.9 christos str[0] = '\0';
1858 1.9 christos remove_trailing_whitespaces (p);
1859 1.9 christos break;
1860 1.9 christos }
1861 1.1 christos
1862 1.9 christos /* Look for line continuation character. */
1863 1.9 christos remove_trailing_whitespaces (p);
1864 1.9 christos j = strlen (buf);
1865 1.9 christos if (!j || buf[j - 1] != '+')
1866 1.9 christos break;
1867 1.9 christos if (j >= sizeof (buf) - 1)
1868 1.9 christos fail ("%s: %d: (continued) line too long\n", filename, lineno);
1869 1.1 christos
1870 1.9 christos if (fgets (buf + j - 1, sizeof (buf) - j + 1, fp) == NULL)
1871 1.9 christos {
1872 1.9 christos fprintf (stderr, "%s: Line continuation on last line?\n",
1873 1.9 christos filename);
1874 1.9 christos break;
1875 1.9 christos }
1876 1.9 christos }
1877 1.1 christos
1878 1.1 christos switch (p[0])
1879 1.1 christos {
1880 1.1 christos case '#':
1881 1.7 christos if (!strcmp("### MARKER ###", buf))
1882 1.7 christos marker = 1;
1883 1.7 christos else
1884 1.7 christos {
1885 1.7 christos /* Since we ignore all included files (we only care about their
1886 1.7 christos #define-s here), we don't need to monitor filenames. The final
1887 1.7 christos line number directive is going to refer to the main source file
1888 1.7 christos again. */
1889 1.7 christos char *end;
1890 1.7 christos unsigned long ln;
1891 1.7 christos
1892 1.7 christos p = remove_leading_whitespaces (p + 1);
1893 1.7 christos if (!strncmp(p, "line", 4))
1894 1.7 christos p += 4;
1895 1.7 christos ln = strtoul (p, &end, 10);
1896 1.7 christos if (ln > 1 && ln < INT_MAX
1897 1.7 christos && *remove_leading_whitespaces (end) == '"')
1898 1.7 christos lineno = ln - 1;
1899 1.7 christos }
1900 1.1 christos /* Ignore comments. */
1901 1.1 christos case '\0':
1902 1.1 christos continue;
1903 1.1 christos break;
1904 1.8 christos case '<':
1905 1.8 christos parse_template (p, lineno);
1906 1.8 christos continue;
1907 1.1 christos default:
1908 1.7 christos if (!marker)
1909 1.7 christos continue;
1910 1.1 christos break;
1911 1.1 christos }
1912 1.1 christos
1913 1.1 christos last = p + strlen (p);
1914 1.1 christos
1915 1.1 christos /* Find name. */
1916 1.1 christos name = next_field (p, ',', &str, last);
1917 1.1 christos
1918 1.8 christos i = expand_templates (name, str, opcode_hash_table, &opcode_array,
1919 1.8 christos lineno);
1920 1.1 christos }
1921 1.1 christos
1922 1.1 christos /* Process opcode array. */
1923 1.1 christos for (j = 0; j < i; j++)
1924 1.1 christos {
1925 1.9 christos const char *name = opcode_array[j]->name;
1926 1.9 christos struct opcode_entry *next;
1927 1.8 christos
1928 1.9 christos for (next = &opcode_array[j]->entry; next; next = next->next)
1929 1.1 christos {
1930 1.1 christos str = next->opcode;
1931 1.1 christos lineno = next->lineno;
1932 1.1 christos last = str + strlen (str);
1933 1.1 christos output_i386_opcode (table, name, str, last, lineno);
1934 1.1 christos }
1935 1.1 christos }
1936 1.1 christos
1937 1.1 christos fclose (fp);
1938 1.1 christos
1939 1.9 christos fprintf (table, "};\n");
1940 1.9 christos
1941 1.9 christos /* Generate opcode sets array. */
1942 1.9 christos fprintf (table, "\n/* i386 opcode sets table. */\n\n");
1943 1.9 christos fprintf (table, "typedef unsigned short i386_op_off_t;\n");
1944 1.9 christos fprintf (table, "static const i386_op_off_t i386_op_sets[] =\n{\n ");
1945 1.9 christos
1946 1.9 christos for (nr = j = 0; j < i; j++)
1947 1.9 christos {
1948 1.9 christos struct opcode_entry *next = &opcode_array[j]->entry;
1949 1.9 christos
1950 1.9 christos if ((j + 1) % 8 != 0)
1951 1.9 christos fprintf (table, "%5u,", nr);
1952 1.9 christos else
1953 1.9 christos fprintf (table, "%5u,\n ", nr);
1954 1.9 christos do
1955 1.9 christos {
1956 1.9 christos ++nr;
1957 1.9 christos next = next->next;
1958 1.9 christos }
1959 1.9 christos while (next);
1960 1.9 christos }
1961 1.9 christos
1962 1.9 christos fprintf (table, "%5u\n};\n", nr);
1963 1.9 christos
1964 1.9 christos /* Emit mnemonics and associated #define-s. */
1965 1.9 christos qsort (opcode_array, i, sizeof (*opcode_array), mnemonic_cmp);
1966 1.9 christos
1967 1.9 christos fp = fopen ("i386-mnem.h", "w");
1968 1.9 christos if (fp == NULL)
1969 1.9 christos fail ("can't create i386-mnem.h, errno = %s\n",
1970 1.9 christos xstrerror (errno));
1971 1.8 christos
1972 1.9 christos process_copyright (fp);
1973 1.1 christos
1974 1.9 christos fprintf (table, "\n/* i386 mnemonics table. */\n\n");
1975 1.9 christos fprintf (table, "const char i386_mnemonics[] =\n");
1976 1.9 christos fprintf (fp, "\nextern const char i386_mnemonics[];\n\n");
1977 1.9 christos
1978 1.9 christos str = NULL;
1979 1.9 christos for (l = strlen (opcode_array[offs = j = 0]->name); j < i; j++)
1980 1.9 christos {
1981 1.9 christos const char *name = opcode_array[j]->name;
1982 1.9 christos const char *next = NULL;
1983 1.9 christos size_t l1 = j + 1 < i ? strlen(next = opcode_array[j + 1]->name) : 0;
1984 1.9 christos
1985 1.9 christos if (str == NULL)
1986 1.9 christos str = mkident (name);
1987 1.9 christos if (l < l1 && !strcmp(name, next + l1 - l))
1988 1.9 christos {
1989 1.9 christos fprintf (fp, "#define MN_%s ", str);
1990 1.9 christos free (str);
1991 1.9 christos str = mkident (next);
1992 1.9 christos fprintf (fp, "(MN_%s + %zu)\n", str, l1 - l);
1993 1.9 christos }
1994 1.9 christos else
1995 1.9 christos {
1996 1.9 christos fprintf (table, " \"\\0\"\"%s\"\n", name);
1997 1.9 christos fprintf (fp, "#define MN_%s %#x\n", str, offs + 1);
1998 1.9 christos offs += strlen (name) + 1;
1999 1.9 christos free (str);
2000 1.9 christos str = NULL;
2001 1.9 christos }
2002 1.9 christos l = l1;
2003 1.9 christos }
2004 1.9 christos
2005 1.9 christos fprintf (table, " \"\\0\"\".insn\"\n");
2006 1.9 christos fprintf (fp, "#define MN__insn %#x\n", offs + 1);
2007 1.1 christos
2008 1.9 christos fprintf (table, ";\n");
2009 1.1 christos
2010 1.9 christos fclose (fp);
2011 1.1 christos }
2012 1.1 christos
2013 1.1 christos static void
2014 1.1 christos process_i386_registers (FILE *table)
2015 1.1 christos {
2016 1.1 christos FILE *fp;
2017 1.1 christos char buf[2048];
2018 1.1 christos char *str, *p, *last;
2019 1.1 christos char *reg_name, *reg_type, *reg_flags, *reg_num;
2020 1.1 christos char *dw2_32_num, *dw2_64_num;
2021 1.1 christos int lineno = 0;
2022 1.1 christos
2023 1.1 christos filename = "i386-reg.tbl";
2024 1.1 christos fp = fopen (filename, "r");
2025 1.1 christos if (fp == NULL)
2026 1.9 christos fail ("can't find i386-reg.tbl for reading, errno = %s\n",
2027 1.1 christos xstrerror (errno));
2028 1.1 christos
2029 1.1 christos fprintf (table, "\n/* i386 register table. */\n\n");
2030 1.9 christos fprintf (table, "static const reg_entry i386_regtab[] =\n{\n");
2031 1.1 christos
2032 1.1 christos while (!feof (fp))
2033 1.1 christos {
2034 1.1 christos if (fgets (buf, sizeof (buf), fp) == NULL)
2035 1.1 christos break;
2036 1.1 christos
2037 1.1 christos lineno++;
2038 1.1 christos
2039 1.1 christos p = remove_leading_whitespaces (buf);
2040 1.1 christos
2041 1.1 christos /* Skip comments. */
2042 1.1 christos str = strstr (p, "//");
2043 1.1 christos if (str != NULL)
2044 1.1 christos str[0] = '\0';
2045 1.1 christos
2046 1.1 christos /* Remove trailing white spaces. */
2047 1.1 christos remove_trailing_whitespaces (p);
2048 1.1 christos
2049 1.1 christos switch (p[0])
2050 1.1 christos {
2051 1.1 christos case '#':
2052 1.1 christos fprintf (table, "%s\n", p);
2053 1.1 christos case '\0':
2054 1.1 christos continue;
2055 1.1 christos break;
2056 1.1 christos default:
2057 1.1 christos break;
2058 1.1 christos }
2059 1.1 christos
2060 1.1 christos last = p + strlen (p);
2061 1.1 christos
2062 1.1 christos /* Find reg_name. */
2063 1.1 christos reg_name = next_field (p, ',', &str, last);
2064 1.1 christos
2065 1.1 christos /* Find reg_type. */
2066 1.1 christos reg_type = next_field (str, ',', &str, last);
2067 1.1 christos
2068 1.1 christos /* Find reg_flags. */
2069 1.1 christos reg_flags = next_field (str, ',', &str, last);
2070 1.1 christos
2071 1.1 christos /* Find reg_num. */
2072 1.1 christos reg_num = next_field (str, ',', &str, last);
2073 1.1 christos
2074 1.1 christos fprintf (table, " { \"%s\",\n ", reg_name);
2075 1.1 christos
2076 1.6 christos process_i386_operand_type (table, reg_type, stage_registers, "\t",
2077 1.6 christos lineno);
2078 1.1 christos
2079 1.1 christos /* Find 32-bit Dwarf2 register number. */
2080 1.1 christos dw2_32_num = next_field (str, ',', &str, last);
2081 1.1 christos
2082 1.1 christos /* Find 64-bit Dwarf2 register number. */
2083 1.1 christos dw2_64_num = next_field (str, ',', &str, last);
2084 1.1 christos
2085 1.1 christos fprintf (table, ",\n %s, %s, { %s, %s } },\n",
2086 1.1 christos reg_flags, reg_num, dw2_32_num, dw2_64_num);
2087 1.1 christos }
2088 1.1 christos
2089 1.1 christos fclose (fp);
2090 1.1 christos
2091 1.1 christos fprintf (table, "};\n");
2092 1.1 christos
2093 1.9 christos fprintf (table, "\nstatic const unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
2094 1.1 christos }
2095 1.1 christos
2096 1.1 christos static void
2097 1.1 christos process_i386_initializers (void)
2098 1.1 christos {
2099 1.1 christos unsigned int i;
2100 1.1 christos FILE *fp = fopen ("i386-init.h", "w");
2101 1.1 christos
2102 1.1 christos if (fp == NULL)
2103 1.9 christos fail ("can't create i386-init.h, errno = %s\n",
2104 1.1 christos xstrerror (errno));
2105 1.1 christos
2106 1.1 christos process_copyright (fp);
2107 1.1 christos
2108 1.9 christos for (i = 0; i < CpuMax; i++)
2109 1.9 christos process_i386_cpu_flag (fp, "0", cpu_flags[i].name, "", " ", -1, i);
2110 1.9 christos
2111 1.9 christos for (i = 0; i < ARRAY_SIZE (isa_dependencies); i++)
2112 1.1 christos {
2113 1.9 christos char *deps = xstrdup (isa_dependencies[i].deps);
2114 1.9 christos
2115 1.9 christos process_i386_cpu_flag (fp, deps, isa_dependencies[i].name,
2116 1.9 christos "", " ", -1, CpuMax);
2117 1.9 christos free (deps);
2118 1.1 christos }
2119 1.1 christos
2120 1.9 christos /* Early x87 is somewhat special: Both 287 and 387 not only add new insns
2121 1.9 christos but also remove some. Hence 8087 isn't a prereq to 287, and 287 isn't
2122 1.9 christos one to 387. We want the reverse to be true though: Disabling 8087 also
2123 1.9 christos is to disable 287+ and later; disabling 287 also means disabling 387+. */
2124 1.9 christos memcpy (isa_reverse_deps[Cpu287], isa_reverse_deps[Cpu387],
2125 1.9 christos sizeof (isa_reverse_deps[0]));
2126 1.9 christos isa_reverse_deps[Cpu287][Cpu387] = 1;
2127 1.9 christos memcpy (isa_reverse_deps[Cpu8087], isa_reverse_deps[Cpu287],
2128 1.9 christos sizeof (isa_reverse_deps[0]));
2129 1.9 christos isa_reverse_deps[Cpu8087][Cpu287] = 1;
2130 1.9 christos
2131 1.9 christos /* While we treat POPCNT as a prereq to SSE4.2, its disabling should not
2132 1.9 christos lead to disabling of anything else. */
2133 1.9 christos memset (isa_reverse_deps[CpuPOPCNT], 0, sizeof (isa_reverse_deps[0]));
2134 1.9 christos
2135 1.9 christos for (i = Cpu686 + 1; i < ARRAY_SIZE (isa_reverse_deps); i++)
2136 1.1 christos {
2137 1.9 christos size_t len;
2138 1.9 christos char *upper;
2139 1.9 christos
2140 1.9 christos if (memchr(isa_reverse_deps[i], 1,
2141 1.9 christos ARRAY_SIZE (isa_reverse_deps[0])) == NULL)
2142 1.9 christos continue;
2143 1.9 christos
2144 1.9 christos isa_reverse_deps[i][i] = 1;
2145 1.9 christos process_i386_cpu_flag (fp, NULL, cpu_flags[i].name, "", " ", -1, i);
2146 1.1 christos }
2147 1.9 christos
2148 1.1 christos fprintf (fp, "\n");
2149 1.1 christos
2150 1.1 christos fclose (fp);
2151 1.1 christos }
2152 1.1 christos
2153 1.1 christos /* Program options. */
2154 1.1 christos #define OPTION_SRCDIR 200
2155 1.1 christos
2156 1.1 christos struct option long_options[] =
2157 1.1 christos {
2158 1.1 christos {"srcdir", required_argument, NULL, OPTION_SRCDIR},
2159 1.1 christos {"debug", no_argument, NULL, 'd'},
2160 1.1 christos {"version", no_argument, NULL, 'V'},
2161 1.1 christos {"help", no_argument, NULL, 'h'},
2162 1.1 christos {0, no_argument, NULL, 0}
2163 1.1 christos };
2164 1.1 christos
2165 1.1 christos static void
2166 1.1 christos print_version (void)
2167 1.1 christos {
2168 1.1 christos printf ("%s: version 1.0\n", program_name);
2169 1.1 christos xexit (0);
2170 1.1 christos }
2171 1.1 christos
2172 1.1 christos static void
2173 1.1 christos usage (FILE * stream, int status)
2174 1.1 christos {
2175 1.1 christos fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
2176 1.1 christos program_name);
2177 1.1 christos xexit (status);
2178 1.1 christos }
2179 1.1 christos
2180 1.1 christos int
2181 1.1 christos main (int argc, char **argv)
2182 1.1 christos {
2183 1.1 christos extern int chdir (char *);
2184 1.1 christos char *srcdir = NULL;
2185 1.1 christos int c;
2186 1.5 christos unsigned int i, cpumax;
2187 1.1 christos FILE *table;
2188 1.1 christos
2189 1.1 christos program_name = *argv;
2190 1.1 christos xmalloc_set_program_name (program_name);
2191 1.1 christos
2192 1.1 christos while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
2193 1.1 christos switch (c)
2194 1.1 christos {
2195 1.1 christos case OPTION_SRCDIR:
2196 1.1 christos srcdir = optarg;
2197 1.1 christos break;
2198 1.1 christos case 'V':
2199 1.1 christos case 'v':
2200 1.1 christos print_version ();
2201 1.1 christos break;
2202 1.1 christos case 'd':
2203 1.1 christos debug = 1;
2204 1.1 christos break;
2205 1.1 christos case 'h':
2206 1.1 christos case '?':
2207 1.1 christos usage (stderr, 0);
2208 1.1 christos default:
2209 1.1 christos case 0:
2210 1.1 christos break;
2211 1.1 christos }
2212 1.1 christos
2213 1.1 christos if (optind != argc)
2214 1.1 christos usage (stdout, 1);
2215 1.1 christos
2216 1.1 christos if (srcdir != NULL)
2217 1.1 christos if (chdir (srcdir) != 0)
2218 1.9 christos fail ("unable to change directory to \"%s\", errno = %s\n",
2219 1.1 christos srcdir, xstrerror (errno));
2220 1.1 christos
2221 1.5 christos /* cpu_flags isn't sorted by position. */
2222 1.5 christos cpumax = 0;
2223 1.5 christos for (i = 0; i < ARRAY_SIZE (cpu_flags); i++)
2224 1.5 christos if (cpu_flags[i].position > cpumax)
2225 1.5 christos cpumax = cpu_flags[i].position;
2226 1.5 christos
2227 1.1 christos /* Check the unused bitfield in i386_cpu_flags. */
2228 1.5 christos #ifdef CpuUnused
2229 1.7 christos static_assert (ARRAY_SIZE (cpu_flags) == CpuMax + 2);
2230 1.7 christos
2231 1.5 christos if ((cpumax - 1) != CpuMax)
2232 1.9 christos fail ("CpuMax != %d!\n", cpumax);
2233 1.5 christos #else
2234 1.7 christos static_assert (ARRAY_SIZE (cpu_flags) == CpuMax + 1);
2235 1.7 christos
2236 1.5 christos if (cpumax != CpuMax)
2237 1.9 christos fail ("CpuMax != %d!\n", cpumax);
2238 1.5 christos
2239 1.1 christos c = CpuNumOfBits - CpuMax - 1;
2240 1.1 christos if (c)
2241 1.9 christos fail ("%d unused bits in i386_cpu_flags.\n", c);
2242 1.9 christos #endif
2243 1.9 christos
2244 1.9 christos /* If this triggers, CpuIsaBits needs to be increased. */
2245 1.9 christos static_assert (CpuAttrEnums <= (1u << CpuIsaBits));
2246 1.9 christos
2247 1.9 christos /* Check the unused bitfield in i386_cpu_attr. */
2248 1.9 christos #ifndef CpuAttrUnused
2249 1.9 christos c = CpuAttrNumOfBits - (CpuIsaBits + CpuMax + 1 - CpuAttrEnums);
2250 1.9 christos if (c)
2251 1.9 christos fail ("%d unused bits in i386_cpu_attr.\n", c);
2252 1.1 christos #endif
2253 1.1 christos
2254 1.7 christos static_assert (ARRAY_SIZE (opcode_modifiers) == Opcode_Modifier_Num);
2255 1.7 christos
2256 1.1 christos /* Check the unused bitfield in i386_operand_type. */
2257 1.7 christos #ifdef OTUnused
2258 1.7 christos static_assert (ARRAY_SIZE (operand_types) + CLASS_WIDTH + INSTANCE_WIDTH
2259 1.7 christos == OTNum + 1);
2260 1.7 christos #else
2261 1.7 christos static_assert (ARRAY_SIZE (operand_types) + CLASS_WIDTH + INSTANCE_WIDTH
2262 1.7 christos == OTNum);
2263 1.7 christos
2264 1.7 christos c = OTNumOfBits - OTNum;
2265 1.1 christos if (c)
2266 1.9 christos fail ("%d unused bits in i386_operand_type.\n", c);
2267 1.1 christos #endif
2268 1.1 christos
2269 1.1 christos qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
2270 1.1 christos compare);
2271 1.1 christos
2272 1.1 christos qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
2273 1.1 christos sizeof (opcode_modifiers [0]), compare);
2274 1.1 christos
2275 1.1 christos qsort (operand_types, ARRAY_SIZE (operand_types),
2276 1.1 christos sizeof (operand_types [0]), compare);
2277 1.1 christos
2278 1.9 christos process_i386_initializers ();
2279 1.9 christos
2280 1.1 christos table = fopen ("i386-tbl.h", "w");
2281 1.1 christos if (table == NULL)
2282 1.9 christos fail ("can't create i386-tbl.h, errno = %s\n",
2283 1.1 christos xstrerror (errno));
2284 1.1 christos
2285 1.1 christos process_copyright (table);
2286 1.1 christos
2287 1.1 christos process_i386_opcodes (table);
2288 1.1 christos process_i386_registers (table);
2289 1.1 christos
2290 1.1 christos fclose (table);
2291 1.1 christos
2292 1.1 christos exit (0);
2293 1.1 christos }
2294