133965Sjdp/* itbl-ops.c
2218822Sdim   Copyright 1997, 1999, 2000, 2001, 2002, 2003, 2005, 2006
3218822Sdim   Free Software Foundation, Inc.
433965Sjdp
533965Sjdp   This file is part of GAS, the GNU Assembler.
633965Sjdp
733965Sjdp   GAS is free software; you can redistribute it and/or modify
833965Sjdp   it under the terms of the GNU General Public License as published by
933965Sjdp   the Free Software Foundation; either version 2, or (at your option)
1033965Sjdp   any later version.
1133965Sjdp
1233965Sjdp   GAS is distributed in the hope that it will be useful,
1333965Sjdp   but WITHOUT ANY WARRANTY; without even the implied warranty of
1433965Sjdp   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1533965Sjdp   GNU General Public License for more details.
1633965Sjdp
1733965Sjdp   You should have received a copy of the GNU General Public License
1833965Sjdp   along with GAS; see the file COPYING.  If not, write to the Free
19218822Sdim   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
20218822Sdim   02110-1301, USA.  */
2133965Sjdp
2233965Sjdp/*======================================================================*/
2333965Sjdp/*
2433965Sjdp * Herein lies the support for dynamic specification of processor
2533965Sjdp * instructions and registers.  Mnemonics, values, and formats for each
2633965Sjdp * instruction and register are specified in an ascii file consisting of
2733965Sjdp * table entries.  The grammar for the table is defined in the document
2833965Sjdp * "Processor instruction table specification".
2933965Sjdp *
3033965Sjdp * Instructions use the gnu assembler syntax, with the addition of
3133965Sjdp * allowing mnemonics for register.
3233965Sjdp * Eg. "func $2,reg3,0x100,symbol ; comment"
3333965Sjdp * 	func - opcode name
3433965Sjdp * 	$n - register n
3533965Sjdp * 	reg3 - mnemonic for processor's register defined in table
3633965Sjdp * 	0xddd..d - immediate value
3733965Sjdp * 	symbol - address of label or external symbol
3833965Sjdp *
3933965Sjdp * First, itbl_parse reads in the table of register and instruction
4033965Sjdp * names and formats, and builds a list of entries for each
4133965Sjdp * processor/type combination.  lex and yacc are used to parse
4233965Sjdp * the entries in the table and call functions defined here to
4333965Sjdp * add each entry to our list.
4433965Sjdp *
4533965Sjdp * Then, when assembling or disassembling, these functions are called to
4633965Sjdp * 1) get information on a processor's registers and
4733965Sjdp * 2) assemble/disassemble an instruction.
4833965Sjdp * To assemble(disassemble) an instruction, the function
4933965Sjdp * itbl_assemble(itbl_disassemble) is called to search the list of
5033965Sjdp * instruction entries, and if a match is found, uses the format
5133965Sjdp * described in the instruction entry structure to complete the action.
5233965Sjdp *
5333965Sjdp * Eg. Suppose we have a Mips coprocessor "cop3" with data register "d2"
5433965Sjdp * and we want to define function "pig" which takes two operands.
5533965Sjdp *
5633965Sjdp * Given the table entries:
5733965Sjdp * 	"p3 insn pig 0x1:24-21 dreg:20-16 immed:15-0"
5833965Sjdp * 	"p3 dreg d2 0x2"
5933965Sjdp * and that the instruction encoding for coprocessor pz has encoding:
6033965Sjdp * 	#define MIPS_ENCODE_COP_NUM(z) ((0x21|(z<<1))<<25)
6133965Sjdp * 	#define ITBL_ENCODE_PNUM(pnum) MIPS_ENCODE_COP_NUM(pnum)
6233965Sjdp *
6333965Sjdp * a structure to describe the instruction might look something like:
6433965Sjdp *      struct itbl_entry = {
6533965Sjdp *      e_processor processor = e_p3
6633965Sjdp *      e_type type = e_insn
6733965Sjdp *      char *name = "pig"
6833965Sjdp *      uint value = 0x1
6933965Sjdp *      uint flags = 0
7033965Sjdp *      struct itbl_range range = 24-21
7133965Sjdp *      struct itbl_field *field = {
7233965Sjdp *              e_type type = e_dreg
7333965Sjdp *              struct itbl_range range = 20-16
7433965Sjdp *              struct itbl_field *next = {
7533965Sjdp *                      e_type type = e_immed
7633965Sjdp *                      struct itbl_range range = 15-0
7733965Sjdp *                      struct itbl_field *next = 0
7833965Sjdp *                      };
7933965Sjdp *              };
8033965Sjdp *      struct itbl_entry *next = 0
8133965Sjdp *      };
8233965Sjdp *
8333965Sjdp * And the assembler instructions:
8433965Sjdp * 	"pig d2,0x100"
8533965Sjdp * 	"pig $2,0x100"
8633965Sjdp *
8733965Sjdp * would both assemble to the hex value:
8833965Sjdp * 	"0x4e220100"
8933965Sjdp *
9033965Sjdp */
9133965Sjdp
92218822Sdim#include "as.h"
9333965Sjdp#include "itbl-ops.h"
94107492Sobrien#include <itbl-parse.h>
9533965Sjdp
9633965Sjdp/* #define DEBUG */
9733965Sjdp
9833965Sjdp#ifdef DEBUG
9933965Sjdp#include <assert.h>
10033965Sjdp#define ASSERT(x) assert(x)
10133965Sjdp#define DBG(x) printf x
10233965Sjdp#else
10333965Sjdp#define ASSERT(x)
10433965Sjdp#define DBG(x)
10533965Sjdp#endif
10633965Sjdp
10733965Sjdp#ifndef min
10833965Sjdp#define min(a,b) (a<b?a:b)
10933965Sjdp#endif
11033965Sjdp
11133965Sjdpint itbl_have_entries = 0;
11233965Sjdp
11333965Sjdp/*======================================================================*/
11433965Sjdp/* structures for keeping itbl format entries */
11533965Sjdp
11677298Sobrienstruct itbl_range {
11777298Sobrien  int sbit;			/* mask starting bit position */
11877298Sobrien  int ebit;			/* mask ending bit position */
11977298Sobrien};
12033965Sjdp
12177298Sobrienstruct itbl_field {
12277298Sobrien  e_type type;			/* dreg/creg/greg/immed/symb */
12377298Sobrien  struct itbl_range range;	/* field's bitfield range within instruction */
12477298Sobrien  unsigned long flags;		/* field flags */
12577298Sobrien  struct itbl_field *next;	/* next field in list */
12677298Sobrien};
12733965Sjdp
12833965Sjdp/* These structures define the instructions and registers for a processor.
12933965Sjdp * If the type is an instruction, the structure defines the format of an
13033965Sjdp * instruction where the fields are the list of operands.
13133965Sjdp * The flags field below uses the same values as those defined in the
13277298Sobrien * gnu assembler and are machine specific.  */
13377298Sobrienstruct itbl_entry {
13477298Sobrien  e_processor processor;	/* processor number */
13577298Sobrien  e_type type;			/* dreg/creg/greg/insn */
13677298Sobrien  char *name;			/* mnemionic name for insn/register */
13777298Sobrien  unsigned long value;		/* opcode/instruction mask/register number */
13877298Sobrien  unsigned long flags;		/* effects of the instruction */
13977298Sobrien  struct itbl_range range;	/* bit range within instruction for value */
14077298Sobrien  struct itbl_field *fields;	/* list of operand definitions (if any) */
14177298Sobrien  struct itbl_entry *next;	/* next entry */
14277298Sobrien};
14333965Sjdp
14433965Sjdp/* local data and structures */
14533965Sjdp
14633965Sjdpstatic int itbl_num_opcodes = 0;
14733965Sjdp/* Array of entries for each processor and entry type */
148218822Sdimstatic struct itbl_entry *entries[e_nprocs][e_ntypes];
14933965Sjdp
15033965Sjdp/* local prototypes */
151130561Sobrienstatic unsigned long build_opcode (struct itbl_entry *e);
152130561Sobrienstatic e_type get_type (int yytype);
153130561Sobrienstatic e_processor get_processor (int yyproc);
154130561Sobrienstatic struct itbl_entry **get_entries (e_processor processor,
155130561Sobrien					e_type type);
156130561Sobrienstatic struct itbl_entry *find_entry_byname (e_processor processor,
157130561Sobrien					e_type type, char *name);
158130561Sobrienstatic struct itbl_entry *find_entry_byval (e_processor processor,
159130561Sobrien			e_type type, unsigned long val, struct itbl_range *r);
160130561Sobrienstatic struct itbl_entry *alloc_entry (e_processor processor,
161130561Sobrien		e_type type, char *name, unsigned long value);
162130561Sobrienstatic unsigned long apply_range (unsigned long value, struct itbl_range r);
163130561Sobrienstatic unsigned long extract_range (unsigned long value, struct itbl_range r);
164130561Sobrienstatic struct itbl_field *alloc_field (e_type type, int sbit,
165130561Sobrien					int ebit, unsigned long flags);
16633965Sjdp
16733965Sjdp/*======================================================================*/
16833965Sjdp/* Interfaces to the parser */
16933965Sjdp
17033965Sjdp/* Open the table and use lex and yacc to parse the entries.
17133965Sjdp * Return 1 for failure; 0 for success.  */
17233965Sjdp
17377298Sobrienint
17433965Sjdpitbl_parse (char *insntbl)
17533965Sjdp{
17633965Sjdp  extern FILE *yyin;
17733965Sjdp  extern int yyparse (void);
17889857Sobrien
17989857Sobrien  yyin = fopen (insntbl, FOPEN_RT);
18033965Sjdp  if (yyin == 0)
18133965Sjdp    {
18233965Sjdp      printf ("Can't open processor instruction specification file \"%s\"\n",
18333965Sjdp	      insntbl);
18433965Sjdp      return 1;
18533965Sjdp    }
18689857Sobrien
18789857Sobrien  while (yyparse ())
18889857Sobrien    ;
18989857Sobrien
19033965Sjdp  fclose (yyin);
19133965Sjdp  itbl_have_entries = 1;
19233965Sjdp  return 0;
19333965Sjdp}
19433965Sjdp
19533965Sjdp/* Add a register entry */
19633965Sjdp
19733965Sjdpstruct itbl_entry *
19833965Sjdpitbl_add_reg (int yyprocessor, int yytype, char *regname,
19933965Sjdp	      int regnum)
20033965Sjdp{
20133965Sjdp  return alloc_entry (get_processor (yyprocessor), get_type (yytype), regname,
20233965Sjdp		      (unsigned long) regnum);
20333965Sjdp}
20433965Sjdp
20533965Sjdp/* Add an instruction entry */
20633965Sjdp
20733965Sjdpstruct itbl_entry *
20833965Sjdpitbl_add_insn (int yyprocessor, char *name, unsigned long value,
20933965Sjdp	       int sbit, int ebit, unsigned long flags)
21033965Sjdp{
21133965Sjdp  struct itbl_entry *e;
21233965Sjdp  e = alloc_entry (get_processor (yyprocessor), e_insn, name, value);
21333965Sjdp  if (e)
21433965Sjdp    {
21533965Sjdp      e->range.sbit = sbit;
21633965Sjdp      e->range.ebit = ebit;
21733965Sjdp      e->flags = flags;
21833965Sjdp      itbl_num_opcodes++;
21933965Sjdp    }
22033965Sjdp  return e;
22133965Sjdp}
22233965Sjdp
22333965Sjdp/* Add an operand to an instruction entry */
22433965Sjdp
22533965Sjdpstruct itbl_field *
22633965Sjdpitbl_add_operand (struct itbl_entry *e, int yytype, int sbit,
22733965Sjdp		  int ebit, unsigned long flags)
22833965Sjdp{
22933965Sjdp  struct itbl_field *f, **last_f;
23033965Sjdp  if (!e)
23133965Sjdp    return 0;
23277298Sobrien  /* Add to end of fields' list.  */
23333965Sjdp  f = alloc_field (get_type (yytype), sbit, ebit, flags);
23433965Sjdp  if (f)
23533965Sjdp    {
23633965Sjdp      last_f = &e->fields;
23733965Sjdp      while (*last_f)
23833965Sjdp	last_f = &(*last_f)->next;
23933965Sjdp      *last_f = f;
24033965Sjdp      f->next = 0;
24133965Sjdp    }
24233965Sjdp  return f;
24333965Sjdp}
24433965Sjdp
24533965Sjdp/*======================================================================*/
24633965Sjdp/* Interfaces for assembler and disassembler */
24733965Sjdp
24833965Sjdp#ifndef STAND_ALONE
24933965Sjdpstatic void append_insns_as_macros (void);
25033965Sjdp
25177298Sobrien/* Initialize for gas.  */
25277298Sobrien
25377298Sobrienvoid
25433965Sjdpitbl_init (void)
25533965Sjdp{
25633965Sjdp  struct itbl_entry *e, **es;
25733965Sjdp  e_processor procn;
25833965Sjdp  e_type type;
25933965Sjdp
26033965Sjdp  if (!itbl_have_entries)
26177298Sobrien    return;
26233965Sjdp
26333965Sjdp  /* Since register names don't have a prefix, put them in the symbol table so
26433965Sjdp     they can't be used as symbols.  This simplifies argument parsing as
26577298Sobrien     we can let gas parse registers for us.  */
26633965Sjdp  /* Use symbol_create instead of symbol_new so we don't try to
26733965Sjdp     output registers into the object file's symbol table.  */
26833965Sjdp
26933965Sjdp  for (type = e_regtype0; type < e_nregtypes; type++)
27033965Sjdp    for (procn = e_p0; procn < e_nprocs; procn++)
27133965Sjdp      {
27233965Sjdp	es = get_entries (procn, type);
27333965Sjdp	for (e = *es; e; e = e->next)
27433965Sjdp	  {
27533965Sjdp	    symbol_table_insert (symbol_create (e->name, reg_section,
27677298Sobrien						e->value, &zero_address_frag));
27733965Sjdp	  }
27833965Sjdp      }
27933965Sjdp  append_insns_as_macros ();
28033965Sjdp}
28133965Sjdp
28277298Sobrien/* Append insns to opcodes table and increase number of opcodes
28377298Sobrien * Structure of opcodes table:
28433965Sjdp * struct itbl_opcode
28533965Sjdp * {
28633965Sjdp *   const char *name;
28777298Sobrien *   const char *args; 		- string describing the arguments.
28877298Sobrien *   unsigned long match; 	- opcode, or ISA level if pinfo=INSN_MACRO
28977298Sobrien *   unsigned long mask; 	- opcode mask, or macro id if pinfo=INSN_MACRO
29077298Sobrien *   unsigned long pinfo; 	- insn flags, or INSN_MACRO
29133965Sjdp * };
29233965Sjdp * examples:
29333965Sjdp *	{"li",      "t,i",  0x34000000, 0xffe00000, WR_t    },
29433965Sjdp *	{"li",      "t,I",  0,    (int) M_LI,   INSN_MACRO  },
29533965Sjdp */
29633965Sjdp
29733965Sjdpstatic char *form_args (struct itbl_entry *e);
29877298Sobrienstatic void
29933965Sjdpappend_insns_as_macros (void)
30033965Sjdp{
30133965Sjdp  struct ITBL_OPCODE_STRUCT *new_opcodes, *o;
30233965Sjdp  struct itbl_entry *e, **es;
30333965Sjdp  int n, id, size, new_size, new_num_opcodes;
30433965Sjdp
30533965Sjdp  if (!itbl_have_entries)
30677298Sobrien    return;
30733965Sjdp
30833965Sjdp  if (!itbl_num_opcodes)	/* no new instructions to add! */
30933965Sjdp    {
31033965Sjdp      return;
31133965Sjdp    }
31233965Sjdp  DBG (("previous num_opcodes=%d\n", ITBL_NUM_OPCODES));
31333965Sjdp
31433965Sjdp  new_num_opcodes = ITBL_NUM_OPCODES + itbl_num_opcodes;
31533965Sjdp  ASSERT (new_num_opcodes >= itbl_num_opcodes);
31633965Sjdp
31733965Sjdp  size = sizeof (struct ITBL_OPCODE_STRUCT) * ITBL_NUM_OPCODES;
31833965Sjdp  ASSERT (size >= 0);
31933965Sjdp  DBG (("I get=%d\n", size / sizeof (ITBL_OPCODES[0])));
32033965Sjdp
32133965Sjdp  new_size = sizeof (struct ITBL_OPCODE_STRUCT) * new_num_opcodes;
32233965Sjdp  ASSERT (new_size > size);
32333965Sjdp
32433965Sjdp  /* FIXME since ITBL_OPCODES culd be a static table,
32577298Sobrien		we can't realloc or delete the old memory.  */
32633965Sjdp  new_opcodes = (struct ITBL_OPCODE_STRUCT *) malloc (new_size);
32733965Sjdp  if (!new_opcodes)
32833965Sjdp    {
32960484Sobrien      printf (_("Unable to allocate memory for new instructions\n"));
33033965Sjdp      return;
33133965Sjdp    }
332130561Sobrien  if (size)			/* copy preexisting opcodes table */
33333965Sjdp    memcpy (new_opcodes, ITBL_OPCODES, size);
33433965Sjdp
33533965Sjdp  /* FIXME! some NUMOPCODES are calculated expressions.
33677298Sobrien		These need to be changed before itbls can be supported.  */
33733965Sjdp
33833965Sjdp  id = ITBL_NUM_MACROS;		/* begin the next macro id after the last */
33933965Sjdp  o = &new_opcodes[ITBL_NUM_OPCODES];	/* append macro to opcodes list */
34033965Sjdp  for (n = e_p0; n < e_nprocs; n++)
34133965Sjdp    {
34233965Sjdp      es = get_entries (n, e_insn);
34333965Sjdp      for (e = *es; e; e = e->next)
34433965Sjdp	{
34533965Sjdp	  /* name,    args,   mask,       match,  pinfo
34633965Sjdp		 * {"li",      "t,i",  0x34000000, 0xffe00000, WR_t    },
34733965Sjdp		 * {"li",      "t,I",  0,    (int) M_LI,   INSN_MACRO  },
34833965Sjdp		 * Construct args from itbl_fields.
34933965Sjdp		*/
35033965Sjdp	  o->name = e->name;
35133965Sjdp	  o->args = strdup (form_args (e));
35233965Sjdp	  o->mask = apply_range (e->value, e->range);
353130561Sobrien	  /* FIXME how to catch during assembly? */
35433965Sjdp	  /* mask to identify this insn */
35533965Sjdp	  o->match = apply_range (e->value, e->range);
35633965Sjdp	  o->pinfo = 0;
35733965Sjdp
35833965Sjdp#ifdef USE_MACROS
359130561Sobrien	  o->mask = id++;	/* FIXME how to catch during assembly? */
36033965Sjdp	  o->match = 0;		/* for macros, the insn_isa number */
36133965Sjdp	  o->pinfo = INSN_MACRO;
36233965Sjdp#endif
36333965Sjdp
36433965Sjdp	  /* Don't add instructions which caused an error */
36533965Sjdp	  if (o->args)
36633965Sjdp	    o++;
36733965Sjdp	  else
36833965Sjdp	    new_num_opcodes--;
36933965Sjdp	}
37033965Sjdp    }
37133965Sjdp  ITBL_OPCODES = new_opcodes;
37233965Sjdp  ITBL_NUM_OPCODES = new_num_opcodes;
37333965Sjdp
37433965Sjdp  /* FIXME
37533965Sjdp		At this point, we can free the entries, as they should have
37633965Sjdp		been added to the assembler's tables.
37733965Sjdp		Don't free name though, since name is being used by the new
37833965Sjdp		opcodes table.
37933965Sjdp
38077298Sobrien		Eventually, we should also free the new opcodes table itself
38133965Sjdp		on exit.
38233965Sjdp	*/
38333965Sjdp}
38433965Sjdp
38533965Sjdpstatic char *
38633965Sjdpform_args (struct itbl_entry *e)
38733965Sjdp{
38833965Sjdp  static char s[31];
38933965Sjdp  char c = 0, *p = s;
39033965Sjdp  struct itbl_field *f;
39133965Sjdp
39233965Sjdp  ASSERT (e);
39333965Sjdp  for (f = e->fields; f; f = f->next)
39433965Sjdp    {
39533965Sjdp      switch (f->type)
39633965Sjdp	{
39733965Sjdp	case e_dreg:
39833965Sjdp	  c = 'd';
39933965Sjdp	  break;
40033965Sjdp	case e_creg:
40133965Sjdp	  c = 't';
40233965Sjdp	  break;
40333965Sjdp	case e_greg:
40433965Sjdp	  c = 's';
40533965Sjdp	  break;
40633965Sjdp	case e_immed:
40733965Sjdp	  c = 'i';
40833965Sjdp	  break;
40933965Sjdp	case e_addr:
41033965Sjdp	  c = 'a';
41133965Sjdp	  break;
41233965Sjdp	default:
41333965Sjdp	  c = 0;		/* ignore; unknown field type */
41433965Sjdp	}
41533965Sjdp      if (c)
41633965Sjdp	{
41733965Sjdp	  if (p != s)
41833965Sjdp	    *p++ = ',';
41933965Sjdp	  *p++ = c;
42033965Sjdp	}
42133965Sjdp    }
42233965Sjdp  *p = 0;
42333965Sjdp  return s;
42433965Sjdp}
42533965Sjdp#endif /* !STAND_ALONE */
42633965Sjdp
42733965Sjdp/* Get processor's register name from val */
42833965Sjdp
42960484Sobrienint
43060484Sobrienitbl_get_reg_val (char *name, unsigned long *pval)
43133965Sjdp{
43233965Sjdp  e_type t;
43333965Sjdp  e_processor p;
43460484Sobrien
43533965Sjdp  for (p = e_p0; p < e_nprocs; p++)
43660484Sobrien    {
43760484Sobrien      for (t = e_regtype0; t < e_nregtypes; t++)
43860484Sobrien	{
43960484Sobrien	  if (itbl_get_val (p, t, name, pval))
44060484Sobrien	    return 1;
44160484Sobrien	}
44260484Sobrien    }
44333965Sjdp  return 0;
44433965Sjdp}
44533965Sjdp
44633965Sjdpchar *
44733965Sjdpitbl_get_name (e_processor processor, e_type type, unsigned long val)
44833965Sjdp{
44933965Sjdp  struct itbl_entry *r;
45033965Sjdp  /* type depends on instruction passed */
45133965Sjdp  r = find_entry_byval (processor, type, val, 0);
45233965Sjdp  if (r)
45333965Sjdp    return r->name;
45433965Sjdp  else
45533965Sjdp    return 0;			/* error; invalid operand */
45633965Sjdp}
45733965Sjdp
45833965Sjdp/* Get processor's register value from name */
45933965Sjdp
46060484Sobrienint
46160484Sobrienitbl_get_val (e_processor processor, e_type type, char *name,
46260484Sobrien	      unsigned long *pval)
46333965Sjdp{
46433965Sjdp  struct itbl_entry *r;
46533965Sjdp  /* type depends on instruction passed */
46633965Sjdp  r = find_entry_byname (processor, type, name);
46760484Sobrien  if (r == NULL)
46860484Sobrien    return 0;
46960484Sobrien  *pval = r->value;
47060484Sobrien  return 1;
47133965Sjdp}
47233965Sjdp
47333965Sjdp/* Assemble instruction "name" with operands "s".
47433965Sjdp * name - name of instruction
47533965Sjdp * s - operands
47633965Sjdp * returns - long word for assembled instruction */
47733965Sjdp
47877298Sobrienunsigned long
47933965Sjdpitbl_assemble (char *name, char *s)
48033965Sjdp{
48133965Sjdp  unsigned long opcode;
48278828Sobrien  struct itbl_entry *e = NULL;
48333965Sjdp  struct itbl_field *f;
48433965Sjdp  char *n;
48533965Sjdp  int processor;
48633965Sjdp
48733965Sjdp  if (!name || !*name)
48889857Sobrien    return 0;			/* error!  must have an opcode name/expr */
48933965Sjdp
49033965Sjdp  /* find entry in list of instructions for all processors */
49133965Sjdp  for (processor = 0; processor < e_nprocs; processor++)
49233965Sjdp    {
49333965Sjdp      e = find_entry_byname (processor, e_insn, name);
49433965Sjdp      if (e)
49533965Sjdp	break;
49633965Sjdp    }
49733965Sjdp  if (!e)
49877298Sobrien    return 0;			/* opcode not in table; invalid instruction */
49933965Sjdp  opcode = build_opcode (e);
50033965Sjdp
50133965Sjdp  /* parse opcode's args (if any) */
50277298Sobrien  for (f = e->fields; f; f = f->next)	/* for each arg, ...  */
50333965Sjdp    {
50433965Sjdp      struct itbl_entry *r;
50533965Sjdp      unsigned long value;
50633965Sjdp      if (!s || !*s)
50733965Sjdp	return 0;		/* error - not enough operands */
50833965Sjdp      n = itbl_get_field (&s);
50933965Sjdp      /* n should be in form $n or 0xhhh (are symbol names valid?? */
51033965Sjdp      switch (f->type)
51133965Sjdp	{
51233965Sjdp	case e_dreg:
51333965Sjdp	case e_creg:
51433965Sjdp	case e_greg:
51533965Sjdp	  /* Accept either a string name
51633965Sjdp			 * or '$' followed by the register number */
51733965Sjdp	  if (*n == '$')
51833965Sjdp	    {
51933965Sjdp	      n++;
52033965Sjdp	      value = strtol (n, 0, 10);
52133965Sjdp	      /* FIXME! could have "0l"... then what?? */
52233965Sjdp	      if (value == 0 && *n != '0')
52333965Sjdp		return 0;	/* error; invalid operand */
52433965Sjdp	    }
52533965Sjdp	  else
52633965Sjdp	    {
52733965Sjdp	      r = find_entry_byname (e->processor, f->type, n);
52833965Sjdp	      if (r)
52933965Sjdp		value = r->value;
53033965Sjdp	      else
53133965Sjdp		return 0;	/* error; invalid operand */
53233965Sjdp	    }
53333965Sjdp	  break;
53433965Sjdp	case e_addr:
53533965Sjdp	  /* use assembler's symbol table to find symbol */
53633965Sjdp	  /* FIXME!! Do we need this?
53733965Sjdp				if so, what about relocs??
53833965Sjdp				my_getExpression (&imm_expr, s);
53933965Sjdp				return 0;	/-* error; invalid operand *-/
54033965Sjdp				break;
54133965Sjdp			*/
54233965Sjdp	  /* If not a symbol, fall thru to IMMED */
54333965Sjdp	case e_immed:
54477298Sobrien	  if (*n == '0' && *(n + 1) == 'x')	/* hex begins 0x...  */
54533965Sjdp	    {
54633965Sjdp	      n += 2;
54733965Sjdp	      value = strtol (n, 0, 16);
54833965Sjdp	      /* FIXME! could have "0xl"... then what?? */
54933965Sjdp	    }
55033965Sjdp	  else
55133965Sjdp	    {
55233965Sjdp	      value = strtol (n, 0, 10);
55333965Sjdp	      /* FIXME! could have "0l"... then what?? */
55433965Sjdp	      if (value == 0 && *n != '0')
55533965Sjdp		return 0;	/* error; invalid operand */
55633965Sjdp	    }
55733965Sjdp	  break;
55833965Sjdp	default:
55933965Sjdp	  return 0;		/* error; invalid field spec */
56033965Sjdp	}
56133965Sjdp      opcode |= apply_range (value, f->range);
56233965Sjdp    }
56333965Sjdp  if (s && *s)
56433965Sjdp    return 0;			/* error - too many operands */
56533965Sjdp  return opcode;		/* done! */
56633965Sjdp}
56733965Sjdp
56833965Sjdp/* Disassemble instruction "insn".
56933965Sjdp * insn - instruction
57033965Sjdp * s - buffer to hold disassembled instruction
57133965Sjdp * returns - 1 if succeeded; 0 if failed
57233965Sjdp */
57333965Sjdp
57477298Sobrienint
57533965Sjdpitbl_disassemble (char *s, unsigned long insn)
57633965Sjdp{
57733965Sjdp  e_processor processor;
57833965Sjdp  struct itbl_entry *e;
57933965Sjdp  struct itbl_field *f;
58033965Sjdp
58133965Sjdp  if (!ITBL_IS_INSN (insn))
58277298Sobrien    return 0;			/* error */
58333965Sjdp  processor = get_processor (ITBL_DECODE_PNUM (insn));
58433965Sjdp
58533965Sjdp  /* find entry in list */
58633965Sjdp  e = find_entry_byval (processor, e_insn, insn, 0);
58733965Sjdp  if (!e)
58877298Sobrien    return 0;			/* opcode not in table; invalid instruction */
58933965Sjdp  strcpy (s, e->name);
59033965Sjdp
59177298Sobrien  /* Parse insn's args (if any).  */
59277298Sobrien  for (f = e->fields; f; f = f->next)	/* for each arg, ...  */
59333965Sjdp    {
59433965Sjdp      struct itbl_entry *r;
59533965Sjdp      unsigned long value;
59633965Sjdp
597130561Sobrien      if (f == e->fields)	/* First operand is preceded by tab.  */
59833965Sjdp	strcat (s, "\t");
59977298Sobrien      else			/* ','s separate following operands.  */
60033965Sjdp	strcat (s, ",");
60133965Sjdp      value = extract_range (insn, f->range);
60233965Sjdp      /* n should be in form $n or 0xhhh (are symbol names valid?? */
60333965Sjdp      switch (f->type)
60433965Sjdp	{
60533965Sjdp	case e_dreg:
60633965Sjdp	case e_creg:
60733965Sjdp	case e_greg:
60833965Sjdp	  /* Accept either a string name
60977298Sobrien	     or '$' followed by the register number.  */
61033965Sjdp	  r = find_entry_byval (e->processor, f->type, value, &f->range);
61133965Sjdp	  if (r)
61233965Sjdp	    strcat (s, r->name);
61333965Sjdp	  else
61460484Sobrien	    sprintf (s, "%s$%lu", s, value);
61533965Sjdp	  break;
61633965Sjdp	case e_addr:
61777298Sobrien	  /* Use assembler's symbol table to find symbol.  */
61877298Sobrien	  /* FIXME!! Do we need this?  If so, what about relocs??  */
61977298Sobrien	  /* If not a symbol, fall through to IMMED.  */
62033965Sjdp	case e_immed:
62160484Sobrien	  sprintf (s, "%s0x%lx", s, value);
62233965Sjdp	  break;
62333965Sjdp	default:
62433965Sjdp	  return 0;		/* error; invalid field spec */
62533965Sjdp	}
62633965Sjdp    }
62777298Sobrien  return 1;			/* Done!  */
62833965Sjdp}
62933965Sjdp
63033965Sjdp/*======================================================================*/
63133965Sjdp/*
63233965Sjdp * Local functions for manipulating private structures containing
63333965Sjdp * the names and format for the new instructions and registers
63433965Sjdp * for each processor.
63533965Sjdp */
63633965Sjdp
63733965Sjdp/* Calculate instruction's opcode and function values from entry */
63833965Sjdp
63977298Sobrienstatic unsigned long
64033965Sjdpbuild_opcode (struct itbl_entry *e)
64133965Sjdp{
64233965Sjdp  unsigned long opcode;
64333965Sjdp
64433965Sjdp  opcode = apply_range (e->value, e->range);
64533965Sjdp  opcode |= ITBL_ENCODE_PNUM (e->processor);
64633965Sjdp  return opcode;
64733965Sjdp}
64833965Sjdp
64933965Sjdp/* Calculate absolute value given the relative value and bit position range
65033965Sjdp * within the instruction.
65133965Sjdp * The range is inclusive where 0 is least significant bit.
65233965Sjdp * A range of { 24, 20 } will have a mask of
65333965Sjdp * bit   3           2            1
65433965Sjdp * pos: 1098 7654 3210 9876 5432 1098 7654 3210
65533965Sjdp * bin: 0000 0001 1111 0000 0000 0000 0000 0000
65633965Sjdp * hex:    0    1    f    0    0    0    0    0
65733965Sjdp * mask: 0x01f00000.
65833965Sjdp */
65933965Sjdp
66077298Sobrienstatic unsigned long
66133965Sjdpapply_range (unsigned long rval, struct itbl_range r)
66233965Sjdp{
66333965Sjdp  unsigned long mask;
66433965Sjdp  unsigned long aval;
66533965Sjdp  int len = MAX_BITPOS - r.sbit;
66633965Sjdp
66733965Sjdp  ASSERT (r.sbit >= r.ebit);
66833965Sjdp  ASSERT (MAX_BITPOS >= r.sbit);
66933965Sjdp  ASSERT (r.ebit >= 0);
67033965Sjdp
67133965Sjdp  /* create mask by truncating 1s by shifting */
67233965Sjdp  mask = 0xffffffff << len;
67333965Sjdp  mask = mask >> len;
67433965Sjdp  mask = mask >> r.ebit;
67533965Sjdp  mask = mask << r.ebit;
67633965Sjdp
67733965Sjdp  aval = (rval << r.ebit) & mask;
67833965Sjdp  return aval;
67933965Sjdp}
68033965Sjdp
68133965Sjdp/* Calculate relative value given the absolute value and bit position range
68233965Sjdp * within the instruction.  */
68333965Sjdp
68477298Sobrienstatic unsigned long
68533965Sjdpextract_range (unsigned long aval, struct itbl_range r)
68633965Sjdp{
68733965Sjdp  unsigned long mask;
68833965Sjdp  unsigned long rval;
68933965Sjdp  int len = MAX_BITPOS - r.sbit;
69033965Sjdp
69133965Sjdp  /* create mask by truncating 1s by shifting */
69233965Sjdp  mask = 0xffffffff << len;
69333965Sjdp  mask = mask >> len;
69433965Sjdp  mask = mask >> r.ebit;
69533965Sjdp  mask = mask << r.ebit;
69633965Sjdp
69733965Sjdp  rval = (aval & mask) >> r.ebit;
69833965Sjdp  return rval;
69933965Sjdp}
70033965Sjdp
70133965Sjdp/* Extract processor's assembly instruction field name from s;
70233965Sjdp * forms are "n args" "n,args" or "n" */
70333965Sjdp/* Return next argument from string pointer "s" and advance s.
70460484Sobrien * delimiters are " ,()" */
70533965Sjdp
70633965Sjdpchar *
70733965Sjdpitbl_get_field (char **S)
70833965Sjdp{
70933965Sjdp  static char n[128];
71060484Sobrien  char *s;
71133965Sjdp  int len;
71233965Sjdp
71333965Sjdp  s = *S;
71433965Sjdp  if (!s || !*s)
71533965Sjdp    return 0;
71660484Sobrien  /* FIXME: This is a weird set of delimiters.  */
71760484Sobrien  len = strcspn (s, " \t,()");
71833965Sjdp  ASSERT (128 > len + 1);
71933965Sjdp  strncpy (n, s, len);
72033965Sjdp  n[len] = 0;
72133965Sjdp  if (s[len] == '\0')
72233965Sjdp    s = 0;			/* no more args */
72333965Sjdp  else
72433965Sjdp    s += len + 1;		/* advance to next arg */
72533965Sjdp
72633965Sjdp  *S = s;
72733965Sjdp  return n;
72833965Sjdp}
72933965Sjdp
73033965Sjdp/* Search entries for a given processor and type
73133965Sjdp * to find one matching the name "n".
73233965Sjdp * Return a pointer to the entry */
73333965Sjdp
73433965Sjdpstatic struct itbl_entry *
73533965Sjdpfind_entry_byname (e_processor processor,
73633965Sjdp		   e_type type, char *n)
73733965Sjdp{
73833965Sjdp  struct itbl_entry *e, **es;
73933965Sjdp
74033965Sjdp  es = get_entries (processor, type);
74177298Sobrien  for (e = *es; e; e = e->next)	/* for each entry, ...  */
74233965Sjdp    {
74333965Sjdp      if (!strcmp (e->name, n))
74433965Sjdp	return e;
74533965Sjdp    }
74633965Sjdp  return 0;
74733965Sjdp}
74833965Sjdp
74933965Sjdp/* Search entries for a given processor and type
75033965Sjdp * to find one matching the value "val" for the range "r".
75133965Sjdp * Return a pointer to the entry.
75233965Sjdp * This function is used for disassembling fields of an instruction.
75333965Sjdp */
75433965Sjdp
75533965Sjdpstatic struct itbl_entry *
75633965Sjdpfind_entry_byval (e_processor processor, e_type type,
75733965Sjdp		  unsigned long val, struct itbl_range *r)
75833965Sjdp{
75933965Sjdp  struct itbl_entry *e, **es;
76033965Sjdp  unsigned long eval;
76133965Sjdp
76233965Sjdp  es = get_entries (processor, type);
76377298Sobrien  for (e = *es; e; e = e->next)	/* for each entry, ...  */
76433965Sjdp    {
76533965Sjdp      if (processor != e->processor)
76633965Sjdp	continue;
76733965Sjdp      /* For insns, we might not know the range of the opcode,
76833965Sjdp	 * so a range of 0 will allow this routine to match against
76933965Sjdp	 * the range of the entry to be compared with.
77033965Sjdp	 * This could cause ambiguities.
77133965Sjdp	 * For operands, we get an extracted value and a range.
77233965Sjdp	 */
77377298Sobrien      /* if range is 0, mask val against the range of the compared entry.  */
77433965Sjdp      if (r == 0)		/* if no range passed, must be whole 32-bits
77533965Sjdp			 * so create 32-bit value from entry's range */
77633965Sjdp	{
77733965Sjdp	  eval = apply_range (e->value, e->range);
77833965Sjdp	  val &= apply_range (0xffffffff, e->range);
77933965Sjdp	}
78060484Sobrien      else if ((r->sbit == e->range.sbit && r->ebit == e->range.ebit)
78160484Sobrien	       || (e->range.sbit == 0 && e->range.ebit == 0))
78233965Sjdp	{
78333965Sjdp	  eval = apply_range (e->value, *r);
78433965Sjdp	  val = apply_range (val, *r);
78533965Sjdp	}
78633965Sjdp      else
78733965Sjdp	continue;
78833965Sjdp      if (val == eval)
78933965Sjdp	return e;
79033965Sjdp    }
79133965Sjdp  return 0;
79233965Sjdp}
79333965Sjdp
79477298Sobrien/* Return a pointer to the list of entries for a given processor and type.  */
79533965Sjdp
79633965Sjdpstatic struct itbl_entry **
79733965Sjdpget_entries (e_processor processor, e_type type)
79833965Sjdp{
79933965Sjdp  return &entries[processor][type];
80033965Sjdp}
80133965Sjdp
80277298Sobrien/* Return an integral value for the processor passed from yyparse.  */
80333965Sjdp
80477298Sobrienstatic e_processor
80533965Sjdpget_processor (int yyproc)
80633965Sjdp{
80733965Sjdp  /* translate from yacc's processor to enum */
80833965Sjdp  if (yyproc >= e_p0 && yyproc < e_nprocs)
80933965Sjdp    return (e_processor) yyproc;
81033965Sjdp  return e_invproc;		/* error; invalid processor */
81133965Sjdp}
81233965Sjdp
81377298Sobrien/* Return an integral value for the entry type passed from yyparse.  */
81433965Sjdp
81577298Sobrienstatic e_type
81633965Sjdpget_type (int yytype)
81733965Sjdp{
81833965Sjdp  switch (yytype)
81933965Sjdp    {
82033965Sjdp      /* translate from yacc's type to enum */
82133965Sjdp    case INSN:
82233965Sjdp      return e_insn;
82333965Sjdp    case DREG:
82433965Sjdp      return e_dreg;
82533965Sjdp    case CREG:
82633965Sjdp      return e_creg;
82733965Sjdp    case GREG:
82833965Sjdp      return e_greg;
82933965Sjdp    case ADDR:
83033965Sjdp      return e_addr;
83133965Sjdp    case IMMED:
83233965Sjdp      return e_immed;
83333965Sjdp    default:
83433965Sjdp      return e_invtype;		/* error; invalid type */
83533965Sjdp    }
83633965Sjdp}
83733965Sjdp
83833965Sjdp/* Allocate and initialize an entry */
83933965Sjdp
84033965Sjdpstatic struct itbl_entry *
84133965Sjdpalloc_entry (e_processor processor, e_type type,
84233965Sjdp	     char *name, unsigned long value)
84333965Sjdp{
84433965Sjdp  struct itbl_entry *e, **es;
84533965Sjdp  if (!name)
84633965Sjdp    return 0;
84733965Sjdp  e = (struct itbl_entry *) malloc (sizeof (struct itbl_entry));
84833965Sjdp  if (e)
84933965Sjdp    {
85033965Sjdp      memset (e, 0, sizeof (struct itbl_entry));
85133965Sjdp      e->name = (char *) malloc (sizeof (strlen (name)) + 1);
85233965Sjdp      if (e->name)
85333965Sjdp	strcpy (e->name, name);
85433965Sjdp      e->processor = processor;
85533965Sjdp      e->type = type;
85633965Sjdp      e->value = value;
85733965Sjdp      es = get_entries (e->processor, e->type);
85833965Sjdp      e->next = *es;
85933965Sjdp      *es = e;
86033965Sjdp    }
86133965Sjdp  return e;
86233965Sjdp}
86333965Sjdp
86433965Sjdp/* Allocate and initialize an entry's field */
86533965Sjdp
86633965Sjdpstatic struct itbl_field *
86733965Sjdpalloc_field (e_type type, int sbit, int ebit,
86833965Sjdp	     unsigned long flags)
86933965Sjdp{
87033965Sjdp  struct itbl_field *f;
87133965Sjdp  f = (struct itbl_field *) malloc (sizeof (struct itbl_field));
87233965Sjdp  if (f)
87333965Sjdp    {
87433965Sjdp      memset (f, 0, sizeof (struct itbl_field));
87533965Sjdp      f->type = type;
87633965Sjdp      f->range.sbit = sbit;
87733965Sjdp      f->range.ebit = ebit;
87833965Sjdp      f->flags = flags;
87933965Sjdp    }
88033965Sjdp  return f;
88133965Sjdp}
882