gdb/
[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" },
f1f8f695
L
119 { "CPU_MOVBE_FLAGS",
120 "CpuMovbe" },
1b7f3fb0
L
121 { "CPU_RDTSCP_FLAGS",
122 "CpuRdtscp" },
f1f8f695
L
123 { "CPU_EPT_FLAGS",
124 "CpuEPT" },
40fb9820
L
125 { "CPU_3DNOW_FLAGS",
126 "CpuMMX|Cpu3dnow" },
127 { "CPU_3DNOWA_FLAGS",
115c7c25 128 "CpuMMX|Cpu3dnow|Cpu3dnowA" },
40fb9820
L
129 { "CPU_PADLOCK_FLAGS",
130 "CpuPadLock" },
131 { "CPU_SVME_FLAGS",
132 "CpuSVME" },
133 { "CPU_SSE4A_FLAGS",
115c7c25 134 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a" },
40fb9820 135 { "CPU_ABM_FLAGS",
3629bb00 136 "CpuABM" },
c0f3af97
L
137 { "CPU_AVX_FLAGS",
138 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX" },
40fb9820
L
139};
140
8acd5377 141static initializer operand_type_init[] =
40fb9820
L
142{
143 { "OPERAND_TYPE_NONE",
144 "0" },
145 { "OPERAND_TYPE_REG8",
146 "Reg8" },
147 { "OPERAND_TYPE_REG16",
148 "Reg16" },
149 { "OPERAND_TYPE_REG32",
150 "Reg32" },
151 { "OPERAND_TYPE_REG64",
152 "Reg64" },
153 { "OPERAND_TYPE_IMM1",
154 "Imm1" },
155 { "OPERAND_TYPE_IMM8",
156 "Imm8" },
157 { "OPERAND_TYPE_IMM8S",
158 "Imm8S" },
159 { "OPERAND_TYPE_IMM16",
160 "Imm16" },
161 { "OPERAND_TYPE_IMM32",
162 "Imm32" },
163 { "OPERAND_TYPE_IMM32S",
164 "Imm32S" },
165 { "OPERAND_TYPE_IMM64",
166 "Imm64" },
167 { "OPERAND_TYPE_BASEINDEX",
168 "BaseIndex" },
169 { "OPERAND_TYPE_DISP8",
170 "Disp8" },
171 { "OPERAND_TYPE_DISP16",
172 "Disp16" },
173 { "OPERAND_TYPE_DISP32",
174 "Disp32" },
175 { "OPERAND_TYPE_DISP32S",
176 "Disp32S" },
177 { "OPERAND_TYPE_DISP64",
178 "Disp64" },
179 { "OPERAND_TYPE_INOUTPORTREG",
180 "InOutPortReg" },
181 { "OPERAND_TYPE_SHIFTCOUNT",
182 "ShiftCount" },
183 { "OPERAND_TYPE_CONTROL",
184 "Control" },
185 { "OPERAND_TYPE_TEST",
186 "Test" },
187 { "OPERAND_TYPE_DEBUG",
188 "FloatReg" },
189 { "OPERAND_TYPE_FLOATREG",
190 "FloatReg" },
191 { "OPERAND_TYPE_FLOATACC",
192 "FloatAcc" },
193 { "OPERAND_TYPE_SREG2",
194 "SReg2" },
195 { "OPERAND_TYPE_SREG3",
196 "SReg3" },
197 { "OPERAND_TYPE_ACC",
198 "Acc" },
199 { "OPERAND_TYPE_JUMPABSOLUTE",
200 "JumpAbsolute" },
201 { "OPERAND_TYPE_REGMMX",
202 "RegMMX" },
203 { "OPERAND_TYPE_REGXMM",
204 "RegXMM" },
c0f3af97
L
205 { "OPERAND_TYPE_REGYMM",
206 "RegYMM" },
40fb9820
L
207 { "OPERAND_TYPE_ESSEG",
208 "EsSeg" },
209 { "OPERAND_TYPE_ACC32",
7d5e4556 210 "Reg32|Acc|Dword" },
40fb9820 211 { "OPERAND_TYPE_ACC64",
7d5e4556 212 "Reg64|Acc|Qword" },
65da13b5
L
213 { "OPERAND_TYPE_INOUTPORTREG",
214 "InOutPortReg" },
40fb9820
L
215 { "OPERAND_TYPE_REG16_INOUTPORTREG",
216 "Reg16|InOutPortReg" },
217 { "OPERAND_TYPE_DISP16_32",
218 "Disp16|Disp32" },
219 { "OPERAND_TYPE_ANYDISP",
220 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
221 { "OPERAND_TYPE_IMM16_32",
222 "Imm16|Imm32" },
223 { "OPERAND_TYPE_IMM16_32S",
224 "Imm16|Imm32S" },
225 { "OPERAND_TYPE_IMM16_32_32S",
226 "Imm16|Imm32|Imm32S" },
227 { "OPERAND_TYPE_IMM32_32S_DISP32",
228 "Imm32|Imm32S|Disp32" },
229 { "OPERAND_TYPE_IMM64_DISP64",
230 "Imm64|Disp64" },
231 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
232 "Imm32|Imm32S|Imm64|Disp32" },
233 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
234 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
235};
236
237typedef struct bitfield
238{
239 int position;
240 int value;
241 const char *name;
242} bitfield;
243
244#define BITFIELD(n) { n, 0, #n }
245
246static bitfield cpu_flags[] =
247{
248 BITFIELD (Cpu186),
249 BITFIELD (Cpu286),
250 BITFIELD (Cpu386),
251 BITFIELD (Cpu486),
252 BITFIELD (Cpu586),
253 BITFIELD (Cpu686),
bd5295b2
L
254 BITFIELD (CpuClflush),
255 BITFIELD (CpuSYSCALL),
40fb9820 256 BITFIELD (CpuMMX),
40fb9820
L
257 BITFIELD (CpuSSE),
258 BITFIELD (CpuSSE2),
259 BITFIELD (CpuSSE3),
260 BITFIELD (CpuSSSE3),
261 BITFIELD (CpuSSE4_1),
262 BITFIELD (CpuSSE4_2),
c0f3af97 263 BITFIELD (CpuAVX),
40fb9820
L
264 BITFIELD (CpuSSE4a),
265 BITFIELD (Cpu3dnow),
266 BITFIELD (Cpu3dnowA),
267 BITFIELD (CpuPadLock),
268 BITFIELD (CpuSVME),
269 BITFIELD (CpuVMX),
47dd174c 270 BITFIELD (CpuSMX),
40fb9820 271 BITFIELD (CpuABM),
475a2301 272 BITFIELD (CpuXsave),
c0f3af97 273 BITFIELD (CpuAES),
594ab6a3 274 BITFIELD (CpuPCLMUL),
c0f3af97
L
275 BITFIELD (CpuFMA),
276 BITFIELD (CpuLM),
f1f8f695
L
277 BITFIELD (CpuMovbe),
278 BITFIELD (CpuEPT),
1b7f3fb0 279 BITFIELD (CpuRdtscp),
40fb9820
L
280 BITFIELD (Cpu64),
281 BITFIELD (CpuNo64),
282#ifdef CpuUnused
283 BITFIELD (CpuUnused),
284#endif
285};
286
287static bitfield opcode_modifiers[] =
288{
289 BITFIELD (D),
290 BITFIELD (W),
b6169b20 291 BITFIELD (S),
40fb9820
L
292 BITFIELD (Modrm),
293 BITFIELD (ShortForm),
294 BITFIELD (Jump),
295 BITFIELD (JumpDword),
296 BITFIELD (JumpByte),
297 BITFIELD (JumpInterSegment),
298 BITFIELD (FloatMF),
299 BITFIELD (FloatR),
300 BITFIELD (FloatD),
301 BITFIELD (Size16),
302 BITFIELD (Size32),
303 BITFIELD (Size64),
304 BITFIELD (IgnoreSize),
305 BITFIELD (DefaultSize),
306 BITFIELD (No_bSuf),
307 BITFIELD (No_wSuf),
308 BITFIELD (No_lSuf),
309 BITFIELD (No_sSuf),
310 BITFIELD (No_qSuf),
7ce189b3 311 BITFIELD (No_ldSuf),
40fb9820
L
312 BITFIELD (FWait),
313 BITFIELD (IsString),
314 BITFIELD (RegKludge),
e2ec9d29 315 BITFIELD (FirstXmm0),
c0f3af97 316 BITFIELD (Implicit1stXmm0),
ca61edf2
L
317 BITFIELD (ByteOkIntel),
318 BITFIELD (ToDword),
319 BITFIELD (ToQword),
320 BITFIELD (AddrPrefixOp0),
40fb9820
L
321 BITFIELD (IsPrefix),
322 BITFIELD (ImmExt),
323 BITFIELD (NoRex64),
324 BITFIELD (Rex64),
325 BITFIELD (Ugh),
c0f3af97
L
326 BITFIELD (Vex),
327 BITFIELD (Vex256),
c0f3af97 328 BITFIELD (VexNDS),
03547503 329 BITFIELD (VexNDD),
c0f3af97
L
330 BITFIELD (VexW0),
331 BITFIELD (VexW1),
332 BITFIELD (Vex0F),
333 BITFIELD (Vex0F38),
334 BITFIELD (Vex0F3A),
335 BITFIELD (Vex3Sources),
336 BITFIELD (VexImmExt),
337 BITFIELD (SSE2AVX),
81f8a913 338 BITFIELD (NoAVX),
1efbbeb4
L
339 BITFIELD (OldGcc),
340 BITFIELD (ATTMnemonic),
e1d4d893 341 BITFIELD (ATTSyntax),
5c07affc 342 BITFIELD (IntelSyntax),
40fb9820
L
343};
344
345static bitfield operand_types[] =
346{
347 BITFIELD (Reg8),
348 BITFIELD (Reg16),
349 BITFIELD (Reg32),
350 BITFIELD (Reg64),
351 BITFIELD (FloatReg),
352 BITFIELD (RegMMX),
353 BITFIELD (RegXMM),
c0f3af97 354 BITFIELD (RegYMM),
40fb9820
L
355 BITFIELD (Imm8),
356 BITFIELD (Imm8S),
357 BITFIELD (Imm16),
358 BITFIELD (Imm32),
359 BITFIELD (Imm32S),
360 BITFIELD (Imm64),
361 BITFIELD (Imm1),
362 BITFIELD (BaseIndex),
363 BITFIELD (Disp8),
364 BITFIELD (Disp16),
365 BITFIELD (Disp32),
366 BITFIELD (Disp32S),
367 BITFIELD (Disp64),
368 BITFIELD (InOutPortReg),
369 BITFIELD (ShiftCount),
370 BITFIELD (Control),
371 BITFIELD (Debug),
372 BITFIELD (Test),
373 BITFIELD (SReg2),
374 BITFIELD (SReg3),
375 BITFIELD (Acc),
376 BITFIELD (FloatAcc),
377 BITFIELD (JumpAbsolute),
378 BITFIELD (EsSeg),
379 BITFIELD (RegMem),
5c07affc 380 BITFIELD (Mem),
7d5e4556
L
381 BITFIELD (Byte),
382 BITFIELD (Word),
383 BITFIELD (Dword),
384 BITFIELD (Fword),
385 BITFIELD (Qword),
386 BITFIELD (Tbyte),
387 BITFIELD (Xmmword),
c0f3af97 388 BITFIELD (Ymmword),
7d5e4556
L
389 BITFIELD (Unspecified),
390 BITFIELD (Anysize),
40fb9820
L
391#ifdef OTUnused
392 BITFIELD (OTUnused),
393#endif
394};
395
3d4d5afa
L
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\
22da050b
L
422/* Copyright 2007, 2008, 2009\n\
423 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 496static void
bd5295b2 497set_bitfield (const char *f, bitfield *array, unsigned int size, int lineno)
40fb9820
L
498{
499 unsigned int i;
500
1b7f3fb0 501 if (strcmp (f, "Mmword") == 0)
7d5e4556
L
502 f= "Qword";
503 else if (strcmp (f, "Oword") == 0)
504 f= "Xmmword";
40fb9820
L
505
506 for (i = 0; i < size; i++)
507 if (strcasecmp (array[i].name, f) == 0)
508 {
509 array[i].value = 1;
510 return;
511 }
512
bd5295b2
L
513 if (lineno != -1)
514 fail (_("%s: %d: Unknown bitfield: %s\n"), filename, lineno, f);
515 else
516 fail (_("Unknown bitfield: %s\n"), f);
40fb9820
L
517}
518
519static void
520output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
521 int macro, const char *comma, const char *indent)
522{
523 unsigned int i;
524
525 fprintf (table, "%s{ { ", indent);
526
527 for (i = 0; i < size - 1; i++)
528 {
529 fprintf (table, "%d, ", flags[i].value);
530 if (((i + 1) % 20) == 0)
531 {
532 /* We need \\ for macro. */
533 if (macro)
534 fprintf (table, " \\\n %s", indent);
535 else
536 fprintf (table, "\n %s", indent);
537 }
538 }
539
540 fprintf (table, "%d } }%s\n", flags[i].value, comma);
541}
542
543static void
544process_i386_cpu_flag (FILE *table, char *flag, int macro,
bd5295b2
L
545 const char *comma, const char *indent,
546 int lineno)
40fb9820
L
547{
548 char *str, *next, *last;
549 bitfield flags [ARRAY_SIZE (cpu_flags)];
550
551 /* Copy the default cpu flags. */
552 memcpy (flags, cpu_flags, sizeof (cpu_flags));
553
554 if (strcasecmp (flag, "unknown") == 0)
555 {
556 unsigned int i;
557
558 /* We turn on everything except for cpu64 in case of
559 CPU_UNKNOWN_FLAGS. */
560 for (i = 0; i < ARRAY_SIZE (flags); i++)
561 if (flags[i].position != Cpu64)
562 flags[i].value = 1;
563 }
564 else if (strcmp (flag, "0"))
565 {
566 last = flag + strlen (flag);
567 for (next = flag; next && next < last; )
568 {
c587b3f9 569 str = next_field (next, '|', &next, last);
40fb9820 570 if (str)
bd5295b2 571 set_bitfield (str, flags, ARRAY_SIZE (flags), lineno);
40fb9820
L
572 }
573 }
574
575 output_cpu_flags (table, flags, ARRAY_SIZE (flags), macro,
576 comma, indent);
577}
578
579static void
580output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
581{
582 unsigned int i;
583
584 fprintf (table, " { ");
585
586 for (i = 0; i < size - 1; i++)
587 {
588 fprintf (table, "%d, ", modifier[i].value);
589 if (((i + 1) % 20) == 0)
590 fprintf (table, "\n ");
591 }
592
593 fprintf (table, "%d },\n", modifier[i].value);
594}
595
596static void
bd5295b2 597process_i386_opcode_modifier (FILE *table, char *mod, int lineno)
40fb9820
L
598{
599 char *str, *next, *last;
600 bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
601
602 /* Copy the default opcode modifier. */
603 memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
604
605 if (strcmp (mod, "0"))
606 {
607 last = mod + strlen (mod);
608 for (next = mod; next && next < last; )
609 {
c587b3f9 610 str = next_field (next, '|', &next, last);
40fb9820 611 if (str)
bd5295b2 612 set_bitfield (str, modifiers, ARRAY_SIZE (modifiers), lineno);
40fb9820
L
613 }
614 }
615 output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
616}
617
618static void
619output_operand_type (FILE *table, bitfield *types, unsigned int size,
620 int macro, const char *indent)
621{
622 unsigned int i;
623
624 fprintf (table, "{ { ");
625
626 for (i = 0; i < size - 1; i++)
627 {
628 fprintf (table, "%d, ", types[i].value);
629 if (((i + 1) % 20) == 0)
630 {
631 /* We need \\ for macro. */
632 if (macro)
633 fprintf (table, "\\\n%s", indent);
634 else
635 fprintf (table, "\n%s", indent);
636 }
637 }
638
639 fprintf (table, "%d } }", types[i].value);
640}
641
642static void
643process_i386_operand_type (FILE *table, char *op, int macro,
bd5295b2 644 const char *indent, int lineno)
40fb9820
L
645{
646 char *str, *next, *last;
647 bitfield types [ARRAY_SIZE (operand_types)];
648
649 /* Copy the default operand type. */
650 memcpy (types, operand_types, sizeof (types));
651
652 if (strcmp (op, "0"))
653 {
654 last = op + strlen (op);
655 for (next = op; next && next < last; )
656 {
c587b3f9 657 str = next_field (next, '|', &next, last);
40fb9820 658 if (str)
bd5295b2 659 set_bitfield (str, types, ARRAY_SIZE (types), lineno);
40fb9820
L
660 }
661 }
662 output_operand_type (table, types, ARRAY_SIZE (types), macro,
663 indent);
664}
665
c587b3f9
L
666static void
667output_i386_opcode (FILE *table, const char *name, char *str,
bd5295b2 668 char *last, int lineno)
c587b3f9
L
669{
670 unsigned int i;
671 char *operands, *base_opcode, *extension_opcode, *opcode_length;
672 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
673
674 /* Find number of operands. */
675 operands = next_field (str, ',', &str, last);
676
677 /* Find base_opcode. */
678 base_opcode = next_field (str, ',', &str, last);
679
680 /* Find extension_opcode. */
681 extension_opcode = next_field (str, ',', &str, last);
682
683 /* Find opcode_length. */
684 opcode_length = next_field (str, ',', &str, last);
685
686 /* Find cpu_flags. */
687 cpu_flags = next_field (str, ',', &str, last);
688
689 /* Find opcode_modifier. */
690 opcode_modifier = next_field (str, ',', &str, last);
691
692 /* Remove the first {. */
693 str = remove_leading_whitespaces (str);
694 if (*str != '{')
695 abort ();
696 str = remove_leading_whitespaces (str + 1);
697
698 i = strlen (str);
699
700 /* There are at least "X}". */
701 if (i < 2)
702 abort ();
703
704 /* Remove trailing white spaces and }. */
705 do
706 {
707 i--;
708 if (ISSPACE (str[i]) || str[i] == '}')
709 str[i] = '\0';
710 else
711 break;
712 }
713 while (i != 0);
714
715 last = str + i;
716
717 /* Find operand_types. */
718 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
719 {
720 if (str >= last)
721 {
722 operand_types [i] = NULL;
723 break;
724 }
725
726 operand_types [i] = next_field (str, ',', &str, last);
727 if (*operand_types[i] == '0')
728 {
729 if (i != 0)
730 operand_types[i] = NULL;
731 break;
732 }
733 }
734
735 fprintf (table, " { \"%s\", %s, %s, %s, %s,\n",
736 name, operands, base_opcode, extension_opcode,
737 opcode_length);
738
bd5295b2 739 process_i386_cpu_flag (table, cpu_flags, 0, ",", " ", lineno);
c587b3f9 740
bd5295b2 741 process_i386_opcode_modifier (table, opcode_modifier, lineno);
c587b3f9
L
742
743 fprintf (table, " { ");
744
745 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
746 {
747 if (operand_types[i] == NULL || *operand_types[i] == '0')
748 {
749 if (i == 0)
bd5295b2 750 process_i386_operand_type (table, "0", 0, "\t ", lineno);
c587b3f9
L
751 break;
752 }
753
754 if (i != 0)
755 fprintf (table, ",\n ");
756
757 process_i386_operand_type (table, operand_types[i], 0,
bd5295b2 758 "\t ", lineno);
c587b3f9
L
759 }
760 fprintf (table, " } },\n");
761}
762
763struct opcode_hash_entry
764{
765 struct opcode_hash_entry *next;
766 char *name;
767 char *opcode;
bd5295b2 768 int lineno;
c587b3f9
L
769};
770
771/* Calculate the hash value of an opcode hash entry P. */
772
773static hashval_t
774opcode_hash_hash (const void *p)
775{
776 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
777 return htab_hash_string (entry->name);
778}
779
780/* Compare a string Q against an opcode hash entry P. */
781
782static int
783opcode_hash_eq (const void *p, const void *q)
784{
785 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
786 const char *name = (const char *) q;
787 return strcmp (name, entry->name) == 0;
788}
789
40b8e679 790static void
72ffa0fb 791process_i386_opcodes (FILE *table)
40b8e679 792{
3d4d5afa 793 FILE *fp;
40b8e679 794 char buf[2048];
c587b3f9
L
795 unsigned int i, j;
796 char *str, *p, *last, *name;
797 struct opcode_hash_entry **hash_slot, **entry, *next;
798 htab_t opcode_hash_table;
799 struct opcode_hash_entry **opcode_array;
800 unsigned int opcode_array_size = 1024;
bd5295b2 801 int lineno = 0;
40b8e679 802
3d4d5afa
L
803 filename = "i386-opc.tbl";
804 fp = fopen (filename, "r");
805
40b8e679 806 if (fp == NULL)
34edb9ad 807 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
40fb9820 808 xstrerror (errno));
40b8e679 809
c587b3f9
L
810 i = 0;
811 opcode_array = (struct opcode_hash_entry **)
812 xmalloc (sizeof (*opcode_array) * opcode_array_size);
813
814 opcode_hash_table = htab_create_alloc (16, opcode_hash_hash,
815 opcode_hash_eq, NULL,
816 xcalloc, free);
817
34edb9ad
L
818 fprintf (table, "\n/* i386 opcode table. */\n\n");
819 fprintf (table, "const template i386_optab[] =\n{\n");
40b8e679 820
c587b3f9 821 /* Put everything on opcode array. */
40b8e679
L
822 while (!feof (fp))
823 {
824 if (fgets (buf, sizeof (buf), fp) == NULL)
825 break;
826
3d4d5afa
L
827 lineno++;
828
40b8e679
L
829 p = remove_leading_whitespaces (buf);
830
831 /* Skip comments. */
832 str = strstr (p, "//");
833 if (str != NULL)
834 str[0] = '\0';
835
836 /* Remove trailing white spaces. */
837 remove_trailing_whitespaces (p);
838
839 switch (p[0])
840 {
841 case '#':
c587b3f9 842 /* Ignore comments. */
40b8e679
L
843 case '\0':
844 continue;
845 break;
846 default:
847 break;
848 }
849
850 last = p + strlen (p);
851
852 /* Find name. */
c587b3f9 853 name = next_field (p, ',', &str, last);
40b8e679 854
c587b3f9
L
855 /* Get the slot in hash table. */
856 hash_slot = (struct opcode_hash_entry **)
857 htab_find_slot_with_hash (opcode_hash_table, name,
858 htab_hash_string (name),
859 INSERT);
40b8e679 860
c587b3f9 861 if (*hash_slot == NULL)
40b8e679 862 {
c587b3f9
L
863 /* It is the new one. Put it on opcode array. */
864 if (i >= opcode_array_size)
40b8e679 865 {
c587b3f9
L
866 /* Grow the opcode array when needed. */
867 opcode_array_size += 1024;
868 opcode_array = (struct opcode_hash_entry **)
869 xrealloc (opcode_array,
870 sizeof (*opcode_array) * opcode_array_size);
40b8e679
L
871 }
872
c587b3f9
L
873 opcode_array[i] = (struct opcode_hash_entry *)
874 xmalloc (sizeof (struct opcode_hash_entry));
875 opcode_array[i]->next = NULL;
876 opcode_array[i]->name = xstrdup (name);
877 opcode_array[i]->opcode = xstrdup (str);
bd5295b2 878 opcode_array[i]->lineno = lineno;
c587b3f9
L
879 *hash_slot = opcode_array[i];
880 i++;
40b8e679 881 }
c587b3f9 882 else
40b8e679 883 {
c587b3f9
L
884 /* Append it to the existing one. */
885 entry = hash_slot;
886 while ((*entry) != NULL)
887 entry = &(*entry)->next;
888 *entry = (struct opcode_hash_entry *)
889 xmalloc (sizeof (struct opcode_hash_entry));
890 (*entry)->next = NULL;
891 (*entry)->name = (*hash_slot)->name;
892 (*entry)->opcode = xstrdup (str);
bd5295b2 893 (*entry)->lineno = lineno;
c587b3f9
L
894 }
895 }
40b8e679 896
c587b3f9
L
897 /* Process opcode array. */
898 for (j = 0; j < i; j++)
899 {
900 for (next = opcode_array[j]; next; next = next->next)
901 {
902 name = next->name;
903 str = next->opcode;
bd5295b2 904 lineno = next->lineno;
c587b3f9 905 last = str + strlen (str);
bd5295b2 906 output_i386_opcode (table, name, str, last, lineno);
40b8e679 907 }
40b8e679
L
908 }
909
34edb9ad
L
910 fclose (fp);
911
4dffcebc 912 fprintf (table, " { NULL, 0, 0, 0, 0,\n");
40fb9820 913
bd5295b2 914 process_i386_cpu_flag (table, "0", 0, ",", " ", -1);
40fb9820 915
bd5295b2 916 process_i386_opcode_modifier (table, "0", -1);
40fb9820
L
917
918 fprintf (table, " { ");
bd5295b2 919 process_i386_operand_type (table, "0", 0, "\t ", -1);
40fb9820
L
920 fprintf (table, " } }\n");
921
34edb9ad 922 fprintf (table, "};\n");
40b8e679
L
923}
924
925static void
72ffa0fb 926process_i386_registers (FILE *table)
40b8e679 927{
3d4d5afa 928 FILE *fp;
40b8e679
L
929 char buf[2048];
930 char *str, *p, *last;
931 char *reg_name, *reg_type, *reg_flags, *reg_num;
a60de03c 932 char *dw2_32_num, *dw2_64_num;
bd5295b2 933 int lineno = 0;
40b8e679 934
3d4d5afa
L
935 filename = "i386-reg.tbl";
936 fp = fopen (filename, "r");
40b8e679 937 if (fp == NULL)
34edb9ad 938 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
40fb9820 939 xstrerror (errno));
40b8e679 940
34edb9ad
L
941 fprintf (table, "\n/* i386 register table. */\n\n");
942 fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
40b8e679
L
943
944 while (!feof (fp))
945 {
946 if (fgets (buf, sizeof (buf), fp) == NULL)
947 break;
948
3d4d5afa
L
949 lineno++;
950
40b8e679
L
951 p = remove_leading_whitespaces (buf);
952
953 /* Skip comments. */
954 str = strstr (p, "//");
955 if (str != NULL)
956 str[0] = '\0';
957
958 /* Remove trailing white spaces. */
959 remove_trailing_whitespaces (p);
960
961 switch (p[0])
962 {
963 case '#':
34edb9ad 964 fprintf (table, "%s\n", p);
40b8e679
L
965 case '\0':
966 continue;
967 break;
968 default:
969 break;
970 }
971
972 last = p + strlen (p);
973
974 /* Find reg_name. */
c587b3f9 975 reg_name = next_field (p, ',', &str, last);
40b8e679
L
976
977 /* Find reg_type. */
c587b3f9 978 reg_type = next_field (str, ',', &str, last);
40b8e679
L
979
980 /* Find reg_flags. */
c587b3f9 981 reg_flags = next_field (str, ',', &str, last);
40b8e679
L
982
983 /* Find reg_num. */
c587b3f9 984 reg_num = next_field (str, ',', &str, last);
a60de03c 985
40fb9820
L
986 fprintf (table, " { \"%s\",\n ", reg_name);
987
bd5295b2 988 process_i386_operand_type (table, reg_type, 0, "\t", lineno);
40fb9820 989
a60de03c 990 /* Find 32-bit Dwarf2 register number. */
c587b3f9 991 dw2_32_num = next_field (str, ',', &str, last);
a60de03c
JB
992
993 /* Find 64-bit Dwarf2 register number. */
c587b3f9 994 dw2_64_num = next_field (str, ',', &str, last);
a60de03c
JB
995
996 fprintf (table, ",\n %s, %s, { %s, %s } },\n",
997 reg_flags, reg_num, dw2_32_num, dw2_64_num);
40b8e679
L
998 }
999
34edb9ad
L
1000 fclose (fp);
1001
1002 fprintf (table, "};\n");
40b8e679 1003
34edb9ad 1004 fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
40b8e679
L
1005}
1006
40fb9820
L
1007static void
1008process_i386_initializers (void)
1009{
1010 unsigned int i;
1011 FILE *fp = fopen ("i386-init.h", "w");
1012 char *init;
1013
1014 if (fp == NULL)
1015 fail (_("can't create i386-init.h, errno = %s\n"),
1016 xstrerror (errno));
1017
1018 process_copyright (fp);
1019
1020 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
1021 {
1022 fprintf (fp, "\n#define %s \\\n", cpu_flag_init[i].name);
1023 init = xstrdup (cpu_flag_init[i].init);
bd5295b2 1024 process_i386_cpu_flag (fp, init, 1, "", " ", -1);
40fb9820
L
1025 free (init);
1026 }
1027
1028 for (i = 0; i < ARRAY_SIZE (operand_type_init); i++)
1029 {
1030 fprintf (fp, "\n\n#define %s \\\n ", operand_type_init[i].name);
1031 init = xstrdup (operand_type_init[i].init);
bd5295b2 1032 process_i386_operand_type (fp, init, 1, " ", -1);
40fb9820
L
1033 free (init);
1034 }
1035 fprintf (fp, "\n");
1036
1037 fclose (fp);
1038}
1039
40b8e679
L
1040/* Program options. */
1041#define OPTION_SRCDIR 200
1042
1043struct option long_options[] =
1044{
1045 {"srcdir", required_argument, NULL, OPTION_SRCDIR},
1046 {"debug", no_argument, NULL, 'd'},
1047 {"version", no_argument, NULL, 'V'},
1048 {"help", no_argument, NULL, 'h'},
1049 {0, no_argument, NULL, 0}
1050};
1051
1052static void
1053print_version (void)
1054{
1055 printf ("%s: version 1.0\n", program_name);
1056 xexit (0);
1057}
1058
1059static void
1060usage (FILE * stream, int status)
1061{
1062 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1063 program_name);
1064 xexit (status);
1065}
1066
1067int
1068main (int argc, char **argv)
1069{
1070 extern int chdir (char *);
1071 char *srcdir = NULL;
8b40d594 1072 int c;
72ffa0fb 1073 FILE *table;
40b8e679
L
1074
1075 program_name = *argv;
1076 xmalloc_set_program_name (program_name);
1077
1078 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
1079 switch (c)
1080 {
1081 case OPTION_SRCDIR:
1082 srcdir = optarg;
1083 break;
1084 case 'V':
1085 case 'v':
1086 print_version ();
1087 break;
1088 case 'd':
1089 debug = 1;
1090 break;
1091 case 'h':
1092 case '?':
1093 usage (stderr, 0);
1094 default:
1095 case 0:
1096 break;
1097 }
1098
1099 if (optind != argc)
1100 usage (stdout, 1);
1101
1102 if (srcdir != NULL)
1103 if (chdir (srcdir) != 0)
1104 fail (_("unable to change directory to \"%s\", errno = %s\n"),
40fb9820
L
1105 srcdir, xstrerror (errno));
1106
1107 /* Check the unused bitfield in i386_cpu_flags. */
1108#ifndef CpuUnused
8b40d594
L
1109 c = CpuNumOfBits - CpuMax - 1;
1110 if (c)
1111 fail (_("%d unused bits in i386_cpu_flags.\n"), c);
40fb9820
L
1112#endif
1113
1114 /* Check the unused bitfield in i386_operand_type. */
1115#ifndef OTUnused
8b40d594
L
1116 c = OTNumOfBits - OTMax - 1;
1117 if (c)
1118 fail (_("%d unused bits in i386_operand_type.\n"), c);
40fb9820
L
1119#endif
1120
1121 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
1122 compare);
1123
1124 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
1125 sizeof (opcode_modifiers [0]), compare);
1126
1127 qsort (operand_types, ARRAY_SIZE (operand_types),
1128 sizeof (operand_types [0]), compare);
40b8e679 1129
34edb9ad
L
1130 table = fopen ("i386-tbl.h", "w");
1131 if (table == NULL)
40fb9820
L
1132 fail (_("can't create i386-tbl.h, errno = %s\n"),
1133 xstrerror (errno));
34edb9ad 1134
72ffa0fb 1135 process_copyright (table);
40b8e679 1136
72ffa0fb
L
1137 process_i386_opcodes (table);
1138 process_i386_registers (table);
40fb9820 1139 process_i386_initializers ();
40b8e679 1140
34edb9ad
L
1141 fclose (table);
1142
40b8e679
L
1143 exit (0);
1144}
This page took 0.17603 seconds and 4 git commands to generate.