Blame libcpu/i386_parse.y

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