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