diff options
Diffstat (limited to 'gas')
-rw-r--r-- | gas/ChangeLog | 43 | ||||
-rw-r--r-- | gas/Makefile.in | 17 | ||||
-rw-r--r-- | gas/config/.Sanitize | 2 | ||||
-rw-r--r-- | gas/config/m68k-parse.h | 279 | ||||
-rw-r--r-- | gas/config/m68k-parse.y | 959 | ||||
-rw-r--r-- | gas/config/tc-m68k.c | 2327 | ||||
-rwxr-xr-x | gas/configure | 45 | ||||
-rw-r--r-- | gas/configure.in | 13 |
8 files changed, 1953 insertions, 1732 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index ff179ec6..53b3e58 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,46 @@ +Mon Aug 7 17:18:10 1995 Ian Lance Taylor <ian@cygnus.com> + + * config/m68k-parse.y: New file: bison grammar for m68k operands, + including support for Motorola syntax. + * config/m68k-parse.h: New file; definitions shared between + m68k-parse.y and tc-m68k.c. + * config/tc-m68k.c: Include m68k-parse.h. + (enum operand_type): Move to m68k-parse.h, where it is named + m68k_operand_type. Rename all uses. Rearrange somewhat. Add + FPREG. Rename AOFF to DISP. Rename AINDX to BASE. Rename APODX + to POST. Rename APRDX to PRE. Remove AMIND. Rename MSCR to + CONTROL. Remove DINDR. + (struct m68k_exp): Move to m68k-parse.h. Remove e_beg, e_end and + e_seg fields. Rename e_exp to exp. Rename e_siz to size, and + change type to enum m68k_size. Change all uses. + (enum _register): Move to m68k-parse.h, where it is named + m68k_register. Rename all uses. Add ZDATA0-7 and ZADDR0-7. + (struct m68k_op): Move to m68k-parse.h. Change all fields. + (seg): Don't define. + (add_exp): Remove. + (FAIL, OK): Remove. + (m68k_reg_parse): Move to m68k-parse.y, and rewrite. + (SKIP_WHITE, SKIP_W): Remove. + (try_moto_index, try_index): Remove. + (m68k_ip_op): Move to m68k-parse.y, and rewrite to use grammar. + (main): Remove obsolete test function. + (m68k_ip): Extensive changes to use new grammar. + (get_regs): Remove. + (crack_operand): m68k_ip_op now returns 0 on success. + (init_table): Add ssp, zd0-7 and za0-7. + (md_assemble): Make er const. Correct loop over operands when + looking for error message. + (md_begin): Set alt_notend_table for '(' and '@'. + (get_num): Expression is already parsed. Don't set seg. + * configure.in: If cpu_type is m68k, put m68k-parse.o in + extra-objects. + * configure: Rebuild. + * Makefile.in (DISTSTUFF): Add m68k-parse.c. + (BISON): Use ../bison/bison if it exists. + (BISONFLAGS): Define as empty. + (TARG_CPU_DEP_m68k): Depend upon $(srcdir)/config/m68k-parse.h. + (m68k-parse.c, m68k-parse.o): New targets. + start-sanitize-sh3e Mon Aug 7 02:54:20 1995 Jeff Law (law@snake.cs.utah.edu) diff --git a/gas/Makefile.in b/gas/Makefile.in index f06d0b0..8de9e3b 100644 --- a/gas/Makefile.in +++ b/gas/Makefile.in @@ -62,11 +62,12 @@ INSTALL_DATA = $(INSTALL) INSTALL_XFORM = $(INSTALL) -t='-e $(program_transform_name)' INSTALL_XFORM1= $(INSTALL_XFORM) -b=.1 -DISTSTUFF= make-gas.com +DISTSTUFF= make-gas.com m68k-parse.c AR = ar AR_FLAGS = qv -BISON = bison -y +BISON = `if [ -f ../bison/bison ] ; then echo ../bison/bison -y -L../bison/bison ; else echo bison -y ; fi` +BISONFLAGS = MAKEINFO = makeinfo TEXI2DVI = texi2dvi RANLIB = ranlib @@ -289,7 +290,8 @@ TARG_CPU_DEP_hppa = TARG_CPU_DEP_i386 = $(srcdir)/../include/opcode/i386.h TARG_CPU_DEP_i860 = TARG_CPU_DEP_i960 = -TARG_CPU_DEP_m68k = $(srcdir)/../include/opcode/m68k.h +TARG_CPU_DEP_m68k = $(srcdir)/../include/opcode/m68k.h \ + $(srcdir)/config/m68k-parse.h TARG_CPU_DEP_m88k = $(srcdir)/config/m88k-opcode.h TARG_CPU_DEP_mips = $(srcdir)/../include/opcode/mips.h TARG_CPU_DEP_ns32k = @@ -347,6 +349,13 @@ e-mipself.o : $(srcdir)/config/e-mipself.c e-mipsecoff.o : $(srcdir)/config/e-mipsecoff.c $(CC) -c $(ALL_CFLAGS) $(CPPFLAGS) $(INCLUDES) $(srcdir)/config/e-mipsecoff.c +# The m68k operand parser. + +m68k-parse.c: $(srcdir)/config/m68k-parse.y + $(BISON) $(BISONFLAGS) $(srcdir)/config/m68k-parse.y + mv -f y.tab.c m68k-parse.c +m68k-parse.o: m68k-parse.c $(srcdir)/config/m68k-parse.y + # Remake the info files. doc: $(srcdir)/as.info @@ -492,7 +501,7 @@ de-stage3: force force: Makefile: $(srcdir)/Makefile.in $(host_makefile_frag) $(target_makefile_frag) \ - $(srcdir)/configure.in config.status + $(srcdir)/configure.in config.status conf.in $(SHELL) ./config.status .gdbinit: $(srcdir)/gdbinit.in config.status $(SHELL) ./config.status diff --git a/gas/config/.Sanitize b/gas/config/.Sanitize index 7128ce7..588afa3 100644 --- a/gas/config/.Sanitize +++ b/gas/config/.Sanitize @@ -50,6 +50,8 @@ go32.cfg e-mipsecoff.c e-mipself.c i386coff.mt +m68k-parse.h +m68k-parse.y m68kcoff.mt m88k-opcode.h m88kcoff.mt diff --git a/gas/config/m68k-parse.h b/gas/config/m68k-parse.h new file mode 100644 index 0000000..128944c --- /dev/null +++ b/gas/config/m68k-parse.h @@ -0,0 +1,279 @@ +/* m68k-parse.h -- header file for m68k assembler + Copyright (C) 1987, 91, 92, 93, 94, 1995 Free Software Foundation, Inc. + + This file is part of GAS, the GNU Assembler. + + GAS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + GAS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GAS; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#ifndef M68K_PARSE_H +#define M68K_PARSE_H + +/* This header file defines things which are shared between the + operand parser in m68k.y and the m68k assembler proper in + tc-m68k.c. */ + +/* The various m68k registers. */ + +/* DATA and ADDR have to be contiguous, so that reg-DATA gives + 0-7==data reg, 8-15==addr reg for operands that take both types. + + We don't use forms like "ADDR0 = ADDR" here because this file is + likely to be used on an Apollo, and the broken Apollo compiler + gives an `undefined variable' error if we do that, according to + troy@cbme.unsw.edu.au. */ + +#define DATA DATA0 +#define ADDR ADDR0 +#define SP ADDR7 +#define COPNUM COP0 +#define BAD BAD0 +#define BAC BAC0 + +enum m68k_register +{ + DATA0 = 1, /* 1- 8 == data registers 0-7 */ + DATA1, + DATA2, + DATA3, + DATA4, + DATA5, + DATA6, + DATA7, + + ADDR0, + ADDR1, + ADDR2, + ADDR3, + ADDR4, + ADDR5, + ADDR6, + ADDR7, + + FP0, /* Eight FP registers */ + FP1, + FP2, + FP3, + FP4, + FP5, + FP6, + FP7, + + /* Note that COP0==processor #1 -- COP0+7==#8, which stores as 000 */ + /* I think. . . */ + + COP0, /* Co-processor #1-#8 */ + COP1, + COP2, + COP3, + COP4, + COP5, + COP6, + COP7, + + PC, /* Program counter */ + ZPC, /* Hack for Program space, but 0 addressing */ + SR, /* Status Reg */ + CCR, /* Condition code Reg */ + + /* These have to be grouped together for the movec instruction to work. */ + USP, /* User Stack Pointer */ + ISP, /* Interrupt stack pointer */ + SFC, + DFC, + CACR, + VBR, + CAAR, + MSP, + ITT0, + ITT1, + DTT0, + DTT1, + MMUSR, + TC, + SRP, + URP, + BUSCR, /* 68060 added these */ + PCR, +#define last_movec_reg PCR + /* end of movec ordering constraints */ + + FPI, + FPS, + FPC, + + DRP, /* 68851 or 68030 MMU regs */ + CRP, + CAL, + VAL, + SCC, + AC, + BAD0, + BAD1, + BAD2, + BAD3, + BAD4, + BAD5, + BAD6, + BAD7, + BAC0, + BAC1, + BAC2, + BAC3, + BAC4, + BAC5, + BAC6, + BAC7, + PSR, /* aka MMUSR on 68030 (but not MMUSR on 68040) + and ACUSR on 68ec030 */ + PCSR, + + IC, /* instruction cache token */ + DC, /* data cache token */ + NC, /* no cache token */ + BC, /* both caches token */ + + TT0, /* 68030 access control unit regs */ + TT1, + + ZDATA0, /* suppressed data registers. */ + ZDATA1, + ZDATA2, + ZDATA3, + ZDATA4, + ZDATA5, + ZDATA6, + ZDATA7, + + ZADDR0, /* suppressed address registers. */ + ZADDR1, + ZADDR2, + ZADDR3, + ZADDR4, + ZADDR5, + ZADDR6, + ZADDR7, +}; + +/* Size information. */ + +enum m68k_size +{ + /* Unspecified. */ + SIZE_UNSPEC, + + /* Byte. */ + SIZE_BYTE, + + /* Word (2 bytes). */ + SIZE_WORD, + + /* Longword (4 bytes). */ + SIZE_LONG +}; + +/* The structure used to hold information about an index register. */ + +struct m68k_indexreg +{ + /* The index register itself. */ + enum m68k_register reg; + + /* The size to use. */ + enum m68k_size size; + + /* The value to scale by. */ + int scale; +}; + +/* The structure used to hold information about an expression. */ + +struct m68k_exp +{ + /* The size to use. */ + enum m68k_size size; + + /* The expression itself. */ + expressionS exp; +}; + +/* See whether an expression is a signed eight bit value. */ + +#define expr8(ex) \ + ((ex)->exp.X_op == O_constant \ + && (ex)->exp.X_add_number >= -0x80 \ + && (ex)->exp.X_add_number < 0x80) + +/* See whether an expression is a signed sixteen bit value. */ + +#define expr16(ex) \ + ((ex)->exp.X_op == O_constant \ + && (ex)->exp.X_add_number >= -0x8000 \ + && (ex)->exp.X_add_number < 0x8000) + +/* The operand modes. */ + +enum m68k_operand_type +{ + IMMED = 1, + ABSL, + DREG, + AREG, + FPREG, + CONTROL, + AINDR, + AINC, + ADEC, + DISP, + BASE, + POST, + PRE, + REGLST +}; + +/* The structure used to hold a parsed operand. */ + +struct m68k_op +{ + /* The type of operand. */ + enum m68k_operand_type mode; + + /* The main register. */ + enum m68k_register reg; + + /* The register mask for mode REGLST. */ + unsigned long mask; + + /* An error message. */ + const char *error; + + /* The index register. */ + struct m68k_indexreg index; + + /* The displacement. */ + struct m68k_exp disp; + + /* The outer displacement. */ + struct m68k_exp odisp; +}; + +#endif /* ! defined (M68K_PARSE_H) */ + +/* The parsing function. */ + +extern int m68k_ip_op PARAMS ((char *, struct m68k_op *)); + +/* Whether register prefixes are optional. */ +extern int flag_reg_prefix_optional; diff --git a/gas/config/m68k-parse.y b/gas/config/m68k-parse.y new file mode 100644 index 0000000..d3d690a --- /dev/null +++ b/gas/config/m68k-parse.y @@ -0,0 +1,959 @@ +/* m68k.y -- bison grammar for m68k operand parsing + Copyright (C) 1995 Free Software Foundation, Inc. + Written by Ken Raeburn and Ian Lance Taylor, Cygnus Support + + This file is part of GAS, the GNU Assembler. + + GAS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + GAS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GAS; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +/* This file holds a bison grammar to parse m68k operands. The m68k + has a complicated operand syntax, and gas supports two main + variations of it. Using a grammar is probably overkill, but at + least it makes clear exactly what we do support. */ + +%{ + +#include "as.h" +#include "tc-m68k.h" +#include "m68k-parse.h" + +/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, + etc), as well as gratuitiously global symbol names If other parser + generators (bison, byacc, etc) produce additional global names that + conflict at link time, then those parser generators need to be + fixed instead of adding those names to this list. */ + +#define yymaxdepth m68k_maxdepth +#define yyparse m68k_parse +#define yylex m68k_lex +#define yyerror m68k_error +#define yylval m68k_lval +#define yychar m68k_char +#define yydebug m68k_debug +#define yypact m68k_pact +#define yyr1 m68k_r1 +#define yyr2 m68k_r2 +#define yydef m68k_def +#define yychk m68k_chk +#define yypgo m68k_pgo +#define yyact m68k_act +#define yyexca m68k_exca +#define yyerrflag m68k_errflag +#define yynerrs m68k_nerrs +#define yyps m68k_ps +#define yypv m68k_pv +#define yys m68k_s +#define yy_yys m68k_yys +#define yystate m68k_state +#define yytmp m68k_tmp +#define yyv m68k_v +#define yy_yyv m68k_yyv +#define yyval m68k_val +#define yylloc m68k_lloc +#define yyreds m68k_reds /* With YYDEBUG defined */ +#define yytoks m68k_toks /* With YYDEBUG defined */ +#define yylhs m68k_yylhs +#define yylen m68k_yylen +#define yydefred m68k_yydefred +#define yydgoto m68k_yydgoto +#define yysindex m68k_yysindex +#define yyrindex m68k_yyrindex +#define yygindex m68k_yygindex +#define yytable m68k_yytable +#define yycheck m68k_yycheck + +#ifndef YYDEBUG +#define YYDEBUG 1 +#endif + +/* Internal functions. */ + +static enum m68k_register m68k_reg_parse PARAMS ((char **)); +static int yylex PARAMS (()); +static void yyerror PARAMS ((const char *)); + +/* The parser sets fields pointed to by this global variable. */ +static struct m68k_op *op; + +%} + +%union +{ + struct m68k_indexreg indexreg; + enum m68k_register reg; + struct m68k_exp exp; + unsigned long mask; + int onereg; +} + +%token <reg> DR AR FPR FPCR LPC ZAR ZDR LZPC CREG +%token <indexreg> INDEXREG +%token <exp> EXPR + +%type <indexreg> zireg zdireg +%type <reg> zadr zdr apc zapc zpc optzapc optczapc +%type <exp> optcexpr optexprc +%type <mask> reglist ireglist reglistpair +%type <onereg> reglistreg + +%% + +/* An operand. */ + +operand: + generic_operand + | motorola_operand + | mit_operand + ; + +/* A generic operand. */ + +generic_operand: + DR + { + op->mode = DREG; + op->reg = $1; + } + | AR + { + op->mode = AREG; + op->reg = $1; + } + | FPR + { + op->mode = FPREG; + op->reg = $1; + } + | FPCR + { + op->mode = CONTROL; + op->reg = $1; + } + | CREG + { + op->mode = CONTROL; + op->reg = $1; + } + | EXPR + { + op->mode = ABSL; + op->disp = $1; + } + | '#' EXPR + { + op->mode = IMMED; + op->disp = $2; + } + | '&' EXPR + { + op->mode = IMMED; + op->disp = $2; + } + | reglist + { + op->mode = REGLST; + op->mask = $1; + } + ; + +/* An operand in Motorola syntax. This includes MRI syntax as well, + which may or may not be different in that it permits commutativity + of index and base registers, and permits an offset expression to + appear inside or outside of the parentheses. */ + +motorola_operand: + '(' AR ')' + { + op->mode = AINDR; + op->reg = $2; + } + | '(' AR ')' '+' + { + op->mode = AINC; + op->reg = $2; + } + | '-' '(' AR ')' + { + op->mode = ADEC; + op->reg = $3; + } + | '(' EXPR ',' zapc ')' + { + op->reg = $4; + op->disp = $2; + if (($4 >= ZADDR0 && $4 <= ZADDR7) + || $4 == ZPC) + op->mode = BASE; + else + op->mode = DISP; + } + | EXPR '(' zapc ')' + { + op->reg = $3; + op->disp = $1; + if (($3 >= ZADDR0 && $3 <= ZADDR7) + || $3 == ZPC) + op->mode = BASE; + else + op->mode = DISP; + } + | '(' ZAR ')' + { + op->mode = BASE; + op->reg = $2; + } + | '(' zpc ')' + { + op->mode = BASE; + op->reg = $2; + } + | '(' EXPR ',' zapc ',' zireg ')' + { + op->mode = BASE; + op->reg = $4; + op->disp = $2; + op->index = $6; + } + | '(' EXPR ',' zapc ',' zpc ')' + { + if ($4 == PC || $4 == ZPC) + yyerror ("syntax error"); + op->mode = BASE; + op->reg = $6; + op->disp = $2; + op->index.reg = $4; + op->index.size = SIZE_UNSPEC; + op->index.scale = 1; + } + | '(' EXPR ',' zdireg optczapc ')' + { + op->mode = BASE; + op->reg = $5; + op->disp = $2; + op->index = $4; + } + | EXPR '(' zapc ',' zireg ')' + { + op->mode = BASE; + op->reg = $3; + op->disp = $1; + op->index = $5; + } + | '(' zapc ',' zireg ')' + { + op->mode = BASE; + op->reg = $2; + op->index = $4; + } + | EXPR '(' zapc ',' zpc ')' + { + if ($3 == PC || $3 == ZPC) + yyerror ("syntax error"); + op->mode = BASE; + op->reg = $5; + op->disp = $1; + op->index.reg = $3; + op->index.size = SIZE_UNSPEC; + op->index.scale = 1; + } + | '(' zapc ',' zpc ')' + { + if ($2 == PC || $2 == ZPC) + yyerror ("syntax error"); + op->mode = BASE; + op->reg = $4; + op->index.reg = $2; + op->index.size = SIZE_UNSPEC; + op->index.scale = 1; + } + | EXPR '(' zdireg optczapc ')' + { + op->mode = BASE; + op->reg = $4; + op->disp = $1; + op->index = $3; + } + | '(' zdireg optczapc ')' + { + op->mode = BASE; + op->reg = $3; + op->index = $2; + } + | '(' '[' EXPR optczapc ']' ',' zireg optcexpr ')' + { + op->mode = POST; + op->reg = $4; + op->disp = $3; + op->index = $7; + op->odisp = $8; + } + | '(' '[' EXPR optczapc ']' optcexpr ')' + { + op->mode = POST; + op->reg = $4; + op->disp = $3; + op->odisp = $6; + } + | '(' '[' zapc ']' ',' zireg optcexpr ')' + { + op->mode = POST; + op->reg = $3; + op->index = $6; + op->odisp = $7; + } + | '(' '[' zapc ']' optcexpr ')' + { + op->mode = POST; + op->reg = $3; + op->odisp = $5; + } + | '(' '[' EXPR ',' zapc ',' zireg ']' optcexpr ')' + { + op->mode = PRE; + op->reg = $5; + op->disp = $3; + op->index = $7; + op->odisp = $9; + } + | '(' '[' zapc ',' zireg ']' optcexpr ')' + { + op->mode = PRE; + op->reg = $3; + op->index = $5; + op->odisp = $7; + } + | '(' '[' EXPR ',' zapc ',' zpc ']' optcexpr ')' + { + if ($5 == PC || $5 == ZPC) + yyerror ("syntax error"); + op->mode = PRE; + op->reg = $7; + op->disp = $3; + op->index.reg = $5; + op->index.size = SIZE_UNSPEC; + op->index.scale = 1; + op->odisp = $9; + } + | '(' '[' zapc ',' zpc ']' optcexpr ')' + { + if ($3 == PC || $3 == ZPC) + yyerror ("syntax error"); + op->mode = PRE; + op->reg = $5; + op->index.reg = $3; + op->index.size = SIZE_UNSPEC; + op->index.scale = 1; + op->odisp = $7; + } + | '(' '[' optexprc zdireg optczapc ']' optcexpr ')' + { + op->mode = PRE; + op->reg = $5; + op->disp = $3; + op->index = $4; + op->odisp = $7; + } + ; + +/* An operand in MIT syntax. */ + +mit_operand: + optzapc '@' + { + /* We use optzapc to avoid a shift/reduce conflict. */ + if ($1 < ADDR0 || $1 > ADDR7) + yyerror ("syntax error"); + op->mode = AINDR; + op->reg = $1; + } + | optzapc '@' '+' + { + /* We use optzapc to avoid a shift/reduce conflict. */ + if ($1 < ADDR0 || $1 > ADDR7) + yyerror ("syntax error"); + op->mode = AINC; + op->reg = $1; + } + | optzapc '@' '-' + { + /* We use optzapc to avoid a shift/reduce conflict. */ + if ($1 < ADDR0 || $1 > ADDR7) + yyerror ("syntax error"); + op->mode = ADEC; + op->reg = $1; + } + | optzapc '@' '(' EXPR ')' + { + op->reg = $1; + op->disp = $4; + if (($1 >= ZADDR0 && $1 <= ZADDR7) + || $1 == ZPC) + op->mode = BASE; + else + op->mode = DISP; + } + | optzapc '@' '(' optexprc zireg ')' + { + op->mode = BASE; + op->reg = $1; + op->disp = $4; + op->index = $5; + } + | optzapc '@' '(' EXPR ')' '@' '(' optexprc zireg ')' + { + op->mode = POST; + op->reg = $1; + op->disp = $4; + op->index = $9; + op->odisp = $8; + } + | optzapc '@' '(' EXPR ')' '@' '(' EXPR ')' + { + op->mode = POST; + op->reg = $1; + op->disp = $4; + op->odisp = $8; + } + | optzapc '@' '(' optexprc zireg ')' '@' '(' EXPR ')' + { + op->mode = PRE; + op->reg = $1; + op->disp = $4; + op->index = $5; + op->odisp = $9; + } + ; + +/* An index register, possibly suppressed, which need not have a size + or scale. */ + +zireg: + INDEXREG + | zadr + { + $$.reg = $1; + $$.size = SIZE_UNSPEC; + $$.scale = 1; + } + ; + +/* A register which may be an index register, but which may not be an + address register. This nonterminal is used to avoid ambiguity when + trying to parse something like (0,d5,a6) as compared to (0,a6,d5). */ + +zdireg: + INDEXREG + | zdr + { + $$.reg = $1; + $$.size = SIZE_UNSPEC; + $$.scale = 1; + } + ; + +/* An address or data register, or a suppressed address or data + register. */ + +zadr: + zdr + | AR + | ZAR + ; + +/* A data register which may be suppressed. */ + +zdr: + DR + | ZDR + ; + +/* Either an address register or the PC. */ + +apc: + AR + | LPC + ; + +/* Either an address register, or the PC, or a suppressed address + register, or a suppressed PC. */ + +zapc: + apc + | LZPC + | ZAR + ; + +/* An optional zapc. */ + +optzapc: + /* empty */ + { + $$ = ZADDR0; + } + | zapc + ; + +/* The PC, optionally suppressed. */ + +zpc: + LPC + | LZPC + ; + +/* ',' zapc when it may be omitted. */ + +optczapc: + /* empty */ + { + $$ = ZADDR0; + } + | ',' zapc + { + $$ = $2; + } + ; + +/* ',' EXPR when it may be omitted. */ + +optcexpr: + /* empty */ + { + $$.exp.X_op = O_absent; + $$.size = SIZE_UNSPEC; + } + | ',' EXPR + { + $$ = $2; + } + ; + +/* EXPR ',' when it may be omitted. */ + +optexprc: + /* empty */ + { + $$.exp.X_op = O_absent; + $$.size = SIZE_UNSPEC; + } + | EXPR ',' + { + $$ = $1; + } + ; + +/* A register list for the movem instruction. */ + +reglist: + reglistpair + | reglistpair '/' ireglist + { + $$ = $1 | $3; + } + | reglistreg '/' ireglist + { + $$ = (1 << $1) | $3; + } + ; + +/* We use ireglist when we know we are looking at a reglist, and we + can safely reduce a simple register to reglistreg. If we permitted + reglist to reduce to reglistreg, it would be ambiguous whether a + plain register were a DREG/AREG/FPREG or a REGLST. */ + +ireglist: + reglistreg + { + $$ = 1 << $1; + } + | reglistpair + | reglistpair '/' ireglist + { + $$ = $1 | $3; + } + | reglistreg '/' ireglist + { + $$ = (1 << $1) | $3; + } + ; + +reglistpair: + reglistreg '-' reglistreg + { + $$ = (1 << ($3 + 1)) - 1 - ((1 << $1) - 1); + } + ; + +reglistreg: + DR + { + $$ = $1 - DATA0; + } + | AR + { + $$ = $1 - ADDR0 + 8; + } + | FPR + { + $$ = $1 - FP0 + 16; + } + | FPCR + { + if ($1 == FPI) + $$ = 24; + else if ($1 == FPS) + $$ = 25; + else + $$ = 26; + } + ; + +%% + +/* The string to parse is stored here, and modified by yylex. */ + +static char *str; + +/* The original string pointer. */ + +static char *strorig; + +/* If *CCP could be a register, return the register number and advance + *CCP. Otherwise don't change *CCP, and return 0. */ + +static enum m68k_register +m68k_reg_parse (ccp) + register char **ccp; +{ + char *start = *ccp; + char c; + char *p; + symbolS *symbolp; + + if (flag_reg_prefix_optional) + { + if (*start == REGISTER_PREFIX) + start++; + p = start; + } + else + { + if (*start != REGISTER_PREFIX) + return 0; + p = start + 1; + } + + if (! is_name_beginner (*p)) + return 0; + + p++; + while (is_part_of_name (*p) && *p != '.' && *p != ':' && *p != '*') + p++; + + c = *p; + *p = 0; + symbolp = symbol_find (start); + *p = c; + + if (symbolp != NULL && S_GET_SEGMENT (symbolp) == reg_section) + { + *ccp = p; + return S_GET_VALUE (symbolp); + } + + return 0; +} + +/* The lexer. */ + +static int +yylex () +{ + enum m68k_register reg; + char *s; + int parens; + int c = 0; + char *hold; + + if (*str == ' ') + ++str; + + if (*str == '\0') + return 0; + + /* Various special characters are just returned directly. */ + switch (*str) + { + case '#': + case '&': + case ',': + 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') + return *str++; + break; + case '-': + /* A '-' can only appear in -(ar), rn-rn, or ar@-. If it + appears anywhere else, it must be a unary minus on an + expression. */ + if (str[1] == '\0') + return *str++; + s = str + 1; + if (*s == '(') + ++s; + if (m68k_reg_parse (&s) != 0) + return *str++; + break; + case '(': + /* A '(' can only appear in `(reg)', `(expr,...', `([', `@(', or + `)('. If it appears anywhere else, it must be starting an + expression. */ + if (str[1] == '[' + || (str > strorig + && (str[-1] == '@' + || str[-1] == ')'))) + return *str++; + s = str + 1; + if (m68k_reg_parse (&s) != 0) + return *str++; + /* Check for the case of '(expr,...' by scanning ahead. If we + find a comma outside of balanced parentheses, we return '('. + If we find an unbalanced right parenthesis, then presumably + the '(' really starts an expression. */ + parens = 0; + for (s = str + 1; *s != '\0'; s++) + { + if (*s == '(') + ++parens; + else if (*s == ')') + { + if (parens == 0) + break; + --parens; + } + else if (*s == ',' && parens == 0) + { + /* A comma can not normally appear in an expression, so + this is a case of '(expr,...'. */ + return *str++; + } + } + } + + /* See if it's a register. */ + + reg = m68k_reg_parse (&str); + if (reg != 0) + { + int ret; + + yylval.reg = reg; + + if (reg >= DATA0 && reg <= DATA7) + ret = DR; + else if (reg >= ADDR0 && reg <= ADDR7) + ret = AR; + else if (reg >= FP0 && reg <= FP7) + return FPR; + else if (reg == FPI + || reg == FPS + || reg == FPC) + return FPCR; + else if (reg == PC) + return LPC; + else if (reg >= ZDATA0 && reg <= ZDATA7) + ret = ZDR; + else if (reg >= ZADDR0 && reg <= ZADDR7) + ret = ZAR; + else if (reg == ZPC) + return LZPC; + else + return CREG; + + /* If we get here, we have a data or address register. We + must check for a size or scale; if we find one, we must + return INDEXREG. */ + + s = str; + + if (*s != '.' && *s != ':' && *s != '*') + return ret; + + yylval.indexreg.reg = reg; + + if (*s != '.' && *s != ':') + yylval.indexreg.size = SIZE_UNSPEC; + else + { + ++s; + switch (*s) + { + case 'w': + case 'W': + yylval.indexreg.size = SIZE_WORD; + ++s; + break; + case 'l': + case 'L': + yylval.indexreg.size = SIZE_LONG; + ++s; + break; + default: + yyerror ("illegal size specification"); + yylval.indexreg.size = SIZE_UNSPEC; + break; + } + } + + if (*s != '*' && *s != ':') + yylval.indexreg.scale = 1; + else + { + ++s; + switch (*s) + { + case '1': + case '2': + case '4': + case '8': + yylval.indexreg.scale = *s - '0'; + ++s; + break; + default: + yyerror ("illegal scale specification"); + yylval.indexreg.scale = 1; + break; + } + } + + str = s; + + return INDEXREG; + } + + /* It must be an expression. Before we call expression, we need to + look ahead to see if there is a size specification. We must do + that first, because otherwise foo.l will be treated as the symbol + foo.l, rather than as the symbol foo with a long size + specification. The grammar requires that all expressions end at + the end of the operand, or with ',', '(', ']', ')'. */ + + parens = 0; + for (s = str; *s != '\0'; s++) + { + if (*s == '(') + { + if (parens == 0 + && s > str + && (s[-1] == ')' || isalnum ((unsigned char) s[-1]))) + break; + ++parens; + } + else if (*s == ')') + { + if (parens == 0) + break; + --parens; + } + else if (parens == 0 + && (*s == ',' || *s == ']')) + break; + } + + yylval.exp.size = SIZE_UNSPEC; + if (s <= str + 2 + || (s[-2] != '.' && s[-2] != ':')) + s = NULL; + else + { + switch (s[-1]) + { + case 's': + case 'S': + case 'b': + case 'B': + yylval.exp.size = SIZE_BYTE; + break; + case 'w': + case 'W': + yylval.exp.size = SIZE_WORD; + break; + case 'l': + case 'L': + yylval.exp.size = SIZE_LONG; + break; + default: + s = NULL; + break; + } + if (yylval.exp.size != SIZE_UNSPEC) + { + c = s[-2]; + s[-2] = '\0'; + } + } + + hold = input_line_pointer; + input_line_pointer = str; + expression (&yylval.exp.exp); + str = input_line_pointer; + input_line_pointer = hold; + + if (s != NULL) + { + s[-2] = c; + str = s; + } + + return EXPR; +} + +/* Parse an m68k operand. This is the only function which is called + from outside this file. */ + +int +m68k_ip_op (s, oparg) + char *s; + struct m68k_op *oparg; +{ + memset (oparg, 0, sizeof *oparg); + oparg->error = NULL; + oparg->index.reg = ZDATA0; + oparg->index.scale = 1; + oparg->disp.exp.X_op = O_absent; + oparg->odisp.exp.X_op = O_absent; + + str = strorig = s; + op = oparg; + + return yyparse (); +} + +/* The error handler. */ + +static void +yyerror (s) + const char *s; +{ + op->error = s; +} diff --git a/gas/config/tc-m68k.c b/gas/config/tc-m68k.c index 364183b..49fc5ab 100644 --- a/gas/config/tc-m68k.c +++ b/gas/config/tc-m68k.c @@ -1,7 +1,5 @@ -/* All the m68k specific stuff in one convenient, huge, slow to - compile, easy to find file. - - Copyright (C) 1987, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. +/* tc-m68k.c -- Assemble for the m68k family + Copyright (C) 1987, 91, 92, 93, 94, 1995 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -16,25 +14,17 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with GAS; see the file COPYING. If not, write to - the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + along with GAS; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ #include <ctype.h> #define NO_RELOC 0 #include "as.h" #include "obstack.h" -/* The opcode table is too big for some versions of gcc, which require - exponential(?) space at compile time for initialized arrays. */ -#ifdef __GNUC__ -#define DO_BREAK_UP_BIG_DECL -#define BREAK_UP_BIG_DECL }; struct m68k_opcode m68k_opcodes_2[] = { -#define AND_OTHER_PART sizeof (m68k_opcodes_2) -#endif - -/* Note that this file includes real declarations and thus can only be - included by one source file per executable. */ #include "opcode/m68k.h" +#include "m68k-parse.h" /* This array holds the chars that always start a comment. If the pre-processor is disabled, these aren't very useful */ @@ -118,7 +108,7 @@ static struct obstack robyn; struct m68k_incant { - char *m_operands; + const char *m_operands; unsigned long m_opcode; short m_opnum; short m_codenum; @@ -129,290 +119,72 @@ struct m68k_incant #define getone(x) ((((x)->m_opcode)>>16)&0xffff) #define gettwo(x) (((x)->m_opcode)&0xffff) -/* Operands we can parse: (And associated modes) - - numb: 8 bit num - numw: 16 bit num - numl: 32 bit num - dreg: data reg 0-7 - reg: address or data register - areg: address register - apc: address register, PC, ZPC or empty string - num: 16 or 32 bit num - num2: like num - sz: w or l if omitted, l assumed - scale: 1 2 4 or 8 if omitted, 1 assumed - - 7.4 IMMED #num --> NUM - 0.? DREG dreg --> dreg - 1.? AREG areg --> areg - 2.? AINDR areg@ --> *(areg) - 3.? AINC areg@+ --> *(areg++) - 4.? ADEC areg@- --> *(--areg) - 5.? AOFF apc@(numw) --> *(apc+numw) -- empty string and ZPC not allowed here - 6.? AINDX apc@(num,reg:sz:scale) --> *(apc+num+reg*scale) - 6.? AINDX apc@(reg:sz:scale) --> same, with num=0 - 6.? APODX apc@(num)@(num2,reg:sz:scale) --> *(*(apc+num)+num2+reg*scale) - 6.? APODX apc@(num)@(reg:sz:scale) --> same, with num2=0 - 6.? AMIND apc@(num)@(num2) --> *(*(apc+num)+num2) (previous mode without an index reg) - 6.? APRDX apc@(num,reg:sz:scale)@(num2) --> *(*(apc+num+reg*scale)+num2) - 6.? APRDX apc@(reg:sz:scale)@(num2) --> same, with num=0 - 7.0 ABSL num:sz --> *(num) - num --> *(num) (sz L assumed) - *** MSCR otherreg --> Magic - With -l option - 5.? AOFF apc@(num) --> *(apc+num) -- empty string and ZPC not allowed here still - ?.? DINDR dreg@ --> (dreg) -- cas2 only - - examples: - #foo #0x35 #12 - d2 - a4 - a3@ - a5@+ - a6@- - a2@(12) pc@(14) - a1@(5,d2:w:1) @(45,d6:l:4) - pc@(a2) @(d4) - etc . . . - - - #name@(numw) -->turn into PC rel mode - apc@(num8,reg:sz:scale) --> *(apc+num8+reg*scale) - - */ - -enum operand_type - { - IMMED = 1, - DREG, - AREG, - AINDR, - ADEC, - AINC, - AOFF, - AINDX, - APODX, - AMIND, - APRDX, - ABSL, - MSCR, - REGLST, - DINDR - }; - - -struct m68k_exp - { - char *e_beg; - char *e_end; - segT e_seg; - expressionS e_exp; - short e_siz; /* 0== default 1==short/byte 2==word 3==long */ - }; - -/* DATA and ADDR have to be contiguous, so that reg-DATA gives - 0-7==data reg, 8-15==addr reg for operands that take both types. - - We don't use forms like "ADDR0 = ADDR" here because this file is - likely to be used on an Apollo, and the broken Apollo compiler - gives an `undefined variable' error if we do that, according to - troy@cbme.unsw.edu.au. */ - -#define DATA DATA0 -#define ADDR ADDR0 -#define SP ADDR7 -#define FPREG FP0 -#define COPNUM COP0 -#define BAD BAD0 -#define BAC BAC0 - -enum _register - { - DATA0 = 1, /* 1- 8 == data registers 0-7 */ - DATA1, - DATA2, - DATA3, - DATA4, - DATA5, - DATA6, - DATA7, - - ADDR0, - ADDR1, - ADDR2, - ADDR3, - ADDR4, - ADDR5, - ADDR6, - ADDR7, - - FP0, /* Eight FP registers */ - FP1, - FP2, - FP3, - FP4, - FP5, - FP6, - FP7, - - /* Note that COP0==processor #1 -- COP0+7==#8, which stores as 000 */ - /* I think. . . */ - - COP0, /* Co-processor #1-#8 */ - COP1, - COP2, - COP3, - COP4, - COP5, - COP6, - COP7, - - PC, /* Program counter */ - ZPC, /* Hack for Program space, but 0 addressing */ - SR, /* Status Reg */ - CCR, /* Condition code Reg */ - - /* These have to be grouped together for the movec instruction to work. */ - USP, /* User Stack Pointer */ - ISP, /* Interrupt stack pointer */ - SFC, - DFC, - CACR, - VBR, - CAAR, - MSP, - ITT0, - ITT1, - DTT0, - DTT1, - MMUSR, - TC, - SRP, - URP, - BUSCR, /* 68060 added these */ - PCR, -#define last_movec_reg PCR - /* end of movec ordering constraints */ - - FPI, - FPS, - FPC, - - DRP, /* 68851 or 68030 MMU regs */ - CRP, - CAL, - VAL, - SCC, - AC, - BAD0, - BAD1, - BAD2, - BAD3, - BAD4, - BAD5, - BAD6, - BAD7, - BAC0, - BAC1, - BAC2, - BAC3, - BAC4, - BAC5, - BAC6, - BAC7, - PSR, /* aka MMUSR on 68030 (but not MMUSR on 68040) - and ACUSR on 68ec030 */ - PCSR, - - IC, /* instruction cache token */ - DC, /* data cache token */ - NC, /* no cache token */ - BC, /* both caches token */ - - TT0, /* 68030 access control unit regs */ - TT1, - }; - -static const enum _register m68000_control_regs[] = { 0 }; -static const enum _register m68010_control_regs[] = { +static const enum m68k_register m68000_control_regs[] = { 0 }; +static const enum m68k_register m68010_control_regs[] = { SFC, DFC, USP, VBR, 0 }; -static const enum _register m68020_control_regs[] = { +static const enum m68k_register m68020_control_regs[] = { SFC, DFC, USP, VBR, CACR, CAAR, MSP, ISP, 0 }; -static const enum _register m68040_control_regs[] = { +static const enum m68k_register m68040_control_regs[] = { SFC, DFC, CACR, TC, ITT0, ITT1, DTT0, DTT1, USP, VBR, MSP, ISP, MMUSR, URP, SRP, 0 }; -static const enum _register m68060_control_regs[] = { +static const enum m68k_register m68060_control_regs[] = { SFC, DFC, CACR, TC, ITT0, ITT1, DTT0, DTT1, BUSCR, USP, VBR, URP, SRP, PCR, 0 }; #define cpu32_control_regs m68010_control_regs -static const enum _register *control_regs; - -/* Internal form of an operand. */ -struct m68k_op - { - char *error; /* Couldn't parse it */ - enum operand_type mode; /* What mode this instruction is in. */ - enum _register reg; /* Base register */ - struct m68k_exp *con1; - int ireg; /* Index register */ - int isiz; /* 0==unspec 1==byte(?) 2==short 3==long */ - int imul; /* Multipy ireg by this (1,2,4,or 8) */ - struct m68k_exp *con2; - }; +static const enum m68k_register *control_regs; /* internal form of a 68020 instruction */ struct m68k_it - { - char *error; - char *args; /* list of opcode info */ - int numargs; +{ + const char *error; + const char *args; /* list of opcode info */ + int numargs; - int numo; /* Number of shorts in opcode */ - short opcode[11]; + int numo; /* Number of shorts in opcode */ + short opcode[11]; - struct m68k_op operands[6]; + struct m68k_op operands[6]; - int nexp; /* number of exprs in use */ - struct m68k_exp exprs[4]; + int nexp; /* number of exprs in use */ + struct m68k_exp exprs[4]; - int nfrag; /* Number of frags we have to produce */ - struct - { - int fragoff; /* Where in the current opcode[] the frag ends */ - symbolS *fadd; - long foff; - int fragty; - } - fragb[4]; + int nfrag; /* Number of frags we have to produce */ + struct + { + int fragoff; /* Where in the current opcode the frag ends */ + symbolS *fadd; + long foff; + int fragty; + } + fragb[4]; - int nrel; /* Num of reloc strucs in use */ - struct - { - int n; - expressionS exp; - char wid; - char pcrel; - /* In a pc relative address the difference between the address - of the offset and the address that the offset is relative - to. This depends on the addressing mode. Basically this - is the value to put in the offset field to address the - first byte of the offset, without regarding the special - significance of some values (in the branch instruction, for - example). */ - int pcrel_fix; - } - reloc[5]; /* Five is enough??? */ - }; + int nrel; /* Num of reloc strucs in use */ + struct + { + int n; + expressionS exp; + char wid; + char pcrel; + /* In a pc relative address the difference between the address + of the offset and the address that the offset is relative + to. This depends on the addressing mode. Basically this + is the value to put in the offset field to address the + first byte of the offset, without regarding the special + significance of some values (in the branch instruction, for + example). */ + int pcrel_fix; + } + reloc[5]; /* Five is enough??? */ +}; #define cpu_of_arch(x) ((x) & m68000up) #define float_of_arch(x) ((x) & mfloat) @@ -420,11 +192,10 @@ struct m68k_it static struct m68k_it the_ins; /* the instruction being assembled */ -#define seg(exp) ((exp)->e_seg) -#define op(exp) ((exp)->e_exp.X_op) -#define adds(exp) ((exp)->e_exp.X_add_symbol) -#define subs(exp) ((exp)->e_exp.X_op_symbol) -#define offs(exp) ((exp)->e_exp.X_add_number) +#define op(ex) ((ex)->exp.X_op) +#define adds(ex) ((ex)->exp.X_add_symbol) +#define subs(ex) ((ex)->exp.X_op_symbol) +#define offs(ex) ((ex)->exp.X_add_number) /* Macros for adding things to the m68k_it struct */ @@ -447,17 +218,6 @@ insop (w, opcode) the_ins.numo++; } -static struct m68k_exp * -add_exp (beg, end) - char *beg; - char *end; -{ - the_ins.exprs[the_ins.nexp].e_beg=beg; - the_ins.exprs[the_ins.nexp].e_end=end; - return &the_ins.exprs[the_ins.nexp++]; -} - - /* The numo+1 kludge is so we can hit the low order byte of the prev word. Blecch. */ static void @@ -472,7 +232,7 @@ add_fix (width, exp, pc_rel, pc_fix) : (((width)=='b') ? (the_ins.numo*2+1) : (the_ins.numo*2))); - the_ins.reloc[the_ins.nrel].exp = exp->e_exp; + the_ins.reloc[the_ins.nrel].exp = exp->exp; the_ins.reloc[the_ins.nrel].wid = width; the_ins.reloc[the_ins.nrel].pcrel_fix = pc_fix; the_ins.reloc[the_ins.nrel++].pcrel = pc_rel; @@ -500,15 +260,13 @@ add_frag(add,off,type) the_ins.fragb[the_ins.nfrag++].fragty=type; } -#define isvar(exp) \ - ((exp) && op (exp) != O_constant && op (exp) != O_big) +#define isvar(ex) \ + (op (ex) != O_constant && op (ex) != O_big) static char *crack_operand PARAMS ((char *str, struct m68k_op *opP)); static int get_num PARAMS ((struct m68k_exp *exp, int ok)); -static int get_regs PARAMS ((int i, char *str, struct m68k_op *opP)); static int reverse_16_bits PARAMS ((int in)); static int reverse_8_bits PARAMS ((int in)); -static int try_index PARAMS ((char **s, struct m68k_op *opP)); static void install_gen_operand PARAMS ((int mode, int val)); static void install_operand PARAMS ((int mode, int val)); static void s_bss PARAMS ((int)); @@ -675,807 +433,14 @@ CONST pseudo_typeS mote_pseudo_table[] = extern char *input_line_pointer; -enum - { - FAIL = 0, - OK = 1, - }; - static char mklower_table[256]; #define mklower(c) (mklower_table[(unsigned char)(c)]) static char notend_table[256]; static char alt_notend_table[256]; -#define notend(s) ( !(notend_table[(unsigned char)(*s)] || (*s==':' &&\ - alt_notend_table[(unsigned char)(s[1])]))) - -/* JF modified this to handle cases where the first part of a symbol name - looks like a register */ - -/* - * m68k_reg_parse() := if it looks like a register, return it's token & - * advance the pointer. - */ - -enum _register -m68k_reg_parse (ccp) - register char **ccp; -{ - char *start = *ccp; - char c; - char *p; - symbolS *symbolP; - - if (flag_reg_prefix_optional) - { - if (*start == REGISTER_PREFIX) - start++; - p = start; - } - else - { - if (*start != REGISTER_PREFIX) - return FAIL; - p = start + 1; - } - - if (!isalpha (*p) || !is_name_beginner (*p)) - return FAIL; - - c = *p++; - while (isalpha (c) || isdigit (c) || c == '_') - { - c = *p++; - } - - *--p = 0; - symbolP = symbol_find (start); - *p = c; - - if (symbolP && S_GET_SEGMENT (symbolP) == reg_section) - { - *ccp = p; - return S_GET_VALUE (symbolP); - } - - return FAIL; -} - -#define SKIP_WHITE() { str++; if(*str==' ') str++;} -#define SKIP_W() { ss++; if(*ss==' ') ss++;} - -/* Parse an index specification using Motorola syntax. */ - -static int -try_moto_index (s, opP) - char **s; - struct m68k_op *opP; -{ - register int i; - char *ss; - - ss = *s; - /* SKIP_W(); */ - if (*ss == ' ') - ss++; - i = m68k_reg_parse (&ss); - if (!(i >= DATA + 0 && i <= ADDR + 7)) - { /* if i is not DATA or ADDR reg */ - opP->error = "Invalid index register"; - *s = ss; - return FAIL; - } - opP->ireg = i; - /* SKIP_W(); */ - if (*ss == ')') - { - opP->isiz = 0; - opP->imul = 1; - SKIP_W (); - *s = ss; - return OK; - } - if (*ss != '.') - { - opP->error = "Missing . in index register"; - *s = ss; - return FAIL; - } - SKIP_W (); - if (mklower (*ss) == 'w') - opP->isiz = 2; - else if (mklower (*ss) == 'l') - opP->isiz = 3; - else - { - opP->error = "Size spec not .W or .L"; - *s = ss; - return FAIL; - } - SKIP_W (); - if (*ss == '.' || *ss == '*') - { - SKIP_W (); - switch (*ss) - { - case '1': - case '2': - case '4': - case '8': - opP->imul = *ss - '0'; - break; - default: - opP->error = "index multiplier not 1, 2, 4 or 8"; - *s = ss; - return FAIL; - } - SKIP_W (); - } - else - opP->imul = 1; - if (*ss != ')') - { - opP->error = "Missing )"; - *s = ss; - return FAIL; - } - SKIP_W (); - *s = ss; - return OK; -} - -/* - * - * try_index := data_or_address_register + ')' + SKIP_W - * | data_or_address_register + ':' + SKIP_W + size_spec + SKIP_W + multiplier + ')' + SKIP_W - * - * multiplier := <empty> - * | ':' + multiplier_number - * ; - * - * multiplier_number := '1' | '2' | '4' | '8' ; - * - * size_spec := 'l' | 'L' | 'w' | 'W' ; - * - * SKIP_W := <empty> | ' ' ; - * - */ - -static int -try_index (s, opP) - char **s; - struct m68k_op *opP; -{ - register int i; - char *ss; - - ss = *s; - /* SKIP_W(); */ - i = m68k_reg_parse (&ss); - if (!(i >= DATA + 0 && i <= ADDR + 7)) - { /* if i is not DATA or ADDR reg */ - *s = ss; - return FAIL; - } - opP->ireg = i; - /* SKIP_W(); */ - if (*ss == ')') - { - opP->isiz = 0; - opP->imul = 1; - SKIP_W (); - *s = ss; - return OK; - } - if (*ss != ':') - { - opP->error = "Missing : in index register"; - *s = ss; - return FAIL; - } - SKIP_W (); - switch (*ss) - { - case 'w': - case 'W': - opP->isiz = 2; - break; - case 'l': - case 'L': - opP->isiz = 3; - break; - default: - opP->error = "Index register size spec not :w or :l"; - *s = ss; - return FAIL; - } - SKIP_W (); - if (*ss == ':') - { - SKIP_W (); - switch (*ss) - { - case '1': - case '2': - case '4': - case '8': - if (cpu_of_arch (current_architecture) < m68020) - { - opP->error = "no index scaling in pre-68020's"; - *s = ss; - return FAIL; - } - opP->imul = *ss - '0'; - break; - default: - opP->error = "index multiplier not 1, 2, 4 or 8"; - *s = ss; - return FAIL; - } - SKIP_W (); - } - else - opP->imul = 1; - if (*ss != ')') - { - opP->error = "Missing )"; - *s = ss; - return FAIL; - } - SKIP_W (); - *s = ss; - return OK; -} /* try_index() */ - -/* Ian Taylor expanded this function to accept both MIT and Motorola - syntax. I removed the old comment, since it was wrong. The syntax - this accepted even before my changes was complex and undocumented. - I mainly added a large case when the operand string does not - contain an '@', since the Motorola syntax does not use the '@' - character. */ - -int -m68k_ip_op (str, opP) - char *str; - register struct m68k_op *opP; -{ - char *strend; - long i; - char *parse_index (); - int needp; - - if (*str == ' ') - { - str++; - } /* Find the beginning of the string */ - - if (!*str) - { - opP->error = "Missing operand"; - return FAIL; - } /* Out of gas */ - - for (strend = str; *strend; strend++) - ; - --strend; - - if (*str == '#' || *str == '&') - { - str++; - opP->con1 = add_exp (str, strend); - opP->mode = IMMED; - return OK; - } /* Guess what: A constant. Shar and enjoy */ - - i = m68k_reg_parse (&str); - - if (i != FAIL) - { - if (*str == '/' || *str == '-') - { - /* "Rm-Rn/Ro-Rp" Register list for MOVEM instruction */ - opP->mode = REGLST; - return get_regs (i, str, opP); - } - if (*str == '\0') - { - opP->reg = i; - /* "Rn" Register Direct mode */ - if (i >= DATA + 0 && i <= DATA + 7) - opP->mode = DREG; - else if (i >= ADDR + 0 && i <= ADDR + 7) - opP->mode = AREG; - else - opP->mode = MSCR; - return OK; - } - } - - if (*str != '@') - { - char *stmp; - - if ((stmp = strchr (str, '@')) != 0) - { - opP->con1 = add_exp (str, stmp - 1); - if (stmp == strend) - { - opP->mode = AINDX; - return (OK); - } - - if ((current_architecture & m68020up) == 0) - { - return (FAIL); - } /* if target is not a '20 or better */ - - stmp++; - if (*stmp++ != '(' || *strend-- != ')') - { - opP->error = "Malformed operand"; - return (FAIL); - } - i = try_index (&stmp, opP); - opP->con2 = add_exp (stmp, strend); - - if (i == FAIL) - { - opP->mode = AMIND; - } - else - { - opP->mode = APODX; - } - return (OK); - } /* if there's an '@' */ - -#ifndef MIT_SYNTAX_ONLY - /* The operand has no '@'. Try to parse it using - Motorola syntax. */ - /* Logic of the parsing switch(*str): - case opP->mode = - ---- ----------- - #anything IMMED 1 - REG AREG or DREG or MSCR 3 or 2 or 13 - REG- or REG/ REGLST 14 - (REG) AINDR 4 - (REG)+ AINC 6 - (REG,INDX) AINDX 8 - (EXPR,REG) AOFF 7 - (EXPR,REG,INDX) AINDX 8 - -(REG) ADEC 5 - EXP2(REG) AOFF 7 - EXP2(REG,INDX) AINDX 8 - EXP2 ABSL 12 - - REG means truth(m68k_reg_parse(&str)) - INDX means truth(try_moto_index(&str,opP)) - EXPR means not REG - EXP2 means not REG and not '(' and not '-(' - */ - - if (*str == '(') - { - str++; - i = m68k_reg_parse (&str); - if ((i < ADDR + 0 || i > ADDR + 7) - && (i < DATA + 0 || i > DATA + 7 - || *str != ')' || str[1] != '0') - && i != PC && i != ZPC && i != FAIL) - { - /* Can't indirect off non address regs */ - opP->error = "Invalid indirect register"; - return FAIL; - } - if (i != FAIL) - { - opP->reg = i; - if (*str == ')') - { - str++; - if (*str == '\0') - { - /* "(An)" Address Register Indirect mode - or "(Dn)" for cas2. */ - if (i >= DATA + 0 && i <= DATA + 7) - opP->mode = DINDR; - else - opP->mode = AINDR; - return OK; - } - if (*str == '+') - { - if (str[1] == '\0') - { - /* "(An)+" Register Indirect w Postincrement */ - opP->mode = AINC; - return OK; - } - } - opP->error = "Junk after indirect"; - return FAIL; - } - if (*str == ',') - { - str++; - i = try_moto_index (&str, opP); - if (i == FAIL) - return FAIL; - /* "(An,Rn)" Register Indirect with Index mode*/ - opP->mode = AINDX; - return OK; - } - else - { - opP->error = "Bad indirect syntax"; - return FAIL; - } - } - else - { - /* "(EXPR,..." , a displacement */ - char *stmp; - - if ((stmp = strchr (str, ',')) != NULL) - { - opP->con1 = add_exp (str, stmp - 1); - str = stmp; - SKIP_WHITE (); - i = m68k_reg_parse (&str); - if ((i < ADDR + 0 || i > ADDR + 7) && i != PC && i != ZPC) - { - /* Can't indirect off non address regs */ - opP->error = "Invalid indirect register"; - return FAIL; - } - if (i != FAIL) - { - opP->reg = i; - if (*str == ')') - { - /* "(d,An)" Register Indirect w Displacement */ - opP->mode = AOFF; - return OK; - } - if (*str == ',') - { - str++; - i = try_moto_index (&str, opP); - if (i == FAIL) - return FAIL; - /* "(d,An,Rn)" Register Indirect with Index */ - opP->mode = AINDX; - return OK; - } - else - { - opP->error = "Bad indirect syntax"; - return FAIL; - } - } - else - { - opP->error = "Invalid register"; - return FAIL; - } - } - else - { - opP->mode = ABSL; - opP->con1 = add_exp (str - 1, strend); - return OK; - } - } - } - - if (*str == '-') - { - if (str[1] == '(') - { - str = str + 2; - i = m68k_reg_parse (&str); - if ((i < ADDR + 0 || i > ADDR + 7) && i != PC && i != ZPC && i != FAIL) - { - /* Can't indirect off non address regs */ - opP->error = "Invalid indirect register"; - return FAIL; - } - if (i != FAIL) - { - opP->reg = i; - if (*str == ')') - { - str++; - if (*str == '\0') - { - /* "-(An)" Register Indirect with Predecrement */ - opP->mode = ADEC; - return OK; - } - opP->error = "Junk after indirect"; - return FAIL; - } - opP->error = "Bad indirect syntax"; - return FAIL; - } - opP->mode = ABSL; - opP->con1 = add_exp (str - 2, strend); - return OK; - } - /* if '-' but not "-(', do nothing */ - } - - /* whether *str=='-' or not */ - { - /* "EXP2" or "EXP2(REG..." */ - char *stmp; - if ((stmp = strchr (str, '(')) != NULL) - { - char *ostr = str; - - opP->con1 = add_exp (str, stmp - 1); - str = stmp + 1; - i = m68k_reg_parse (&str); - if ((i < ADDR + 0 || i > ADDR + 7) && i != PC - && i != ZPC && i != FAIL) - { - /* Can't indirect off non address regs */ - opP->error = "Invalid indirect register"; - return FAIL; - } - if (i != FAIL) - { - opP->reg = i; - if (*str == ')') - { - /* "d(An)" Register Indirect w Displacement */ - opP->mode = AOFF; - return OK; - } - if (*str == ',') - { - str++; - i = try_moto_index (&str, opP); - if (i == FAIL) - return FAIL; - /* "d(An,Rn)" Register Indirect with Index */ - opP->mode = AINDX; - return OK; - } - else - { - opP->error = "Bad indirect syntax"; - return FAIL; - } - } - else - { - opP->mode = ABSL; - opP->con1 = add_exp (ostr, strend); - return OK; - } - } - else - { - /* "EXP2" Absolute */ - opP->mode = ABSL; - opP->isiz = 0; - if (strend[-1] == '.' || strend[-1] == ':') - { - /* mode ==foo.[wl] */ - switch (*strend) - { - case 'w': - case 'W': - opP->isiz = 2; - break; - case 'l': - case 'L': - opP->isiz = 3; - break; - } - } - opP->con1 = add_exp (str, strend); - return OK; - } - } - /*NOTREACHED*/ -#else /* defined (MIT_SYNTAX_ONLY) */ - opP->mode = ABSL; - opP->con1 = add_exp (str, strend); - return OK; -#endif /* defined (MIT_SYNTAX_ONLY) */ - } - - opP->reg = i; - - /* Can't indirect off non address regs, but Dx@ is OK for cas2 */ - if ((i < ADDR + 0 || i > ADDR + 7) && i != PC && i != ZPC && i != FAIL - && (str[1] != '\0' || i < DATA + 0 || i > DATA + 7)) - { - opP->error = "Invalid indirect register"; - return FAIL; - } - know (*str == '@'); - - str++; - switch (*str) - { - case '\0': - if (i < DATA + 0 || i > DATA + 7) - opP->mode = AINDR; - else - opP->mode = DINDR; - return OK; - case '-': - opP->mode = ADEC; - return OK; - case '+': - opP->mode = AINC; - return OK; - case '(': - str++; - break; - default: - opP->error = "Junk after indirect"; - return FAIL; - } - /* Some kind of indexing involved. Lets find out how bad it is */ - i = try_index (&str, opP); - /* Didn't start with an index reg, maybe its offset or offset,reg */ - if (i == FAIL) - { - char *beg_str; - - beg_str = str; - for (i = 1; i;) - { - switch (*str++) - { - case '\0': - opP->error = "Missing )"; - return FAIL; - case ',': - i = 0; - break; - case '(': - i++; - break; - case ')': - --i; - break; - } - } - opP->con1 = add_exp (beg_str, str - 2); - /* Should be offset,reg */ - if (str[-1] == ',') - { - i = try_index (&str, opP); - if (i == FAIL) - { - opP->error = "Malformed index reg"; - return FAIL; - } - } - } - /* We've now got offset) offset,reg) or reg) */ - - if (*str == '\0') - { - /* Th-the-thats all folks */ - if (opP->reg == FAIL) - opP->mode = AINDX; /* Other form of indirect */ - else if (opP->ireg == FAIL) - opP->mode = AOFF; - else - opP->mode = AINDX; - return (OK); - } - /* Next thing had better be another @ */ - if (*str == '@') - { - if (str[1] == '(') - { - needp = 1; - str += 2; - } - else - { - needp = 0; - str++; - } - } - - if ((current_architecture & m68020up) == 0) - { - return (FAIL); - } /* if target is not a '20 or better */ - - - if (opP->ireg != FAIL) - { - opP->mode = APRDX; - - i = try_index (&str, opP); - if (i != FAIL) - { - opP->error = "Two index registers! not allowed!"; - return (FAIL); - } - } - else - { - i = try_index (&str, opP); - } - - if (i == FAIL) - { - char *beg_str; - - beg_str = str; - - for (i = 1; i;) - { - switch (*str++) - { - case '\0': - if (needp) - opP->error = "Missing )"; - return (FAIL); - break; - case ',': - i = 0; - break; - case '(': - i++; - break; - case ')': - --i; - break; - } - } - - opP->con2 = add_exp (beg_str, str - 2); - - if (str[-1] == ',') - { - if (opP->ireg != FAIL) - { - opP->error = "Can't have two index regs"; - return (FAIL); - } - - i = try_index (&str, opP); - - if (i == FAIL) - { - opP->error = "malformed index reg"; - return (FAIL); - } - - opP->mode = APODX; - } - else if (opP->ireg != FAIL) - { - opP->mode = APRDX; - } - else - { - opP->mode = AMIND; - } - } - else - { - opP->mode = APODX; - } - - if (*str != '\0') - { - opP->error = "Junk after indirect"; - return FAIL; - } - return (OK); -} - +#define notend(s) \ + (! (notend_table[(unsigned char) *s] \ + || (*s == ':' \ + && alt_notend_table[(unsigned char) s[1]]))) #if defined (M68KCOFF) && !defined (BFD_ASSEMBLER) @@ -1573,65 +538,12 @@ tc_gen_reloc (section, fixp) #endif /* BFD_ASSEMBLER */ -#ifdef TEST1 /* TEST1 tests m68k_ip_op(), which parses operands */ -main () -{ - char buf[128]; - struct m68k_op thark; - - for (;;) - { - if (!gets (buf)) - break; - memset (&thark, '\0', sizeof (thark)); - if (!m68k_ip_op (buf, &thark)) - printf ("FAIL:"); - if (thark.error) - printf ("op1 error %s in %s\n", thark.error, buf); - printf ("mode %d, reg %d, ", thark.mode, thark.reg); - if (thark.b_const) - printf ("Constant: '%.*s',", 1 + thark.e_const - thark.b_const, thark.b_const); - printf ("ireg %d, isiz %d, imul %d ", thark.ireg, thark.isiz, thark.imul); - if (thark.b_iadd) - printf ("Iadd: '%.*s'", 1 + thark.e_iadd - thark.b_iadd, thark.b_iadd); - printf ("\n"); - } - exit (EXIT_SUCCESS); -} - -#endif - - /* Handle of the OPCODE hash table. NULL means any use before m68k_ip_begin() will crash. */ static struct hash_control *op_hash; +/* Assemble an m68k instruction. */ -/* - * m 6 8 k _ i p ( ) - * - * This converts a string into a 68k instruction. - * The string must be a bare single instruction in sun format - * with RMS-style 68020 indirects - * (example: ) - * - * It provides some error messages: at most one fatal error message (which - * stops the scan) and at most one warning message for each operand. - * The 68k instruction is returned in exploded form, since we have no - * knowledge of how you parse (or evaluate) your expressions. - * We do however strip off and decode addressing modes and operation - * mnemonic. - * - * This function's value is a string. If it is not "" then an internal - * logic error was found: read this code to assign meaning to the string. - * No argument string should generate such an error string: - * it means a bug in our code, not in the user's text. - * - * You MUST have called m68k_ip_begin() once and m86_ip_end() never before using - * this function. - */ - -/* JF this function no longer returns a useful value. Sorry */ void m68k_ip (instring) char *instring; @@ -1639,10 +551,10 @@ m68k_ip (instring) register char *p; register struct m68k_op *opP; register struct m68k_incant *opcode; - register char *s; + register const char *s; register int tmpreg = 0, baseo = 0, outro = 0, nextword; char *pdot, *pdotmove; - int siz1, siz2; + enum m68k_size siz1, siz2; char c; int losing; int opsfound; @@ -1668,14 +580,12 @@ m68k_ip (instring) if (p == instring) { the_ins.error = "No operator"; - the_ins.opcode[0] = 0; - /* the_ins.numo=1; */ return; } /* p now points to the end of the opcode name, probably whitespace. - make sure the name is null terminated by clobbering the whitespace, - look it up in the hash table, then fix it back. + Make sure the name is null terminated by clobbering the + whitespace, look it up in the hash table, then fix it back. Remove a dot, first, since the opcode tables have none. */ if (pdot != NULL) { @@ -1700,8 +610,6 @@ m68k_ip (instring) if (opcode == NULL) { the_ins.error = "Unknown operator"; - the_ins.opcode[0] = 0; - /* the_ins.numo=1; */ return; } @@ -1709,7 +617,6 @@ m68k_ip (instring) while (*p == ' ') ++p; - if (opcode->m_operands == 0) { char *old = input_line_pointer; @@ -1726,7 +633,6 @@ m68k_ip (instring) for (opP = &the_ins.operands[0]; *p; opP++) { - p = crack_operand (p, opP); if (opP->error) @@ -1738,8 +644,8 @@ m68k_ip (instring) opsfound = opP - &the_ins.operands[0]; - /* This ugly hack is to support the floating pt opcodes in their standard form */ - /* Essentially, we fake a first enty of type COP#1 */ + /* This ugly hack is to support the floating pt opcodes in their + standard form. Essentially, we fake a first enty of type COP#1 */ if (opcode->m_operands[0] == 'I') { int n; @@ -1747,8 +653,9 @@ m68k_ip (instring) for (n = opsfound; n > 0; --n) the_ins.operands[n] = the_ins.operands[n - 1]; - memset ((char *) (&the_ins.operands[0]), '\0', sizeof (the_ins.operands[0])); - the_ins.operands[0].mode = MSCR; + memset ((char *) (&the_ins.operands[0]), '\0', + sizeof (the_ins.operands[0])); + the_ins.operands[0].mode = CONTROL; the_ins.operands[0].reg = COPNUM; /* COP #1 */ opsfound++; } @@ -1767,7 +674,9 @@ m68k_ip (instring) } else { - for (s = opcode->m_operands, opP = &the_ins.operands[0]; *s && !losing; s += 2, opP++) + for (s = opcode->m_operands, opP = &the_ins.operands[0]; + *s && !losing; + s += 2, opP++) { /* Warning: this switch is huge! */ /* I've tried to organize the cases into this order: @@ -1778,20 +687,31 @@ m68k_ip (instring) switch (*s) { case '!': - if (opP->mode == MSCR || opP->mode == IMMED - || opP->mode == DREG || opP->mode == AREG - || opP->mode == AINC || opP->mode == ADEC - || opP->mode == REGLST) - losing++; + switch (opP->mode) + { + case IMMED: + case DREG: + case AREG: + case FPREG: + case CONTROL: + case AINC: + case ADEC: + case REGLST: + losing++; + break; + default: + break; + } break; case '`': switch (opP->mode) { - case MSCR: case IMMED: case DREG: case AREG: + case FPREG: + case CONTROL: case AINC: case REGLST: case AINDR: @@ -1805,16 +725,14 @@ m68k_ip (instring) case '#': if (opP->mode != IMMED) losing++; - else - { - long t; - - t = get_num (opP->con1, 80); - if (s[1] == 'b' && !isbyte (t)) - losing++; - else if (s[1] == 'w' && !isword (t)) - losing++; - } + else if (s[1] == 'b' + && ! isvar (&opP->disp) + && ! expr8 (&opP->disp)) + losing++; + else if (s[1] == 'w' + && ! isvar (&opP->disp) + && ! expr16 (&opP->disp)) + losing++; break; case '^': @@ -1824,27 +742,55 @@ m68k_ip (instring) break; case '$': - if (opP->mode == MSCR || opP->mode == AREG || - opP->mode == IMMED || opP->reg == PC || opP->reg == ZPC || opP->mode == REGLST) + if (opP->mode == AREG + || opP->mode == CONTROL + || opP->mode == FPREG + || opP->mode == IMMED + || opP->mode == REGLST + || (opP->mode != ABSL + && (opP->reg == PC + || opP->reg == ZPC))) losing++; break; case '%': - if (opP->mode == MSCR || opP->reg == PC || - opP->reg == ZPC || opP->mode == REGLST) + if (opP->mode == CONTROL + || opP->mode == FPREG + || opP->mode == REGLST + || (opP->mode != ABSL + && opP->mode != IMMED + && (opP->reg == PC + || opP->reg == ZPC))) losing++; break; - case '&': - if (opP->mode == MSCR || opP->mode == DREG || - opP->mode == AREG || opP->mode == IMMED || opP->reg == PC || opP->reg == ZPC || - opP->mode == AINC || opP->mode == ADEC || opP->mode == REGLST) - losing++; + switch (opP->mode) + { + case DREG: + case AREG: + case FPREG: + case CONTROL: + case IMMED: + case AINC: + case ADEC: + case REGLST: + losing++; + break; + case ABSL: + break; + default: + if (opP->reg == PC + || opP->reg == ZPC) + losing++; + break; + } break; case '*': - if (opP->mode == MSCR || opP->mode == REGLST) + if (opP->mode == CONTROL + || opP->mode == FPREG + || opP->mode == REGLST) losing++; break; @@ -1859,37 +805,96 @@ m68k_ip (instring) break; case '/': - if (opP->mode == MSCR || opP->mode == AREG || - opP->mode == AINC || opP->mode == ADEC || opP->mode == IMMED || opP->mode == REGLST) - losing++; + switch (opP->mode) + { + case AREG: + case CONTROL: + case FPREG: + case AINC: + case ADEC: + case IMMED: + case REGLST: + losing++; + break; + default: + break; + } break; case ';': - if (opP->mode == MSCR || opP->mode == AREG || opP->mode == REGLST) - losing++; + switch (opP->mode) + { + case AREG: + case CONTROL: + case FPREG: + case REGLST: + losing++; + break; + default: + break; + } break; case '?': - if (opP->mode == MSCR || opP->mode == AREG || - opP->mode == AINC || opP->mode == ADEC || opP->mode == IMMED || opP->reg == PC || - opP->reg == ZPC || opP->mode == REGLST) - losing++; + switch (opP->mode) + { + case AREG: + case CONTROL: + case FPREG: + case AINC: + case ADEC: + case IMMED: + case REGLST: + losing++; + break; + case ABSL: + break; + default: + if (opP->reg == PC || opP->reg == ZPC) + losing++; + break; + } break; case '@': - if (opP->mode == MSCR || opP->mode == AREG || - opP->mode == IMMED || opP->mode == REGLST) - losing++; + switch (opP->mode) + { + case AREG: + case CONTROL: + case FPREG: + case IMMED: + case REGLST: + losing++; + break; + default: + break; + } break; case '~': /* For now! (JF FOO is this right?) */ - if (opP->mode == MSCR || opP->mode == DREG || - opP->mode == AREG || opP->mode == IMMED || opP->reg == PC || opP->reg == ZPC || opP->mode == REGLST) - losing++; + switch (opP->mode) + { + case DREG: + case AREG: + case CONTROL: + case FPREG: + case IMMED: + case REGLST: + losing++; + break; + case ABSL: + break; + default: + if (opP->reg == PC + || opP->reg == ZPC) + losing++; + break; + } break; case '3': - if (opP->mode != MSCR || (opP->reg != TT0 && opP->reg != TT1)) + if (opP->mode != CONTROL + || (opP->reg != TT0 && opP->reg != TT1)) losing++; break; @@ -1897,28 +902,28 @@ m68k_ip (instring) if (opP->mode != AREG) losing++; break; + case 'a': if (opP->mode != AINDR) - { - ++losing; - } /* if not address register indirect */ + ++losing; break; + case 'B': /* FOO */ - if (opP->mode != ABSL || (flag_long_jumps && instring[0] == 'j' - && instring[1] == 'b' - && instring[2] == 's' - && instring[3] == 'r')) + if (opP->mode != ABSL + || (flag_long_jumps + && strncmp (instring, "jbsr", 4) == 0)) losing++; break; case 'C': - if (opP->mode != MSCR || opP->reg != CCR) + if (opP->mode != CONTROL || opP->reg != CCR) losing++; break; - case 'd': /* FOO This mode is a KLUDGE!! */ - if (opP->mode != AOFF && (opP->mode != ABSL || - opP->con1->e_beg[0] != '(' || opP->con1->e_end[0] != ')')) + case 'd': + if (opP->mode != DISP + || opP->reg < ADDR0 + || opP->reg > ADDR7) losing++; break; @@ -1928,24 +933,25 @@ m68k_ip (instring) break; case 'F': - if (opP->mode != MSCR || opP->reg < (FPREG + 0) || opP->reg > (FPREG + 7)) + if (opP->mode != FPREG) losing++; break; case 'I': - if (opP->mode != MSCR || opP->reg < COPNUM || - opP->reg >= COPNUM + 7) + if (opP->mode != CONTROL + || opP->reg < COPNUM + || opP->reg >= COPNUM + 7) losing++; break; case 'J': - if (opP->mode != MSCR + if (opP->mode != CONTROL || opP->reg < USP || opP->reg > last_movec_reg) losing++; else { - const enum _register *rp; + const enum m68k_register *rp; for (rp = control_regs; *rp; rp++) if (*rp == opP->reg) break; @@ -1961,38 +967,68 @@ m68k_ip (instring) case 'l': case 'L': - if (opP->mode == DREG || opP->mode == AREG || opP->mode == FPREG) + if (opP->mode == DREG + || opP->mode == AREG + || opP->mode == FPREG) { if (s[1] == '8') losing++; else { + switch (opP->mode) + { + case DREG: + opP->mask = 1 << (opP->reg - DATA0); + break; + case AREG: + opP->mask = 1 << (opP->reg - ADDR0 + 8); + break; + case FPREG: + opP->mask = 1 << (opP->reg - FP0 + 16); + break; + default: + abort (); + } opP->mode = REGLST; - opP->reg = 1 << (opP->reg - DATA); } } - else if (opP->mode != REGLST) + else if (opP->mode == CONTROL) { - losing++; + if (s[1] != '8') + losing++; + else + { + switch (opP->reg) + { + case FPI: + opP->mask = 1 << 24; + break; + case FPS: + opP->mask = 1 << 25; + break; + case FPC: + opP->mask = 1 << 26; + break; + default: + losing++; + break; + } + opP->mode = REGLST; + } } - else if (s[1] == '8' && opP->reg & 0x0FFffFF) + else if (opP->mode != REGLST) + losing++; + else if (s[1] == '8' && (opP->mask & 0x0ffffff) != 0) losing++; - else if (s[1] == '3' && opP->reg & 0x7000000) + else if (s[1] == '3' && (opP->mask & 0x7000000) != 0) losing++; break; case 'M': if (opP->mode != IMMED) losing++; - else - { - long t; - - t = get_num (opP->con1, 0); - if (!issbyte (t) - || isvar (opP->con1)) - losing++; - } + else if (! expr8 (&opP->disp)) + losing++; break; case 'O': @@ -2003,14 +1039,10 @@ m68k_ip (instring) case 'Q': if (opP->mode != IMMED) losing++; - else - { - long t; - - t = get_num (opP->con1, 80); - if (t < 1 || t > 8 || isvar (opP->con1)) - losing++; - } + else if (! expr8 (&opP->disp) + || opP->disp.exp.X_add_number < 1 + || opP->disp.exp.X_add_number > 8) + losing++; break; case 'R': @@ -2019,33 +1051,44 @@ m68k_ip (instring) break; case 'r': - if (opP->mode != AINDR && opP->mode != DINDR) + if (opP->mode != AINDR + && (opP->mode != BASE + || (opP->reg != 0 + && opP->reg != ZADDR0) + || opP->disp.exp.X_op != O_absent + || ((opP->index.reg < DATA0 + || opP->index.reg > DATA7) + && (opP->index.reg < ADDR0 + || opP->index.reg > ADDR7)) + || opP->index.size != SIZE_UNSPEC + || opP->index.scale != 1)) losing++; break; case 's': - if (opP->mode != MSCR || !(opP->reg == FPI || opP->reg == FPS || opP->reg == FPC)) + if (opP->mode != CONTROL + || ! (opP->reg == FPI + || opP->reg == FPS + || opP->reg == FPC)) losing++; break; case 'S': - if (opP->mode != MSCR || opP->reg != SR) + if (opP->mode != CONTROL || opP->reg != SR) losing++; break; case 't': if (opP->mode != IMMED) losing++; - else - { - long t = get_num (opP->con1, 80); - if (t < 0 || t > 7 || isvar (opP->con1)) - losing++; - } + else if (! expr8 (&opP->disp) + || opP->disp.exp.X_add_number < 0 + || opP->disp.exp.X_add_number > 7) + losing++; break; case 'U': - if (opP->mode != MSCR || opP->reg != USP) + if (opP->mode != CONTROL || opP->reg != USP) losing++; break; @@ -2058,57 +1101,67 @@ m68k_ip (instring) #ifndef NO_68851 /* Memory addressing mode used by pflushr */ case '|': - if (opP->mode == MSCR || opP->mode == DREG || - opP->mode == AREG || opP->mode == REGLST) + if (opP->mode == CONTROL + || opP->mode == FPREG + || opP->mode == DREG + || opP->mode == AREG + || opP->mode == REGLST) losing++; break; case 'f': - if (opP->mode != MSCR || (opP->reg != SFC && opP->reg != DFC)) + if (opP->mode != CONTROL + || (opP->reg != SFC && opP->reg != DFC)) losing++; break; case 'P': - if (opP->mode != MSCR - || (opP->reg != TC && opP->reg != CAL - && opP->reg != VAL && opP->reg != SCC && opP->reg != AC)) + if (opP->mode != CONTROL + || (opP->reg != TC + && opP->reg != CAL + && opP->reg != VAL + && opP->reg != SCC + && opP->reg != AC)) losing++; break; case 'V': - if (opP->reg != VAL) + if (opP->mode != CONTROL + || opP->reg != VAL) losing++; break; case 'W': - if (opP->mode != MSCR - || (opP->reg != DRP && opP->reg != SRP + if (opP->mode != CONTROL + || (opP->reg != DRP + && opP->reg != SRP && opP->reg != CRP)) losing++; break; case 'X': - if (opP->mode != MSCR || - (!(opP->reg >= BAD && opP->reg <= BAD + 7) && - !(opP->reg >= BAC && opP->reg <= BAC + 7))) + if (opP->mode != CONTROL + || (!(opP->reg >= BAD && opP->reg <= BAD + 7) + && !(opP->reg >= BAC && opP->reg <= BAC + 7))) losing++; break; case 'Y': - if (opP->reg != PSR) + if (opP->mode != CONTROL || opP->reg != PSR) losing++; break; case 'Z': - if (opP->reg != PCSR) + if (opP->mode != CONTROL || opP->reg != PCSR) losing++; break; #endif case 'c': - if (opP->reg != NC - && opP->reg != IC - && opP->reg != DC - && opP->reg != BC) + if (opP->mode != CONTROL + || (opP->reg != NC + && opP->reg != IC + && opP->reg != DC + && opP->reg != BC)) { losing++; } /* not a cache specifier. */ @@ -2116,14 +1169,11 @@ m68k_ip (instring) case '_': if (opP->mode != ABSL) - { - ++losing; - } /* not absolute */ + ++losing; break; default: - as_fatal ("Internal error: Operand mode %c unknown in line %d of file \"%s\"", - *s, __LINE__, __FILE__); + abort (); } /* switch on type of operand */ if (losing) @@ -2145,7 +1195,8 @@ m68k_ip (instring) { char buf[200], *cp; int len; - strcpy (buf, "invalid instruction for this architecture; needs "); + strcpy (buf, + "invalid instruction for this architecture; needs "); cp = buf + strlen (buf); switch (ok_arch) { @@ -2167,7 +1218,8 @@ m68k_ip (instring) default: { int got_one = 0, idx; - for (idx = 0; idx < sizeof (archs) / sizeof (archs[0]); idx++) + for (idx = 0; idx < sizeof (archs) / sizeof (archs[0]); + idx++) { if (archs[idx].arch & ok_arch) { @@ -2230,11 +1282,11 @@ m68k_ip (instring) case IMMED: tmpreg = 0x3c; /* 7.4 */ if (strchr ("bwl", s[1])) - nextword = get_num (opP->con1, 80); + nextword = get_num (&opP->disp, 80); else - nextword = get_num (opP->con1, 0); - if (isvar (opP->con1)) - add_fix (s[1], opP->con1, 0, 0); + nextword = get_num (&opP->disp, 0); + if (isvar (&opP->disp)) + add_fix (s[1], &opP->disp, 0, 0); switch (s[1]) { case 'b': @@ -2272,23 +1324,22 @@ m68k_ip (instring) outro = -1; break; default: - as_fatal ("Internal error: Can't decode %c%c in line %d of file \"%s\"", - *s, s[1], __LINE__, __FILE__); + abort (); } if (!baseo) break; /* We gotta put out some float */ - if (op (opP->con1) != O_big) + if (op (&opP->disp) != O_big) { valueT val; int gencnt; /* Can other cases happen here? */ - if (op (opP->con1) != O_constant) + if (op (&opP->disp) != O_constant) abort (); - val = (valueT) offs (opP->con1); + val = (valueT) offs (&opP->disp); gencnt = 0; do { @@ -2297,19 +1348,22 @@ m68k_ip (instring) ++gencnt; } while (val != 0); - offs (opP->con1) = gencnt; + offs (&opP->disp) = gencnt; } - if (offs (opP->con1) > 0) + if (offs (&opP->disp) > 0) { - if (offs (opP->con1) > baseo) + if (offs (&opP->disp) > baseo) { - as_warn ("Bignum too big for %c format; truncated", s[1]); - offs (opP->con1) = baseo; + as_warn ("Bignum too big for %c format; truncated", + s[1]); + offs (&opP->disp) = baseo; } - baseo -= offs (opP->con1); + baseo -= offs (&opP->disp); while (baseo--) addword (0); - for (wordp = generic_bignum + offs (opP->con1) - 1; offs (opP->con1)--; --wordp) + for (wordp = generic_bignum + offs (&opP->disp) - 1; + offs (&opP->disp)--; + --wordp) addword (*wordp); break; } @@ -2332,9 +1386,9 @@ m68k_ip (instring) case AINC: tmpreg = 0x18 + opP->reg - ADDR; /* 3.areg */ break; - case AOFF: + case DISP: - nextword = get_num (opP->con1, 80); + nextword = get_num (&opP->disp, 80); /* Force into index mode. Hope this works */ /* We do the first bit for 32-bit displacements, and the @@ -2344,28 +1398,27 @@ m68k_ip (instring) inefficiency for the sake of working output. */ if (!issword (nextword) - || (isvar (opP->con1) - && ((opP->con1->e_siz == 0 + || (isvar (&opP->disp) + && ((opP->disp.size == SIZE_UNSPEC && flag_short_refs == 0 && cpu_of_arch (current_architecture) >= m68020) - || opP->con1->e_siz == 3))) + || opP->disp.size == SIZE_LONG))) { - if (opP->reg == PC) tmpreg = 0x3B; /* 7.3 */ else tmpreg = 0x30 + opP->reg - ADDR; /* 6.areg */ - if (isvar (opP->con1)) + if (isvar (&opP->disp)) { if (opP->reg == PC) { #if 0 addword (0x0170); - add_fix ('l', opP->con1, 1, 2); + add_fix ('l', &opP->disp, 1, 2); addword (0), addword (0); #else - add_frag (adds (opP->con1), - offs (opP->con1), + add_frag (adds (&opP->disp), + offs (&opP->disp), TAB (PCLEA, SZ_UNDEF)); #endif break; @@ -2373,7 +1426,7 @@ m68k_ip (instring) else { addword (0x0170); - add_fix ('l', opP->con1, 0, 0); + add_fix ('l', &opP->disp, 0, 0); } } else @@ -2387,55 +1440,74 @@ m68k_ip (instring) else tmpreg = 0x28 + opP->reg - ADDR; /* 5.areg */ - if (isvar (opP->con1)) + if (isvar (&opP->disp)) { if (opP->reg == PC) { - add_fix ('w', opP->con1, 1, 0); + add_fix ('w', &opP->disp, 1, 0); } else - add_fix ('w', opP->con1, 0, 0); + add_fix ('w', &opP->disp, 0, 0); } } addword (nextword); break; - case APODX: - case AMIND: - case APRDX: - know (current_architecture & m68020up); - /* intentional fall-through */ - case AINDX: + case POST: + case PRE: + case BASE: nextword = 0; - baseo = get_num (opP->con1, 80); - outro = get_num (opP->con2, 80); + baseo = get_num (&opP->disp, 80); + if (opP->mode == POST || opP->mode == PRE) + outro = get_num (&opP->odisp, 80); /* Figure out the `addressing mode'. Also turn on the BASE_DISABLE bit, if needed. */ if (opP->reg == PC || opP->reg == ZPC) { - tmpreg = 0x3b;/* 7.3 */ + tmpreg = 0x3b; /* 7.3 */ if (opP->reg == ZPC) nextword |= 0x80; } - else if (opP->reg == FAIL) + else if (opP->reg == 0) + { + nextword |= 0x80; + tmpreg = 0x30; /* 6.garbage */ + } + else if (opP->reg >= ZADDR0 && opP->reg <= ZADDR7) { nextword |= 0x80; - tmpreg = 0x30;/* 6.garbage */ + tmpreg = 0x30 + opP->reg - ZADDR0; } else tmpreg = 0x30 + opP->reg - ADDR; /* 6.areg */ - siz1 = (opP->con1) ? opP->con1->e_siz : 0; - siz2 = (opP->con2) ? opP->con2->e_siz : 0; + siz1 = opP->disp.size; + if (opP->mode == POST || opP->mode == PRE) + siz2 = opP->odisp.size; + else + siz2 = SIZE_UNSPEC; /* Index register stuff */ - if (opP->ireg >= DATA + 0 && opP->ireg <= ADDR + 7) + if (opP->index.reg != 0 + && opP->index.reg >= DATA + && opP->index.reg <= ADDR7) { - nextword |= (opP->ireg - DATA) << 12; + nextword |= (opP->index.reg - DATA) << 12; - if (opP->isiz == 0 || opP->isiz == 3) + if (opP->index.size == SIZE_UNSPEC + || opP->index.size == SIZE_LONG) nextword |= 0x800; - switch (opP->imul) + + if (cpu_of_arch (current_architecture) < m68020) + { + if (opP->index.scale != 1) + { + opP->error = + "scale factor invalid on this architecture; needs 68020 or higher"; + } + } + + switch (opP->index.scale) { case 1: break; @@ -2449,7 +1521,7 @@ m68k_ip (instring) nextword |= 0x600; break; default: - as_fatal ("failed sanity check."); + abort (); } /* IF its simple, GET US OUT OF HERE! */ @@ -2459,68 +1531,79 @@ m68k_ip (instring) forced, or we know it will fit. For a 68000 or 68010, force this mode anyways, because the larger modes aren't supported. */ - if (opP->mode == AINDX - && opP->reg != FAIL - && opP->reg != ZPC - && (/* :b specified */ - siz1 == 1 - /* known to fit in 8 bits */ - || (issbyte (baseo) && !isvar (opP->con1)) - /* doesn't support wider modes */ - || cpu_of_arch (current_architecture) < m68020 - /* simple enough to do relaxation */ - || subs (opP->con1) == NULL - )) + if (opP->mode == BASE + && ((opP->reg >= ADDR0 + && opP->reg <= ADDR7) + || opP->reg == PC)) { - if (((!isvar (opP->con1) - || subs (opP->con1) != NULL) - && siz1 == 0) - || siz1 == 1) - { - /* Can't handle more complex expressions - here yet. Should only wind up here if - the CPU doesn't support wider modes, so - do a byte relocation and let the fixup - processing later complain if it won't - reach. */ + if (siz1 == SIZE_BYTE + || cpu_of_arch (current_architecture) < m68020 + || (siz1 == SIZE_UNSPEC + && ! isvar (&opP->disp) + && issbyte (baseo))) + { nextword += baseo & 0xff; addword (nextword); - if (isvar (opP->con1)) + if (isvar (&opP->disp)) { + /* Do a byte relocation. If it doesn't + fit (possible on m68000) let the + fixup processing complain later. */ if (opP->reg == PC) - add_fix ('B', opP->con1, 1, 1); + add_fix ('B', &opP->disp, 1, 1); else - add_fix ('B', opP->con1, 0, 0); + add_fix ('B', &opP->disp, 0, 0); } - } - else if (opP->reg != PC || siz1 != 0) - { - goto no_pc_relax; - } - else - { + else if (siz1 != SIZE_BYTE) + { + if (siz1 != SIZE_UNSPEC) + as_warn ("Forcing byte displacement"); + if (! issbyte (baseo)) + opP->error = "byte displacement out of range"; + } + + break; + } + else if (siz1 == SIZE_UNSPEC + && opP->reg == PC + && isvar (&opP->disp) + && subs (&opP->disp) == NULL) + { nextword += baseo & 0xff; addword (nextword); - add_frag (adds (opP->con1), offs (opP->con1), + add_frag (adds (&opP->disp), offs (&opP->disp), TAB (PCINDEX, SZ_UNDEF)); + + break; } - break; } } else - nextword |= 0x40; /* No index reg */ + { + nextword |= 0x40; /* No index reg */ + if (opP->index.reg >= ZDATA0 + && opP->index.reg <= ZDATA7) + nextword |= (opP->index.reg - ZDATA0) << 12; + else if (opP->index.reg >= ZADDR0 + || opP->index.reg <= ZADDR7) + nextword |= (opP->index.reg - ZADDR0 + 8) << 12; + } - no_pc_relax: /* It isn't simple. */ + + if (cpu_of_arch (current_architecture) < m68020) + opP->error = + "invalid operand mode for this architecture; needs 68020 or higher"; + nextword |= 0x100; /* If the guy specified a width, we assume that it is wide enough. Maybe it isn't. If so, we lose. */ switch (siz1) { - case 0: - if (isvar (opP->con1) || !issword (baseo)) + case SIZE_UNSPEC: + if (isvar (&opP->disp) || !issword (baseo)) { - siz1 = 3; + siz1 = SIZE_LONG; nextword |= 0x30; } else if (baseo == 0) @@ -2528,28 +1611,29 @@ m68k_ip (instring) else { nextword |= 0x20; - siz1 = 2; + siz1 = SIZE_WORD; } break; - case 1: - as_warn ("Byte dispacement won't work. Defaulting to :w"); - case 2: + case SIZE_BYTE: + as_warn (":b not permitted; defaulting to :w"); + /* Fall through. */ + case SIZE_WORD: nextword |= 0x20; break; - case 3: + case SIZE_LONG: nextword |= 0x30; break; } /* Figure out innner displacement stuff */ - if (opP->mode != AINDX) + if (opP->mode == POST || opP->mode == PRE) { switch (siz2) { - case 0: - if (isvar (opP->con2) || !issword (outro)) + case SIZE_UNSPEC: + if (isvar (&opP->odisp) || !issword (outro)) { - siz2 = 3; + siz2 = SIZE_LONG; nextword |= 0x3; } else if (outro == 0) @@ -2557,11 +1641,12 @@ m68k_ip (instring) else { nextword |= 0x2; - siz2 = 2; + siz2 = SIZE_WORD; } break; case 1: - as_warn ("Byte dispacement won't work. Defaulting to :w"); + as_warn (":b not permitted; defaulting to :w"); + /* Fall through. */ case 2: nextword |= 0x2; break; @@ -2569,44 +1654,40 @@ m68k_ip (instring) nextword |= 0x3; break; } - if (opP->mode == APODX) + if (opP->mode == POST) nextword |= 0x04; - else if (opP->mode == AMIND) - nextword |= 0x40; } addword (nextword); - if (isvar (opP->con1)) + if (siz1 != SIZE_UNSPEC && isvar (&opP->disp)) { if (opP->reg == PC || opP->reg == ZPC) - { - add_fix (siz1 == 3 ? 'l' : 'w', opP->con1, 1, 2); - } + add_fix (siz1 == SIZE_LONG ? 'l' : 'w', &opP->disp, 1, 2); else - add_fix (siz1 == 3 ? 'l' : 'w', opP->con1, 0, 0); + add_fix (siz1 == SIZE_LONG ? 'l' : 'w', &opP->disp, 0, 0); } - if (siz1 == 3) + if (siz1 == SIZE_LONG) addword (baseo >> 16); - if (siz1) + if (siz1 != SIZE_UNSPEC) addword (baseo); - if (isvar (opP->con2)) - add_fix (siz2 == 3 ? 'l' : 'w', opP->con2, 0, 0); - if (siz2 == 3) + if (siz2 != SIZE_UNSPEC && isvar (&opP->odisp)) + add_fix (siz2 == SIZE_LONG ? 'l' : 'w', &opP->odisp, 0, 0); + if (siz2 == SIZE_LONG) addword (outro >> 16); - if (siz2) + if (siz2 != SIZE_UNSPEC) addword (outro); break; case ABSL: - nextword = get_num (opP->con1, 80); - switch (opP->con1->e_siz) + nextword = get_num (&opP->disp, 80); + switch (opP->disp.size) { default: - as_warn ("Unknown size for absolute reference"); - case 0: - if (!isvar (opP->con1) && issword (offs (opP->con1))) + abort (); + case SIZE_UNSPEC: + if (!isvar (&opP->disp) && issword (offs (&opP->disp))) { tmpreg = 0x38; /* 7.0 */ addword (nextword); @@ -2614,43 +1695,42 @@ m68k_ip (instring) } /* Don't generate pc relative code on 68010 and 68000. */ - if (isvar (opP->con1) - && !subs (opP->con1) - && seg (opP->con1) == text_section + if (isvar (&opP->disp) + && !subs (&opP->disp) + && adds (&opP->disp) + && (S_GET_SEGMENT (adds (&opP->disp)) == text_section) && now_seg == text_section && cpu_of_arch (current_architecture) >= m68020 && !flag_long_jumps && !strchr ("~%&$?", s[0])) { tmpreg = 0x3A; /* 7.2 */ - add_frag (adds (opP->con1), - offs (opP->con1), + add_frag (adds (&opP->disp), + offs (&opP->disp), TAB (PCREL, SZ_UNDEF)); break; } /* Fall through into long */ - case 3: - if (isvar (opP->con1)) - add_fix ('l', opP->con1, 0, 0); + case SIZE_LONG: + if (isvar (&opP->disp)) + add_fix ('l', &opP->disp, 0, 0); tmpreg = 0x39;/* 7.1 mode */ addword (nextword >> 16); addword (nextword); break; - case 2: /* Word */ - if (isvar (opP->con1)) - add_fix ('w', opP->con1, 0, 0); + case SIZE_WORD: /* Word */ + if (isvar (&opP->disp)) + add_fix ('w', &opP->disp, 0, 0); tmpreg = 0x38;/* 7.0 mode */ addword (nextword); break; } break; - case DINDR: - as_bad ("invalid indirect register"); - break; - case MSCR: + case CONTROL: + case FPREG: default: as_bad ("unknown/incorrect operand"); /* abort(); */ @@ -2676,9 +1756,9 @@ m68k_ip (instring) tmpreg = 80; break; } - tmpreg = get_num (opP->con1, tmpreg); - if (isvar (opP->con1)) - add_fix (s[1], opP->con1, 0, 0); + tmpreg = get_num (&opP->disp, tmpreg); + if (isvar (&opP->disp)) + add_fix (s[1], &opP->disp, 0, 0); switch (s[1]) { case 'b': /* Danger: These do no check for @@ -2687,14 +1767,14 @@ m68k_ip (instring) if (!isbyte (tmpreg)) opP->error = "out of range"; insop (tmpreg, opcode); - if (isvar (opP->con1)) + if (isvar (&opP->disp)) the_ins.reloc[the_ins.nrel - 1].n = (opcode->m_codenum) * 2; break; case 'w': if (!isword (tmpreg)) opP->error = "out of range"; insop (tmpreg, opcode); - if (isvar (opP->con1)) + if (isvar (&opP->disp)) the_ins.reloc[the_ins.nrel - 1].n = (opcode->m_codenum) * 2; break; case 'l': @@ -2702,7 +1782,7 @@ m68k_ip (instring) backwards. */ insop (tmpreg, opcode); insop (tmpreg >> 16, opcode); - if (isvar (opP->con1)) + if (isvar (&opP->disp)) the_ins.reloc[the_ins.nrel - 1].n = (opcode->m_codenum) * 2; break; case '3': @@ -2712,7 +1792,7 @@ m68k_ip (instring) install_operand (s[1], tmpreg); break; default: - as_fatal ("Internal error: Unknown mode #%c in line %d of file \"%s\"", s[1], __LINE__, __FILE__); + abort (); } break; @@ -2724,51 +1804,47 @@ m68k_ip (instring) break; case 'B': - tmpreg = get_num (opP->con1, 80); + tmpreg = get_num (&opP->disp, 80); switch (s[1]) { case 'B': - add_fix ('B', opP->con1, 1, -1); + add_fix ('B', &opP->disp, 1, -1); break; case 'W': - add_fix ('w', opP->con1, 1, 0); + add_fix ('w', &opP->disp, 1, 0); addword (0); break; case 'L': long_branch: - if (cpu_of_arch (current_architecture) < m68020) /* 68000 or 010 */ + if (cpu_of_arch (current_architecture) < m68020) as_warn ("Can't use long branches on 68000/68010"); the_ins.opcode[the_ins.numo - 1] |= 0xff; - add_fix ('l', opP->con1, 1, 0); + add_fix ('l', &opP->disp, 1, 0); addword (0); addword (0); break; case 'g': - if (subs (opP->con1)) /* We can't relax it */ + if (subs (&opP->disp)) /* We can't relax it */ goto long_branch; - /* This could either be a symbol, or an - absolute address. No matter, the - frag hacking will finger it out. - Not quite: it can't switch from - BRANCH to BCC68000 for the case - where opnd is absolute (it needs - to use the 68000 hack since no - conditional abs jumps). */ + /* This could either be a symbol, or an absolute + address. No matter, the frag hacking will finger it + out. Not quite: it can't switch from BRANCH to + BCC68000 for the case where opnd is absolute (it + needs to use the 68000 hack since no conditional abs + jumps). */ if (((cpu_of_arch (current_architecture) < m68020) - || (0 == adds (opP->con1))) + || (0 == adds (&opP->disp))) && (the_ins.opcode[0] >= 0x6200) && (the_ins.opcode[0] <= 0x6f00)) - { - add_frag (adds (opP->con1), offs (opP->con1), TAB (BCC68000, SZ_UNDEF)); - } + add_frag (adds (&opP->disp), offs (&opP->disp), + TAB (BCC68000, SZ_UNDEF)); else - { - add_frag (adds (opP->con1), offs (opP->con1), TAB (ABRANCH, SZ_UNDEF)); - } + add_frag (adds (&opP->disp), offs (&opP->disp), + TAB (ABRANCH, SZ_UNDEF)); break; case 'w': - if (isvar (opP->con1)) + if (isvar (&opP->disp)) { #if 1 /* check for DBcc instruction */ @@ -2776,42 +1852,41 @@ m68k_ip (instring) { /* size varies if patch */ /* needed for long form */ - add_frag (adds (opP->con1), offs (opP->con1), + add_frag (adds (&opP->disp), offs (&opP->disp), TAB (DBCC, SZ_UNDEF)); break; } #endif - add_fix ('w', opP->con1, 1, 0); + add_fix ('w', &opP->disp, 1, 0); } addword (0); break; case 'C': /* Fixed size LONG coproc branches */ - add_fix ('l', opP->con1, 1, 0); + add_fix ('l', &opP->disp, 1, 0); addword (0); addword (0); break; case 'c': /* Var size Coprocesssor branches */ - if (subs (opP->con1)) + if (subs (&opP->disp)) { - add_fix ('l', opP->con1, 1, 0); + add_fix ('l', &opP->disp, 1, 0); add_frag ((symbolS *) 0, (long) 0, TAB (FBRANCH, LONG)); } - else if (adds (opP->con1)) - { - add_frag (adds (opP->con1), offs (opP->con1), TAB (FBRANCH, SZ_UNDEF)); - } + else if (adds (&opP->disp)) + add_frag (adds (&opP->disp), offs (&opP->disp), + TAB (FBRANCH, SZ_UNDEF)); else { - /* add_frag((symbolS *)0,offs(opP->con1),TAB(FBRANCH,SHORT)); */ + /* add_frag((symbolS *) 0, offs(&opP->disp), + TAB(FBRANCH,SHORT)); */ the_ins.opcode[the_ins.numo - 1] |= 0x40; - add_fix ('l', opP->con1, 1, 0); + add_fix ('l', &opP->disp, 1, 0); addword (0); addword (0); } break; default: - as_fatal ("Internal error: operand type B%c unknown in line %d of file \"%s\"", - s[1], __LINE__, __FILE__); + abort (); } break; @@ -2819,28 +1894,8 @@ m68k_ip (instring) break; case 'd': /* JF this is a kludge */ - if (opP->mode == AOFF) - { - install_operand ('s', opP->reg - ADDR); - } - else - { - char *tmpP; - - tmpP = opP->con1->e_end - 2; - opP->con1->e_beg++; - opP->con1->e_end -= 4; /* point to the , */ - baseo = m68k_reg_parse (&tmpP); - if (baseo < ADDR + 0 || baseo > ADDR + 7) - { - as_bad ("Unknown address reg, using A0"); - baseo = 0; - } - else - baseo -= ADDR; - install_operand ('s', baseo); - } - tmpreg = get_num (opP->con1, 80); + install_operand ('s', opP->reg - ADDR); + tmpreg = get_num (&opP->disp, 80); if (!issword (tmpreg)) { as_warn ("Expression out of range, using 0"); @@ -2854,7 +1909,7 @@ m68k_ip (instring) break; case 'F': - install_operand (s[1], opP->reg - FPREG); + install_operand (s[1], opP->reg - FP0); break; case 'I': @@ -2923,18 +1978,18 @@ m68k_ip (instring) tmpreg = 0x808; break; default: - as_fatal ("failed sanity check."); + abort (); } install_operand (s[1], tmpreg); break; case 'k': - tmpreg = get_num (opP->con1, 55); + tmpreg = get_num (&opP->disp, 55); install_operand (s[1], tmpreg & 0x7f); break; case 'l': - tmpreg = opP->reg; + tmpreg = opP->mask; if (s[1] == 'w') { if (tmpreg & 0x7FF0000) @@ -2950,7 +2005,7 @@ m68k_ip (instring) break; case 'L': - tmpreg = opP->reg; + tmpreg = opP->mask; if (s[1] == 'w') { if (tmpreg & 0x7FF0000) @@ -2973,31 +2028,37 @@ m68k_ip (instring) break; case 'M': - install_operand (s[1], get_num (opP->con1, 60)); + install_operand (s[1], get_num (&opP->disp, 60)); break; case 'O': - tmpreg = (opP->mode == DREG) - ? 0x20 + opP->reg - DATA - : (get_num (opP->con1, 40) & 0x1F); + tmpreg = ((opP->mode == DREG) + ? 0x20 + opP->reg - DATA + : (get_num (&opP->disp, 40) & 0x1F)); install_operand (s[1], tmpreg); break; case 'Q': - tmpreg = get_num (opP->con1, 10); + tmpreg = get_num (&opP->disp, 10); if (tmpreg == 8) tmpreg = 0; install_operand (s[1], tmpreg); break; case 'R': - case 'r': - /* This depends on the fact that ADDR registers are - eight more than their corresponding DATA regs, so - the result will have the ADDR_REG bit set */ + /* This depends on the fact that ADDR registers are eight + more than their corresponding DATA regs, so the result + will have the ADDR_REG bit set */ install_operand (s[1], opP->reg - DATA); break; + case 'r': + if (opP->mode == AINDR) + install_operand (s[1], opP->reg - DATA); + else + install_operand (s[1], opP->index.reg - DATA); + break; + case 's': if (opP->reg == FPI) tmpreg = 0x1; @@ -3006,7 +2067,7 @@ m68k_ip (instring) else if (opP->reg == FPC) tmpreg = 0x4; else - as_fatal ("failed sanity check."); + abort (); install_operand (s[1], tmpreg); break; @@ -3014,7 +2075,7 @@ m68k_ip (instring) break; case 'T': - install_operand (s[1], get_num (opP->con1, 30)); + install_operand (s[1], get_num (&opP->disp, 30)); break; case 'U': /* Ignore it */ @@ -3052,7 +2113,7 @@ m68k_ip (instring) tmpreg = 1; break; default: - as_fatal ("failed sanity check."); + abort (); } install_operand (s[1], tmpreg); break; @@ -3076,7 +2137,7 @@ m68k_ip (instring) tmpreg = 7; break; default: - as_fatal ("failed sanity check."); + abort (); } install_operand (s[1], tmpreg); break; @@ -3084,12 +2145,11 @@ m68k_ip (instring) case 'V': if (opP->reg == VAL) break; - as_fatal ("failed sanity check."); + abort (); case 'W': switch (opP->reg) { - case DRP: tmpreg = 1; break; @@ -3100,7 +2160,7 @@ m68k_ip (instring) tmpreg = 3; break; default: - as_fatal ("failed sanity check."); + abort (); } install_operand (s[1], tmpreg); break; @@ -3131,7 +2191,7 @@ m68k_ip (instring) break; default: - as_fatal ("failed sanity check."); + abort (); } install_operand (s[1], tmpreg); break; @@ -3152,109 +2212,27 @@ m68k_ip (instring) tmpreg = 3; break; default: - as_fatal ("failed sanity check"); + abort (); } install_operand (s[1], tmpreg); break; case 't': - tmpreg = get_num (opP->con1, 20); + tmpreg = get_num (&opP->disp, 20); install_operand (s[1], tmpreg); break; - case '_': /* used only for move16 absolute 32-bit address */ - tmpreg = get_num (opP->con1, 80); + case '_': /* used only for move16 absolute 32-bit address */ + tmpreg = get_num (&opP->disp, 80); addword (tmpreg >> 16); addword (tmpreg & 0xFFFF); break; default: - as_fatal ("Internal error: Operand type %c unknown in line %d of file \"%s\"", - s[0], __LINE__, __FILE__); + abort (); } } /* By the time whe get here (FINALLY) the_ins contains the complete instruction, ready to be emitted. . . */ -} /* m68k_ip() */ - -/* - * get_regs := '/' + ? - * | '-' + <register> - * | '-' + <register> + ? - * | <empty> - * ; - * - - * The idea here must be to scan in a set of registers but I don't - * understand it. Looks awfully sloppy to me but I don't have any doc on - * this format so... - - * - * - */ - -static int -get_regs (i, str, opP) - int i; - struct m68k_op *opP; - char *str; -{ - /* 26, 25, 24, 23-16, 15-8, 0-7 */ - /* Low order 24 bits encoded fpc,fps,fpi,fp7-fp0,a7-a0,d7-d0 */ - unsigned long cur_regs = 0; - int reg1, reg2; - -#define ADD_REG(x) { if(x==FPI) cur_regs|=(1<<24);\ -else if(x==FPS) cur_regs|=(1<<25);\ -else if(x==FPC) cur_regs|=(1<<26);\ -else cur_regs|=(1<<(x-1)); } - - reg1 = i; - for (;;) - { - if (*str == '/') - { - ADD_REG (reg1); - str++; - } - else if (*str == '-') - { - str++; - reg2 = m68k_reg_parse (&str); - if (reg2 < DATA || reg2 >= FPREG + 8 || reg1 == FPI || reg1 == FPS || reg1 == FPC) - { - opP->error = "unknown register in register list"; - return FAIL; - } - while (reg1 <= reg2) - { - ADD_REG (reg1); - reg1++; - } - if (*str == '\0') - break; - } - else if (*str == '\0') - { - ADD_REG (reg1); - break; - } - else - { - opP->error = "unknow character in register list"; - return FAIL; - } - /* DJA -- Bug Fix. Did't handle d1-d2/a1 until the following instruction was added */ - if (*str == '/') - str++; - reg1 = m68k_reg_parse (&str); - if ((reg1 < DATA || reg1 >= FPREG + 8) && !(reg1 == FPI || reg1 == FPS || reg1 == FPC)) - { - opP->error = "unknown register in register list"; - return FAIL; - } - } - opP->reg = cur_regs; - return OK; -} /* get_regs() */ +} static int reverse_16_bits (in) @@ -3460,7 +2438,7 @@ crack_operand (str, opP) } c = *str; *str = '\0'; - if (m68k_ip_op (beg_str, opP) == FAIL) + if (m68k_ip_op (beg_str, opP) != 0) { *str = c; return str; @@ -3536,6 +2514,7 @@ static const struct init_entry init_table[] = { "fp", ADDR6 }, { "a7", ADDR7 }, { "sp", ADDR7 }, + { "ssp", ADDR7 }, { "fp0", FP0 }, { "fp1", FP1 }, { "fp2", FP2 }, @@ -3631,6 +2610,24 @@ static const struct init_entry init_table[] = /* 68ec030 access control unit, identical to 030 MMU status reg */ { "acusr", PSR }, + /* Suppressed data and address registers. */ + { "zd0", ZDATA0 }, + { "zd1", ZDATA1 }, + { "zd2", ZDATA2 }, + { "zd3", ZDATA3 }, + { "zd4", ZDATA4 }, + { "zd5", ZDATA5 }, + { "zd6", ZDATA6 }, + { "zd7", ZDATA7 }, + { "za0", ZADDR0 }, + { "za1", ZADDR1 }, + { "za2", ZADDR2 }, + { "za3", ZADDR3 }, + { "za4", ZADDR4 }, + { "za5", ZADDR5 }, + { "za6", ZADDR6 }, + { "za7", ZADDR7 }, + { 0, 0 } }; @@ -3653,7 +2650,7 @@ void md_assemble (str) char *str; { - char *er; + const char *er; short *fromP; char *toP = NULL; int m, n = 0; @@ -3666,7 +2663,7 @@ md_assemble (str) er = the_ins.error; if (!er) { - for (n = the_ins.numargs; n; --n) + for (n = 0; n < the_ins.numargs; n++) if (the_ins.operands[n].error) { er = the_ins.operands[n].error; @@ -3806,21 +2803,6 @@ md_assemble (str) } } -/* See BREAK_UP_BIG_DECL definition, above. */ -#ifdef DO_BREAK_UP_BIG_DECL -static const struct m68k_opcode * -opcode_ptr (i) - int i; -{ - int lim1 = sizeof (m68k_opcodes) / sizeof (m68k_opcodes[0]); - if (i >= lim1) - return m68k_opcodes_2 + (i - lim1); - return m68k_opcodes + i; -} -#else -#define opcode_ptr(i) (m68k_opcodes + i) -#endif - void md_begin () { @@ -3847,12 +2829,12 @@ md_begin () op_hash = hash_new (); obstack_begin (&robyn, 4000); - for (i = 0; i < numopcodes; i++) + for (i = 0; i < m68k_numopcodes; i++) { hack = slak = (struct m68k_incant *) obstack_alloc (&robyn, sizeof (struct m68k_incant)); do { - ins = opcode_ptr (i); + ins = &m68k_opcodes[i]; /* We *could* ignore insns that don't match our arch here but just leaving them out of the hash. */ slak->m_operands = ins->args; @@ -3861,8 +2843,8 @@ md_begin () slak->m_opcode = ins->opcode; /* This is kludgey */ slak->m_codenum = ((ins->match) & 0xffffL) ? 2 : 1; - if (i + 1 != numopcodes - && !strcmp (ins->name, opcode_ptr (i + 1)->name)) + if (i + 1 != m68k_numopcodes + && !strcmp (ins->name, m68k_opcodes[i + 1].name)) { slak->m_next = (struct m68k_incant *) obstack_alloc (&robyn, sizeof (struct m68k_incant)); i++; @@ -3878,7 +2860,7 @@ md_begin () as_fatal ("Internal Error: Can't hash %s: %s", ins->name, retval); } - for (i = 0; i < numaliases; i++) + for (i = 0; i < m68k_numaliases; i++) { const char *name = m68k_opcode_aliases[i].primary; const char *alias = m68k_opcode_aliases[i].alias; @@ -3913,6 +2895,16 @@ md_begin () alt_notend_table[REGISTER_PREFIX] = 1; #endif + /* We need to put '(' in alt_notend_table to handle + cas2 %d0:%d2,%d3:%d4,(%a0):(%a1) + */ + alt_notend_table['('] = 1; + + /* We need to put '@' in alt_notend_table to handle + cas2 %d0:%d2,%d3:%d4,@(%d0):@(%d1) + */ + alt_notend_table['@'] = 1; + #ifndef MIT_SYNTAX_ONLY /* Insert pseudo ops, these have to go into the opcode table since gas expects pseudo ops to start with a dot */ @@ -4030,10 +3022,11 @@ m68k_init_after_args () /* Equal to MAX_PRECISION in atof-ieee.c */ #define MAX_LITTLENUMS 6 -/* Turn a string in input_line_pointer into a floating point constant of type - type, and store the appropriate bytes in *litP. The number of LITTLENUMS - emitted is stored in *sizeP . An error message is returned, or NULL on OK. - */ +/* Turn a string in input_line_pointer into a floating point constant + of type type, and store the appropriate bytes in *litP. The number + of LITTLENUMS emitted is stored in *sizeP . An error message is + returned, or NULL on OK. */ + char * md_atof (type, litP, sizeP) char type; @@ -4778,7 +3771,9 @@ md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol) } #endif -/* Different values of OK tell what its OK to return. Things that aren't OK are an error (what a shock, no?) + +/* Different values of OK tell what its OK to return. Things that + aren't OK are an error (what a shock, no?) 0: Everything is OK 10: Absolute 1:8 only @@ -4798,79 +3793,9 @@ get_num (exp, ok) struct m68k_exp *exp; int ok; { -#ifdef TEST2 - long l = 0; - - if (!exp->e_beg) - return 0; - if (*exp->e_beg == '0') - { - if (exp->e_beg[1] == 'x') - sscanf (exp->e_beg + 2, "%x", &l); - else - sscanf (exp->e_beg + 1, "%O", &l); - return l; - } - return atol (exp->e_beg); -#else - char *save_in; - char c_save; - segT section; - - if (!exp) - { - /* Can't do anything */ - return 0; - } - if (!exp->e_beg || !exp->e_end) - { - seg (exp) = absolute_section; - adds (exp) = 0; - subs (exp) = 0; - offs (exp) = (ok == 10) ? 1 : 0; - as_warn ("Null expression defaults to %ld", offs (exp)); - return 0; - } - - exp->e_siz = 0; - if ( /* ok!=80 && */ (exp->e_end[-1] == ':' || exp->e_end[-1] == '.') - && (exp->e_end - exp->e_beg) >= 2) - { - switch (exp->e_end[0]) - { - case 's': - case 'S': - case 'b': - case 'B': - exp->e_siz = 1; - exp->e_end -= 2; - break; - case 'w': - case 'W': - exp->e_siz = 2; - exp->e_end -= 2; - break; - case 'l': - case 'L': - exp->e_siz = 3; - exp->e_end -= 2; - break; - default: - if (exp->e_end[-1] == ':') - as_bad ("Unknown size for expression \"%c\"", exp->e_end[0]); - break; - } - } - c_save = exp->e_end[1]; - exp->e_end[1] = '\0'; - save_in = input_line_pointer; - input_line_pointer = exp->e_beg; - section = expression (&exp->e_exp); - seg (exp) = section; - if (exp->e_exp.X_op == O_absent) + if (exp->exp.X_op == O_absent) { /* Do the same thing the VAX asm does */ - seg (exp) = absolute_section; op (exp) = O_constant; adds (exp) = 0; subs (exp) = 0; @@ -4881,7 +3806,7 @@ get_num (exp, ok) offs (exp) = 1; } } - else if (exp->e_exp.X_op == O_constant) + else if (exp->exp.X_op == O_constant) { switch (ok) { @@ -4928,7 +3853,7 @@ get_num (exp, ok) break; } } - else if (exp->e_exp.X_op == O_big) + else if (exp->exp.X_op == O_big) { if (offs (exp) <= 0 /* flonum */ && (ok == 80 /* no bignums */ @@ -4942,7 +3867,6 @@ get_num (exp, ok) LITTLENUM_TYPE words[6]; gen_to_words (words, 2, 8L); /* These numbers are magic! */ - seg (exp) = absolute_section; op (exp) = O_constant; adds (exp) = 0; subs (exp) = 0; @@ -4950,47 +3874,46 @@ get_num (exp, ok) } else if (ok != 0) { - seg (exp) = absolute_section; op (exp) = O_constant; adds (exp) = 0; subs (exp) = 0; offs (exp) = (ok == 10) ? 1 : 0; - as_warn ("Can't deal with expression \"%s\": defaulting to %ld", exp->e_beg, offs (exp)); + as_warn ("Can't deal with expression; defaulting to %ld", + offs (exp)); } } else { if (ok >= 10 && ok <= 70) { - seg (exp) = absolute_section; op (exp) = O_constant; adds (exp) = 0; subs (exp) = 0; offs (exp) = (ok == 10) ? 1 : 0; - as_warn ("Can't deal with expression \"%s\": defaulting to %ld", exp->e_beg, offs (exp)); + as_warn ("Can't deal with expression; defaulting to %ld", + offs (exp)); } } - if (input_line_pointer != exp->e_end + 1) - as_bad ("Ignoring junk after expression"); - exp->e_end[1] = c_save; - input_line_pointer = save_in; - if (exp->e_siz) + if (exp->size != SIZE_UNSPEC) { - switch (exp->e_siz) + switch (exp->size) { - case 1: + case SIZE_UNSPEC: + case SIZE_LONG: + break; + case SIZE_BYTE: if (!isbyte (offs (exp))) as_warn ("expression doesn't fit in BYTE"); break; - case 2: + case SIZE_WORD: if (!isword (offs (exp))) as_warn ("expression doesn't fit in WORD"); break; } } + return offs (exp); -#endif } /* These are the back-ends for the various machine dependent pseudo-ops. */ diff --git a/gas/configure b/gas/configure index 4508d48..293402a 100755 --- a/gas/configure +++ b/gas/configure @@ -555,7 +555,7 @@ te_file=generic # check for architecture variants case ${target_cpu} in armeb) cpu_type=arm endian=big ;; - arm*) cpu_tpye=arm endian=little ;; + arm*) cpu_type=arm endian=little ;; hppa*) cpu_type=hppa ;; i[45]86) cpu_type=i386 ;; m680[012346]0) cpu_type=m68k ;; @@ -636,7 +636,7 @@ for this_target in $target $canon_targets ; do rs6000*) cpu_type=ppc ;; sparc64) cpu_type=sparc obj_format=elf want_sparcv9=true ;; sparclite*) cpu_type=sparc ;; - *) cpu_type=${target_cpu} ;; + *) cpu_type=${cpu} ;; esac if test ${this_target} = $target ; then @@ -664,8 +664,7 @@ for this_target in $target $canon_targets ; do arc-*-elf*) fmt=elf bfd_gas=yes ;; # end-sanitize-arc - arm-*-riscix*) fmt=aout targ=arm-lit - emulation=riscix ;; + arm-*-riscix*) fmt=aout targ=arm-lit ;; arm-*-aout) fmt=aout case "$endian" in big) targ=arm-big ;; @@ -689,7 +688,7 @@ for this_target in $target $canon_targets ; do i386-*-bsd*) fmt=aout em=386bsd ;; i386-*-netbsd0.8) fmt=aout em=386bsd ;; i386-*-netbsd*) fmt=aout em=nbsd bfd_gas=yes;; - i386-*-linux*aout*) fmt=aout em=linux ;; + i386-*-linux*aout* | i386-*-linuxoldld) fmt=aout em=linux ;; i386-*-linux*coff*) fmt=coff em=linux targ=i386coff ;; i386-*-linux*) fmt=elf em=linux ;; @@ -828,6 +827,10 @@ for this_target in $target $canon_targets ; do *) ;; esac + case ${cpu_type} in + m68k) extra_objects="$extra_objects m68k-parse.o" ;; + esac + # See if we really can support this configuration with the emulation code. if test $this_target = $target ; then @@ -1227,7 +1230,7 @@ else # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. cat > conftest.$ac_ext <<EOF -#line 1231 "configure" +#line 1230 "configure" #include "confdefs.h" #include <assert.h> Syntax Error @@ -1241,7 +1244,7 @@ else rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext <<EOF -#line 1245 "configure" +#line 1244 "configure" #include "confdefs.h" #include <assert.h> Syntax Error @@ -1274,7 +1277,7 @@ if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1278 "configure" +#line 1277 "configure" #include "confdefs.h" #include <$ac_hdr> EOF @@ -1326,7 +1329,7 @@ else ac_cv_c_cross=yes else cat > conftest.$ac_ext <<EOF -#line 1330 "configure" +#line 1329 "configure" #include "confdefs.h" main(){return(0);} EOF @@ -1349,7 +1352,7 @@ if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1353 "configure" +#line 1352 "configure" #include "confdefs.h" #include <alloca.h> int main() { return 0; } @@ -1380,7 +1383,7 @@ if eval "test \"`echo '$''{'ac_cv_func_alloca'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1384 "configure" +#line 1383 "configure" #include "confdefs.h" #ifdef __GNUC__ @@ -1438,7 +1441,7 @@ if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1442 "configure" +#line 1441 "configure" #include "confdefs.h" #if defined(CRAY) && ! defined(CRAY2) webecray @@ -1466,7 +1469,7 @@ if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1470 "configure" +#line 1469 "configure" #include "confdefs.h" /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func(); below. */ @@ -1520,7 +1523,7 @@ else ac_cv_c_stack_direction=0 else cat > conftest.$ac_ext <<EOF -#line 1524 "configure" +#line 1523 "configure" #include "confdefs.h" find_stack_direction () { @@ -1562,7 +1565,7 @@ else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat > conftest.$ac_ext <<EOF -#line 1566 "configure" +#line 1565 "configure" #include "confdefs.h" int main() { return 0; } @@ -1601,7 +1604,7 @@ if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1605 "configure" +#line 1604 "configure" #include "confdefs.h" /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func(); below. */ @@ -1654,7 +1657,7 @@ if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1658 "configure" +#line 1657 "configure" #include "confdefs.h" /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func(); below. */ @@ -1707,7 +1710,7 @@ if eval "test \"`echo '$''{'gas_cv_assert_ok'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1711 "configure" +#line 1710 "configure" #include "confdefs.h" #include <assert.h> #include <stdio.h> @@ -1764,7 +1767,7 @@ if eval "test \"`echo '$''{'gas_cv_decl_needed_malloc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1768 "configure" +#line 1767 "configure" #include "confdefs.h" $gas_test_headers int main() { return 0; } @@ -1800,7 +1803,7 @@ if eval "test \"`echo '$''{'gas_cv_decl_needed_free'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1804 "configure" +#line 1803 "configure" #include "confdefs.h" $gas_test_headers int main() { return 0; } @@ -1839,7 +1842,7 @@ if eval "test \"`echo '$''{'gas_cv_decl_needed_errno'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1843 "configure" +#line 1842 "configure" #include "confdefs.h" #ifdef HAVE_ERRNO_H diff --git a/gas/configure.in b/gas/configure.in index 245b847..675cb22 100644 --- a/gas/configure.in +++ b/gas/configure.in @@ -39,7 +39,7 @@ te_file=generic # check for architecture variants case ${target_cpu} in armeb) cpu_type=arm endian=big ;; - arm*) cpu_tpye=arm endian=little ;; + arm*) cpu_type=arm endian=little ;; hppa*) cpu_type=hppa ;; changequote(,)dnl i[45]86) cpu_type=i386 ;; @@ -109,7 +109,7 @@ changequote([,])dnl rs6000*) cpu_type=ppc ;; sparc64) cpu_type=sparc obj_format=elf want_sparcv9=true ;; sparclite*) cpu_type=sparc ;; - *) cpu_type=${target_cpu} ;; + *) cpu_type=${cpu} ;; esac if test ${this_target} = $target ; then @@ -137,8 +137,7 @@ changequote([,])dnl arc-*-elf*) fmt=elf bfd_gas=yes ;; # end-sanitize-arc - arm-*-riscix*) fmt=aout targ=arm-lit - emulation=riscix ;; + arm-*-riscix*) fmt=aout targ=arm-lit ;; arm-*-aout) fmt=aout case "$endian" in big) targ=arm-big ;; @@ -162,7 +161,7 @@ changequote([,])dnl i386-*-bsd*) fmt=aout em=386bsd ;; i386-*-netbsd0.8) fmt=aout em=386bsd ;; i386-*-netbsd*) fmt=aout em=nbsd bfd_gas=yes;; - i386-*-linux*aout*) fmt=aout em=linux ;; + i386-*-linux*aout* | i386-*-linuxoldld) fmt=aout em=linux ;; i386-*-linux*coff*) fmt=coff em=linux targ=i386coff ;; i386-*-linux*) fmt=elf em=linux ;; @@ -301,6 +300,10 @@ changequote([,])dnl *) ;; esac + case ${cpu_type} in + m68k) extra_objects="$extra_objects m68k-parse.o" ;; + esac + # See if we really can support this configuration with the emulation code. if test $this_target = $target ; then |