]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - opcodes/i386-gen.c
*** empty log message ***
[thirdparty/binutils-gdb.git] / opcodes / i386-gen.c
CommitLineData
22da050b
L
1/* Copyright 2007, 2008, 2009
2 Free Software Foundation, Inc.
40b8e679 3
9b201bb5 4 This file is part of the GNU opcodes library.
40b8e679 5
9b201bb5 6 This library is free software; you can redistribute it and/or modify
40b8e679 7 it under the terms of the GNU General Public License as published by
9b201bb5
NC
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
40b8e679 10
9b201bb5
NC
11 It is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 License for more details.
40b8e679
L
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
9b201bb5
NC
18 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
40b8e679 20
40fb9820 21#include "sysdep.h"
40b8e679 22#include <stdio.h>
40b8e679
L
23#include <errno.h>
24#include "getopt.h"
25#include "libiberty.h"
c587b3f9 26#include "hashtab.h"
40b8e679
L
27#include "safe-ctype.h"
28
29#include "i386-opc.h"
30
31#include <libintl.h>
32#define _(String) gettext (String)
33
34static const char *program_name = NULL;
35static int debug = 0;
36
40fb9820
L
37typedef struct initializer
38{
39 const char *name;
40 const char *init;
41} initializer;
42
43static initializer cpu_flag_init [] =
44{
45 { "CPU_UNKNOWN_FLAGS",
46 "unknown" },
47 { "CPU_GENERIC32_FLAGS",
48 "Cpu186|Cpu286|Cpu386" },
49 { "CPU_GENERIC64_FLAGS",
bd5295b2 50 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|CpuMMX|CpuSSE|CpuSSE2|CpuLM" },
40fb9820
L
51 { "CPU_NONE_FLAGS",
52 "0" },
53 { "CPU_I186_FLAGS",
54 "Cpu186" },
55 { "CPU_I286_FLAGS",
56 "Cpu186|Cpu286" },
57 { "CPU_I386_FLAGS",
58 "Cpu186|Cpu286|Cpu386" },
59 { "CPU_I486_FLAGS",
60 "Cpu186|Cpu286|Cpu386|Cpu486" },
61 { "CPU_I586_FLAGS",
62 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586" },
63 { "CPU_I686_FLAGS",
64 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686" },
65 { "CPU_P2_FLAGS",
66 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuMMX" },
67 { "CPU_P3_FLAGS",
115c7c25 68 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuMMX|CpuSSE" },
40fb9820 69 { "CPU_P4_FLAGS",
bd5295b2 70 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|CpuMMX|CpuSSE|CpuSSE2" },
40fb9820 71 { "CPU_NOCONA_FLAGS",
bd5295b2 72 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuLM" },
40fb9820 73 { "CPU_CORE_FLAGS",
bd5295b2 74 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3" },
40fb9820 75 { "CPU_CORE2_FLAGS",
bd5295b2
L
76 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuLM" },
77 { "CPU_COREI7_FLAGS",
78 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuRdtscp|CpuLM" },
40fb9820 79 { "CPU_K6_FLAGS",
bd5295b2 80 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuSYSCALL|CpuMMX" },
40fb9820 81 { "CPU_K6_2_FLAGS",
bd5295b2 82 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuSYSCALL|CpuMMX|Cpu3dnow" },
40fb9820 83 { "CPU_ATHLON_FLAGS",
bd5295b2 84 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|CpuMMX|Cpu3dnow|Cpu3dnowA" },
40fb9820 85 { "CPU_K8_FLAGS",
bd5295b2 86 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|CpuRdtscp|CpuMMX|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2|CpuLM" },
40fb9820 87 { "CPU_AMDFAM10_FLAGS",
bd5295b2
L
88 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|CpuRdtscp|CpuMMX|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuLM" },
89 { "CPU_CLFLUSH_FLAGS",
90 "CpuClflush" },
91 { "CPU_SYSCALL_FLAGS",
92 "CpuSYSCALL" },
40fb9820
L
93 { "CPU_MMX_FLAGS",
94 "CpuMMX" },
95 { "CPU_SSE_FLAGS",
115c7c25 96 "CpuMMX|CpuSSE" },
40fb9820 97 { "CPU_SSE2_FLAGS",
115c7c25 98 "CpuMMX|CpuSSE|CpuSSE2" },
40fb9820 99 { "CPU_SSE3_FLAGS",
115c7c25 100 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3" },
40fb9820 101 { "CPU_SSSE3_FLAGS",
115c7c25 102 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3" },
40fb9820 103 { "CPU_SSE4_1_FLAGS",
115c7c25 104 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1" },
40fb9820 105 { "CPU_SSE4_2_FLAGS",
115c7c25 106 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2" },
6305a203
L
107 { "CPU_VMX_FLAGS",
108 "CpuVMX" },
109 { "CPU_SMX_FLAGS",
110 "CpuSMX" },
f03fe4c1
L
111 { "CPU_XSAVE_FLAGS",
112 "CpuXsave" },
c0f3af97
L
113 { "CPU_AES_FLAGS",
114 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAES" },
594ab6a3
L
115 { "CPU_PCLMUL_FLAGS",
116 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuPCLMUL" },
c0f3af97
L
117 { "CPU_FMA_FLAGS",
118 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuFMA" },
f1f8f695
L
119 { "CPU_MOVBE_FLAGS",
120 "CpuMovbe" },
1b7f3fb0
L
121 { "CPU_RDTSCP_FLAGS",
122 "CpuRdtscp" },
f1f8f695
L
123 { "CPU_EPT_FLAGS",
124 "CpuEPT" },
40fb9820
L
125 { "CPU_3DNOW_FLAGS",
126 "CpuMMX|Cpu3dnow" },
127 { "CPU_3DNOWA_FLAGS",
115c7c25 128 "CpuMMX|Cpu3dnow|Cpu3dnowA" },
40fb9820
L
129 { "CPU_PADLOCK_FLAGS",
130 "CpuPadLock" },
131 { "CPU_SVME_FLAGS",
132 "CpuSVME" },
133 { "CPU_SSE4A_FLAGS",
115c7c25 134 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a" },
40fb9820 135 { "CPU_ABM_FLAGS",
3629bb00 136 "CpuABM" },
85f10a01 137 { "CPU_SSE5_FLAGS",
115c7c25 138 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuSSE5"},
c0f3af97
L
139 { "CPU_AVX_FLAGS",
140 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX" },
40fb9820
L
141};
142
143static initializer operand_type_init [] =
144{
145 { "OPERAND_TYPE_NONE",
146 "0" },
147 { "OPERAND_TYPE_REG8",
148 "Reg8" },
149 { "OPERAND_TYPE_REG16",
150 "Reg16" },
151 { "OPERAND_TYPE_REG32",
152 "Reg32" },
153 { "OPERAND_TYPE_REG64",
154 "Reg64" },
155 { "OPERAND_TYPE_IMM1",
156 "Imm1" },
157 { "OPERAND_TYPE_IMM8",
158 "Imm8" },
159 { "OPERAND_TYPE_IMM8S",
160 "Imm8S" },
161 { "OPERAND_TYPE_IMM16",
162 "Imm16" },
163 { "OPERAND_TYPE_IMM32",
164 "Imm32" },
165 { "OPERAND_TYPE_IMM32S",
166 "Imm32S" },
167 { "OPERAND_TYPE_IMM64",
168 "Imm64" },
169 { "OPERAND_TYPE_BASEINDEX",
170 "BaseIndex" },
171 { "OPERAND_TYPE_DISP8",
172 "Disp8" },
173 { "OPERAND_TYPE_DISP16",
174 "Disp16" },
175 { "OPERAND_TYPE_DISP32",
176 "Disp32" },
177 { "OPERAND_TYPE_DISP32S",
178 "Disp32S" },
179 { "OPERAND_TYPE_DISP64",
180 "Disp64" },
181 { "OPERAND_TYPE_INOUTPORTREG",
182 "InOutPortReg" },
183 { "OPERAND_TYPE_SHIFTCOUNT",
184 "ShiftCount" },
185 { "OPERAND_TYPE_CONTROL",
186 "Control" },
187 { "OPERAND_TYPE_TEST",
188 "Test" },
189 { "OPERAND_TYPE_DEBUG",
190 "FloatReg" },
191 { "OPERAND_TYPE_FLOATREG",
192 "FloatReg" },
193 { "OPERAND_TYPE_FLOATACC",
194 "FloatAcc" },
195 { "OPERAND_TYPE_SREG2",
196 "SReg2" },
197 { "OPERAND_TYPE_SREG3",
198 "SReg3" },
199 { "OPERAND_TYPE_ACC",
200 "Acc" },
201 { "OPERAND_TYPE_JUMPABSOLUTE",
202 "JumpAbsolute" },
203 { "OPERAND_TYPE_REGMMX",
204 "RegMMX" },
205 { "OPERAND_TYPE_REGXMM",
206 "RegXMM" },
c0f3af97
L
207 { "OPERAND_TYPE_REGYMM",
208 "RegYMM" },
40fb9820
L
209 { "OPERAND_TYPE_ESSEG",
210 "EsSeg" },
211 { "OPERAND_TYPE_ACC32",
7d5e4556 212 "Reg32|Acc|Dword" },
40fb9820 213 { "OPERAND_TYPE_ACC64",
7d5e4556 214 "Reg64|Acc|Qword" },
65da13b5
L
215 { "OPERAND_TYPE_INOUTPORTREG",
216 "InOutPortReg" },
40fb9820
L
217 { "OPERAND_TYPE_REG16_INOUTPORTREG",
218 "Reg16|InOutPortReg" },
219 { "OPERAND_TYPE_DISP16_32",
220 "Disp16|Disp32" },
221 { "OPERAND_TYPE_ANYDISP",
222 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
223 { "OPERAND_TYPE_IMM16_32",
224 "Imm16|Imm32" },
225 { "OPERAND_TYPE_IMM16_32S",
226 "Imm16|Imm32S" },
227 { "OPERAND_TYPE_IMM16_32_32S",
228 "Imm16|Imm32|Imm32S" },
229 { "OPERAND_TYPE_IMM32_32S_DISP32",
230 "Imm32|Imm32S|Disp32" },
231 { "OPERAND_TYPE_IMM64_DISP64",
232 "Imm64|Disp64" },
233 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
234 "Imm32|Imm32S|Imm64|Disp32" },
235 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
236 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
c0f3af97
L
237 { "OPERAND_TYPE_VEX_IMM4",
238 "VEX_Imm4" },
40fb9820
L
239};
240
241typedef struct bitfield
242{
243 int position;
244 int value;
245 const char *name;
246} bitfield;
247
248#define BITFIELD(n) { n, 0, #n }
249
250static bitfield cpu_flags[] =
251{
252 BITFIELD (Cpu186),
253 BITFIELD (Cpu286),
254 BITFIELD (Cpu386),
255 BITFIELD (Cpu486),
256 BITFIELD (Cpu586),
257 BITFIELD (Cpu686),
bd5295b2
L
258 BITFIELD (CpuClflush),
259 BITFIELD (CpuSYSCALL),
40fb9820 260 BITFIELD (CpuMMX),
40fb9820
L
261 BITFIELD (CpuSSE),
262 BITFIELD (CpuSSE2),
263 BITFIELD (CpuSSE3),
264 BITFIELD (CpuSSSE3),
265 BITFIELD (CpuSSE4_1),
266 BITFIELD (CpuSSE4_2),
c0f3af97 267 BITFIELD (CpuAVX),
40fb9820 268 BITFIELD (CpuSSE4a),
85f10a01 269 BITFIELD (CpuSSE5),
40fb9820
L
270 BITFIELD (Cpu3dnow),
271 BITFIELD (Cpu3dnowA),
272 BITFIELD (CpuPadLock),
273 BITFIELD (CpuSVME),
274 BITFIELD (CpuVMX),
47dd174c 275 BITFIELD (CpuSMX),
40fb9820 276 BITFIELD (CpuABM),
475a2301 277 BITFIELD (CpuXsave),
c0f3af97 278 BITFIELD (CpuAES),
594ab6a3 279 BITFIELD (CpuPCLMUL),
c0f3af97
L
280 BITFIELD (CpuFMA),
281 BITFIELD (CpuLM),
f1f8f695
L
282 BITFIELD (CpuMovbe),
283 BITFIELD (CpuEPT),
1b7f3fb0 284 BITFIELD (CpuRdtscp),
40fb9820
L
285 BITFIELD (Cpu64),
286 BITFIELD (CpuNo64),
287#ifdef CpuUnused
288 BITFIELD (CpuUnused),
289#endif
290};
291
292static bitfield opcode_modifiers[] =
293{
294 BITFIELD (D),
295 BITFIELD (W),
b6169b20 296 BITFIELD (S),
40fb9820
L
297 BITFIELD (Modrm),
298 BITFIELD (ShortForm),
299 BITFIELD (Jump),
300 BITFIELD (JumpDword),
301 BITFIELD (JumpByte),
302 BITFIELD (JumpInterSegment),
303 BITFIELD (FloatMF),
304 BITFIELD (FloatR),
305 BITFIELD (FloatD),
306 BITFIELD (Size16),
307 BITFIELD (Size32),
308 BITFIELD (Size64),
309 BITFIELD (IgnoreSize),
310 BITFIELD (DefaultSize),
311 BITFIELD (No_bSuf),
312 BITFIELD (No_wSuf),
313 BITFIELD (No_lSuf),
314 BITFIELD (No_sSuf),
315 BITFIELD (No_qSuf),
7ce189b3 316 BITFIELD (No_ldSuf),
40fb9820
L
317 BITFIELD (FWait),
318 BITFIELD (IsString),
319 BITFIELD (RegKludge),
e2ec9d29 320 BITFIELD (FirstXmm0),
c0f3af97 321 BITFIELD (Implicit1stXmm0),
ca61edf2
L
322 BITFIELD (ByteOkIntel),
323 BITFIELD (ToDword),
324 BITFIELD (ToQword),
325 BITFIELD (AddrPrefixOp0),
40fb9820
L
326 BITFIELD (IsPrefix),
327 BITFIELD (ImmExt),
328 BITFIELD (NoRex64),
329 BITFIELD (Rex64),
330 BITFIELD (Ugh),
85f10a01
MM
331 BITFIELD (Drex),
332 BITFIELD (Drexv),
333 BITFIELD (Drexc),
c0f3af97
L
334 BITFIELD (Vex),
335 BITFIELD (Vex256),
c0f3af97 336 BITFIELD (VexNDS),
03547503 337 BITFIELD (VexNDD),
c0f3af97
L
338 BITFIELD (VexW0),
339 BITFIELD (VexW1),
340 BITFIELD (Vex0F),
341 BITFIELD (Vex0F38),
342 BITFIELD (Vex0F3A),
343 BITFIELD (Vex3Sources),
344 BITFIELD (VexImmExt),
345 BITFIELD (SSE2AVX),
81f8a913 346 BITFIELD (NoAVX),
1efbbeb4
L
347 BITFIELD (OldGcc),
348 BITFIELD (ATTMnemonic),
e1d4d893 349 BITFIELD (ATTSyntax),
5c07affc 350 BITFIELD (IntelSyntax),
40fb9820
L
351};
352
353static bitfield operand_types[] =
354{
355 BITFIELD (Reg8),
356 BITFIELD (Reg16),
357 BITFIELD (Reg32),
358 BITFIELD (Reg64),
359 BITFIELD (FloatReg),
360 BITFIELD (RegMMX),
361 BITFIELD (RegXMM),
c0f3af97 362 BITFIELD (RegYMM),
40fb9820
L
363 BITFIELD (Imm8),
364 BITFIELD (Imm8S),
365 BITFIELD (Imm16),
366 BITFIELD (Imm32),
367 BITFIELD (Imm32S),
368 BITFIELD (Imm64),
369 BITFIELD (Imm1),
370 BITFIELD (BaseIndex),
371 BITFIELD (Disp8),
372 BITFIELD (Disp16),
373 BITFIELD (Disp32),
374 BITFIELD (Disp32S),
375 BITFIELD (Disp64),
376 BITFIELD (InOutPortReg),
377 BITFIELD (ShiftCount),
378 BITFIELD (Control),
379 BITFIELD (Debug),
380 BITFIELD (Test),
381 BITFIELD (SReg2),
382 BITFIELD (SReg3),
383 BITFIELD (Acc),
384 BITFIELD (FloatAcc),
385 BITFIELD (JumpAbsolute),
386 BITFIELD (EsSeg),
387 BITFIELD (RegMem),
5c07affc 388 BITFIELD (Mem),
7d5e4556
L
389 BITFIELD (Byte),
390 BITFIELD (Word),
391 BITFIELD (Dword),
392 BITFIELD (Fword),
393 BITFIELD (Qword),
394 BITFIELD (Tbyte),
395 BITFIELD (Xmmword),
c0f3af97 396 BITFIELD (Ymmword),
7d5e4556
L
397 BITFIELD (Unspecified),
398 BITFIELD (Anysize),
c0f3af97 399 BITFIELD (Vex_Imm4),
40fb9820
L
400#ifdef OTUnused
401 BITFIELD (OTUnused),
402#endif
403};
404
3d4d5afa
L
405static const char *filename;
406
40fb9820
L
407static int
408compare (const void *x, const void *y)
409{
410 const bitfield *xp = (const bitfield *) x;
411 const bitfield *yp = (const bitfield *) y;
412 return xp->position - yp->position;
413}
414
40b8e679
L
415static void
416fail (const char *message, ...)
417{
418 va_list args;
419
420 va_start (args, message);
421 fprintf (stderr, _("%s: Error: "), program_name);
422 vfprintf (stderr, message, args);
423 va_end (args);
424 xexit (1);
425}
426
72ffa0fb
L
427static void
428process_copyright (FILE *fp)
429{
430 fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
22da050b
L
431/* Copyright 2007, 2008, 2009\n\
432 Free Software Foundation, Inc.\n\
72ffa0fb
L
433\n\
434 This file is part of the GNU opcodes library.\n\
435\n\
436 This library is free software; you can redistribute it and/or modify\n\
437 it under the terms of the GNU General Public License as published by\n\
438 the Free Software Foundation; either version 3, or (at your option)\n\
439 any later version.\n\
440\n\
441 It is distributed in the hope that it will be useful, but WITHOUT\n\
442 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
443 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
444 License for more details.\n\
445\n\
446 You should have received a copy of the GNU General Public License\n\
447 along with this program; if not, write to the Free Software\n\
448 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
449 MA 02110-1301, USA. */\n");
450}
451
40b8e679
L
452/* Remove leading white spaces. */
453
454static char *
455remove_leading_whitespaces (char *str)
456{
457 while (ISSPACE (*str))
458 str++;
459 return str;
460}
461
462/* Remove trailing white spaces. */
463
464static void
465remove_trailing_whitespaces (char *str)
466{
467 size_t last = strlen (str);
468
469 if (last == 0)
470 return;
471
472 do
473 {
474 last--;
475 if (ISSPACE (str [last]))
476 str[last] = '\0';
477 else
478 break;
479 }
480 while (last != 0);
481}
482
93b1ec2c 483/* Find next field separated by SEP and terminate it. Return a
40b8e679
L
484 pointer to the one after it. */
485
486static char *
c587b3f9 487next_field (char *str, char sep, char **next, char *last)
40b8e679
L
488{
489 char *p;
490
491 p = remove_leading_whitespaces (str);
93b1ec2c 492 for (str = p; *str != sep && *str != '\0'; str++);
40b8e679
L
493
494 *str = '\0';
495 remove_trailing_whitespaces (p);
496
497 *next = str + 1;
498
c587b3f9
L
499 if (p >= last)
500 abort ();
501
40b8e679
L
502 return p;
503}
504
40fb9820 505static void
bd5295b2 506set_bitfield (const char *f, bitfield *array, unsigned int size, int lineno)
40fb9820
L
507{
508 unsigned int i;
509
1b7f3fb0 510 if (strcmp (f, "Mmword") == 0)
7d5e4556
L
511 f= "Qword";
512 else if (strcmp (f, "Oword") == 0)
513 f= "Xmmword";
40fb9820
L
514
515 for (i = 0; i < size; i++)
516 if (strcasecmp (array[i].name, f) == 0)
517 {
518 array[i].value = 1;
519 return;
520 }
521
bd5295b2
L
522 if (lineno != -1)
523 fail (_("%s: %d: Unknown bitfield: %s\n"), filename, lineno, f);
524 else
525 fail (_("Unknown bitfield: %s\n"), f);
40fb9820
L
526}
527
528static void
529output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
530 int macro, const char *comma, const char *indent)
531{
532 unsigned int i;
533
534 fprintf (table, "%s{ { ", indent);
535
536 for (i = 0; i < size - 1; i++)
537 {
538 fprintf (table, "%d, ", flags[i].value);
539 if (((i + 1) % 20) == 0)
540 {
541 /* We need \\ for macro. */
542 if (macro)
543 fprintf (table, " \\\n %s", indent);
544 else
545 fprintf (table, "\n %s", indent);
546 }
547 }
548
549 fprintf (table, "%d } }%s\n", flags[i].value, comma);
550}
551
552static void
553process_i386_cpu_flag (FILE *table, char *flag, int macro,
bd5295b2
L
554 const char *comma, const char *indent,
555 int lineno)
40fb9820
L
556{
557 char *str, *next, *last;
558 bitfield flags [ARRAY_SIZE (cpu_flags)];
559
560 /* Copy the default cpu flags. */
561 memcpy (flags, cpu_flags, sizeof (cpu_flags));
562
563 if (strcasecmp (flag, "unknown") == 0)
564 {
565 unsigned int i;
566
567 /* We turn on everything except for cpu64 in case of
568 CPU_UNKNOWN_FLAGS. */
569 for (i = 0; i < ARRAY_SIZE (flags); i++)
570 if (flags[i].position != Cpu64)
571 flags[i].value = 1;
572 }
573 else if (strcmp (flag, "0"))
574 {
575 last = flag + strlen (flag);
576 for (next = flag; next && next < last; )
577 {
c587b3f9 578 str = next_field (next, '|', &next, last);
40fb9820 579 if (str)
bd5295b2 580 set_bitfield (str, flags, ARRAY_SIZE (flags), lineno);
40fb9820
L
581 }
582 }
583
584 output_cpu_flags (table, flags, ARRAY_SIZE (flags), macro,
585 comma, indent);
586}
587
588static void
589output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
590{
591 unsigned int i;
592
593 fprintf (table, " { ");
594
595 for (i = 0; i < size - 1; i++)
596 {
597 fprintf (table, "%d, ", modifier[i].value);
598 if (((i + 1) % 20) == 0)
599 fprintf (table, "\n ");
600 }
601
602 fprintf (table, "%d },\n", modifier[i].value);
603}
604
605static void
bd5295b2 606process_i386_opcode_modifier (FILE *table, char *mod, int lineno)
40fb9820
L
607{
608 char *str, *next, *last;
609 bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
610
611 /* Copy the default opcode modifier. */
612 memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
613
614 if (strcmp (mod, "0"))
615 {
616 last = mod + strlen (mod);
617 for (next = mod; next && next < last; )
618 {
c587b3f9 619 str = next_field (next, '|', &next, last);
40fb9820 620 if (str)
bd5295b2 621 set_bitfield (str, modifiers, ARRAY_SIZE (modifiers), lineno);
40fb9820
L
622 }
623 }
624 output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
625}
626
627static void
628output_operand_type (FILE *table, bitfield *types, unsigned int size,
629 int macro, const char *indent)
630{
631 unsigned int i;
632
633 fprintf (table, "{ { ");
634
635 for (i = 0; i < size - 1; i++)
636 {
637 fprintf (table, "%d, ", types[i].value);
638 if (((i + 1) % 20) == 0)
639 {
640 /* We need \\ for macro. */
641 if (macro)
642 fprintf (table, "\\\n%s", indent);
643 else
644 fprintf (table, "\n%s", indent);
645 }
646 }
647
648 fprintf (table, "%d } }", types[i].value);
649}
650
651static void
652process_i386_operand_type (FILE *table, char *op, int macro,
bd5295b2 653 const char *indent, int lineno)
40fb9820
L
654{
655 char *str, *next, *last;
656 bitfield types [ARRAY_SIZE (operand_types)];
657
658 /* Copy the default operand type. */
659 memcpy (types, operand_types, sizeof (types));
660
661 if (strcmp (op, "0"))
662 {
663 last = op + strlen (op);
664 for (next = op; next && next < last; )
665 {
c587b3f9 666 str = next_field (next, '|', &next, last);
40fb9820 667 if (str)
bd5295b2 668 set_bitfield (str, types, ARRAY_SIZE (types), lineno);
40fb9820
L
669 }
670 }
671 output_operand_type (table, types, ARRAY_SIZE (types), macro,
672 indent);
673}
674
c587b3f9
L
675static void
676output_i386_opcode (FILE *table, const char *name, char *str,
bd5295b2 677 char *last, int lineno)
c587b3f9
L
678{
679 unsigned int i;
680 char *operands, *base_opcode, *extension_opcode, *opcode_length;
681 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
682
683 /* Find number of operands. */
684 operands = next_field (str, ',', &str, last);
685
686 /* Find base_opcode. */
687 base_opcode = next_field (str, ',', &str, last);
688
689 /* Find extension_opcode. */
690 extension_opcode = next_field (str, ',', &str, last);
691
692 /* Find opcode_length. */
693 opcode_length = next_field (str, ',', &str, last);
694
695 /* Find cpu_flags. */
696 cpu_flags = next_field (str, ',', &str, last);
697
698 /* Find opcode_modifier. */
699 opcode_modifier = next_field (str, ',', &str, last);
700
701 /* Remove the first {. */
702 str = remove_leading_whitespaces (str);
703 if (*str != '{')
704 abort ();
705 str = remove_leading_whitespaces (str + 1);
706
707 i = strlen (str);
708
709 /* There are at least "X}". */
710 if (i < 2)
711 abort ();
712
713 /* Remove trailing white spaces and }. */
714 do
715 {
716 i--;
717 if (ISSPACE (str[i]) || str[i] == '}')
718 str[i] = '\0';
719 else
720 break;
721 }
722 while (i != 0);
723
724 last = str + i;
725
726 /* Find operand_types. */
727 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
728 {
729 if (str >= last)
730 {
731 operand_types [i] = NULL;
732 break;
733 }
734
735 operand_types [i] = next_field (str, ',', &str, last);
736 if (*operand_types[i] == '0')
737 {
738 if (i != 0)
739 operand_types[i] = NULL;
740 break;
741 }
742 }
743
744 fprintf (table, " { \"%s\", %s, %s, %s, %s,\n",
745 name, operands, base_opcode, extension_opcode,
746 opcode_length);
747
bd5295b2 748 process_i386_cpu_flag (table, cpu_flags, 0, ",", " ", lineno);
c587b3f9 749
bd5295b2 750 process_i386_opcode_modifier (table, opcode_modifier, lineno);
c587b3f9
L
751
752 fprintf (table, " { ");
753
754 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
755 {
756 if (operand_types[i] == NULL || *operand_types[i] == '0')
757 {
758 if (i == 0)
bd5295b2 759 process_i386_operand_type (table, "0", 0, "\t ", lineno);
c587b3f9
L
760 break;
761 }
762
763 if (i != 0)
764 fprintf (table, ",\n ");
765
766 process_i386_operand_type (table, operand_types[i], 0,
bd5295b2 767 "\t ", lineno);
c587b3f9
L
768 }
769 fprintf (table, " } },\n");
770}
771
772struct opcode_hash_entry
773{
774 struct opcode_hash_entry *next;
775 char *name;
776 char *opcode;
bd5295b2 777 int lineno;
c587b3f9
L
778};
779
780/* Calculate the hash value of an opcode hash entry P. */
781
782static hashval_t
783opcode_hash_hash (const void *p)
784{
785 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
786 return htab_hash_string (entry->name);
787}
788
789/* Compare a string Q against an opcode hash entry P. */
790
791static int
792opcode_hash_eq (const void *p, const void *q)
793{
794 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
795 const char *name = (const char *) q;
796 return strcmp (name, entry->name) == 0;
797}
798
40b8e679 799static void
72ffa0fb 800process_i386_opcodes (FILE *table)
40b8e679 801{
3d4d5afa 802 FILE *fp;
40b8e679 803 char buf[2048];
c587b3f9
L
804 unsigned int i, j;
805 char *str, *p, *last, *name;
806 struct opcode_hash_entry **hash_slot, **entry, *next;
807 htab_t opcode_hash_table;
808 struct opcode_hash_entry **opcode_array;
809 unsigned int opcode_array_size = 1024;
bd5295b2 810 int lineno = 0;
40b8e679 811
3d4d5afa
L
812 filename = "i386-opc.tbl";
813 fp = fopen (filename, "r");
814
40b8e679 815 if (fp == NULL)
34edb9ad 816 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
40fb9820 817 xstrerror (errno));
40b8e679 818
c587b3f9
L
819 i = 0;
820 opcode_array = (struct opcode_hash_entry **)
821 xmalloc (sizeof (*opcode_array) * opcode_array_size);
822
823 opcode_hash_table = htab_create_alloc (16, opcode_hash_hash,
824 opcode_hash_eq, NULL,
825 xcalloc, free);
826
34edb9ad
L
827 fprintf (table, "\n/* i386 opcode table. */\n\n");
828 fprintf (table, "const template i386_optab[] =\n{\n");
40b8e679 829
c587b3f9 830 /* Put everything on opcode array. */
40b8e679
L
831 while (!feof (fp))
832 {
833 if (fgets (buf, sizeof (buf), fp) == NULL)
834 break;
835
3d4d5afa
L
836 lineno++;
837
40b8e679
L
838 p = remove_leading_whitespaces (buf);
839
840 /* Skip comments. */
841 str = strstr (p, "//");
842 if (str != NULL)
843 str[0] = '\0';
844
845 /* Remove trailing white spaces. */
846 remove_trailing_whitespaces (p);
847
848 switch (p[0])
849 {
850 case '#':
c587b3f9 851 /* Ignore comments. */
40b8e679
L
852 case '\0':
853 continue;
854 break;
855 default:
856 break;
857 }
858
859 last = p + strlen (p);
860
861 /* Find name. */
c587b3f9 862 name = next_field (p, ',', &str, last);
40b8e679 863
c587b3f9
L
864 /* Get the slot in hash table. */
865 hash_slot = (struct opcode_hash_entry **)
866 htab_find_slot_with_hash (opcode_hash_table, name,
867 htab_hash_string (name),
868 INSERT);
40b8e679 869
c587b3f9 870 if (*hash_slot == NULL)
40b8e679 871 {
c587b3f9
L
872 /* It is the new one. Put it on opcode array. */
873 if (i >= opcode_array_size)
40b8e679 874 {
c587b3f9
L
875 /* Grow the opcode array when needed. */
876 opcode_array_size += 1024;
877 opcode_array = (struct opcode_hash_entry **)
878 xrealloc (opcode_array,
879 sizeof (*opcode_array) * opcode_array_size);
40b8e679
L
880 }
881
c587b3f9
L
882 opcode_array[i] = (struct opcode_hash_entry *)
883 xmalloc (sizeof (struct opcode_hash_entry));
884 opcode_array[i]->next = NULL;
885 opcode_array[i]->name = xstrdup (name);
886 opcode_array[i]->opcode = xstrdup (str);
bd5295b2 887 opcode_array[i]->lineno = lineno;
c587b3f9
L
888 *hash_slot = opcode_array[i];
889 i++;
40b8e679 890 }
c587b3f9 891 else
40b8e679 892 {
c587b3f9
L
893 /* Append it to the existing one. */
894 entry = hash_slot;
895 while ((*entry) != NULL)
896 entry = &(*entry)->next;
897 *entry = (struct opcode_hash_entry *)
898 xmalloc (sizeof (struct opcode_hash_entry));
899 (*entry)->next = NULL;
900 (*entry)->name = (*hash_slot)->name;
901 (*entry)->opcode = xstrdup (str);
bd5295b2 902 (*entry)->lineno = lineno;
c587b3f9
L
903 }
904 }
40b8e679 905
c587b3f9
L
906 /* Process opcode array. */
907 for (j = 0; j < i; j++)
908 {
909 for (next = opcode_array[j]; next; next = next->next)
910 {
911 name = next->name;
912 str = next->opcode;
bd5295b2 913 lineno = next->lineno;
c587b3f9 914 last = str + strlen (str);
bd5295b2 915 output_i386_opcode (table, name, str, last, lineno);
40b8e679 916 }
40b8e679
L
917 }
918
34edb9ad
L
919 fclose (fp);
920
4dffcebc 921 fprintf (table, " { NULL, 0, 0, 0, 0,\n");
40fb9820 922
bd5295b2 923 process_i386_cpu_flag (table, "0", 0, ",", " ", -1);
40fb9820 924
bd5295b2 925 process_i386_opcode_modifier (table, "0", -1);
40fb9820
L
926
927 fprintf (table, " { ");
bd5295b2 928 process_i386_operand_type (table, "0", 0, "\t ", -1);
40fb9820
L
929 fprintf (table, " } }\n");
930
34edb9ad 931 fprintf (table, "};\n");
40b8e679
L
932}
933
934static void
72ffa0fb 935process_i386_registers (FILE *table)
40b8e679 936{
3d4d5afa 937 FILE *fp;
40b8e679
L
938 char buf[2048];
939 char *str, *p, *last;
940 char *reg_name, *reg_type, *reg_flags, *reg_num;
a60de03c 941 char *dw2_32_num, *dw2_64_num;
bd5295b2 942 int lineno = 0;
40b8e679 943
3d4d5afa
L
944 filename = "i386-reg.tbl";
945 fp = fopen (filename, "r");
40b8e679 946 if (fp == NULL)
34edb9ad 947 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
40fb9820 948 xstrerror (errno));
40b8e679 949
34edb9ad
L
950 fprintf (table, "\n/* i386 register table. */\n\n");
951 fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
40b8e679
L
952
953 while (!feof (fp))
954 {
955 if (fgets (buf, sizeof (buf), fp) == NULL)
956 break;
957
3d4d5afa
L
958 lineno++;
959
40b8e679
L
960 p = remove_leading_whitespaces (buf);
961
962 /* Skip comments. */
963 str = strstr (p, "//");
964 if (str != NULL)
965 str[0] = '\0';
966
967 /* Remove trailing white spaces. */
968 remove_trailing_whitespaces (p);
969
970 switch (p[0])
971 {
972 case '#':
34edb9ad 973 fprintf (table, "%s\n", p);
40b8e679
L
974 case '\0':
975 continue;
976 break;
977 default:
978 break;
979 }
980
981 last = p + strlen (p);
982
983 /* Find reg_name. */
c587b3f9 984 reg_name = next_field (p, ',', &str, last);
40b8e679
L
985
986 /* Find reg_type. */
c587b3f9 987 reg_type = next_field (str, ',', &str, last);
40b8e679
L
988
989 /* Find reg_flags. */
c587b3f9 990 reg_flags = next_field (str, ',', &str, last);
40b8e679
L
991
992 /* Find reg_num. */
c587b3f9 993 reg_num = next_field (str, ',', &str, last);
a60de03c 994
40fb9820
L
995 fprintf (table, " { \"%s\",\n ", reg_name);
996
bd5295b2 997 process_i386_operand_type (table, reg_type, 0, "\t", lineno);
40fb9820 998
a60de03c 999 /* Find 32-bit Dwarf2 register number. */
c587b3f9 1000 dw2_32_num = next_field (str, ',', &str, last);
a60de03c
JB
1001
1002 /* Find 64-bit Dwarf2 register number. */
c587b3f9 1003 dw2_64_num = next_field (str, ',', &str, last);
a60de03c
JB
1004
1005 fprintf (table, ",\n %s, %s, { %s, %s } },\n",
1006 reg_flags, reg_num, dw2_32_num, dw2_64_num);
40b8e679
L
1007 }
1008
34edb9ad
L
1009 fclose (fp);
1010
1011 fprintf (table, "};\n");
40b8e679 1012
34edb9ad 1013 fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
40b8e679
L
1014}
1015
40fb9820
L
1016static void
1017process_i386_initializers (void)
1018{
1019 unsigned int i;
1020 FILE *fp = fopen ("i386-init.h", "w");
1021 char *init;
1022
1023 if (fp == NULL)
1024 fail (_("can't create i386-init.h, errno = %s\n"),
1025 xstrerror (errno));
1026
1027 process_copyright (fp);
1028
1029 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
1030 {
1031 fprintf (fp, "\n#define %s \\\n", cpu_flag_init[i].name);
1032 init = xstrdup (cpu_flag_init[i].init);
bd5295b2 1033 process_i386_cpu_flag (fp, init, 1, "", " ", -1);
40fb9820
L
1034 free (init);
1035 }
1036
1037 for (i = 0; i < ARRAY_SIZE (operand_type_init); i++)
1038 {
1039 fprintf (fp, "\n\n#define %s \\\n ", operand_type_init[i].name);
1040 init = xstrdup (operand_type_init[i].init);
bd5295b2 1041 process_i386_operand_type (fp, init, 1, " ", -1);
40fb9820
L
1042 free (init);
1043 }
1044 fprintf (fp, "\n");
1045
1046 fclose (fp);
1047}
1048
40b8e679
L
1049/* Program options. */
1050#define OPTION_SRCDIR 200
1051
1052struct option long_options[] =
1053{
1054 {"srcdir", required_argument, NULL, OPTION_SRCDIR},
1055 {"debug", no_argument, NULL, 'd'},
1056 {"version", no_argument, NULL, 'V'},
1057 {"help", no_argument, NULL, 'h'},
1058 {0, no_argument, NULL, 0}
1059};
1060
1061static void
1062print_version (void)
1063{
1064 printf ("%s: version 1.0\n", program_name);
1065 xexit (0);
1066}
1067
1068static void
1069usage (FILE * stream, int status)
1070{
1071 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1072 program_name);
1073 xexit (status);
1074}
1075
1076int
1077main (int argc, char **argv)
1078{
1079 extern int chdir (char *);
1080 char *srcdir = NULL;
8b40d594 1081 int c;
72ffa0fb 1082 FILE *table;
40b8e679
L
1083
1084 program_name = *argv;
1085 xmalloc_set_program_name (program_name);
1086
1087 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
1088 switch (c)
1089 {
1090 case OPTION_SRCDIR:
1091 srcdir = optarg;
1092 break;
1093 case 'V':
1094 case 'v':
1095 print_version ();
1096 break;
1097 case 'd':
1098 debug = 1;
1099 break;
1100 case 'h':
1101 case '?':
1102 usage (stderr, 0);
1103 default:
1104 case 0:
1105 break;
1106 }
1107
1108 if (optind != argc)
1109 usage (stdout, 1);
1110
1111 if (srcdir != NULL)
1112 if (chdir (srcdir) != 0)
1113 fail (_("unable to change directory to \"%s\", errno = %s\n"),
40fb9820
L
1114 srcdir, xstrerror (errno));
1115
1116 /* Check the unused bitfield in i386_cpu_flags. */
1117#ifndef CpuUnused
8b40d594
L
1118 c = CpuNumOfBits - CpuMax - 1;
1119 if (c)
1120 fail (_("%d unused bits in i386_cpu_flags.\n"), c);
40fb9820
L
1121#endif
1122
1123 /* Check the unused bitfield in i386_operand_type. */
1124#ifndef OTUnused
8b40d594
L
1125 c = OTNumOfBits - OTMax - 1;
1126 if (c)
1127 fail (_("%d unused bits in i386_operand_type.\n"), c);
40fb9820
L
1128#endif
1129
1130 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
1131 compare);
1132
1133 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
1134 sizeof (opcode_modifiers [0]), compare);
1135
1136 qsort (operand_types, ARRAY_SIZE (operand_types),
1137 sizeof (operand_types [0]), compare);
40b8e679 1138
34edb9ad
L
1139 table = fopen ("i386-tbl.h", "w");
1140 if (table == NULL)
40fb9820
L
1141 fail (_("can't create i386-tbl.h, errno = %s\n"),
1142 xstrerror (errno));
34edb9ad 1143
72ffa0fb 1144 process_copyright (table);
40b8e679 1145
72ffa0fb
L
1146 process_i386_opcodes (table);
1147 process_i386_registers (table);
40fb9820 1148 process_i386_initializers ();
40b8e679 1149
34edb9ad
L
1150 fclose (table);
1151
40b8e679
L
1152 exit (0);
1153}