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