* cgen-asm.c: Include symcat.h.

* cgen-dis.c,cgen-opc.c,cgen-asm.in,cgen-dis.in: Ditto.
This commit is contained in:
Doug Evans 1998-02-23 21:17:29 +00:00
parent 677c3439a7
commit 833d299073
3 changed files with 123 additions and 77 deletions

View File

@ -1,3 +1,8 @@
Mon Feb 23 13:16:17 1998 Doug Evans <devans@seba.cygnus.com>
* cgen-asm.c: Include symcat.h.
* cgen-dis.c,cgen-opc.c,cgen-asm.in,cgen-dis.in: Ditto.
start-sanitize-sky
Mon Feb 23 09:51:39 1998 Doug Evans <devans@canuck.cygnus.com>

View File

@ -3,7 +3,7 @@
This file is used to generate @arch@-asm.c.
Copyright (C) 1996, 1997 Free Software Foundation, Inc.
Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
This file is part of the GNU Binutils and GDB, the GNU debugger.
@ -26,6 +26,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include <stdio.h>
#include "ansidecl.h"
#include "bfd.h"
#include "symcat.h"
#include "@arch@-opc.h"
/* ??? The layout of this stuff is still work in progress.
@ -35,33 +36,66 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
compiled with GCC), or switch to macros, or use something else.
*/
static const char *parse_insn_normal
static const char * parse_insn_normal
PARAMS ((const CGEN_INSN *, const char **, CGEN_FIELDS *));
static void insert_insn_normal
static const char * insert_insn_normal
PARAMS ((const CGEN_INSN *, CGEN_FIELDS *, cgen_insn_t *));
/* Default insertion routine.
SHIFT is negative for left shifts, positive for right shifts.
All bits of VALUE to be inserted must be valid as we don't handle
signed vs unsigned shifts.
ATTRS is a mask of the boolean attributes.
LENGTH is the length of VALUE in bits.
TOTAL_LENGTH is the total length of the insn (currently 8,16,32).
ATTRS is a mask of the boolean attributes. We don't need any at the
moment, but for consistency with extract_normal we have them. */
The result is an error message or NULL if success. */
/* FIXME: This duplicates functionality with bfd's howto table and
/* ??? This duplicates functionality with bfd's howto table and
bfd_install_relocation. */
/* FIXME: For architectures where insns can be representable as ints,
store insn in `field' struct and add registers, etc. while parsing. */
/* ??? For architectures where insns can be representable as ints,
store insn in `field' struct and add registers, etc. while parsing? */
static CGEN_INLINE void
static const char *
insert_normal (value, attrs, start, length, shift, total_length, buffer)
long value;
unsigned int attrs;
int start, length, shift, total_length;
char *buffer;
int start;
int length;
int shift;
int total_length;
char * buffer;
{
bfd_vma x;
static char buf[100];
if (shift < 0)
value <<= -shift;
else
value >>= shift;
/* Ensure VALUE will fit. */
if ((attrs & (1 << CGEN_OPERAND_UNSIGNED)) != 0)
{
unsigned long max = (1 << length) - 1;
if ((unsigned long) value > max)
{
const char *err = "operand out of range (%lu not between 0 and %lu)";
sprintf (buf, err, value, max);
return buf;
}
}
else
{
long min = - (1 << (length - 1));
long max = (1 << (length - 1)) - 1;
if (value < min || value > max)
{
const char *err = "operand out of range (%ld not between %ld and %ld)";
sprintf (buf, err, value, min, max);
return buf;
}
}
#if 0 /*def CGEN_INT_INSN*/
*buffer |= ((value & ((1 << length) - 1))
@ -70,7 +104,7 @@ insert_normal (value, attrs, start, length, shift, total_length, buffer)
switch (total_length)
{
case 8:
x = *(unsigned char *) buffer;
x = * (unsigned char *) buffer;
break;
case 16:
if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG)
@ -88,18 +122,13 @@ insert_normal (value, attrs, start, length, shift, total_length, buffer)
abort ();
}
if (shift < 0)
value <<= -shift;
else
value >>= shift;
x |= ((value & ((1 << length) - 1))
<< (total_length - (start + length)));
switch (total_length)
{
case 8:
*buffer = value;
* buffer = value;
break;
case 16:
if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG)
@ -117,6 +146,8 @@ insert_normal (value, attrs, start, length, shift, total_length, buffer)
abort ();
}
#endif
return NULL;
}
/* -- assembler routines inserted here */
@ -137,15 +168,15 @@ insert_normal (value, attrs, start, length, shift, total_length, buffer)
static const char *
parse_insn_normal (insn, strp, fields)
const CGEN_INSN *insn;
const char **strp;
CGEN_FIELDS *fields;
const CGEN_INSN * insn;
const char ** strp;
CGEN_FIELDS * fields;
{
const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
const char *str = *strp;
const char *errmsg;
const char *p;
const unsigned char *syn;
const CGEN_SYNTAX * syntax = CGEN_INSN_SYNTAX (insn);
const char * str = *strp;
const char * errmsg;
const char * p;
const unsigned char * syn;
#ifdef CGEN_MNEMONIC_OPERANDS
int past_opcode_p;
#endif
@ -153,9 +184,9 @@ parse_insn_normal (insn, strp, fields)
/* For now we assume the mnemonic is first (there are no leading operands).
We can parse it without needing to set up operand parsing. */
p = CGEN_INSN_MNEMONIC (insn);
while (*p && *p == *str)
++p, ++str;
if (*p || (*str && !isspace (*str)))
while (* p && * p == * str)
++ p, ++ str;
if (* p || (* str && !isspace (* str)))
return "unrecognized instruction";
CGEN_INIT_PARSE ();
@ -167,29 +198,33 @@ parse_insn_normal (insn, strp, fields)
/* We don't check for (*str != '\0') here because we want to parse
any trailing fake arguments in the syntax string. */
syn = CGEN_SYNTAX_STRING (CGEN_INSN_SYNTAX (insn));
/* Mnemonics come first for now, ensure valid string. */
if (! CGEN_SYNTAX_MNEMONIC_P (*syn))
if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
abort ();
++syn;
while (*syn != 0)
while (* syn != 0)
{
/* Non operand chars must match exactly. */
/* FIXME: Need to better handle whitespace. */
if (CGEN_SYNTAX_CHAR_P (*syn))
if (CGEN_SYNTAX_CHAR_P (* syn))
{
if (*str == CGEN_SYNTAX_CHAR (*syn))
if (*str == CGEN_SYNTAX_CHAR (* syn))
{
#ifdef CGEN_MNEMONIC_OPERANDS
if (*syn == ' ')
if (* syn == ' ')
past_opcode_p = 1;
#endif
++syn;
++str;
++ syn;
++ str;
}
else
{
/* Syntax char didn't match. Can't be this insn. */
/* FIXME: would like to return "expected char `c'" */
/* FIXME: would like to return something like
"expected char `c'" */
return "syntax error";
}
continue;
@ -202,20 +237,20 @@ parse_insn_normal (insn, strp, fields)
return errmsg;
/* Done with this operand, continue with next one. */
++syn;
++ syn;
}
/* If we're at the end of the syntax string, we're done. */
if (*syn == '\0')
if (* syn == '\0')
{
/* FIXME: For the moment we assume a valid `str' can only contain
blanks now. IE: We needn't try again with a longer version of
the insn and it is assumed that longer versions of insns appear
before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */
while (isspace (*str))
++str;
while (isspace (* str))
++ str;
if (*str != '\0')
if (* str != '\0')
return "junk at end of line"; /* FIXME: would like to include `str' */
return NULL;
@ -226,17 +261,19 @@ parse_insn_normal (insn, strp, fields)
}
/* Default insn builder (insert handler).
The instruction is recorded in target byte order. */
The instruction is recorded in target byte order.
The result is an error message or NULL if success. */
/* FIXME: change buffer to char *? */
static void
static const char *
insert_insn_normal (insn, fields, buffer)
const CGEN_INSN *insn;
CGEN_FIELDS *fields;
cgen_insn_t *buffer;
const CGEN_INSN * insn;
CGEN_FIELDS * fields;
cgen_insn_t * buffer;
{
const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
const CGEN_SYNTAX * syntax = CGEN_INSN_SYNTAX (insn);
bfd_vma value;
const unsigned char *syn;
const unsigned char * syn;
CGEN_INIT_INSERT ();
value = CGEN_INSN_VALUE (insn);
@ -251,7 +288,7 @@ insert_insn_normal (insn, fields, buffer)
switch (min (CGEN_BASE_INSN_BITSIZE, CGEN_FIELDS_BITSIZE (fields)))
{
case 8:
*buffer = value;
* buffer = value;
break;
case 16:
if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG)
@ -273,13 +310,20 @@ insert_insn_normal (insn, fields, buffer)
/* ??? Rather than scanning the syntax string again, we could store
in `fields' a null terminated list of the fields that are present. */
for (syn = CGEN_SYNTAX_STRING (syntax); *syn != '\0'; ++syn)
for (syn = CGEN_SYNTAX_STRING (syntax); * syn != '\0'; ++ syn)
{
if (CGEN_SYNTAX_CHAR_P (*syn))
const char *errmsg;
if (CGEN_SYNTAX_CHAR_P (* syn))
continue;
@arch@_cgen_insert_operand (CGEN_SYNTAX_FIELD (*syn), fields, buffer);
errmsg = @arch@_cgen_insert_operand (CGEN_SYNTAX_FIELD (*syn), fields,
(char *) buffer);
if (errmsg)
return errmsg;
}
return NULL;
}
/* Main entry point.
@ -292,17 +336,17 @@ insert_insn_normal (insn, fields, buffer)
const CGEN_INSN *
@arch@_cgen_assemble_insn (str, fields, buf, errmsg)
const char *str;
CGEN_FIELDS *fields;
cgen_insn_t *buf;
char **errmsg;
const char * str;
CGEN_FIELDS * fields;
cgen_insn_t * buf;
char ** errmsg;
{
const char *start;
CGEN_INSN_LIST *ilist;
const char * start;
CGEN_INSN_LIST * ilist;
/* Skip leading white space. */
while (isspace (*str))
++str;
while (isspace (* str))
++ str;
/* The instructions are stored in hashed lists.
Get the first in the list. */
@ -336,16 +380,10 @@ const CGEN_INSN *
/* FIXME: wip */
CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
/* ??? The extent to which moving the parse and insert handlers into
this function (thus removing the function call) will speed things up
is unclear. The simplicity and flexibility of the current scheme is
appropriate for now. One could have the best of both worlds with
inline functions but of course that would only work for gcc. Since
we're machine generating some code we could do that here too. Maybe
later. */
if (! (*CGEN_PARSE_FN (insn)) (insn, &str, fields))
if (! CGEN_PARSE_FN (insn) (insn, & str, fields))
{
(*CGEN_INSERT_FN (insn)) (insn, fields, buf);
if (CGEN_INSERT_FN (insn) (insn, fields, buf) != NULL)
continue;
/* It is up to the caller to actually output the insn and any
queued relocs. */
return insn;
@ -376,12 +414,12 @@ const CGEN_INSN *
void
@arch@_cgen_asm_hash_keywords (opvals)
CGEN_KEYWORD *opvals;
CGEN_KEYWORD * opvals;
{
CGEN_KEYWORD_SEARCH search = cgen_keyword_search_init (opvals, NULL);
const CGEN_KEYWORD_ENTRY *ke;
const CGEN_KEYWORD_ENTRY * ke;
while ((ke = cgen_keyword_search_next (&search)) != NULL)
while ((ke = cgen_keyword_search_next (& search)) != NULL)
{
#if 0 /* Unnecessary, should be done in the search routine. */
if (! @arch@_cgen_opval_supported (ke))

View File

@ -26,6 +26,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "ansidecl.h"
#include "dis-asm.h"
#include "bfd.h"
#include "symcat.h"
#include "@arch@-opc.h"
/* ??? The layout of this stuff is still work in progress.
@ -87,6 +88,8 @@ extract_normal (buf_ctrl, insn_value, attrs, start, length, shift, total_length,
value <<= shift;
*valuep = value;
/* FIXME: for now */
return 1;
}
@ -166,7 +169,7 @@ extract_insn_normal (insn, buf_ctrl, insn_value, fields)
continue;
length = @arch@_cgen_extract_operand (CGEN_SYNTAX_FIELD (*syn),
buf_ctrl, insn_value, fields);
buf_ctrl, insn_value, fields);
if (length == 0)
return 0;
}