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