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