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