OSDN Git Service

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