* ld-cris/tls-err-77.d, ld-cris/tls-gc-79.d, ld-cris/tls-ie-8e.s,
[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),
287 BITFIELD (Modrm),
288 BITFIELD (ShortForm),
289 BITFIELD (Jump),
290 BITFIELD (JumpDword),
291 BITFIELD (JumpByte),
292 BITFIELD (JumpInterSegment),
293 BITFIELD (FloatMF),
294 BITFIELD (FloatR),
295 BITFIELD (FloatD),
296 BITFIELD (Size16),
297 BITFIELD (Size32),
298 BITFIELD (Size64),
299 BITFIELD (IgnoreSize),
300 BITFIELD (DefaultSize),
301 BITFIELD (No_bSuf),
302 BITFIELD (No_wSuf),
303 BITFIELD (No_lSuf),
304 BITFIELD (No_sSuf),
305 BITFIELD (No_qSuf),
7ce189b3 306 BITFIELD (No_ldSuf),
40fb9820
L
307 BITFIELD (FWait),
308 BITFIELD (IsString),
309 BITFIELD (RegKludge),
e2ec9d29 310 BITFIELD (FirstXmm0),
c0f3af97 311 BITFIELD (Implicit1stXmm0),
ca61edf2
L
312 BITFIELD (ByteOkIntel),
313 BITFIELD (ToDword),
314 BITFIELD (ToQword),
315 BITFIELD (AddrPrefixOp0),
40fb9820
L
316 BITFIELD (IsPrefix),
317 BITFIELD (ImmExt),
318 BITFIELD (NoRex64),
319 BITFIELD (Rex64),
320 BITFIELD (Ugh),
85f10a01
MM
321 BITFIELD (Drex),
322 BITFIELD (Drexv),
323 BITFIELD (Drexc),
c0f3af97
L
324 BITFIELD (Vex),
325 BITFIELD (Vex256),
c0f3af97 326 BITFIELD (VexNDS),
03547503 327 BITFIELD (VexNDD),
c0f3af97
L
328 BITFIELD (VexW0),
329 BITFIELD (VexW1),
330 BITFIELD (Vex0F),
331 BITFIELD (Vex0F38),
332 BITFIELD (Vex0F3A),
333 BITFIELD (Vex3Sources),
334 BITFIELD (VexImmExt),
335 BITFIELD (SSE2AVX),
81f8a913 336 BITFIELD (NoAVX),
1efbbeb4
L
337 BITFIELD (OldGcc),
338 BITFIELD (ATTMnemonic),
e1d4d893 339 BITFIELD (ATTSyntax),
5c07affc 340 BITFIELD (IntelSyntax),
40fb9820
L
341};
342
343static bitfield operand_types[] =
344{
345 BITFIELD (Reg8),
346 BITFIELD (Reg16),
347 BITFIELD (Reg32),
348 BITFIELD (Reg64),
349 BITFIELD (FloatReg),
350 BITFIELD (RegMMX),
351 BITFIELD (RegXMM),
c0f3af97 352 BITFIELD (RegYMM),
40fb9820
L
353 BITFIELD (Imm8),
354 BITFIELD (Imm8S),
355 BITFIELD (Imm16),
356 BITFIELD (Imm32),
357 BITFIELD (Imm32S),
358 BITFIELD (Imm64),
359 BITFIELD (Imm1),
360 BITFIELD (BaseIndex),
361 BITFIELD (Disp8),
362 BITFIELD (Disp16),
363 BITFIELD (Disp32),
364 BITFIELD (Disp32S),
365 BITFIELD (Disp64),
366 BITFIELD (InOutPortReg),
367 BITFIELD (ShiftCount),
368 BITFIELD (Control),
369 BITFIELD (Debug),
370 BITFIELD (Test),
371 BITFIELD (SReg2),
372 BITFIELD (SReg3),
373 BITFIELD (Acc),
374 BITFIELD (FloatAcc),
375 BITFIELD (JumpAbsolute),
376 BITFIELD (EsSeg),
377 BITFIELD (RegMem),
5c07affc 378 BITFIELD (Mem),
7d5e4556
L
379 BITFIELD (Byte),
380 BITFIELD (Word),
381 BITFIELD (Dword),
382 BITFIELD (Fword),
383 BITFIELD (Qword),
384 BITFIELD (Tbyte),
385 BITFIELD (Xmmword),
c0f3af97 386 BITFIELD (Ymmword),
7d5e4556
L
387 BITFIELD (Unspecified),
388 BITFIELD (Anysize),
c0f3af97 389 BITFIELD (Vex_Imm4),
40fb9820
L
390#ifdef OTUnused
391 BITFIELD (OTUnused),
392#endif
393};
394
3d4d5afa
L
395static int lineno;
396static const char *filename;
397
40fb9820
L
398static int
399compare (const void *x, const void *y)
400{
401 const bitfield *xp = (const bitfield *) x;
402 const bitfield *yp = (const bitfield *) y;
403 return xp->position - yp->position;
404}
405
40b8e679
L
406static void
407fail (const char *message, ...)
408{
409 va_list args;
410
411 va_start (args, message);
412 fprintf (stderr, _("%s: Error: "), program_name);
413 vfprintf (stderr, message, args);
414 va_end (args);
415 xexit (1);
416}
417
72ffa0fb
L
418static void
419process_copyright (FILE *fp)
420{
421 fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
6f143e4d 422/* Copyright 2007, 2008 Free Software Foundation, Inc.\n\
72ffa0fb
L
423\n\
424 This file is part of the GNU opcodes library.\n\
425\n\
426 This library is free software; you can redistribute it and/or modify\n\
427 it under the terms of the GNU General Public License as published by\n\
428 the Free Software Foundation; either version 3, or (at your option)\n\
429 any later version.\n\
430\n\
431 It is distributed in the hope that it will be useful, but WITHOUT\n\
432 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
433 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
434 License for more details.\n\
435\n\
436 You should have received a copy of the GNU General Public License\n\
437 along with this program; if not, write to the Free Software\n\
438 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
439 MA 02110-1301, USA. */\n");
440}
441
40b8e679
L
442/* Remove leading white spaces. */
443
444static char *
445remove_leading_whitespaces (char *str)
446{
447 while (ISSPACE (*str))
448 str++;
449 return str;
450}
451
452/* Remove trailing white spaces. */
453
454static void
455remove_trailing_whitespaces (char *str)
456{
457 size_t last = strlen (str);
458
459 if (last == 0)
460 return;
461
462 do
463 {
464 last--;
465 if (ISSPACE (str [last]))
466 str[last] = '\0';
467 else
468 break;
469 }
470 while (last != 0);
471}
472
93b1ec2c 473/* Find next field separated by SEP and terminate it. Return a
40b8e679
L
474 pointer to the one after it. */
475
476static char *
c587b3f9 477next_field (char *str, char sep, char **next, char *last)
40b8e679
L
478{
479 char *p;
480
481 p = remove_leading_whitespaces (str);
93b1ec2c 482 for (str = p; *str != sep && *str != '\0'; str++);
40b8e679
L
483
484 *str = '\0';
485 remove_trailing_whitespaces (p);
486
487 *next = str + 1;
488
c587b3f9
L
489 if (p >= last)
490 abort ();
491
40b8e679
L
492 return p;
493}
494
40fb9820
L
495static void
496set_bitfield (const char *f, bitfield *array, unsigned int size)
497{
498 unsigned int i;
499
500 if (strcmp (f, "CpuSledgehammer") == 0)
501 f= "CpuK8";
7d5e4556
L
502 else if (strcmp (f, "Mmword") == 0)
503 f= "Qword";
504 else if (strcmp (f, "Oword") == 0)
505 f= "Xmmword";
40fb9820
L
506
507 for (i = 0; i < size; i++)
508 if (strcasecmp (array[i].name, f) == 0)
509 {
510 array[i].value = 1;
511 return;
512 }
513
50e8458f 514 fail (_("%s: %d: Unknown bitfield: %s\n"), filename, lineno, f);
40fb9820
L
515}
516
517static void
518output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
519 int macro, const char *comma, const char *indent)
520{
521 unsigned int i;
522
523 fprintf (table, "%s{ { ", indent);
524
525 for (i = 0; i < size - 1; i++)
526 {
527 fprintf (table, "%d, ", flags[i].value);
528 if (((i + 1) % 20) == 0)
529 {
530 /* We need \\ for macro. */
531 if (macro)
532 fprintf (table, " \\\n %s", indent);
533 else
534 fprintf (table, "\n %s", indent);
535 }
536 }
537
538 fprintf (table, "%d } }%s\n", flags[i].value, comma);
539}
540
541static void
542process_i386_cpu_flag (FILE *table, char *flag, int macro,
543 const char *comma, const char *indent)
544{
545 char *str, *next, *last;
546 bitfield flags [ARRAY_SIZE (cpu_flags)];
547
548 /* Copy the default cpu flags. */
549 memcpy (flags, cpu_flags, sizeof (cpu_flags));
550
551 if (strcasecmp (flag, "unknown") == 0)
552 {
553 unsigned int i;
554
555 /* We turn on everything except for cpu64 in case of
556 CPU_UNKNOWN_FLAGS. */
557 for (i = 0; i < ARRAY_SIZE (flags); i++)
558 if (flags[i].position != Cpu64)
559 flags[i].value = 1;
560 }
561 else if (strcmp (flag, "0"))
562 {
563 last = flag + strlen (flag);
564 for (next = flag; next && next < last; )
565 {
c587b3f9 566 str = next_field (next, '|', &next, last);
40fb9820
L
567 if (str)
568 set_bitfield (str, flags, ARRAY_SIZE (flags));
569 }
570 }
571
572 output_cpu_flags (table, flags, ARRAY_SIZE (flags), macro,
573 comma, indent);
574}
575
576static void
577output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
578{
579 unsigned int i;
580
581 fprintf (table, " { ");
582
583 for (i = 0; i < size - 1; i++)
584 {
585 fprintf (table, "%d, ", modifier[i].value);
586 if (((i + 1) % 20) == 0)
587 fprintf (table, "\n ");
588 }
589
590 fprintf (table, "%d },\n", modifier[i].value);
591}
592
593static void
594process_i386_opcode_modifier (FILE *table, char *mod)
595{
596 char *str, *next, *last;
597 bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
598
599 /* Copy the default opcode modifier. */
600 memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
601
602 if (strcmp (mod, "0"))
603 {
604 last = mod + strlen (mod);
605 for (next = mod; next && next < last; )
606 {
c587b3f9 607 str = next_field (next, '|', &next, last);
40fb9820
L
608 if (str)
609 set_bitfield (str, modifiers, ARRAY_SIZE (modifiers));
610 }
611 }
612 output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
613}
614
615static void
616output_operand_type (FILE *table, bitfield *types, unsigned int size,
617 int macro, const char *indent)
618{
619 unsigned int i;
620
621 fprintf (table, "{ { ");
622
623 for (i = 0; i < size - 1; i++)
624 {
625 fprintf (table, "%d, ", types[i].value);
626 if (((i + 1) % 20) == 0)
627 {
628 /* We need \\ for macro. */
629 if (macro)
630 fprintf (table, "\\\n%s", indent);
631 else
632 fprintf (table, "\n%s", indent);
633 }
634 }
635
636 fprintf (table, "%d } }", types[i].value);
637}
638
639static void
640process_i386_operand_type (FILE *table, char *op, int macro,
641 const char *indent)
642{
643 char *str, *next, *last;
644 bitfield types [ARRAY_SIZE (operand_types)];
645
646 /* Copy the default operand type. */
647 memcpy (types, operand_types, sizeof (types));
648
649 if (strcmp (op, "0"))
650 {
651 last = op + strlen (op);
652 for (next = op; next && next < last; )
653 {
c587b3f9 654 str = next_field (next, '|', &next, last);
40fb9820
L
655 if (str)
656 set_bitfield (str, types, ARRAY_SIZE (types));
657 }
658 }
659 output_operand_type (table, types, ARRAY_SIZE (types), macro,
660 indent);
661}
662
c587b3f9
L
663static void
664output_i386_opcode (FILE *table, const char *name, char *str,
665 char *last)
666{
667 unsigned int i;
668 char *operands, *base_opcode, *extension_opcode, *opcode_length;
669 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
670
671 /* Find number of operands. */
672 operands = next_field (str, ',', &str, last);
673
674 /* Find base_opcode. */
675 base_opcode = next_field (str, ',', &str, last);
676
677 /* Find extension_opcode. */
678 extension_opcode = next_field (str, ',', &str, last);
679
680 /* Find opcode_length. */
681 opcode_length = next_field (str, ',', &str, last);
682
683 /* Find cpu_flags. */
684 cpu_flags = next_field (str, ',', &str, last);
685
686 /* Find opcode_modifier. */
687 opcode_modifier = next_field (str, ',', &str, last);
688
689 /* Remove the first {. */
690 str = remove_leading_whitespaces (str);
691 if (*str != '{')
692 abort ();
693 str = remove_leading_whitespaces (str + 1);
694
695 i = strlen (str);
696
697 /* There are at least "X}". */
698 if (i < 2)
699 abort ();
700
701 /* Remove trailing white spaces and }. */
702 do
703 {
704 i--;
705 if (ISSPACE (str[i]) || str[i] == '}')
706 str[i] = '\0';
707 else
708 break;
709 }
710 while (i != 0);
711
712 last = str + i;
713
714 /* Find operand_types. */
715 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
716 {
717 if (str >= last)
718 {
719 operand_types [i] = NULL;
720 break;
721 }
722
723 operand_types [i] = next_field (str, ',', &str, last);
724 if (*operand_types[i] == '0')
725 {
726 if (i != 0)
727 operand_types[i] = NULL;
728 break;
729 }
730 }
731
732 fprintf (table, " { \"%s\", %s, %s, %s, %s,\n",
733 name, operands, base_opcode, extension_opcode,
734 opcode_length);
735
736 process_i386_cpu_flag (table, cpu_flags, 0, ",", " ");
737
738 process_i386_opcode_modifier (table, opcode_modifier);
739
740 fprintf (table, " { ");
741
742 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
743 {
744 if (operand_types[i] == NULL || *operand_types[i] == '0')
745 {
746 if (i == 0)
747 process_i386_operand_type (table, "0", 0, "\t ");
748 break;
749 }
750
751 if (i != 0)
752 fprintf (table, ",\n ");
753
754 process_i386_operand_type (table, operand_types[i], 0,
755 "\t ");
756 }
757 fprintf (table, " } },\n");
758}
759
760struct opcode_hash_entry
761{
762 struct opcode_hash_entry *next;
763 char *name;
764 char *opcode;
765};
766
767/* Calculate the hash value of an opcode hash entry P. */
768
769static hashval_t
770opcode_hash_hash (const void *p)
771{
772 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
773 return htab_hash_string (entry->name);
774}
775
776/* Compare a string Q against an opcode hash entry P. */
777
778static int
779opcode_hash_eq (const void *p, const void *q)
780{
781 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
782 const char *name = (const char *) q;
783 return strcmp (name, entry->name) == 0;
784}
785
40b8e679 786static void
72ffa0fb 787process_i386_opcodes (FILE *table)
40b8e679 788{
3d4d5afa 789 FILE *fp;
40b8e679 790 char buf[2048];
c587b3f9
L
791 unsigned int i, j;
792 char *str, *p, *last, *name;
793 struct opcode_hash_entry **hash_slot, **entry, *next;
794 htab_t opcode_hash_table;
795 struct opcode_hash_entry **opcode_array;
796 unsigned int opcode_array_size = 1024;
40b8e679 797
3d4d5afa
L
798 filename = "i386-opc.tbl";
799 fp = fopen (filename, "r");
800
40b8e679 801 if (fp == NULL)
34edb9ad 802 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
40fb9820 803 xstrerror (errno));
40b8e679 804
c587b3f9
L
805 i = 0;
806 opcode_array = (struct opcode_hash_entry **)
807 xmalloc (sizeof (*opcode_array) * opcode_array_size);
808
809 opcode_hash_table = htab_create_alloc (16, opcode_hash_hash,
810 opcode_hash_eq, NULL,
811 xcalloc, free);
812
34edb9ad
L
813 fprintf (table, "\n/* i386 opcode table. */\n\n");
814 fprintf (table, "const template i386_optab[] =\n{\n");
40b8e679 815
c587b3f9 816 /* Put everything on opcode array. */
40b8e679
L
817 while (!feof (fp))
818 {
819 if (fgets (buf, sizeof (buf), fp) == NULL)
820 break;
821
3d4d5afa
L
822 lineno++;
823
40b8e679
L
824 p = remove_leading_whitespaces (buf);
825
826 /* Skip comments. */
827 str = strstr (p, "//");
828 if (str != NULL)
829 str[0] = '\0';
830
831 /* Remove trailing white spaces. */
832 remove_trailing_whitespaces (p);
833
834 switch (p[0])
835 {
836 case '#':
c587b3f9 837 /* Ignore comments. */
40b8e679
L
838 case '\0':
839 continue;
840 break;
841 default:
842 break;
843 }
844
845 last = p + strlen (p);
846
847 /* Find name. */
c587b3f9 848 name = next_field (p, ',', &str, last);
40b8e679 849
c587b3f9
L
850 /* Get the slot in hash table. */
851 hash_slot = (struct opcode_hash_entry **)
852 htab_find_slot_with_hash (opcode_hash_table, name,
853 htab_hash_string (name),
854 INSERT);
40b8e679 855
c587b3f9 856 if (*hash_slot == NULL)
40b8e679 857 {
c587b3f9
L
858 /* It is the new one. Put it on opcode array. */
859 if (i >= opcode_array_size)
40b8e679 860 {
c587b3f9
L
861 /* Grow the opcode array when needed. */
862 opcode_array_size += 1024;
863 opcode_array = (struct opcode_hash_entry **)
864 xrealloc (opcode_array,
865 sizeof (*opcode_array) * opcode_array_size);
40b8e679
L
866 }
867
c587b3f9
L
868 opcode_array[i] = (struct opcode_hash_entry *)
869 xmalloc (sizeof (struct opcode_hash_entry));
870 opcode_array[i]->next = NULL;
871 opcode_array[i]->name = xstrdup (name);
872 opcode_array[i]->opcode = xstrdup (str);
873 *hash_slot = opcode_array[i];
874 i++;
40b8e679 875 }
c587b3f9 876 else
40b8e679 877 {
c587b3f9
L
878 /* Append it to the existing one. */
879 entry = hash_slot;
880 while ((*entry) != NULL)
881 entry = &(*entry)->next;
882 *entry = (struct opcode_hash_entry *)
883 xmalloc (sizeof (struct opcode_hash_entry));
884 (*entry)->next = NULL;
885 (*entry)->name = (*hash_slot)->name;
886 (*entry)->opcode = xstrdup (str);
887 }
888 }
40b8e679 889
c587b3f9
L
890 /* Process opcode array. */
891 for (j = 0; j < i; j++)
892 {
893 for (next = opcode_array[j]; next; next = next->next)
894 {
895 name = next->name;
896 str = next->opcode;
897 last = str + strlen (str);
898 output_i386_opcode (table, name, str, last);
40b8e679 899 }
40b8e679
L
900 }
901
34edb9ad
L
902 fclose (fp);
903
4dffcebc 904 fprintf (table, " { NULL, 0, 0, 0, 0,\n");
40fb9820
L
905
906 process_i386_cpu_flag (table, "0", 0, ",", " ");
907
908 process_i386_opcode_modifier (table, "0");
909
910 fprintf (table, " { ");
911 process_i386_operand_type (table, "0", 0, "\t ");
912 fprintf (table, " } }\n");
913
34edb9ad 914 fprintf (table, "};\n");
40b8e679
L
915}
916
917static void
72ffa0fb 918process_i386_registers (FILE *table)
40b8e679 919{
3d4d5afa 920 FILE *fp;
40b8e679
L
921 char buf[2048];
922 char *str, *p, *last;
923 char *reg_name, *reg_type, *reg_flags, *reg_num;
a60de03c 924 char *dw2_32_num, *dw2_64_num;
40b8e679 925
3d4d5afa
L
926 filename = "i386-reg.tbl";
927 fp = fopen (filename, "r");
40b8e679 928 if (fp == NULL)
34edb9ad 929 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
40fb9820 930 xstrerror (errno));
40b8e679 931
34edb9ad
L
932 fprintf (table, "\n/* i386 register table. */\n\n");
933 fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
40b8e679
L
934
935 while (!feof (fp))
936 {
937 if (fgets (buf, sizeof (buf), fp) == NULL)
938 break;
939
3d4d5afa
L
940 lineno++;
941
40b8e679
L
942 p = remove_leading_whitespaces (buf);
943
944 /* Skip comments. */
945 str = strstr (p, "//");
946 if (str != NULL)
947 str[0] = '\0';
948
949 /* Remove trailing white spaces. */
950 remove_trailing_whitespaces (p);
951
952 switch (p[0])
953 {
954 case '#':
34edb9ad 955 fprintf (table, "%s\n", p);
40b8e679
L
956 case '\0':
957 continue;
958 break;
959 default:
960 break;
961 }
962
963 last = p + strlen (p);
964
965 /* Find reg_name. */
c587b3f9 966 reg_name = next_field (p, ',', &str, last);
40b8e679
L
967
968 /* Find reg_type. */
c587b3f9 969 reg_type = next_field (str, ',', &str, last);
40b8e679
L
970
971 /* Find reg_flags. */
c587b3f9 972 reg_flags = next_field (str, ',', &str, last);
40b8e679
L
973
974 /* Find reg_num. */
c587b3f9 975 reg_num = next_field (str, ',', &str, last);
a60de03c 976
40fb9820
L
977 fprintf (table, " { \"%s\",\n ", reg_name);
978
979 process_i386_operand_type (table, reg_type, 0, "\t");
980
a60de03c 981 /* Find 32-bit Dwarf2 register number. */
c587b3f9 982 dw2_32_num = next_field (str, ',', &str, last);
a60de03c
JB
983
984 /* Find 64-bit Dwarf2 register number. */
c587b3f9 985 dw2_64_num = next_field (str, ',', &str, last);
a60de03c
JB
986
987 fprintf (table, ",\n %s, %s, { %s, %s } },\n",
988 reg_flags, reg_num, dw2_32_num, dw2_64_num);
40b8e679
L
989 }
990
34edb9ad
L
991 fclose (fp);
992
993 fprintf (table, "};\n");
40b8e679 994
34edb9ad 995 fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
40b8e679
L
996}
997
40fb9820
L
998static void
999process_i386_initializers (void)
1000{
1001 unsigned int i;
1002 FILE *fp = fopen ("i386-init.h", "w");
1003 char *init;
1004
1005 if (fp == NULL)
1006 fail (_("can't create i386-init.h, errno = %s\n"),
1007 xstrerror (errno));
1008
1009 process_copyright (fp);
1010
1011 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
1012 {
1013 fprintf (fp, "\n#define %s \\\n", cpu_flag_init[i].name);
1014 init = xstrdup (cpu_flag_init[i].init);
1015 process_i386_cpu_flag (fp, init, 1, "", " ");
1016 free (init);
1017 }
1018
1019 for (i = 0; i < ARRAY_SIZE (operand_type_init); i++)
1020 {
1021 fprintf (fp, "\n\n#define %s \\\n ", operand_type_init[i].name);
1022 init = xstrdup (operand_type_init[i].init);
1023 process_i386_operand_type (fp, init, 1, " ");
1024 free (init);
1025 }
1026 fprintf (fp, "\n");
1027
1028 fclose (fp);
1029}
1030
40b8e679
L
1031/* Program options. */
1032#define OPTION_SRCDIR 200
1033
1034struct option long_options[] =
1035{
1036 {"srcdir", required_argument, NULL, OPTION_SRCDIR},
1037 {"debug", no_argument, NULL, 'd'},
1038 {"version", no_argument, NULL, 'V'},
1039 {"help", no_argument, NULL, 'h'},
1040 {0, no_argument, NULL, 0}
1041};
1042
1043static void
1044print_version (void)
1045{
1046 printf ("%s: version 1.0\n", program_name);
1047 xexit (0);
1048}
1049
1050static void
1051usage (FILE * stream, int status)
1052{
1053 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1054 program_name);
1055 xexit (status);
1056}
1057
1058int
1059main (int argc, char **argv)
1060{
1061 extern int chdir (char *);
1062 char *srcdir = NULL;
8b40d594 1063 int c;
72ffa0fb 1064 FILE *table;
40b8e679
L
1065
1066 program_name = *argv;
1067 xmalloc_set_program_name (program_name);
1068
1069 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
1070 switch (c)
1071 {
1072 case OPTION_SRCDIR:
1073 srcdir = optarg;
1074 break;
1075 case 'V':
1076 case 'v':
1077 print_version ();
1078 break;
1079 case 'd':
1080 debug = 1;
1081 break;
1082 case 'h':
1083 case '?':
1084 usage (stderr, 0);
1085 default:
1086 case 0:
1087 break;
1088 }
1089
1090 if (optind != argc)
1091 usage (stdout, 1);
1092
1093 if (srcdir != NULL)
1094 if (chdir (srcdir) != 0)
1095 fail (_("unable to change directory to \"%s\", errno = %s\n"),
40fb9820
L
1096 srcdir, xstrerror (errno));
1097
1098 /* Check the unused bitfield in i386_cpu_flags. */
1099#ifndef CpuUnused
8b40d594
L
1100 c = CpuNumOfBits - CpuMax - 1;
1101 if (c)
1102 fail (_("%d unused bits in i386_cpu_flags.\n"), c);
40fb9820
L
1103#endif
1104
1105 /* Check the unused bitfield in i386_operand_type. */
1106#ifndef OTUnused
8b40d594
L
1107 c = OTNumOfBits - OTMax - 1;
1108 if (c)
1109 fail (_("%d unused bits in i386_operand_type.\n"), c);
40fb9820
L
1110#endif
1111
1112 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
1113 compare);
1114
1115 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
1116 sizeof (opcode_modifiers [0]), compare);
1117
1118 qsort (operand_types, ARRAY_SIZE (operand_types),
1119 sizeof (operand_types [0]), compare);
40b8e679 1120
34edb9ad
L
1121 table = fopen ("i386-tbl.h", "w");
1122 if (table == NULL)
40fb9820
L
1123 fail (_("can't create i386-tbl.h, errno = %s\n"),
1124 xstrerror (errno));
34edb9ad 1125
72ffa0fb 1126 process_copyright (table);
40b8e679 1127
72ffa0fb
L
1128 process_i386_opcodes (table);
1129 process_i386_registers (table);
40fb9820 1130 process_i386_initializers ();
40b8e679 1131
34edb9ad
L
1132 fclose (table);
1133
40b8e679
L
1134 exit (0);
1135}
This page took 0.134028 seconds and 4 git commands to generate.