summaryrefslogtreecommitdiffstats
path: root/src/libcpu/i386_parse.y
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcpu/i386_parse.y')
-rw-r--r--src/libcpu/i386_parse.y1687
1 files changed, 0 insertions, 1687 deletions
diff --git a/src/libcpu/i386_parse.y b/src/libcpu/i386_parse.y
deleted file mode 100644
index 689ba222..00000000
--- a/src/libcpu/i386_parse.y
+++ /dev/null
@@ -1,1687 +0,0 @@
-%{
-/* Parser for i386 CPU description.
- Copyright (C) 2004, 2005, 2007, 2008, 2009 Red Hat, Inc.
- Written by Ulrich Drepper <drepper@redhat.com>, 2004.
-
- This file is free software; you can redistribute it and/or modify
- it under the terms of either
-
- * the GNU Lesser General Public License as published by the Free
- Software Foundation; either version 3 of the License, or (at
- your option) any later version
-
- or
-
- * the GNU General Public License as published by the Free
- Software Foundation; either version 2 of the License, or (at
- your option) any later version
-
- or both in parallel, as here.
-
- elfutils is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received copies of the GNU General Public License and
- the GNU Lesser General Public License along with this program. If
- not, see <http://www.gnu.org/licenses/>. */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <assert.h>
-#include <ctype.h>
-#include <errno.h>
-#include <error.h>
-#include <inttypes.h>
-#include <libintl.h>
-#include <math.h>
-#include <obstack.h>
-#include <search.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/param.h>
-
-#include <system.h>
-
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
-/* The error handler. */
-static void yyerror (const char *s);
-
-extern int yylex (void);
-extern int i386_lineno;
-extern char *infname;
-
-
-struct known_bitfield
-{
- char *name;
- unsigned long int bits;
- int tmp;
-};
-
-
-struct bitvalue
-{
- enum bittype { zeroone, field, failure } type;
- union
- {
- unsigned int value;
- struct known_bitfield *field;
- };
- struct bitvalue *next;
-};
-
-
-struct argname
-{
- enum nametype { string, nfield } type;
- union
- {
- char *str;
- struct known_bitfield *field;
- };
- struct argname *next;
-};
-
-
-struct argument
-{
- struct argname *name;
- struct argument *next;
-};
-
-
-struct instruction
-{
- /* The byte encoding. */
- struct bitvalue *bytes;
-
- /* Prefix possible. */
- int repe;
- int rep;
-
- /* Mnemonic. */
- char *mnemonic;
-
- /* Suffix. */
- enum { suffix_none = 0, suffix_w, suffix_w0, suffix_W, suffix_tttn,
- suffix_w1, suffix_W1, suffix_D } suffix;
-
- /* Flag set if modr/m is used. */
- int modrm;
-
- /* Operands. */
- struct operand
- {
- char *fct;
- char *str;
- int off1;
- int off2;
- int off3;
- } operands[3];
-
- struct instruction *next;
-};
-
-
-struct synonym
-{
- char *from;
- char *to;
-};
-
-
-struct suffix
-{
- char *name;
- int idx;
-};
-
-
-struct argstring
-{
- char *str;
- int idx;
- int off;
-};
-
-
-static struct known_bitfield ax_reg =
- {
- .name = "ax", .bits = 0, .tmp = 0
- };
-
-static struct known_bitfield dx_reg =
- {
- .name = "dx", .bits = 0, .tmp = 0
- };
-
-static struct known_bitfield di_reg =
- {
- .name = "es_di", .bits = 0, .tmp = 0
- };
-
-static struct known_bitfield si_reg =
- {
- .name = "ds_si", .bits = 0, .tmp = 0
- };
-
-static struct known_bitfield bx_reg =
- {
- .name = "ds_bx", .bits = 0, .tmp = 0
- };
-
-
-static int bitfield_compare (const void *p1, const void *p2);
-static void new_bitfield (char *name, unsigned long int num);
-static void check_bits (struct bitvalue *value);
-static int check_duplicates (struct bitvalue *val);
-static int check_argsdef (struct bitvalue *bitval, struct argument *args);
-static int check_bitsused (struct bitvalue *bitval,
- struct known_bitfield *suffix,
- struct argument *args);
-static struct argname *combine (struct argname *name);
-static void fillin_arg (struct bitvalue *bytes, struct argname *name,
- struct instruction *instr, int n);
-static void find_numbers (void);
-static int compare_syn (const void *p1, const void *p2);
-static int compare_suf (const void *p1, const void *p2);
-static void instrtable_out (void);
-#if 0
-static void create_mnemonic_table (void);
-#endif
-
-static void *bitfields;
-static struct instruction *instructions;
-static size_t ninstructions;
-static void *synonyms;
-static void *suffixes;
-static int nsuffixes;
-static void *mnemonics;
-size_t nmnemonics;
-extern FILE *outfile;
-
-/* Number of bits used mnemonics. */
-#if 0
-static size_t best_mnemonic_bits;
-#endif
-%}
-
-%union {
- unsigned long int num;
- char *str;
- char ch;
- struct known_bitfield *field;
- struct bitvalue *bit;
- struct argname *name;
- struct argument *arg;
-}
-
-%token kMASK
-%token kPREFIX
-%token kSUFFIX
-%token kSYNONYM
-%token <str> kID
-%token <num> kNUMBER
-%token kPERCPERC
-%token <str> kBITFIELD
-%token <ch> kCHAR
-%token kSPACE
-
-%type <bit> bit byte bytes
-%type <field> bitfieldopt
-%type <name> argcomp arg
-%type <arg> args optargs
-
-%defines
-
-%%
-
-spec: masks kPERCPERC '\n' instrs
- {
- if (error_message_count != 0)
- error (EXIT_FAILURE, 0,
- "terminated due to previous error");
-
- instrtable_out ();
- }
- ;
-
-masks: masks '\n' mask
- | mask
- ;
-
-mask: kMASK kBITFIELD kNUMBER
- { new_bitfield ($2, $3); }
- | kPREFIX kBITFIELD
- { new_bitfield ($2, -1); }
- | kSUFFIX kBITFIELD
- { new_bitfield ($2, -2); }
- | kSYNONYM kBITFIELD kBITFIELD
- {
- struct synonym *newp = xmalloc (sizeof (*newp));
- newp->from = $2;
- newp->to = $3;
- if (tfind (newp, &synonyms, compare_syn) != NULL)
- error (0, 0,
- "%d: duplicate definition for synonym '%s'",
- i386_lineno, $2);
- else if (tsearch ( newp, &synonyms, compare_syn) == NULL)
- error (EXIT_FAILURE, 0, "tsearch");
- }
- |
- ;
-
-instrs: instrs '\n' instr
- | instr
- ;
-
-instr: bytes ':' bitfieldopt kID bitfieldopt optargs
- {
- if ($3 != NULL && strcmp ($3->name, "RE") != 0
- && strcmp ($3->name, "R") != 0)
- {
- error (0, 0, "%d: only 'R' and 'RE' prefix allowed",
- i386_lineno - 1);
- }
- if (check_duplicates ($1) == 0
- && check_argsdef ($1, $6) == 0
- && check_bitsused ($1, $5, $6) == 0)
- {
- struct instruction *newp = xcalloc (sizeof (*newp),
- 1);
- if ($3 != NULL)
- {
- if (strcmp ($3->name, "RE") == 0)
- newp->repe = 1;
- else if (strcmp ($3->name, "R") == 0)
- newp->rep = 1;
- }
-
- newp->bytes = $1;
- newp->mnemonic = $4;
- if (newp->mnemonic != (void *) -1l
- && tfind ($4, &mnemonics,
- (comparison_fn_t) strcmp) == NULL)
- {
- if (tsearch ($4, &mnemonics,
- (comparison_fn_t) strcmp) == NULL)
- error (EXIT_FAILURE, errno, "tsearch");
- ++nmnemonics;
- }
-
- if ($5 != NULL)
- {
- if (strcmp ($5->name, "w") == 0)
- newp->suffix = suffix_w;
- else if (strcmp ($5->name, "w0") == 0)
- newp->suffix = suffix_w0;
- else if (strcmp ($5->name, "tttn") == 0)
- newp->suffix = suffix_tttn;
- else if (strcmp ($5->name, "w1") == 0)
- newp->suffix = suffix_w1;
- else if (strcmp ($5->name, "W") == 0)
- newp->suffix = suffix_W;
- else if (strcmp ($5->name, "W1") == 0)
- newp->suffix = suffix_W1;
- else if (strcmp ($5->name, "D") == 0)
- newp->suffix = suffix_D;
- else
- error (EXIT_FAILURE, 0,
- "%s: %d: unknown suffix '%s'",
- infname, i386_lineno - 1, $5->name);
-
- struct suffix search = { .name = $5->name };
- if (tfind (&search, &suffixes, compare_suf)
- == NULL)
- {
- struct suffix *ns = xmalloc (sizeof (*ns));
- ns->name = $5->name;
- ns->idx = ++nsuffixes;
- if (tsearch (ns, &suffixes, compare_suf)
- == NULL)
- error (EXIT_FAILURE, errno, "tsearch");
- }
- }
-
- struct argument *args = $6;
- int n = 0;
- while (args != NULL)
- {
- fillin_arg ($1, args->name, newp, n);
-
- args = args->next;
- ++n;
- }
-
- newp->next = instructions;
- instructions = newp;
- ++ninstructions;
- }
- }
- |
- ;
-
-bitfieldopt: kBITFIELD
- {
- struct known_bitfield search;
- search.name = $1;
- struct known_bitfield **res;
- res = tfind (&search, &bitfields, bitfield_compare);
- if (res == NULL)
- {
- error (0, 0, "%d: unknown bitfield '%s'",
- i386_lineno, search.name);
- $$ = NULL;
- }
- else
- $$ = *res;
- }
- |
- { $$ = NULL; }
- ;
-
-bytes: bytes ',' byte
- {
- check_bits ($3);
-
- struct bitvalue *runp = $1;
- while (runp->next != NULL)
- runp = runp->next;
- runp->next = $3;
- $$ = $1;
- }
- | byte
- {
- check_bits ($1);
- $$ = $1;
- }
- ;
-
-byte: byte bit
- {
- struct bitvalue *runp = $1;
- while (runp->next != NULL)
- runp = runp->next;
- runp->next = $2;
- $$ = $1;
- }
- | bit
- { $$ = $1; }
- ;
-
-bit: '0'
- {
- $$ = xmalloc (sizeof (struct bitvalue));
- $$->type = zeroone;
- $$->value = 0;
- $$->next = NULL;
- }
- | '1'
- {
- $$ = xmalloc (sizeof (struct bitvalue));
- $$->type = zeroone;
- $$->value = 1;
- $$->next = NULL;
- }
- | kBITFIELD
- {
- $$ = xmalloc (sizeof (struct bitvalue));
- struct known_bitfield search;
- search.name = $1;
- struct known_bitfield **res;
- res = tfind (&search, &bitfields, bitfield_compare);
- if (res == NULL)
- {
- error (0, 0, "%d: unknown bitfield '%s'",
- i386_lineno, search.name);
- $$->type = failure;
- }
- else
- {
- $$->type = field;
- $$->field = *res;
- }
- $$->next = NULL;
- }
- ;
-
-optargs: kSPACE args
- { $$ = $2; }
- |
- { $$ = NULL; }
- ;
-
-args: args ',' arg
- {
- struct argument *runp = $1;
- while (runp->next != NULL)
- runp = runp->next;
- runp->next = xmalloc (sizeof (struct argument));
- runp->next->name = combine ($3);
- runp->next->next = NULL;
- $$ = $1;
- }
- | arg
- {
- $$ = xmalloc (sizeof (struct argument));
- $$->name = combine ($1);
- $$->next = NULL;
- }
- ;
-
-arg: arg argcomp
- {
- struct argname *runp = $1;
- while (runp->next != NULL)
- runp = runp->next;
- runp->next = $2;
- $$ = $1;
- }
- | argcomp
- { $$ = $1; }
- ;
-argcomp: kBITFIELD
- {
- $$ = xmalloc (sizeof (struct argname));
- $$->type = nfield;
- $$->next = NULL;
-
- struct known_bitfield search;
- search.name = $1;
- struct known_bitfield **res;
- res = tfind (&search, &bitfields, bitfield_compare);
- if (res == NULL)
- {
- if (strcmp ($1, "ax") == 0)
- $$->field = &ax_reg;
- else if (strcmp ($1, "dx") == 0)
- $$->field = &dx_reg;
- else if (strcmp ($1, "es_di") == 0)
- $$->field = &di_reg;
- else if (strcmp ($1, "ds_si") == 0)
- $$->field = &si_reg;
- else if (strcmp ($1, "ds_bx") == 0)
- $$->field = &bx_reg;
- else
- {
- error (0, 0, "%d: unknown bitfield '%s'",
- i386_lineno, search.name);
- $$->field = NULL;
- }
- }
- else
- $$->field = *res;
- }
- | kCHAR
- {
- $$ = xmalloc (sizeof (struct argname));
- $$->type = string;
- $$->next = NULL;
- $$->str = xmalloc (2);
- $$->str[0] = $1;
- $$->str[1] = '\0';
- }
- | kID
- {
- $$ = xmalloc (sizeof (struct argname));
- $$->type = string;
- $$->next = NULL;
- $$->str = $1;
- }
- | ':'
- {
- $$ = xmalloc (sizeof (struct argname));
- $$->type = string;
- $$->next = NULL;
- $$->str = xmalloc (2);
- $$->str[0] = ':';
- $$->str[1] = '\0';
- }
- ;
-
-%%
-
-static void
-yyerror (const char *s)
-{
- error (0, 0, gettext ("while reading i386 CPU description: %s at line %d"),
- gettext (s), i386_lineno);
-}
-
-
-static int
-bitfield_compare (const void *p1, const void *p2)
-{
- struct known_bitfield *f1 = (struct known_bitfield *) p1;
- struct known_bitfield *f2 = (struct known_bitfield *) p2;
-
- return strcmp (f1->name, f2->name);
-}
-
-
-static void
-new_bitfield (char *name, unsigned long int num)
-{
- struct known_bitfield *newp = xmalloc (sizeof (struct known_bitfield));
- newp->name = name;
- newp->bits = num;
- newp->tmp = 0;
-
- if (tfind (newp, &bitfields, bitfield_compare) != NULL)
- {
- error (0, 0, "%d: duplicated definition of bitfield '%s'",
- i386_lineno, name);
- free (name);
- return;
- }
-
- if (tsearch (newp, &bitfields, bitfield_compare) == NULL)
- error (EXIT_FAILURE, errno, "%d: cannot insert new bitfield '%s'",
- i386_lineno, name);
-}
-
-
-/* Check that the number of bits is a multiple of 8. */
-static void
-check_bits (struct bitvalue *val)
-{
- struct bitvalue *runp = val;
- unsigned int total = 0;
-
- while (runp != NULL)
- {
- if (runp->type == zeroone)
- ++total;
- else if (runp->field == NULL)
- /* No sense doing anything, the field is not known. */
- return;
- else
- total += runp->field->bits;
-
- runp = runp->next;
- }
-
- if (total % 8 != 0)
- {
- struct obstack os;
- obstack_init (&os);
-
- while (val != NULL)
- {
- if (val->type == zeroone)
- obstack_printf (&os, "%u", val->value);
- else
- obstack_printf (&os, "{%s}", val->field->name);
- val = val->next;
- }
- obstack_1grow (&os, '\0');
-
- error (0, 0, "%d: field '%s' not a multiple of 8 bits in size",
- i386_lineno, (char *) obstack_finish (&os));
-
- obstack_free (&os, NULL);
- }
-}
-
-
-static int
-check_duplicates (struct bitvalue *val)
-{
- static int testcnt;
- ++testcnt;
-
- int result = 0;
- while (val != NULL)
- {
- if (val->type == field && val->field != NULL)
- {
- if (val->field->tmp == testcnt)
- {
- error (0, 0, "%d: bitfield '%s' used more than once",
- i386_lineno - 1, val->field->name);
- result = 1;
- }
- val->field->tmp = testcnt;
- }
-
- val = val->next;
- }
-
- return result;
-}
-
-
-static int
-check_argsdef (struct bitvalue *bitval, struct argument *args)
-{
- int result = 0;
-
- while (args != NULL)
- {
- for (struct argname *name = args->name; name != NULL; name = name->next)
- if (name->type == nfield && name->field != NULL
- && name->field != &ax_reg && name->field != &dx_reg
- && name->field != &di_reg && name->field != &si_reg
- && name->field != &bx_reg)
- {
- struct bitvalue *runp = bitval;
-
- while (runp != NULL)
- if (runp->type == field && runp->field == name->field)
- break;
- else
- runp = runp->next;
-
- if (runp == NULL)
- {
- error (0, 0, "%d: unknown bitfield '%s' used in output format",
- i386_lineno - 1, name->field->name);
- result = 1;
- }
- }
-
- args = args->next;
- }
-
- return result;
-}
-
-
-static int
-check_bitsused (struct bitvalue *bitval, struct known_bitfield *suffix,
- struct argument *args)
-{
- int result = 0;
-
- while (bitval != NULL)
- {
- if (bitval->type == field && bitval->field != NULL
- && bitval->field != suffix
- /* {w} is handled special. */
- && strcmp (bitval->field->name, "w") != 0)
- {
- struct argument *runp;
- for (runp = args; runp != NULL; runp = runp->next)
- {
- struct argname *name = runp->name;
-
- while (name != NULL)
- if (name->type == nfield && name->field == bitval->field)
- break;
- else
- name = name->next;
-
- if (name != NULL)
- break;
- }
-
-#if 0
- if (runp == NULL)
- {
- error (0, 0, "%d: bitfield '%s' not used",
- i386_lineno - 1, bitval->field->name);
- result = 1;
- }
-#endif
- }
-
- bitval = bitval->next;
- }
-
- return result;
-}
-
-
-static struct argname *
-combine (struct argname *name)
-{
- struct argname *last_str = NULL;
- for (struct argname *runp = name; runp != NULL; runp = runp->next)
- {
- if (runp->type == string)
- {
- if (last_str == NULL)
- last_str = runp;
- else
- {
- last_str->str = xrealloc (last_str->str,
- strlen (last_str->str)
- + strlen (runp->str) + 1);
- strcat (last_str->str, runp->str);
- last_str->next = runp->next;
- }
- }
- else
- last_str = NULL;
- }
- return name;
-}
-
-
-#define obstack_grow_str(ob, str) obstack_grow (ob, str, strlen (str))
-
-
-static void
-fillin_arg (struct bitvalue *bytes, struct argname *name,
- struct instruction *instr, int n)
-{
- static struct obstack ob;
- static int initialized;
- if (! initialized)
- {
- initialized = 1;
- obstack_init (&ob);
- }
-
- struct argname *runp = name;
- int cnt = 0;
- while (runp != NULL)
- {
- /* We ignore strings in the function name. */
- if (runp->type == string)
- {
- if (instr->operands[n].str != NULL)
- error (EXIT_FAILURE, 0,
- "%d: cannot have more than one string parameter",
- i386_lineno - 1);
-
- instr->operands[n].str = runp->str;
- }
- else
- {
- assert (runp->type == nfield);
-
- /* Construct the function name. */
- if (cnt++ > 0)
- obstack_1grow (&ob, '$');
-
- if (runp->field == NULL)
- /* Add some string which contains invalid characters. */
- obstack_grow_str (&ob, "!!!INVALID!!!");
- else
- {
- char *fieldname = runp->field->name;
-
- struct synonym search = { .from = fieldname };
-
- struct synonym **res = tfind (&search, &synonyms, compare_syn);
- if (res != NULL)
- fieldname = (*res)->to;
-
- obstack_grow_str (&ob, fieldname);
- }
-
- /* Now compute the bit offset of the field. */
- struct bitvalue *b = bytes;
- int bitoff = 0;
- if (runp->field != NULL)
- while (b != NULL)
- {
- if (b->type == field && b->field != NULL)
- {
- if (strcmp (b->field->name, runp->field->name) == 0)
- break;
- bitoff += b->field->bits;
- }
- else
- ++bitoff;
-
- b = b->next;
- }
- if (instr->operands[n].off1 == 0)
- instr->operands[n].off1 = bitoff;
- else if (instr->operands[n].off2 == 0)
- instr->operands[n].off2 = bitoff;
- else if (instr->operands[n].off3 == 0)
- instr->operands[n].off3 = bitoff;
- else
- error (EXIT_FAILURE, 0,
- "%d: cannot have more than three fields in parameter",
- i386_lineno - 1);
-
- if (runp->field != NULL
- && strncasecmp (runp->field->name, "mod", 3) == 0)
- instr->modrm = 1;
- }
-
- runp = runp->next;
- }
- if (obstack_object_size (&ob) == 0)
- obstack_grow_str (&ob, "string");
- obstack_1grow (&ob, '\0');
- char *fct = obstack_finish (&ob);
-
- instr->operands[n].fct = fct;
-}
-
-
-#if 0
-static void
-nameout (const void *nodep, VISIT value, int level)
-{
- if (value == leaf || value == postorder)
- printf (" %s\n", *(const char **) nodep);
-}
-#endif
-
-
-static int
-compare_argstring (const void *p1, const void *p2)
-{
- const struct argstring *a1 = (const struct argstring *) p1;
- const struct argstring *a2 = (const struct argstring *) p2;
-
- return strcmp (a1->str, a2->str);
-}
-
-
-static int maxoff[3][3];
-static int minoff[3][3] = { { 1000, 1000, 1000 },
- { 1000, 1000, 1000 },
- { 1000, 1000, 1000 } };
-static int nbitoff[3][3];
-static void *fct_names[3];
-static int nbitfct[3];
-static int nbitsuf;
-static void *strs[3];
-static int nbitstr[3];
-static int total_bits = 2; // Already counted the rep/repe bits.
-
-static void
-find_numbers (void)
-{
- int nfct_names[3] = { 0, 0, 0 };
- int nstrs[3] = { 0, 0, 0 };
-
- /* We reverse the order of the instruction list while processing it.
- Later phases need it in the order in which the input file has
- them. */
- struct instruction *reversed = NULL;
-
- struct instruction *runp = instructions;
- while (runp != NULL)
- {
- for (int i = 0; i < 3; ++i)
- if (runp->operands[i].fct != NULL)
- {
- struct argstring search = { .str = runp->operands[i].fct };
- if (tfind (&search, &fct_names[i], compare_argstring) == NULL)
- {
- struct argstring *newp = xmalloc (sizeof (*newp));
- newp->str = runp->operands[i].fct;
- newp->idx = 0;
- if (tsearch (newp, &fct_names[i], compare_argstring) == NULL)
- error (EXIT_FAILURE, errno, "tsearch");
- ++nfct_names[i];
- }
-
- if (runp->operands[i].str != NULL)
- {
- search.str = runp->operands[i].str;
- if (tfind (&search, &strs[i], compare_argstring) == NULL)
- {
- struct argstring *newp = xmalloc (sizeof (*newp));
- newp->str = runp->operands[i].str;
- newp->idx = 0;
- if (tsearch (newp, &strs[i], compare_argstring) == NULL)
- error (EXIT_FAILURE, errno, "tsearch");
- ++nstrs[i];
- }
- }
-
- maxoff[i][0] = MAX (maxoff[i][0], runp->operands[i].off1);
- maxoff[i][1] = MAX (maxoff[i][1], runp->operands[i].off2);
- maxoff[i][2] = MAX (maxoff[i][2], runp->operands[i].off3);
-
- if (runp->operands[i].off1 > 0)
- minoff[i][0] = MIN (minoff[i][0], runp->operands[i].off1);
- if (runp->operands[i].off2 > 0)
- minoff[i][1] = MIN (minoff[i][1], runp->operands[i].off2);
- if (runp->operands[i].off3 > 0)
- minoff[i][2] = MIN (minoff[i][2], runp->operands[i].off3);
- }
-
- struct instruction *old = runp;
- runp = runp->next;
-
- old->next = reversed;
- reversed = old;
- }
- instructions = reversed;
-
- int d;
- int c;
- for (int i = 0; i < 3; ++i)
- {
- // printf ("min1 = %d, min2 = %d, min3 = %d\n", minoff[i][0], minoff[i][1], minoff[i][2]);
- // printf ("max1 = %d, max2 = %d, max3 = %d\n", maxoff[i][0], maxoff[i][1], maxoff[i][2]);
-
- if (minoff[i][0] == 1000)
- nbitoff[i][0] = 0;
- else
- {
- nbitoff[i][0] = 1;
- d = maxoff[i][0] - minoff[i][0];
- c = 1;
- while (c < d)
- {
- ++nbitoff[i][0];
- c *= 2;
- }
- total_bits += nbitoff[i][0];
- }
-
- if (minoff[i][1] == 1000)
- nbitoff[i][1] = 0;
- else
- {
- nbitoff[i][1] = 1;
- d = maxoff[i][1] - minoff[i][1];
- c = 1;
- while (c < d)
- {
- ++nbitoff[i][1];
- c *= 2;
- }
- total_bits += nbitoff[i][1];
- }
-
- if (minoff[i][2] == 1000)
- nbitoff[i][2] = 0;
- else
- {
- nbitoff[i][2] = 1;
- d = maxoff[i][2] - minoff[i][2];
- c = 1;
- while (c < d)
- {
- ++nbitoff[i][2];
- c *= 2;
- }
- total_bits += nbitoff[i][2];
- }
- // printf ("off1 = %d, off2 = %d, off3 = %d\n", nbitoff[i][0], nbitoff[i][1], nbitoff[i][2]);
-
- nbitfct[i] = 1;
- d = nfct_names[i];
- c = 1;
- while (c < d)
- {
- ++nbitfct[i];
- c *= 2;
- }
- total_bits += nbitfct[i];
- // printf ("%d fct[%d], %d bits\n", nfct_names[i], i, nbitfct[i]);
-
- if (nstrs[i] != 0)
- {
- nbitstr[i] = 1;
- d = nstrs[i];
- c = 1;
- while (c < d)
- {
- ++nbitstr[i];
- c *= 2;
- }
- total_bits += nbitstr[i];
- }
-
- // twalk (fct_names[i], nameout);
- }
-
- nbitsuf = 0;
- d = nsuffixes;
- c = 1;
- while (c < d)
- {
- ++nbitsuf;
- c *= 2;
- }
- total_bits += nbitsuf;
- // printf ("%d suffixes, %d bits\n", nsuffixes, nbitsuf);
-}
-
-
-static int
-compare_syn (const void *p1, const void *p2)
-{
- const struct synonym *s1 = (const struct synonym *) p1;
- const struct synonym *s2 = (const struct synonym *) p2;
-
- return strcmp (s1->from, s2->from);
-}
-
-
-static int
-compare_suf (const void *p1, const void *p2)
-{
- const struct suffix *s1 = (const struct suffix *) p1;
- const struct suffix *s2 = (const struct suffix *) p2;
-
- return strcmp (s1->name, s2->name);
-}
-
-
-static int count_op_str;
-static int off_op_str;
-static void
-print_op_str (const void *nodep, VISIT value,
- int level __attribute__ ((unused)))
-{
- if (value == leaf || value == postorder)
- {
- const char *str = (*(struct argstring **) nodep)->str;
- fprintf (outfile, "%s\n \"%s",
- count_op_str == 0 ? "" : "\\0\"", str);
- (*(struct argstring **) nodep)->idx = ++count_op_str;
- (*(struct argstring **) nodep)->off = off_op_str;
- off_op_str += strlen (str) + 1;
- }
-}
-
-
-static void
-print_op_str_idx (const void *nodep, VISIT value,
- int level __attribute__ ((unused)))
-{
- if (value == leaf || value == postorder)
- printf (" %d,\n", (*(struct argstring **) nodep)->off);
-}
-
-
-static void
-print_op_fct (const void *nodep, VISIT value,
- int level __attribute__ ((unused)))
-{
- if (value == leaf || value == postorder)
- {
- fprintf (outfile, " FCT_%s,\n", (*(struct argstring **) nodep)->str);
- (*(struct argstring **) nodep)->idx = ++count_op_str;
- }
-}
-
-
-#if NMNES < 2
-# error "bogus NMNES value"
-#endif
-
-static void
-instrtable_out (void)
-{
- find_numbers ();
-
-#if 0
- create_mnemonic_table ();
-
- fprintf (outfile, "#define MNEMONIC_BITS %zu\n", best_mnemonic_bits);
-#else
- fprintf (outfile, "#define MNEMONIC_BITS %ld\n",
- lrint (ceil (log2 (NMNES))));
-#endif
- fprintf (outfile, "#define SUFFIX_BITS %d\n", nbitsuf);
- for (int i = 0; i < 3; ++i)
- {
- fprintf (outfile, "#define FCT%d_BITS %d\n", i + 1, nbitfct[i]);
- if (nbitstr[i] != 0)
- fprintf (outfile, "#define STR%d_BITS %d\n", i + 1, nbitstr[i]);
- fprintf (outfile, "#define OFF%d_1_BITS %d\n", i + 1, nbitoff[i][0]);
- fprintf (outfile, "#define OFF%d_1_BIAS %d\n", i + 1, minoff[i][0]);
- if (nbitoff[i][1] != 0)
- {
- fprintf (outfile, "#define OFF%d_2_BITS %d\n", i + 1, nbitoff[i][1]);
- fprintf (outfile, "#define OFF%d_2_BIAS %d\n", i + 1, minoff[i][1]);
- }
- if (nbitoff[i][2] != 0)
- {
- fprintf (outfile, "#define OFF%d_3_BITS %d\n", i + 1, nbitoff[i][2]);
- fprintf (outfile, "#define OFF%d_3_BIAS %d\n", i + 1, minoff[i][2]);
- }
- }
-
- fputs ("\n#include <i386_data.h>\n\n", outfile);
-
-
-#define APPEND(a, b) APPEND_ (a, b)
-#define APPEND_(a, b) a##b
-#define EMIT_SUFFIX(suf) \
- fprintf (outfile, "#define suffix_%s %d\n", #suf, APPEND (suffix_, suf))
- EMIT_SUFFIX (none);
- EMIT_SUFFIX (w);
- EMIT_SUFFIX (w0);
- EMIT_SUFFIX (W);
- EMIT_SUFFIX (tttn);
- EMIT_SUFFIX (D);
- EMIT_SUFFIX (w1);
- EMIT_SUFFIX (W1);
-
- fputc_unlocked ('\n', outfile);
-
- for (int i = 0; i < 3; ++i)
- {
- /* Functions. */
- count_op_str = 0;
- fprintf (outfile, "static const opfct_t op%d_fct[] =\n{\n NULL,\n",
- i + 1);
- twalk (fct_names[i], print_op_fct);
- fputs ("};\n", outfile);
-
- /* The operand strings. */
- if (nbitstr[i] != 0)
- {
- count_op_str = 0;
- off_op_str = 0;
- fprintf (outfile, "static const char op%d_str[] =", i + 1);
- twalk (strs[i], print_op_str);
- fputs ("\";\n", outfile);
-
- fprintf (outfile, "static const uint8_t op%d_str_idx[] = {\n",
- i + 1);
- twalk (strs[i], print_op_str_idx);
- fputs ("};\n", outfile);
- }
- }
-
-
- fputs ("static const struct instr_enc instrtab[] =\n{\n", outfile);
- struct instruction *instr;
- for (instr = instructions; instr != NULL; instr = instr->next)
- {
- fputs (" {", outfile);
- if (instr->mnemonic == (void *) -1l)
- fputs (" .mnemonic = MNE_INVALID,", outfile);
- else
- fprintf (outfile, " .mnemonic = MNE_%s,", instr->mnemonic);
- fprintf (outfile, " .rep = %d,", instr->rep);
- fprintf (outfile, " .repe = %d,", instr->repe);
- fprintf (outfile, " .suffix = %d,", instr->suffix);
- fprintf (outfile, " .modrm = %d,", instr->modrm);
-
- for (int i = 0; i < 3; ++i)
- {
- int idx = 0;
- if (instr->operands[i].fct != NULL)
- {
- struct argstring search = { .str = instr->operands[i].fct };
- struct argstring **res = tfind (&search, &fct_names[i],
- compare_argstring);
- assert (res != NULL);
- idx = (*res)->idx;
- }
- fprintf (outfile, " .fct%d = %d,", i + 1, idx);
-
- idx = 0;
- if (instr->operands[i].str != NULL)
- {
- struct argstring search = { .str = instr->operands[i].str };
- struct argstring **res = tfind (&search, &strs[i],
- compare_argstring);
- assert (res != NULL);
- idx = (*res)->idx;
- }
- if (nbitstr[i] != 0)
- fprintf (outfile, " .str%d = %d,", i + 1, idx);
-
- fprintf (outfile, " .off%d_1 = %d,", i + 1,
- MAX (0, instr->operands[i].off1 - minoff[i][0]));
-
- if (nbitoff[i][1] != 0)
- fprintf (outfile, " .off%d_2 = %d,", i + 1,
- MAX (0, instr->operands[i].off2 - minoff[i][1]));
-
- if (nbitoff[i][2] != 0)
- fprintf (outfile, " .off%d_3 = %d,", i + 1,
- MAX (0, instr->operands[i].off3 - minoff[i][2]));
- }
-
- fputs (" },\n", outfile);
- }
- fputs ("};\n", outfile);
-
- fputs ("static const uint8_t match_data[] =\n{\n", outfile);
- size_t cnt = 0;
- for (instr = instructions; instr != NULL; instr = instr->next, ++cnt)
- {
- /* First count the number of bytes. */
- size_t totalbits = 0;
- size_t zerobits = 0;
- bool leading_p = true;
- size_t leadingbits = 0;
- struct bitvalue *b = instr->bytes;
- while (b != NULL)
- {
- if (b->type == zeroone)
- {
- ++totalbits;
- zerobits = 0;
- if (leading_p)
- ++leadingbits;
- }
- else
- {
- totalbits += b->field->bits;
- /* We must always count the mod/rm byte. */
- if (strncasecmp (b->field->name, "mod", 3) == 0)
- zerobits = 0;
- else
- zerobits += b->field->bits;
- leading_p = false;
- }
- b = b->next;
- }
- size_t nbytes = (totalbits - zerobits + 7) / 8;
- assert (nbytes > 0);
- size_t leadingbytes = leadingbits / 8;
-
- fprintf (outfile, " %#zx,", nbytes | (leadingbytes << 4));
-
- /* Now create the mask and byte values. */
- uint8_t byte = 0;
- uint8_t mask = 0;
- int nbits = 0;
- b = instr->bytes;
- while (b != NULL)
- {
- if (b->type == zeroone)
- {
- byte = (byte << 1) | b->value;
- mask = (mask << 1) | 1;
- if (++nbits == 8)
- {
- if (leadingbytes > 0)
- {
- assert (mask == 0xff);
- fprintf (outfile, " %#" PRIx8 ",", byte);
- --leadingbytes;
- }
- else
- fprintf (outfile, " %#" PRIx8 ", %#" PRIx8 ",",
- mask, byte);
- byte = mask = nbits = 0;
- if (--nbytes == 0)
- break;
- }
- }
- else
- {
- assert (leadingbytes == 0);
-
- unsigned long int remaining = b->field->bits;
- while (nbits + remaining > 8)
- {
- fprintf (outfile, " %#" PRIx8 ", %#" PRIx8 ",",
- mask << (8 - nbits), byte << (8 - nbits));
- remaining = nbits + remaining - 8;
- byte = mask = nbits = 0;
- if (--nbytes == 0)
- break;
- }
- byte <<= remaining;
- mask <<= remaining;
- nbits += remaining;
- if (nbits == 8)
- {
- fprintf (outfile, " %#" PRIx8 ", %#" PRIx8 ",", mask, byte);
- byte = mask = nbits = 0;
- if (--nbytes == 0)
- break;
- }
- }
- b = b->next;
- }
-
- fputc_unlocked ('\n', outfile);
- }
- fputs ("};\n", outfile);
-}
-
-
-#if 0
-static size_t mnemonic_maxlen;
-static size_t mnemonic_minlen;
-static size_t
-which_chars (const char *str[], size_t nstr)
-{
- char used_char[256];
- memset (used_char, '\0', sizeof (used_char));
- mnemonic_maxlen = 0;
- mnemonic_minlen = 10000;
- for (size_t cnt = 0; cnt < nstr; ++cnt)
- {
- const unsigned char *cp = (const unsigned char *) str[cnt];
- mnemonic_maxlen = MAX (mnemonic_maxlen, strlen ((char *) cp));
- mnemonic_minlen = MIN (mnemonic_minlen, strlen ((char *) cp));
- do
- used_char[*cp++] = 1;
- while (*cp != '\0');
- }
- size_t nused_char = 0;
- for (size_t cnt = 0; cnt < 256; ++cnt)
- if (used_char[cnt] != 0)
- ++nused_char;
- return nused_char;
-}
-
-
-static const char **mnemonic_strs;
-static size_t nmnemonic_strs;
-static void
-add_mnemonics (const void *nodep, VISIT value,
- int level __attribute__ ((unused)))
-{
- if (value == leaf || value == postorder)
- mnemonic_strs[nmnemonic_strs++] = *(const char **) nodep;
-}
-
-
-struct charfreq
-{
- char ch;
- int freq;
-};
-static struct charfreq pfxfreq[256];
-static struct charfreq sfxfreq[256];
-
-
-static int
-compare_freq (const void *p1, const void *p2)
-{
- const struct charfreq *c1 = (const struct charfreq *) p1;
- const struct charfreq *c2 = (const struct charfreq *) p2;
-
- if (c1->freq > c2->freq)
- return -1;
- if (c1->freq < c2->freq)
- return 1;
- return 0;
-}
-
-
-static size_t
-compute_pfxfreq (const char *str[], size_t nstr)
-{
- memset (pfxfreq, '\0', sizeof (pfxfreq));
-
- for (size_t i = 0; i < nstr; ++i)
- pfxfreq[i].ch = i;
-
- for (size_t i = 0; i < nstr; ++i)
- ++pfxfreq[*((const unsigned char *) str[i])].freq;
-
- qsort (pfxfreq, 256, sizeof (struct charfreq), compare_freq);
-
- size_t n = 0;
- while (n < 256 && pfxfreq[n].freq != 0)
- ++n;
- return n;
-}
-
-
-struct strsnlen
-{
- const char *str;
- size_t len;
-};
-
-static size_t
-compute_sfxfreq (size_t nstr, struct strsnlen *strsnlen)
-{
- memset (sfxfreq, '\0', sizeof (sfxfreq));
-
- for (size_t i = 0; i < nstr; ++i)
- sfxfreq[i].ch = i;
-
- for (size_t i = 0; i < nstr; ++i)
- ++sfxfreq[((const unsigned char *) strchrnul (strsnlen[i].str, '\0'))[-1]].freq;
-
- qsort (sfxfreq, 256, sizeof (struct charfreq), compare_freq);
-
- size_t n = 0;
- while (n < 256 && sfxfreq[n].freq != 0)
- ++n;
- return n;
-}
-
-
-static void
-create_mnemonic_table (void)
-{
- mnemonic_strs = xmalloc (nmnemonics * sizeof (char *));
-
- twalk (mnemonics, add_mnemonics);
-
- (void) which_chars (mnemonic_strs, nmnemonic_strs);
-
- size_t best_so_far = 100000000;
- char *best_prefix = NULL;
- char *best_suffix = NULL;
- char *best_table = NULL;
- size_t best_table_size = 0;
- size_t best_table_bits = 0;
- size_t best_prefix_bits = 0;
-
- /* We can precompute the prefix characters. */
- size_t npfx_char = compute_pfxfreq (mnemonic_strs, nmnemonic_strs);
-
- /* Compute best size for string representation including explicit NUL. */
- for (size_t pfxbits = 0; (1u << pfxbits) < 2 * npfx_char; ++pfxbits)
- {
- char prefix[1 << pfxbits];
- size_t i;
- for (i = 0; i < (1u << pfxbits) - 1; ++i)
- prefix[i] = pfxfreq[i].ch;
- prefix[i] = '\0';
-
- struct strsnlen strsnlen[nmnemonic_strs];
-
- for (i = 0; i < nmnemonic_strs; ++i)
- {
- if (strchr (prefix, *mnemonic_strs[i]) != NULL)
- strsnlen[i].str = mnemonic_strs[i] + 1;
- else
- strsnlen[i].str = mnemonic_strs[i];
- strsnlen[i].len = strlen (strsnlen[i].str);
- }
-
- /* With the prefixes gone, try to combine strings. */
- size_t nstrsnlen = 1;
- for (i = 1; i < nmnemonic_strs; ++i)
- {
- size_t j;
- for (j = 0; j < nstrsnlen; ++j)
- if (strsnlen[i].len > strsnlen[j].len
- && strcmp (strsnlen[j].str,
- strsnlen[i].str + (strsnlen[i].len
- - strsnlen[j].len)) == 0)
- {
- strsnlen[j] = strsnlen[i];
- break;
- }
- else if (strsnlen[i].len < strsnlen[j].len
- && strcmp (strsnlen[i].str,
- strsnlen[j].str + (strsnlen[j].len
- - strsnlen[i].len)) == 0)
- break;
-;
- if (j == nstrsnlen)
- strsnlen[nstrsnlen++] = strsnlen[i];
- }
-
- size_t nsfx_char = compute_sfxfreq (nstrsnlen, strsnlen);
-
- for (size_t sfxbits = 0; (1u << sfxbits) < 2 * nsfx_char; ++sfxbits)
- {
- char suffix[1 << sfxbits];
-
- for (i = 0; i < (1u << sfxbits) - 1; ++i)
- suffix[i] = sfxfreq[i].ch;
- suffix[i] = '\0';
-
- size_t newlen[nstrsnlen];
-
- for (i = 0; i < nstrsnlen; ++i)
- if (strchr (suffix, strsnlen[i].str[strsnlen[i].len - 1]) != NULL)
- newlen[i] = strsnlen[i].len - 1;
- else
- newlen[i] = strsnlen[i].len;
-
- char charused[256];
- memset (charused, '\0', sizeof (charused));
- size_t ncharused = 0;
-
- const char *tablestr[nstrsnlen];
- size_t ntablestr = 1;
- tablestr[0] = strsnlen[0].str;
- size_t table = newlen[0] + 1;
- for (i = 1; i < nstrsnlen; ++i)
- {
- size_t j;
- for (j = 0; j < ntablestr; ++j)
- if (newlen[i] > newlen[j]
- && memcmp (tablestr[j],
- strsnlen[i].str + (newlen[i] - newlen[j]),
- newlen[j]) == 0)
- {
- table += newlen[i] - newlen[j];
- tablestr[j] = strsnlen[i].str;
- newlen[j] = newlen[i];
- break;
- }
- else if (newlen[i] < newlen[j]
- && memcmp (strsnlen[i].str,
- tablestr[j] + (newlen[j] - newlen[i]),
- newlen[i]) == 0)
- break;
-
- if (j == ntablestr)
- {
- table += newlen[i] + 1;
- tablestr[ntablestr] = strsnlen[i].str;
- newlen[ntablestr] = newlen[i];
-
- ++ntablestr;
- }
-
- for (size_t x = 0; x < newlen[j]; ++x)
- if (charused[((const unsigned char *) tablestr[j])[x]]++ == 0)
- ++ncharused;
- }
-
- size_t ncharused_bits = 0;
- i = 1;
- while (i < ncharused)
- {
- i *= 2;
- ++ncharused_bits;
- }
-
- size_t table_bits = 0;
- i = 1;
- while (i < table)
- {
- i *= 2;
- ++table_bits;
- }
-
- size_t mnemonic_bits = table_bits + pfxbits + sfxbits;
- size_t new_total = (((table + 7) / 8) * ncharused_bits + ncharused
- + (pfxbits == 0 ? 0 : (1 << pfxbits) - 1)
- + (sfxbits == 0 ? 0 : (1 << sfxbits) - 1)
- + (((total_bits + mnemonic_bits + 7) / 8)
- * ninstructions));
-
- if (new_total < best_so_far)
- {
- best_so_far = new_total;
- best_mnemonic_bits = mnemonic_bits;
-
- free (best_suffix);
- best_suffix = xstrdup (suffix);
-
- free (best_prefix);
- best_prefix = xstrdup (prefix);
- best_prefix_bits = pfxbits;
-
- best_table_size = table;
- best_table_bits = table_bits;
- char *cp = best_table = xrealloc (best_table, table);
- for (i = 0; i < ntablestr; ++i)
- {
- assert (cp + newlen[i] + 1 <= best_table + table);
- cp = mempcpy (cp, tablestr[i], newlen[i]);
- *cp++ = '\0';
- }
- assert (cp == best_table + table);
- }
- }
- }
-
- fputs ("static const char mnemonic_table[] =\n\"", outfile);
- for (size_t i = 0; i < best_table_size; ++i)
- {
- if (((i + 1) % 60) == 0)
- fputs ("\"\n\"", outfile);
- if (!isascii (best_table[i]) || !isprint (best_table[i]))
- fprintf (outfile, "\\%03o", best_table[i]);
- else
- fputc (best_table[i], outfile);
- }
- fputs ("\";\n", outfile);
-
- if (best_prefix[0] != '\0')
- fprintf (outfile,
- "static const char prefix[%zu] = \"%s\";\n"
- "#define PREFIXCHAR_BITS %zu\n",
- strlen (best_prefix), best_prefix, best_prefix_bits);
- else
- fputs ("#define NO_PREFIX\n", outfile);
-
- if (best_suffix[0] != '\0')
- fprintf (outfile, "static const char suffix[%zu] = \"%s\";\n",
- strlen (best_suffix), best_suffix);
- else
- fputs ("#define NO_SUFFIX\n", outfile);
-
- for (size_t i = 0; i < nmnemonic_strs; ++i)
- {
- const char *mne = mnemonic_strs[i];
-
- size_t pfxval = 0;
- char *cp = strchr (best_prefix, *mne);
- if (cp != NULL)
- {
- pfxval = 1 + (cp - best_prefix);
- ++mne;
- }
-
- size_t l = strlen (mne);
-
- size_t sfxval = 0;
- cp = strchr (best_suffix, mne[l - 1]);
- if (cp != NULL)
- {
- sfxval = 1 + (cp - best_suffix);
- --l;
- }
-
- char *off = memmem (best_table, best_table_size, mne, l);
- while (off[l] != '\0')
- {
- off = memmem (off + 1, best_table_size, mne, l);
- assert (off != NULL);
- }
-
- fprintf (outfile, "#define MNE_%s %#zx\n",
- mnemonic_strs[i],
- (off - best_table)
- + ((pfxval + (sfxval << best_prefix_bits)) << best_table_bits));
- }
-}
-#endif