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