* 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 start-sanitize-sky
Mon Feb 23 09:51:39 1998 Doug Evans <devans@canuck.cygnus.com> 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. 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. 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 <stdio.h>
#include "ansidecl.h" #include "ansidecl.h"
#include "bfd.h" #include "bfd.h"
#include "symcat.h"
#include "@arch@-opc.h" #include "@arch@-opc.h"
/* ??? The layout of this stuff is still work in progress. /* ??? 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. 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 *)); 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 *)); PARAMS ((const CGEN_INSN *, CGEN_FIELDS *, cgen_insn_t *));
/* Default insertion routine. /* Default insertion routine.
SHIFT is negative for left shifts, positive for right shifts. ATTRS is a mask of the boolean attributes.
All bits of VALUE to be inserted must be valid as we don't handle LENGTH is the length of VALUE in bits.
signed vs unsigned shifts. 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 The result is an error message or NULL if success. */
moment, but for consistency with extract_normal we have them. */
/* FIXME: This duplicates functionality with bfd's howto table and /* ??? This duplicates functionality with bfd's howto table and
bfd_install_relocation. */ bfd_install_relocation. */
/* FIXME: For architectures where insns can be representable as ints, /* ??? For architectures where insns can be representable as ints,
store insn in `field' struct and add registers, etc. while parsing. */ 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) insert_normal (value, attrs, start, length, shift, total_length, buffer)
long value; long value;
unsigned int attrs; unsigned int attrs;
int start, length, shift, total_length; int start;
char *buffer; int length;
int shift;
int total_length;
char * buffer;
{ {
bfd_vma x; 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*/ #if 0 /*def CGEN_INT_INSN*/
*buffer |= ((value & ((1 << length) - 1)) *buffer |= ((value & ((1 << length) - 1))
@ -70,7 +104,7 @@ insert_normal (value, attrs, start, length, shift, total_length, buffer)
switch (total_length) switch (total_length)
{ {
case 8: case 8:
x = *(unsigned char *) buffer; x = * (unsigned char *) buffer;
break; break;
case 16: case 16:
if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG) if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG)
@ -88,18 +122,13 @@ insert_normal (value, attrs, start, length, shift, total_length, buffer)
abort (); abort ();
} }
if (shift < 0)
value <<= -shift;
else
value >>= shift;
x |= ((value & ((1 << length) - 1)) x |= ((value & ((1 << length) - 1))
<< (total_length - (start + length))); << (total_length - (start + length)));
switch (total_length) switch (total_length)
{ {
case 8: case 8:
*buffer = value; * buffer = value;
break; break;
case 16: case 16:
if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG) if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG)
@ -117,6 +146,8 @@ insert_normal (value, attrs, start, length, shift, total_length, buffer)
abort (); abort ();
} }
#endif #endif
return NULL;
} }
/* -- assembler routines inserted here */ /* -- assembler routines inserted here */
@ -137,15 +168,15 @@ insert_normal (value, attrs, start, length, shift, total_length, buffer)
static const char * static const char *
parse_insn_normal (insn, strp, fields) parse_insn_normal (insn, strp, fields)
const CGEN_INSN *insn; const CGEN_INSN * insn;
const char **strp; const char ** strp;
CGEN_FIELDS *fields; CGEN_FIELDS * fields;
{ {
const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn); const CGEN_SYNTAX * syntax = CGEN_INSN_SYNTAX (insn);
const char *str = *strp; const char * str = *strp;
const char *errmsg; const char * errmsg;
const char *p; const char * p;
const unsigned char *syn; const unsigned char * syn;
#ifdef CGEN_MNEMONIC_OPERANDS #ifdef CGEN_MNEMONIC_OPERANDS
int past_opcode_p; int past_opcode_p;
#endif #endif
@ -153,9 +184,9 @@ parse_insn_normal (insn, strp, fields)
/* For now we assume the mnemonic is first (there are no leading operands). /* For now we assume the mnemonic is first (there are no leading operands).
We can parse it without needing to set up operand parsing. */ We can parse it without needing to set up operand parsing. */
p = CGEN_INSN_MNEMONIC (insn); p = CGEN_INSN_MNEMONIC (insn);
while (*p && *p == *str) while (* p && * p == * str)
++p, ++str; ++ p, ++ str;
if (*p || (*str && !isspace (*str))) if (* p || (* str && !isspace (* str)))
return "unrecognized instruction"; return "unrecognized instruction";
CGEN_INIT_PARSE (); 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 /* We don't check for (*str != '\0') here because we want to parse
any trailing fake arguments in the syntax string. */ any trailing fake arguments in the syntax string. */
syn = CGEN_SYNTAX_STRING (CGEN_INSN_SYNTAX (insn)); syn = CGEN_SYNTAX_STRING (CGEN_INSN_SYNTAX (insn));
/* Mnemonics come first for now, ensure valid string. */ /* Mnemonics come first for now, ensure valid string. */
if (! CGEN_SYNTAX_MNEMONIC_P (*syn)) if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
abort (); abort ();
++syn; ++syn;
while (*syn != 0)
while (* syn != 0)
{ {
/* Non operand chars must match exactly. */ /* Non operand chars must match exactly. */
/* FIXME: Need to better handle whitespace. */ /* 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 #ifdef CGEN_MNEMONIC_OPERANDS
if (*syn == ' ') if (* syn == ' ')
past_opcode_p = 1; past_opcode_p = 1;
#endif #endif
++syn; ++ syn;
++str; ++ str;
} }
else else
{ {
/* Syntax char didn't match. Can't be this insn. */ /* 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"; return "syntax error";
} }
continue; continue;
@ -202,20 +237,20 @@ parse_insn_normal (insn, strp, fields)
return errmsg; return errmsg;
/* Done with this operand, continue with next one. */ /* Done with this operand, continue with next one. */
++syn; ++ syn;
} }
/* If we're at the end of the syntax string, we're done. */ /* 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 /* 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 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 the insn and it is assumed that longer versions of insns appear
before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */ before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */
while (isspace (*str)) while (isspace (* str))
++str; ++ str;
if (*str != '\0') if (* str != '\0')
return "junk at end of line"; /* FIXME: would like to include `str' */ return "junk at end of line"; /* FIXME: would like to include `str' */
return NULL; return NULL;
@ -226,17 +261,19 @@ parse_insn_normal (insn, strp, fields)
} }
/* Default insn builder (insert handler). /* 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) insert_insn_normal (insn, fields, buffer)
const CGEN_INSN *insn; const CGEN_INSN * insn;
CGEN_FIELDS *fields; CGEN_FIELDS * fields;
cgen_insn_t *buffer; cgen_insn_t * buffer;
{ {
const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn); const CGEN_SYNTAX * syntax = CGEN_INSN_SYNTAX (insn);
bfd_vma value; bfd_vma value;
const unsigned char *syn; const unsigned char * syn;
CGEN_INIT_INSERT (); CGEN_INIT_INSERT ();
value = CGEN_INSN_VALUE (insn); 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))) switch (min (CGEN_BASE_INSN_BITSIZE, CGEN_FIELDS_BITSIZE (fields)))
{ {
case 8: case 8:
*buffer = value; * buffer = value;
break; break;
case 16: case 16:
if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG) 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 /* ??? Rather than scanning the syntax string again, we could store
in `fields' a null terminated list of the fields that are present. */ 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; 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. /* Main entry point.
@ -292,17 +336,17 @@ insert_insn_normal (insn, fields, buffer)
const CGEN_INSN * const CGEN_INSN *
@arch@_cgen_assemble_insn (str, fields, buf, errmsg) @arch@_cgen_assemble_insn (str, fields, buf, errmsg)
const char *str; const char * str;
CGEN_FIELDS *fields; CGEN_FIELDS * fields;
cgen_insn_t *buf; cgen_insn_t * buf;
char **errmsg; char ** errmsg;
{ {
const char *start; const char * start;
CGEN_INSN_LIST *ilist; CGEN_INSN_LIST * ilist;
/* Skip leading white space. */ /* Skip leading white space. */
while (isspace (*str)) while (isspace (* str))
++str; ++ str;
/* The instructions are stored in hashed lists. /* The instructions are stored in hashed lists.
Get the first in the list. */ Get the first in the list. */
@ -336,16 +380,10 @@ const CGEN_INSN *
/* FIXME: wip */ /* FIXME: wip */
CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn); CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
/* ??? The extent to which moving the parse and insert handlers into if (! CGEN_PARSE_FN (insn) (insn, & str, fields))
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))
{ {
(*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 /* It is up to the caller to actually output the insn and any
queued relocs. */ queued relocs. */
return insn; return insn;
@ -376,12 +414,12 @@ const CGEN_INSN *
void void
@arch@_cgen_asm_hash_keywords (opvals) @arch@_cgen_asm_hash_keywords (opvals)
CGEN_KEYWORD *opvals; CGEN_KEYWORD * opvals;
{ {
CGEN_KEYWORD_SEARCH search = cgen_keyword_search_init (opvals, NULL); 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 0 /* Unnecessary, should be done in the search routine. */
if (! @arch@_cgen_opval_supported (ke)) 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 "ansidecl.h"
#include "dis-asm.h" #include "dis-asm.h"
#include "bfd.h" #include "bfd.h"
#include "symcat.h"
#include "@arch@-opc.h" #include "@arch@-opc.h"
/* ??? The layout of this stuff is still work in progress. /* ??? 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; value <<= shift;
*valuep = value; *valuep = value;
/* FIXME: for now */
return 1; return 1;
} }
@ -166,7 +169,7 @@ extract_insn_normal (insn, buf_ctrl, insn_value, fields)
continue; continue;
length = @arch@_cgen_extract_operand (CGEN_SYNTAX_FIELD (*syn), length = @arch@_cgen_extract_operand (CGEN_SYNTAX_FIELD (*syn),
buf_ctrl, insn_value, fields); buf_ctrl, insn_value, fields);
if (length == 0) if (length == 0)
return 0; return 0;
} }