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