diff options
Diffstat (limited to 'gas/config')
-rw-r--r-- | gas/config/m68k-parse.h | 14 | ||||
-rw-r--r-- | gas/config/m68k-parse.y | 35 | ||||
-rw-r--r-- | gas/config/tc-m68k.c | 175 |
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 }, |