aboutsummaryrefslogtreecommitdiff
path: root/gas/config
diff options
context:
space:
mode:
Diffstat (limited to 'gas/config')
-rw-r--r--gas/config/m68k-parse.h14
-rw-r--r--gas/config/m68k-parse.y35
-rw-r--r--gas/config/tc-m68k.c175
3 files changed, 169 insertions, 55 deletions
diff --git a/gas/config/m68k-parse.h b/gas/config/m68k-parse.h
index c82e69f..3b98b8a 100644
--- a/gas/config/m68k-parse.h
+++ b/gas/config/m68k-parse.h
@@ -1,6 +1,6 @@
/* m68k-parse.h -- header file for m68k assembler
Copyright 1987, 1991, 1992, 1993, 1994, 1995, 1996, 1999, 2000,
- 2003 Free Software Foundation, Inc.
+ 2003, 2004 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
@@ -84,7 +84,12 @@ enum m68k_register
ZPC, /* Hack for Program space, but 0 addressing */
SR, /* Status Reg */
CCR, /* Condition code Reg */
- ACC, /* Accumulator Reg */
+ ACC, /* Accumulator Reg0 (EMAC or ACC on MAC). */
+ ACC1, /* Accumulator Reg 1 (EMAC). */
+ ACC2, /* Accumulator Reg 2 (EMAC). */
+ ACC3, /* Accumulator Reg 3 (EMAC). */
+ ACCEXT01, /* Accumulator extension 0&1 (EMAC). */
+ ACCEXT23, /* Accumulator extension 2&3 (EMAC). */
MACSR, /* MAC Status Reg */
MASK, /* Modulus Reg */
@@ -295,6 +300,8 @@ enum m68k_operand_type
BASE,
POST,
PRE,
+ LSH, /* MAC/EMAC scalefactor '<<'. */
+ RSH, /* MAC/EMAC scalefactor '>>'. */
REGLST
};
@@ -322,6 +329,9 @@ struct m68k_op
/* The outer displacement. */
struct m68k_exp odisp;
+
+ /* Is a trailing '&' added to an <ea>? (for MAC/EMAC mask addressing). */
+ int trailing_ampersand;
};
#endif /* ! defined (M68K_PARSE_H) */
diff --git a/gas/config/m68k-parse.y b/gas/config/m68k-parse.y
index 813bfaa..c56ad23 100644
--- a/gas/config/m68k-parse.y
+++ b/gas/config/m68k-parse.y
@@ -98,6 +98,7 @@ static struct m68k_op *op;
struct m68k_exp exp;
unsigned long mask;
int onereg;
+ int trailing_ampersand;
}
%token <reg> DR AR FPR FPCR LPC ZAR ZDR LZPC CREG
@@ -109,6 +110,7 @@ static struct m68k_op *op;
%type <exp> optcexpr optexprc
%type <mask> reglist ireglist reglistpair
%type <onereg> reglistreg
+%type <trailing_ampersand> optional_ampersand
%%
@@ -116,14 +118,35 @@ static struct m68k_op *op;
operand:
generic_operand
- | motorola_operand
+ | motorola_operand optional_ampersand
+ {
+ op->trailing_ampersand = $2;
+ }
| mit_operand
;
+/* A trailing ampersand(for MAC/EMAC mask addressing). */
+optional_ampersand:
+ /* empty */
+ { $$ = 0; }
+ | '&'
+ { $$ = 1; }
+ ;
+
/* A generic operand. */
generic_operand:
- DR
+ '<' '<'
+ {
+ op->mode = LSH;
+ }
+
+ | '>' '>'
+ {
+ op->mode = RSH;
+ }
+
+ | DR
{
op->mode = DREG;
op->reg = $1;
@@ -757,12 +780,14 @@ yylex ()
case '/':
case '[':
case ']':
+ case '<':
+ case '>':
return *str++;
case '+':
/* It so happens that a '+' can only appear at the end of an
- operand. If it appears anywhere else, it must be a unary
- plus on an expression. */
- if (str[1] == '\0')
+ operand, or if it is trailed by an '&'(see mac load insn).
+ If it appears anywhere else, it must be a unary. */
+ if (str[1] == '\0' || (str[1] == '&' && str[2] == '\0'))
return *str++;
break;
case '-':
diff --git a/gas/config/tc-m68k.c b/gas/config/tc-m68k.c
index 5bef34b..86fa9dc 100644
--- a/gas/config/tc-m68k.c
+++ b/gas/config/tc-m68k.c
@@ -371,52 +371,52 @@ struct m68k_cpu
static const struct m68k_cpu archs[] =
{
- { m68000, "68000", 0 },
- { m68010, "68010", 0 },
- { m68020, "68020", 0 },
- { m68030, "68030", 0 },
- { m68040, "68040", 0 },
- { m68060, "68060", 0 },
- { cpu32, "cpu32", 0 },
- { m68881, "68881", 0 },
- { m68851, "68851", 0 },
- { mcf5200, "5200", 0 },
- { mcf5206e,"5206e", 0 },
- { mcf528x, "528x", 0 },
- { mcf5307, "5307", 0 },
- { mcf5407, "5407", 0 },
- { mcfv4e, "cfv4e", 0 },
+ { m68000, "68000", 0 },
+ { m68010, "68010", 0 },
+ { m68020, "68020", 0 },
+ { m68030, "68030", 0 },
+ { m68040, "68040", 0 },
+ { m68060, "68060", 0 },
+ { cpu32, "cpu32", 0 },
+ { m68881, "68881", 0 },
+ { m68851, "68851", 0 },
+ { mcf5200, "5200", 0 },
+ { mcf5206e, "5206e", 0 },
+ { mcf528x|mcfmac, "528x", 0 },
+ { mcf5307|mcfmac, "5307", 0 },
+ { mcf5407|mcfmac, "5407", 0 },
+ { mcfv4e|mcfemac, "cfv4e", 0 },
/* Aliases (effectively, so far as gas is concerned) for the above
cpus. */
- { m68020, "68k", 1 },
- { m68000, "68008", 1 },
- { m68000, "68302", 1 },
- { m68000, "68306", 1 },
- { m68000, "68307", 1 },
- { m68000, "68322", 1 },
- { m68000, "68356", 1 },
- { m68000, "68ec000", 1 },
- { m68000, "68hc000", 1 },
- { m68000, "68hc001", 1 },
- { m68020, "68ec020", 1 },
- { m68030, "68ec030", 1 },
- { m68040, "68ec040", 1 },
- { m68060, "68ec060", 1 },
- { cpu32, "68330", 1 },
- { cpu32, "68331", 1 },
- { cpu32, "68332", 1 },
- { cpu32, "68333", 1 },
- { cpu32, "68334", 1 },
- { cpu32, "68336", 1 },
- { cpu32, "68340", 1 },
- { cpu32, "68341", 1 },
- { cpu32, "68349", 1 },
- { cpu32, "68360", 1 },
- { m68881, "68882", 1 },
- { mcf5200, "5202", 1 },
- { mcf5200, "5204", 1 },
- { mcf5200, "5206", 1 },
- { mcf5407, "cfv4", 1 },
+ { m68020, "68k", 1 },
+ { m68000, "68008", 1 },
+ { m68000, "68302", 1 },
+ { m68000, "68306", 1 },
+ { m68000, "68307", 1 },
+ { m68000, "68322", 1 },
+ { m68000, "68356", 1 },
+ { m68000, "68ec000", 1 },
+ { m68000, "68hc000", 1 },
+ { m68000, "68hc001", 1 },
+ { m68020, "68ec020", 1 },
+ { m68030, "68ec030", 1 },
+ { m68040, "68ec040", 1 },
+ { m68060, "68ec060", 1 },
+ { cpu32, "68330", 1 },
+ { cpu32, "68331", 1 },
+ { cpu32, "68332", 1 },
+ { cpu32, "68333", 1 },
+ { cpu32, "68334", 1 },
+ { cpu32, "68336", 1 },
+ { cpu32, "68340", 1 },
+ { cpu32, "68341", 1 },
+ { cpu32, "68349", 1 },
+ { cpu32, "68360", 1 },
+ { m68881, "68882", 1 },
+ { mcf5200, "5202", 1 },
+ { mcf5200, "5204", 1 },
+ { mcf5200, "5206", 1 },
+ { mcf5407|mcfmac, "cfv4", 1 },
};
static const int n_archs = sizeof (archs) / sizeof (archs[0]);
@@ -1505,6 +1505,14 @@ m68k_ip (instring)
++losing;
break;
+ case '4':
+ if (opP->mode != AINDR && opP->mode != AINC && opP->mode != ADEC
+ && (opP->mode != DISP
+ || opP->reg < ADDR0
+ || opP->reg > ADDR7))
+ ++losing;
+ break;
+
case 'B': /* FOO */
if (opP->mode != ABSL
|| (flag_long_jumps
@@ -1552,6 +1560,12 @@ m68k_ip (instring)
losing++;
break;
+ case 'e':
+ if (opP->reg != ACC && opP->reg != ACC1
+ && opP->reg != ACC2 && opP->reg != ACC3)
+ losing++;
+ break;
+
case 'F':
if (opP->mode != FPREG)
losing++;
@@ -1562,6 +1576,11 @@ m68k_ip (instring)
losing++;
break;
+ case 'g':
+ if (opP->reg != ACCEXT01 && opP->reg != ACCEXT23)
+ losing++;
+ break;
+
case 'H':
if (opP->reg != MASK)
losing++;
@@ -1574,6 +1593,11 @@ m68k_ip (instring)
losing++;
break;
+ case 'i':
+ if (opP->mode != LSH && opP->mode != RSH)
+ losing++;
+ break;
+
case 'J':
if (opP->mode != CONTROL
|| opP->reg < USP
@@ -1994,6 +2018,7 @@ m68k_ip (instring)
case 'w':
case 'y':
case 'z':
+ case '4':
#ifndef NO_68851
case '|':
#endif
@@ -2519,6 +2544,16 @@ m68k_ip (instring)
as_bad (_("unknown/incorrect operand"));
/* abort (); */
}
+
+ /* If s[0] is '4', then this is for the mac instructions
+ that can have a trailing_ampersand set. If so, set 0x100
+ bit on tmpreg so install_gen_operand can check for it and
+ set the appropriate bit (word2, bit 5). */
+ if (s[0] == '4')
+ {
+ if (opP->trailing_ampersand)
+ tmpreg |= 0x100;
+ }
install_gen_operand (s[1], tmpreg);
break;
@@ -2737,6 +2772,10 @@ m68k_ip (instring)
install_operand (s[1], opP->reg - DATA);
break;
+ case 'e': /* EMAC ACCx, reg/reg. */
+ install_operand (s[1], opP->reg - ACC);
+ break;
+
case 'E': /* Ignore it. */
break;
@@ -2744,6 +2783,10 @@ m68k_ip (instring)
install_operand (s[1], opP->reg - FP0);
break;
+ case 'g': /* EMAC ACCEXTx. */
+ install_operand (s[1], opP->reg - ACCEXT01);
+ break;
+
case 'G': /* Ignore it. */
case 'H':
break;
@@ -2753,6 +2796,10 @@ m68k_ip (instring)
install_operand (s[1], tmpreg);
break;
+ case 'i': /* MAC/EMAC scale factor. */
+ install_operand (s[1], opP->mode == LSH ? 0x1 : 0x3);
+ break;
+
case 'J': /* JF foo. */
switch (opP->reg)
{
@@ -3286,25 +3333,46 @@ install_operand (mode, val)
the_ins.opcode[0] |= ((val & 0x7) << 9);
the_ins.opcode[1] |= ((val & 0x10) << (7 - 4));
break;
- case 'n':
+ case 'n': /* MAC/EMAC Rx on !load. */
the_ins.opcode[0] |= ((val & 0x8) << (6 - 3));
the_ins.opcode[0] |= ((val & 0x7) << 9);
+ the_ins.opcode[1] |= ((val & 0x10) << (7 - 4));
break;
- case 'o':
+ case 'o': /* MAC/EMAC Rx on load. */
the_ins.opcode[1] |= val << 12;
the_ins.opcode[1] |= ((val & 0x10) << (7 - 4));
break;
- case 'M':
+ case 'M': /* MAC/EMAC Ry on !load. */
the_ins.opcode[0] |= (val & 0xF);
the_ins.opcode[1] |= ((val & 0x10) << (6 - 4));
break;
- case 'N':
+ case 'N': /* MAC/EMAC Ry on load. */
the_ins.opcode[1] |= (val & 0xF);
the_ins.opcode[1] |= ((val & 0x10) << (6 - 4));
break;
case 'h':
the_ins.opcode[1] |= ((val != 1) << 10);
break;
+ case 'F':
+ the_ins.opcode[0] |= ((val & 0x3) << 9);
+ break;
+ case 'f':
+ the_ins.opcode[0] |= ((val & 0x3) << 0);
+ break;
+ case 'G':
+ the_ins.opcode[0] |= ((~val & 0x1) << 7);
+ the_ins.opcode[1] |= ((val & 0x2) << (4 - 1));
+ break;
+ case 'H':
+ the_ins.opcode[0] |= ((val & 0x1) << 7);
+ the_ins.opcode[1] |= ((val & 0x2) << (4 - 1));
+ break;
+ case 'I':
+ the_ins.opcode[1] |= ((val & 0x3) << 9);
+ break;
+ case ']':
+ the_ins.opcode[0] |= (val & 0x1) <<10;
+ break;
case 'c':
default:
as_fatal (_("failed sanity check."));
@@ -3318,6 +3386,11 @@ install_gen_operand (mode, val)
{
switch (mode)
{
+ case '/': /* Special for mask loads for mac/msac insns with
+ possible mask; trailing_ampersend set in bit 8. */
+ the_ins.opcode[0] |= (val & 0x3f);
+ the_ins.opcode[1] |= (((val & 0x100) >> 8) << 5);
+ break;
case 's':
the_ins.opcode[0] |= val;
break;
@@ -3507,6 +3580,12 @@ static const struct init_entry init_table[] =
{ "cc", CCR },
{ "acc", ACC },
+ { "acc0", ACC },
+ { "acc1", ACC1 },
+ { "acc2", ACC2 },
+ { "acc3", ACC3 },
+ { "accext01", ACCEXT01 },
+ { "accext23", ACCEXT23 },
{ "macsr", MACSR },
{ "mask", MASK },