OSDN Git Service

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