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