This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Patch to clean up h8300 pasing code
- From: Richard Sandiford <rsandifo at redhat dot com>
- To: binutils at sources dot redhat dot com
- Date: 04 Jul 2003 10:18:17 +0100
- Subject: Patch to clean up h8300 pasing code
This patch is supposed to clean up the h8300 parsing code a bit.
At the moment there are four functions that guess a constant's size:
- colonmod24 (absolute addresses and some displacements)
- get_operand (pc-relative addresses)
- fix_operand_size (short displacements)
- get_specific (immediates)
As a result, each call to parse_exp() could be followed by one of
three different bits of size-reading code, depending on what kind
of guess was needed:
- skip_colonthing (immediates - no guess)
- colonmod24 (addresses and displacements - sometimes guess)
- inline code (pc-relative addresses - always guess)
I found it difficult to figure out when an operand's size was valid
and when it wasn't. And my recent fix_operand_size() patch didn't
make things any easier.
Anyway, the patch changes things so that:
- the parsing code never guesses the size of operands
- fix_operand_size() guesses the size of everything except immediates
- get_specific() works out the size of immediates
In other words, there are now two places that guess the size rather than
four. And since the parsing code no longer guesses the size of anything,
the size-reading code can be folded into parse_exp().
There shouldn't really be a need for a separate call to skip_colonthing()
after these changes. However, we seem to accept:
mov.w @(foo,er0:16),r0l
as another way of writing:
mov.w @(foo:16,er0),r0l
so there is one other call remaining.
One minor change in behaviour: we no longer accept "xx:160" as "xx:16".
I don't think there are any others though.
Patch tested on h8300-elf and h8300-coff. I also ran it through the sim
& gcc testsuites. OK to install?
Richard
* config/tc-h8300.c (h8300sxnmode): Add prototype.
(DSYMMODE): Remove.
(parse_exp): Replace expressionS argument with a h8_op. Parse the
operand size as well.
(skip_colonthing): Remove unused expression argument. Tighten
checks for 2-digit sizes.
(colonmod24): Remove.
(get_mova_operands): Combine calls to parse_exp and skip_colonthing.
(get_operand): Likewise. Use the standard code to read the size of
pc-relative operands.
(fix_operand_size): Include the size-guessing logic that used to be
in colonmod24 and get_operand().
Index: gas/config/tc-h8300.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-h8300.c,v
retrieving revision 1.33
diff -c -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.33 tc-h8300.c
*** gas/config/tc-h8300.c 25 Jun 2003 15:31:58 -0000 1.33
--- gas/config/tc-h8300.c 4 Jul 2003 08:14:17 -0000
*************** const char comment_chars[] = ";";
*** 43,56 ****
const char line_comment_chars[] = "#";
const char line_separator_chars[] = "";
! void cons PARAMS ((int));
! void sbranch PARAMS ((int));
! void h8300hmode PARAMS ((int));
! void h8300smode PARAMS ((int));
! void h8300hnmode PARAMS ((int));
! void h8300snmode PARAMS ((int));
! void h8300sxmode PARAMS ((int));
! static void pint PARAMS ((int));
int Hmode;
int Smode;
--- 43,57 ----
const char line_comment_chars[] = "#";
const char line_separator_chars[] = "";
! void cons PARAMS ((int));
! void sbranch PARAMS ((int));
! void h8300hmode PARAMS ((int));
! void h8300smode PARAMS ((int));
! void h8300hnmode PARAMS ((int));
! void h8300snmode PARAMS ((int));
! void h8300sxmode PARAMS ((int));
! void h8300sxnmode PARAMS ((int));
! static void pint PARAMS ((int));
int Hmode;
int Smode;
*************** int Nmode;
*** 58,64 ****
int SXmode;
#define PSIZE (Hmode ? L_32 : L_16)
- #define DSYMMODE (Hmode ? L_24 : L_16)
int bsize = L_8; /* Default branch displacement. */
--- 59,64 ----
*************** static void build_bytes PARAMS ((cons
*** 339,350 ****
static void do_a_fix_imm PARAMS ((int, int, struct h8_op *, int));
static void check_operand PARAMS ((struct h8_op *, unsigned int, char *));
static const struct h8_instruction * get_specific PARAMS ((const struct h8_instruction *, struct h8_op *, int));
! static char * get_operands PARAMS ((unsigned, char *, struct h8_op *));
! static void get_operand PARAMS ((char **, struct h8_op *, int));
! static char * skip_colonthing PARAMS ((char *, expressionS *, int *));
! static char * parse_exp PARAMS ((char *, expressionS *));
! static int parse_reg PARAMS ((char *, op_type *, unsigned *, int));
! char * colonmod24 PARAMS ((struct h8_op *, char *));
static int constant_fits_width_p PARAMS ((struct h8_op *, unsigned int));
static int constant_fits_size_p PARAMS ((struct h8_op *, int, int));
--- 339,349 ----
static void do_a_fix_imm PARAMS ((int, int, struct h8_op *, int));
static void check_operand PARAMS ((struct h8_op *, unsigned int, char *));
static const struct h8_instruction * get_specific PARAMS ((const struct h8_instruction *, struct h8_op *, int));
! static char *get_operands PARAMS ((unsigned, char *, struct h8_op *));
! static void get_operand PARAMS ((char **, struct h8_op *, int));
! static int parse_reg PARAMS ((char *, op_type *, unsigned *, int));
! static char *skip_colonthing PARAMS ((char *, int *));
! static char *parse_exp PARAMS ((char *, struct h8_op *));
static int constant_fits_width_p PARAMS ((struct h8_op *, unsigned int));
static int constant_fits_size_p PARAMS ((struct h8_op *, int, int));
*************** parse_reg (src, mode, reg, direction)
*** 474,529 ****
return 0;
}
static char *
! parse_exp (s, op)
! char *s;
! expressionS *op;
{
! char *save = input_line_pointer;
! char *new;
! input_line_pointer = s;
! expression (op);
! if (op->X_op == O_absent)
as_bad (_("missing operand"));
! new = input_line_pointer;
input_line_pointer = save;
! return new;
}
static char *
! skip_colonthing (ptr, exp, mode)
! char *ptr;
! expressionS *exp ATTRIBUTE_UNUSED;
int *mode;
{
! if (*ptr == ':')
{
! ptr++;
*mode &= ~SIZE;
! if (ptr[0] == '8' && ! ISDIGIT (ptr[1]))
*mode |= L_8;
! else if (ptr[0] == '2' && ! ISDIGIT (ptr[1]))
*mode |= L_2;
! else if (ptr[0] == '3' && ! ISDIGIT (ptr[1]))
*mode |= L_3;
! else if (ptr[0] == '4' && ! ISDIGIT (ptr[1]))
*mode |= L_4;
! else if (ptr[0] == '5' && ! ISDIGIT (ptr[1]))
*mode |= L_5;
! else if (ptr[0] == '2' && ptr[1] == '4')
*mode |= L_24;
! else if (ptr[0] == '3' && ptr[1] == '2')
*mode |= L_32;
! else if (ptr[0] == '1' && ptr[1] == '6')
*mode |= L_16;
else
as_bad (_("invalid operand size requested"));
! while (ISDIGIT (*ptr))
! ptr++;
}
! return ptr;
}
/* The many forms of operand:
--- 473,537 ----
return 0;
}
+
+ /* Parse an immediate or address-related constant and store it in OP.
+ If the user also specifies the operand's size, store that size
+ in OP->MODE, otherwise leave it for later code to decide. */
+
static char *
! parse_exp (src, op)
! char *src;
! struct h8_op *op;
{
! char *save;
! save = input_line_pointer;
! input_line_pointer = src;
! expression (&op->exp);
! if (op->exp.X_op == O_absent)
as_bad (_("missing operand"));
! src = input_line_pointer;
input_line_pointer = save;
!
! return skip_colonthing (src, &op->mode);
}
+
+ /* If SRC starts with an explicit operand size, skip it and store the size
+ in *MODE. Leave *MODE unchanged otherwise. */
+
static char *
! skip_colonthing (src, mode)
! char *src;
int *mode;
{
! if (*src == ':')
{
! src++;
*mode &= ~SIZE;
! if (src[0] == '8' && !ISDIGIT (src[1]))
*mode |= L_8;
! else if (src[0] == '2' && !ISDIGIT (src[1]))
*mode |= L_2;
! else if (src[0] == '3' && !ISDIGIT (src[1]))
*mode |= L_3;
! else if (src[0] == '4' && !ISDIGIT (src[1]))
*mode |= L_4;
! else if (src[0] == '5' && !ISDIGIT (src[1]))
*mode |= L_5;
! else if (src[0] == '2' && src[1] == '4' && !ISDIGIT (src[2]))
*mode |= L_24;
! else if (src[0] == '3' && src[1] == '2' && !ISDIGIT (src[2]))
*mode |= L_32;
! else if (src[0] == '1' && src[1] == '6' && !ISDIGIT (src[2]))
*mode |= L_16;
else
as_bad (_("invalid operand size requested"));
! while (ISDIGIT (*src))
! src++;
}
! return src;
}
/* The many forms of operand:
*************** skip_colonthing (ptr, exp, mode)
*** 541,575 ****
@(exp:[8], pc) pc rel
@@aa[:8] memory indirect. */
- char *
- colonmod24 (op, src)
- struct h8_op *op;
- char *src;
- {
- int mode = 0;
- src = skip_colonthing (src, &op->exp, &mode);
-
- if (!mode)
- {
- /* If the operand is a 16-bit constant integer, leave fix_operand_size
- to calculate its size. Otherwise choose a default here. */
- if (op->exp.X_add_number < -32768
- || op->exp.X_add_number > 32767)
- {
- if (Hmode)
- mode = L_24;
- else
- mode = L_16;
- }
- else if (op->exp.X_add_symbol
- || op->exp.X_op_symbol)
- mode = DSYMMODE;
- }
-
- op->mode |= mode;
- return src;
- }
-
static int
constant_fits_width_p (operand, width)
struct h8_op *operand;
--- 549,554 ----
*************** get_operand (ptr, op, direction)
*** 707,719 ****
src++;
if (*src == '@')
{
! src++;
! src = parse_exp (src, &op->exp);
!
! src = skip_colonthing (src, &op->exp, &op->mode);
!
! *ptr = src;
!
if (op->exp.X_add_number >= 0x100)
{
int divisor;
--- 686,692 ----
src++;
if (*src == '@')
{
! *ptr = parse_exp (src + 1, op);
if (op->exp.X_add_number >= 0x100)
{
int divisor;
*************** get_operand (ptr, op, direction)
*** 731,762 ****
}
else
op->mode = MEMIND;
-
return;
}
if (*src == '-' || *src == '+')
{
! char c = *src;
! src++;
! len = parse_reg (src, &mode, &num, direction);
if (len == 0)
{
/* Oops, not a reg after all, must be ordinary exp. */
! src--;
! /* Must be a symbol. */
! op->mode = ABS | PSIZE | direction;
! *ptr = skip_colonthing (parse_exp (src, &op->exp),
! &op->exp, &op->mode);
!
return;
}
if ((mode & SIZE) != PSIZE)
as_bad (_("Wrong size pointer register for architecture."));
! op->mode = c == '-' ? RDPREDEC : RDPREINC;
op->reg = num;
! *ptr = src + len;
return;
}
if (*src == '(')
--- 704,729 ----
}
else
op->mode = MEMIND;
return;
}
if (*src == '-' || *src == '+')
{
! len = parse_reg (src + 1, &mode, &num, direction);
if (len == 0)
{
/* Oops, not a reg after all, must be ordinary exp. */
! op->mode = ABS | direction;
! *ptr = parse_exp (src, op);
return;
}
if ((mode & SIZE) != PSIZE)
as_bad (_("Wrong size pointer register for architecture."));
!
! op->mode = src[0] == '-' ? RDPREDEC : RDPREINC;
op->reg = num;
! *ptr = src + 1 + len;
return;
}
if (*src == '(')
*************** get_operand (ptr, op, direction)
*** 801,815 ****
/* Start off assuming a 16 bit offset. */
! src = parse_exp (src, &op->exp);
!
! src = colonmod24 (op, src);
!
if (*src == ')')
{
- src++;
op->mode |= ABS | direction;
! *ptr = src;
return;
}
--- 768,778 ----
/* Start off assuming a 16 bit offset. */
! src = parse_exp (src, op);
if (*src == ')')
{
op->mode |= ABS | direction;
! *ptr = src + 1;
return;
}
*************** get_operand (ptr, op, direction)
*** 817,823 ****
{
as_bad (_("expected @(exp, reg16)"));
return;
-
}
src++;
--- 780,785 ----
*************** get_operand (ptr, op, direction)
*** 849,855 ****
}
else
op->mode |= DISP | direction;
! src = skip_colonthing (src, &op->exp, &op->mode);
if (*src != ')' && '(')
{
--- 811,817 ----
}
else
op->mode |= DISP | direction;
! src = skip_colonthing (src, &op->mode);
if (*src != ')' && '(')
{
*************** get_operand (ptr, op, direction)
*** 857,863 ****
return;
}
*ptr = src + 1;
-
return;
}
len = parse_reg (src, &mode, &num, direction);
--- 819,824 ----
*************** get_operand (ptr, op, direction)
*** 889,909 ****
/* must be a symbol */
op->mode = ABS | direction;
! src = parse_exp (src, &op->exp);
!
! *ptr = colonmod24 (op, src);
!
return;
}
}
if (*src == '#')
{
- src++;
op->mode = IMM;
! src = parse_exp (src, &op->exp);
! *ptr = skip_colonthing (src, &op->exp, &op->mode);
!
return;
}
else if (strncmp (src, "mach", 4) == 0 ||
--- 850,864 ----
/* must be a symbol */
op->mode = ABS | direction;
! *ptr = parse_exp (src, op);
return;
}
}
if (*src == '#')
{
op->mode = IMM;
! *ptr = parse_exp (src + 1, op);
return;
}
else if (strncmp (src, "mach", 4) == 0 ||
*************** get_operand (ptr, op, direction)
*** 918,952 ****
}
else
{
! src = parse_exp (src, &op->exp);
! /* Trailing ':' size ? */
! if (*src == ':')
! {
! if (src[1] == '1' && src[2] == '6')
! {
! op->mode = PCREL | L_16;
! src += 3;
! }
! else if (src[1] == '8')
! {
! op->mode = PCREL | L_8;
! src += 2;
! }
! else
! as_bad (_("expect :8 or :16 here"));
! }
! else
! {
! int val = op->exp.X_add_number;
!
! op->mode = PCREL;
! if (-128 < val && val < 127)
! op->mode |= L_8;
! else
! op->mode |= L_16;
! }
!
! *ptr = src;
}
}
--- 873,880 ----
}
else
{
! op->mode = PCREL;
! *ptr = parse_exp (src, op);
}
}
*************** get_mova_operands (char *op_end, struct
*** 1010,1017 ****
goto error;
ptr += 3;
operand[0].mode = 0;
! ptr = parse_exp (ptr, &operand[0].exp);
! ptr = colonmod24 (operand + 0, ptr);
if (*ptr !=',')
goto error;
--- 938,944 ----
goto error;
ptr += 3;
operand[0].mode = 0;
! ptr = parse_exp (ptr, &operand[0]);
if (*ptr !=',')
goto error;
*************** clever_message (instruction, operand)
*** 1880,1890 ****
}
! /* Adjust OPERAND's value and size given that it is accessing a field
! of SIZE bytes.
! This function handles the choice between @(d:2,ERn) and @(d:16,ERn)
! when no size is explicitly given. It also scales down the assembly-level
displacement in an @(d:2,ERn) operand. */
static void
--- 1807,1817 ----
}
! /* If OPERAND is part of an address, adjust its size and value given
! that it addresses SIZE bytes.
! This function decides how big non-immediate constants are when no
! size was explicitly given. It also scales down the assembly-level
displacement in an @(d:2,ERn) operand. */
static void
*************** fix_operand_size (operand, size)
*** 1892,1903 ****
struct h8_op *operand;
int size;
{
! if ((operand->mode & MODE) == DISP)
{
/* If the user didn't specify an operand width, see if we
can use @(d:2,ERn). */
! if (SXmode
! && (operand->mode & SIZE) == 0
&& (operand->exp.X_add_number == size
|| operand->exp.X_add_number == size * 2
|| operand->exp.X_add_number == size * 3))
--- 1819,1829 ----
struct h8_op *operand;
int size;
{
! if (SXmode && (operand->mode & MODE) == DISP)
{
/* If the user didn't specify an operand width, see if we
can use @(d:2,ERn). */
! if ((operand->mode & SIZE) == 0
&& (operand->exp.X_add_number == size
|| operand->exp.X_add_number == size * 2
|| operand->exp.X_add_number == size * 3))
*************** fix_operand_size (operand, size)
*** 1913,1920 ****
}
}
- /* If the operand needs a size but doesn't have one yet, it must be
- a 16-bit integer (see colonmod24). */
if ((operand->mode & SIZE) == 0)
switch (operand->mode & MODE)
{
--- 1839,1844 ----
*************** fix_operand_size (operand, size)
*** 1923,1929 ****
case INDEXW:
case INDEXL:
case ABS:
! operand->mode |= L_16;
break;
}
}
--- 1847,1872 ----
case INDEXW:
case INDEXL:
case ABS:
! /* Pick a 24-bit address unless we know that a 16-bit address
! is safe. get_specific() will relax L_24 into L_32 where
! necessary. */
! if (Hmode
! && (operand->exp.X_add_number < -32768
! || operand->exp.X_add_number > 32767
! || operand->exp.X_add_symbol != 0
! || operand->exp.X_op_symbol != 0))
! operand->mode |= L_24;
! else
! operand->mode |= L_16;
! break;
!
! case PCREL:
! /* This condition is long standing, though somewhat suspect. */
! if (operand->exp.X_add_number > -128
! && operand->exp.X_add_number < 127)
! operand->mode |= L_8;
! else
! operand->mode |= L_16;
break;
}
}