Allow stm.l and ldm.l insns to accept parentheses enclosed register lists.

This commit is contained in:
Nick Clifton
2002-05-31 14:29:58 +00:00
parent 149add75fa
commit 3048287aca
2 changed files with 93 additions and 81 deletions

View File

@ -1,3 +1,8 @@
2002-05-31 Shrinivas Atre <ShrinivasA@kpit.com>
* config/tc-h8300.c (get_operand): Allow stm.l and ldm.l insns to
accept parentheses enclosed register lists.
2002-05-31 Alan Modra <amodra@bigpond.net.au> 2002-05-31 Alan Modra <amodra@bigpond.net.au>
* Makefile.am: Run "make dep-am". * Makefile.am: Run "make dep-am".

View File

@ -38,24 +38,24 @@ const char comment_chars[] = ";";
const char line_comment_chars[] = "#"; const char line_comment_chars[] = "#";
const char line_separator_chars[] = ""; const char line_separator_chars[] = "";
/* This table describes all the machine specific pseudo-ops the assembler void cons PARAMS ((int));
has to support. The fields are: void sbranch PARAMS ((int));
pseudo-op name without dot void h8300hmode PARAMS ((int));
function to call to execute this pseudo-op void h8300smode PARAMS ((int));
Integer arg to pass to the function static void pint PARAMS ((int));
*/
void cons ();
int Hmode; int Hmode;
int Smode; int Smode;
#define PSIZE (Hmode ? L_32 : L_16) #define PSIZE (Hmode ? L_32 : L_16)
#define DMODE (L_16) #define DMODE (L_16)
#define DSYMMODE (Hmode ? L_24 : L_16) #define DSYMMODE (Hmode ? L_24 : L_16)
int bsize = L_8; /* default branch displacement */ int bsize = L_8; /* default branch displacement */
void void
h8300hmode () h8300hmode (arg)
int arg ATTRIBUTE_UNUSED;
{ {
Hmode = 1; Hmode = 1;
Smode = 0; Smode = 0;
@ -66,7 +66,8 @@ h8300hmode ()
} }
void void
h8300smode () h8300smode (arg)
int arg ATTRIBUTE_UNUSED;
{ {
Smode = 1; Smode = 1;
Hmode = 1; Hmode = 1;
@ -84,11 +85,18 @@ sbranch (size)
} }
static void static void
pint () pint (arg)
int arg ATTRIBUTE_UNUSED;
{ {
cons (Hmode ? 4 : 2); cons (Hmode ? 4 : 2);
} }
/* This table describes all the machine specific pseudo-ops the assembler
has to support. The fields are:
pseudo-op name without dot
function to call to execute this pseudo-op
Integer arg to pass to the function. */
const pseudo_typeS md_pseudo_table[] = const pseudo_typeS md_pseudo_table[] =
{ {
{"h8300h", h8300hmode, 0}, {"h8300h", h8300hmode, 0},
@ -112,16 +120,17 @@ const int md_reloc_size;
const char EXP_CHARS[] = "eE"; const char EXP_CHARS[] = "eE";
/* Chars that mean this number is a floating point constant */ /* Chars that mean this number is a floating point constant
/* As in 0f12.456 */ As in 0f12.456
/* or 0d1.2345e12 */ or 0d1.2345e12. */
const char FLT_CHARS[] = "rRsSfFdDxXpP"; const char FLT_CHARS[] = "rRsSfFdDxXpP";
static struct hash_control *opcode_hash_control; /* Opcode mnemonics */ static struct hash_control *opcode_hash_control; /* Opcode mnemonics. */
/* This function is called once, at assembler startup time. This /* This function is called once, at assembler startup time. This
should set up all the tables, etc. that the MD part of the assembler should set up all the tables, etc. that the MD part of the assembler
needs. */ needs. */
void void
md_begin () md_begin ()
{ {
@ -188,7 +197,7 @@ struct h8_exp
}; };
int dispreg; int dispreg;
int opsize; /* Set when a register size is seen */ int opsize; /* Set when a register size is seen. */
struct h8_op struct h8_op
{ {
@ -197,6 +206,18 @@ struct h8_op
expressionS exp; expressionS exp;
}; };
static void clever_message PARAMS ((struct h8_opcode *, struct h8_op *));
static void build_bytes PARAMS ((struct h8_opcode *, struct h8_op *));
static void do_a_fix_imm PARAMS ((int, struct h8_op *, int));
static void check_operand PARAMS ((struct h8_op *, unsigned int, char *));
static struct h8_opcode * get_specific PARAMS ((struct h8_opcode *, struct h8_op *, int));
static char * get_operands PARAMS ((unsigned, char *, struct h8_op *));
static void get_operand PARAMS ((char **, struct h8_op *, unsigned, 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 *));
/* /*
parse operands parse operands
WREG r0,r1,r2,r3,r4,r5,r6,r7,fp,sp WREG r0,r1,r2,r3,r4,r5,r6,r7,fp,sp
@ -216,7 +237,6 @@ parse_reg (src, mode, reg, direction)
op_type *mode; op_type *mode;
unsigned int *reg; unsigned int *reg;
int direction; int direction;
{ {
char *end; char *end;
int len; int len;
@ -329,7 +349,7 @@ skip_colonthing (ptr, exp, mode)
if (*ptr == '8') if (*ptr == '8')
{ {
ptr++; ptr++;
/* ff fill any 8 bit quantity */ /* ff fill any 8 bit quantity. */
/* exp->X_add_number -= 0x100; */ /* exp->X_add_number -= 0x100; */
*mode |= L_8; *mode |= L_8;
} }
@ -367,15 +387,12 @@ skip_colonthing (ptr, exp, mode)
#xx[:size] immediate data #xx[:size] immediate data
@(exp:[8], pc) pc rel @(exp:[8], pc) pc rel
@@aa[:8] memory indirect @@aa[:8] memory indirect. */
*/
char * char *
colonmod24 (op, src) colonmod24 (op, src)
struct h8_op *op; struct h8_op *op;
char *src; char *src;
{ {
int mode = 0; int mode = 0;
src = skip_colonthing (src, &op->exp, &mode); src = skip_colonthing (src, &op->exp, &mode);
@ -397,9 +414,9 @@ colonmod24 (op, src)
else else
mode = DMODE; mode = DMODE;
} }
op->mode |= mode; op->mode |= mode;
return src; return src;
} }
static void static void
@ -416,6 +433,10 @@ get_operand (ptr, op, dst, direction)
op->mode = E; op->mode = E;
/* Check for '(' and ')' for instructions ldm and stm. */
if (src[0] == '(' && src[8] == ')')
++ src;
/* Gross. Gross. ldm and stm have a format not easily handled /* Gross. Gross. ldm and stm have a format not easily handled
by get_operand. We deal with it explicitly here. */ by get_operand. We deal with it explicitly here. */
if (src[0] == 'e' && src[1] == 'r' && ISDIGIT (src[2]) if (src[0] == 'e' && src[1] == 'r' && ISDIGIT (src[2])
@ -445,6 +466,9 @@ get_operand (ptr, op, dst, direction)
so we know this is "very special". */ so we know this is "very special". */
op->reg = 0x80000000 | (high << 8) | low; op->reg = 0x80000000 | (high << 8) | low;
op->mode = REG; op->mode = REG;
if (src[7] == ')')
*ptr = src + 8;
else
*ptr = src + 7; *ptr = src + 7;
return; return;
} }
@ -613,14 +637,11 @@ get_operand (ptr, op, dst, direction)
src += 2; src += 2;
} }
else else
{
as_bad (_("expect :8 or :16 here")); as_bad (_("expect :8 or :16 here"));
} }
}
else else
{
op->mode = PCREL | bsize; op->mode = PCREL | bsize;
}
*ptr = src; *ptr = src;
} }
} }
@ -672,6 +693,7 @@ get_operands (noperands, op_end, operand)
/* Passed a pointer to a list of opcodes which use different /* Passed a pointer to a list of opcodes which use different
addressing modes, return the opcode which matches the opcodes addressing modes, return the opcode which matches the opcodes
provided. */ provided. */
static struct h8_opcode * static struct h8_opcode *
get_specific (opcode, operands, size) get_specific (opcode, operands, size)
struct h8_opcode *opcode; struct h8_opcode *opcode;
@ -680,8 +702,7 @@ get_specific (opcode, operands, size)
{ {
struct h8_opcode *this_try = opcode; struct h8_opcode *this_try = opcode;
int found = 0; int found = 0;
int this_index = opcode->idx;
unsigned int this_index = opcode->idx;
/* There's only one ldm/stm and it's easier to just /* There's only one ldm/stm and it's easier to just
get out quick for them. */ get out quick for them. */
@ -704,7 +725,7 @@ get_specific (opcode, operands, size)
} }
else else
{ {
unsigned int i; int i;
for (i = 0; i < this_try->noperands && found; i++) for (i = 0; i < this_try->noperands && found; i++)
{ {
@ -804,7 +825,7 @@ check_operand (operand, width, string)
fs. */ fs. */
if ((operand->exp.X_add_number & ~width) != 0 && if ((operand->exp.X_add_number & ~width) != 0 &&
(operand->exp.X_add_number | width) != (~0)) (operand->exp.X_add_number | width) != (unsigned)(~0))
{ {
if (width == 255 if (width == 255
&& (operand->exp.X_add_number & 0xff00) == 0xff00) && (operand->exp.X_add_number & 0xff00) == 0xff00)
@ -940,20 +961,20 @@ do_a_fix_imm (offset, operand, relaxmode)
} }
/* Now we know what sort of opcodes it is, let's build the bytes. */ /* Now we know what sort of opcodes it is, let's build the bytes. */
static void static void
build_bytes (this_try, operand) build_bytes (this_try, operand)
struct h8_opcode *this_try; struct h8_opcode *this_try;
struct h8_op *operand; struct h8_op *operand;
{ {
unsigned int i; int i;
char *output = frag_more (this_try->length); char *output = frag_more (this_try->length);
op_type *nibble_ptr = this_try->data.nib; op_type *nibble_ptr = this_try->data.nib;
op_type c; op_type c;
unsigned int nibble_count = 0; unsigned int nibble_count = 0;
int absat; int absat = 0;
int immat; int immat = 0;
int nib; int nib = 0;
int movb = 0; int movb = 0;
char asnibbles[30]; char asnibbles[30];
char *p = asnibbles; char *p = asnibbles;
@ -970,19 +991,15 @@ build_bytes (this_try, operand)
d = (c & (DST | SRC_IN_DST)) != 0; d = (c & (DST | SRC_IN_DST)) != 0;
if (c < 16) if (c < 16)
{
nib = c; nib = c;
}
else else
{ {
if (c & (REG | IND | INC | DEC)) if (c & (REG | IND | INC | DEC))
{
nib = operand[d].reg; nib = operand[d].reg;
}
else if ((c & DISPREG) == (DISPREG)) else if ((c & DISPREG) == (DISPREG))
{
nib = dispreg; nib = dispreg;
}
else if (c & ABS) else if (c & ABS)
{ {
operand[d].mode = c; operand[d].mode = c;
@ -996,9 +1013,8 @@ build_bytes (this_try, operand)
nib = 0; nib = 0;
} }
else if (c & IGNORE) else if (c & IGNORE)
{
nib = 0; nib = 0;
}
else if (c & DBIT) else if (c & DBIT)
{ {
switch (operand[0].exp.X_add_number) switch (operand[0].exp.X_add_number)
@ -1038,14 +1054,10 @@ build_bytes (this_try, operand)
} }
if (c & MEMRELAX) if (c & MEMRELAX)
{
operand[d].mode |= MEMRELAX; operand[d].mode |= MEMRELAX;
}
if (c & B31) if (c & B31)
{
nib |= 0x8; nib |= 0x8;
}
if (c & MACREG) if (c & MACREG)
{ {
@ -1076,9 +1088,7 @@ build_bytes (this_try, operand)
} }
for (i = 0; i < this_try->length; i++) for (i = 0; i < this_try->length; i++)
{
output[i] = (asnibbles[i * 2] << 4) | asnibbles[i * 2 + 1]; output[i] = (asnibbles[i * 2] << 4) | asnibbles[i * 2 + 1];
}
/* Note if this is a movb instruction -- there's a special relaxation /* Note if this is a movb instruction -- there's a special relaxation
which only applies to them. */ which only applies to them. */
@ -1091,18 +1101,16 @@ build_bytes (this_try, operand)
int x = operand[i].mode; int x = operand[i].mode;
if (x & (IMM | DISP)) if (x & (IMM | DISP))
{
do_a_fix_imm (output - frag_now->fr_literal + immat, do_a_fix_imm (output - frag_now->fr_literal + immat,
operand + i, x & MEMRELAX != 0); operand + i, (x & MEMRELAX) != 0);
}
else if (x & ABS) else if (x & ABS)
{
do_a_fix_imm (output - frag_now->fr_literal + absat, do_a_fix_imm (output - frag_now->fr_literal + absat,
operand + i, x & MEMRELAX ? movb + 1 : 0); operand + i, (x & MEMRELAX) ? movb + 1 : 0);
}
else if (x & PCREL) else if (x & PCREL)
{ {
int size16 = x & L_16; int size16 = x & (L_16);
int where = size16 ? 2 : 1; int where = size16 ? 2 : 1;
int size = size16 ? 2 : 1; int size = size16 ? 2 : 1;
int type = size16 ? R_PCRWORD : R_PCRBYTE; int type = size16 ? R_PCRWORD : R_PCRBYTE;
@ -1111,11 +1119,8 @@ build_bytes (this_try, operand)
check_operand (operand + i, size16 ? 0x7fff : 0x7f, "@"); check_operand (operand + i, size16 ? 0x7fff : 0x7f, "@");
if (operand[i].exp.X_add_number & 1) if (operand[i].exp.X_add_number & 1)
{
as_warn (_("branch operand has odd offset (%lx)\n"), as_warn (_("branch operand has odd offset (%lx)\n"),
(unsigned long) operand->exp.X_add_number); (unsigned long) operand->exp.X_add_number);
}
#ifndef OBJ_ELF #ifndef OBJ_ELF
/* The COFF port has always been off by one, changing it /* The COFF port has always been off by one, changing it
now would be an incompatible change, so we leave it as-is. now would be an incompatible change, so we leave it as-is.
@ -1124,7 +1129,6 @@ build_bytes (this_try, operand)
compatible with the proposed ELF format from Hitachi. */ compatible with the proposed ELF format from Hitachi. */
operand[i].exp.X_add_number -= 1; operand[i].exp.X_add_number -= 1;
#endif #endif
operand[i].exp.X_add_number = operand[i].exp.X_add_number =
((operand[i].exp.X_add_number & 0xff) ^ 0x80) - 0x80; ((operand[i].exp.X_add_number & 0xff) ^ 0x80) - 0x80;
@ -1160,11 +1164,11 @@ build_bytes (this_try, operand)
/* This jmp may be a jump or a branch. */ /* This jmp may be a jump or a branch. */
check_operand (operand + i, Hmode ? 0xffffff : 0xffff, "@"); check_operand (operand + i, Hmode ? 0xffffff : 0xffff, "@");
if (operand[i].exp.X_add_number & 1) if (operand[i].exp.X_add_number & 1)
{
as_warn (_("branch operand has odd offset (%lx)\n"), as_warn (_("branch operand has odd offset (%lx)\n"),
(unsigned long) operand->exp.X_add_number); (unsigned long) operand->exp.X_add_number);
}
if (!Hmode) if (!Hmode)
operand[i].exp.X_add_number = operand[i].exp.X_add_number =
((operand[i].exp.X_add_number & 0xffff) ^ 0x8000) - 0x8000; ((operand[i].exp.X_add_number & 0xffff) ^ 0x8000) - 0x8000;
@ -1180,6 +1184,7 @@ build_bytes (this_try, operand)
/* Try to give an intelligent error message for common and simple to /* Try to give an intelligent error message for common and simple to
detect errors. */ detect errors. */
static void static void
clever_message (opcode, operand) clever_message (opcode, operand)
struct h8_opcode *opcode; struct h8_opcode *opcode;
@ -1189,7 +1194,7 @@ clever_message (opcode, operand)
if ((opcode + 1)->idx != opcode->idx) if ((opcode + 1)->idx != opcode->idx)
{ {
unsigned int argn; int argn;
/* Only one opcode of this flavour, try to guess which operand /* Only one opcode of this flavour, try to guess which operand
didn't match. */ didn't match. */
@ -1246,6 +1251,7 @@ clever_message (opcode, operand)
/* This is the guts of the machine-dependent assembler. STR points to /* This is the guts of the machine-dependent assembler. STR points to
a machine dependent instruction. This function is supposed to emit a machine dependent instruction. This function is supposed to emit
the frags/bytes it assembles. */ the frags/bytes it assembles. */
void void
md_assemble (str) md_assemble (str)
char *str; char *str;
@ -1388,7 +1394,6 @@ md_atof (type, litP, sizeP)
LITTLENUM_TYPE words[MAX_LITTLENUMS]; LITTLENUM_TYPE words[MAX_LITTLENUMS];
LITTLENUM_TYPE *wordP; LITTLENUM_TYPE *wordP;
char *t; char *t;
char *atof_ieee ();
switch (type) switch (type)
{ {
@ -1454,6 +1459,8 @@ md_show_usage (stream)
{ {
} }
void tc_aout_fix_to_chars PARAMS ((void));
void void
tc_aout_fix_to_chars () tc_aout_fix_to_chars ()
{ {