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