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