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
43static initializer cpu_flag_init [] =
44{
45 { "CPU_UNKNOWN_FLAGS",
46 "unknown" },
47 { "CPU_GENERIC32_FLAGS",
48 "Cpu186|Cpu286|Cpu386" },
49 { "CPU_GENERIC64_FLAGS",
599121aa 50 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|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",
115c7c25 70 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX|CpuSSE|CpuSSE2" },
40fb9820 71 { "CPU_NOCONA_FLAGS",
115c7c25 72 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuLM" },
40fb9820 73 { "CPU_CORE_FLAGS",
115c7c25 74 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3" },
40fb9820 75 { "CPU_CORE2_FLAGS",
115c7c25 76 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuLM" },
40fb9820
L
77 { "CPU_K6_FLAGS",
78 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuK6|CpuMMX" },
79 { "CPU_K6_2_FLAGS",
80 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuK6|CpuMMX|Cpu3dnow" },
81 { "CPU_ATHLON_FLAGS",
115c7c25 82 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuK6|CpuMMX|Cpu3dnow|Cpu3dnowA" },
40fb9820 83 { "CPU_K8_FLAGS",
115c7c25 84 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuK6|CpuK8|CpuMMX|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2|CpuLM" },
40fb9820 85 { "CPU_AMDFAM10_FLAGS",
115c7c25 86 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuK6|CpuK8|CpuMMX|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuLM" },
40fb9820
L
87 { "CPU_MMX_FLAGS",
88 "CpuMMX" },
89 { "CPU_SSE_FLAGS",
115c7c25 90 "CpuMMX|CpuSSE" },
40fb9820 91 { "CPU_SSE2_FLAGS",
115c7c25 92 "CpuMMX|CpuSSE|CpuSSE2" },
40fb9820 93 { "CPU_SSE3_FLAGS",
115c7c25 94 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3" },
40fb9820 95 { "CPU_SSSE3_FLAGS",
115c7c25 96 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3" },
40fb9820 97 { "CPU_SSE4_1_FLAGS",
115c7c25 98 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1" },
40fb9820 99 { "CPU_SSE4_2_FLAGS",
115c7c25 100 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2" },
6305a203
L
101 { "CPU_VMX_FLAGS",
102 "CpuVMX" },
103 { "CPU_SMX_FLAGS",
104 "CpuSMX" },
f03fe4c1
L
105 { "CPU_XSAVE_FLAGS",
106 "CpuXsave" },
c0f3af97
L
107 { "CPU_AES_FLAGS",
108 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAES" },
594ab6a3
L
109 { "CPU_PCLMUL_FLAGS",
110 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuPCLMUL" },
c0f3af97
L
111 { "CPU_FMA_FLAGS",
112 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuFMA" },
f1f8f695
L
113 { "CPU_MOVBE_FLAGS",
114 "CpuMovbe" },
115 { "CPU_EPT_FLAGS",
116 "CpuEPT" },
40fb9820
L
117 { "CPU_3DNOW_FLAGS",
118 "CpuMMX|Cpu3dnow" },
119 { "CPU_3DNOWA_FLAGS",
115c7c25 120 "CpuMMX|Cpu3dnow|Cpu3dnowA" },
40fb9820
L
121 { "CPU_PADLOCK_FLAGS",
122 "CpuPadLock" },
123 { "CPU_SVME_FLAGS",
124 "CpuSVME" },
125 { "CPU_SSE4A_FLAGS",
115c7c25 126 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a" },
40fb9820 127 { "CPU_ABM_FLAGS",
3629bb00 128 "CpuABM" },
85f10a01 129 { "CPU_SSE5_FLAGS",
115c7c25 130 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuSSE5"},
c0f3af97
L
131 { "CPU_AVX_FLAGS",
132 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX" },
40fb9820
L
133};
134
135static initializer operand_type_init [] =
136{
137 { "OPERAND_TYPE_NONE",
138 "0" },
139 { "OPERAND_TYPE_REG8",
140 "Reg8" },
141 { "OPERAND_TYPE_REG16",
142 "Reg16" },
143 { "OPERAND_TYPE_REG32",
144 "Reg32" },
145 { "OPERAND_TYPE_REG64",
146 "Reg64" },
147 { "OPERAND_TYPE_IMM1",
148 "Imm1" },
149 { "OPERAND_TYPE_IMM8",
150 "Imm8" },
151 { "OPERAND_TYPE_IMM8S",
152 "Imm8S" },
153 { "OPERAND_TYPE_IMM16",
154 "Imm16" },
155 { "OPERAND_TYPE_IMM32",
156 "Imm32" },
157 { "OPERAND_TYPE_IMM32S",
158 "Imm32S" },
159 { "OPERAND_TYPE_IMM64",
160 "Imm64" },
161 { "OPERAND_TYPE_BASEINDEX",
162 "BaseIndex" },
163 { "OPERAND_TYPE_DISP8",
164 "Disp8" },
165 { "OPERAND_TYPE_DISP16",
166 "Disp16" },
167 { "OPERAND_TYPE_DISP32",
168 "Disp32" },
169 { "OPERAND_TYPE_DISP32S",
170 "Disp32S" },
171 { "OPERAND_TYPE_DISP64",
172 "Disp64" },
173 { "OPERAND_TYPE_INOUTPORTREG",
174 "InOutPortReg" },
175 { "OPERAND_TYPE_SHIFTCOUNT",
176 "ShiftCount" },
177 { "OPERAND_TYPE_CONTROL",
178 "Control" },
179 { "OPERAND_TYPE_TEST",
180 "Test" },
181 { "OPERAND_TYPE_DEBUG",
182 "FloatReg" },
183 { "OPERAND_TYPE_FLOATREG",
184 "FloatReg" },
185 { "OPERAND_TYPE_FLOATACC",
186 "FloatAcc" },
187 { "OPERAND_TYPE_SREG2",
188 "SReg2" },
189 { "OPERAND_TYPE_SREG3",
190 "SReg3" },
191 { "OPERAND_TYPE_ACC",
192 "Acc" },
193 { "OPERAND_TYPE_JUMPABSOLUTE",
194 "JumpAbsolute" },
195 { "OPERAND_TYPE_REGMMX",
196 "RegMMX" },
197 { "OPERAND_TYPE_REGXMM",
198 "RegXMM" },
c0f3af97
L
199 { "OPERAND_TYPE_REGYMM",
200 "RegYMM" },
40fb9820
L
201 { "OPERAND_TYPE_ESSEG",
202 "EsSeg" },
203 { "OPERAND_TYPE_ACC32",
7d5e4556 204 "Reg32|Acc|Dword" },
40fb9820 205 { "OPERAND_TYPE_ACC64",
7d5e4556 206 "Reg64|Acc|Qword" },
65da13b5
L
207 { "OPERAND_TYPE_INOUTPORTREG",
208 "InOutPortReg" },
40fb9820
L
209 { "OPERAND_TYPE_REG16_INOUTPORTREG",
210 "Reg16|InOutPortReg" },
211 { "OPERAND_TYPE_DISP16_32",
212 "Disp16|Disp32" },
213 { "OPERAND_TYPE_ANYDISP",
214 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
215 { "OPERAND_TYPE_IMM16_32",
216 "Imm16|Imm32" },
217 { "OPERAND_TYPE_IMM16_32S",
218 "Imm16|Imm32S" },
219 { "OPERAND_TYPE_IMM16_32_32S",
220 "Imm16|Imm32|Imm32S" },
221 { "OPERAND_TYPE_IMM32_32S_DISP32",
222 "Imm32|Imm32S|Disp32" },
223 { "OPERAND_TYPE_IMM64_DISP64",
224 "Imm64|Disp64" },
225 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
226 "Imm32|Imm32S|Imm64|Disp32" },
227 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
228 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
c0f3af97
L
229 { "OPERAND_TYPE_VEX_IMM4",
230 "VEX_Imm4" },
40fb9820
L
231};
232
233typedef struct bitfield
234{
235 int position;
236 int value;
237 const char *name;
238} bitfield;
239
240#define BITFIELD(n) { n, 0, #n }
241
242static bitfield cpu_flags[] =
243{
244 BITFIELD (Cpu186),
245 BITFIELD (Cpu286),
246 BITFIELD (Cpu386),
247 BITFIELD (Cpu486),
248 BITFIELD (Cpu586),
249 BITFIELD (Cpu686),
250 BITFIELD (CpuP4),
251 BITFIELD (CpuK6),
252 BITFIELD (CpuK8),
253 BITFIELD (CpuMMX),
40fb9820
L
254 BITFIELD (CpuSSE),
255 BITFIELD (CpuSSE2),
256 BITFIELD (CpuSSE3),
257 BITFIELD (CpuSSSE3),
258 BITFIELD (CpuSSE4_1),
259 BITFIELD (CpuSSE4_2),
c0f3af97 260 BITFIELD (CpuAVX),
40fb9820 261 BITFIELD (CpuSSE4a),
85f10a01 262 BITFIELD (CpuSSE5),
40fb9820
L
263 BITFIELD (Cpu3dnow),
264 BITFIELD (Cpu3dnowA),
265 BITFIELD (CpuPadLock),
266 BITFIELD (CpuSVME),
267 BITFIELD (CpuVMX),
47dd174c 268 BITFIELD (CpuSMX),
40fb9820 269 BITFIELD (CpuABM),
475a2301 270 BITFIELD (CpuXsave),
c0f3af97 271 BITFIELD (CpuAES),
594ab6a3 272 BITFIELD (CpuPCLMUL),
c0f3af97
L
273 BITFIELD (CpuFMA),
274 BITFIELD (CpuLM),
f1f8f695
L
275 BITFIELD (CpuMovbe),
276 BITFIELD (CpuEPT),
40fb9820
L
277 BITFIELD (Cpu64),
278 BITFIELD (CpuNo64),
279#ifdef CpuUnused
280 BITFIELD (CpuUnused),
281#endif
282};
283
284static bitfield opcode_modifiers[] =
285{
286 BITFIELD (D),
287 BITFIELD (W),
b6169b20 288 BITFIELD (S),
40fb9820
L
289 BITFIELD (Modrm),
290 BITFIELD (ShortForm),
291 BITFIELD (Jump),
292 BITFIELD (JumpDword),
293 BITFIELD (JumpByte),
294 BITFIELD (JumpInterSegment),
295 BITFIELD (FloatMF),
296 BITFIELD (FloatR),
297 BITFIELD (FloatD),
298 BITFIELD (Size16),
299 BITFIELD (Size32),
300 BITFIELD (Size64),
301 BITFIELD (IgnoreSize),
302 BITFIELD (DefaultSize),
303 BITFIELD (No_bSuf),
304 BITFIELD (No_wSuf),
305 BITFIELD (No_lSuf),
306 BITFIELD (No_sSuf),
307 BITFIELD (No_qSuf),
7ce189b3 308 BITFIELD (No_ldSuf),
40fb9820
L
309 BITFIELD (FWait),
310 BITFIELD (IsString),
311 BITFIELD (RegKludge),
e2ec9d29 312 BITFIELD (FirstXmm0),
c0f3af97 313 BITFIELD (Implicit1stXmm0),
ca61edf2
L
314 BITFIELD (ByteOkIntel),
315 BITFIELD (ToDword),
316 BITFIELD (ToQword),
317 BITFIELD (AddrPrefixOp0),
40fb9820
L
318 BITFIELD (IsPrefix),
319 BITFIELD (ImmExt),
320 BITFIELD (NoRex64),
321 BITFIELD (Rex64),
322 BITFIELD (Ugh),
85f10a01
MM
323 BITFIELD (Drex),
324 BITFIELD (Drexv),
325 BITFIELD (Drexc),
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),
c0f3af97 391 BITFIELD (Vex_Imm4),
40fb9820
L
392#ifdef OTUnused
393 BITFIELD (OTUnused),
394#endif
395};
396
3d4d5afa
L
397static int lineno;
398static const char *filename;
399
40fb9820
L
400static int
401compare (const void *x, const void *y)
402{
403 const bitfield *xp = (const bitfield *) x;
404 const bitfield *yp = (const bitfield *) y;
405 return xp->position - yp->position;
406}
407
40b8e679
L
408static void
409fail (const char *message, ...)
410{
411 va_list args;
412
413 va_start (args, message);
414 fprintf (stderr, _("%s: Error: "), program_name);
415 vfprintf (stderr, message, args);
416 va_end (args);
417 xexit (1);
418}
419
72ffa0fb
L
420static void
421process_copyright (FILE *fp)
422{
423 fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
22da050b
L
424/* Copyright 2007, 2008, 2009\n\
425 Free Software Foundation, Inc.\n\
72ffa0fb
L
426\n\
427 This file is part of the GNU opcodes library.\n\
428\n\
429 This library is free software; you can redistribute it and/or modify\n\
430 it under the terms of the GNU General Public License as published by\n\
431 the Free Software Foundation; either version 3, or (at your option)\n\
432 any later version.\n\
433\n\
434 It is distributed in the hope that it will be useful, but WITHOUT\n\
435 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
436 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
437 License for more details.\n\
438\n\
439 You should have received a copy of the GNU General Public License\n\
440 along with this program; if not, write to the Free Software\n\
441 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
442 MA 02110-1301, USA. */\n");
443}
444
40b8e679
L
445/* Remove leading white spaces. */
446
447static char *
448remove_leading_whitespaces (char *str)
449{
450 while (ISSPACE (*str))
451 str++;
452 return str;
453}
454
455/* Remove trailing white spaces. */
456
457static void
458remove_trailing_whitespaces (char *str)
459{
460 size_t last = strlen (str);
461
462 if (last == 0)
463 return;
464
465 do
466 {
467 last--;
468 if (ISSPACE (str [last]))
469 str[last] = '\0';
470 else
471 break;
472 }
473 while (last != 0);
474}
475
93b1ec2c 476/* Find next field separated by SEP and terminate it. Return a
40b8e679
L
477 pointer to the one after it. */
478
479static char *
c587b3f9 480next_field (char *str, char sep, char **next, char *last)
40b8e679
L
481{
482 char *p;
483
484 p = remove_leading_whitespaces (str);
93b1ec2c 485 for (str = p; *str != sep && *str != '\0'; str++);
40b8e679
L
486
487 *str = '\0';
488 remove_trailing_whitespaces (p);
489
490 *next = str + 1;
491
c587b3f9
L
492 if (p >= last)
493 abort ();
494
40b8e679
L
495 return p;
496}
497
40fb9820
L
498static void
499set_bitfield (const char *f, bitfield *array, unsigned int size)
500{
501 unsigned int i;
502
503 if (strcmp (f, "CpuSledgehammer") == 0)
504 f= "CpuK8";
7d5e4556
L
505 else if (strcmp (f, "Mmword") == 0)
506 f= "Qword";
507 else if (strcmp (f, "Oword") == 0)
508 f= "Xmmword";
40fb9820
L
509
510 for (i = 0; i < size; i++)
511 if (strcasecmp (array[i].name, f) == 0)
512 {
513 array[i].value = 1;
514 return;
515 }
516
50e8458f 517 fail (_("%s: %d: Unknown bitfield: %s\n"), filename, lineno, f);
40fb9820
L
518}
519
520static void
521output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
522 int macro, const char *comma, const char *indent)
523{
524 unsigned int i;
525
526 fprintf (table, "%s{ { ", indent);
527
528 for (i = 0; i < size - 1; i++)
529 {
530 fprintf (table, "%d, ", flags[i].value);
531 if (((i + 1) % 20) == 0)
532 {
533 /* We need \\ for macro. */
534 if (macro)
535 fprintf (table, " \\\n %s", indent);
536 else
537 fprintf (table, "\n %s", indent);
538 }
539 }
540
541 fprintf (table, "%d } }%s\n", flags[i].value, comma);
542}
543
544static void
545process_i386_cpu_flag (FILE *table, char *flag, int macro,
546 const char *comma, const char *indent)
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
L
570 if (str)
571 set_bitfield (str, flags, ARRAY_SIZE (flags));
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
597process_i386_opcode_modifier (FILE *table, char *mod)
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
L
611 if (str)
612 set_bitfield (str, modifiers, ARRAY_SIZE (modifiers));
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,
644 const char *indent)
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
L
658 if (str)
659 set_bitfield (str, types, ARRAY_SIZE (types));
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,
668 char *last)
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
739 process_i386_cpu_flag (table, cpu_flags, 0, ",", " ");
740
741 process_i386_opcode_modifier (table, opcode_modifier);
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)
750 process_i386_operand_type (table, "0", 0, "\t ");
751 break;
752 }
753
754 if (i != 0)
755 fprintf (table, ",\n ");
756
757 process_i386_operand_type (table, operand_types[i], 0,
758 "\t ");
759 }
760 fprintf (table, " } },\n");
761}
762
763struct opcode_hash_entry
764{
765 struct opcode_hash_entry *next;
766 char *name;
767 char *opcode;
768};
769
770/* Calculate the hash value of an opcode hash entry P. */
771
772static hashval_t
773opcode_hash_hash (const void *p)
774{
775 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
776 return htab_hash_string (entry->name);
777}
778
779/* Compare a string Q against an opcode hash entry P. */
780
781static int
782opcode_hash_eq (const void *p, const void *q)
783{
784 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
785 const char *name = (const char *) q;
786 return strcmp (name, entry->name) == 0;
787}
788
40b8e679 789static void
72ffa0fb 790process_i386_opcodes (FILE *table)
40b8e679 791{
3d4d5afa 792 FILE *fp;
40b8e679 793 char buf[2048];
c587b3f9
L
794 unsigned int i, j;
795 char *str, *p, *last, *name;
796 struct opcode_hash_entry **hash_slot, **entry, *next;
797 htab_t opcode_hash_table;
798 struct opcode_hash_entry **opcode_array;
799 unsigned int opcode_array_size = 1024;
40b8e679 800
3d4d5afa
L
801 filename = "i386-opc.tbl";
802 fp = fopen (filename, "r");
803
40b8e679 804 if (fp == NULL)
34edb9ad 805 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
40fb9820 806 xstrerror (errno));
40b8e679 807
c587b3f9
L
808 i = 0;
809 opcode_array = (struct opcode_hash_entry **)
810 xmalloc (sizeof (*opcode_array) * opcode_array_size);
811
812 opcode_hash_table = htab_create_alloc (16, opcode_hash_hash,
813 opcode_hash_eq, NULL,
814 xcalloc, free);
815
34edb9ad
L
816 fprintf (table, "\n/* i386 opcode table. */\n\n");
817 fprintf (table, "const template i386_optab[] =\n{\n");
40b8e679 818
c587b3f9 819 /* Put everything on opcode array. */
40b8e679
L
820 while (!feof (fp))
821 {
822 if (fgets (buf, sizeof (buf), fp) == NULL)
823 break;
824
3d4d5afa
L
825 lineno++;
826
40b8e679
L
827 p = remove_leading_whitespaces (buf);
828
829 /* Skip comments. */
830 str = strstr (p, "//");
831 if (str != NULL)
832 str[0] = '\0';
833
834 /* Remove trailing white spaces. */
835 remove_trailing_whitespaces (p);
836
837 switch (p[0])
838 {
839 case '#':
c587b3f9 840 /* Ignore comments. */
40b8e679
L
841 case '\0':
842 continue;
843 break;
844 default:
845 break;
846 }
847
848 last = p + strlen (p);
849
850 /* Find name. */
c587b3f9 851 name = next_field (p, ',', &str, last);
40b8e679 852
c587b3f9
L
853 /* Get the slot in hash table. */
854 hash_slot = (struct opcode_hash_entry **)
855 htab_find_slot_with_hash (opcode_hash_table, name,
856 htab_hash_string (name),
857 INSERT);
40b8e679 858
c587b3f9 859 if (*hash_slot == NULL)
40b8e679 860 {
c587b3f9
L
861 /* It is the new one. Put it on opcode array. */
862 if (i >= opcode_array_size)
40b8e679 863 {
c587b3f9
L
864 /* Grow the opcode array when needed. */
865 opcode_array_size += 1024;
866 opcode_array = (struct opcode_hash_entry **)
867 xrealloc (opcode_array,
868 sizeof (*opcode_array) * opcode_array_size);
40b8e679
L
869 }
870
c587b3f9
L
871 opcode_array[i] = (struct opcode_hash_entry *)
872 xmalloc (sizeof (struct opcode_hash_entry));
873 opcode_array[i]->next = NULL;
874 opcode_array[i]->name = xstrdup (name);
875 opcode_array[i]->opcode = xstrdup (str);
876 *hash_slot = opcode_array[i];
877 i++;
40b8e679 878 }
c587b3f9 879 else
40b8e679 880 {
c587b3f9
L
881 /* Append it to the existing one. */
882 entry = hash_slot;
883 while ((*entry) != NULL)
884 entry = &(*entry)->next;
885 *entry = (struct opcode_hash_entry *)
886 xmalloc (sizeof (struct opcode_hash_entry));
887 (*entry)->next = NULL;
888 (*entry)->name = (*hash_slot)->name;
889 (*entry)->opcode = xstrdup (str);
890 }
891 }
40b8e679 892
c587b3f9
L
893 /* Process opcode array. */
894 for (j = 0; j < i; j++)
895 {
896 for (next = opcode_array[j]; next; next = next->next)
897 {
898 name = next->name;
899 str = next->opcode;
900 last = str + strlen (str);
901 output_i386_opcode (table, name, str, last);
40b8e679 902 }
40b8e679
L
903 }
904
34edb9ad
L
905 fclose (fp);
906
4dffcebc 907 fprintf (table, " { NULL, 0, 0, 0, 0,\n");
40fb9820
L
908
909 process_i386_cpu_flag (table, "0", 0, ",", " ");
910
911 process_i386_opcode_modifier (table, "0");
912
913 fprintf (table, " { ");
914 process_i386_operand_type (table, "0", 0, "\t ");
915 fprintf (table, " } }\n");
916
34edb9ad 917 fprintf (table, "};\n");
40b8e679
L
918}
919
920static void
72ffa0fb 921process_i386_registers (FILE *table)
40b8e679 922{
3d4d5afa 923 FILE *fp;
40b8e679
L
924 char buf[2048];
925 char *str, *p, *last;
926 char *reg_name, *reg_type, *reg_flags, *reg_num;
a60de03c 927 char *dw2_32_num, *dw2_64_num;
40b8e679 928
3d4d5afa
L
929 filename = "i386-reg.tbl";
930 fp = fopen (filename, "r");
40b8e679 931 if (fp == NULL)
34edb9ad 932 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
40fb9820 933 xstrerror (errno));
40b8e679 934
34edb9ad
L
935 fprintf (table, "\n/* i386 register table. */\n\n");
936 fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
40b8e679
L
937
938 while (!feof (fp))
939 {
940 if (fgets (buf, sizeof (buf), fp) == NULL)
941 break;
942
3d4d5afa
L
943 lineno++;
944
40b8e679
L
945 p = remove_leading_whitespaces (buf);
946
947 /* Skip comments. */
948 str = strstr (p, "//");
949 if (str != NULL)
950 str[0] = '\0';
951
952 /* Remove trailing white spaces. */
953 remove_trailing_whitespaces (p);
954
955 switch (p[0])
956 {
957 case '#':
34edb9ad 958 fprintf (table, "%s\n", p);
40b8e679
L
959 case '\0':
960 continue;
961 break;
962 default:
963 break;
964 }
965
966 last = p + strlen (p);
967
968 /* Find reg_name. */
c587b3f9 969 reg_name = next_field (p, ',', &str, last);
40b8e679
L
970
971 /* Find reg_type. */
c587b3f9 972 reg_type = next_field (str, ',', &str, last);
40b8e679
L
973
974 /* Find reg_flags. */
c587b3f9 975 reg_flags = next_field (str, ',', &str, last);
40b8e679
L
976
977 /* Find reg_num. */
c587b3f9 978 reg_num = next_field (str, ',', &str, last);
a60de03c 979
40fb9820
L
980 fprintf (table, " { \"%s\",\n ", reg_name);
981
982 process_i386_operand_type (table, reg_type, 0, "\t");
983
a60de03c 984 /* Find 32-bit Dwarf2 register number. */
c587b3f9 985 dw2_32_num = next_field (str, ',', &str, last);
a60de03c
JB
986
987 /* Find 64-bit Dwarf2 register number. */
c587b3f9 988 dw2_64_num = next_field (str, ',', &str, last);
a60de03c
JB
989
990 fprintf (table, ",\n %s, %s, { %s, %s } },\n",
991 reg_flags, reg_num, dw2_32_num, dw2_64_num);
40b8e679
L
992 }
993
34edb9ad
L
994 fclose (fp);
995
996 fprintf (table, "};\n");
40b8e679 997
34edb9ad 998 fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
40b8e679
L
999}
1000
40fb9820
L
1001static void
1002process_i386_initializers (void)
1003{
1004 unsigned int i;
1005 FILE *fp = fopen ("i386-init.h", "w");
1006 char *init;
1007
1008 if (fp == NULL)
1009 fail (_("can't create i386-init.h, errno = %s\n"),
1010 xstrerror (errno));
1011
1012 process_copyright (fp);
1013
1014 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
1015 {
1016 fprintf (fp, "\n#define %s \\\n", cpu_flag_init[i].name);
1017 init = xstrdup (cpu_flag_init[i].init);
1018 process_i386_cpu_flag (fp, init, 1, "", " ");
1019 free (init);
1020 }
1021
1022 for (i = 0; i < ARRAY_SIZE (operand_type_init); i++)
1023 {
1024 fprintf (fp, "\n\n#define %s \\\n ", operand_type_init[i].name);
1025 init = xstrdup (operand_type_init[i].init);
1026 process_i386_operand_type (fp, init, 1, " ");
1027 free (init);
1028 }
1029 fprintf (fp, "\n");
1030
1031 fclose (fp);
1032}
1033
40b8e679
L
1034/* Program options. */
1035#define OPTION_SRCDIR 200
1036
1037struct option long_options[] =
1038{
1039 {"srcdir", required_argument, NULL, OPTION_SRCDIR},
1040 {"debug", no_argument, NULL, 'd'},
1041 {"version", no_argument, NULL, 'V'},
1042 {"help", no_argument, NULL, 'h'},
1043 {0, no_argument, NULL, 0}
1044};
1045
1046static void
1047print_version (void)
1048{
1049 printf ("%s: version 1.0\n", program_name);
1050 xexit (0);
1051}
1052
1053static void
1054usage (FILE * stream, int status)
1055{
1056 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1057 program_name);
1058 xexit (status);
1059}
1060
1061int
1062main (int argc, char **argv)
1063{
1064 extern int chdir (char *);
1065 char *srcdir = NULL;
8b40d594 1066 int c;
72ffa0fb 1067 FILE *table;
40b8e679
L
1068
1069 program_name = *argv;
1070 xmalloc_set_program_name (program_name);
1071
1072 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
1073 switch (c)
1074 {
1075 case OPTION_SRCDIR:
1076 srcdir = optarg;
1077 break;
1078 case 'V':
1079 case 'v':
1080 print_version ();
1081 break;
1082 case 'd':
1083 debug = 1;
1084 break;
1085 case 'h':
1086 case '?':
1087 usage (stderr, 0);
1088 default:
1089 case 0:
1090 break;
1091 }
1092
1093 if (optind != argc)
1094 usage (stdout, 1);
1095
1096 if (srcdir != NULL)
1097 if (chdir (srcdir) != 0)
1098 fail (_("unable to change directory to \"%s\", errno = %s\n"),
40fb9820
L
1099 srcdir, xstrerror (errno));
1100
1101 /* Check the unused bitfield in i386_cpu_flags. */
1102#ifndef CpuUnused
8b40d594
L
1103 c = CpuNumOfBits - CpuMax - 1;
1104 if (c)
1105 fail (_("%d unused bits in i386_cpu_flags.\n"), c);
40fb9820
L
1106#endif
1107
1108 /* Check the unused bitfield in i386_operand_type. */
1109#ifndef OTUnused
8b40d594
L
1110 c = OTNumOfBits - OTMax - 1;
1111 if (c)
1112 fail (_("%d unused bits in i386_operand_type.\n"), c);
40fb9820
L
1113#endif
1114
1115 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
1116 compare);
1117
1118 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
1119 sizeof (opcode_modifiers [0]), compare);
1120
1121 qsort (operand_types, ARRAY_SIZE (operand_types),
1122 sizeof (operand_types [0]), compare);
40b8e679 1123
34edb9ad
L
1124 table = fopen ("i386-tbl.h", "w");
1125 if (table == NULL)
40fb9820
L
1126 fail (_("can't create i386-tbl.h, errno = %s\n"),
1127 xstrerror (errno));
34edb9ad 1128
72ffa0fb 1129 process_copyright (table);
40b8e679 1130
72ffa0fb
L
1131 process_i386_opcodes (table);
1132 process_i386_registers (table);
40fb9820 1133 process_i386_initializers ();
40b8e679 1134
34edb9ad
L
1135 fclose (table);
1136
40b8e679
L
1137 exit (0);
1138}
This page took 0.126971 seconds and 4 git commands to generate.