aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>1995-08-08 02:36:10 +0000
committerIan Lance Taylor <ian@airs.com>1995-08-08 02:36:10 +0000
commita1c7c0f3ac78467be6f4d649a0ac0a7b2302aa2a (patch)
treebbd8a48660102b04207a51853902b8a68663c9d3 /gas
parent764efb58e9a436ceb69ab7228b9d867534d43e9a (diff)
downloadgdb-a1c7c0f3ac78467be6f4d649a0ac0a7b2302aa2a.zip
gdb-a1c7c0f3ac78467be6f4d649a0ac0a7b2302aa2a.tar.gz
gdb-a1c7c0f3ac78467be6f4d649a0ac0a7b2302aa2a.tar.bz2
* 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.
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog43
-rw-r--r--gas/Makefile.in17
-rw-r--r--gas/config/.Sanitize2
-rw-r--r--gas/config/m68k-parse.h279
-rw-r--r--gas/config/m68k-parse.y959
-rw-r--r--gas/config/tc-m68k.c2327
-rwxr-xr-xgas/configure45
-rw-r--r--gas/configure.in13
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