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