* config/tc-m68k.c (m68k_abspcadd): New static variable.
(m68k_quick): New static variable. (m68k_rel32): New static variable. (md_pseudo_table): Add opt and reg. (m68k_ip): Permit absolute symbols in 'l'/'L' recognition. Check m68k_quick in 'M' and 'Q' recognition. Check m68k_abspcadd in DISP handling. Check m68k_rel32 in BASE/POST/PRE handling. (md_begin): In MRI mode, initialize m68k_abspcadd and m68k_rel32. In MRI mode, change unsized branch aliases to be variable sized. (struct opt_action): Define. (opt_table): Define. (s_opt): New static function. (skip_to_comma): New static function. (opt_chip): New static function. (opt_list): New static function. (opt_list_symbols): New static function. (s_reg): New static function. * as.h (flag_keep_locals): Change from unsigned char to int. (flag_no_warnings): Likewise.
This commit is contained in:
parent
69e077f3c7
commit
6700d36e84
@ -1,5 +1,35 @@
|
||||
Wed Aug 9 10:51:48 1995 Ian Lance Taylor <ian@cygnus.com>
|
||||
|
||||
* config/tc-m68k.c (m68k_abspcadd): New static variable.
|
||||
(m68k_quick): New static variable.
|
||||
(m68k_rel32): New static variable.
|
||||
(md_pseudo_table): Add opt and reg.
|
||||
(m68k_ip): Permit absolute symbols in 'l'/'L' recognition. Check
|
||||
m68k_quick in 'M' and 'Q' recognition. Check m68k_abspcadd in
|
||||
DISP handling. Check m68k_rel32 in BASE/POST/PRE handling.
|
||||
(md_begin): In MRI mode, initialize m68k_abspcadd and m68k_rel32.
|
||||
In MRI mode, change unsized branch aliases to be variable sized.
|
||||
(struct opt_action): Define.
|
||||
(opt_table): Define.
|
||||
(s_opt): New static function.
|
||||
(skip_to_comma): New static function.
|
||||
(opt_chip): New static function.
|
||||
(opt_list): New static function.
|
||||
(opt_list_symbols): New static function.
|
||||
(s_reg): New static function.
|
||||
* as.h (flag_keep_locals): Change from unsigned char to int.
|
||||
(flag_no_warnings): Likewise.
|
||||
|
||||
* read.c (mri_line_label): Make non-static.
|
||||
(potable): Add nopage, page, plen.
|
||||
(s_org): Error if in MRI mode.
|
||||
* read.h (mri_line_label): Declare.
|
||||
* listing.c (listing_nopage): New function.
|
||||
* listing.h (listing_nopage): Declare.
|
||||
|
||||
* symbols.c (symbol_begin): Set sy_frag of abs_symbol to
|
||||
&zero_address_frag.
|
||||
|
||||
* write.c (adjust_reloc_syms): Check that symbol is not NULL
|
||||
before checking sy_mri_common.
|
||||
(fixup_segment): Likewise.
|
||||
|
@ -76,6 +76,19 @@ int flag_reg_prefix_optional;
|
||||
/* The floating point coprocessor to use by default. */
|
||||
static enum m68k_register m68k_float_copnum = COP1;
|
||||
|
||||
/* If this is non-zero, then references to number(%pc) will be taken
|
||||
to refer to number, rather than to %pc + number. */
|
||||
static int m68k_abspcadd;
|
||||
|
||||
/* If this is non-zero, then the quick forms of the move, add, and sub
|
||||
instructions are used when possible. */
|
||||
static int m68k_quick = 1;
|
||||
|
||||
/* If this is non-zero, then if the size is not specified for a base
|
||||
or outer displacement, the assembler assumes that the size should
|
||||
be 32 bits. */
|
||||
static int m68k_rel32 = 1;
|
||||
|
||||
/* Its an arbitrary name: This means I don't approve of it */
|
||||
/* See flames below */
|
||||
static struct obstack robyn;
|
||||
@ -280,6 +293,8 @@ static void s_proc PARAMS ((int));
|
||||
static void mri_chip PARAMS ((void));
|
||||
static void s_chip PARAMS ((int));
|
||||
static void s_fopt PARAMS ((int));
|
||||
static void s_opt PARAMS ((int));
|
||||
static void s_reg PARAMS ((int));
|
||||
|
||||
static int current_architecture;
|
||||
|
||||
@ -410,6 +425,8 @@ CONST pseudo_typeS md_pseudo_table[] =
|
||||
{"comline", s_space, 1},
|
||||
{"fopt", s_fopt, 0},
|
||||
{"mask2", s_ignore, 0},
|
||||
{"opt", s_opt, 0},
|
||||
{"reg", s_reg, 0},
|
||||
|
||||
{0, 0, 0}
|
||||
};
|
||||
@ -1036,6 +1053,14 @@ m68k_ip (instring)
|
||||
opP->mode = REGLST;
|
||||
}
|
||||
}
|
||||
else if (opP->mode == ABSL
|
||||
&& opP->disp.size == SIZE_UNSPEC
|
||||
&& opP->disp.exp.X_op == O_constant)
|
||||
{
|
||||
/* This is what the MRI REG pseudo-op generates. */
|
||||
opP->mode = REGLST;
|
||||
opP->mask = opP->disp.exp.X_add_number;
|
||||
}
|
||||
else if (opP->mode != REGLST)
|
||||
losing++;
|
||||
else if (s[1] == '8' && (opP->mask & 0x0ffffff) != 0)
|
||||
@ -1049,6 +1074,10 @@ m68k_ip (instring)
|
||||
losing++;
|
||||
else if (! expr8 (&opP->disp))
|
||||
losing++;
|
||||
else if (! m68k_quick
|
||||
&& instring[3] != 'q'
|
||||
&& instring[4] != 'q')
|
||||
losing++;
|
||||
break;
|
||||
|
||||
case 'O':
|
||||
@ -1063,6 +1092,11 @@ m68k_ip (instring)
|
||||
|| opP->disp.exp.X_add_number < 1
|
||||
|| opP->disp.exp.X_add_number > 8)
|
||||
losing++;
|
||||
else if (! m68k_quick
|
||||
&& (strncmp (instring, "add", 3) == 0
|
||||
|| strncmp (instring, "sub", 3) == 0)
|
||||
&& instring[3] != 'q')
|
||||
losing++;
|
||||
break;
|
||||
|
||||
case 'R':
|
||||
@ -1409,6 +1443,20 @@ m68k_ip (instring)
|
||||
case DISP:
|
||||
|
||||
nextword = get_num (&opP->disp, 80);
|
||||
|
||||
if (opP->reg == PC
|
||||
&& ! isvar (&opP->disp)
|
||||
&& m68k_abspcadd)
|
||||
{
|
||||
opP->disp.exp.X_op = O_symbol;
|
||||
#ifndef BFD_ASSEMBLER
|
||||
opP->disp.exp.X_add_symbol = &abs_symbol;
|
||||
#else
|
||||
opP->disp.exp.X_add_symbol =
|
||||
section_symbol (absolute_section);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Force into index mode. Hope this works */
|
||||
|
||||
/* We do the first bit for 32-bit displacements, and the
|
||||
@ -1621,12 +1669,14 @@ m68k_ip (instring)
|
||||
switch (siz1)
|
||||
{
|
||||
case SIZE_UNSPEC:
|
||||
if (isvar (&opP->disp) || !issword (baseo))
|
||||
if (isvar (&opP->disp)
|
||||
? m68k_rel32
|
||||
: ! issword (baseo))
|
||||
{
|
||||
siz1 = SIZE_LONG;
|
||||
nextword |= 0x30;
|
||||
}
|
||||
else if (baseo == 0)
|
||||
else if (! isvar (&opP->disp) && baseo == 0)
|
||||
nextword |= 0x10;
|
||||
else
|
||||
{
|
||||
@ -1651,12 +1701,14 @@ m68k_ip (instring)
|
||||
switch (siz2)
|
||||
{
|
||||
case SIZE_UNSPEC:
|
||||
if (isvar (&opP->odisp) || !issword (outro))
|
||||
if (isvar (&opP->odisp)
|
||||
? m68k_rel32
|
||||
: ! issword (outro))
|
||||
{
|
||||
siz2 = SIZE_LONG;
|
||||
nextword |= 0x3;
|
||||
}
|
||||
else if (outro == 0)
|
||||
else if (! isvar (&opP->disp) && outro == 0)
|
||||
nextword |= 0x1;
|
||||
else
|
||||
{
|
||||
@ -2842,7 +2894,11 @@ md_begin ()
|
||||
register char c;
|
||||
|
||||
if (flag_mri)
|
||||
flag_reg_prefix_optional = 1;
|
||||
{
|
||||
flag_reg_prefix_optional = 1;
|
||||
m68k_abspcadd = 1;
|
||||
m68k_rel32 = 0;
|
||||
}
|
||||
|
||||
op_hash = hash_new ();
|
||||
|
||||
@ -2890,6 +2946,43 @@ md_begin ()
|
||||
as_fatal ("Internal Error: Can't hash %s: %s", alias, retval);
|
||||
}
|
||||
|
||||
/* In MRI mode, all unsized branches are variable sized. Normally,
|
||||
they are word sized. */
|
||||
if (flag_mri)
|
||||
{
|
||||
static struct m68k_opcode_alias mri_aliases[] =
|
||||
{
|
||||
{ "bhi", "jhi", },
|
||||
{ "bls", "jls", },
|
||||
{ "bcc", "jcc", },
|
||||
{ "bcs", "jcs", },
|
||||
{ "bne", "jne", },
|
||||
{ "beq", "jeq", },
|
||||
{ "bvc", "jvc", },
|
||||
{ "bvs", "jvs", },
|
||||
{ "bpl", "jpl", },
|
||||
{ "bmi", "jmi", },
|
||||
{ "bge", "jge", },
|
||||
{ "blt", "jlt", },
|
||||
{ "bgt", "jgt", },
|
||||
{ "ble", "jle", },
|
||||
{ "bra", "jra", },
|
||||
{ "bsr", "jbsr", },
|
||||
};
|
||||
|
||||
for (i = 0; i < sizeof mri_aliases / sizeof mri_aliases[0]; i++)
|
||||
{
|
||||
const char *name = mri_aliases[i].primary;
|
||||
const char *alias = mri_aliases[i].alias;
|
||||
PTR val = hash_find (op_hash, name);
|
||||
if (!val)
|
||||
as_fatal ("Internal Error: Can't find %s in hash table", name);
|
||||
retval = hash_jam (op_hash, alias, val);
|
||||
if (retval)
|
||||
as_fatal ("Internal Error: Can't hash %s: %s", alias, retval);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof (mklower_table); i++)
|
||||
mklower_table[i] = (isupper (c = (char) i)) ? tolower (c) : c;
|
||||
|
||||
@ -4067,6 +4160,278 @@ s_fopt (ignore)
|
||||
|
||||
demand_empty_rest_of_line ();
|
||||
}
|
||||
|
||||
/* The structure used to handle the MRI OPT pseudo-op. */
|
||||
|
||||
struct opt_action
|
||||
{
|
||||
/* The name of the option. */
|
||||
const char *name;
|
||||
|
||||
/* If this is not NULL, just call this function. The first argument
|
||||
is the ARG field of this structure, the second argument is
|
||||
whether the option was negated. */
|
||||
void (*pfn) PARAMS ((int arg, int on));
|
||||
|
||||
/* If this is not NULL, and the PFN field is NULL, set the variable
|
||||
this points to. Set it to the ARG field if the option was not
|
||||
negated, and the NOTARG field otherwise. */
|
||||
int *pvar;
|
||||
|
||||
/* The value to pass to PFN or to assign to *PVAR. */
|
||||
int arg;
|
||||
|
||||
/* The value to assign to *PVAR if the option is negated. If PFN is
|
||||
NULL, and PVAR is not NULL, and ARG and NOTARG are the same, then
|
||||
the option may not be negated. */
|
||||
int notarg;
|
||||
};
|
||||
|
||||
/* The table used to handle the MRI OPT pseudo-op. */
|
||||
|
||||
static void skip_to_comma PARAMS ((int, int));
|
||||
static void opt_chip PARAMS ((int, int));
|
||||
static void opt_list PARAMS ((int, int));
|
||||
static void opt_list_symbols PARAMS ((int, int));
|
||||
|
||||
static const struct opt_action opt_table[] =
|
||||
{
|
||||
{ "abspcadd", 0, &m68k_abspcadd, 1, 0 },
|
||||
|
||||
/* We do relaxing, so there is little use for these options. */
|
||||
{ "b", 0, 0, 0, 0 },
|
||||
{ "brs", 0, 0, 0, 0 },
|
||||
{ "brb", 0, 0, 0, 0 },
|
||||
{ "brl", 0, 0, 0, 0 },
|
||||
{ "brw", 0, 0, 0, 0 },
|
||||
|
||||
{ "c", 0, 0, 0, 0 },
|
||||
{ "cex", 0, 0, 0, 0 },
|
||||
{ "case", 0, &symbols_case_sensitive, 1, 0 },
|
||||
{ "cl", 0, 0, 0, 0 },
|
||||
{ "cre", 0, 0, 0, 0 },
|
||||
{ "d", 0, &flag_keep_locals, 1, 0 },
|
||||
{ "e", 0, 0, 0, 0 },
|
||||
{ "f", 0, &flag_short_refs, 1, 0 },
|
||||
{ "frs", 0, &flag_short_refs, 1, 0 },
|
||||
{ "frl", 0, &flag_short_refs, 0, 1 },
|
||||
{ "g", 0, 0, 0, 0 },
|
||||
{ "i", 0, 0, 0, 0 },
|
||||
{ "m", 0, 0, 0, 0 },
|
||||
{ "mex", 0, 0, 0, 0 },
|
||||
{ "mc", 0, 0, 0, 0 },
|
||||
{ "md", 0, 0, 0, 0 },
|
||||
{ "next", skip_to_comma, 0, 0, 0 },
|
||||
{ "o", 0, 0, 0, 0 },
|
||||
{ "old", 0, 0, 0, 0 },
|
||||
{ "op", skip_to_comma, 0, 0, 0 },
|
||||
{ "pco", 0, 0, 0, 0 },
|
||||
{ "p", opt_chip, 0, 0, 0 },
|
||||
{ "pcr", 0, 0, 0, 0 },
|
||||
{ "pcs", 0, 0, 0, 0 },
|
||||
{ "r", 0, 0, 0, 0 },
|
||||
{ "quick", 0, &m68k_quick, 1, 0 },
|
||||
{ "rel32", 0, &m68k_rel32, 1, 0 },
|
||||
{ "s", opt_list, 0, 0, 0 },
|
||||
{ "t", opt_list_symbols, 0, 0, 0 },
|
||||
{ "w", 0, &flag_no_warnings, 0, 1 },
|
||||
{ "x", 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
#define OPTCOUNT (sizeof opt_table / sizeof opt_table[0])
|
||||
|
||||
/* The MRI OPT pseudo-op. */
|
||||
|
||||
static void
|
||||
s_opt (ignore)
|
||||
int ignore;
|
||||
{
|
||||
do
|
||||
{
|
||||
int t;
|
||||
char *s;
|
||||
char c;
|
||||
int i;
|
||||
const struct opt_action *o;
|
||||
|
||||
SKIP_WHITESPACE ();
|
||||
|
||||
t = 1;
|
||||
if (*input_line_pointer == '-')
|
||||
{
|
||||
++input_line_pointer;
|
||||
t = 0;
|
||||
}
|
||||
else if (strncasecmp (input_line_pointer, "NO", 2) == 0)
|
||||
{
|
||||
input_line_pointer += 2;
|
||||
t = 0;
|
||||
}
|
||||
|
||||
s = input_line_pointer;
|
||||
c = get_symbol_end ();
|
||||
|
||||
for (i = 0, o = opt_table; i < OPTCOUNT; i++, o++)
|
||||
{
|
||||
if (strcasecmp (s, o->name) == 0)
|
||||
{
|
||||
if (o->pfn)
|
||||
{
|
||||
/* Restore input_line_pointer now in case the option
|
||||
takes arguments. */
|
||||
*input_line_pointer = c;
|
||||
(*o->pfn) (o->arg, t);
|
||||
}
|
||||
else if (o->pvar != NULL)
|
||||
{
|
||||
if (! t && o->arg == o->notarg)
|
||||
as_bad ("option `%s' may not be negated", s);
|
||||
*input_line_pointer = c;
|
||||
*o->pvar = t ? o->arg : o->notarg;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i >= OPTCOUNT)
|
||||
{
|
||||
as_bad ("option `%s' not recognized", s);
|
||||
*input_line_pointer = c;
|
||||
}
|
||||
}
|
||||
while (*input_line_pointer++ == ',');
|
||||
|
||||
/* Move back to terminating character. */
|
||||
--input_line_pointer;
|
||||
demand_empty_rest_of_line ();
|
||||
}
|
||||
|
||||
/* Skip ahead to a comma. This is used for OPT options which we do
|
||||
not suppor tand which take arguments. */
|
||||
|
||||
static void
|
||||
skip_to_comma (arg, on)
|
||||
int arg;
|
||||
int on;
|
||||
{
|
||||
while (*input_line_pointer != ','
|
||||
&& ! is_end_of_line[(unsigned char) *input_line_pointer])
|
||||
++input_line_pointer;
|
||||
}
|
||||
|
||||
/* Handle the OPT P=chip option. */
|
||||
|
||||
static void
|
||||
opt_chip (arg, on)
|
||||
int arg;
|
||||
int on;
|
||||
{
|
||||
if (*input_line_pointer != '=')
|
||||
{
|
||||
/* This is just OPT P, which we do not support. */
|
||||
return;
|
||||
}
|
||||
|
||||
++input_line_pointer;
|
||||
mri_chip ();
|
||||
}
|
||||
|
||||
/* Handle the OPT S option. */
|
||||
|
||||
static void
|
||||
opt_list (arg, on)
|
||||
int arg;
|
||||
int on;
|
||||
{
|
||||
listing_list (on);
|
||||
}
|
||||
|
||||
/* Handle the OPT T option. */
|
||||
|
||||
static void
|
||||
opt_list_symbols (arg, on)
|
||||
int arg;
|
||||
int on;
|
||||
{
|
||||
if (on)
|
||||
listing |= LISTING_SYMBOLS;
|
||||
else
|
||||
listing &=~ LISTING_SYMBOLS;
|
||||
}
|
||||
|
||||
/* Handle the MRI REG pseudo-op. */
|
||||
|
||||
static void
|
||||
s_reg (ignore)
|
||||
int ignore;
|
||||
{
|
||||
char *s;
|
||||
int c;
|
||||
struct m68k_op op;
|
||||
unsigned long mask;
|
||||
|
||||
if (mri_line_label == NULL)
|
||||
{
|
||||
as_bad ("missing label");
|
||||
ignore_rest_of_line ();
|
||||
return;
|
||||
}
|
||||
|
||||
SKIP_WHITESPACE ();
|
||||
|
||||
s = input_line_pointer;
|
||||
while (isalnum ((unsigned char) *input_line_pointer)
|
||||
#ifdef REGISTER_PREFIX
|
||||
|| *input_line_pointer == REGISTER_PREFIX
|
||||
#endif
|
||||
|| *input_line_pointer == '/'
|
||||
|| *input_line_pointer == '-')
|
||||
++input_line_pointer;
|
||||
c = *input_line_pointer;
|
||||
*input_line_pointer = '\0';
|
||||
|
||||
if (m68k_ip_op (s, &op) != 0)
|
||||
{
|
||||
if (op.error == NULL)
|
||||
as_bad ("bad register list");
|
||||
else
|
||||
as_bad ("bad register list: %s", op.error);
|
||||
*input_line_pointer = c;
|
||||
ignore_rest_of_line ();
|
||||
return;
|
||||
}
|
||||
|
||||
*input_line_pointer = c;
|
||||
|
||||
if (op.mode == REGLST)
|
||||
mask = op.mask;
|
||||
else if (op.mode == DREG)
|
||||
mask = 1 << (op.reg - DATA0);
|
||||
else if (op.mode == AREG)
|
||||
mask = 1 << (op.reg - ADDR0 + 8);
|
||||
else if (op.mode == FPREG)
|
||||
mask = 1 << (op.reg - FP0 + 16);
|
||||
else if (op.mode == CONTROL
|
||||
&& op.reg == FPI)
|
||||
mask = 1 << 24;
|
||||
else if (op.mode == CONTROL
|
||||
&& op.reg == FPS)
|
||||
mask = 1 << 25;
|
||||
else if (op.mode == CONTROL
|
||||
&& op.reg == FPC)
|
||||
mask = 1 << 26;
|
||||
else
|
||||
{
|
||||
as_bad ("bad register list");
|
||||
ignore_rest_of_line ();
|
||||
return;
|
||||
}
|
||||
|
||||
S_SET_SEGMENT (mri_line_label, absolute_section);
|
||||
S_SET_VALUE (mri_line_label, mask);
|
||||
mri_line_label->sy_frag = &zero_address_frag;
|
||||
|
||||
demand_empty_rest_of_line ();
|
||||
}
|
||||
|
||||
/*
|
||||
* md_parse_option
|
||||
|
Loading…
Reference in New Issue
Block a user