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