gas/
[deliverable/binutils-gdb.git] / opcodes / i386-gen.c
CommitLineData
6f143e4d 1/* Copyright 2007, 2008 Free Software Foundation, Inc.
40b8e679 2
9b201bb5 3 This file is part of the GNU opcodes library.
40b8e679 4
9b201bb5 5 This library is free software; you can redistribute it and/or modify
40b8e679 6 it under the terms of the GNU General Public License as published by
9b201bb5
NC
7 the Free Software Foundation; either version 3, or (at your option)
8 any later version.
40b8e679 9
9b201bb5
NC
10 It is distributed in the hope that it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
13 License for more details.
40b8e679
L
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
9b201bb5
NC
17 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
18 MA 02110-1301, USA. */
40b8e679 19
40fb9820 20#include "sysdep.h"
40b8e679 21#include <stdio.h>
40b8e679
L
22#include <errno.h>
23#include "getopt.h"
24#include "libiberty.h"
25#include "safe-ctype.h"
26
27#include "i386-opc.h"
28
29#include <libintl.h>
30#define _(String) gettext (String)
31
32static const char *program_name = NULL;
33static int debug = 0;
34
40fb9820
L
35typedef struct initializer
36{
37 const char *name;
38 const char *init;
39} initializer;
40
41static initializer cpu_flag_init [] =
42{
43 { "CPU_UNKNOWN_FLAGS",
44 "unknown" },
45 { "CPU_GENERIC32_FLAGS",
46 "Cpu186|Cpu286|Cpu386" },
47 { "CPU_GENERIC64_FLAGS",
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",
3629bb00 84 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuK6|CpuK8|CpuMMX|CpuMMX2|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuLM" },
40fb9820
L
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",
3629bb00 96 "CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1" },
40fb9820 97 { "CPU_SSE4_2_FLAGS",
3629bb00 98 "CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2" },
40fb9820
L
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",
3629bb00 110 "CpuABM" },
85f10a01 111 { "CPU_SSE5_FLAGS",
3629bb00 112 "CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuSSE5"},
40fb9820
L
113};
114
115static 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",
7d5e4556 182 "Reg32|Acc|Dword" },
40fb9820 183 { "OPERAND_TYPE_ACC64",
7d5e4556 184 "Reg64|Acc|Qword" },
40fb9820
L
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
207typedef struct bitfield
208{
209 int position;
210 int value;
211 const char *name;
212} bitfield;
213
214#define BITFIELD(n) { n, 0, #n }
215
216static 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),
85f10a01 236 BITFIELD (CpuSSE5),
40fb9820
L
237 BITFIELD (Cpu3dnow),
238 BITFIELD (Cpu3dnowA),
239 BITFIELD (CpuPadLock),
240 BITFIELD (CpuSVME),
241 BITFIELD (CpuVMX),
47dd174c 242 BITFIELD (CpuSMX),
40fb9820
L
243 BITFIELD (CpuABM),
244 BITFIELD (CpuLM),
245 BITFIELD (Cpu64),
246 BITFIELD (CpuNo64),
247#ifdef CpuUnused
248 BITFIELD (CpuUnused),
249#endif
250};
251
252static 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),
7ce189b3 275 BITFIELD (No_ldSuf),
40fb9820
L
276 BITFIELD (FWait),
277 BITFIELD (IsString),
278 BITFIELD (RegKludge),
e2ec9d29 279 BITFIELD (FirstXmm0),
ca61edf2
L
280 BITFIELD (ByteOkIntel),
281 BITFIELD (ToDword),
282 BITFIELD (ToQword),
283 BITFIELD (AddrPrefixOp0),
40fb9820
L
284 BITFIELD (IsPrefix),
285 BITFIELD (ImmExt),
286 BITFIELD (NoRex64),
287 BITFIELD (Rex64),
288 BITFIELD (Ugh),
85f10a01
MM
289 BITFIELD (Drex),
290 BITFIELD (Drexv),
291 BITFIELD (Drexc),
1efbbeb4
L
292 BITFIELD (OldGcc),
293 BITFIELD (ATTMnemonic),
e1d4d893 294 BITFIELD (ATTSyntax),
5c07affc 295 BITFIELD (IntelSyntax),
40fb9820
L
296};
297
298static 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),
5c07affc 332 BITFIELD (Mem),
7d5e4556
L
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),
40fb9820
L
342#ifdef OTUnused
343 BITFIELD (OTUnused),
344#endif
345};
346
3d4d5afa
L
347static int lineno;
348static const char *filename;
349
40fb9820
L
350static int
351compare (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
40b8e679
L
358static void
359fail (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
72ffa0fb
L
370static void
371process_copyright (FILE *fp)
372{
373 fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
6f143e4d 374/* Copyright 2007, 2008 Free Software Foundation, Inc.\n\
72ffa0fb
L
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
40b8e679
L
394/* Remove leading white spaces. */
395
396static char *
397remove_leading_whitespaces (char *str)
398{
399 while (ISSPACE (*str))
400 str++;
401 return str;
402}
403
404/* Remove trailing white spaces. */
405
406static void
407remove_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
93b1ec2c 425/* Find next field separated by SEP and terminate it. Return a
40b8e679
L
426 pointer to the one after it. */
427
428static char *
93b1ec2c 429next_field (char *str, char sep, char **next)
40b8e679
L
430{
431 char *p;
432
433 p = remove_leading_whitespaces (str);
93b1ec2c 434 for (str = p; *str != sep && *str != '\0'; str++);
40b8e679
L
435
436 *str = '\0';
437 remove_trailing_whitespaces (p);
438
439 *next = str + 1;
440
441 return p;
442}
443
40fb9820
L
444static void
445set_bitfield (const char *f, bitfield *array, unsigned int size)
446{
447 unsigned int i;
448
449 if (strcmp (f, "CpuSledgehammer") == 0)
450 f= "CpuK8";
7d5e4556
L
451 else if (strcmp (f, "Mmword") == 0)
452 f= "Qword";
453 else if (strcmp (f, "Oword") == 0)
454 f= "Xmmword";
40fb9820
L
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
50e8458f 463 fail (_("%s: %d: Unknown bitfield: %s\n"), filename, lineno, f);
40fb9820
L
464}
465
466static void
467output_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
490static void
491process_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
525static void
526output_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
542static void
543process_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
564static void
565output_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
588static void
589process_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
40b8e679 612static void
72ffa0fb 613process_i386_opcodes (FILE *table)
40b8e679 614{
3d4d5afa 615 FILE *fp;
40b8e679
L
616 char buf[2048];
617 unsigned int i;
618 char *str, *p, *last;
619 char *name, *operands, *base_opcode, *extension_opcode;
4dffcebc 620 char *opcode_length;
40b8e679
L
621 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
622
3d4d5afa
L
623 filename = "i386-opc.tbl";
624 fp = fopen (filename, "r");
625
40b8e679 626 if (fp == NULL)
34edb9ad 627 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
40fb9820 628 xstrerror (errno));
40b8e679 629
34edb9ad
L
630 fprintf (table, "\n/* i386 opcode table. */\n\n");
631 fprintf (table, "const template i386_optab[] =\n{\n");
40b8e679
L
632
633 while (!feof (fp))
634 {
635 if (fgets (buf, sizeof (buf), fp) == NULL)
636 break;
637
3d4d5afa
L
638 lineno++;
639
40b8e679
L
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 '#':
34edb9ad 653 fprintf (table, "%s\n", p);
40b8e679
L
654 case '\0':
655 continue;
656 break;
657 default:
658 break;
659 }
660
661 last = p + strlen (p);
662
663 /* Find name. */
93b1ec2c 664 name = next_field (p, ',', &str);
40b8e679
L
665
666 if (str >= last)
667 abort ();
668
669 /* Find number of operands. */
93b1ec2c 670 operands = next_field (str, ',', &str);
40b8e679
L
671
672 if (str >= last)
673 abort ();
674
675 /* Find base_opcode. */
93b1ec2c 676 base_opcode = next_field (str, ',', &str);
40b8e679
L
677
678 if (str >= last)
679 abort ();
680
681 /* Find extension_opcode. */
93b1ec2c 682 extension_opcode = next_field (str, ',', &str);
40b8e679 683
4dffcebc
L
684 if (str >= last)
685 abort ();
686
687 /* Find opcode_length. */
688 opcode_length = next_field (str, ',', &str);
689
40b8e679
L
690 if (str >= last)
691 abort ();
692
693 /* Find cpu_flags. */
93b1ec2c 694 cpu_flags = next_field (str, ',', &str);
40b8e679
L
695
696 if (str >= last)
697 abort ();
698
699 /* Find opcode_modifier. */
93b1ec2c 700 opcode_modifier = next_field (str, ',', &str);
40b8e679
L
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
93b1ec2c 739 operand_types [i] = next_field (str, ',', &str);
40b8e679
L
740 if (*operand_types[i] == '0')
741 {
742 if (i != 0)
743 operand_types[i] = NULL;
744 break;
745 }
746 }
747
4dffcebc
L
748 fprintf (table, " { \"%s\", %s, %s, %s, %s,\n",
749 name, operands, base_opcode, extension_opcode,
750 opcode_length);
40fb9820
L
751
752 process_i386_cpu_flag (table, cpu_flags, 0, ",", " ");
40b8e679 753
40fb9820 754 process_i386_opcode_modifier (table, opcode_modifier);
40b8e679 755
34edb9ad 756 fprintf (table, " { ");
40b8e679
L
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)
40fb9820 764 process_i386_operand_type (table, "0", 0, "\t ");
40b8e679
L
765 break;
766 }
767
768 if (i != 0)
34edb9ad 769 fprintf (table, ",\n ");
40b8e679 770
40fb9820
L
771 process_i386_operand_type (table, operand_types[i], 0,
772 "\t ");
40b8e679 773 }
34edb9ad 774 fprintf (table, " } },\n");
40b8e679
L
775 }
776
34edb9ad
L
777 fclose (fp);
778
4dffcebc 779 fprintf (table, " { NULL, 0, 0, 0, 0,\n");
40fb9820
L
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
34edb9ad 789 fprintf (table, "};\n");
40b8e679
L
790}
791
792static void
72ffa0fb 793process_i386_registers (FILE *table)
40b8e679 794{
3d4d5afa 795 FILE *fp;
40b8e679
L
796 char buf[2048];
797 char *str, *p, *last;
798 char *reg_name, *reg_type, *reg_flags, *reg_num;
799
3d4d5afa
L
800 filename = "i386-reg.tbl";
801 fp = fopen (filename, "r");
40b8e679 802 if (fp == NULL)
34edb9ad 803 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
40fb9820 804 xstrerror (errno));
40b8e679 805
34edb9ad
L
806 fprintf (table, "\n/* i386 register table. */\n\n");
807 fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
40b8e679
L
808
809 while (!feof (fp))
810 {
811 if (fgets (buf, sizeof (buf), fp) == NULL)
812 break;
813
3d4d5afa
L
814 lineno++;
815
40b8e679
L
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 '#':
34edb9ad 829 fprintf (table, "%s\n", p);
40b8e679
L
830 case '\0':
831 continue;
832 break;
833 default:
834 break;
835 }
836
837 last = p + strlen (p);
838
839 /* Find reg_name. */
93b1ec2c 840 reg_name = next_field (p, ',', &str);
40b8e679
L
841
842 if (str >= last)
843 abort ();
844
845 /* Find reg_type. */
93b1ec2c 846 reg_type = next_field (str, ',', &str);
40b8e679
L
847
848 if (str >= last)
849 abort ();
850
851 /* Find reg_flags. */
93b1ec2c 852 reg_flags = next_field (str, ',', &str);
40b8e679
L
853
854 if (str >= last)
855 abort ();
856
857 /* Find reg_num. */
93b1ec2c 858 reg_num = next_field (str, ',', &str);
40b8e679 859
40fb9820
L
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);
40b8e679
L
865 }
866
34edb9ad
L
867 fclose (fp);
868
869 fprintf (table, "};\n");
40b8e679 870
34edb9ad 871 fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
40b8e679
L
872}
873
40fb9820
L
874static void
875process_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
40b8e679
L
907/* Program options. */
908#define OPTION_SRCDIR 200
909
910struct 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
919static void
920print_version (void)
921{
922 printf ("%s: version 1.0\n", program_name);
923 xexit (0);
924}
925
926static void
927usage (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
934int
935main (int argc, char **argv)
936{
937 extern int chdir (char *);
938 char *srcdir = NULL;
8b40d594 939 int c;
72ffa0fb 940 FILE *table;
40b8e679
L
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"),
40fb9820
L
972 srcdir, xstrerror (errno));
973
974 /* Check the unused bitfield in i386_cpu_flags. */
975#ifndef CpuUnused
8b40d594
L
976 c = CpuNumOfBits - CpuMax - 1;
977 if (c)
978 fail (_("%d unused bits in i386_cpu_flags.\n"), c);
40fb9820
L
979#endif
980
981 /* Check the unused bitfield in i386_operand_type. */
982#ifndef OTUnused
8b40d594
L
983 c = OTNumOfBits - OTMax - 1;
984 if (c)
985 fail (_("%d unused bits in i386_operand_type.\n"), c);
40fb9820
L
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);
40b8e679 996
34edb9ad
L
997 table = fopen ("i386-tbl.h", "w");
998 if (table == NULL)
40fb9820
L
999 fail (_("can't create i386-tbl.h, errno = %s\n"),
1000 xstrerror (errno));
34edb9ad 1001
72ffa0fb 1002 process_copyright (table);
40b8e679 1003
72ffa0fb
L
1004 process_i386_opcodes (table);
1005 process_i386_registers (table);
40fb9820 1006 process_i386_initializers ();
40b8e679 1007
34edb9ad
L
1008 fclose (table);
1009
40b8e679
L
1010 exit (0);
1011}
This page took 0.091276 seconds and 4 git commands to generate.