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