aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>1995-08-09 23:22:13 +0000
committerIan Lance Taylor <ian@airs.com>1995-08-09 23:22:13 +0000
commit6700d36e840fad4694c68b12915efdb8ac2ff3ec (patch)
tree549dec58502518e1b3010afed1abd4c9c0e07cd2 /gas
parent69e077f3c73bd55a09a92385ade3c447786123ac (diff)
downloadgdb-6700d36e840fad4694c68b12915efdb8ac2ff3ec.zip
gdb-6700d36e840fad4694c68b12915efdb8ac2ff3ec.tar.gz
gdb-6700d36e840fad4694c68b12915efdb8ac2ff3ec.tar.bz2
* 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.
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog30
-rw-r--r--gas/config/tc-m68k.c375
2 files changed, 400 insertions, 5 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 09e0b74..ccdf546 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -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.
diff --git a/gas/config/tc-m68k.c b/gas/config/tc-m68k.c
index 6412a5d..3832755 100644
--- a/gas/config/tc-m68k.c
+++ b/gas/config/tc-m68k.c
@@ -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