* Makefile.am: Bfin support.
authorCatherine Moore <clm@redhat.com>
Fri, 30 Sep 2005 15:05:07 +0000 (15:05 +0000)
committerCatherine Moore <clm@redhat.com>
Fri, 30 Sep 2005 15:05:07 +0000 (15:05 +0000)
* Makefile.in: Regenerated.
* aclocal.m4: Regenerated.
* configure: Regenerated.
* configure.in: Bfin support.
* configure.tgt: Bfin support.
* config/bfin-aux.h: New file.
* config/bfin-defs.h: New file.
* config/bfin-lex.l: New file.
* config/bfin-parse.y: New file.
* config/tc-bfin.c: New file.
* config/tc-bfin.h: New file.
* doc/Makefile.am: Recognize c-bfin.texi.
* doc/Makefile.in: Regenerated.
* doc/all.texi: Bfin support.
* doc/as.texinfo: Likewise.
* doc/c-bfin.texi: Document bfin-specific syntax and
directives.

18 files changed:
gas/ChangeLog
gas/Makefile.am
gas/Makefile.in
gas/aclocal.m4
gas/config/bfin-aux.h [new file with mode: 0755]
gas/config/bfin-defs.h [new file with mode: 0644]
gas/config/bfin-lex.l [new file with mode: 0644]
gas/config/bfin-parse.y [new file with mode: 0644]
gas/config/tc-bfin.c [new file with mode: 0644]
gas/config/tc-bfin.h [new file with mode: 0644]
gas/configure
gas/configure.in
gas/configure.tgt
gas/doc/Makefile.am
gas/doc/Makefile.in
gas/doc/all.texi
gas/doc/as.texinfo
gas/doc/c-bfin.texi [new file with mode: 0644]

index 88b6511c0968394743aec18fc8e3bdf458cd2302..c885fcfb0cce23709d0548e6a1f04845bc013ae5 100644 (file)
@@ -1,3 +1,24 @@
+2005-09-30  Catherine Moore  <clm@cm00re.com>
+
+       * Makefile.am: Bfin support.
+       * Makefile.in: Regenerated.
+       * aclocal.m4: Regenerated.
+       * configure: Regenerated.
+       * configure.in: Bfin support.
+       * configure.tgt: Bfin support.
+       * config/bfin-aux.h: New file.
+       * config/bfin-defs.h: New file.
+       * config/bfin-lex.l: New file.
+       * config/bfin-parse.y: New file.
+       * config/tc-bfin.c: New file.
+       * config/tc-bfin.h: New file.
+       * doc/Makefile.am: Recognize c-bfin.texi.
+       * doc/Makefile.in: Regenerated.
+       * doc/all.texi: Bfin support.
+       * doc/as.texinfo: Likewise.
+       * doc/c-bfin.texi: Document bfin-specific syntax and
+       directives.
+
 2005-09-30  Paul Brook  <paul@codesourcery.com>
 
        * config/tc-arm.c (opcode_tag): Add OT_cinfix3_legacy.
index eecedec19255efd67d30535b534b738aef8638fd..40fbc7d787a47af002a6379fc4041405526bd54c 100644 (file)
@@ -45,6 +45,7 @@ CPU_TYPES = \
        arc \
        arm \
        avr \
+       bfin \
        cris \
        crx \
        d10v \
@@ -227,6 +228,7 @@ TARGET_CPU_CFILES = \
        config/tc-arc.c \
        config/tc-arm.c \
        config/tc-avr.c \
+       config/tc-bfin.c \
        config/tc-cris.c \
        config/tc-crx.c \
        config/tc-d10v.c \
@@ -275,6 +277,7 @@ TARGET_CPU_HFILES = \
        config/tc-arc.h \
        config/tc-arm.h \
        config/tc-avr.h \
+       config/tc-bfin.h \
        config/tc-cris.h \
        config/tc-crx.h \
        config/tc-d10v.h \
@@ -437,7 +440,9 @@ noinst_PROGRAMS = as-new
 noinst_SCRIPTS = $(GDBINIT)
 EXTRA_SCRIPTS = .gdbinit
 
-EXTRA_DIST = m68k-parse.c itbl-parse.c itbl-parse.h itbl-lex.c
+EXTRA_DIST = m68k-parse.c itbl-parse.c itbl-parse.h itbl-lex.c \
+       bfin-parse.c bfin-lex.l bfin-defs.h
+
 diststuff: $(EXTRA_DIST) info
 all: info
 
@@ -567,7 +572,7 @@ xtensa-relax.o: $(srcdir)/config/xtensa-relax.c
 
 # The m68k operand parser.
 
-EXTRA_as_new_SOURCES = config/m68k-parse.y
+EXTRA_as_new_SOURCES = config/m68k-parse.y config/bfin-parse.y
 
 # If m68k-parse.y is in a different directory, then ylwrap will use an
 # absolute path when it invokes yacc, which will cause yacc to put the
@@ -600,6 +605,18 @@ m68k-parse.o: m68k-parse.c $(srcdir)/config/m68k-parse.h
 m68k-parse.h: ; @true
 $(srcdir)/config/m68k-parse.h: ; @true
 
+bfin-parse.c bfin-parse.tab.h: $(srcdir)/config/bfin-parse.y
+       $(SHELL) $(YLWRAP) $(srcdir)/config/bfin-parse.y y.tab.c bfin-parse.c y.tab.h bfin-parse.tab.h -- $(YACCCOMPILE) -d ;
+bfin-parse.o: bfin-parse.c bfin-parse.tab.h $(srcdir)/config/bfin-defs.h
+
+bfin-defs.h: ; @true
+$(srcdir)/config/bfin-defs.h: ; @true
+
+bfin-lex.c: $(srcdir)/config/bfin-lex.l
+       $(SHELL) $(YLWRAP) "$(LEX)" <$(srcdir)/config/bfin-lex.l lex.yy.c bfin-lex.c
+bfin-lex.o: bfin-lex.c bfin-parse.tab.h $(srcdir)/config/bfin-defs.h
+       $(COMPILE) -c $< $(NO_WERROR)
+
 # The instruction table specification lexical analyzer and parser.
 
 itbl-lex.c: $(srcdir)/itbl-lex.l
@@ -989,6 +1006,11 @@ DEPTC_avr_elf = $(INCDIR)/symcat.h $(srcdir)/config/obj-elf.h \
   $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(srcdir)/config/tc-avr.h \
   $(INCDIR)/safe-ctype.h subsegs.h $(INCDIR)/obstack.h \
   $(INCDIR)/opcode/avr.h
+DEPTC_bfin_elf = $(INCDIR)/symcat.h $(srcdir)/config/obj-elf.h \
+  $(BFDDIR)/elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
+  $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(srcdir)/config/tc-bfin.h \
+  $(INCDIR)/safe-ctype.h subsegs.h $(INCDIR)/obstack.h \
+  $(INCDIR)/opcode/bfin.h $(srcdir)/config/bfin-defs.h
 DEPTC_cris_aout = $(INCDIR)/symcat.h $(srcdir)/config/obj-aout.h \
   $(srcdir)/config/tc-cris.h $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h \
   $(INCDIR)/safe-ctype.h subsegs.h $(INCDIR)/obstack.h \
@@ -1525,6 +1547,11 @@ DEPOBJ_avr_elf = $(INCDIR)/symcat.h $(srcdir)/config/obj-elf.h \
   $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(srcdir)/config/tc-avr.h \
   $(INCDIR)/safe-ctype.h subsegs.h $(INCDIR)/obstack.h \
   struc-symbol.h dwarf2dbg.h $(INCDIR)/aout/aout64.h
+DEPOBJ_bfin_elf = $(INCDIR)/symcat.h $(srcdir)/config/obj-elf.h \
+  $(BFDDIR)/elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
+  $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(srcdir)/config/tc-bfin.h \
+  $(INCDIR)/safe-ctype.h subsegs.h $(INCDIR)/obstack.h \
+  struc-symbol.h dwarf2dbg.h $(INCDIR)/aout/aout64.h
 DEPOBJ_cris_aout = $(INCDIR)/symcat.h $(srcdir)/config/obj-aout.h \
   $(srcdir)/config/tc-cris.h $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h \
   $(INCDIR)/aout/aout64.h $(INCDIR)/obstack.h
@@ -1968,6 +1995,9 @@ DEP_avr_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-avr.h \
 DEP_avr_elf = $(srcdir)/config/obj-elf.h $(INCDIR)/symcat.h \
   $(BFDDIR)/elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
   $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(srcdir)/config/tc-avr.h
+DEP_bfin_elf = $(srcdir)/config/obj-elf.h $(INCDIR)/symcat.h \
+  $(BFDDIR)/elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
+  $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(srcdir)/config/tc-bfin.h
 DEP_cris_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-cris.h \
   $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h
 DEP_cris_elf = $(srcdir)/config/obj-elf.h $(INCDIR)/symcat.h \
index e61635b180ed1b39c619e7894c5df93b5c325169..94b34e8ec77dd81dfc57cacba807b13d2c635071 100644 (file)
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.9.5 from Makefile.am.
+# Makefile.in generated by automake 1.9.2 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@@ -42,14 +42,16 @@ host_triplet = @host@
 target_triplet = @target@
 noinst_PROGRAMS = as-new$(EXEEXT)
 EXTRA_PROGRAMS = itbl-test$(EXEEXT)
-DIST_COMMON = $(srcdir)/../config.guess $(srcdir)/../config.sub NEWS \
-       README ChangeLog $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+DIST_COMMON = $(srcdir)/../config.guess $(srcdir)/../config.sub \
+       INSTALL NEWS README AUTHORS ChangeLog THANKS \
+       $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
        $(top_srcdir)/configure $(am__configure_deps) \
        $(srcdir)/config.in $(srcdir)/../mkinstalldirs \
        $(srcdir)/gdbinit.in $(srcdir)/gdbinit.in \
-       $(top_srcdir)/po/Make-in m68k-parse.c itbl-parse.c itbl-lex.c \
-       $(srcdir)/../ylwrap $(srcdir)/../ltmain.sh \
-       $(srcdir)/../config.guess $(srcdir)/../config.sub
+       $(top_srcdir)/po/Make-in m68k-parse.c bfin-parse.c \
+       itbl-parse.c itbl-lex.c $(srcdir)/../ylwrap \
+       $(srcdir)/../ltmain.sh $(srcdir)/../config.guess \
+       $(srcdir)/../config.sub
 subdir = .
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
@@ -274,6 +276,7 @@ CPU_TYPES = \
        arc \
        arm \
        avr \
+       bfin \
        cris \
        crx \
        d10v \
@@ -454,6 +457,7 @@ TARGET_CPU_CFILES = \
        config/tc-arc.c \
        config/tc-arm.c \
        config/tc-avr.c \
+       config/tc-bfin.c \
        config/tc-cris.c \
        config/tc-crx.c \
        config/tc-d10v.c \
@@ -502,6 +506,7 @@ TARGET_CPU_HFILES = \
        config/tc-arc.h \
        config/tc-arm.h \
        config/tc-avr.h \
+       config/tc-bfin.h \
        config/tc-cris.h \
        config/tc-crx.h \
        config/tc-d10v.h \
@@ -656,7 +661,9 @@ POTFILES = $(MULTI_CFILES) $(TARGET_ENV_HFILES) $(OBJ_FORMAT_HFILES) \
 
 noinst_SCRIPTS = $(GDBINIT)
 EXTRA_SCRIPTS = .gdbinit
-EXTRA_DIST = m68k-parse.c itbl-parse.c itbl-parse.h itbl-lex.c
+EXTRA_DIST = m68k-parse.c itbl-parse.c itbl-parse.h itbl-lex.c \
+       bfin-parse.c bfin-lex.l bfin-defs.h
+
 DISTCLEANFILES = targ-cpu.h obj-format.h targ-env.h itbl-cpu.h cgen-desc.h
 
 # Now figure out from those variables how to compile and link.
@@ -698,7 +705,7 @@ RUNTEST = runtest
 RUNTESTFLAGS = 
 
 # The m68k operand parser.
-EXTRA_as_new_SOURCES = config/m68k-parse.y
+EXTRA_as_new_SOURCES = config/m68k-parse.y config/bfin-parse.y
 itbl_test_SOURCES = itbl-parse.y itbl-lex.l
 itbl_test_LDADD = itbl-tops.o itbl-test.o $(GASLIBS) @LEXLIB@
 
@@ -786,6 +793,12 @@ DEPTC_avr_elf = $(INCDIR)/symcat.h $(srcdir)/config/obj-elf.h \
   $(INCDIR)/safe-ctype.h subsegs.h $(INCDIR)/obstack.h \
   $(INCDIR)/opcode/avr.h
 
+DEPTC_bfin_elf = $(INCDIR)/symcat.h $(srcdir)/config/obj-elf.h \
+  $(BFDDIR)/elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
+  $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(srcdir)/config/tc-bfin.h \
+  $(INCDIR)/safe-ctype.h subsegs.h $(INCDIR)/obstack.h \
+  $(INCDIR)/opcode/bfin.h $(srcdir)/config/bfin-defs.h
+
 DEPTC_cris_aout = $(INCDIR)/symcat.h $(srcdir)/config/obj-aout.h \
   $(srcdir)/config/tc-cris.h $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h \
   $(INCDIR)/safe-ctype.h subsegs.h $(INCDIR)/obstack.h \
@@ -1426,6 +1439,12 @@ DEPOBJ_avr_elf = $(INCDIR)/symcat.h $(srcdir)/config/obj-elf.h \
   $(INCDIR)/safe-ctype.h subsegs.h $(INCDIR)/obstack.h \
   struc-symbol.h dwarf2dbg.h $(INCDIR)/aout/aout64.h
 
+DEPOBJ_bfin_elf = $(INCDIR)/symcat.h $(srcdir)/config/obj-elf.h \
+  $(BFDDIR)/elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
+  $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(srcdir)/config/tc-bfin.h \
+  $(INCDIR)/safe-ctype.h subsegs.h $(INCDIR)/obstack.h \
+  struc-symbol.h dwarf2dbg.h $(INCDIR)/aout/aout64.h
+
 DEPOBJ_cris_aout = $(INCDIR)/symcat.h $(srcdir)/config/obj-aout.h \
   $(srcdir)/config/tc-cris.h $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h \
   $(INCDIR)/aout/aout64.h $(INCDIR)/obstack.h
@@ -1972,6 +1991,10 @@ DEP_avr_elf = $(srcdir)/config/obj-elf.h $(INCDIR)/symcat.h \
   $(BFDDIR)/elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
   $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(srcdir)/config/tc-avr.h
 
+DEP_bfin_elf = $(srcdir)/config/obj-elf.h $(INCDIR)/symcat.h \
+  $(BFDDIR)/elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
+  $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(srcdir)/config/tc-bfin.h
+
 DEP_cris_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-cris.h \
   $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h
 
@@ -2438,6 +2461,9 @@ distclean-compile:
 .y.c:
        $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h $*.h y.output $*.output -- $(YACCCOMPILE)
 
+bfin-parse.c: config/bfin-parse.y
+       $(SHELL) $(YLWRAP) `test -f 'config/bfin-parse.y' || echo '$(srcdir)/'`config/bfin-parse.y y.tab.c bfin-parse.c y.tab.h bfin-parse.h y.output bfin-parse.output -- $(YACC) $(YFLAGS) $(AM_YFLAGS)
+
 mostlyclean-libtool:
        -rm -f *.lo
 
@@ -2455,13 +2481,7 @@ uninstall-info-am:
 #     (which will cause the Makefiles to be regenerated when you run `make');
 # (2) otherwise, pass the desired values on the `make' command line.
 $(RECURSIVE_TARGETS):
-       @failcom='exit 1'; \
-       for f in x $$MAKEFLAGS; do \
-         case $$f in \
-           *=* | --[!k]*);; \
-           *k*) failcom='fail=yes';; \
-         esac; \
-       done; \
+       @set fnord $$MAKEFLAGS; amf=$$2; \
        dot_seen=no; \
        target=`echo $@ | sed s/-recursive//`; \
        list='$(SUBDIRS)'; for subdir in $$list; do \
@@ -2473,7 +2493,7 @@ $(RECURSIVE_TARGETS):
            local_target="$$target"; \
          fi; \
          (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
-         || eval $$failcom; \
+          || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
        done; \
        if test "$$dot_seen" = "no"; then \
          $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
@@ -2481,13 +2501,7 @@ $(RECURSIVE_TARGETS):
 
 mostlyclean-recursive clean-recursive distclean-recursive \
 maintainer-clean-recursive:
-       @failcom='exit 1'; \
-       for f in x $$MAKEFLAGS; do \
-         case $$f in \
-           *=* | --[!k]*);; \
-           *k*) failcom='fail=yes';; \
-         esac; \
-       done; \
+       @set fnord $$MAKEFLAGS; amf=$$2; \
        dot_seen=no; \
        case "$@" in \
          distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
@@ -2508,7 +2522,7 @@ maintainer-clean-recursive:
            local_target="$$target"; \
          fi; \
          (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
-         || eval $$failcom; \
+          || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
        done && test -z "$$fail"
 tags-recursive:
        list='$(SUBDIRS)'; for subdir in $$list; do \
@@ -2637,6 +2651,7 @@ distclean-generic:
 maintainer-clean-generic:
        @echo "This command is intended for maintainers to use"
        @echo "it deletes files that may require special tools to rebuild."
+       -rm -f bfin-parse.c
        -rm -f itbl-lex.c
        -rm -f itbl-parse.c
        -rm -f m68k-parse.c
@@ -2713,6 +2728,7 @@ uninstall-info: uninstall-info-recursive
 po/POTFILES.in: @MAINT@ Makefile
        for f in $(POTFILES); do echo $$f; done | LC_COLLATE= sort > tmp \
          && mv tmp $(srcdir)/po/POTFILES.in
+
 diststuff: $(EXTRA_DIST) info
 all: info
 
@@ -2827,6 +2843,18 @@ m68k-parse.o: m68k-parse.c $(srcdir)/config/m68k-parse.h
 m68k-parse.h: ; @true
 $(srcdir)/config/m68k-parse.h: ; @true
 
+bfin-parse.c bfin-parse.tab.h: $(srcdir)/config/bfin-parse.y
+       $(SHELL) $(YLWRAP) $(srcdir)/config/bfin-parse.y y.tab.c bfin-parse.c y.tab.h bfin-parse.tab.h -- $(YACCCOMPILE) -d ;
+bfin-parse.o: bfin-parse.c bfin-parse.tab.h $(srcdir)/config/bfin-defs.h
+
+bfin-defs.h: ; @true
+$(srcdir)/config/bfin-defs.h: ; @true
+
+bfin-lex.c: $(srcdir)/config/bfin-lex.l
+       $(SHELL) $(YLWRAP) "$(LEX)" <$(srcdir)/config/bfin-lex.l lex.yy.c bfin-lex.c
+bfin-lex.o: bfin-lex.c bfin-parse.tab.h $(srcdir)/config/bfin-defs.h
+       $(COMPILE) -c $< $(NO_WERROR)
+
 # The instruction table specification lexical analyzer and parser.
 
 itbl-lex.c: $(srcdir)/itbl-lex.l
index ca849970a1b18a5c575b286bfbac55e55c54face..389bef76886b9df06cdf92f69b564d024b41d32a 100644 (file)
@@ -1,4 +1,4 @@
-# generated automatically by aclocal 1.9.5 -*- Autoconf -*-
+# generated automatically by aclocal 1.9.2 -*- Autoconf -*-
 
 # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 # 2005  Free Software Foundation, Inc.
 # even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 # PARTICULAR PURPOSE.
 
-# Copyright (C) 2002, 2003, 2005  Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
+#                                                        -*- Autoconf -*-
+# Copyright (C) 2002, 2003  Free Software Foundation, Inc.
+# Generated from amversion.in; do not edit by hand.
+
+# This program 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.
+
+# This program 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 this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 
 # AM_AUTOMAKE_VERSION(VERSION)
 # ----------------------------
@@ -28,15 +40,26 @@ AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version="1.9"])
 # Call AM_AUTOMAKE_VERSION so it can be traced.
 # This function is AC_REQUIREd by AC_INIT_AUTOMAKE.
 AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
-        [AM_AUTOMAKE_VERSION([1.9.5])])
+        [AM_AUTOMAKE_VERSION([1.9.2])])
 
-# AM_AUX_DIR_EXPAND                                         -*- Autoconf -*-
+# AM_AUX_DIR_EXPAND
 
-# Copyright (C) 2001, 2003, 2005  Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
+# Copyright (C) 2001, 2003 Free Software Foundation, Inc.
+
+# This program 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.
+
+# This program 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 this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
 
 # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
 # $ac_aux_dir to `$srcdir/foo'.  In other projects, it is set to
@@ -83,16 +106,26 @@ AC_PREREQ([2.50])dnl
 am_aux_dir=`cd $ac_aux_dir && pwd`
 ])
 
-# AM_CONDITIONAL                                            -*- Autoconf -*-
+# AM_CONDITIONAL                                              -*- Autoconf -*-
 
-# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005
-# Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
+# Copyright (C) 1997, 2000, 2001, 2003, 2004 Free Software Foundation, Inc.
 
-# serial 7
+# This program 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.
+
+# This program 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 this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+# serial 6
 
 # AM_CONDITIONAL(NAME, SHELL-CONDITION)
 # -------------------------------------
@@ -116,15 +149,26 @@ AC_CONFIG_COMMANDS_PRE(
 Usually this means the macro was only invoked conditionally.]])
 fi])])
 
+# serial 7                                             -*- Autoconf -*-
 
-# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
 # Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
 
-# serial 8
+# This program 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.
+
+# This program 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 this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
 
 # There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
 # written in clear, in which case automake, when reading aclocal.m4,
@@ -133,6 +177,7 @@ fi])])
 # CC etc. in the Makefile, will ask for an AC_PROG_CC use...
 
 
+
 # _AM_DEPENDENCIES(NAME)
 # ----------------------
 # See how the compiler implements dependency checking.
@@ -272,16 +317,27 @@ AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
 AC_SUBST([AMDEPBACKSLASH])
 ])
 
-# Generate code to set up dependency tracking.              -*- Autoconf -*-
+# Generate code to set up dependency tracking.   -*- Autoconf -*-
 
-# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
-# Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
+#   Free Software Foundation, Inc.
 
-#serial 3
+# This program 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.
+
+# This program 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 this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+#serial 2
 
 # _AM_OUTPUT_DEPENDENCY_COMMANDS
 # ------------------------------
@@ -340,31 +396,54 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
      [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
 ])
 
-# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005
-# Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
+# Like AC_CONFIG_HEADER, but automatically create stamp file. -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 2000, 2001, 2003 Free Software Foundation, Inc.
+
+# This program 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.
+
+# This program 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 this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
 
-# serial 8
+# serial 7
 
 # AM_CONFIG_HEADER is obsolete.  It has been replaced by AC_CONFIG_HEADERS.
 AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)])
 
-# Do all the work for Automake.                             -*- Autoconf -*-
+# Do all the work for Automake.                            -*- Autoconf -*-
 
-# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+# This macro actually does too much some checks are only needed if
+# your package does certain things.  But this isn't really a big deal.
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
 # Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
 
-# serial 12
+# This program 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.
 
-# This macro actually does too much.  Some checks are only needed if
-# your package does certain things.  But this isn't really a big deal.
+# This program 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 this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+# serial 11
 
 # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
 # AM_INIT_AUTOMAKE([OPTIONS])
@@ -466,27 +545,51 @@ for _am_header in $config_headers :; do
 done
 echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count])
 
-# Copyright (C) 2001, 2003, 2005  Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
 # AM_PROG_INSTALL_SH
 # ------------------
 # Define $install_sh.
+
+# Copyright (C) 2001, 2003 Free Software Foundation, Inc.
+
+# This program 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.
+
+# This program 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 this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
 AC_DEFUN([AM_PROG_INSTALL_SH],
 [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
 install_sh=${install_sh-"$am_aux_dir/install-sh"}
 AC_SUBST(install_sh)])
 
-# Copyright (C) 2003, 2005  Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
+#                                                          -*- Autoconf -*-
+# Copyright (C) 2003  Free Software Foundation, Inc.
 
-# serial 2
+# This program 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.
+
+# This program 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 this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+# serial 1
 
 # Check whether the underlying file-system supports filenames
 # with a leading dot.  For instance MS-DOS doesn't.
@@ -501,14 +604,26 @@ fi
 rmdir .tst 2>/dev/null
 AC_SUBST([am__leading_dot])])
 
-# Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005
+
+# Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
 # Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
 
-# serial 5
+# This program 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.
+
+# This program 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 this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+# serial 4
 
 # AM_PROG_LEX
 # -----------
@@ -522,17 +637,28 @@ if test "$LEX" = :; then
   LEX=${am_missing_run}flex
 fi])
 
-# Add --enable-maintainer-mode option to configure.         -*- Autoconf -*-
+# Add --enable-maintainer-mode option to configure.
 # From Jim Meyering
 
-# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005
+# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004
 # Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
 
-# serial 4
+# This program 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.
+
+# This program 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 this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+# serial 3
 
 AC_DEFUN([AM_MAINTAINER_MODE],
 [AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
@@ -551,15 +677,26 @@ AC_DEFUN([AM_MAINTAINER_MODE],
 
 AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE])
 
-# Check to see how 'make' treats includes.                 -*- Autoconf -*-
+# Check to see how 'make' treats includes.     -*- Autoconf -*-
 
-# Copyright (C) 2001, 2002, 2003, 2005  Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
+# Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
 
-# serial 3
+# This program 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.
+
+# This program 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 this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+# serial 2
 
 # AM_MAKE_INCLUDE()
 # -----------------
@@ -603,16 +740,27 @@ AC_MSG_RESULT([$_am_result])
 rm -f confinc confmf
 ])
 
-# Fake the existence of programs that GNU maintainers use.  -*- Autoconf -*-
+#  -*- Autoconf -*-
 
-# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2005
-# Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
 
-# serial 4
+# Copyright (C) 1997, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
+
+# This program 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.
+
+# This program 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 this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+# serial 3
 
 # AM_MISSING_PROG(NAME, PROGRAM)
 # ------------------------------
@@ -638,16 +786,27 @@ else
 fi
 ])
 
-# Copyright (C) 2003, 2004, 2005  Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
 # AM_PROG_MKDIR_P
 # ---------------
 # Check whether `mkdir -p' is supported, fallback to mkinstalldirs otherwise.
-#
+
+# Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+
+# This program 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.
+
+# This program 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 this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
 # Automake 1.8 used `mkdir -m 0755 -p --' to ensure that directories
 # created by `make install' are always world readable, even if the
 # installer happens to have an overly restrictive umask (e.g. 077).
@@ -701,15 +860,26 @@ else
 fi
 AC_SUBST([mkdir_p])])
 
-# Helper functions for option handling.                     -*- Autoconf -*-
+# Helper functions for option handling.                    -*- Autoconf -*-
 
-# Copyright (C) 2001, 2002, 2003, 2005  Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
+# Copyright (C) 2001, 2002, 2003  Free Software Foundation, Inc.
 
-# serial 3
+# This program 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.
+
+# This program 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 this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+# serial 2
 
 # _AM_MANGLE_OPTION(NAME)
 # -----------------------
@@ -734,16 +904,28 @@ AC_DEFUN([_AM_SET_OPTIONS],
 AC_DEFUN([_AM_IF_OPTION],
 [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
 
-# Check to make sure that the build environment is sane.    -*- Autoconf -*-
-
-# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005
-# Free Software Foundation, Inc.
 #
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
+# Check to make sure that the build environment is sane.
+#
 
-# serial 4
+# Copyright (C) 1996, 1997, 2000, 2001, 2003 Free Software Foundation, Inc.
+
+# This program 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.
+
+# This program 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 this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+# serial 3
 
 # AM_SANITY_CHECK
 # ---------------
@@ -786,14 +968,25 @@ Check your system clock])
 fi
 AC_MSG_RESULT(yes)])
 
-# Copyright (C) 2001, 2003, 2005  Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
 # AM_PROG_INSTALL_STRIP
-# ---------------------
+
+# Copyright (C) 2001, 2003 Free Software Foundation, Inc.
+
+# This program 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.
+
+# This program 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 this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
 # One issue with vendor `install' (even GNU) is that you can't
 # specify the program used to strip binaries.  This is especially
 # annoying in cross-compiling environments, where the build's strip
@@ -816,13 +1009,25 @@ AC_SUBST([INSTALL_STRIP_PROGRAM])])
 
 # Check how to create a tarball.                            -*- Autoconf -*-
 
-# Copyright (C) 2004, 2005  Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
+# Copyright (C) 2004  Free Software Foundation, Inc.
+
+# This program 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.
+
+# This program 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 this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+# serial 1
 
-# serial 2
 
 # _AM_PROG_TAR(FORMAT)
 # --------------------
diff --git a/gas/config/bfin-aux.h b/gas/config/bfin-aux.h
new file mode 100755 (executable)
index 0000000..be6b63a
--- /dev/null
@@ -0,0 +1,151 @@
+/* bfin-aux.h ADI Blackfin Header file for gas\r
+   Copyright 2005\r
+   Free Software Foundation, Inc.\r
+\r
+   This file is part of GAS, the GNU Assembler.\r
+\r
+   GAS is free software; you can redistribute it and/or modify\r
+   it under the terms of the GNU General Public License as published by\r
+   the Free Software Foundation; either version 2, or (at your option)\r
+   any later version.\r
+\r
+   GAS is distributed in the hope that it will be useful,\r
+   but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+   GNU General Public License for more details.\r
+\r
+   You should have received a copy of the GNU General Public License\r
+   along with GAS; see the file COPYING.  If not, write to the Free\r
+   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA\r
+   02110-1301, USA.  */\r
+\r
+#include "bfin-defs.h"\r
+\r
+#define REG_T Register *\r
+\r
+INSTR_T\r
+bfin_gen_dsp32mac (int op1, int mm, int mmod, int w1, int p,\r
+              int h01, int h11, int h00, int h10,\r
+             int op0, REG_T dst, REG_T src0, REG_T src1, int w0);\r
+\r
+INSTR_T\r
+bfin_gen_dsp32mult (int op1, int mm, int mmod, int w1, int p,\r
+               int h01, int h11, int h00, int h10,\r
+              int op0, REG_T dst, REG_T src0, REG_T src1, int w0);\r
+\r
+INSTR_T\r
+bfin_gen_dsp32alu (int HL, int aopcde, int aop, int s, int x,\r
+              REG_T dst0, REG_T dst1, REG_T src0, REG_T src1);\r
+\r
+INSTR_T\r
+bfin_gen_dsp32shift (int sopcde, REG_T dst0, REG_T src0, REG_T src1,\r
+                int sop, int hls);\r
+\r
+INSTR_T\r
+bfin_gen_dsp32shiftimm (int sopcde, REG_T dst0, int immag, REG_T src1,\r
+                   int sop, int hls);\r
+\r
+INSTR_T\r
+bfin_gen_ldimmhalf (REG_T reg, int h, int s, int z, Expr_Node *hword,\r
+               int reloc);\r
+\r
+INSTR_T\r
+bfin_gen_ldstidxi (REG_T ptr, REG_T reg, int w, int sz, int z,\r
+              Expr_Node *offset);\r
+\r
+INSTR_T\r
+bfin_gen_ldst (REG_T ptr, REG_T reg, int aop, int sz, int z, int w);\r
+\r
+INSTR_T\r
+bfin_gen_ldstii (REG_T ptr, REG_T reg, Expr_Node *offset, int w, int op);\r
+\r
+INSTR_T\r
+bfin_gen_ldstiifp (REG_T reg, Expr_Node *offset, int w);\r
+\r
+INSTR_T\r
+bfin_gen_ldstpmod (REG_T ptr, REG_T reg, int aop, int w, REG_T idx);\r
+\r
+INSTR_T\r
+bfin_gen_dspldst (REG_T i, REG_T reg, int aop, int w, int m);\r
+\r
+INSTR_T\r
+bfin_gen_alu2op (REG_T dst, REG_T src, int opc);\r
+\r
+INSTR_T\r
+bfin_gen_compi2opd (REG_T dst, int src, int op);\r
+\r
+INSTR_T\r
+bfin_gen_compi2opp (REG_T dst, int src, int op);\r
+\r
+INSTR_T\r
+bfin_gen_dagmodik (REG_T i, int op);\r
+\r
+INSTR_T\r
+bfin_gen_dagmodim (REG_T i, REG_T m, int op, int br);\r
+\r
+INSTR_T\r
+bfin_gen_ptr2op (REG_T dst, REG_T src, int opc);\r
+\r
+INSTR_T\r
+bfin_gen_logi2op (int dst, int src, int opc);\r
+\r
+INSTR_T\r
+bfin_gen_comp3op (REG_T src0, REG_T src1, REG_T dst, int opc);\r
+\r
+INSTR_T\r
+bfin_gen_ccmv (REG_T src, REG_T dst, int t);\r
+\r
+INSTR_T\r
+bfin_gen_ccflag (REG_T x, int y, int opc, int i, int g);\r
+\r
+INSTR_T\r
+bfin_gen_cc2stat (int cbit, int op, int d);\r
+\r
+INSTR_T\r
+bfin_gen_regmv (REG_T src, REG_T dst);\r
+\r
+INSTR_T\r
+bfin_gen_cc2dreg (int op, REG_T reg);\r
+\r
+INSTR_T\r
+bfin_gen_brcc (int t, int b, Expr_Node *offset);\r
+\r
+INSTR_T\r
+bfin_gen_ujump (Expr_Node *offset);\r
+\r
+INSTR_T\r
+bfin_gen_cactrl (REG_T reg, int a, int op);\r
+\r
+INSTR_T\r
+bfin_gen_progctrl (int prgfunc, int poprnd);\r
+\r
+INSTR_T\r
+bfin_gen_loopsetup (Expr_Node *soffset, REG_T c, int rop,\r
+               Expr_Node *eoffset, REG_T reg);\r
+\r
+INSTR_T\r
+bfin_gen_loop (Expr_Node *expr, REG_T reg, int rop, REG_T preg);\r
+\r
+INSTR_T\r
+bfin_gen_pushpopmultiple (int dr, int pr, int d, int p, int w);\r
+\r
+INSTR_T\r
+bfin_gen_pushpopreg (REG_T reg, int w);\r
+\r
+INSTR_T\r
+bfin_gen_calla (Expr_Node *addr, int s);\r
+\r
+INSTR_T\r
+bfin_gen_linkage (int r, int framesize);\r
+\r
+INSTR_T\r
+bfin_gen_pseudodbg (int fn, int reg, int grp);\r
+\r
+INSTR_T\r
+bfin_gen_pseudodbg_assert (int dbgop, REG_T regtest, int expected);\r
+\r
+bfd_boolean\r
+bfin_resource_conflict (INSTR_T dsp32, INSTR_T dsp16_grp1, INSTR_T dsp16_grp2);\r
+\r
+INSTR_T\r
+bfin_gen_multi_instr (INSTR_T dsp32, INSTR_T dsp16_grp1, INSTR_T dsp16_grp2);\r
diff --git a/gas/config/bfin-defs.h b/gas/config/bfin-defs.h
new file mode 100644 (file)
index 0000000..221e8c4
--- /dev/null
@@ -0,0 +1,383 @@
+/* bfin-defs.h ADI Blackfin gas header file
+   Copyright 2005
+   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, 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+#ifndef BFIN_PARSE_H
+#define BFIN_PARSE_H  
+
+#include <bfd.h>
+#include "as.h"
+
+#define PCREL  1
+#define CODE_FRAG_SIZE 4096  /* 1 page.  */  
+
+
+/* Definition for all status bits.  */
+typedef enum
+{
+  c_0,
+  c_1,
+  c_4,
+  c_2,
+  c_uimm2,
+  c_uimm3,
+  c_imm3,
+  c_pcrel4, 
+  c_imm4,
+  c_uimm4s4,
+  c_uimm4,
+  c_uimm4s2,
+  c_negimm5s4,
+  c_imm5,
+  c_uimm5,
+  c_imm6,  
+  c_imm7,
+  c_imm8,
+  c_uimm8,
+  c_pcrel8,
+  c_uimm8s4,
+  c_pcrel8s4,
+  c_lppcrel10,
+  c_pcrel10, 
+  c_pcrel12,
+  c_imm16s4,
+  c_luimm16,
+  c_imm16,
+  c_huimm16,
+  c_rimm16,
+  c_imm16s2,
+  c_uimm16s4, 
+  c_uimm16,
+  c_pcrel24 
+} const_forms_t;
+
+
+/* High-Nibble: group code, low nibble: register code.  */
+
+
+#define T_REG_R       0x00
+#define T_REG_P       0x10
+#define T_REG_I       0x20
+#define T_REG_B       0x30
+#define T_REG_L       0x34
+#define T_REG_M       0x24
+#define T_REG_A       0x40
+
+/* All registers above this value don't
+   belong to a usuable register group.  */
+#define T_NOGROUP     0xa0
+
+/* Flags.  */
+#define F_REG_ALL    0x1000
+#define F_REG_HIGH   0x2000  /* Half register: high half.  */
+
+enum machine_registers
+{
+  REG_R0    = T_REG_R, REG_R1, REG_R2, REG_R3, REG_R4, REG_R5, REG_R6, REG_R7, 
+  REG_P0    = T_REG_P, REG_P1, REG_P2, REG_P3, REG_P4, REG_P5, REG_SP, REG_FP,
+  REG_I0    = T_REG_I, REG_I1, REG_I2, REG_I3,
+  REG_M0    = T_REG_M, REG_M1, REG_M2, REG_M3, 
+  REG_B0    = T_REG_B, REG_B1, REG_B2, REG_B3,
+  REG_L0    = T_REG_L, REG_L1, REG_L2, REG_L3, 
+  REG_A0x   = T_REG_A, REG_A0w, REG_A1x, REG_A1w,
+  REG_ASTAT = 0x46,
+  REG_RETS  = 0x47,
+  REG_LC0   = 0x60, REG_LT0, REG_LB0,  REG_LC1, REG_LT1, REG_LB1,
+              REG_CYCLES, REG_CYCLES2,
+  REG_USP   = 0x70, REG_SEQSTAT, REG_SYSCFG,
+             REG_RETI, REG_RETX, REG_RETN, REG_RETE, REG_EMUDAT, 
+
+/* These don't have groups.  */
+  REG_sftreset = T_NOGROUP, REG_omode, REG_excause, REG_emucause,
+                REG_idle_req, REG_hwerrcause,
+  REG_A0       = 0xc0, REG_A1, REG_CC,
+/* Pseudo registers, used only for distinction from symbols.  */
+                REG_RL0, REG_RL1, REG_RL2, REG_RL3,
+                REG_RL4, REG_RL5, REG_RL6, REG_RL7, 
+                REG_RH0, REG_RH1, REG_RH2, REG_RH3,
+                REG_RH4, REG_RH5, REG_RH6, REG_RH7, 
+                REG_LASTREG
+};
+
+/* Status register flags.  */
+
+enum statusflags
+{
+  S_AZ = 0,
+  S_AN,
+  S_AQ = 6,
+  S_AC0 = 12,
+  S_AC1,
+  S_AV0 = 16,
+  S_AV0S,
+  S_AV1,
+  S_AV1S,
+  S_V = 24,
+  S_VS = 25
+}; 
+
+
+enum reg_class
+{
+  rc_dregs_lo,
+  rc_dregs_hi,
+  rc_dregs,
+  rc_dregs_pair,
+  rc_pregs,
+  rc_spfp,
+  rc_dregs_hilo,
+  rc_accum_ext,
+  rc_accum_word,
+  rc_accum,
+  rc_iregs,
+  rc_mregs,
+  rc_bregs,
+  rc_lregs,
+  rc_dpregs,
+  rc_gregs,
+  rc_regs,
+  rc_statbits,
+  rc_ignore_bits,
+  rc_ccstat,
+  rc_counters,
+  rc_dregs2_sysregs1,
+  rc_open,
+  rc_sysregs2,
+  rc_sysregs3,
+  rc_allregs,
+  LIM_REG_CLASSES
+};
+
+/* mmod field.  */
+#define M_S2RND 1
+#define M_T     2
+#define M_W32   3
+#define M_FU    4
+#define M_TFU   6
+#define M_IS    8
+#define M_ISS2  9
+#define M_IH    11
+#define M_IU    12
+
+/* Register type checking macros.  */
+
+#define CODE_MASK  0x07
+#define CLASS_MASK 0xf0
+
+#define REG_SAME(a, b)   ((a).regno == (b).regno)
+#define REG_EQUAL(a, b)  (((a).regno & CODE_MASK) == ((b).regno & CODE_MASK))
+#define REG_CLASS(a)     ((a.regno) & 0xf0)
+#define IS_A1(a)         ((a).regno == REG_A1)
+#define IS_H(a)          ((a).regno & F_REG_HIGH ? 1: 0)
+#define IS_EVEN(r)       (r.regno % 2 == 0)
+#define IS_HCOMPL(a, b)  (REG_EQUAL(a, b) && \
+                         ((a).regno & F_REG_HIGH) != ((b).regno & F_REG_HIGH))
+
+/* register type checking.  */
+#define _TYPECHECK(r, x) (((r).regno & CLASS_MASK) == T_REG_##x)
+
+#define IS_DREG(r)       _TYPECHECK(r, R)
+#define IS_DREG_H(r)     (_TYPECHECK(r, R) && IS_H(r))
+#define IS_DREG_L(r)     (_TYPECHECK(r, R) && !IS_H(r))
+#define IS_PREG(r)       _TYPECHECK(r, P)
+#define IS_IREG(r)       (((r).regno & 0xf4) == T_REG_I)
+#define IS_MREG(r)       (((r).regno & 0xf4) == T_REG_M)
+#define IS_CREG(r)       ((r).regno == REG_LC0 || (r).regno == REG_LC1)
+#define IS_ALLREG(r)     ((r).regno < T_NOGROUP)
+
+/* Expression value macros.  */
+
+typedef enum
+{ 
+  ones_compl,
+  twos_compl,
+  mult,
+  divide,
+  mod,
+  add,
+  sub,
+  lsh,
+  rsh,
+  logand,
+  logior,
+  logxor
+} expr_opcodes_t;
+
+struct expressionS;
+
+#define SYMBOL_T       symbolS*
+struct expression_cell
+{
+  int value;
+  SYMBOL_T symbol;
+};
+
+/* User Type Definitions.  */
+struct bfin_insn
+{
+  unsigned long value;
+  struct bfin_insn *next;
+  struct expression_cell *exp;
+  int pcrel;
+  int reloc;
+};
+    
+#define INSTR_T struct bfin_insn*
+#define EXPR_T  struct expression_cell* 
+
+typedef struct expr_node_struct Expr_Node;
+extern INSTR_T gencode (unsigned long x);
+extern INSTR_T conscode (INSTR_T head, INSTR_T tail);   
+extern INSTR_T conctcode (INSTR_T head, INSTR_T tail);
+extern INSTR_T note_reloc
+       (INSTR_T code, Expr_Node *, int reloc,int pcrel);
+extern INSTR_T note_reloc1
+       (INSTR_T code, const char * sym, int reloc, int pcrel);
+extern INSTR_T note_reloc2
+       (INSTR_T code, const char *symbol, int reloc, int value, int pcrel);
+/* Types of expressions.  */
+typedef enum 
+{
+  Expr_Node_Binop,             /* Binary operator.  */
+  Expr_Node_Unop,              /* Unary operator.  */
+  Expr_Node_Reloc,             /* Symbol to be relocated.  */
+  Expr_Node_Constant           /* Constant.  */
+} Expr_Node_Type;
+
+/* Types of operators.  */
+typedef enum 
+{
+  Expr_Op_Type_Add,
+  Expr_Op_Type_Sub,
+  Expr_Op_Type_Mult,
+  Expr_Op_Type_Div,
+  Expr_Op_Type_Mod,
+  Expr_Op_Type_Lshift,
+  Expr_Op_Type_Rshift,
+  Expr_Op_Type_BAND,           /* Bitwise AND.  */
+  Expr_Op_Type_BOR,            /* Bitwise OR.  */
+  Expr_Op_Type_BXOR,           /* Bitwise exclusive OR.  */
+  Expr_Op_Type_LAND,           /* Logical AND.  */
+  Expr_Op_Type_LOR,            /* Logical OR.  */
+  Expr_Op_Type_NEG,
+  Expr_Op_Type_COMP            /* Complement.  */
+} Expr_Op_Type;
+
+/* The value that can be stored ... depends on type.  */
+typedef union
+{
+  const char *s_value;         /* if relocation symbol, the text.  */
+  int i_value;                 /* if constant, the value.  */
+  Expr_Op_Type op_value;       /* if operator, the value.  */
+} Expr_Node_Value;
+
+/* The expression node.  */
+struct expr_node_struct
+{
+  Expr_Node_Type       type;
+  Expr_Node_Value      value;
+  Expr_Node            *Left_Child;
+  Expr_Node            *Right_Child;
+};
+
+
+/* Operations on the expression node.  */
+Expr_Node *Expr_Node_Create (Expr_Node_Type type, 
+                        Expr_Node_Value value, 
+                        Expr_Node *Left_Child, 
+                        Expr_Node *Right_Child);
+
+/* Generate the reloc structure as a series of instructions.  */
+INSTR_T Expr_Node_Gen_Reloc (Expr_Node *head, int parent_reloc);
+#define MKREF(x)       mkexpr (0,x)
+#define ALLOCATE(x)    malloc (x)
+#define NULL_CODE ((INSTR_T) 0)
+
+#ifndef EXPR_VALUE
+#define EXPR_VALUE(x)  (((x)->type == Expr_Node_Constant) ? ((x)->value.i_value) : 0)
+#endif
+#ifndef EXPR_SYMBOL
+#define EXPR_SYMBOL(x) ((x)->symbol)
+#endif
+
+
+typedef long reg_t;
+
+
+typedef struct _register
+{
+  reg_t regno;       /* Register ID as defined in machine_registers.  */
+  int   flags;
+} Register;
+
+
+typedef struct _macfunc
+{
+  char n;
+  char op;
+  char w;
+  char P;
+  Register dst;
+  Register s0;
+  Register s1;
+} Macfunc;
+
+typedef struct _opt_mode
+{
+  int MM;
+  int mod;
+} Opt_mode;
+
+typedef enum
+{
+  SEMANTIC_ERROR,
+  NO_INSN_GENERATED,
+  INSN_GENERATED
+} parse_state;
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int debug_codeselection;
+
+void error (char *format, ...);
+void warn (char *format, ...);
+int  semantic_error (char *syntax);
+void semantic_error_2 (char *syntax);
+
+EXPR_T mkexpr (int, SYMBOL_T);
+
+extern void bfin_equals (Expr_Node *sym);
+/* Defined in bfin-lex.l.  */
+void set_start_state (void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* BFIN_PARSE_H */
+
diff --git a/gas/config/bfin-lex.l b/gas/config/bfin-lex.l
new file mode 100644 (file)
index 0000000..df65035
--- /dev/null
@@ -0,0 +1,554 @@
+/* bfin-lex.l  ADI Blackfin lexer
+   Copyright 2005
+   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, 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+%{
+
+#include <stdlib.h>
+#include <string.h>
+#include "bfin-defs.h"
+#include "bfin-parse.tab.h"
+#include "as.h"
+
+static long parse_int (char **end);
+static int parse_halfreg (Register *r, int cl, char *hr);
+static int parse_reg (Register *r, int type, char *rt);
+int yylex (void);
+
+#define _REG yylval.reg
+
+
+%}
+
+/* Define Start States ... Actually we will use exclusion.
+   If no start state is specified it should match any state
+   and <INITIAL> would match some keyword rules only with
+   initial.  */
+%s KEYWORD
+
+%%
+[sS][fF][tT][rR][eE][sS][eE][tT]        _REG.regno = REG_sftreset;  return REG;
+[oO][mM][oO][dD][eE]                    _REG.regno = REG_omode;     return REG;
+[iI][dD][lL][eE]_[rR][eE][qQ]           _REG.regno = REG_idle_req;  return REG;
+[hH][wW][eE][rR][rR][cC][aA][uU][sS][eE] _REG.regno = REG_hwerrcause; return REG;
+[eE][xX][cC][aA][uU][sS][eE]            _REG.regno = REG_excause;   return REG;
+[eE][mM][uU][cC][aA][uU][sS][eE]       _REG.regno = REG_emucause;  return REG;
+[zZ]                                    return Z;
+[xX]                                    return X;
+[wW]32                                  yylval.value = M_W32; return MMOD;
+[wW]                                    return W;
+[vV][iI][tT]_[mM][aA][xX]               return VIT_MAX;
+[vV]               return V; /* Special: V is a statflag and a modifier.  */
+[uU][sS][pP]       _REG.regno = REG_USP; return REG;
+[tT][lL]                                return TL;
+[tT][hH]                                return TH;
+[tT][fF][uU]                            yylval.value = M_TFU; return MMOD;
+[tT][eE][sS][tT][sS][eE][tT]            return TESTSET;
+[tT]                                    yylval.value = M_T; return MMOD;
+[sS]                                                        return S;
+[sS][yY][sS][cC][fF][gG]       _REG.regno = REG_SYSCFG; return REG;
+[sS][tT][iI]                            return STI;
+[sS][sS][yY][nN][cC]                    return SSYNC;
+[sS][pP]"."[lL]                         _REG.regno = REG_SP; return HALF_REG;
+[sS][pP]"."[hH]                         _REG.regno = REG_SP | F_REG_HIGH; return HALF_REG;
+[sS][pP]                                _REG.regno = REG_SP; return REG;
+[sS][iI][gG][nN][bB][iI][tT][sS]        return SIGNBITS;
+[sS][iI][gG][nN]                        return SIGN;
+[sS][eE][qQ][sS][tT][aA][tT]     _REG.regno = REG_SEQSTAT; return REG;
+[sS][eE][aA][rR][cC][hH]                return SEARCH;
+[sS][hH][iI][fF][tT]                    return SHIFT;
+[sS][cC][oO]                            return SCO;
+
+[sS][aA][aA]                            return SAA;
+[sS]2[rR][nN][dD]                       yylval.value = M_S2RND; return MMOD;
+[rR][tT][xX]                            return RTX;
+[rR][tT][sS]                            return RTS;
+[rR][tT][nN]                            return RTN;
+[rR][tT][iI]                            return RTI;
+[rR][tT][eE]                            return RTE;
+[rR][oO][tT]                            return ROT;
+[rR][nN][dD]20                          return RND20;
+[rR][nN][dD]12                          return RND12;
+[rR][nN][dD][lL]                        return RNDL;
+[rR][nN][dD][hH]                        return RNDH;
+[rR][nN][dD]                            return RND;
+
+[rR][0-7]"."[lLhHbB]  return parse_halfreg(&yylval.reg, T_REG_R, yytext);
+
+[rR][eE][tT][sS]               _REG.regno = REG_RETS; return REG;
+[rR][eE][tT][iI]               _REG.regno = REG_RETI; return REG;
+[rR][eE][tT][xX]               _REG.regno = REG_RETX; return REG;
+[rR][eE][tT][nN]               _REG.regno = REG_RETN; return REG;
+[rR][eE][tT][eE]               _REG.regno = REG_RETE; return REG;
+[eE][mM][uU][dD][aA][tT]       _REG.regno = REG_EMUDAT; return REG;
+[rR][aA][iI][sS][eE]           return RAISE;
+
+[rR][0-7]           return parse_reg (&yylval.reg, T_REG_R, yytext);
+
+[rR]      return R;
+[pP][rR][nN][tT]                        return PRNT;
+[pP][cC]                                return PC;
+[pP][aA][cC][kK]                        return PACK;
+
+[pP][0-5]"."[lLhH]  return parse_halfreg (&yylval.reg, T_REG_P, yytext);
+[pP][0-5]           return parse_reg (&yylval.reg, T_REG_P, yytext);
+
+[oO][uU][tT][cC]                        return OUTC;
+[oO][nN][eE][sS]                        return ONES;
+
+[nN][oO][tT]                            return NOT;
+[nN][oO][pP]                            return NOP;
+[mM][nN][oO][pP]                        return MNOP;
+[nN][sS]                                return NS;
+
+
+[mM][iI][nN]                            return MIN;
+[mM][aA][xX]                            return MAX;
+
+[mM][0-3]"."[lLhH]  return parse_halfreg (&yylval.reg, T_REG_M, yytext);
+[mM][0-3]           return parse_reg (&yylval.reg, T_REG_M, yytext);
+
+[mM]                                    return M;
+[lL][tT]                                return LT;
+[lL][sS][hH][iI][fF][tT]                return LSHIFT;
+[lL][sS][eE][tT][uU][pP]                return LSETUP;
+[lL][oO][oO][pP]                       return LOOP;
+[lL][oO][oO][pP]_[bB][eE][gG][iI][nN]  return LOOP_BEGIN;
+[lL][oO][oO][pP]_[eE][nN][dD]          return LOOP_END;
+
+[lL][eE]                                return LE;
+[lL][cC]0 _REG.regno = REG_LC0; return REG;
+[lL][tT]0 _REG.regno = REG_LT0; return REG;
+[lL][bB]0 _REG.regno = REG_LB0; return REG;
+[lL][cC]1 _REG.regno = REG_LC1; return REG;
+[lL][tT]1 _REG.regno = REG_LT1; return REG;
+[lL][bB]1 _REG.regno = REG_LB1; return REG;
+
+[lL][0-3]"."[lLhH]  return parse_halfreg (&yylval.reg, T_REG_L, yytext);
+[lL][0-3]           return parse_reg (&yylval.reg, T_REG_L, yytext);
+[lL][oO]                                return LO;
+[jJ][uU][mM][pP]"."[sS]                 { BEGIN 0; return JUMP_DOT_S;}
+[jJ][uU][mM][pP]"."[lL]                 { BEGIN 0; return JUMP_DOT_L;}
+[jJ][uU][mM][pP]                        { BEGIN 0; return JUMP;}
+[jJ][uU][mM][pP]"."[xX]                 { BEGIN 0; return JUMP_DOT_L; }
+[iI][uU]                                yylval.value = M_IU;   return MMOD;
+[iI][sS][sS]2                           yylval.value = M_ISS2; return MMOD;
+[iI][sS]                                yylval.value = M_IS;   return MMOD;
+[iI][hH]                                yylval.value = M_IH;   return MMOD;
+[iI][fF]                                return IF;
+[iI][0-3]"."[lLhH]  return parse_halfreg (&yylval.reg, T_REG_I, yytext);
+[iI][0-3]           return parse_reg (&yylval.reg, T_REG_I, yytext);
+[hH][lL][tT]                            return HLT;
+[hH][iI]                                return HI;
+[gG][tT]                                return GT;
+[gG][eE]                                return GE;
+[fF][uU]                                yylval.value = M_FU; return MMOD;
+[fF][pP]         _REG.regno = REG_FP; return REG;
+[fF][pP]"."[lL]  _REG.regno = REG_FP; return HALF_REG;
+[fF][pP]"."[hH]  _REG.regno = REG_FP | F_REG_HIGH; return HALF_REG;
+
+[eE][xX][tT][rR][aA][cC][tT]            return EXTRACT;
+[eE][xX][pP][aA][dD][jJ]                return EXPADJ;
+[eE][xX][cC][pP][tT]                    return EXCPT;
+[eE][mM][uU][eE][xX][cC][pP][tT]        return EMUEXCPT;
+[dD][iI][vV][sS]                        return DIVS;
+[dD][iI][vV][qQ]                        return DIVQ;
+[dD][iI][sS][aA][lL][gG][nN][eE][xX][cC][pP][tT]  return DISALGNEXCPT;
+[dD][eE][pP][oO][sS][iI][tT]            return DEPOSIT;
+[dD][bB][gG][hH][aA][lL][tT]            return DBGHALT;
+[dD][bB][gG][cC][mM][pP][lL][xX]        return DBGCMPLX;
+[dD][bB][gG][aA][lL]                    return DBGAL;
+[dD][bB][gG][aA][hH]                    return DBGAH;
+[dD][bB][gG][aA]                        return DBGA;
+[dD][bB][gG]                            return DBG;
+[cC][yY][cC][lL][eE][sS]2  { _REG.regno = REG_CYCLES2; return REG; }
+[cC][yY][cC][lL][eE][sS]  { _REG.regno = REG_CYCLES; return REG; }
+[cC][sS][yY][nN][cC]                    return CSYNC;
+[cC][oO]                                return CO;
+[cC][lL][iI]                            return CLI;
+
+[cC][cC]     _REG.regno = REG_CC; return CCREG;
+[cC][aA][lL][lL]"."[xX]                 { BEGIN 0; return CALL;}
+[cC][aA][lL][lL]                        { BEGIN 0; return CALL;}
+[bB][yY][tT][eE][uU][nN][pP][aA][cC][kK] return BYTEUNPACK;
+[bB][yY][tT][eE][pP][aA][cC][kK]        return BYTEPACK;
+[bB][yY][tT][eE][oO][pP]16[mM]          return BYTEOP16M;
+[bB][yY][tT][eE][oO][pP]16[pP]          return BYTEOP16P;
+[bB][yY][tT][eE][oO][pP]3[pP]           return BYTEOP3P;
+[bB][yY][tT][eE][oO][pP]2[mM]           return BYTEOP2M;
+[bB][yY][tT][eE][oO][pP]2[pP]           return BYTEOP2P;
+[bB][yY][tT][eE][oO][pP]1[pP]           return BYTEOP1P;
+[bB][yY]                                return BY;
+[bB][xX][oO][rR][sS][hH][iI][fF][tT]    return BXORSHIFT;
+[bB][xX][oO][rR]                        return BXOR;
+
+[bB][rR][eE][vV]                        return BREV;
+[bB][pP]                                return BP;
+[bB][iI][tT][tT][sS][tT]                return BITTST;
+[bB][iI][tT][tT][gG][lL]                return BITTGL;
+[bB][iI][tT][sS][eE][tT]                return BITSET;
+[bB][iI][tT][mM][uU][xX]                return BITMUX;
+[bB][iI][tT][cC][lL][rR]                return BITCLR;
+[bB][0-3]"."[lLhH]  return parse_halfreg (&yylval.reg, T_REG_B, yytext);
+[bB][0-3]           return parse_reg (&yylval.reg, T_REG_B, yytext);
+[bB]                                    return B;
+[aA][zZ]  _REG.regno = S_AZ;   return STATUS_REG;
+[aA][nN]  _REG.regno = S_AN;   return STATUS_REG;
+[aA][qQ]  _REG.regno = S_AQ;   return STATUS_REG;
+[aA][cC]0 _REG.regno = S_AC0;  return STATUS_REG;
+[aA][cC]1 _REG.regno = S_AC1;  return STATUS_REG;
+[aA][vV]0 _REG.regno = S_AV0;  return STATUS_REG;
+[aA][vV]0[sS] _REG.regno = S_AV0S; return STATUS_REG;
+[aA][vV]1 _REG.regno = S_AV1;  return STATUS_REG;
+[aA][vV]1[sS] _REG.regno = S_AV1S; return STATUS_REG;
+[vV] _REG.regno = S_V; return STATUS_REG;
+[vV][sS]  _REG.regno = S_VS;   return STATUS_REG;
+
+
+[aA][sS][tT][aA][tT]   _REG.regno = REG_ASTAT; return REG;
+[aA][sS][hH][iI][fF][tT]                return ASHIFT;
+[aA][sS][lL]                            return ASL;
+[aA][sS][rR]                            return ASR;
+[aA][lL][iI][gG][nN]8                   return ALIGN8;
+[aA][lL][iI][gG][nN]16                  return ALIGN16;
+[aA][lL][iI][gG][nN]24                  return ALIGN24;
+[aA]1"."[lL]    return A_ONE_DOT_L;
+[aA]0"."[lL]    return A_ZERO_DOT_L;
+[aA]1"."[hH]    return A_ONE_DOT_H;
+[aA]0"."[hH]    return A_ZERO_DOT_H;
+[aA][bB][sS]                            return ABS;
+abort                                   return ABORT;
+[aA]1"."[xX]    _REG.regno = REG_A1x; return REG;
+[aA]1"."[wW]    _REG.regno = REG_A1w; return REG;
+[aA]1           _REG.regno = REG_A1;  return REG_A_DOUBLE_ONE;
+[aA]0"."[xX]    _REG.regno = REG_A0x; return REG;
+[aA]0"."[wW]    _REG.regno = REG_A0w; return REG;
+[aA]0           _REG.regno = REG_A0;  return REG_A_DOUBLE_ZERO;
+[Gg][Oo][Tt]   return GOT;
+[Pp][Ll][Tt][Pp][Cc]   return PLTPC;
+
+
+"~"                     return TILDA;
+"|="                    return _BAR_ASSIGN;
+"|"                     return BAR;
+"^="                    return _CARET_ASSIGN;
+"^"                     return CARET;
+"]"                     return RBRACK;
+"["                     return LBRACK;
+">>>="                  return _GREATER_GREATER_GREATER_THAN_ASSIGN;
+">>="                   return _GREATER_GREATER_ASSIGN;
+">>>"                   return _GREATER_GREATER_GREATER;
+">>"                    return GREATER_GREATER;
+"=="                    return _ASSIGN_ASSIGN;
+"="                     return ASSIGN;
+"<="                    return _LESS_THAN_ASSIGN;
+"<<="                   return _LESS_LESS_ASSIGN;
+"<<"                    return LESS_LESS;
+"<"                     return LESS_THAN;
+"("                     return LPAREN;
+")"                     return RPAREN;
+":"                     return COLON;
+"/"                     return SLASH;
+"-="                    return _MINUS_ASSIGN;
+"+|+"                                  return _PLUS_BAR_PLUS;
+"-|+"                                  return _MINUS_BAR_PLUS;
+"+|-"                                  return _PLUS_BAR_MINUS;
+"-|-"                                  return _MINUS_BAR_MINUS;
+"--"                    return _MINUS_MINUS;
+"-"                     return MINUS;
+","                     return COMMA;
+"+="                    return _PLUS_ASSIGN;
+"++"                    return _PLUS_PLUS;
+"+"                     return PLUS;
+"*="                    return _STAR_ASSIGN;
+"*"                     return STAR;
+"&="                    return _AMPERSAND_ASSIGN;
+"&"                     return AMPERSAND;
+"%"                     return PERCENT;
+"!"                     return BANG;
+";"                     return SEMICOLON;
+"=!"                   return _ASSIGN_BANG;
+"||"                   return DOUBLE_BAR;
+"@"                    return AT;
+<KEYWORD>[pP][rR][eE][fF][eE][tT][cC][hH]        return PREFETCH;
+<KEYWORD>[uU][nN][lL][iI][nN][kK]                return UNLINK;
+<KEYWORD>[lL][iI][nN][kK]                        return LINK;
+<KEYWORD>[iI][dD][lL][eE]                        return IDLE;
+<KEYWORD>[iI][fF][lL][uU][sS][hH]                return IFLUSH;
+<KEYWORD>[fF][lL][uU][sS][hH][iI][nN][vV]        return FLUSHINV;
+<KEYWORD>[fF][lL][uU][sS][hH]                    return FLUSH;
+([0-9]+)|(0[xX][0-9a-fA-F]+)|([bhfodBHOFD]#[0-9a-fA-F]+)|(0.[0-9]+) {
+    yylval.value = parse_int (&yytext);
+    return NUMBER;
+  }
+[A-Za-z_$.][A-Za-z0-9_$.]* { 
+    yylval.symbol = symbol_find_or_make (yytext);
+    symbol_mark_used (yylval.symbol);
+    return SYMBOL; 
+  }
+[0-9][bfBF] {
+    char *name;
+    char *ref = strdup (yytext);
+    if (ref[1] == 'b' || ref[1] == 'B')
+      {
+        name = fb_label_name ((int) (ref[0] - '0'), 0);
+       yylval.symbol = symbol_find (name);
+
+       if ((yylval.symbol != NULL)
+             && (S_IS_DEFINED (yylval.symbol)))
+          return SYMBOL;
+       as_bad ("backward reference to unknown label %d:", 
+                                                 (int) (ref[0] - '0')); 
+      }
+    else if (ref[1] == 'f' || ref[1] == 'F')
+      {
+        /* Forward reference.  Expect symbol to be undefined or
+           unknown.  undefined: seen it before.  unknown: never seen
+           it before.
+
+           Construct a local label name, then an undefined symbol.
+           Just return it as never seen before.  */
+
+        name = fb_label_name ((int) (ref[0] - '0'), 1);
+       yylval.symbol = symbol_find_or_make (name);
+       /* We have no need to check symbol properties.  */
+       return SYMBOL;
+      }                                  
+  }                                  
+[ \t\n]                                    ;
+"/*".*"*/"                                 ;
+.                                          return yytext[0];
+%%
+static long parse_int (char **end)
+{
+  char fmt = '\0';
+  int not_done = 1;
+  int shiftvalue = 0;
+  char * char_bag;
+  long value = 0;
+  char c;
+  char *arg = *end;
+
+  while (*arg && *arg == ' ')
+    arg++;
+
+  switch (*arg)
+    {
+      case '1':
+      case '2':
+      case '3':
+      case '4':
+      case '5':
+      case '6':
+      case '7':
+      case '8':
+      case '9':
+        fmt = 'd';
+        break;
+
+      case '0':  /* Accept different formated integers hex octal and binary. */
+        {
+         c = *++arg;
+          arg++;
+         if (c == 'x' || c == 'X') /* Hex input.  */
+           fmt = 'h';
+         else if (c == 'b' || c == 'B')
+           fmt = 'b';
+         else if (c == '.')
+           fmt = 'f';
+         else
+            {             /* Octal.  */
+             arg--;
+             fmt = 'o';
+           }
+         break;
+        }
+
+      case 'd':
+      case 'D':
+      case 'h':
+      case 'H':
+      case 'o':
+      case 'O':
+      case 'b':
+      case 'B':
+      case 'f':
+      case 'F':
+        {
+         fmt = *arg++;
+         if (*arg == '#')
+           arg++;
+        }
+    }
+
+  switch (fmt)
+    {
+      case 'h':
+      case 'H':
+        shiftvalue = 4;
+        char_bag = "0123456789ABCDEFabcdef";
+        break;
+
+      case 'o':
+      case 'O':
+        shiftvalue = 3;
+        char_bag = "01234567";
+        break;
+
+      case 'b':
+      case 'B':
+        shiftvalue = 1;
+        char_bag = "01";
+        break;
+
+/* The assembler allows for fractional constants to be created
+   by either the 0.xxxx or the f#xxxx format 
+
+   i.e.   0.5 would result in 0x4000
+
+   note .5 would result in the identifier .5.
+
+   The assembler converts to fractional format 1.15 by the simple rule:
+
+             value = (short) (finput * (1 << 15)).  */
+
+      case 'f':
+      case 'F':
+        {
+          float fval = 0.0;
+          float pos = 10.0;
+          while (1)
+            {
+              int c;
+              c = *arg++;
+
+              if (c >= '0' && c <= '9')
+                {
+                  float digit = (c - '0') / pos;
+                  fval = fval + digit;
+                  pos = pos * 10.0;
+                }
+              else
+                {
+                 *--arg = c;
+                  value = (short) (fval * (1 << 15));
+                  break;
+                }
+            }
+          *end = arg+1;
+          return value;
+        }
+
+      case 'd':
+      case 'D':
+      default:
+        {
+          while (1)
+            {
+              int c;
+              c = *arg++;
+              if (c >= '0' && c <= '9')
+                value = (value * 10) + (c - '0');
+              else
+                {
+                  /* Constants that are suffixed with k|K are multiplied by 1024
+                     This suffix is only allowed on decimal constants. */
+                  if (c == 'k' || c == 'K')
+                    value *= 1024;
+                  else
+                    *--arg = c;
+                  break;
+                }
+            }
+          *end = arg+1;
+          return value;
+        }
+    }
+
+  while (not_done)
+    {
+      char c;
+      c = *arg++;
+      if (c == 0 || !index (char_bag, c))
+       {
+          not_done = 0;
+          *--arg = c;
+        }
+      else
+        {
+          if (c >= 'a' && c <= 'z')
+            c = c - ('a' - '9') + 1;
+          else if (c >= 'A' && c <= 'Z')
+            c = c - ('A' - '9') + 1;
+
+          c -= '0';
+          value = (value << shiftvalue) + c;
+        }
+    }
+  *end = arg+1;
+  return value;
+}
+
+
+static int parse_reg (Register *r, int cl, char *rt)
+{
+  r->regno = cl | (rt[1] - '0');
+  return REG;
+}
+
+static int parse_halfreg (Register *r, int cl, char *rt)
+{
+  r->regno = cl | (rt[1] - '0');
+
+  switch (rt[3])
+    {
+      case 'b':
+      case 'B':
+       return BYTE_DREG;
+
+      case 'l':
+      case 'L':
+       break;
+
+      case 'h':
+      case 'H':
+       r->regno |= F_REG_HIGH;
+       break;
+    }
+
+  return HALF_REG;
+}
+
+/* Our start state is KEYWORD as we have
+   command keywords such as PREFETCH.  */
+
+void 
+set_start_state (void)
+{
+  BEGIN KEYWORD;
+}
+
+
+#ifndef yywrap
+int
+yywrap ()
+{ 
+  return 1;
+}
+#endif
diff --git a/gas/config/bfin-parse.y b/gas/config/bfin-parse.y
new file mode 100644 (file)
index 0000000..7751b68
--- /dev/null
@@ -0,0 +1,4360 @@
+/* bfin-parse.y  ADI Blackfin parser
+   Copyright 2005
+   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, 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+%{
+
+#include <stdio.h>
+#include "bfin-aux.h"
+#include <stdarg.h>
+#include <obstack.h>
+
+#define DSP32ALU(aopcde, HL, dst1, dst0, src0, src1, s, x, aop) \
+       bfin_gen_dsp32alu (HL, aopcde, aop, s, x, dst0, dst1, src0, src1)
+
+#define DSP32MAC(op1, MM, mmod, w1, P, h01, h11, h00, h10, dst, op0, src0, src1, w0) \
+       bfin_gen_dsp32mac (op1, MM, mmod, w1, P, h01, h11, h00, h10, op0, \
+                          dst, src0, src1, w0)
+
+#define DSP32MULT(op1, MM, mmod, w1, P, h01, h11, h00, h10, dst, op0, src0, src1, w0) \
+       bfin_gen_dsp32mult (op1, MM, mmod, w1, P, h01, h11, h00, h10, op0, \
+                           dst, src0, src1, w0)
+
+#define DSP32SHIFT(sopcde, dst0, src0, src1, sop, hls)  \
+       bfin_gen_dsp32shift (sopcde, dst0, src0, src1, sop, hls)
+
+#define DSP32SHIFTIMM(sopcde, dst0, immag, src1, sop, hls)  \
+       bfin_gen_dsp32shiftimm (sopcde, dst0, immag, src1, sop, hls)
+
+#define LDIMMHALF_R(reg, h, s, z, hword) \
+       bfin_gen_ldimmhalf (reg, h, s, z, hword, 1)
+
+#define LDIMMHALF_R5(reg, h, s, z, hword) \
+        bfin_gen_ldimmhalf (reg, h, s, z, hword, 2)
+
+#define LDSTIDXI(ptr, reg, w, sz, z, offset)  \
+       bfin_gen_ldstidxi (ptr, reg, w, sz, z, offset)
+
+#define LDST(ptr, reg, aop, sz, z, w)  \
+       bfin_gen_ldst (ptr, reg, aop, sz, z, w)
+
+#define LDSTII(ptr, reg, offset, w, op)  \
+       bfin_gen_ldstii (ptr, reg, offset, w, op)
+
+#define DSPLDST(i, m, reg, aop, w) \
+       bfin_gen_dspldst (i, reg, aop, w, m)
+
+#define LDSTPMOD(ptr, reg, idx, aop, w) \
+       bfin_gen_ldstpmod (ptr, reg, aop, w, idx)
+
+#define LDSTIIFP(offset, reg, w)  \
+       bfin_gen_ldstiifp (reg, offset, w)
+
+#define LOGI2OP(dst, src, opc) \
+       bfin_gen_logi2op (opc, src, dst.regno & CODE_MASK)
+
+#define ALU2OP(dst, src, opc)  \
+       bfin_gen_alu2op (dst, src, opc)
+
+#define BRCC(t, b, offset) \
+       bfin_gen_brcc (t, b, offset)
+
+#define UJUMP(offset) \
+       bfin_gen_ujump (offset)
+
+#define PROGCTRL(prgfunc, poprnd) \
+       bfin_gen_progctrl (prgfunc, poprnd)
+
+#define PUSHPOPMULTIPLE(dr, pr, d, p, w) \
+       bfin_gen_pushpopmultiple (dr, pr, d, p, w)
+
+#define PUSHPOPREG(reg, w) \
+       bfin_gen_pushpopreg (reg, w)
+
+#define CALLA(addr, s)  \
+       bfin_gen_calla (addr, s)
+
+#define LINKAGE(r, framesize) \
+       bfin_gen_linkage (r, framesize)
+
+#define COMPI2OPD(dst, src, op)  \
+       bfin_gen_compi2opd (dst, src, op)
+
+#define COMPI2OPP(dst, src, op)  \
+       bfin_gen_compi2opp (dst, src, op)
+
+#define DAGMODIK(i, op)  \
+       bfin_gen_dagmodik (i, op)
+
+#define DAGMODIM(i, m, op, br)  \
+       bfin_gen_dagmodim (i, m, op, br)
+
+#define COMP3OP(dst, src0, src1, opc)   \
+       bfin_gen_comp3op (src0, src1, dst, opc)
+
+#define PTR2OP(dst, src, opc)   \
+       bfin_gen_ptr2op (dst, src, opc)
+
+#define CCFLAG(x, y, opc, i, g)  \
+       bfin_gen_ccflag (x, y, opc, i, g)
+
+#define CCMV(src, dst, t) \
+       bfin_gen_ccmv (src, dst, t)
+
+#define CACTRL(reg, a, op) \
+       bfin_gen_cactrl (reg, a, op)
+
+#define LOOPSETUP(soffset, c, rop, eoffset, reg) \
+       bfin_gen_loopsetup (soffset, c, rop, eoffset, reg)
+
+#define HL2(r1, r0)  (IS_H (r1) << 1 | IS_H (r0))
+#define IS_RANGE(bits, expr, sign, mul)    \
+       value_match(expr, bits, sign, mul, 1)
+#define IS_URANGE(bits, expr, sign, mul)    \
+       value_match(expr, bits, sign, mul, 0)
+#define IS_CONST(expr) (expr->type == Expr_Node_Constant)
+#define IS_RELOC(expr) (expr->type != Expr_Node_Constant)
+#define IS_IMM(expr, bits)  value_match (expr, bits, 0, 1, 1)
+#define IS_UIMM(expr, bits)  value_match (expr, bits, 0, 1, 0)
+
+#define IS_PCREL4(expr) \
+       (value_match (expr, 4, 0, 2, 0))
+
+#define IS_LPPCREL10(expr) \
+       (value_match (expr, 10, 0, 2, 0))
+
+#define IS_PCREL10(expr) \
+       (value_match (expr, 10, 0, 2, 1))
+
+#define IS_PCREL12(expr) \
+       (value_match (expr, 12, 0, 2, 1))
+
+#define IS_PCREL24(expr) \
+       (value_match (expr, 24, 0, 2, 1))
+
+
+static int value_match (Expr_Node *expr, int sz, int sign, int mul, int issigned);
+
+extern FILE *errorf;
+extern INSTR_T insn;
+
+static Expr_Node *binary (Expr_Op_Type, Expr_Node *, Expr_Node *);
+static Expr_Node *unary  (Expr_Op_Type, Expr_Node *);
+
+static void notethat (char *format, ...);
+
+char *current_inputline;
+extern char *yytext;
+int yyerror (char *msg);
+
+void error (char *format, ...)
+{
+    va_list ap;
+    char buffer[2000];
+    
+    va_start (ap, format);
+    vsprintf (buffer, format, ap);
+    va_end (ap);
+
+    as_bad (buffer);
+}
+
+int
+yyerror (char *msg)
+{
+  if (msg[0] == '\0')
+    error ("%s", msg);
+
+  else if (yytext[0] != ';')
+    error ("%s. Input text was %s.", msg, yytext);
+  else
+    error ("%s.", msg);
+
+  return -1;
+}
+
+static int
+in_range_p (Expr_Node *expr, int from, int to, unsigned int mask)
+{
+  int val = EXPR_VALUE (expr);
+  if (expr->type != Expr_Node_Constant)
+    return 0;
+  if (val < from || val > to)
+    return 0;
+  return (val & mask) == 0;
+}
+
+extern int yylex (void);
+
+#define imm3(x) EXPR_VALUE (x)
+#define imm4(x) EXPR_VALUE (x)
+#define uimm4(x) EXPR_VALUE (x)
+#define imm5(x) EXPR_VALUE (x)
+#define uimm5(x) EXPR_VALUE (x)
+#define imm6(x) EXPR_VALUE (x)
+#define imm7(x) EXPR_VALUE (x)
+#define imm16(x) EXPR_VALUE (x)
+#define uimm16s4(x) ((EXPR_VALUE (x)) >> 2)
+#define uimm16(x) EXPR_VALUE (x)
+
+/* Return true if a value is inside a range.  */
+#define IN_RANGE(x, low, high) \
+  (((EXPR_VALUE(x)) >= (low)) && (EXPR_VALUE(x)) <= ((high)))
+
+/* Auxiliary functions.  */
+
+static void
+neg_value (Expr_Node *expr)
+{
+  expr->value.i_value = -expr->value.i_value;
+}
+
+static int
+valid_dreg_pair (Register *reg1, Expr_Node *reg2)
+{
+  if (!IS_DREG (*reg1))
+    {
+      yyerror ("Dregs expected");
+      return 0;
+    }
+
+  if (reg1->regno != 1 && reg1->regno != 3)
+    {
+      yyerror ("Bad register pair");
+      return 0;
+    }
+
+  if (imm7 (reg2) != reg1->regno - 1)
+    {
+      yyerror ("Bad register pair");
+      return 0;
+    }
+
+  reg1->regno--;
+  return 1;
+}
+
+static int
+check_multiply_halfregs (Macfunc *aa, Macfunc *ab)
+{
+  if ((!REG_EQUAL (aa->s0, ab->s0) && !REG_EQUAL (aa->s0, ab->s1))
+      || (!REG_EQUAL (aa->s1, ab->s1) && !REG_EQUAL (aa->s1, ab->s0)))
+    return yyerror ("Source multiplication register mismatch");
+
+  return 0;
+}
+
+
+/* Check (vector) mac funcs and ops.  */
+
+static int
+check_macfuncs (Macfunc *aa, Opt_mode *opa,
+               Macfunc *ab, Opt_mode *opb)
+{
+  /* Variables for swapping.  */
+  Macfunc mtmp;
+  Opt_mode otmp;
+
+  /* If a0macfunc comes before a1macfunc, swap them.  */
+       
+  if (aa->n == 0)
+    {
+      /*  (M) is not allowed here.  */
+      if (opa->MM != 0)
+       return yyerror ("(M) not allowed with A0MAC");
+      if (ab->n != 1)
+       return yyerror ("Vector AxMACs can't be same");
+
+      mtmp = *aa; *aa = *ab; *ab = mtmp;
+      otmp = *opa; *opa = *opb; *opb = otmp;
+    }
+  else
+    {
+      if (opb->MM != 0)
+       return yyerror ("(M) not allowed with A0MAC");
+      if (opa->mod != 0)
+       return yyerror ("Bad opt mode");
+      if (ab->n != 0)
+       return yyerror ("Vector AxMACs can't be same");
+    }
+
+  /*  If both ops are != 3, we have multiply_halfregs in both
+  assignment_or_macfuncs.  */
+  if (aa->op == ab->op && aa->op != 3)
+    {
+      if (check_multiply_halfregs (aa, ab) < 0)
+       return -1;
+    }
+  else
+    {
+      /*  Only one of the assign_macfuncs has a half reg multiply
+      Evil trick: Just 'OR' their source register codes:
+      We can do that, because we know they were initialized to 0
+      in the rules that don't use multiply_halfregs.  */
+      aa->s0.regno |= (ab->s0.regno & CODE_MASK);
+      aa->s1.regno |= (ab->s1.regno & CODE_MASK);
+    }
+
+  if (aa->w == ab->w  && aa->P != ab->P)
+    {
+      return yyerror ("macfuncs must differ");
+      if (aa->w && (aa->dst.regno - ab->dst.regno != 1))
+       return yyerror ("Destination Dregs must differ by one");
+    }
+  /* We assign to full regs, thus obey even/odd rules.  */
+  else if ((aa->w && aa->P && IS_EVEN (aa->dst)) 
+          || (ab->w && ab->P && !IS_EVEN (ab->dst)))
+    return yyerror ("Even/Odd register assignment mismatch");
+  /* We assign to half regs, thus obey hi/low rules.  */
+  else if ( (aa->w && !aa->P && !IS_H (aa->dst)) 
+           || (ab->w && !aa->P && IS_H (ab->dst)))
+    return yyerror ("High/Low register assignment mismatch");
+
+  /* Make sure first macfunc has got both P flags ORed.  */
+  aa->P |= ab->P;
+
+  /* Make sure mod flags get ORed, too.  */
+  opb->mod |= opa->mod;
+  return 0;    
+}
+
+
+static int
+is_group1 (INSTR_T x)
+{
+  /* Group1 is dpsLDST, LDSTpmod, LDST, LDSTiiFP, LDSTii.  */
+  if ((x->value & 0xc000) == 0x8000 || (x->value == 0x0000))
+    return 1;
+
+  return 0;
+}
+
+static int
+is_group2 (INSTR_T x)
+{
+  if ((((x->value & 0xfc00) == 0x9c00)  /* dspLDST.  */
+       && !((x->value & 0xfde0) == 0x9c60)  /* dagMODim.  */
+       && !((x->value & 0xfde0) == 0x9ce0)  /* dagMODim with bit rev.  */
+       && !((x->value & 0xfde0) == 0x9d60)) /* pick dagMODik.  */
+      || (x->value == 0x0000))
+    return 1;
+  return 0;
+}
+
+%}
+
+%union {
+  INSTR_T instr;
+  Expr_Node *expr;
+  SYMBOL_T symbol;
+  long value;
+  Register reg;
+  Macfunc macfunc;
+  struct { int r0; int s0; int x0; int aop; } modcodes;
+  struct { int r0; } r0;
+  Opt_mode mod;
+}
+
+
+/* Tokens.  */
+
+/* Vector Specific.  */
+%token BYTEOP16P BYTEOP16M
+%token BYTEOP1P BYTEOP2P BYTEOP2M BYTEOP3P
+%token BYTEUNPACK BYTEPACK
+%token PACK
+%token SAA
+%token ALIGN8 ALIGN16 ALIGN24
+%token VIT_MAX
+%token EXTRACT DEPOSIT EXPADJ SEARCH
+%token ONES SIGN SIGNBITS
+
+/* Stack.  */
+%token LINK UNLINK
+
+/* Registers.  */
+%token REG
+%token PC
+%token CCREG BYTE_DREG
+%token REG_A_DOUBLE_ZERO REG_A_DOUBLE_ONE
+%token A_ZERO_DOT_L A_ZERO_DOT_H A_ONE_DOT_L A_ONE_DOT_H
+%token HALF_REG
+
+/* Progctrl.  */
+%token NOP
+%token RTI RTS RTX RTN RTE
+%token HLT IDLE
+%token STI CLI
+%token CSYNC SSYNC
+%token EMUEXCPT
+%token RAISE EXCPT
+%token LSETUP
+%token LOOP
+%token LOOP_BEGIN
+%token LOOP_END
+%token DISALGNEXCPT
+%token JUMP JUMP_DOT_S JUMP_DOT_L
+%token CALL
+
+/* Emulator only.  */
+%token ABORT
+
+/* Operators.  */
+%token NOT TILDA BANG
+%token AMPERSAND BAR
+%token PERCENT
+%token CARET
+%token BXOR
+
+%token MINUS PLUS STAR SLASH
+%token NEG
+%token MIN MAX ABS
+%token DOUBLE_BAR
+%token _PLUS_BAR_PLUS _PLUS_BAR_MINUS _MINUS_BAR_PLUS _MINUS_BAR_MINUS
+%token _MINUS_MINUS _PLUS_PLUS
+
+/* Shift/rotate ops.  */
+%token SHIFT LSHIFT ASHIFT BXORSHIFT
+%token _GREATER_GREATER_GREATER_THAN_ASSIGN
+%token ROT
+%token LESS_LESS GREATER_GREATER  
+%token _GREATER_GREATER_GREATER
+%token _LESS_LESS_ASSIGN _GREATER_GREATER_ASSIGN
+%token DIVS DIVQ
+
+/* In place operators.  */
+%token ASSIGN _STAR_ASSIGN
+%token _BAR_ASSIGN _CARET_ASSIGN _AMPERSAND_ASSIGN
+%token _MINUS_ASSIGN _PLUS_ASSIGN
+
+/* Assignments, comparisons.  */
+%token _ASSIGN_BANG _LESS_THAN_ASSIGN _ASSIGN_ASSIGN
+%token GE LT LE GT
+%token LESS_THAN
+
+/* Cache.  */
+%token FLUSHINV FLUSH
+%token IFLUSH PREFETCH
+
+/* Misc.  */
+%token PRNT
+%token OUTC
+%token WHATREG
+%token TESTSET
+
+/* Modifiers.  */
+%token ASL ASR
+%token B W
+%token NS S CO SCO
+%token TH TL
+%token BP
+%token BREV
+%token X Z
+%token M MMOD
+%token R RND RNDL RNDH RND12 RND20
+%token V
+%token LO HI
+
+/* Bit ops.  */
+%token BITTGL BITCLR BITSET BITTST BITMUX
+
+/* Debug.  */
+%token DBGAL DBGAH DBGHALT DBG DBGA DBGCMPLX
+
+/* Semantic auxiliaries.  */
+
+%token IF COMMA BY
+%token COLON SEMICOLON
+%token RPAREN LPAREN LBRACK RBRACK
+%token STATUS_REG
+%token MNOP
+%token SYMBOL NUMBER
+%token GOT AT PLTPC
+
+/* Types.  */
+%type <instr> asm
+%type <value> MMOD
+%type <mod> opt_mode
+
+%type <value> NUMBER
+%type <r0> aligndir
+%type <modcodes> byteop_mod
+%type <reg> a_assign
+%type <reg> a_plusassign
+%type <reg> a_minusassign
+%type <macfunc> multiply_halfregs
+%type <macfunc> assign_macfunc 
+%type <macfunc> a_macfunc 
+%type <expr> expr_1
+%type <instr> asm_1
+%type <r0> vmod
+%type <modcodes> vsmod
+%type <modcodes> ccstat
+%type <r0> cc_op
+%type <reg> CCREG
+%type <reg> reg_with_postinc
+%type <reg> reg_with_predec
+
+%type <r0> searchmod
+%type <expr> symbol
+%type <symbol> SYMBOL
+%type <expr> eterm
+%type <reg> REG
+%type <reg> BYTE_DREG
+%type <reg> REG_A_DOUBLE_ZERO
+%type <reg> REG_A_DOUBLE_ONE
+%type <reg> REG_A
+%type <reg> STATUS_REG 
+%type <expr> expr
+%type <r0> xpmod
+%type <r0> xpmod1
+%type <modcodes> smod 
+%type <modcodes> b3_op
+%type <modcodes> rnd_op
+%type <modcodes> post_op
+%type <reg> HALF_REG
+%type <r0> iu_or_nothing
+%type <r0> plus_minus
+%type <r0> asr_asl
+%type <r0> asr_asl_0
+%type <modcodes> sco
+%type <modcodes> amod0
+%type <modcodes> amod1
+%type <modcodes> amod2
+%type <r0> op_bar_op
+%type <r0> w32_or_nothing
+%type <r0> c_align
+%type <r0> min_max
+%type <expr> got
+%type <expr> got_or_expr
+%type <expr> pltpc
+
+
+/* Precedence rules.  */
+%left BAR
+%left CARET
+%left AMPERSAND
+%left LESS_LESS GREATER_GREATER
+%left PLUS MINUS
+%left STAR SLASH PERCENT
+
+%right ASSIGN
+
+%right TILDA BANG
+%start statement
+%%
+statement: 
+       | asm
+       {
+         insn = $1;
+         if (insn == (INSTR_T) 0)
+           return NO_INSN_GENERATED;
+         else if (insn == (INSTR_T) - 1)
+           return SEMANTIC_ERROR;
+         else
+           return INSN_GENERATED;
+       }
+       ;
+
+asm: asm_1 SEMICOLON
+       /* Parallel instructions.  */
+       | asm_1 DOUBLE_BAR asm_1 DOUBLE_BAR asm_1 SEMICOLON
+       {
+         if (($1->value & 0xf800) == 0xc000)
+           {
+             if (is_group1 ($3) && is_group2 ($5))
+               $$ = bfin_gen_multi_instr ($1, $3, $5);
+             else if (is_group2 ($3) && is_group1 ($5))
+               $$ = bfin_gen_multi_instr ($1, $5, $3);
+             else
+               return yyerror ("Wrong 16 bit instructions groups, slot 2 and slot 3 must be 16-bit instrution group");
+           }
+         else if (($3->value & 0xf800) == 0xc000)
+           {
+             if (is_group1 ($1) && is_group2 ($5))
+               $$ = bfin_gen_multi_instr ($3, $1, $5);
+             else if (is_group2 ($1) && is_group1 ($5))
+               $$ = bfin_gen_multi_instr ($3, $5, $1);
+             else
+               return yyerror ("Wrong 16 bit instructions groups, slot 1 and slot 3 must be 16-bit instrution group");
+           }
+         else if (($5->value & 0xf800) == 0xc000)
+           {
+             if (is_group1 ($1) && is_group2 ($3))
+               $$ = bfin_gen_multi_instr ($5, $1, $3);
+             else if (is_group2 ($1) && is_group1 ($3))
+               $$ = bfin_gen_multi_instr ($5, $3, $1);
+             else
+               return yyerror ("Wrong 16 bit instructions groups, slot 1 and slot 2 must be 16-bit instrution group");
+           }
+         else
+           error ("\nIllegal Multi Issue Construct, at least any one of the slot must be DSP32 instruction group\n");
+       }
+
+       | asm_1 DOUBLE_BAR asm_1 SEMICOLON
+       {
+         if (($1->value & 0xf800) == 0xc000)
+           {
+             if (is_group1 ($3))
+               $$ = bfin_gen_multi_instr ($1, $3, 0);
+             else if (is_group2 ($3))
+               $$ = bfin_gen_multi_instr ($1, 0, $3);
+             else
+               return yyerror ("Wrong 16 bit instructions groups, slot 2 must be the 16-bit instruction group");
+           }
+         else if (($3->value & 0xf800) == 0xc000)
+           {
+             if (is_group1 ($1))
+               $$ = bfin_gen_multi_instr ($3, $1, 0);
+             else if (is_group2 ($1))
+               $$ = bfin_gen_multi_instr ($3, 0, $1);
+             else
+               return yyerror ("Wrong 16 bit instructions groups, slot 1 must be the 16-bit instruction group");
+           }
+         else if (is_group1 ($1) && is_group2 ($3))
+             $$ = bfin_gen_multi_instr (0, $1, $3);
+         else if (is_group2 ($1) && is_group1 ($3))
+           $$ = bfin_gen_multi_instr (0, $3, $1);
+         else
+           return yyerror ("Wrong 16 bit instructions groups, slot 1 and slot 2 must be the 16-bit instruction group");
+       }
+       | error
+       {
+       $$ = 0;
+       yyerror ("");
+       yyerrok;
+       }
+       ;
+
+/* DSPMAC.  */
+
+asm_1:   
+       MNOP
+       {
+         $$ = DSP32MAC (3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0);
+       }
+       | assign_macfunc opt_mode
+       {
+         int op0, op1;
+         int w0 = 0, w1 = 0;
+         int h00, h10, h01, h11;
+
+         if ($1.n == 0)
+           {
+             if ($2.MM) 
+               return yyerror ("(m) not allowed with a0 unit");
+             op1 = 3;
+             op0 = $1.op;
+             w1 = 0;
+              w0 = $1.w;
+             h00 = IS_H ($1.s0);
+              h10 = IS_H ($1.s1);
+             h01 = h11 = 0;
+           }
+         else
+           {
+             op1 = $1.op;
+             op0 = 3;
+             w1 = $1.w;
+              w0 = 0;
+             h00 = h10 = 0;
+             h01 = IS_H ($1.s0);
+              h11 = IS_H ($1.s1);
+           }
+         $$ = DSP32MAC (op1, $2.MM, $2.mod, w1, $1.P, h01, h11, h00, h10,
+                        &$1.dst, op0, &$1.s0, &$1.s1, w0);
+       }
+
+
+/* VECTOR MACs.  */
+
+       | assign_macfunc opt_mode COMMA assign_macfunc opt_mode
+       {
+         Register *dst;
+
+         if (check_macfuncs (&$1, &$2, &$4, &$5) < 0) 
+           return -1;
+         notethat ("assign_macfunc (.), assign_macfunc (.)\n");
+
+         if ($1.w)
+           dst = &$1.dst;
+         else
+           dst = &$4.dst;
+
+         $$ = DSP32MAC ($1.op, $2.MM, $5.mod, $1.w, $1.P,
+                        IS_H ($1.s0),  IS_H ($1.s1), IS_H ($4.s0), IS_H ($4.s1),
+                        dst, $4.op, &$1.s0, &$1.s1, $4.w);
+       }
+
+/* DSPALU.  */
+
+       | DISALGNEXCPT
+       {
+         notethat ("dsp32alu: DISALGNEXCPT\n");
+         $$ = DSP32ALU (18, 0, 0, 0, 0, 0, 0, 0, 3);
+       }
+       | REG ASSIGN LPAREN a_plusassign REG_A RPAREN
+       {
+         if (IS_DREG ($1) && !IS_A1 ($4) && IS_A1 ($5))
+           {
+             notethat ("dsp32alu: dregs = ( A0 += A1 )\n");
+             $$ = DSP32ALU (11, 0, 0, &$1, 0, 0, 0, 0, 0);
+           }
+         else 
+           return yyerror ("Register mismatch");
+       }       
+       | HALF_REG ASSIGN LPAREN a_plusassign REG_A RPAREN
+       {
+         if (!IS_A1 ($4) && IS_A1 ($5))
+           {
+             notethat ("dsp32alu: dregs_half = ( A0 += A1 )\n");
+             $$ = DSP32ALU (11, IS_H ($1), 0, &$1, 0, 0, 0, 0, 1);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+       | A_ZERO_DOT_H ASSIGN HALF_REG
+       {
+         notethat ("dsp32alu: A_ZERO_DOT_H = dregs_hi\n");
+         $$ = DSP32ALU (9, IS_H ($3), 0, 0, &$3, 0, 0, 0, 0);
+       }
+       | A_ONE_DOT_H ASSIGN HALF_REG
+       {
+         notethat ("dsp32alu: A_ZERO_DOT_H = dregs_hi\n");
+         $$ = DSP32ALU (9, IS_H ($3), 0, 0, &$3, 0, 0, 0, 2);
+       }
+       | LPAREN REG COMMA REG RPAREN ASSIGN BYTEOP16P LPAREN REG
+         COLON expr COMMA REG COLON expr RPAREN aligndir
+       {
+         if (!IS_DREG ($2) || !IS_DREG ($4))
+           return yyerror ("Dregs expected");
+         else if (!valid_dreg_pair (&$9, $11))
+           return yyerror ("Bad dreg pair");
+         else if (!valid_dreg_pair (&$13, $15))
+           return yyerror ("Bad dreg pair");
+         else
+           {
+             notethat ("dsp32alu: (dregs , dregs ) = BYTEOP16P (dregs_pair , dregs_pair ) (half)\n");
+             $$ = DSP32ALU (21, 0, &$2, &$4, &$9, &$13, $17.r0, 0, 0);
+           }
+       }
+
+       | LPAREN REG COMMA REG RPAREN ASSIGN BYTEOP16M LPAREN REG COLON expr COMMA
+         REG COLON expr RPAREN aligndir 
+       {
+         if (!IS_DREG ($2) || !IS_DREG($4))
+           return yyerror ("Dregs expected");
+         else if (!valid_dreg_pair (&$9, $11))
+           return yyerror ("Bad dreg pair");
+         else if (!valid_dreg_pair (&$13, $15))
+           return yyerror ("Bad dreg pair");
+         else
+           {
+             notethat ("dsp32alu: (dregs , dregs ) = BYTEOP16M (dregs_pair , dregs_pair ) (aligndir)\n");
+             $$ = DSP32ALU (21, 0, &$2, &$4, &$9, &$13, $17.r0, 0, 1);
+           }
+       }
+
+       | LPAREN REG COMMA REG RPAREN ASSIGN BYTEUNPACK REG COLON expr aligndir
+       {
+         if (!IS_DREG ($2) || !IS_DREG ($4))
+           return yyerror ("Dregs expected");
+         else if (!valid_dreg_pair (&$8, $10))
+           return yyerror ("Bad dreg pair");
+         else
+           {
+             notethat ("dsp32alu: (dregs , dregs ) = BYTEUNPACK dregs_pair (aligndir)\n");
+             $$ = DSP32ALU (24, 0, &$2, &$4, &$8, 0, $11.r0, 0, 1);
+           }
+       }
+       | LPAREN REG COMMA REG RPAREN ASSIGN SEARCH REG LPAREN searchmod RPAREN
+       {
+         if (IS_DREG ($2) && IS_DREG ($4) && IS_DREG ($8))
+           {
+             notethat ("dsp32alu: (dregs , dregs ) = SEARCH dregs (searchmod)\n");
+             $$ = DSP32ALU (13, 0, &$2, &$4, &$8, 0, 0, 0, $10.r0);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+       | REG ASSIGN A_ONE_DOT_L PLUS A_ONE_DOT_H COMMA
+         REG ASSIGN A_ZERO_DOT_L PLUS A_ZERO_DOT_H
+       {
+         if (IS_DREG ($1) && IS_DREG ($7))
+           {
+             notethat ("dsp32alu: dregs = A1.l + A1.h, dregs = A0.l + A0.h  \n");
+             $$ = DSP32ALU (12, 0, &$1, &$7, 0, 0, 0, 0, 1);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+
+       | REG ASSIGN REG_A PLUS REG_A COMMA REG ASSIGN REG_A MINUS REG_A amod1 
+       {
+         if (IS_DREG ($1) && IS_DREG ($7) && !REG_SAME ($3, $5)
+             && IS_A1 ($9) && !IS_A1 ($11))
+           {
+             notethat ("dsp32alu: dregs = A1 + A0 , dregs = A1 - A0 (amod1)\n");
+             $$ = DSP32ALU (17, 0, &$1, &$7, 0, 0, $12.s0, $12.x0, 0);
+             
+           }
+         else if (IS_DREG ($1) && IS_DREG ($7) && !REG_SAME ($3, $5)
+                  && !IS_A1 ($9) && IS_A1 ($11))
+           {
+             notethat ("dsp32alu: dregs = A0 + A1 , dregs = A0 - A1 (amod1)\n");
+             $$ = DSP32ALU (17, 0, &$1, &$7, 0, 0, $12.s0, $12.x0, 1);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | REG ASSIGN REG plus_minus REG COMMA REG ASSIGN REG plus_minus REG amod1
+       {
+         if ($4.r0 == $10.r0) 
+           return yyerror ("Operators must differ");
+
+         if (IS_DREG ($1) && IS_DREG ($3) && IS_DREG ($5)
+             && REG_SAME ($3, $9) && REG_SAME ($5, $11))
+           {
+             notethat ("dsp32alu: dregs = dregs + dregs,"
+                      "dregs = dregs - dregs (amod1)\n");
+             $$ = DSP32ALU (4, 0, &$1, &$7, &$3, &$5, $12.s0, $12.x0, 2);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+/*  Bar Operations.  */
+
+       | REG ASSIGN REG op_bar_op REG COMMA REG ASSIGN REG op_bar_op REG amod2 
+       {
+         if (!REG_SAME ($3, $9) || !REG_SAME ($5, $11))
+           return yyerror ("Differing source registers");
+
+         if (!IS_DREG ($1) || !IS_DREG ($3) || !IS_DREG ($5) || !IS_DREG ($7)) 
+           return yyerror ("Dregs expected");
+
+       
+         if ($4.r0 == 1 && $10.r0 == 2)
+           {
+             notethat ("dsp32alu:  dregs = dregs .|. dregs , dregs = dregs .|. dregs (amod2)\n");
+             $$ = DSP32ALU (1, 1, &$1, &$7, &$3, &$5, $12.s0, $12.x0, $12.r0);
+           }
+         else if ($4.r0 == 0 && $10.r0 == 3)
+           {
+             notethat ("dsp32alu:  dregs = dregs .|. dregs , dregs = dregs .|. dregs (amod2)\n");
+             $$ = DSP32ALU (1, 0, &$1, &$7, &$3, &$5, $12.s0, $12.x0, $12.r0);
+           }
+         else
+           return yyerror ("Bar operand mismatch");
+       }
+
+       | REG ASSIGN ABS REG vmod
+       {
+         int op;
+
+         if (IS_DREG ($1) && IS_DREG ($4))
+           {
+             if ($5.r0)
+               {
+                 notethat ("dsp32alu: dregs = ABS dregs (v)\n");
+                 op = 6;
+               }
+             else
+               {
+                 /* Vector version of ABS.  */
+                 notethat ("dsp32alu: dregs = ABS dregs\n");
+                 op = 7;
+               }
+             $$ = DSP32ALU (op, 0, 0, &$1, &$4, 0, 0, 0, 2);
+           }
+         else
+           return yyerror ("Dregs expected");
+       }
+       | a_assign ABS REG_A
+       {
+         notethat ("dsp32alu: Ax = ABS Ax\n");
+         $$ = DSP32ALU (16, IS_A1 ($1), 0, 0, 0, 0, 0, 0, IS_A1 ($3));
+       }
+       | A_ZERO_DOT_L ASSIGN HALF_REG
+       {
+         if (IS_DREG_L ($3))
+           {
+             notethat ("dsp32alu: A0.l = reg_half\n");
+             $$ = DSP32ALU (9, IS_H ($3), 0, 0, &$3, 0, 0, 0, 0);
+           }
+         else
+           return yyerror ("A0.l = Rx.l expected");
+       }
+       | A_ONE_DOT_L ASSIGN HALF_REG
+       {
+         if (IS_DREG_L ($3))
+           {
+             notethat ("dsp32alu: A1.l = reg_half\n");
+             $$ = DSP32ALU (9, IS_H ($3), 0, 0, &$3, 0, 0, 0, 2);
+           }
+         else
+           return yyerror ("A1.l = Rx.l expected");
+       }
+
+       | REG ASSIGN c_align LPAREN REG COMMA REG RPAREN
+       {
+         if (IS_DREG ($1) && IS_DREG ($5) && IS_DREG ($7))
+           {
+             notethat ("dsp32shift: dregs = ALIGN8 (dregs , dregs )\n");
+             $$ = DSP32SHIFT (13, &$1, &$7, &$5, $3.r0, 0);
+           }
+         else
+           return yyerror ("Dregs expected");
+       }
+
+       | REG ASSIGN BYTEOP1P LPAREN REG COLON expr COMMA REG COLON expr RPAREN byteop_mod
+       {
+         if (!IS_DREG ($1))
+           return yyerror ("Dregs expected");
+         else if (!valid_dreg_pair (&$5, $7))
+           return yyerror ("Bad dreg pair");
+         else if (!valid_dreg_pair (&$9, $11))
+           return yyerror ("Bad dreg pair");
+         else
+           {
+             notethat ("dsp32alu: dregs = BYTEOP1P (dregs_pair , dregs_pair ) (T)\n");
+             $$ = DSP32ALU (20, 0, 0, &$1, &$5, &$9, $13.s0, 0, $13.r0);
+           }
+       }
+       | REG ASSIGN BYTEOP1P LPAREN REG COLON expr COMMA REG COLON expr RPAREN
+       {
+         if (!IS_DREG ($1))
+           return yyerror ("Dregs expected");
+         else if (!valid_dreg_pair (&$5, $7))
+           return yyerror ("Bad dreg pair");
+         else if (!valid_dreg_pair (&$9, $11))
+           return yyerror ("Bad dreg pair");
+         else
+           {
+             notethat ("dsp32alu: dregs = BYTEOP1P (dregs_pair , dregs_pair ) (T)\n");
+             $$ = DSP32ALU (20, 0, 0, &$1, &$5, &$9, 0, 0, 0);
+           }
+       }
+
+       | REG ASSIGN BYTEOP2P LPAREN REG COLON expr COMMA REG COLON expr RPAREN
+         rnd_op
+       {
+         if (!IS_DREG ($1))
+           return yyerror ("Dregs expected");
+         else if (!valid_dreg_pair (&$5, $7))
+           return yyerror ("Bad dreg pair");
+         else if (!valid_dreg_pair (&$9, $11))
+           return yyerror ("Bad dreg pair");
+         else
+           {
+             notethat ("dsp32alu: dregs = BYTEOP2P (dregs_pair , dregs_pair ) (rnd_op)\n");
+             $$ = DSP32ALU (22, $13.r0, 0, &$1, &$5, &$9, $13.s0, $13.x0, $13.aop);
+           }
+       }
+
+       | REG ASSIGN BYTEOP2M LPAREN REG COLON expr COMMA REG COLON expr RPAREN
+         rnd_op
+       {
+         if (!IS_DREG ($1))
+           return yyerror ("Dregs expected");
+         else if (!valid_dreg_pair (&$5, $7))
+           return yyerror ("Bad dreg pair");
+         else if (!valid_dreg_pair (&$9, $11))
+           return yyerror ("Bad dreg pair");
+         else
+           {
+             notethat ("dsp32alu: dregs = BYTEOP2P (dregs_pair , dregs_pair ) (rnd_op)\n");
+             $$ = DSP32ALU (22, $13.r0, 0, &$1, &$5, &$9, $13.s0, 0, $13.x0);
+           }
+       }
+
+       | REG ASSIGN BYTEOP3P LPAREN REG COLON expr COMMA REG COLON expr RPAREN
+         b3_op
+       {
+         if (!IS_DREG ($1))
+           return yyerror ("Dregs expected");
+         else if (!valid_dreg_pair (&$5, $7))
+           return yyerror ("Bad dreg pair");
+         else if (!valid_dreg_pair (&$9, $11))
+           return yyerror ("Bad dreg pair");
+         else
+           {
+             notethat ("dsp32alu: dregs = BYTEOP3P (dregs_pair , dregs_pair ) (b3_op)\n");
+             $$ = DSP32ALU (23, $13.x0, 0, &$1, &$5, &$9, $13.s0, 0, 0);
+           }
+       }
+
+       | REG ASSIGN BYTEPACK LPAREN REG COMMA REG RPAREN
+       {
+         if (IS_DREG ($1) && IS_DREG ($5) && IS_DREG ($7))
+           {
+             notethat ("dsp32alu: dregs = BYTEPACK (dregs , dregs )\n");
+             $$ = DSP32ALU (24, 0, 0, &$1, &$5, &$7, 0, 0, 0);
+           }
+         else
+           return yyerror ("Dregs expected");
+       }
+
+       | HALF_REG ASSIGN HALF_REG ASSIGN SIGN LPAREN HALF_REG RPAREN STAR
+         HALF_REG PLUS SIGN LPAREN HALF_REG RPAREN STAR HALF_REG 
+       {
+         if (IS_HCOMPL ($1, $3) && IS_HCOMPL ($7, $14) && IS_HCOMPL ($10, $17))
+           {
+             notethat ("dsp32alu:      dregs_hi = dregs_lo ="
+                      "SIGN (dregs_hi) * dregs_hi + "
+                      "SIGN (dregs_lo) * dregs_lo \n");
+
+               $$ = DSP32ALU (12, 0, 0, &$1, &$7, &$10, 0, 0, 0);
+           }
+         else
+           return yyerror ("Dregs expected");
+       }
+       | REG ASSIGN REG plus_minus REG amod1 
+       {
+         if (IS_DREG ($1) && IS_DREG ($3) && IS_DREG ($5))
+           {
+             if ($6.aop == 0)
+               {
+                 /* No saturation flag specified, generate the 16 bit variant.  */
+                 notethat ("COMP3op: dregs = dregs +- dregs\n");
+                 $$ = COMP3OP (&$1, &$3, &$5, $4.r0);
+               }
+             else
+               {
+                /* Saturation flag specified, generate the 32 bit variant.  */
+                 notethat ("dsp32alu: dregs = dregs +- dregs (amod1)\n");
+                 $$ = DSP32ALU (4, 0, 0, &$1, &$3, &$5, $6.s0, $6.x0, $4.r0);
+               }
+           }
+         else
+           if (IS_PREG ($1) && IS_PREG ($3) && IS_PREG ($5) && $4.r0 == 0)
+             {
+               notethat ("COMP3op: pregs = pregs + pregs\n");
+               $$ = COMP3OP (&$1, &$3, &$5, 5);
+             }
+           else
+             return yyerror ("Dregs expected");
+       }
+       | REG ASSIGN min_max LPAREN REG COMMA REG RPAREN vmod
+       {
+         int op;
+
+         if (IS_DREG ($1) && IS_DREG ($5) && IS_DREG ($7))
+           {
+             if ($9.r0)
+               op = 6;
+             else
+               op = 7;
+
+             notethat ("dsp32alu: dregs = {MIN|MAX} (dregs, dregs)\n");
+             $$ = DSP32ALU (op, 0, 0, &$1, &$5, &$7, 0, 0, $3.r0);
+           }
+         else
+           return yyerror ("Dregs expected");
+       }
+
+       | a_assign MINUS REG_A
+       {
+         notethat ("dsp32alu: Ax = - Ax\n");
+         $$ = DSP32ALU (14, IS_A1 ($1), 0, 0, 0, 0, 0, 0, IS_A1 ($3));
+       }
+       | HALF_REG ASSIGN HALF_REG plus_minus HALF_REG amod1
+       {
+         notethat ("dsp32alu: dregs_lo = dregs_lo +- dregs_lo (amod1)\n");
+         $$ = DSP32ALU (2 | $4.r0, IS_H ($1), 0, &$1, &$3, &$5,
+                        $6.s0, $6.x0, HL2 ($3, $5));
+       }
+       | a_assign a_assign expr
+       {
+         if (EXPR_VALUE ($3) == 0 && !REG_SAME ($1, $2))
+           {
+             notethat ("dsp32alu: A1 = A0 = 0\n");
+             $$ = DSP32ALU (8, 0, 0, 0, 0, 0, 0, 0, 2);
+           }
+         else
+           return yyerror ("Bad value, 0 expected");
+       }
+
+       /* Saturating.  */
+       | a_assign REG_A LPAREN S RPAREN
+       {
+         if (REG_SAME ($1, $2))
+           {
+             notethat ("dsp32alu: Ax = Ax (S)\n");
+             $$ = DSP32ALU (8, 0, 0, 0, 0, 0, 1, 0, IS_A1 ($1));
+           }
+         else
+           return yyerror ("Registers must be equal");
+       }
+
+       | HALF_REG ASSIGN REG LPAREN RND RPAREN
+       {
+         if (IS_DREG ($3))
+           {
+             notethat ("dsp32alu: dregs_half = dregs (RND)\n");
+             $$ = DSP32ALU (12, IS_H ($1), 0, &$1, &$3, 0, 0, 0, 3);
+           }
+         else
+           return yyerror ("Dregs expected");
+       }
+
+       | HALF_REG ASSIGN REG plus_minus REG LPAREN RND12 RPAREN
+       {
+         if (IS_DREG ($3) && IS_DREG ($5))
+           {
+             notethat ("dsp32alu: dregs_half = dregs (+-) dregs (RND12)\n");
+             $$ = DSP32ALU (5, IS_H ($1), 0, &$1, &$3, &$5, 0, 0, $4.r0);
+           }
+         else
+           return yyerror ("Dregs expected");
+       }
+
+       | HALF_REG ASSIGN REG plus_minus REG LPAREN RND20 RPAREN
+       {
+         if (IS_DREG ($3) && IS_DREG ($5))
+           {
+             notethat ("dsp32alu: dregs_half = dregs -+ dregs (RND20)\n");
+             $$ = DSP32ALU (5, IS_H ($1), 0, &$1, &$3, &$5, 0, 1, $4.r0 | 2);
+           }
+         else
+           return yyerror ("Dregs expected");
+       }
+
+       | a_assign REG_A 
+       {
+         if (!REG_SAME ($1, $2))
+           {
+             notethat ("dsp32alu: An = Am\n");
+             $$ = DSP32ALU (8, 0, 0, 0, 0, 0, IS_A1 ($1), 0, 3);
+           }
+         else
+           return yyerror ("Accu reg arguments must differ");
+       }
+
+       | a_assign REG
+       {
+         if (IS_DREG ($2))
+           {
+             notethat ("dsp32alu: An = dregs\n");
+             $$ = DSP32ALU (9, 0, 0, 0, &$2, 0, 1, 0, IS_A1 ($1) << 1);
+           }
+         else
+           return yyerror ("Dregs expected");
+       }
+
+       | REG ASSIGN HALF_REG xpmod
+       {
+         if (!IS_H ($3))
+           {
+             if ($1.regno == REG_A0x && IS_DREG ($3))
+               {
+                 notethat ("dsp32alu: A0.x = dregs_lo\n");
+                 $$ = DSP32ALU (9, 0, 0, 0, &$3, 0, 0, 0, 1);
+               }
+             else if ($1.regno == REG_A1x && IS_DREG ($3))
+               {
+                 notethat ("dsp32alu: A1.x = dregs_lo\n");
+                 $$ = DSP32ALU (9, 0, 0, 0, &$3, 0, 0, 0, 3);
+               }
+             else if (IS_DREG ($1) && IS_DREG ($3))
+               {
+                 notethat ("ALU2op: dregs = dregs_lo\n");
+                 $$ = ALU2OP (&$1, &$3, 10 | ($4.r0 ? 0: 1));
+               }
+             else
+               return yyerror ("Register mismatch");
+           }
+         else
+           return yyerror ("Low reg expected");
+       }
+
+       | HALF_REG ASSIGN expr
+       {
+         notethat ("LDIMMhalf: pregs_half = imm16\n");
+         if (!IS_IMM ($3, 16) && !IS_UIMM ($3, 16))
+           return yyerror ("Constant out of range");
+         $$ = LDIMMHALF_R (&$1, IS_H ($1), 0, 0, $3);
+       }
+
+       | a_assign expr
+       {
+         notethat ("dsp32alu: An = 0\n");
+
+         if (imm7 ($2) != 0)
+           return yyerror ("0 expected");
+
+         $$ = DSP32ALU (8, 0, 0, 0, 0, 0, 0, 0, IS_A1 ($1));
+       }
+
+       | REG ASSIGN expr xpmod1
+       {
+         if ($4.r0 == 0)
+           {
+             /* 7 bit immediate value if possible.
+                We will check for that constant value for efficiency
+                If it goes to reloc, it will be 16 bit.  */
+             if (IS_CONST ($3) && IS_IMM ($3, 7) && (IS_DREG ($1) || IS_PREG ($1)))
+               {
+                 /* if the expr is a relocation, generate it.  */
+                 if (IS_DREG ($1) && IS_IMM ($3, 7))
+                   {
+                     notethat ("COMPI2opD: dregs = imm7 (x) \n");
+                     $$ = COMPI2OPD (&$1, imm7 ($3), 0);
+                   }
+                 else if (IS_PREG ($1) && IS_IMM ($3, 7))
+                   {
+                     notethat ("COMPI2opP: pregs = imm7 (x)\n");
+                     $$ = COMPI2OPP (&$1, imm7 ($3), 0);
+                   }
+                 else
+                   return yyerror ("Bad register or value for assigment");
+               }
+             else
+               {
+                 notethat ("LDIMMhalf: regs = luimm16 (x)\n");
+                 /* reg, H, S, Z.   */
+                 $$ = LDIMMHALF_R5 (&$1, 0, 1, 0, $3);
+               } 
+           }
+         else
+           {
+             /* (z) There is no 7 bit zero extended instruction.
+             If the expr is a relocation, generate it.   */
+             notethat ("LDIMMhalf: regs = luimm16 (x)\n");
+             /* reg, H, S, Z.  */
+             $$ = LDIMMHALF_R5 (&$1, 0, 0, 1, $3);
+           }
+       }
+
+       | HALF_REG ASSIGN REG
+       {
+         if (IS_H ($1))
+           return yyerror ("Low reg expected");
+
+         if (IS_DREG ($1) && $3.regno == REG_A0x)
+           {
+             notethat ("dsp32alu: dregs_lo = A0.x\n");
+             $$ = DSP32ALU (10, 0, 0, &$1, 0, 0, 0, 0, 0);
+           }
+         else if (IS_DREG ($1) && $3.regno == REG_A1x)
+           {
+             notethat ("dsp32alu: dregs_lo = A1.x\n");
+             $$ = DSP32ALU (10, 0, 0, &$1, 0, 0, 0, 0, 1);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | REG ASSIGN REG op_bar_op REG amod0 
+       {
+         if (IS_DREG ($1) && IS_DREG ($3) && IS_DREG ($5))
+           {
+             notethat ("dsp32alu: dregs = dregs .|. dregs (amod0)\n");
+             $$ = DSP32ALU (0, 0, 0, &$1, &$3, &$5, $6.s0, $6.x0, $4.r0);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | REG ASSIGN BYTE_DREG xpmod
+       {
+         if (IS_DREG ($1) && IS_DREG ($3))
+           {
+             notethat ("ALU2op: dregs = dregs_byte\n");
+             $$ = ALU2OP (&$1, &$3, 12 | ($4.r0 ? 0: 1));
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | a_assign ABS REG_A COMMA a_assign ABS REG_A
+       {
+         if (REG_SAME ($1, $3) && REG_SAME ($5, $7) && !REG_SAME ($1, $5))
+           {
+             notethat ("dsp32alu: A1 = ABS A1 , A0 = ABS A0\n");
+             $$ = DSP32ALU (16, 0, 0, 0, 0, 0, 0, 0, 3);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | a_assign MINUS REG_A COMMA a_assign MINUS REG_A
+       {
+         if (REG_SAME ($1, $3) && REG_SAME ($5, $7) && !REG_SAME ($1, $5))
+           {
+             notethat ("dsp32alu: A1 = - A1 , A0 = - A0\n");
+             $$ = DSP32ALU (14, 0, 0, 0, 0, 0, 0, 0, 3);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | a_minusassign REG_A w32_or_nothing
+       {
+         if (!IS_A1 ($1) && IS_A1 ($2))
+           {
+             notethat ("dsp32alu: A0 -= A1\n");
+             $$ = DSP32ALU (11, 0, 0, 0, 0, 0, $3.r0, 0, 3);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | REG _MINUS_ASSIGN expr
+       {
+         if (IS_IREG ($1) && EXPR_VALUE ($3) == 4)
+           {
+             notethat ("dagMODik: iregs -= 4\n");
+             $$ = DAGMODIK (&$1, 3);
+           }
+         else if (IS_IREG ($1) && EXPR_VALUE ($3) == 2)
+           {
+             notethat ("dagMODik: iregs -= 2\n");
+             $$ = DAGMODIK (&$1, 1);
+           }
+         else
+           return yyerror ("Register or value mismatch");
+       }
+
+       | REG _PLUS_ASSIGN REG LPAREN BREV RPAREN
+       {
+         if (IS_IREG ($1) && IS_MREG ($3))
+           {
+             notethat ("dagMODim: iregs += mregs (opt_brev)\n");
+             /* i, m, op, br.  */
+             $$ = DAGMODIM (&$1, &$3, 0, 1);
+           }
+         else if (IS_PREG ($1) && IS_PREG ($3))
+           {
+             notethat ("PTR2op: pregs += pregs (BREV )\n");
+             $$ = PTR2OP (&$1, &$3, 5);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | REG _MINUS_ASSIGN REG
+       {
+         if (IS_IREG ($1) && IS_MREG ($3))
+           {
+             notethat ("dagMODim: iregs -= mregs\n");
+             $$ = DAGMODIM (&$1, &$3, 1, 0);
+           }
+         else if (IS_PREG ($1) && IS_PREG ($3))
+           {
+             notethat ("PTR2op: pregs -= pregs\n");
+             $$ = PTR2OP (&$1, &$3, 0);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | REG_A _PLUS_ASSIGN REG_A w32_or_nothing
+       {
+         if (!IS_A1 ($1) && IS_A1 ($3))
+           {
+             notethat ("dsp32alu: A0 += A1 (W32)\n");
+             $$ = DSP32ALU (11, 0, 0, 0, 0, 0, $4.r0, 0, 2);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | REG _PLUS_ASSIGN REG
+       {
+         if (IS_IREG ($1) && IS_MREG ($3))
+           {
+             notethat ("dagMODim: iregs += mregs\n");
+             $$ = DAGMODIM (&$1, &$3, 0, 0);
+           }
+         else
+           return yyerror ("iregs += mregs expected");
+       }
+
+       | REG _PLUS_ASSIGN expr
+       {
+         if (IS_IREG ($1))
+           {
+             if (EXPR_VALUE ($3) == 4)
+               {
+                 notethat ("dagMODik: iregs += 4\n");
+                 $$ = DAGMODIK (&$1, 2);
+               }
+             else if (EXPR_VALUE ($3) == 2)
+               {
+                 notethat ("dagMODik: iregs += 2\n");
+                 $$ = DAGMODIK (&$1, 0);
+               }
+             else
+               return yyerror ("iregs += [ 2 | 4 ");
+           }
+         else if (IS_PREG ($1) && IS_IMM ($3, 7))
+           {
+             notethat ("COMPI2opP: pregs += imm7\n");
+             $$ = COMPI2OPP (&$1, imm7 ($3), 1);
+           }
+         else if (IS_DREG ($1) && IS_IMM ($3, 7))
+           {
+             notethat ("COMPI2opD: dregs += imm7\n");
+             $$ = COMPI2OPD (&$1, imm7 ($3), 1);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | REG _STAR_ASSIGN REG
+       {
+         if (IS_DREG ($1) && IS_DREG ($3))
+           {
+             notethat ("ALU2op: dregs *= dregs\n");
+             $$ = ALU2OP (&$1, &$3, 3);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | SAA LPAREN REG COLON expr COMMA REG COLON expr RPAREN aligndir
+       {
+         if (!valid_dreg_pair (&$3, $5))
+           return yyerror ("Bad dreg pair");
+         else if (!valid_dreg_pair (&$7, $9))
+           return yyerror ("Bad dreg pair");
+         else
+           {
+             notethat ("dsp32alu: SAA (dregs_pair , dregs_pair ) (aligndir)\n");
+             $$ = DSP32ALU (18, 0, 0, 0, &$3, &$7, $11.r0, 0, 0);
+           }
+       }
+
+       | a_assign REG_A LPAREN S RPAREN COMMA a_assign REG_A LPAREN S RPAREN
+       {
+         if (REG_SAME ($1, $2) && REG_SAME ($7, $8) && !REG_SAME ($1, $7))
+           {
+             notethat ("dsp32alu: A1 = A1 (S) , A0 = A0 (S)\n");
+             $$ = DSP32ALU (8, 0, 0, 0, 0, 0, 1, 0, 2);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | REG ASSIGN LPAREN REG PLUS REG RPAREN LESS_LESS expr
+       {
+         if (IS_DREG ($1) && IS_DREG ($4) && IS_DREG ($6)
+             && REG_SAME ($1, $4))
+           {
+             if (EXPR_VALUE ($9) == 1)
+               {
+                 notethat ("ALU2op: dregs = (dregs + dregs) << 1\n");
+                 $$ = ALU2OP (&$1, &$6, 4);
+               }
+             else if (EXPR_VALUE ($9) == 2)
+               {
+                 notethat ("ALU2op: dregs = (dregs + dregs) << 2\n");
+                 $$ = ALU2OP (&$1, &$6, 5);
+               }
+             else
+               return yyerror ("Bad shift value");
+           }
+         else if (IS_PREG ($1) && IS_PREG ($4) && IS_PREG ($6)
+                  && REG_SAME ($1, $4))
+           {
+             if (EXPR_VALUE ($9) == 1)
+               {
+                 notethat ("PTR2op: pregs = (pregs + pregs) << 1\n");
+                 $$ = PTR2OP (&$1, &$6, 6);
+               }
+             else if (EXPR_VALUE ($9) == 2)
+               {
+                 notethat ("PTR2op: pregs = (pregs + pregs) << 2\n");
+                 $$ = PTR2OP (&$1, &$6, 7);
+               }
+             else
+               return yyerror ("Bad shift value");
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+                       
+/*  COMP3 CCFLAG.  */
+       | REG ASSIGN REG BAR REG
+       {
+         if (IS_DREG ($1) && IS_DREG ($3) && IS_DREG ($5))
+           {
+             notethat ("COMP3op: dregs = dregs | dregs\n");
+             $$ = COMP3OP (&$1, &$3, &$5, 3);
+           }
+         else
+           return yyerror ("Dregs expected");
+       }
+       | REG ASSIGN REG CARET REG
+       {
+         if (IS_DREG ($1) && IS_DREG ($3) && IS_DREG ($5))
+           {
+             notethat ("COMP3op: dregs = dregs ^ dregs\n");
+             $$ = COMP3OP (&$1, &$3, &$5, 4);
+           }
+         else
+           return yyerror ("Dregs expected");
+       }
+       | REG ASSIGN REG PLUS LPAREN REG LESS_LESS expr RPAREN
+       {
+         if (IS_PREG ($1) && IS_PREG ($3) && IS_PREG ($6))
+           {
+             if (EXPR_VALUE ($8) == 1)
+               {
+                 notethat ("COMP3op: pregs = pregs + (pregs << 1)\n");
+                 $$ = COMP3OP (&$1, &$3, &$6, 6);
+               }
+             else if (EXPR_VALUE ($8) == 2)
+               {
+                 notethat ("COMP3op: pregs = pregs + (pregs << 2)\n");
+                 $$ = COMP3OP (&$1, &$3, &$6, 7);
+               }
+             else
+                 return yyerror ("Bad shift value");
+           }
+         else
+           return yyerror ("Dregs expected");
+       }
+       | CCREG ASSIGN REG_A _ASSIGN_ASSIGN REG_A
+       {
+         if (!REG_SAME ($3, $5))
+           {
+             notethat ("CCflag: CC = A0 == A1\n");
+             $$ = CCFLAG (0, 0, 5, 0, 0);
+           }
+         else
+           return yyerror ("CC register expected");
+       }
+       | CCREG ASSIGN REG_A LESS_THAN REG_A
+       {
+         if (!REG_SAME ($3, $5))
+           {
+             notethat ("CCflag: CC = A0 < A1\n");
+             $$ = CCFLAG (0, 0, 6, 0, 0);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+       | CCREG ASSIGN REG LESS_THAN REG iu_or_nothing
+       {
+         if (REG_CLASS($3) == REG_CLASS($5))
+           {
+             notethat ("CCflag: CC = dpregs < dpregs\n");
+             $$ = CCFLAG (&$3, $5.regno & CODE_MASK, $6.r0, 0, IS_PREG ($3) ? 1 : 0);
+           }
+         else
+           return yyerror ("Compare only of same register class");
+       }
+       | CCREG ASSIGN REG LESS_THAN expr iu_or_nothing
+       {
+         if (($6.r0 == 1 && IS_IMM ($5, 3))
+             || ($6.r0 == 3 && IS_UIMM ($5, 3)))
+           {
+             notethat ("CCflag: CC = dpregs < (u)imm3\n");
+             $$ = CCFLAG (&$3, imm3 ($5), $6.r0, 1, IS_PREG ($3) ? 1 : 0);
+           }
+         else
+           return yyerror ("Bad constant value");
+       }
+       | CCREG ASSIGN REG _ASSIGN_ASSIGN REG
+       {
+         if (REG_CLASS($3) == REG_CLASS($5))
+           {
+             notethat ("CCflag: CC = dpregs == dpregs\n");
+             $$ = CCFLAG (&$3, $5.regno & CODE_MASK, 0, 0, IS_PREG ($3) ? 1 : 0);
+           } 
+       }
+       | CCREG ASSIGN REG _ASSIGN_ASSIGN expr
+       {
+         if (IS_IMM ($5, 3))
+           {
+             notethat ("CCflag: CC = dpregs == imm3\n");
+             $$ = CCFLAG (&$3, imm3 ($5), 0, 1, IS_PREG ($3) ? 1 : 0);
+           }
+         else
+           return yyerror ("Bad constant range");
+       }
+       | CCREG ASSIGN REG_A _LESS_THAN_ASSIGN REG_A
+       {
+         if (!REG_SAME ($3, $5))
+           {
+             notethat ("CCflag: CC = A0 <= A1\n");
+             $$ = CCFLAG (0, 0, 7, 0, 0);
+           }
+         else
+           return yyerror ("CC register expected");
+       }
+       | CCREG ASSIGN REG _LESS_THAN_ASSIGN REG iu_or_nothing
+       {
+         if (REG_CLASS($3) == REG_CLASS($5))
+           {
+             notethat ("CCflag: CC = pregs <= pregs (..)\n");
+             $$ = CCFLAG (&$3, $5.regno & CODE_MASK,
+                          1 + $6.r0, 0, IS_PREG ($3) ? 1 : 0);
+           }
+         else
+           return yyerror ("Compare only of same register class");
+       }
+       | CCREG ASSIGN REG _LESS_THAN_ASSIGN expr iu_or_nothing
+       {
+         if (($6.r0 == 1 && IS_IMM ($5, 3))
+             || ($6.r0 == 3 && IS_UIMM ($5, 3)))
+           {
+             if (IS_DREG ($3))
+               {
+                 notethat ("CCflag: CC = dregs <= (u)imm3\n");
+                 /*    x       y     opc     I     G   */
+                 $$ = CCFLAG (&$3, imm3 ($5), 1 + $6.r0, 1, 0);
+               }
+             else if (IS_PREG ($3))
+               {
+                 notethat ("CCflag: CC = pregs <= (u)imm3\n");
+                 /*    x       y     opc     I     G   */
+                 $$ = CCFLAG (&$3, imm3 ($5), 1 + $6.r0, 1, 1);
+               }
+             else
+               return yyerror ("Dreg or Preg expected");
+           }
+         else
+           return yyerror ("Bad constant value");
+       }
+
+       | REG ASSIGN REG AMPERSAND REG
+       {
+         if (IS_DREG ($1) && IS_DREG ($3) && IS_DREG ($5))
+           {
+             notethat ("COMP3op: dregs = dregs & dregs\n");
+             $$ = COMP3OP (&$1, &$3, &$5, 2);
+           }
+         else
+           return yyerror ("Dregs expected");
+       }
+
+       | ccstat
+       {
+         notethat ("CC2stat operation\n");
+         $$ = bfin_gen_cc2stat ($1.r0, $1.x0, $1.s0);
+       }
+
+       | REG ASSIGN REG
+       {
+         if (IS_ALLREG ($1) && IS_ALLREG ($3))
+           {
+             notethat ("REGMV: allregs = allregs\n");
+             $$ = bfin_gen_regmv (&$3, &$1);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | CCREG ASSIGN REG
+       {
+         if (IS_DREG ($3))
+           {
+             notethat ("CC2dreg: CC = dregs\n");
+             $$ = bfin_gen_cc2dreg (1, &$3);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | REG ASSIGN CCREG
+       {
+         if (IS_DREG ($1))
+           {
+             notethat ("CC2dreg: dregs = CC\n");
+             $$ = bfin_gen_cc2dreg (0, &$1);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | CCREG _ASSIGN_BANG CCREG
+       {
+         notethat ("CC2dreg: CC =! CC\n");
+         $$ = bfin_gen_cc2dreg (3, 0);
+       }
+                       
+/* DSPMULT.  */
+
+       | HALF_REG ASSIGN multiply_halfregs opt_mode
+       {
+         notethat ("dsp32mult: dregs_half = multiply_halfregs (opt_mode)\n");
+
+         if (!IS_H ($1) && $4.MM)
+           return yyerror ("(M) not allowed with MAC0");
+
+         if (IS_H ($1))
+           {
+             $$ = DSP32MULT (0, $4.MM, $4.mod, 1, 0,
+                             IS_H ($3.s0), IS_H ($3.s1), 0, 0,
+                             &$1, 0, &$3.s0, &$3.s1, 0);
+           }
+         else
+           {
+             $$ = DSP32MULT (0, 0, $4.mod, 0, 0,
+                             0, 0, IS_H ($3.s0), IS_H ($3.s1), 
+                             &$1, 0, &$3.s0, &$3.s1, 1);
+               }       
+       }
+
+       | REG ASSIGN multiply_halfregs opt_mode 
+       {
+         /* Odd registers can use (M).  */
+         if (!IS_DREG ($1))
+           return yyerror ("Dreg expected");
+
+         if (!IS_EVEN ($1))
+           {
+             notethat ("dsp32mult: dregs = multiply_halfregs (opt_mode)\n");
+
+             $$ = DSP32MULT (0, $4.MM, $4.mod, 1, 1,
+                             IS_H ($3.s0), IS_H ($3.s1), 0, 0,
+                             &$1, 0, &$3.s0, &$3.s1, 0);
+           }
+         else if ($4.MM == 0)
+           {
+             notethat ("dsp32mult: dregs = multiply_halfregs opt_mode\n");
+             $$ = DSP32MULT (0, 0, $4.mod, 0, 1,
+                             0, 0, IS_H ($3.s0), IS_H ($3.s1), 
+                             &$1,  0, &$3.s0, &$3.s1, 1);
+           }
+         else
+           return yyerror ("Register or mode mismatch");
+       }
+
+       | HALF_REG ASSIGN multiply_halfregs opt_mode COMMA
+          HALF_REG ASSIGN multiply_halfregs opt_mode
+       {
+         if (!IS_DREG ($1) || !IS_DREG ($6)) 
+           return yyerror ("Dregs expected");
+
+         if (check_multiply_halfregs (&$3, &$8) < 0)
+           return -1;
+
+         if (IS_H ($1) && !IS_H ($6))
+           {
+             notethat ("dsp32mult: dregs_hi = multiply_halfregs mxd_mod, "
+                      "dregs_lo = multiply_halfregs opt_mode\n");
+             $$ = DSP32MULT (0, $4.MM, $9.mod, 1, 0,
+                             IS_H ($3.s0), IS_H ($3.s1), IS_H ($8.s0), IS_H ($8.s1),
+                             &$1, 0, &$3.s0, &$3.s1, 1);
+           }
+         else if (!IS_H ($1) && IS_H ($6) && $4.MM == 0)
+           {
+             $$ = DSP32MULT (0, $9.MM, $9.mod, 1, 0,
+                             IS_H ($8.s0), IS_H ($8.s1), IS_H ($3.s0), IS_H ($3.s1),
+                             &$1, 0, &$3.s0, &$3.s1, 1);
+           }
+         else
+           return yyerror ("Multfunc Register or mode mismatch");
+       }
+
+       | REG ASSIGN multiply_halfregs opt_mode COMMA REG ASSIGN multiply_halfregs opt_mode 
+       {
+         if (!IS_DREG ($1) || !IS_DREG ($6)) 
+           return yyerror ("Dregs expected");
+
+         if (check_multiply_halfregs (&$3, &$8) < 0)
+           return -1;
+
+         notethat ("dsp32mult: dregs = multiply_halfregs mxd_mod, "
+                  "dregs = multiply_halfregs opt_mode\n");
+         if (IS_EVEN ($1))
+           {
+             if ($6.regno - $1.regno != 1 || $4.MM != 0)
+               return yyerror ("Dest registers or mode mismatch");
+
+             /*   op1       MM      mmod  */
+             $$ = DSP32MULT (0, 0, $9.mod, 1, 1,
+                             IS_H ($8.s0), IS_H ($8.s1), IS_H ($3.s0), IS_H ($3.s1),
+                             &$1, 0, &$3.s0, &$3.s1, 1);
+             
+           }
+         else
+           {
+             if ($1.regno - $6.regno != 1)
+               return yyerror ("Dest registers mismatch");
+             
+             $$ = DSP32MULT (0, $9.MM, $9.mod, 1, 1,
+                             IS_H ($3.s0), IS_H ($3.s1), IS_H ($8.s0), IS_H ($8.s1),
+                             &$1, 0, &$3.s0, &$3.s1, 1);
+           }
+       }
+
+\f
+/* SHIFTs.  */
+       | a_assign ASHIFT REG_A BY HALF_REG
+       {
+         if (!REG_SAME ($1, $3))
+           return yyerror ("Aregs must be same");
+
+         if (IS_DREG ($5) && !IS_H ($5))
+           {
+             notethat ("dsp32shift: A0 = ASHIFT A0 BY dregs_lo\n");
+             $$ = DSP32SHIFT (3, 0, &$5, 0, 0, IS_A1 ($1));
+           }
+         else
+           return yyerror ("Dregs expected");
+       }
+
+       | HALF_REG ASSIGN ASHIFT HALF_REG BY HALF_REG smod
+       {
+         if (IS_DREG ($6) && !IS_H ($6))
+           {
+             notethat ("dsp32shift: dregs_half = ASHIFT dregs_half BY dregs_lo\n");
+             $$ = DSP32SHIFT (0, &$1, &$6, &$4, $7.s0, HL2 ($1, $4));
+           }
+         else
+           return yyerror ("Dregs expected");
+       }
+
+       | a_assign REG_A LESS_LESS expr
+       {
+         if (!REG_SAME ($1, $2))
+           return yyerror ("Aregs must be same");
+
+         if (IS_UIMM ($4, 5))
+           {
+             notethat ("dsp32shiftimm: A0 = A0 << uimm5\n");
+             $$ = DSP32SHIFTIMM (3, 0, imm5 ($4), 0, 0, IS_A1 ($1));
+           }
+         else
+           return yyerror ("Bad shift value");
+       }
+
+       | REG ASSIGN REG LESS_LESS expr vsmod
+       {
+         if (IS_DREG ($1) && IS_DREG ($3) && IS_UIMM ($5, 5))
+           {
+             if ($6.r0)
+               {
+                 /*  Vector?  */
+                 notethat ("dsp32shiftimm: dregs = dregs << expr (V, .)\n");
+                 $$ = DSP32SHIFTIMM (1, &$1, imm4 ($5), &$3, $6.s0 ? 1 : 2, 0);
+               }
+             else
+               {
+                 notethat ("dsp32shiftimm: dregs =  dregs << uimm5 (.)\n");
+                 $$ = DSP32SHIFTIMM (2, &$1, imm6 ($5), &$3, $6.s0 ? 1 : 2, 0);
+               }
+           }
+         else if ($6.s0 == 0 && IS_PREG ($1) && IS_PREG ($3))
+           {
+             if (EXPR_VALUE ($5) == 2)
+               {
+                 notethat ("PTR2op: pregs = pregs << 2\n");
+                 $$ = PTR2OP (&$1, &$3, 1);
+               }
+             else if (EXPR_VALUE ($5) == 1)
+               {
+                 notethat ("COMP3op: pregs = pregs << 1\n");
+                 $$ = COMP3OP (&$1, &$3, &$3, 5);
+               }
+             else
+               return yyerror ("Bad shift value");
+           }
+         else
+           return yyerror ("Bad shift value or register");
+       }
+       | HALF_REG ASSIGN HALF_REG LESS_LESS expr
+       {
+         if (IS_UIMM ($5, 4))
+           {
+             notethat ("dsp32shiftimm: dregs_half = dregs_half << uimm4\n");
+             $$ = DSP32SHIFTIMM (0x0, &$1, imm5 ($5), &$3, 2, HL2 ($1, $3));
+           }
+         else
+           return yyerror ("Bad shift value");
+       }
+       | HALF_REG ASSIGN HALF_REG LESS_LESS expr smod 
+       {
+         if (IS_UIMM ($5, 4))
+           {
+             notethat ("dsp32shiftimm: dregs_half = dregs_half << uimm4\n");
+             $$ = DSP32SHIFTIMM (0x0, &$1, imm5 ($5), &$3, $6.s0, HL2 ($1, $3));
+           }
+         else
+           return yyerror ("Bad shift value");
+       }
+       | REG ASSIGN ASHIFT REG BY HALF_REG vsmod
+       {
+         int op;
+
+         if (IS_DREG ($1) && IS_DREG ($4) && IS_DREG ($6) && !IS_H ($6))
+           {
+             if ($7.r0)
+               {
+                 op = 1;
+                 notethat ("dsp32shift: dregs = ASHIFT dregs BY "
+                          "dregs_lo (V, .)\n");
+               }
+             else
+               {
+                 
+                 op = 2;
+                 notethat ("dsp32shift: dregs = ASHIFT dregs BY dregs_lo (.)\n");
+               }
+             $$ = DSP32SHIFT (op, &$1, &$6, &$4, $7.s0, 0);
+           }
+         else
+           return yyerror ("Dregs expected");
+       }
+
+/*  EXPADJ.  */
+       | HALF_REG ASSIGN EXPADJ LPAREN REG COMMA HALF_REG RPAREN vmod
+       {
+         if (IS_DREG_L ($1) && IS_DREG_L ($5) && IS_DREG_L ($7))
+           {
+             notethat ("dsp32shift: dregs_lo = EXPADJ (dregs , dregs_lo )\n");
+             $$ = DSP32SHIFT (7, &$1, &$7, &$5, $9.r0, 0);
+           }
+         else
+           return yyerror ("Bad shift value or register");
+       }
+
+
+       | HALF_REG ASSIGN EXPADJ LPAREN HALF_REG COMMA HALF_REG RPAREN
+       {
+         if (IS_DREG_L ($1) && IS_DREG_L ($5) && IS_DREG_L ($7))
+           {
+             notethat ("dsp32shift: dregs_lo = EXPADJ (dregs_lo, dregs_lo)\n");
+             $$ = DSP32SHIFT (7, &$1, &$7, &$5, 2, 0);
+           }
+         else if (IS_DREG_L ($1) && IS_DREG_H ($5) && IS_DREG_L ($7))
+           {
+             notethat ("dsp32shift: dregs_lo = EXPADJ (dregs_hi, dregs_lo)\n");
+             $$ = DSP32SHIFT (7, &$1, &$7, &$5, 3, 0);
+           }
+         else
+           return yyerror ("Bad shift value or register");
+       }
+
+/* DEPOSIT.  */
+
+       | REG ASSIGN DEPOSIT LPAREN REG COMMA REG RPAREN
+       {
+         if (IS_DREG ($1) && IS_DREG ($5) && IS_DREG ($7))
+           {
+             notethat ("dsp32shift: dregs = DEPOSIT (dregs , dregs )\n");
+             $$ = DSP32SHIFT (10, &$1, &$7, &$5, 2, 0);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | REG ASSIGN DEPOSIT LPAREN REG COMMA REG RPAREN LPAREN X RPAREN
+       {
+         if (IS_DREG ($1) && IS_DREG ($5) && IS_DREG ($7))
+           {
+             notethat ("dsp32shift: dregs = DEPOSIT (dregs , dregs ) (X)\n");
+             $$ = DSP32SHIFT (10, &$1, &$7, &$5, 3, 0);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | REG ASSIGN EXTRACT LPAREN REG COMMA HALF_REG RPAREN xpmod 
+       {
+         if (IS_DREG ($1) && IS_DREG ($5) && IS_DREG_L ($7))
+           {
+             notethat ("dsp32shift: dregs = EXTRACT (dregs, dregs_lo ) (.)\n");
+             $$ = DSP32SHIFT (10, &$1, &$7, &$5, $9.r0, 0);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | a_assign REG_A _GREATER_GREATER_GREATER expr
+       {
+         if (!REG_SAME ($1, $2))
+           return yyerror ("Aregs must be same");
+
+         if (IS_UIMM ($4, 5))
+           {
+             notethat ("dsp32shiftimm: Ax = Ax >>> uimm5\n");
+             $$ = DSP32SHIFTIMM (3, 0, -imm6 ($4), 0, 0, IS_A1 ($1));
+           }
+         else
+           return yyerror ("Shift value range error");
+       }
+       | a_assign LSHIFT REG_A BY HALF_REG
+       {
+         if (REG_SAME ($1, $3) && IS_DREG_L ($5))
+           {
+             notethat ("dsp32shift: Ax = LSHIFT Ax BY dregs_lo\n");
+             $$ = DSP32SHIFT (3, 0, &$5, 0, 1, IS_A1 ($1));
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | HALF_REG ASSIGN LSHIFT HALF_REG BY HALF_REG
+       {
+         if (IS_DREG ($1) && IS_DREG ($4) && IS_DREG_L ($6))
+           {
+             notethat ("dsp32shift: dregs_lo = LSHIFT dregs_hi BY dregs_lo\n");
+             $$ = DSP32SHIFT (0, &$1, &$6, &$4, 2, HL2 ($1, $4));
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | REG ASSIGN LSHIFT REG BY HALF_REG vmod
+       {
+         if (IS_DREG ($1) && IS_DREG ($4) && IS_DREG_L ($6))
+           {
+             notethat ("dsp32shift: dregs = LSHIFT dregs BY dregs_lo (V )\n");
+             $$ = DSP32SHIFT ($7.r0 ? 1: 2, &$1, &$6, &$4, 2, 0);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | REG ASSIGN SHIFT REG BY HALF_REG
+       {
+         if (IS_DREG ($1) && IS_DREG ($4) && IS_DREG_L ($6))
+           {
+             notethat ("dsp32shift: dregs = SHIFT dregs BY dregs_lo\n");
+             $$ = DSP32SHIFT (2, &$1, &$6, &$4, 2, 0);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | a_assign REG_A GREATER_GREATER expr
+       {
+         if (REG_SAME ($1, $2) && IS_IMM ($4, 6) >= 0)
+           {
+             notethat ("dsp32shiftimm: Ax = Ax >> imm6\n");
+             $$ = DSP32SHIFTIMM (3, 0, -imm6 ($4), 0, 1, IS_A1 ($1));
+           }
+         else
+           return yyerror ("Accu register expected");
+       }
+
+       | REG ASSIGN REG GREATER_GREATER expr vmod
+       {
+         if ($6.r0 == 1)
+           {
+             if (IS_DREG ($1) && IS_DREG ($3) && IS_UIMM ($5, 5))
+               {
+                 notethat ("dsp32shiftimm: dregs = dregs >> uimm5 (V)\n");
+                 $$ = DSP32SHIFTIMM (1, &$1, -uimm5 ($5), &$3, 2, 0);
+               }
+             else
+               return yyerror ("Register mismatch");
+           }
+         else
+           {
+             if (IS_DREG ($1) && IS_DREG ($3) && IS_UIMM ($5, 5))
+               {
+                 notethat ("dsp32shiftimm: dregs = dregs >> uimm5\n");
+                 $$ = DSP32SHIFTIMM (2, &$1, -imm6 ($5), &$3, 2, 0);
+               }
+             else if (IS_PREG ($1) && IS_PREG ($3) && EXPR_VALUE ($5) == 2)
+               {
+                 notethat ("PTR2op: pregs = pregs >> 2\n");
+                 $$ = PTR2OP (&$1, &$3, 3);
+               }
+             else if (IS_PREG ($1) && IS_PREG ($3) && EXPR_VALUE ($5) == 1)
+               {
+                 notethat ("PTR2op: pregs = pregs >> 1\n");
+                 $$ = PTR2OP (&$1, &$3, 4);
+               }
+             else
+               return yyerror ("Register mismatch");
+           }
+       }
+       | HALF_REG ASSIGN HALF_REG GREATER_GREATER expr
+       {
+         if (IS_UIMM ($5, 5))
+           {
+             notethat ("dsp32shiftimm:  dregs_half =  dregs_half >> uimm5\n");
+             $$ = DSP32SHIFTIMM (0, &$1, -uimm5 ($5), &$3, 2, HL2 ($1, $3));
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+       | HALF_REG ASSIGN HALF_REG _GREATER_GREATER_GREATER expr smod
+       {
+         if (IS_UIMM ($5, 5))
+           {
+             notethat ("dsp32shiftimm: dregs_half = dregs_half >>> uimm5\n");
+             $$ = DSP32SHIFTIMM (0, &$1, -uimm5 ($5), &$3,
+                                 $6.s0, HL2 ($1, $3));
+           }
+         else
+           return yyerror ("Register or modifier mismatch");
+       }
+
+
+       | REG ASSIGN REG _GREATER_GREATER_GREATER expr vsmod
+       {
+         if (IS_DREG ($1) && IS_DREG ($3) && IS_UIMM ($5, 5))
+           {
+             if ($6.r0)
+               {
+                 /* Vector?  */
+                 notethat ("dsp32shiftimm: dregs  =  dregs >>> uimm5 (V, .)\n");
+                 $$ = DSP32SHIFTIMM (1, &$1, -uimm5 ($5), &$3, $6.s0, 0);
+               }
+             else
+               {
+                 notethat ("dsp32shiftimm: dregs  =  dregs >>> uimm5 (.)\n");
+                 $$ = DSP32SHIFTIMM (2, &$1, -uimm5 ($5), &$3, $6.s0, 0);
+               }
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | HALF_REG ASSIGN ONES REG
+       {
+         if (IS_DREG_L ($1) && IS_DREG ($4))
+           {
+             notethat ("dsp32shift: dregs_lo = ONES dregs\n");
+             $$ = DSP32SHIFT (6, &$1, 0, &$4, 3, 0);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | REG ASSIGN PACK LPAREN HALF_REG COMMA HALF_REG RPAREN
+       {
+         if (IS_DREG ($1) && IS_DREG ($5) && IS_DREG ($7))
+           {
+             notethat ("dsp32shift: dregs = PACK (dregs_hi , dregs_hi )\n");
+             $$ = DSP32SHIFT (4, &$1, &$7, &$5, HL2 ($5, $7), 0);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | HALF_REG ASSIGN CCREG ASSIGN BXORSHIFT LPAREN REG_A COMMA REG RPAREN 
+       {
+         if (IS_DREG ($1)
+             && $7.regno == REG_A0
+             && IS_DREG ($9) && !IS_H ($1) && !IS_A1 ($7))
+           {
+             notethat ("dsp32shift: dregs_lo = CC = BXORSHIFT (A0 , dregs )\n");
+             $$ = DSP32SHIFT (11, &$1, &$9, 0, 0, 0);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | HALF_REG ASSIGN CCREG ASSIGN BXOR LPAREN REG_A COMMA REG RPAREN
+       {
+         if (IS_DREG ($1)
+             && $7.regno == REG_A0
+             && IS_DREG ($9) && !IS_H ($1) && !IS_A1 ($7))
+           {
+             notethat ("dsp32shift: dregs_lo = CC = BXOR (A0 , dregs)\n");
+             $$ = DSP32SHIFT (11, &$1, &$9, 0, 1, 0);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | HALF_REG ASSIGN CCREG ASSIGN BXOR LPAREN REG_A COMMA REG_A COMMA CCREG RPAREN
+       {
+         if (IS_DREG ($1) && !IS_H ($1) && !REG_SAME ($7, $9))
+           {
+             notethat ("dsp32shift: dregs_lo = CC = BXOR (A0 , A1 , CC)\n");
+             $$ = DSP32SHIFT (12, &$1, 0, 0, 1, 0);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | a_assign ROT REG_A BY HALF_REG
+       {
+         if (REG_SAME ($1, $3) && IS_DREG_L ($5))
+           {
+             notethat ("dsp32shift: Ax = ROT Ax BY dregs_lo\n");
+             $$ = DSP32SHIFT (3, 0, &$5, 0, 2, IS_A1 ($1));
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | REG ASSIGN ROT REG BY HALF_REG
+       {
+         if (IS_DREG ($1) && IS_DREG ($4) && IS_DREG_L ($6))
+           {
+             notethat ("dsp32shift: dregs = ROT dregs BY dregs_lo\n");
+             $$ = DSP32SHIFT (2, &$1, &$6, &$4, 3, 0);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | a_assign ROT REG_A BY expr 
+       {
+         if (IS_IMM ($5, 6))
+           {
+             notethat ("dsp32shiftimm: An = ROT An BY imm6\n");
+             $$ = DSP32SHIFTIMM (3, 0, imm6 ($5), 0, 2, IS_A1 ($1));
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | REG ASSIGN ROT REG BY expr 
+       {
+         if (IS_DREG ($1) && IS_DREG ($4) && IS_IMM ($6, 6))
+           {
+             $$ = DSP32SHIFTIMM (2, &$1, imm6 ($6), &$4, 3, IS_A1 ($1));
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | HALF_REG ASSIGN SIGNBITS REG_A
+       {
+         if (IS_DREG_L ($1))
+           {
+             notethat ("dsp32shift: dregs_lo = SIGNBITS An\n");
+             $$ = DSP32SHIFT (6, &$1, 0, 0, IS_A1 ($4), 0);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | HALF_REG ASSIGN SIGNBITS REG
+       {
+         if (IS_DREG_L ($1) && IS_DREG ($4))
+           {
+             notethat ("dsp32shift: dregs_lo = SIGNBITS dregs\n");
+             $$ = DSP32SHIFT (5, &$1, 0, &$4, 0, 0);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | HALF_REG ASSIGN SIGNBITS HALF_REG
+       {
+         if (IS_DREG_L ($1))
+           {
+             notethat ("dsp32shift: dregs_lo = SIGNBITS dregs_lo\n");
+             $$ = DSP32SHIFT (5, &$1, 0, &$4, 1 + IS_H ($4), 0);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+       
+       /* The ASR bit is just inverted here. */
+       | HALF_REG ASSIGN VIT_MAX LPAREN REG RPAREN asr_asl 
+       {
+         if (IS_DREG_L ($1) && IS_DREG ($5))
+           {
+             notethat ("dsp32shift: dregs_lo = VIT_MAX (dregs) (..)\n");
+             $$ = DSP32SHIFT (9, &$1, 0, &$5, ($7.r0 ? 0 : 1), 0);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | REG ASSIGN VIT_MAX LPAREN REG COMMA REG RPAREN asr_asl 
+       {
+         if (IS_DREG ($1) && IS_DREG ($5) && IS_DREG ($7))
+           {
+             notethat ("dsp32shift: dregs = VIT_MAX (dregs, dregs) (ASR)\n");
+             $$ = DSP32SHIFT (9, &$1, &$7, &$5, 2 | ($9.r0 ? 0 : 1), 0);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | BITMUX LPAREN REG COMMA REG COMMA REG_A RPAREN asr_asl
+       {
+         if (IS_DREG ($3) && IS_DREG ($5) && !IS_A1 ($7))
+           {
+             notethat ("dsp32shift: BITMUX (dregs , dregs , A0) (ASR)\n");
+             $$ = DSP32SHIFT (8, 0, &$3, &$5, $9.r0, 0);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | a_assign BXORSHIFT LPAREN REG_A COMMA REG_A COMMA CCREG RPAREN
+       {
+         if (!IS_A1 ($1) && !IS_A1 ($4) && IS_A1 ($6))
+           {
+             notethat ("dsp32shift: A0 = BXORSHIFT (A0 , A1 , CC )\n");
+             $$ = DSP32SHIFT (12, 0, 0, 0, 0, 0);
+           }
+         else
+           return yyerror ("Dregs expected");
+       }
+
+
+/* LOGI2op:    BITCLR (dregs, uimm5).  */
+       | BITCLR LPAREN REG COMMA expr RPAREN
+       {
+         if (IS_DREG ($3) && IS_UIMM ($5, 5))
+           {
+             notethat ("LOGI2op: BITCLR (dregs , uimm5 )\n");
+             $$ = LOGI2OP ($3, uimm5 ($5), 4);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+/* LOGI2op:    BITSET (dregs, uimm5).  */
+       | BITSET LPAREN REG COMMA expr RPAREN
+       {
+         if (IS_DREG ($3) && IS_UIMM ($5, 5))
+           {
+             notethat ("LOGI2op: BITCLR (dregs , uimm5 )\n");
+             $$ = LOGI2OP ($3, uimm5 ($5), 2);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+/* LOGI2op:    BITTGL (dregs, uimm5).  */
+       | BITTGL LPAREN REG COMMA expr RPAREN
+       {
+         if (IS_DREG ($3) && IS_UIMM ($5, 5))
+           {
+             notethat ("LOGI2op: BITCLR (dregs , uimm5 )\n");
+             $$ = LOGI2OP ($3, uimm5 ($5), 3);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | CCREG _ASSIGN_BANG BITTST LPAREN REG COMMA expr RPAREN
+       {
+         if (IS_DREG ($5) && IS_UIMM ($7, 5))
+           {
+             notethat ("LOGI2op: CC =! BITTST (dregs , uimm5 )\n");
+             $$ = LOGI2OP ($5, uimm5 ($7), 0);
+           }
+         else
+           return yyerror ("Register mismatch or value error");
+       }
+
+       | CCREG ASSIGN BITTST LPAREN REG COMMA expr RPAREN
+       {
+         if (IS_DREG ($5) && IS_UIMM ($7, 5))
+           {
+             notethat ("LOGI2op: CC = BITTST (dregs , uimm5 )\n");
+             $$ = LOGI2OP ($5, uimm5 ($7), 1);
+           }
+         else
+           return yyerror ("Register mismatch or value error");
+       }
+
+       | IF BANG CCREG REG ASSIGN REG
+       {
+         if ((IS_DREG ($4) || IS_PREG ($4))
+             && (IS_DREG ($6) || IS_PREG ($6)))
+           {
+             notethat ("ccMV: IF ! CC gregs = gregs\n");
+             $$ = CCMV (&$6, &$4, 0);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | IF CCREG REG ASSIGN REG
+       {
+         if ((IS_DREG ($5) || IS_PREG ($5))
+             && (IS_DREG ($3) || IS_PREG ($3)))
+           {
+             notethat ("ccMV: IF CC gregs = gregs\n");
+             $$ = CCMV (&$5, &$3, 1);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+       | IF BANG CCREG JUMP expr
+       {
+         if (IS_PCREL10 ($5))
+           {
+             notethat ("BRCC: IF !CC JUMP  pcrel11m2\n");
+             $$ = BRCC (0, 0, $5);
+           }
+         else
+           return yyerror ("Bad jump offset");
+       }
+
+       | IF BANG CCREG JUMP expr LPAREN BP RPAREN
+       {
+         if (IS_PCREL10 ($5))
+           {
+             notethat ("BRCC: IF !CC JUMP  pcrel11m2\n");
+             $$ = BRCC (0, 1, $5);
+           }
+         else
+           return yyerror ("Bad jump offset");
+       }
+
+       | IF CCREG JUMP expr
+       {
+         if (IS_PCREL10 ($4))
+           {
+             notethat ("BRCC: IF CC JUMP  pcrel11m2\n");
+             $$ = BRCC (1, 0, $4);
+           }
+         else
+           return yyerror ("Bad jump offset");
+       }
+
+       | IF CCREG JUMP expr LPAREN BP RPAREN
+       {
+         if (IS_PCREL10 ($4))
+           {
+             notethat ("BRCC: IF !CC JUMP  pcrel11m2\n");
+             $$ = BRCC (1, 1, $4);
+           }
+         else
+           return yyerror ("Bad jump offset");
+       }
+       | NOP
+       {
+         notethat ("ProgCtrl: NOP\n");
+         $$ = PROGCTRL (0, 0);
+       }
+
+       | RTS
+       {
+         notethat ("ProgCtrl: RTS\n");
+         $$ = PROGCTRL (1, 0);
+       }
+
+       | RTI
+       {
+         notethat ("ProgCtrl: RTI\n");
+         $$ = PROGCTRL (1, 1);
+       }
+
+       | RTX
+       {
+         notethat ("ProgCtrl: RTX\n");
+         $$ = PROGCTRL (1, 2);
+       }
+
+       | RTN
+       {
+         notethat ("ProgCtrl: RTN\n");
+         $$ = PROGCTRL (1, 3);
+       }
+
+       | RTE
+       {
+         notethat ("ProgCtrl: RTE\n");
+         $$ = PROGCTRL (1, 4);
+       }
+
+       | IDLE
+       {
+         notethat ("ProgCtrl: IDLE\n");
+         $$ = PROGCTRL (2, 0);
+       }
+
+       | CSYNC
+       {
+         notethat ("ProgCtrl: CSYNC\n");
+         $$ = PROGCTRL (2, 3);
+       }
+
+       | SSYNC
+       {
+         notethat ("ProgCtrl: SSYNC\n");
+         $$ = PROGCTRL (2, 4);
+       }
+
+       | EMUEXCPT
+       {
+         notethat ("ProgCtrl: EMUEXCPT\n");
+         $$ = PROGCTRL (2, 5);
+       }
+
+       | CLI REG
+       {
+         if (IS_DREG ($2))
+           {
+             notethat ("ProgCtrl: CLI dregs\n");
+             $$ = PROGCTRL (3, $2.regno & CODE_MASK);
+           }
+         else
+           return yyerror ("Dreg expected for CLI");
+       }
+
+       | STI REG
+       {
+         if (IS_DREG ($2))
+           {
+             notethat ("ProgCtrl: STI dregs\n");
+             $$ = PROGCTRL (4, $2.regno & CODE_MASK);
+           }
+         else
+           return yyerror ("Dreg expected for STI");
+       }
+
+       | JUMP LPAREN REG RPAREN
+       {
+         if (IS_PREG ($3))
+           {
+             notethat ("ProgCtrl: JUMP (pregs )\n");
+             $$ = PROGCTRL (5, $3.regno & CODE_MASK);
+           }
+         else
+           return yyerror ("Bad register for indirect jump");
+       }
+
+       | CALL LPAREN REG RPAREN
+       {
+         if (IS_PREG ($3))
+           {
+             notethat ("ProgCtrl: CALL (pregs )\n");
+             $$ = PROGCTRL (6, $3.regno & CODE_MASK);
+           }
+         else
+           return yyerror ("Bad register for indirect call");
+       }
+
+       | CALL LPAREN PC PLUS REG RPAREN
+       {
+         if (IS_PREG ($5))
+           {
+             notethat ("ProgCtrl: CALL (PC + pregs )\n");
+             $$ = PROGCTRL (7, $5.regno & CODE_MASK);
+           }
+         else
+           return yyerror ("Bad register for indirect call");
+       }
+
+       | JUMP LPAREN PC PLUS REG RPAREN
+       {
+         if (IS_PREG ($5))
+           {
+             notethat ("ProgCtrl: JUMP (PC + pregs )\n");
+             $$ = PROGCTRL (8, $5.regno & CODE_MASK);
+           }
+         else
+           return yyerror ("Bad register for indirect jump");
+       }
+
+       | RAISE expr
+       {
+         if (IS_UIMM ($2, 4))
+           {
+             notethat ("ProgCtrl: RAISE uimm4\n");
+             $$ = PROGCTRL (9, uimm4 ($2));
+           }
+         else
+           return yyerror ("Bad value for RAISE");
+       }
+
+       | EXCPT expr
+       {
+               notethat ("ProgCtrl: EMUEXCPT\n");
+               $$ = PROGCTRL (10, uimm4 ($2));
+       }
+
+       | TESTSET LPAREN REG RPAREN
+       {
+         if (IS_PREG ($3))
+           {
+             notethat ("ProgCtrl: TESTSET (pregs )\n");
+             $$ = PROGCTRL (11, $3.regno & CODE_MASK);
+           }
+         else
+           return yyerror ("Preg expected");
+       }
+
+       | JUMP expr
+       {
+         if (IS_PCREL12 ($2))
+           {
+             notethat ("UJUMP: JUMP pcrel12\n");
+             $$ = UJUMP ($2);
+           }
+         else
+           return yyerror ("Bad value for relative jump");
+       }
+
+       | JUMP_DOT_S expr
+       {
+         if (IS_PCREL12 ($2))
+           {
+             notethat ("UJUMP: JUMP_DOT_S pcrel12\n");
+             $$ = UJUMP($2);
+           }
+         else
+           return yyerror ("Bad value for relative jump");
+       }
+
+       | JUMP_DOT_L expr
+       {
+         if (IS_PCREL24 ($2))
+           {
+             notethat ("CALLa: jump.l pcrel24\n");
+             $$ = CALLA ($2, 0);
+           }
+         else
+           return yyerror ("Bad value for long jump");
+       }
+
+       | JUMP_DOT_L pltpc
+       {
+         if (IS_PCREL24 ($2))
+           {
+             notethat ("CALLa: jump.l pcrel24\n");
+             $$ = CALLA ($2, 2);
+           }
+         else
+           return yyerror ("Bad value for long jump");
+       }
+
+       | CALL expr
+       {
+         if (IS_PCREL24 ($2))
+           {
+             notethat ("CALLa: CALL pcrel25m2\n");
+             $$ = CALLA ($2, 1);
+           }
+         else
+           return yyerror ("Bad call address");
+       }
+       | CALL pltpc
+       {
+         if (IS_PCREL24 ($2))
+           {
+             notethat ("CALLa: CALL pcrel25m2\n");
+             $$ = CALLA ($2, 2);
+           }
+         else
+           return yyerror ("Bad call address");
+       }
+
+/* ALU2ops.  */
+/* ALU2op:     DIVQ (dregs, dregs).  */
+       | DIVQ LPAREN REG COMMA REG RPAREN
+       {
+         if (IS_DREG ($3) && IS_DREG ($5))
+           $$ = ALU2OP (&$3, &$5, 8);
+         else
+           return yyerror ("Bad registers for DIVQ");
+       }
+
+       | DIVS LPAREN REG COMMA REG RPAREN
+       {
+         if (IS_DREG ($3) && IS_DREG ($5))
+           $$ = ALU2OP (&$3, &$5, 9);
+         else
+           return yyerror ("Bad registers for DIVS");
+       }
+
+       | REG ASSIGN MINUS REG vsmod
+       {
+         if (IS_DREG ($1) && IS_DREG ($4))
+           {
+             if ($5.r0 == 0 && $5.s0 == 0 && $5.aop == 0)
+               {
+                 notethat ("ALU2op: dregs = - dregs\n");
+                 $$ = ALU2OP (&$1, &$4, 14);
+               }
+             else if ($5.r0 == 1 && $5.s0 == 0 && $5.aop == 3)
+               {
+                 notethat ("dsp32alu: dregs = - dregs (.)\n");
+                 $$ = DSP32ALU (15, 0, 0, &$1, &$4, 0, $5.s0, 0, 3);
+               }
+             else
+               {
+                 notethat ("dsp32alu: dregs = - dregs (.)\n");
+                 $$ = DSP32ALU (7, 0, 0, &$1, &$4, 0, $5.s0, 0, 3);
+               }
+           }
+         else
+           return yyerror ("Dregs expected");
+       }
+
+       | REG ASSIGN TILDA REG
+       {
+         if (IS_DREG ($1) && IS_DREG ($4))
+           {
+             notethat ("ALU2op: dregs = ~dregs\n");
+             $$ = ALU2OP (&$1, &$4, 15);
+           }
+         else
+           return yyerror ("Dregs expected");
+       }
+
+       | REG _GREATER_GREATER_ASSIGN REG
+       {
+         if (IS_DREG ($1) && IS_DREG ($3))
+           {
+             notethat ("ALU2op: dregs >>= dregs\n");
+             $$ = ALU2OP (&$1, &$3, 1);
+           }
+         else
+           return yyerror ("Dregs expected");
+       }
+
+       | REG _GREATER_GREATER_ASSIGN expr
+       {
+         if (IS_DREG ($1) && IS_UIMM ($3, 5))
+           {
+             notethat ("LOGI2op: dregs >>= uimm5\n");
+             $$ = LOGI2OP ($1, uimm5 ($3), 6);
+           }
+         else
+           return yyerror ("Dregs expected or value error");
+       }
+
+       | REG _GREATER_GREATER_GREATER_THAN_ASSIGN REG
+       {
+         if (IS_DREG ($1) && IS_DREG ($3))
+           {
+             notethat ("ALU2op: dregs >>>= dregs\n");
+             $$ = ALU2OP (&$1, &$3, 0);
+           }
+         else
+           return yyerror ("Dregs expected");
+       }
+
+       | REG _LESS_LESS_ASSIGN REG
+       {
+         if (IS_DREG ($1) && IS_DREG ($3))
+           {
+             notethat ("ALU2op: dregs <<= dregs\n");
+             $$ = ALU2OP (&$1, &$3, 2);
+           }
+         else
+           return yyerror ("Dregs expected");
+       }
+
+       | REG _LESS_LESS_ASSIGN expr
+       {
+         if (IS_DREG ($1) && IS_UIMM ($3, 5))
+           {
+             notethat ("LOGI2op: dregs <<= uimm5\n");
+             $$ = LOGI2OP ($1, uimm5 ($3), 7);
+           }
+         else
+           return yyerror ("Dregs expected or const value error");
+       }
+
+
+       | REG _GREATER_GREATER_GREATER_THAN_ASSIGN expr
+       {
+         if (IS_DREG ($1) && IS_UIMM ($3, 5))
+           {
+             notethat ("LOGI2op: dregs >>>= uimm5\n");
+             $$ = LOGI2OP ($1, uimm5 ($3), 5);
+           }
+         else
+           return yyerror ("Dregs expected");
+       }
+
+/* Cache Control.  */
+
+       | FLUSH LBRACK REG RBRACK
+       {
+         notethat ("CaCTRL: FLUSH [ pregs ]\n");
+         if (IS_PREG ($3))
+           $$ = CACTRL (&$3, 0, 2);
+         else
+           return yyerror ("Bad register(s) for FLUSH");
+       }
+
+       | FLUSH reg_with_postinc
+       {
+         if (IS_PREG ($2))
+           {
+             notethat ("CaCTRL: FLUSH [ pregs ++ ]\n");
+             $$ = CACTRL (&$2, 1, 2);
+           }
+         else
+           return yyerror ("Bad register(s) for FLUSH");
+       }
+
+       | FLUSHINV LBRACK REG RBRACK
+       {
+         if (IS_PREG ($3))
+           {
+             notethat ("CaCTRL: FLUSHINV [ pregs ]\n");
+             $$ = CACTRL (&$3, 0, 1);
+           }
+         else
+           return yyerror ("Bad register(s) for FLUSH");
+       }
+
+       | FLUSHINV reg_with_postinc
+       {
+         if (IS_PREG ($2))
+           {
+             notethat ("CaCTRL: FLUSHINV [ pregs ++ ]\n");
+             $$ = CACTRL (&$2, 1, 1);
+           }
+         else
+           return yyerror ("Bad register(s) for FLUSH");
+       }
+
+/* CaCTRL:     IFLUSH [pregs].  */
+       | IFLUSH LBRACK REG RBRACK
+       {
+         if (IS_PREG ($3))
+           {
+             notethat ("CaCTRL: IFLUSH [ pregs ]\n");
+             $$ = CACTRL (&$3, 0, 3);
+           }
+         else
+           return yyerror ("Bad register(s) for FLUSH");
+       }
+
+       | IFLUSH reg_with_postinc
+       {
+         if (IS_PREG ($2))
+           {
+             notethat ("CaCTRL: IFLUSH [ pregs ++ ]\n");
+             $$ = CACTRL (&$2, 1, 3);
+           }
+         else
+           return yyerror ("Bad register(s) for FLUSH");
+       }
+
+       | PREFETCH LBRACK REG RBRACK
+       {
+         if (IS_PREG ($3))
+           {
+             notethat ("CaCTRL: PREFETCH [ pregs ]\n");
+             $$ = CACTRL (&$3, 0, 0);
+           }
+         else
+           return yyerror ("Bad register(s) for PREFETCH");
+       }
+
+       | PREFETCH reg_with_postinc
+       {
+         if (IS_PREG ($2))
+           {
+             notethat ("CaCTRL: PREFETCH [ pregs ++ ]\n");
+             $$ = CACTRL (&$2, 1, 0);
+           }
+         else
+           return yyerror ("Bad register(s) for PREFETCH");
+       }
+
+/* LOAD/STORE.  */
+/* LDST:       B [ pregs <post_op> ] = dregs.  */
+
+       | B LBRACK REG post_op RBRACK ASSIGN REG
+       {
+         if (IS_PREG ($3) && IS_DREG ($7))
+           {
+             notethat ("LDST: B [ pregs <post_op> ] = dregs\n");
+             $$ = LDST (&$3, &$7, $4.x0, 2, 0, 1);
+           }
+         else
+           return yyerror ("Register mismatch");
+       }
+
+/* LDSTidxI:   B [ pregs + imm16 ] = dregs.  */
+       | B LBRACK REG plus_minus expr RBRACK ASSIGN REG
+       {
+         if (IS_PREG ($3) && IS_RANGE(16, $5, $4.r0, 1) && IS_DREG ($8))
+           {
+             notethat ("LDST: B [ pregs + imm16 ] = dregs\n");
+             if ($4.r0)
+               neg_value ($5);
+             $$ = LDSTIDXI (&$3, &$8, 1, 2, 0, $5);
+           }
+         else
+           return yyerror ("Register mismatch or const size wrong");
+       }
+
+
+/* LDSTii:     W [ pregs + uimm4s2 ] = dregs.  */
+       | W LBRACK REG plus_minus expr RBRACK ASSIGN REG
+       {
+         if (IS_PREG ($3) && IS_URANGE (4, $5, $4.r0, 2) && IS_DREG ($8))
+           {
+             notethat ("LDSTii: W [ pregs +- uimm5m2 ] = dregs\n");
+             $$ = LDSTII (&$3, &$8, $5, 1, 1);
+           }
+         else if (IS_PREG ($3) && IS_RANGE(16, $5, $4.r0, 2) && IS_DREG ($8))
+           {
+             notethat ("LDSTidxI: W [ pregs + imm17m2 ] = dregs\n");
+             if ($4.r0)
+               neg_value ($5);
+             $$ = LDSTIDXI (&$3, &$8, 1, 1, 0, $5);
+           }
+         else
+           return yyerror ("Bad register(s) or wrong constant size");
+       }
+
+/* LDST:       W [ pregs <post_op> ] = dregs.  */
+       | W LBRACK REG post_op RBRACK ASSIGN REG
+       {
+         if (IS_PREG ($3) && IS_DREG ($7))
+           {
+             notethat ("LDST: W [ pregs <post_op> ] = dregs\n");
+             $$ = LDST (&$3, &$7, $4.x0, 1, 0, 1);
+           }
+         else
+           return yyerror ("Bad register(s) for STORE");
+       }
+
+       | W LBRACK REG post_op RBRACK ASSIGN HALF_REG
+       {
+         if (IS_IREG ($3))
+           {
+             notethat ("dspLDST: W [ iregs <post_op> ] = dregs_half\n");
+             $$ = DSPLDST (&$3, 1 + IS_H ($7), &$7, $4.x0, 1);
+           }
+         else if ($4.x0 == 2 && IS_PREG ($3) && IS_DREG ($7))
+           {
+             notethat ("LDSTpmod: W [ pregs <post_op>] = dregs_half\n");
+             $$ = LDSTPMOD (&$3, &$7, &$3, 1 + IS_H ($7), 1);
+             
+           }
+         else
+           return yyerror ("Bad register(s) for STORE");
+       }
+
+/* LDSTiiFP:   [ FP - const ] = dpregs.  */
+       | LBRACK REG plus_minus expr RBRACK ASSIGN REG
+       {
+         Expr_Node *tmp = $4;
+         int ispreg = IS_PREG ($7);
+
+         if (!IS_PREG ($2))
+           return yyerror ("Preg expected for indirect");
+
+         if (!IS_DREG ($7) && !ispreg)
+           return yyerror ("Bad source register for STORE");
+
+         if ($3.r0)
+           tmp = unary (Expr_Op_Type_NEG, tmp);
+
+         if (in_range_p (tmp, 0, 63, 3))
+           {
+             notethat ("LDSTii: dpregs = [ pregs + uimm6m4 ]\n");
+             $$ = LDSTII (&$2, &$7, tmp, 1, ispreg ? 3 : 0);
+           }
+         else if ($2.regno == REG_FP && in_range_p (tmp, -128, 0, 3))
+           {
+             notethat ("LDSTiiFP: dpregs = [ FP - uimm7m4 ]\n");
+             tmp = unary (Expr_Op_Type_NEG, tmp);
+             $$ = LDSTIIFP (tmp, &$7, 1);
+           }
+         else if (in_range_p (tmp, -131072, 131071, 3))
+           {
+             notethat ("LDSTidxI: [ pregs + imm18m4 ] = dpregs\n");
+             $$ = LDSTIDXI (&$2, &$7, 1, 0, ispreg ? 1: 0, tmp);
+           }
+         else
+           return yyerror ("Displacement out of range for store");
+       }
+
+       | REG ASSIGN W LBRACK REG plus_minus expr RBRACK xpmod
+       {
+         if (IS_DREG ($1) && IS_PREG ($5) && IS_URANGE (4, $7, $6.r0, 2))
+           {
+             notethat ("LDSTii: dregs = W [ pregs + uimm4s2 ] (.)\n");
+             $$ = LDSTII (&$5, &$1, $7, 0, 1 << $9.r0);
+           }
+         else if (IS_DREG ($1) && IS_PREG ($5) && IS_RANGE(16, $7, $6.r0, 2))
+           {
+             notethat ("LDSTidxI: dregs = W [ pregs + imm17m2 ] (.)\n");
+             if ($6.r0)
+               neg_value ($7);
+             $$ = LDSTIDXI (&$5, &$1, 0, 1, $9.r0, $7);
+           }
+         else
+           return yyerror ("Bad register or constant for LOAD");
+       }       
+
+       | HALF_REG ASSIGN W LBRACK REG post_op RBRACK
+       {
+         if (IS_IREG ($5))
+           {
+             notethat ("dspLDST: dregs_half = W [ iregs ]\n");
+             $$ = DSPLDST(&$5, 1 + IS_H ($1), &$1, $6.x0, 0);
+           }
+         else if ($6.x0 == 2 && IS_DREG ($1) && IS_PREG ($5))
+           {
+             notethat ("LDSTpmod: dregs_half = W [ pregs ]\n");
+             $$ = LDSTPMOD (&$5, &$1, &$5, 1 + IS_H ($1), 0);
+           }
+         else
+           return yyerror ("Bad register or post_op for LOAD");
+       }
+
+
+       | REG ASSIGN W LBRACK REG post_op RBRACK xpmod
+       {
+         if (IS_DREG ($1) && IS_PREG ($5))
+           {
+             notethat ("LDST: dregs = W [ pregs <post_op> ] (.)\n");
+             $$ = LDST (&$5, &$1, $6.x0, 1, $8.r0, 0);
+           }
+         else
+           return yyerror ("Bad register for LOAD");
+       }
+
+       | REG ASSIGN W LBRACK REG _PLUS_PLUS REG RBRACK xpmod
+       {
+         if (IS_DREG ($1) && IS_PREG ($5) && IS_PREG ($7))
+           {
+             notethat ("LDSTpmod: dregs = W [ pregs ++ pregs ] (.)\n");
+             $$ = LDSTPMOD (&$5, &$1, &$7, 3, $9.r0);
+           }
+         else
+           return yyerror ("Bad register for LOAD");
+       }
+
+       | HALF_REG ASSIGN W LBRACK REG _PLUS_PLUS REG RBRACK
+       {
+         if (IS_DREG ($1) && IS_PREG ($5) && IS_PREG ($7))
+           {
+             notethat ("LDSTpmod: dregs_half = W [ pregs ++ pregs ]\n");
+             $$ = LDSTPMOD (&$5, &$1, &$7, 1 + IS_H ($1), 0);
+           }
+         else
+           return yyerror ("Bad register for LOAD");
+       }
+
+       | LBRACK REG post_op RBRACK ASSIGN REG
+       {
+         if (IS_IREG ($2) && IS_DREG ($6))
+           {
+             notethat ("dspLDST: [ iregs <post_op> ] = dregs\n");
+             $$ = DSPLDST(&$2, 0, &$6, $3.x0, 1);
+           }
+         else if (IS_PREG ($2) && IS_DREG ($6))
+           {
+             notethat ("LDST: [ pregs <post_op> ] = dregs\n");
+             $$ = LDST (&$2, &$6, $3.x0, 0, 0, 1);
+           }
+         else if (IS_PREG ($2) && IS_PREG ($6))
+           {
+             notethat ("LDST: [ pregs <post_op> ] = pregs\n");
+             $$ = LDST (&$2, &$6, $3.x0, 0, 1, 1);
+           }
+         else
+           return yyerror ("Bad register for STORE");
+       }
+
+       | LBRACK REG _PLUS_PLUS REG RBRACK ASSIGN REG
+       {
+         if (! IS_DREG ($7))
+           return yyerror ("Expected Dreg for last argument");
+
+         if (IS_IREG ($2) && IS_MREG ($4))
+           {
+             notethat ("dspLDST: [ iregs ++ mregs ] = dregs\n");
+             $$ = DSPLDST(&$2, $4.regno & CODE_MASK, &$7, 3, 1);
+           }
+         else if (IS_PREG ($2) && IS_PREG ($4))
+           {
+             notethat ("LDSTpmod: [ pregs ++ pregs ] = dregs\n");
+             $$ = LDSTPMOD (&$2, &$7, &$4, 0, 1);
+           }
+         else
+           return yyerror ("Bad register for STORE");
+       }
+                       
+       | W LBRACK REG _PLUS_PLUS REG RBRACK ASSIGN HALF_REG
+       {
+         if (!IS_DREG ($8))
+           return yyerror ("Expect Dreg as last argument");
+         if (IS_PREG ($3) && IS_PREG ($5))
+           {
+             notethat ("LDSTpmod: W [ pregs ++ pregs ] = dregs_half\n");
+             $$ = LDSTPMOD (&$3, &$8, &$5, 1 + IS_H ($8), 1);
+           }
+         else
+           return yyerror ("Bad register for STORE");
+       }
+
+       | REG ASSIGN B LBRACK REG plus_minus expr RBRACK xpmod
+       {
+         if (IS_DREG ($1) && IS_PREG ($5) && IS_RANGE(16, $7, $6.r0, 1))
+           {
+             notethat ("LDSTidxI: dregs = B [ pregs + imm16 ] (%c)\n",
+                      $9.r0 ? 'X' : 'Z');
+             if ($6.r0)
+               neg_value ($7);
+             $$ = LDSTIDXI (&$5, &$1, 0, 2, $9.r0, $7);
+           }
+         else
+           return yyerror ("Bad register or value for LOAD");
+       }
+
+       | REG ASSIGN B LBRACK REG post_op RBRACK xpmod
+       {
+         if (IS_DREG ($1) && IS_PREG ($5))
+           {
+             notethat ("LDST: dregs = B [ pregs <post_op> ] (%c)\n",
+                      $8.r0 ? 'X' : 'Z');
+             $$ = LDST (&$5, &$1, $6.x0, 2, $8.r0, 0);
+           }
+         else
+           return yyerror ("Bad register for LOAD");
+       }
+                       
+       | REG ASSIGN LBRACK REG _PLUS_PLUS REG RBRACK
+       {
+         if (IS_DREG ($1) && IS_IREG ($4) && IS_MREG ($6))
+           {
+             notethat ("dspLDST: dregs = [ iregs ++ mregs ]\n");
+             $$ = DSPLDST(&$4, $6.regno & CODE_MASK, &$1, 3, 0);
+           }
+         else if (IS_DREG ($1) && IS_PREG ($4) && IS_PREG ($6))
+           {
+             notethat ("LDSTpmod: dregs = [ pregs ++ pregs ]\n");
+             $$ = LDSTPMOD (&$4, &$1, &$6, 0, 0);
+           }
+         else
+           return yyerror ("Bad register for LOAD");
+       }
+
+       | REG ASSIGN LBRACK REG plus_minus got_or_expr RBRACK
+       {
+         Expr_Node *tmp = $6;
+         int ispreg = IS_PREG ($1);
+         int isgot = IS_RELOC($6);
+
+         if (!IS_PREG ($4))
+           return yyerror ("Preg expected for indirect");
+
+         if (!IS_DREG ($1) && !ispreg)
+           return yyerror ("Bad destination register for LOAD");
+
+         if ($5.r0)
+           tmp = unary (Expr_Op_Type_NEG, tmp);
+
+         if(isgot){
+             notethat ("LDSTidxI: dpregs = [ pregs + sym@got ]\n");
+             $$ = LDSTIDXI (&$4, &$1, 0, 0, ispreg ? 1: 0, tmp);
+         }
+         else if (in_range_p (tmp, 0, 63, 3))
+           {
+             notethat ("LDSTii: dpregs = [ pregs + uimm7m4 ]\n");
+             $$ = LDSTII (&$4, &$1, tmp, 0, ispreg ? 3 : 0);
+           }
+         else if ($4.regno == REG_FP && in_range_p (tmp, -128, 0, 3))
+           {
+             notethat ("LDSTiiFP: dpregs = [ FP - uimm7m4 ]\n");
+             tmp = unary (Expr_Op_Type_NEG, tmp);
+             $$ = LDSTIIFP (tmp, &$1, 0);
+           }
+         else if (in_range_p (tmp, -131072, 131071, 3))
+           {
+             notethat ("LDSTidxI: dpregs = [ pregs + imm18m4 ]\n");
+             $$ = LDSTIDXI (&$4, &$1, 0, 0, ispreg ? 1: 0, tmp);
+             
+           }
+         else
+           return yyerror ("Displacement out of range for load");
+       }
+
+       | REG ASSIGN LBRACK REG post_op RBRACK
+       {
+         if (IS_DREG ($1) && IS_IREG ($4))
+           {
+             notethat ("dspLDST: dregs = [ iregs <post_op> ]\n");
+             $$ = DSPLDST (&$4, 0, &$1, $5.x0, 0);
+           }
+         else if (IS_DREG ($1) && IS_PREG ($4))
+           {
+             notethat ("LDST: dregs = [ pregs <post_op> ]\n");
+             $$ = LDST (&$4, &$1, $5.x0, 0, 0, 0);
+           }
+         else if (IS_PREG ($1) && IS_PREG ($4))
+           {
+             if (REG_SAME ($1, $4) && $5.x0 != 2)
+               return yyerror ("Pregs can't be same");
+
+             notethat ("LDST: pregs = [ pregs <post_op> ]\n");
+             $$ = LDST (&$4, &$1, $5.x0, 0, 1, 0);
+           }
+         else if ($4.regno == REG_SP && IS_ALLREG ($1) && $5.x0 == 0)
+           {
+             notethat ("PushPopReg: allregs = [ SP ++ ]\n");
+             $$ = PUSHPOPREG (&$1, 0);
+           }
+         else
+           return yyerror ("Bad register or value");
+       }
+
+
+
+/* Expression Assignment.  */
+
+       | expr ASSIGN expr
+       {
+         bfin_equals ($1);
+         $$ = 0;
+       }
+
+
+/*  PushPopMultiple.  */
+       | reg_with_predec ASSIGN LPAREN REG COLON expr COMMA REG COLON expr RPAREN
+       {
+         if ($1.regno != REG_SP)
+           yyerror ("Stack Pointer expected");
+         if ($4.regno == REG_R7
+             && IN_RANGE ($6, 0, 7)
+             && $8.regno == REG_P5
+             && IN_RANGE ($10, 0, 5))
+           {
+             notethat ("PushPopMultiple: [ -- SP ] = (R7 : reglim , P5 : reglim )\n");
+             $$ = PUSHPOPMULTIPLE (imm5 ($6), imm5 ($10), 1, 1, 1);
+           }
+         else
+           return yyerror ("Bad register for PushPopMultiple");
+       }
+
+       | reg_with_predec ASSIGN LPAREN REG COLON expr RPAREN
+       {
+         if ($1.regno != REG_SP)
+           yyerror ("Stack Pointer expected");
+
+         if ($4.regno == REG_R7 && IN_RANGE ($6, 0, 7))
+           {
+             notethat ("PushPopMultiple: [ -- SP ] = (R7 : reglim )\n");
+             $$ = PUSHPOPMULTIPLE (imm5 ($6), 0, 1, 0, 1);
+           }
+         else if ($4.regno == REG_P5 && IN_RANGE ($6, 0, 6))
+           {
+             notethat ("PushPopMultiple: [ -- SP ] = (P5 : reglim )\n");
+             $$ = PUSHPOPMULTIPLE (0, imm5 ($6), 0, 1, 1);
+           }
+         else
+           return yyerror ("Bad register for PushPopMultiple");
+       }
+
+       | LPAREN REG COLON expr COMMA REG COLON expr RPAREN ASSIGN reg_with_postinc
+       {
+         if ($11.regno != REG_SP)
+           yyerror ("Stack Pointer expected");
+         if ($2.regno == REG_R7 && (IN_RANGE ($4, 0, 7))
+             && $6.regno == REG_P5 && (IN_RANGE ($8, 0, 6)))
+           {
+             notethat ("PushPopMultiple: (R7 : reglim , P5 : reglim ) = [ SP ++ ]\n");
+             $$ = PUSHPOPMULTIPLE (imm5 ($4), imm5 ($8), 1, 1, 0);
+           }
+         else
+           return yyerror ("Bad register range for PushPopMultiple");
+       }
+
+       | LPAREN REG COLON expr RPAREN ASSIGN reg_with_postinc
+       {
+         if ($7.regno != REG_SP)
+           yyerror ("Stack Pointer expected");
+
+         if ($2.regno == REG_R7 && IN_RANGE ($4, 0, 7))
+           {
+             notethat ("PushPopMultiple: (R7 : reglim ) = [ SP ++ ]\n");
+             $$ = PUSHPOPMULTIPLE (imm5 ($4), 0, 1, 0, 0);
+           }
+         else if ($2.regno == REG_P5 && IN_RANGE ($4, 0, 6))
+           {
+             notethat ("PushPopMultiple: (P5 : reglim ) = [ SP ++ ]\n");
+             $$ = PUSHPOPMULTIPLE (0, imm5 ($4), 0, 1, 0);
+           }
+         else
+           return yyerror ("Bad register range for PushPopMultiple");
+       }
+
+       | reg_with_predec ASSIGN REG
+       {
+         if ($1.regno != REG_SP)
+           yyerror ("Stack Pointer expected");
+
+         if (IS_ALLREG ($3))
+           {
+             notethat ("PushPopReg: [ -- SP ] = allregs\n");
+             $$ = PUSHPOPREG (&$3, 1);
+           }
+         else
+           return yyerror ("Bad register for PushPopReg");
+       }
+
+/* Linkage.  */
+
+       | LINK expr
+       {
+         if (IS_URANGE (16, $2, 0, 4))
+           $$ = LINKAGE (0, uimm16s4 ($2));
+         else
+           return yyerror ("Bad constant for LINK");
+       }
+               
+       | UNLINK
+       {
+               notethat ("linkage: UNLINK\n");
+               $$ = LINKAGE (1, 0);
+       }
+
+
+/* LSETUP.  */
+
+       | LSETUP LPAREN expr COMMA expr RPAREN REG
+       {
+         if (IS_PCREL4 ($3) && IS_LPPCREL10 ($5) && IS_CREG ($7))
+           {
+             notethat ("LoopSetup: LSETUP (pcrel4 , lppcrel10 ) counters\n");
+             $$ = LOOPSETUP ($3, &$7, 0, $5, 0);
+           }
+         else
+           return yyerror ("Bad register or values for LSETUP");
+         
+       }
+       | LSETUP LPAREN expr COMMA expr RPAREN REG ASSIGN REG
+       {
+         if (IS_PCREL4 ($3) && IS_LPPCREL10 ($5)
+             && IS_PREG ($9) && IS_CREG ($7))
+           {
+             notethat ("LoopSetup: LSETUP (pcrel4 , lppcrel10 ) counters = pregs\n");
+             $$ = LOOPSETUP ($3, &$7, 1, $5, &$9);
+           }
+         else
+           return yyerror ("Bad register or values for LSETUP");
+       }
+
+       | LSETUP LPAREN expr COMMA expr RPAREN REG ASSIGN REG GREATER_GREATER expr
+       {
+         if (IS_PCREL4 ($3) && IS_LPPCREL10 ($5)
+             && IS_PREG ($9) && IS_CREG ($7) 
+             && EXPR_VALUE ($11) == 1)
+           {
+             notethat ("LoopSetup: LSETUP (pcrel4 , lppcrel10 ) counters = pregs >> 1\n");
+             $$ = LOOPSETUP ($3, &$7, 3, $5, &$9);
+           }
+         else
+           return yyerror ("Bad register or values for LSETUP");
+       }
+
+/* LOOP.  */
+       | LOOP expr REG
+       {
+         if (!IS_RELOC ($2))
+           return yyerror ("Invalid expression in loop statement");
+         if (!IS_CREG ($3))
+            return yyerror ("Invalid loop counter register");
+       $$ = bfin_gen_loop ($2, &$3, 0, 0);
+       }
+       | LOOP expr REG ASSIGN REG
+       {
+         if (IS_RELOC ($2) && IS_PREG ($5) && IS_CREG ($3))
+           {
+             notethat ("Loop: LOOP expr counters = pregs\n");
+             $$ = bfin_gen_loop ($2, &$3, 1, &$5);
+           }
+         else
+           return yyerror ("Bad register or values for LOOP");
+       }
+       | LOOP expr REG ASSIGN REG GREATER_GREATER expr
+       {
+         if (IS_RELOC ($2) && IS_PREG ($5) && IS_CREG ($3) && EXPR_VALUE ($7) == 1)
+           {
+             notethat ("Loop: LOOP expr counters = pregs >> 1\n");
+             $$ = bfin_gen_loop ($2, &$3, 3, &$5);
+           }
+         else
+           return yyerror ("Bad register or values for LOOP");
+       }
+/* pseudoDEBUG.  */
+
+       | DBG
+       {
+         notethat ("pseudoDEBUG: DBG\n");
+         $$ = bfin_gen_pseudodbg (3, 7, 0);
+       }
+       | DBG REG_A
+       {
+         notethat ("pseudoDEBUG: DBG REG_A\n");
+         $$ = bfin_gen_pseudodbg (3, IS_A1 ($2), 0);
+       }
+       | DBG REG
+       {
+         notethat ("pseudoDEBUG: DBG allregs\n");
+         $$ = bfin_gen_pseudodbg (0, $2.regno & CODE_MASK, $2.regno & CLASS_MASK);
+       }
+
+       | DBGCMPLX LPAREN REG RPAREN
+       {
+         if (!IS_DREG ($3))
+           return yyerror ("Dregs expected");
+         notethat ("pseudoDEBUG: DBGCMPLX (dregs )\n");
+         $$ = bfin_gen_pseudodbg (3, 6, $3.regno & CODE_MASK);
+       }
+       
+       | DBGHALT
+       {
+         notethat ("psedoDEBUG: DBGHALT\n");
+         $$ = bfin_gen_pseudodbg (3, 5, 0);
+       }
+
+       | DBGA LPAREN HALF_REG COMMA expr RPAREN
+       {
+         notethat ("pseudodbg_assert: DBGA (dregs_lo , uimm16 )\n");
+         $$ = bfin_gen_pseudodbg_assert (IS_H ($3), &$3, uimm16 ($5));
+       }
+               
+       | DBGAH LPAREN REG COMMA expr RPAREN
+       {
+         notethat ("pseudodbg_assert: DBGAH (dregs , uimm16 )\n");
+         $$ = bfin_gen_pseudodbg_assert (3, &$3, uimm16 ($5));
+       }
+
+       | DBGAL LPAREN REG COMMA expr RPAREN
+       {
+         notethat ("psedodbg_assert: DBGAL (dregs , uimm16 )\n");
+         $$ = bfin_gen_pseudodbg_assert (2, &$3, uimm16 ($5));
+       }
+
+
+;
+
+/*  AUX RULES.  */
+
+/*  Register rules.  */
+
+REG_A: REG_A_DOUBLE_ZERO
+       {
+       $$ = $1;
+       }
+       | REG_A_DOUBLE_ONE
+       {
+       $$ = $1;
+       }
+       ;
+
+
+/*  Modifiers. */
+
+opt_mode:
+       {
+       $$.MM = 0;
+       $$.mod = 0;
+       }
+       | LPAREN M COMMA MMOD RPAREN
+       {
+       $$.MM = 1;
+       $$.mod = $4;
+       }
+       | LPAREN MMOD COMMA M RPAREN
+       {
+       $$.MM = 1;
+       $$.mod = $2;
+       }
+       | LPAREN MMOD RPAREN
+       {
+       $$.MM = 0;
+       $$.mod = $2;
+       }
+       | LPAREN M RPAREN
+       {
+       $$.MM = 1;
+       $$.mod = 0;
+       }
+       ;
+
+asr_asl: LPAREN ASL RPAREN
+       {
+       $$.r0 = 1;
+       }
+       | LPAREN ASR RPAREN
+       {
+       $$.r0 = 0;
+       }
+       ;
+
+sco:
+       {
+       $$.s0 = 0;
+       $$.x0 = 0;
+       }
+       | S
+       {
+       $$.s0 = 1;
+       $$.x0 = 0;
+       }
+       | CO
+       {
+       $$.s0 = 0;
+       $$.x0 = 1;
+       }
+       | SCO
+       {       
+       $$.s0 = 1;
+       $$.x0 = 1;
+       }
+       ;
+
+asr_asl_0:
+       ASL
+       {
+       $$.r0 = 1;
+       }
+       | ASR
+       {
+       $$.r0 = 0;
+       }
+       ;
+
+amod0:
+       {
+       $$.s0 = 0;
+       $$.x0 = 0;
+       }
+       | LPAREN sco RPAREN
+       {
+       $$.s0 = $2.s0;
+       $$.x0 = $2.x0;
+       }
+       ;
+
+amod1:
+       {
+       $$.s0 = 0;
+       $$.x0 = 0;
+       $$.aop = 0;
+       }
+       | LPAREN NS RPAREN
+       {
+       $$.s0 = 0;
+       $$.x0 = 0;
+       $$.aop = 1;
+       }
+       | LPAREN S RPAREN
+       {
+       $$.s0 = 1;
+       $$.x0 = 0;
+       $$.aop = 1;
+       }
+       ;
+
+amod2:
+       {
+       $$.r0 = 0;
+       $$.s0 = 0;
+       $$.x0 = 0;
+       }
+       | LPAREN asr_asl_0 RPAREN
+       {
+       $$.r0 = 2 + $2.r0;
+       $$.s0 = 0;
+       $$.x0 = 0;
+       }
+       | LPAREN sco RPAREN
+       {
+       $$.r0 = 0;
+       $$.s0 = $2.s0;
+       $$.x0 = $2.x0;
+       }
+       | LPAREN asr_asl_0 COMMA sco RPAREN
+       {
+       $$.r0 = 2 + $2.r0;
+       $$.s0 = $4.s0;
+       $$.x0 = $4.x0;
+       }
+       | LPAREN sco COMMA asr_asl_0 RPAREN
+       {
+       $$.r0 = 2 + $4.r0;
+       $$.s0 = $2.s0;
+       $$.x0 = $2.x0;
+       }
+       ;
+
+xpmod:
+       {
+       $$.r0 = 0;
+       }
+       | LPAREN Z RPAREN
+       {
+       $$.r0 = 0;
+       }
+       | LPAREN X RPAREN
+       {
+       $$.r0 = 1;
+       }
+       ;
+
+xpmod1:
+       {
+       $$.r0 = 0;
+       }
+       | LPAREN X RPAREN
+       {
+       $$.r0 = 0;
+       }
+       | LPAREN Z RPAREN
+       {
+       $$.r0 = 1;
+       }
+       ;
+
+vsmod:
+       {
+       $$.r0 = 0;
+       $$.s0 = 0;
+       $$.aop = 0;
+       }
+       | LPAREN NS RPAREN
+       {
+       $$.r0 = 0;
+       $$.s0 = 0;
+       $$.aop = 3;
+       }
+       | LPAREN S RPAREN
+       {
+       $$.r0 = 0;
+       $$.s0 = 1;
+       $$.aop = 3;
+       }
+       | LPAREN V RPAREN
+       {
+       $$.r0 = 1;
+       $$.s0 = 0;
+       $$.aop = 3;
+       }
+       | LPAREN V COMMA S RPAREN
+       {
+       $$.r0 = 1;
+       $$.s0 = 1;
+       }
+       | LPAREN S COMMA V RPAREN
+       {
+       $$.r0 = 1;
+       $$.s0 = 1;
+       }
+       ;
+
+vmod:
+       {
+       $$.r0 = 0;
+       }
+       | LPAREN V RPAREN
+       {
+       $$.r0 = 1;
+       }
+       ;
+
+smod:
+       {
+       $$.s0 = 0;
+       }
+       | LPAREN S RPAREN
+       {
+       $$.s0 = 1;
+       }
+       ;
+
+searchmod:
+         GE
+       {
+       $$.r0 = 1;
+       }
+       | GT
+       {
+       $$.r0 = 0;
+       }
+       | LE
+       {
+       $$.r0 = 3;
+       }
+       | LT
+       {
+       $$.r0 = 2;
+       }
+       ;
+
+aligndir:
+       {
+       $$.r0 = 0;
+       }
+       | LPAREN R RPAREN
+       {
+       $$.r0 = 1;
+       }
+       ;
+
+byteop_mod:
+       LPAREN R RPAREN
+       {
+       $$.r0 = 0;
+       $$.s0 = 1;
+       }
+       | LPAREN MMOD RPAREN
+       {
+       if ($2 != M_T)
+         return yyerror ("Bad modifier");
+       $$.r0 = 1;
+       $$.s0 = 0;
+       }
+       | LPAREN MMOD COMMA R RPAREN
+       {
+       if ($2 != M_T)
+         return yyerror ("Bad modifier");
+       $$.r0 = 1;
+       $$.s0 = 1;
+       }
+       | LPAREN R COMMA MMOD RPAREN
+       {
+       if ($4 != M_T)
+         return yyerror ("Bad modifier");
+       $$.r0 = 1;
+       $$.s0 = 1;
+       }
+       ;
+
+
+
+c_align:
+       ALIGN8
+       {
+       $$.r0 = 0;
+       }
+       | ALIGN16
+       {
+       $$.r0 = 1;
+       }
+       | ALIGN24
+       {
+       $$.r0 = 2;
+       }
+       ;
+
+w32_or_nothing:
+       {
+       $$.r0 = 0;
+       }
+       | LPAREN MMOD RPAREN
+       {
+         if ($2 == M_W32)
+           $$.r0 = 1;
+         else
+           return yyerror ("Only (W32) allowed");
+       }
+       ;
+
+iu_or_nothing:
+       {
+       $$.r0 = 1;
+       }
+       | LPAREN MMOD RPAREN
+       {
+         if ($2 == M_IU)
+           $$.r0 = 3;
+         else
+           return yyerror ("(IU) expected");
+       }
+       ;
+
+reg_with_predec: LBRACK _MINUS_MINUS REG RBRACK
+       {
+       $$ = $3;
+       }
+       ;
+
+reg_with_postinc: LBRACK REG _PLUS_PLUS RBRACK
+       {
+       $$ = $2;
+       }
+       ;
+
+/* Operators.  */
+
+min_max:
+       MIN
+       {
+       $$.r0 = 1;
+       }
+       | MAX
+       {
+       $$.r0 = 0;
+       }
+       ;
+op_bar_op:
+       _PLUS_BAR_PLUS
+       {
+       $$.r0 = 0;
+       }
+       | _PLUS_BAR_MINUS
+       {
+       $$.r0 = 1;
+       }
+       | _MINUS_BAR_PLUS
+       {
+       $$.r0 = 2;
+       }
+       | _MINUS_BAR_MINUS
+       {
+       $$.r0 = 3;
+       }
+       ;
+
+plus_minus:
+       PLUS
+       {
+       $$.r0 = 0;
+       }
+       | MINUS
+       {
+       $$.r0 = 1;
+       }
+       ;
+
+rnd_op:
+       LPAREN RNDH RPAREN
+       {
+         $$.r0 = 1;    /* HL.  */
+         $$.s0 = 0;    /* s.  */
+         $$.x0 = 0;    /* x.  */
+         $$.aop = 0;   /* aop.  */
+       }
+
+       | LPAREN TH RPAREN
+       {
+         $$.r0 = 1;    /* HL.  */
+         $$.s0 = 0;    /* s.  */
+         $$.x0 = 0;    /* x.  */
+         $$.aop = 1;   /* aop.  */
+       }
+
+       | LPAREN RNDL RPAREN
+       {
+         $$.r0 = 0;    /* HL.  */
+         $$.s0 = 0;    /* s.  */
+         $$.x0 = 0;    /* x.  */
+         $$.aop = 0;   /* aop.  */
+       }
+
+       | LPAREN TL RPAREN
+       {
+         $$.r0 = 0;    /* HL.  */
+         $$.s0 = 0;    /* s.  */
+         $$.x0 = 0;    /* x.  */
+         $$.aop = 1;
+       }
+
+       | LPAREN RNDH COMMA R RPAREN
+       {
+         $$.r0 = 1;    /* HL.  */
+         $$.s0 = 1;    /* s.  */
+         $$.x0 = 0;    /* x.  */
+         $$.aop = 0;   /* aop.  */
+       }
+       | LPAREN TH COMMA R RPAREN
+       {
+         $$.r0 = 1;    /* HL.  */
+         $$.s0 = 1;    /* s.  */
+         $$.x0 = 0;    /* x.  */
+         $$.aop = 1;   /* aop.  */
+       }
+       | LPAREN RNDL COMMA R RPAREN
+       {
+         $$.r0 = 0;    /* HL.  */
+         $$.s0 = 1;    /* s.  */
+         $$.x0 = 0;    /* x.  */
+         $$.aop = 0;   /* aop.  */
+       }
+
+       | LPAREN TL COMMA R RPAREN
+       {
+         $$.r0 = 0;    /* HL.  */
+         $$.s0 = 1;    /* s.  */
+         $$.x0 = 0;    /* x.  */
+         $$.aop = 1;   /* aop.  */
+       }
+       ;
+
+b3_op:
+       LPAREN LO RPAREN
+       {
+         $$.s0 = 0;    /* s.  */
+         $$.x0 = 0;    /* HL.  */
+       }
+       | LPAREN HI RPAREN
+       {
+         $$.s0 = 0;    /* s.  */
+         $$.x0 = 1;    /* HL.  */
+       }
+       | LPAREN LO COMMA R RPAREN
+       {
+         $$.s0 = 1;    /* s.  */
+         $$.x0 = 0;    /* HL.  */
+       }
+       | LPAREN HI COMMA R RPAREN
+       {
+         $$.s0 = 1;    /* s.  */
+         $$.x0 = 1;    /* HL.  */
+       }
+       ;
+
+post_op:
+       {
+       $$.x0 = 2;
+       } 
+       | _PLUS_PLUS 
+       {
+       $$.x0 = 0;
+       }
+       | _MINUS_MINUS
+       {
+       $$.x0 = 1;
+       }
+       ;
+
+/* Assignments, Macfuncs.  */
+
+a_assign:
+       REG_A ASSIGN
+       {
+       $$ = $1;
+       }
+       ;
+
+a_minusassign:
+       REG_A _MINUS_ASSIGN
+       {
+       $$ = $1;
+       }
+       ;
+
+a_plusassign:
+       REG_A _PLUS_ASSIGN
+       {
+       $$ = $1;
+       }
+       ;
+
+assign_macfunc:
+       REG ASSIGN REG_A
+       {
+         $$.w = 1;
+          $$.P = 1;
+          $$.n = IS_A1 ($3);
+         $$.op = 3;
+          $$.dst = $1;
+         $$.s0.regno = 0;
+          $$.s1.regno = 0;
+
+         if (IS_A1 ($3) && IS_EVEN ($1))
+           return yyerror ("Cannot move A1 to even register");
+         else if (!IS_A1 ($3) && !IS_EVEN ($1))
+           return yyerror ("Cannot move A0 to odd register");
+       }
+       | a_macfunc
+       {
+         $$ = $1;
+         $$.w = 0; $$.P = 0;
+         $$.dst.regno = 0;
+       }
+       | REG ASSIGN LPAREN a_macfunc RPAREN
+       {
+         $$ = $4;
+         $$.w = 1;
+          $$.P = 1;
+          $$.dst = $1;
+       }
+
+       | HALF_REG ASSIGN LPAREN a_macfunc RPAREN
+       {
+         $$ = $4;
+         $$.w = 1;
+         $$.P = 0;
+          $$.dst = $1;
+       }
+
+       | HALF_REG ASSIGN REG_A
+       {
+         $$.w = 1;
+         $$.P = 0;
+         $$.n = IS_A1 ($3);
+         $$.op = 3;
+          $$.dst = $1;
+         $$.s0.regno = 0;
+          $$.s1.regno = 0;
+
+         if (IS_A1 ($3) && !IS_H ($1))
+           return yyerror ("Cannot move A1 to low half of register");
+         else if (!IS_A1 ($3) && IS_H ($1))
+           return yyerror ("Cannot move A0 to high half of register");
+       }
+       ;
+
+a_macfunc:
+       a_assign multiply_halfregs
+       {
+         $$.n = IS_A1 ($1);
+         $$.op = 0;
+         $$.s0 = $2.s0;
+         $$.s1 = $2.s1;
+       }
+       | a_plusassign multiply_halfregs
+       {
+         $$.n = IS_A1 ($1);
+         $$.op = 1;
+         $$.s0 = $2.s0;
+         $$.s1 = $2.s1;
+       }
+       | a_minusassign multiply_halfregs
+       {
+         $$.n = IS_A1 ($1);
+         $$.op = 2;
+         $$.s0 = $2.s0;
+         $$.s1 = $2.s1;
+       }
+       ;
+
+multiply_halfregs:
+       HALF_REG STAR HALF_REG
+       {
+         if (IS_DREG ($1) && IS_DREG ($3))
+           {
+             $$.s0 = $1;
+              $$.s1 = $3;
+           }
+         else
+           return yyerror ("Dregs expected");
+       }
+       ;
+
+cc_op:
+       ASSIGN
+       {
+       $$.r0 = 0;
+       }
+       | _BAR_ASSIGN
+       {
+       $$.r0 = 1;
+       }
+       | _AMPERSAND_ASSIGN
+       {
+       $$.r0 = 2;
+       }
+       | _CARET_ASSIGN
+       {
+       $$.r0 = 3;
+       }
+       ;
+
+ccstat:
+       CCREG cc_op STATUS_REG
+       {
+       $$.r0 = $3.regno;
+       $$.x0 = $2.r0;
+       $$.s0 = 0;
+       }
+       | CCREG cc_op V
+       {
+       $$.r0 = 0x18;
+       $$.x0 = $2.r0;
+       $$.s0 = 0;
+       }
+       | STATUS_REG cc_op CCREG
+       {
+       $$.r0 = $1.regno;
+       $$.x0 = $2.r0;
+       $$.s0 = 1;
+       }
+       | V cc_op CCREG
+       {
+       $$.r0 = 0x18;
+       $$.x0 = $2.r0;
+       $$.s0 = 1;
+       }
+       ;
+
+/* Expressions and Symbols.  */
+
+symbol: SYMBOL
+       {
+       Expr_Node_Value val;
+       val.s_value = S_GET_NAME($1);
+       $$ = Expr_Node_Create (Expr_Node_Reloc, val, NULL, NULL);
+       }
+       ;
+
+got:   symbol AT GOT
+       {
+       $$ = $1;
+       }
+       ;
+
+got_or_expr:   got
+       {
+       $$ = $1;
+       }
+       | expr
+       {
+       $$ = $1;
+       }
+       ;
+
+pltpc :
+       symbol AT PLTPC
+       {
+       $$ = $1;
+       }
+       ;
+
+eterm: NUMBER
+       {
+       Expr_Node_Value val;
+       val.i_value = $1;
+       $$ = Expr_Node_Create (Expr_Node_Constant, val, NULL, NULL);
+       }
+       | symbol
+       {
+       $$ = $1;
+       }
+       | LPAREN expr_1 RPAREN
+       {
+       $$ = $2;
+       }
+       | TILDA expr_1
+       {
+       $$ = unary (Expr_Op_Type_COMP, $2);
+       }
+       | MINUS expr_1 %prec TILDA
+       {
+       $$ = unary (Expr_Op_Type_NEG, $2);
+       }
+       ;
+
+expr: expr_1
+       {
+       $$ = $1;
+       }
+       ;
+
+expr_1: expr_1 STAR expr_1
+       {
+       $$ = binary (Expr_Op_Type_Mult, $1, $3);
+       }
+       | expr_1 SLASH expr_1
+       {
+       $$ = binary (Expr_Op_Type_Div, $1, $3);
+       }
+       | expr_1 PERCENT expr_1
+       {
+       $$ = binary (Expr_Op_Type_Mod, $1, $3);
+       }
+       | expr_1 PLUS expr_1
+       {
+       $$ = binary (Expr_Op_Type_Add, $1, $3);
+       }
+       | expr_1 MINUS expr_1
+       {
+       $$ = binary (Expr_Op_Type_Sub, $1, $3);
+       }
+       | expr_1 LESS_LESS expr_1
+       {
+       $$ = binary (Expr_Op_Type_Lshift, $1, $3);      
+       }
+       | expr_1 GREATER_GREATER expr_1
+       {
+       $$ = binary (Expr_Op_Type_Rshift, $1, $3);
+       }
+       | expr_1 AMPERSAND expr_1
+       {
+       $$ = binary (Expr_Op_Type_BAND, $1, $3);
+       }
+       | expr_1 CARET expr_1
+       {
+       $$ = binary (Expr_Op_Type_LOR, $1, $3);
+       }
+       | expr_1 BAR expr_1
+       {
+       $$ = binary (Expr_Op_Type_BOR, $1, $3);
+       }
+       | eterm 
+       {
+       $$ = $1;
+       }
+       ;
+
+
+%%
+
+EXPR_T
+mkexpr (int x, SYMBOL_T s)
+{
+  EXPR_T e = (EXPR_T) ALLOCATE (sizeof (struct expression_cell));
+  e->value = x;
+  EXPR_SYMBOL(e) = s;
+  return e;
+}
+
+static int
+value_match (Expr_Node *expr, int sz, int sign, int mul, int issigned)
+{
+  long umax = (1L << sz) - 1;
+  long min = -1L << (sz - 1);
+  long max = (1L << (sz - 1)) - 1;
+       
+  long v = EXPR_VALUE (expr);
+
+  if ((v % mul) != 0)
+    {
+      error ("%s:%d: Value Error -- Must align to %d\n", __LINE__, __FILE__, mul); 
+      return 0;
+    }
+
+  v /= mul;
+
+  if (sign)
+    v = -v;
+
+  if (issigned)
+    {
+      if (v >= min && v <= max) return 1;
+
+#ifdef DEBUG
+      fprintf(stderr, "signed value %lx out of range\n", v * mul);
+#endif
+      return 0;
+    }
+  if (v <= umax && v >= 0) 
+    return 1;
+#ifdef DEBUG
+  fprintf(stderr, "unsigned value %lx out of range\n", v * mul);
+#endif
+  return 0;
+}
+
+/* Return the expression structure that allows symbol operations.
+   If the left and right children are constants, do the operation.  */
+static Expr_Node *
+binary (Expr_Op_Type op, Expr_Node *x, Expr_Node *y)
+{
+  if (x->type == Expr_Node_Constant && y->type == Expr_Node_Constant)
+    {
+      switch (op)
+       {
+        case Expr_Op_Type_Add: 
+         x->value.i_value += y->value.i_value;
+         break;
+        case Expr_Op_Type_Sub: 
+         x->value.i_value -= y->value.i_value;
+         break;
+        case Expr_Op_Type_Mult: 
+         x->value.i_value *= y->value.i_value;
+         break;
+        case Expr_Op_Type_Div: 
+         if (y->value.i_value == 0)
+           error ("Illegal Expression:  Division by zero.");
+         else
+           x->value.i_value /= y->value.i_value;
+         break;
+        case Expr_Op_Type_Mod: 
+         x->value.i_value %= y->value.i_value;
+         break;
+        case Expr_Op_Type_Lshift: 
+         x->value.i_value <<= y->value.i_value;
+         break;
+        case Expr_Op_Type_Rshift: 
+         x->value.i_value >>= y->value.i_value;
+         break;
+        case Expr_Op_Type_BAND: 
+         x->value.i_value &= y->value.i_value;
+         break;
+        case Expr_Op_Type_BOR: 
+         x->value.i_value |= y->value.i_value;
+         break;
+        case Expr_Op_Type_BXOR: 
+         x->value.i_value ^= y->value.i_value;
+         break;
+        case Expr_Op_Type_LAND: 
+         x->value.i_value = x->value.i_value && y->value.i_value;
+         break;
+        case Expr_Op_Type_LOR: 
+         x->value.i_value = x->value.i_value || y->value.i_value;
+         break;
+
+       default:
+         error ("%s:%d: Internal compiler error\n", __LINE__, __FILE__); 
+       }
+      return x;
+    }
+  else
+    {
+    /* Create a new expression structure.  */
+    Expr_Node_Value val;
+    val.op_value = op;
+    return Expr_Node_Create (Expr_Node_Binop, val, x, y);
+  }
+}
+
+static Expr_Node *
+unary (Expr_Op_Type op, Expr_Node *x) 
+{
+  if (x->type == Expr_Node_Constant)
+    {
+      switch (op)
+       {
+       case Expr_Op_Type_NEG: 
+         x->value.i_value = -x->value.i_value;
+         break;
+       case Expr_Op_Type_COMP:
+         x->value.i_value = ~x->value.i_value;
+         break;
+       default:
+         error ("%s:%d: Internal compiler error\n", __LINE__, __FILE__); 
+       }
+      return x;
+    }
+  else
+    {
+      /* Create a new expression structure.  */
+      Expr_Node_Value val;
+      val.op_value = op;
+      return Expr_Node_Create (Expr_Node_Unop, val, x, NULL);
+    }
+}
+
+int debug_codeselection = 0;
+static void
+notethat (char *format, ...)
+{
+  va_list ap;
+  va_start (ap, format);
+  if (debug_codeselection)
+    {
+      vfprintf (errorf, format, ap);
+    }
+  va_end (ap);
+}
+
+#ifdef TEST
+main (int argc, char **argv)
+{
+  yyparse();
+}
+#endif
+
diff --git a/gas/config/tc-bfin.c b/gas/config/tc-bfin.c
new file mode 100644 (file)
index 0000000..90763da
--- /dev/null
@@ -0,0 +1,1951 @@
+/* tc-bfin.c -- Assembler for the ADI Blackfin.
+   Copyright 2005
+   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, 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+#include "as.h"
+#include "struc-symbol.h"
+#include "obj-elf.h"
+#include "bfin-defs.h"
+#include "obstack.h"
+#include "safe-ctype.h"
+#ifdef OBJ_ELF
+#include "dwarf2dbg.h"
+#endif
+
+extern int yyparse (void);
+struct yy_buffer_state;
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+extern YY_BUFFER_STATE yy_scan_string (const char *yy_str);
+extern void yy_delete_buffer (YY_BUFFER_STATE b);
+static parse_state parse (char *line);
+static void bfin_s_bss PARAMS ((int));
+static int md_chars_to_number PARAMS ((unsigned char *, int));
+
+/* Global variables. */
+struct bfin_insn *insn;
+int last_insn_size;
+
+extern struct obstack mempool;
+FILE *errorf;
+
+/* Registers list.  */
+struct bfin_reg_entry
+{
+  const char *name;
+  int number;
+};
+
+static const struct bfin_reg_entry bfin_reg_info[] = {
+  {"R0.L", REG_RL0},
+  {"R1.L", REG_RL1},
+  {"R2.L", REG_RL2},
+  {"R3.L", REG_RL3},
+  {"R4.L", REG_RL4},
+  {"R5.L", REG_RL5},
+  {"R6.L", REG_RL6},
+  {"R7.L", REG_RL7},
+  {"R0.H", REG_RH0},
+  {"R1.H", REG_RH1},
+  {"R2.H", REG_RH2},
+  {"R3.H", REG_RH3},
+  {"R4.H", REG_RH4},
+  {"R5.H", REG_RH5},
+  {"R6.H", REG_RH6},
+  {"R7.H", REG_RH7},
+  {"R0", REG_R0},
+  {"R1", REG_R1},
+  {"R2", REG_R2},
+  {"R3", REG_R3},
+  {"R4", REG_R4},
+  {"R5", REG_R5},
+  {"R6", REG_R6},
+  {"R7", REG_R7},
+  {"P0", REG_P0},
+  {"P0.H", REG_P0},
+  {"P0.L", REG_P0},
+  {"P1", REG_P1},
+  {"P1.H", REG_P1},
+  {"P1.L", REG_P1},
+  {"P2", REG_P2},
+  {"P2.H", REG_P2},
+  {"P2.L", REG_P2},
+  {"P3", REG_P3},
+  {"P3.H", REG_P3},
+  {"P3.L", REG_P3},
+  {"P4", REG_P4},
+  {"P4.H", REG_P4},
+  {"P4.L", REG_P4},
+  {"P5", REG_P5},
+  {"P5.H", REG_P5},
+  {"P5.L", REG_P5},
+  {"SP", REG_SP},
+  {"SP.L", REG_SP},
+  {"SP.H", REG_SP},
+  {"FP", REG_FP},
+  {"FP.L", REG_FP},
+  {"FP.H", REG_FP},
+  {"A0x", REG_A0x},
+  {"A1x", REG_A1x},
+  {"A0w", REG_A0w},
+  {"A1w", REG_A1w},
+  {"A0.x", REG_A0x},
+  {"A1.x", REG_A1x},
+  {"A0.w", REG_A0w},
+  {"A1.w", REG_A1w},
+  {"A0", REG_A0},
+  {"A0.L", REG_A0},
+  {"A0.H", REG_A0},
+  {"A1", REG_A1},
+  {"A1.L", REG_A1},
+  {"A1.H", REG_A1},
+  {"I0", REG_I0},
+  {"I0.L", REG_I0},
+  {"I0.H", REG_I0},
+  {"I1", REG_I1},
+  {"I1.L", REG_I1},
+  {"I1.H", REG_I1},
+  {"I2", REG_I2},
+  {"I2.L", REG_I2},
+  {"I2.H", REG_I2},
+  {"I3", REG_I3},
+  {"I3.L", REG_I3},
+  {"I3.H", REG_I3},
+  {"M0", REG_M0},
+  {"M0.H", REG_M0},
+  {"M0.L", REG_M0},
+  {"M1", REG_M1},
+  {"M1.H", REG_M1},
+  {"M1.L", REG_M1},
+  {"M2", REG_M2},
+  {"M2.H", REG_M2},
+  {"M2.L", REG_M2},
+  {"M3", REG_M3},
+  {"M3.H", REG_M3},
+  {"M3.L", REG_M3},
+  {"B0", REG_B0},
+  {"B0.H", REG_B0},
+  {"B0.L", REG_B0},
+  {"B1", REG_B1},
+  {"B1.H", REG_B1},
+  {"B1.L", REG_B1},
+  {"B2", REG_B2},
+  {"B2.H", REG_B2},
+  {"B2.L", REG_B2},
+  {"B3", REG_B3},
+  {"B3.H", REG_B3},
+  {"B3.L", REG_B3},
+  {"L0", REG_L0},
+  {"L0.H", REG_L0},
+  {"L0.L", REG_L0},
+  {"L1", REG_L1},
+  {"L1.H", REG_L1},
+  {"L1.L", REG_L1},
+  {"L2", REG_L2},
+  {"L2.H", REG_L2},
+  {"L2.L", REG_L2},
+  {"L3", REG_L3},
+  {"L3.H", REG_L3},
+  {"L3.L", REG_L3},
+  {"AZ", S_AZ},
+  {"AN", S_AN},
+  {"AC0", S_AC0},
+  {"AC1", S_AC1},
+  {"AV0", S_AV0},
+  {"AV0S", S_AV0S},
+  {"AV1", S_AV1},
+  {"AV1S", S_AV1S},
+  {"AQ", S_AQ},
+  {"V", S_V},
+  {"VS", S_VS},
+  {"sftreset", REG_sftreset},
+  {"omode", REG_omode},
+  {"excause", REG_excause},
+  {"emucause", REG_emucause},
+  {"idle_req", REG_idle_req},
+  {"hwerrcause", REG_hwerrcause},
+  {"CC", REG_CC},
+  {"LC0", REG_LC0},
+  {"LC1", REG_LC1},
+  {"ASTAT", REG_ASTAT},
+  {"RETS", REG_RETS},
+  {"LT0", REG_LT0},
+  {"LB0", REG_LB0},
+  {"LT1", REG_LT1},
+  {"LB1", REG_LB1},
+  {"CYCLES", REG_CYCLES},
+  {"CYCLES2", REG_CYCLES2},
+  {"USP", REG_USP},
+  {"SEQSTAT", REG_SEQSTAT},
+  {"SYSCFG", REG_SYSCFG},
+  {"RETI", REG_RETI},
+  {"RETX", REG_RETX},
+  {"RETN", REG_RETN},
+  {"RETE", REG_RETE},
+  {"EMUDAT", REG_EMUDAT},
+  {0, 0}
+};
+
+
+const pseudo_typeS md_pseudo_table[] = {
+  {"align", s_align_bytes, 0},
+  {"byte2", cons, 2},
+  {"byte4", cons, 4},
+  {"code", obj_elf_section, 0},
+  {"db", cons, 1},
+  {"dd", cons, 4},
+  {"dw", cons, 2},
+  {"p", s_ignore, 0},
+  {"pdata", s_ignore, 0},
+  {"var", s_ignore, 0},
+  {"bss", bfin_s_bss, 0},
+  {0, 0, 0}
+};
+
+static void
+bfin_s_bss (int ignore ATTRIBUTE_UNUSED)
+{
+  register int temp;
+
+  temp = get_absolute_expression ();
+  subseg_set (bss_section, (subsegT) temp);
+  demand_empty_rest_of_line ();
+}
+
+
+/* Characters that are used to denote comments and line separators. */
+const char comment_chars[] = "";
+const char line_comment_chars[] = "#";
+const char line_separator_chars[] = ";";
+
+/* Characters that can be used to separate the mantissa from the
+   exponent in floating point numbers. */
+const char EXP_CHARS[] = "eE";
+
+/* Characters that mean this number is a floating point constant.
+   As in 0f12.456 or  0d1.2345e12.  */
+const char FLT_CHARS[] = "fFdDxX";
+
+/* Define bfin-specific command-line options (there are none). */
+const char *md_shortopts = "";
+
+struct option md_longopts[] = {
+  {NULL, no_argument, NULL, 0}
+};
+size_t md_longopts_size = sizeof (md_longopts);
+
+
+int
+md_parse_option (int c ATTRIBUTE_UNUSED, char *arg ATTRIBUTE_UNUSED)
+{
+  return 0;
+}
+
+void
+md_show_usage (FILE * stream ATTRIBUTE_UNUSED)
+{
+  fprintf (stream, _(" BFIN specific command line options:\n"));
+}
+
+/* Perform machine-specific initializations.  */
+void
+md_begin ()
+{
+  /* Set the default machine type. */
+  if (!bfd_set_arch_mach (stdoutput, bfd_arch_bfin, 0))
+    as_warn ("Could not set architecture and machine.");
+
+  /* Ensure that lines can begin with '(', for multiple
+     register stack pops. */
+  lex_type ['('] = 3;
+  
+#ifdef OBJ_ELF
+  record_alignment (text_section, 2);
+  record_alignment (data_section, 2);
+  record_alignment (bss_section, 2);
+#endif
+
+  errorf = stderr;
+  obstack_init (&mempool);
+
+#ifdef DEBUG
+  extern int debug_codeselection;
+  debug_codeselection = 1;
+#endif 
+
+  last_insn_size = 0;
+}
+
+/* Perform the main parsing, and assembly of the input here.  Also,
+   call the required routines for alignment and fixups here.
+   This is called for every line that contains real assembly code.  */
+
+void
+md_assemble (char *line)
+{
+  char *toP = 0;
+  extern char *current_inputline;
+  int size, insn_size;
+  struct bfin_insn *tmp_insn;
+  size_t len;
+  static size_t buffer_len = 0;
+  parse_state state;
+
+  len = strlen (line);
+  if (len + 2 > buffer_len)
+    {
+      if (buffer_len > 0)
+       free (current_inputline);
+      buffer_len = len + 40;
+      current_inputline = xmalloc (buffer_len);
+    }
+  memcpy (current_inputline, line, len);
+  current_inputline[len] = ';';
+  current_inputline[len + 1] = '\0';
+
+  state = parse (current_inputline);
+  if (state == NO_INSN_GENERATED)
+    return;
+
+  for (insn_size = 0, tmp_insn = insn; tmp_insn; tmp_insn = tmp_insn->next)
+    if (!tmp_insn->reloc || !tmp_insn->exp->symbol)
+      insn_size += 2;
+
+  if (insn_size)
+    toP = frag_more (insn_size);
+
+  last_insn_size = insn_size;
+
+#ifdef DEBUG
+  printf ("INS:");
+#endif
+  while (insn)
+    {
+      if (insn->reloc && insn->exp->symbol)
+       {
+         char *prev_toP = toP - 2;
+         switch (insn->reloc)
+           {
+           case BFD_RELOC_BFIN_24_PCREL_JUMP_L:
+           case BFD_RELOC_24_PCREL:
+           case BFD_RELOC_BFIN_16_LOW:
+           case BFD_RELOC_BFIN_16_HIGH:
+             size = 4;
+             break;
+           default:
+             size = 2;
+           }
+
+         /* Following if condition checks for the arithmetic relocations.
+            If the case then it doesn't required to generate the code.
+            It has been assumed that, their ID will be contiguous.  */
+         if ((BFD_ARELOC_BFIN_PUSH <= insn->reloc
+               && BFD_ARELOC_BFIN_COMP >= insn->reloc)
+              || insn->reloc == BFD_RELOC_BFIN_16_IMM)
+           {
+             size = 2;
+           }
+         if (insn->reloc == BFD_ARELOC_BFIN_CONST
+              || insn->reloc == BFD_ARELOC_BFIN_PUSH)
+           size = 4;
+
+         fix_new (frag_now,
+                   (prev_toP - frag_now->fr_literal),
+                  size, insn->exp->symbol, insn->exp->value,
+                   insn->pcrel, insn->reloc);
+       }
+      else
+       {
+         md_number_to_chars (toP, insn->value, 2);
+         toP += 2;
+       }
+
+#ifdef DEBUG
+      printf (" reloc :");
+      printf (" %02x%02x", ((unsigned char *) &insn->value)[0],
+              ((unsigned char *) &insn->value)[1]);
+      printf ("\n");
+#endif
+      insn = insn->next;
+    }
+#ifdef OBJ_ELF
+  dwarf2_emit_insn (insn_size);
+#endif
+}
+
+/* Parse one line of instructions, and generate opcode for it.
+   To parse the line, YACC and LEX are used, because the instruction set
+   syntax doesn't confirm to the AT&T assembly syntax.
+   To call a YACC & LEX generated parser, we must provide the input via
+   a FILE stream, otherwise stdin is used by default.  Below the input
+   to the function will be put into a temporary file, then the generated
+   parser uses the temporary file for parsing.  */
+
+static parse_state
+parse (char *line)
+{
+  parse_state state;
+  YY_BUFFER_STATE buffstate;
+
+  buffstate = yy_scan_string (line);
+
+  /* our lex requires setting the start state to keyword
+     every line as the first word may be a keyword.
+     Fixes a bug where we could not have keywords as labels.  */
+  set_start_state ();
+
+  /* Call yyparse here.  */
+  state = yyparse ();
+  if (state == SEMANTIC_ERROR)
+    {
+      as_bad ("Parse failed.");
+      insn = 0;
+    }
+
+  yy_delete_buffer (buffstate);
+  return state;
+}
+
+/* We need to handle various expressions properly.
+   Such as, [SP--] = 34, concerned by md_assemble().  */
+
+void
+md_operand (expressionS * expressionP)
+{
+  if (*input_line_pointer == '[')
+    {
+      as_tsktsk ("We found a '['!");
+      input_line_pointer++;
+      expression (expressionP);
+    }
+}
+
+/* Handle undefined symbols. */
+symbolS *
+md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
+{
+  return (symbolS *) 0;
+}
+
+int
+md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED,
+                               segT segment ATTRIBUTE_UNUSED)
+{
+  return 0;
+}
+
+/* Convert from target byte order to host byte order.  */
+
+static int
+md_chars_to_number (val, n)
+     unsigned char *val;       /* Value in target byte order.  */
+     int n;                    /* Number of bytes in the input.  */
+{
+  int retval;
+
+  for (retval = 0; n--;)
+    {
+      retval <<= 8;
+      retval |= val[n];
+    }
+  return retval;
+}
+
+void
+md_apply_fix (fixS *fixP, valueT *valueP, segT seg ATTRIBUTE_UNUSED)
+{
+  char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
+
+  long value = *valueP;
+  long newval;
+
+  switch (fixP->fx_r_type)
+    {
+    case BFD_RELOC_BFIN_GOT:
+      fixP->fx_no_overflow = 1;
+      newval = md_chars_to_number (where, 2);
+      newval |= 0x0 & 0x7f;
+      md_number_to_chars (where, newval, 2);
+      break;
+
+    case BFD_RELOC_BFIN_10_PCREL:
+      if (!value)
+       break;
+      if (value < -1024 || value > 1022)
+       as_bad_where (fixP->fx_file, fixP->fx_line,
+                      "pcrel too far BFD_RELOC_BFIN_10");
+
+      /* 11 bit offset even numbered, so we remove right bit.  */
+      value = value >> 1;
+      newval = md_chars_to_number (where, 2);
+      newval |= value & 0x03ff;
+      md_number_to_chars (where, newval, 2);
+      break;
+
+    case BFD_RELOC_BFIN_12_PCREL_JUMP:
+    case BFD_RELOC_BFIN_12_PCREL_JUMP_S:
+    case BFD_RELOC_12_PCREL:
+      if (!value)
+       break;
+
+      if (value < -4096 || value > 4094)
+       as_bad_where (fixP->fx_file, fixP->fx_line, "pcrel too far BFD_RELOC_BFIN_12");
+      /* 13 bit offset even numbered, so we remove right bit.  */
+      value = value >> 1;
+      newval = md_chars_to_number (where, 2);
+      newval |= value & 0xfff;
+      md_number_to_chars (where, newval, 2);
+      break;
+
+    case BFD_RELOC_BFIN_16_LOW:
+    case BFD_RELOC_BFIN_16_HIGH:
+      fixP->fx_done = FALSE;
+      break;
+
+    case BFD_RELOC_BFIN_24_PCREL_JUMP_L:
+    case BFD_RELOC_BFIN_24_PCREL_CALL_X:
+    case BFD_RELOC_24_PCREL:
+      if (!value)
+       break;
+
+      if (value < -16777216 || value > 16777214)
+       as_bad_where (fixP->fx_file, fixP->fx_line, "pcrel too far BFD_RELOC_BFIN_24");
+
+      /* 25 bit offset even numbered, so we remove right bit.  */
+      value = value >> 1;
+      value++;
+
+      md_number_to_chars (where - 2, value >> 16, 1);
+      md_number_to_chars (where, value, 1);
+      md_number_to_chars (where + 1, value >> 8, 1);
+      break;
+
+    case BFD_RELOC_BFIN_5_PCREL:       /* LSETUP (a, b) : "a" */
+      if (!value)
+       break;
+      if (value < 4 || value > 30)
+       as_bad_where (fixP->fx_file, fixP->fx_line, "pcrel too far BFD_RELOC_BFIN_5");
+      value = value >> 1;
+      newval = md_chars_to_number (where, 1);
+      newval = (newval & 0xf0) | (value & 0xf);
+      md_number_to_chars (where, newval, 1);
+      break;
+
+    case BFD_RELOC_BFIN_11_PCREL:      /* LSETUP (a, b) : "b" */
+      if (!value)
+       break;
+      value += 2;
+      if (value < 4 || value > 2046)
+       as_bad_where (fixP->fx_file, fixP->fx_line, "pcrel too far BFD_RELOC_BFIN_11_PCREL");
+      /* 11 bit unsigned even, so we remove right bit.  */
+      value = value >> 1;
+      newval = md_chars_to_number (where, 2);
+      newval |= value & 0x03ff;
+      md_number_to_chars (where, newval, 2);
+      break;
+
+    case BFD_RELOC_8:
+      if (value < -0x80 || value >= 0x7f)
+       as_bad_where (fixP->fx_file, fixP->fx_line, "rel too far BFD_RELOC_8");
+      md_number_to_chars (where, value, 1);
+      break;
+
+    case BFD_RELOC_BFIN_16_IMM:
+    case BFD_RELOC_16:
+      if (value < -0x8000 || value >= 0x7fff)
+       as_bad_where (fixP->fx_file, fixP->fx_line, "rel too far BFD_RELOC_8");
+      md_number_to_chars (where, value, 2);
+      break;
+
+    case BFD_RELOC_32:
+      md_number_to_chars (where, value, 4);
+      break;
+
+    case BFD_RELOC_BFIN_PLTPC:
+      md_number_to_chars (where, value, 2);
+      break;
+
+    case BFD_RELOC_VTABLE_INHERIT:
+    case BFD_RELOC_VTABLE_ENTRY:
+      fixP->fx_done = FALSE;
+      break;
+
+    default:
+      if ((BFD_ARELOC_BFIN_PUSH > fixP->fx_r_type) || (BFD_ARELOC_BFIN_COMP < fixP->fx_r_type))
+       {
+         fprintf (stderr, "Relocation %d not handled in gas." " Contact support.\n", fixP->fx_r_type);
+         return;
+       }
+    }
+
+  if (!fixP->fx_addsy)
+    fixP->fx_done = TRUE;
+
+}
+
+/* Round up a section size to the appropriate boundary.  */
+valueT
+md_section_align (segment, size)
+     segT segment;
+     valueT size;
+{
+  int boundary = bfd_get_section_alignment (stdoutput, segment);
+  return ((size + (1 << boundary) - 1) & (-1 << boundary));
+}
+
+
+/* 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.  */
+
+/* Equal to MAX_PRECISION in atof-ieee.c.  */
+#define MAX_LITTLENUMS 6
+
+char *
+md_atof (type, litP, sizeP)
+     char   type;
+     char * litP;
+     int *  sizeP;
+{
+  int              prec;
+  LITTLENUM_TYPE   words [MAX_LITTLENUMS];
+  LITTLENUM_TYPE   *wordP;
+  char *           t;
+
+  switch (type)
+    {
+    case 'f':
+    case 'F':
+      prec = 2;
+      break;
+
+    case 'd':
+    case 'D':
+      prec = 4;
+      break;
+
+   /* FIXME: Some targets allow other format chars for bigger sizes here.  */
+
+    default:
+      *sizeP = 0;
+      return _("Bad call to md_atof()");
+    }
+
+  t = atof_ieee (input_line_pointer, type, words);
+  if (t)
+    input_line_pointer = t;
+  *sizeP = prec * sizeof (LITTLENUM_TYPE);
+
+  *sizeP = prec * sizeof (LITTLENUM_TYPE);
+  /* This loops outputs the LITTLENUMs in REVERSE order; in accord with
+     the littleendianness of the processor.  */
+  for (wordP = words + prec - 1; prec--;)
+    {
+      md_number_to_chars (litP, (valueT) (*wordP--), sizeof (LITTLENUM_TYPE));
+      litP += sizeof (LITTLENUM_TYPE);
+    }
+
+  return 0;
+}
+
+
+/* If while processing a fixup, a reloc really needs to be created
+   then it is done here.  */
+
+arelent *
+tc_gen_reloc (seg, fixp)
+     asection *seg ATTRIBUTE_UNUSED;
+     fixS *fixp;
+{
+  arelent *reloc;
+
+  reloc                      = (arelent *) xmalloc (sizeof (arelent));
+  reloc->sym_ptr_ptr  = (asymbol **) xmalloc (sizeof (asymbol *));
+  *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
+  reloc->address      = fixp->fx_frag->fr_address + fixp->fx_where;
+
+  reloc->addend = fixp->fx_offset;
+  reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
+
+  if (reloc->howto == (reloc_howto_type *) NULL)
+    {
+      as_bad_where (fixp->fx_file, fixp->fx_line,
+                   /* xgettext:c-format.  */
+                   _("reloc %d not supported by object file format"),
+                   (int) fixp->fx_r_type);
+
+      xfree (reloc);
+
+      return NULL;
+    }
+
+  return reloc;
+}
+
+/*  The location from which a PC relative jump should be calculated,
+    given a PC relative reloc.  */
+
+long
+md_pcrel_from_section (fixP, sec)
+     fixS *fixP;
+     segT sec;
+{
+  if (fixP->fx_addsy != (symbolS *) NULL
+      && (!S_IS_DEFINED (fixP->fx_addsy)
+      || S_GET_SEGMENT (fixP->fx_addsy) != sec))
+    {
+      /* The symbol is undefined (or is defined but not in this section).
+         Let the linker figure it out.  */
+      return 0;
+    }
+  return fixP->fx_frag->fr_address + fixP->fx_where;
+}
+
+/* Return true if the fix can be handled by GAS, false if it must
+   be passed through to the linker.  */
+
+bfd_boolean  
+bfin_fix_adjustable (fixS *fixP)
+{         
+  switch (fixP->fx_r_type)
+    {     
+  /* Adjust_reloc_syms doesn't know about the GOT.  */
+    case BFD_RELOC_BFIN_GOT :
+    case BFD_RELOC_BFIN_PLTPC :
+  /* We need the symbol name for the VTABLE entries.  */
+    case BFD_RELOC_VTABLE_INHERIT:
+    case BFD_RELOC_VTABLE_ENTRY:
+      return 0;
+        
+    default:
+      return 1;
+    }     
+}
+
+
+/* Handle the LOOP_BEGIN and LOOP_END statements.
+   Parse the Loop_Begin/Loop_End and create a label.  */
+void
+bfin_start_line_hook ()
+{
+  bfd_boolean maybe_begin = FALSE;
+  bfd_boolean maybe_end = FALSE;
+
+  char *c1, *label_name;
+  symbolS *line_label;
+  char *c = input_line_pointer;
+
+  while (ISSPACE (*c))
+    c++;
+
+  /* Look for LSETUP(. */
+  if (!strncasecmp (input_line_pointer, "lsetup(", 7))
+    {
+      /* Need to insert space between lsetup and paren.  */
+      input_line_pointer --;
+      input_line_pointer[0] = 'l';
+      input_line_pointer[1] = 's';
+      input_line_pointer[2] = 'e';
+      input_line_pointer[3] = 't';
+      input_line_pointer[4] = 'u';
+      input_line_pointer[5] = 'p';
+      input_line_pointer[6] = ' ';
+      return;
+    }
+
+  /* Look for Loop_Begin or Loop_End statements.  */
+
+  if (*c != 'L' && *c != 'l')
+    return;
+
+  c++;
+  if (*c != 'O' && *c != 'o')
+    return;
+
+  c++;
+  if (*c != 'O' && *c != 'o')
+    return;
+  c++;
+  if (*c != 'P' && *c != 'p')
+    return;
+
+  c++;
+  if (*c != '_')
+    return;
+
+  c++;
+  if (*c == 'E' || *c == 'e')
+    maybe_end = TRUE;
+  else if (*c == 'B' || *c == 'b')
+    maybe_begin = TRUE;
+  else
+    return;
+
+  if (maybe_end)
+    {
+      c++;
+      if (*c != 'N' && *c != 'n')
+       return;
+
+      c++;
+      if (*c != 'D' && *c != 'd')
+        return;
+    }
+
+  if (maybe_begin)
+    {
+      c++;
+      if (*c != 'E' && *c != 'e')
+       return;
+
+      c++;
+      if (*c != 'G' && *c != 'g')
+        return;
+
+      c++;
+      if (*c != 'I' && *c != 'i')
+       return;
+
+      c++;
+      if (*c != 'N' && *c != 'n')
+        return;
+    }
+
+  c++;
+  while (ISSPACE (*c)) c++;
+  c1 = c;
+  while (ISALPHA (*c) || ISDIGIT (*c) || *c == '_') c++;
+
+  input_line_pointer = c;
+  if (maybe_end)
+    {
+      label_name = (char *) xmalloc ((c - c1) + strlen ("__END") + 1);
+      label_name[0] = 0;
+      strncat (label_name, c1, c-c1);
+      strcat (label_name, "__END");
+    }
+  else /* maybe_begin.  */
+    {
+      label_name = (char *) xmalloc ((c - c1) + strlen ("__BEGIN") + 1);
+      label_name[0] = 0;
+      strncat (label_name, c1, c-c1);
+      strcat (label_name, "__BEGIN");
+    }
+
+  line_label = colon (label_name);
+
+  /* Loop_End follows the last instruction in the loop.
+     Adjust label address.  */
+  if (maybe_end)
+    line_label->sy_value.X_add_number -= last_insn_size;
+
+}
+
+/* Special extra functions that help bfin-parse.y perform its job.  */
+
+#include <stdio.h>
+#include <assert.h>
+#include <obstack.h>
+#include <bfd.h>
+#include "bfin-defs.h"
+
+struct obstack mempool;
+
+INSTR_T
+conscode (INSTR_T head, INSTR_T tail)
+{
+  if (!head)
+    return tail;
+  head->next = tail;
+  return head;
+}
+
+INSTR_T
+conctcode (INSTR_T head, INSTR_T tail)
+{
+  INSTR_T temp = (head);
+  if (!head)
+    return tail;
+  while (temp->next)
+    temp = temp->next;
+  temp->next = tail;
+
+  return head;
+}
+
+INSTR_T
+note_reloc (INSTR_T code, Expr_Node * symbol, int reloc, int pcrel)
+{
+  /* Assert that the symbol is not an operator.  */
+  assert (symbol->type == Expr_Node_Reloc);
+
+  return note_reloc1 (code, symbol->value.s_value, reloc, pcrel);
+
+}
+
+INSTR_T
+note_reloc1 (INSTR_T code, const char *symbol, int reloc, int pcrel)
+{
+  code->reloc = reloc;
+  code->exp = mkexpr (0, symbol_find_or_make (symbol));
+  code->pcrel = pcrel;
+  return code;
+}
+
+INSTR_T
+note_reloc2 (INSTR_T code, const char *symbol, int reloc, int value, int pcrel)
+{
+  code->reloc = reloc;
+  code->exp = mkexpr (value, symbol_find_or_make (symbol));
+  code->pcrel = pcrel;
+  return code;
+}
+
+INSTR_T
+gencode (unsigned long x)
+{
+  INSTR_T cell = (INSTR_T) obstack_alloc (&mempool, sizeof (struct bfin_insn));
+  memset (cell, 0, sizeof (struct bfin_insn));
+  cell->value = (x);
+  return cell;
+}
+
+int reloc;
+int ninsns;
+int count_insns;
+
+static void *
+allocate (int n)
+{
+  return (void *) obstack_alloc (&mempool, n);
+}
+
+Expr_Node *
+Expr_Node_Create (Expr_Node_Type type,
+                 Expr_Node_Value value,
+                  Expr_Node *Left_Child,
+                  Expr_Node *Right_Child)
+{
+
+
+  Expr_Node *node = (Expr_Node *) allocate (sizeof (Expr_Node));
+  node->type = type;
+  node->value = value;
+  node->Left_Child = Left_Child;
+  node->Right_Child = Right_Child;
+  return node;
+}
+
+static const char *con = ".__constant";
+static const char *op = ".__operator";
+static INSTR_T Expr_Node_Gen_Reloc_R (Expr_Node * head);
+INSTR_T Expr_Node_Gen_Reloc (Expr_Node *head, int parent_reloc);
+
+INSTR_T
+Expr_Node_Gen_Reloc (Expr_Node * head, int parent_reloc)
+{
+  /* Top level reloction expression generator VDSP style.
+   If the relocation is just by itself, generate one item
+   else generate this convoluted expression.  */
+
+  INSTR_T note = NULL_CODE;
+  INSTR_T note1 = NULL_CODE;
+  int pcrel = 1;  /* Is the parent reloc pcrelative?
+                 This calculation here and HOWTO should match.  */
+
+  if (parent_reloc)
+    {
+      /*  If it's 32 bit quantity then 16bit code needs to be added.  */
+      int value = 0;
+
+      if (head->type == Expr_Node_Constant)
+       {
+         /* If note1 is not null code, we have to generate a right
+             aligned value for the constant. Otherwise the reloc is
+             a part of the basic command and the yacc file
+             generates this.  */
+         value = head->value.i_value;
+       }
+      switch (parent_reloc)
+       {
+         /*  Some reloctions will need to allocate extra words.  */
+       case BFD_RELOC_BFIN_16_IMM:
+       case BFD_RELOC_BFIN_16_LOW:
+       case BFD_RELOC_BFIN_16_HIGH:
+         note1 = conscode (gencode (value), NULL_CODE);
+         pcrel = 0;
+         break;
+       case BFD_RELOC_BFIN_PLTPC:
+         note1 = conscode (gencode (value), NULL_CODE);
+         pcrel = 0;
+         break;
+       case BFD_RELOC_16:
+       case BFD_RELOC_BFIN_GOT:
+         note1 = conscode (gencode (value), NULL_CODE);
+         pcrel = 0;
+         break;
+       case BFD_RELOC_24_PCREL:
+       case BFD_RELOC_BFIN_24_PCREL_JUMP_L:
+       case BFD_RELOC_BFIN_24_PCREL_CALL_X:
+         /* These offsets are even numbered pcrel.  */
+         note1 = conscode (gencode (value >> 1), NULL_CODE);
+         break;
+       default:
+         note1 = NULL_CODE;
+       }
+    }
+  if (head->type == Expr_Node_Constant)
+    note = note1;
+  else if (head->type == Expr_Node_Reloc)
+    {
+      note = note_reloc1 (gencode (0), head->value.s_value, parent_reloc, pcrel);
+      if (note1 != NULL_CODE)
+       note = conscode (note1, note);
+    }
+  else
+    {
+      /* Call the recursive function.  */
+      note = note_reloc1 (gencode (0), op, parent_reloc, pcrel);
+      if (note1 != NULL_CODE)
+       note = conscode (note1, note);
+      note = conctcode (Expr_Node_Gen_Reloc_R (head), note);
+    }
+  return note;
+}
+
+static INSTR_T
+Expr_Node_Gen_Reloc_R (Expr_Node * head)
+{
+
+  INSTR_T note = 0;
+  INSTR_T note1 = 0;
+
+  switch (head->type)
+    {
+    case Expr_Node_Constant:
+      note = conscode (note_reloc2 (gencode (0), con, BFD_ARELOC_BFIN_CONST, head->value.i_value, 0), NULL_CODE);
+      break;
+    case Expr_Node_Reloc:
+      note = conscode (note_reloc (gencode (0), head, BFD_ARELOC_BFIN_PUSH, 0), NULL_CODE);
+      break;
+    case Expr_Node_Binop:
+      note1 = conctcode (Expr_Node_Gen_Reloc_R (head->Left_Child), Expr_Node_Gen_Reloc_R (head->Right_Child));
+      switch (head->value.op_value)
+       {
+       case Expr_Op_Type_Add:
+         note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_ADD, 0), NULL_CODE));
+         break;
+       case Expr_Op_Type_Sub:
+         note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_SUB, 0), NULL_CODE));
+         break;
+       case Expr_Op_Type_Mult:
+         note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_MULT, 0), NULL_CODE));
+         break;
+       case Expr_Op_Type_Div:
+         note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_DIV, 0), NULL_CODE));
+         break;
+       case Expr_Op_Type_Mod:
+         note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_MOD, 0), NULL_CODE));
+         break;
+       case Expr_Op_Type_Lshift:
+         note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_LSHIFT, 0), NULL_CODE));
+         break;
+       case Expr_Op_Type_Rshift:
+         note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_RSHIFT, 0), NULL_CODE));
+         break;
+       case Expr_Op_Type_BAND:
+         note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_AND, 0), NULL_CODE));
+         break;
+       case Expr_Op_Type_BOR:
+         note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_OR, 0), NULL_CODE));
+         break;
+       case Expr_Op_Type_BXOR:
+         note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_XOR, 0), NULL_CODE));
+         break;
+       case Expr_Op_Type_LAND:
+         note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_LAND, 0), NULL_CODE));
+         break;
+       case Expr_Op_Type_LOR:
+         note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_LOR, 0), NULL_CODE));
+         break;
+       default:
+         fprintf (stderr, "%s:%d:Unkonwn operator found for arithmetic" " relocation", __FILE__, __LINE__);
+
+
+       }
+      break;
+    case Expr_Node_Unop:
+      note1 = conscode (Expr_Node_Gen_Reloc_R (head->Left_Child), NULL_CODE);
+      switch (head->value.op_value)
+       {
+       case Expr_Op_Type_NEG:
+         note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_NEG, 0), NULL_CODE));
+         break;
+       case Expr_Op_Type_COMP:
+         note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_COMP, 0), NULL_CODE));
+         break;
+       default:
+         fprintf (stderr, "%s:%d:Unkonwn operator found for arithmetic" " relocation", __FILE__, __LINE__);
+       }
+      break;
+    default:
+      fprintf (stderr, "%s:%d:Unknown node expression found during " "arithmetic relocation generation", __FILE__, __LINE__);
+    }
+  return note;
+}
+
+
+/* Blackfin opcode generation.  */
+
+/* These functions are called by the generated parser
+   (from bfin-parse.y), the register type classification
+   happens in bfin-lex.l.  */
+
+#include "bfin-aux.h"
+#include "opcode/bfin.h"
+
+#define INIT(t)  t c_code = init_##t
+#define ASSIGN(x) c_code.opcode |= ((x & c_code.mask_##x)<<c_code.bits_##x)
+#define ASSIGN_R(x) c_code.opcode |= (((x ? (x->regno & CODE_MASK) : 0) & c_code.mask_##x)<<c_code.bits_##x)
+
+#define HI(x) ((x >> 16) & 0xffff)
+#define LO(x) ((x      ) & 0xffff)
+
+#define GROUP(x) ((x->regno & CLASS_MASK) >> 4)
+
+#define GEN_OPCODE32()  \
+       conscode (gencode (HI (c_code.opcode)), \
+       conscode (gencode (LO (c_code.opcode)), NULL_CODE))
+
+#define GEN_OPCODE16()  \
+       conscode (gencode (c_code.opcode), NULL_CODE)
+
+
+/*  32 BIT INSTRUCTIONS.  */
+
+
+/* DSP32 instruction generation.  */
+
+INSTR_T
+bfin_gen_dsp32mac (int op1, int MM, int mmod, int w1, int P,
+                  int h01, int h11, int h00, int h10, int op0,
+                   REG_T dst, REG_T src0, REG_T src1, int w0)
+{
+  INIT (DSP32Mac);
+
+  ASSIGN (op0);
+  ASSIGN (op1);
+  ASSIGN (MM);
+  ASSIGN (mmod);
+  ASSIGN (w0);
+  ASSIGN (w1);
+  ASSIGN (h01);
+  ASSIGN (h11);
+  ASSIGN (h00);
+  ASSIGN (h10);
+  ASSIGN (P);
+
+  /* If we have full reg assignments, mask out LSB to encode
+  single or simultaneous even/odd register moves.  */
+  if (P)
+    {
+      dst->regno &= 0x06;
+    }
+
+  ASSIGN_R (dst);
+  ASSIGN_R (src0);
+  ASSIGN_R (src1);
+
+  return GEN_OPCODE32 ();
+}
+
+INSTR_T
+bfin_gen_dsp32mult (int op1, int MM, int mmod, int w1, int P,
+                   int h01, int h11, int h00, int h10, int op0,
+                    REG_T dst, REG_T src0, REG_T src1, int w0)
+{
+  INIT (DSP32Mult);
+
+  ASSIGN (op0);
+  ASSIGN (op1);
+  ASSIGN (MM);
+  ASSIGN (mmod);
+  ASSIGN (w0);
+  ASSIGN (w1);
+  ASSIGN (h01);
+  ASSIGN (h11);
+  ASSIGN (h00);
+  ASSIGN (h10);
+  ASSIGN (P);
+
+  if (P)
+    {
+      dst->regno &= 0x06;
+    }
+
+  ASSIGN_R (dst);
+  ASSIGN_R (src0);
+  ASSIGN_R (src1);
+
+  return GEN_OPCODE32 ();
+}
+
+INSTR_T
+bfin_gen_dsp32alu (int HL, int aopcde, int aop, int s, int x,
+              REG_T dst0, REG_T dst1, REG_T src0, REG_T src1)
+{
+  INIT (DSP32Alu);
+
+  ASSIGN (HL);
+  ASSIGN (aopcde);
+  ASSIGN (aop);
+  ASSIGN (s);
+  ASSIGN (x);
+  ASSIGN_R (dst0);
+  ASSIGN_R (dst1);
+  ASSIGN_R (src0);
+  ASSIGN_R (src1);
+
+  return GEN_OPCODE32 ();
+}
+
+INSTR_T
+bfin_gen_dsp32shift (int sopcde, REG_T dst0, REG_T src0,
+                REG_T src1, int sop, int HLs)
+{
+  INIT (DSP32Shift);
+
+  ASSIGN (sopcde);
+  ASSIGN (sop);
+  ASSIGN (HLs);
+
+  ASSIGN_R (dst0);
+  ASSIGN_R (src0);
+  ASSIGN_R (src1);
+
+  return GEN_OPCODE32 ();
+}
+
+INSTR_T
+bfin_gen_dsp32shiftimm (int sopcde, REG_T dst0, int immag,
+                   REG_T src1, int sop, int HLs)
+{
+  INIT (DSP32ShiftImm);
+
+  ASSIGN (sopcde);
+  ASSIGN (sop);
+  ASSIGN (HLs);
+
+  ASSIGN_R (dst0);
+  ASSIGN (immag);
+  ASSIGN_R (src1);
+
+  return GEN_OPCODE32 ();
+}
+
+/* LOOP SETUP.  */
+
+INSTR_T
+bfin_gen_loopsetup (Expr_Node * psoffset, REG_T c, int rop,
+               Expr_Node * peoffset, REG_T reg)
+{
+  int soffset, eoffset;
+  INIT (LoopSetup);
+
+  soffset = (EXPR_VALUE (psoffset) >> 1);
+  ASSIGN (soffset);
+  eoffset = (EXPR_VALUE (peoffset) >> 1);
+  ASSIGN (eoffset);
+  ASSIGN (rop);
+  ASSIGN_R (c);
+  ASSIGN_R (reg);
+
+  return
+      conscode (gencode (HI (c_code.opcode)),
+               conctcode (Expr_Node_Gen_Reloc (psoffset, BFD_RELOC_BFIN_5_PCREL),
+                          conctcode (gencode (LO (c_code.opcode)), Expr_Node_Gen_Reloc (peoffset, BFD_RELOC_BFIN_11_PCREL))));
+
+}
+
+/*  Call, Link.  */
+
+INSTR_T
+bfin_gen_calla (Expr_Node * addr, int S)
+{
+  int val;
+  int high_val;
+  int reloc = 0;
+  INIT (CALLa);
+
+  switch(S){
+   case 0 : reloc = BFD_RELOC_BFIN_24_PCREL_JUMP_L; break;
+   case 1 : reloc = BFD_RELOC_24_PCREL; break;
+   case 2 : reloc = BFD_RELOC_BFIN_PLTPC; break;
+   default : break;
+  }
+
+  ASSIGN (S);
+
+  val = EXPR_VALUE (addr) >> 1;
+  high_val = val >> 16;
+
+  return conscode (gencode (HI (c_code.opcode) | (high_val & 0xff)),
+                     Expr_Node_Gen_Reloc (addr, reloc));
+  }
+
+INSTR_T
+bfin_gen_linkage (int R, int framesize)
+{
+  INIT (Linkage);
+
+  ASSIGN (R);
+  ASSIGN (framesize);
+
+  return GEN_OPCODE32 ();
+}
+
+
+/* Load and Store.  */
+
+INSTR_T
+bfin_gen_ldimmhalf (REG_T reg, int H, int S, int Z, Expr_Node * phword, int reloc)
+{
+  int grp, hword;
+  unsigned val = EXPR_VALUE (phword);
+  INIT (LDIMMhalf);
+
+  ASSIGN (H);
+  ASSIGN (S);
+  ASSIGN (Z);
+
+  ASSIGN_R (reg);
+  grp = (GROUP (reg));
+  ASSIGN (grp);
+  if (reloc == 2)
+    {
+      return conscode (gencode (HI (c_code.opcode)), Expr_Node_Gen_Reloc (phword, BFD_RELOC_BFIN_16_IMM));
+    }
+  else if (reloc == 1)
+    {
+      return conscode (gencode (HI (c_code.opcode)), Expr_Node_Gen_Reloc (phword, IS_H (*reg) ? BFD_RELOC_BFIN_16_HIGH : BFD_RELOC_BFIN_16_LOW));
+    }
+  else
+    {
+      hword = val;
+      ASSIGN (hword);
+    }
+  return GEN_OPCODE32 ();
+}
+
+INSTR_T
+bfin_gen_ldstidxi (REG_T ptr, REG_T reg, int W, int sz, int Z, Expr_Node * poffset)
+{
+  int offset;
+  int value = 0;
+  INIT (LDSTidxI);
+
+  if (!IS_PREG (*ptr) || (!IS_DREG (*reg) && !Z))
+    {
+      fprintf (stderr, "Warning: possible mixup of Preg/Dreg\n");
+      return 0;
+    }
+
+  ASSIGN_R (ptr);
+  ASSIGN_R (reg);
+  ASSIGN (W);
+  ASSIGN (sz);
+  switch (sz)
+    {
+    case 0:
+      value = EXPR_VALUE (poffset) >> 2;
+      break;
+    case 1:
+      value = EXPR_VALUE (poffset) >> 1;
+      break;
+    case 2:
+      value = EXPR_VALUE (poffset);
+      break;
+    }
+
+
+  ASSIGN (Z);
+
+  offset = (value & 0xffff);
+  ASSIGN (offset);
+  /* TODO : test if you need to check this here.
+     The reloc case should automatically generate instruction
+     if constant.  */
+  if(poffset->type != Expr_Node_Constant){
+    /* A GOT relocation such as R0 = [P5 + symbol@GOT].
+       Distinguish between R0 = [P5 + symbol@GOT] and
+       P5 = [P5 + _current_shared_library_p5_offset_].  */
+    if(!strcmp(poffset->value.s_value, "_current_shared_library_p5_offset_")){
+      return  conscode (gencode (HI (c_code.opcode)),
+                       Expr_Node_Gen_Reloc(poffset, BFD_RELOC_16));
+    }
+    else
+    {
+      return  conscode (gencode (HI (c_code.opcode)),
+                       Expr_Node_Gen_Reloc(poffset, BFD_RELOC_BFIN_GOT));
+    }
+  }
+  else{
+    return GEN_OPCODE32 ();
+  }
+}
+
+
+INSTR_T
+bfin_gen_ldst (REG_T ptr, REG_T reg, int aop, int sz, int Z, int W)
+{
+  INIT (LDST);
+
+  if (!IS_PREG (*ptr) || (!IS_DREG (*reg) && !Z))
+    {
+      fprintf (stderr, "Warning: possible mixup of Preg/Dreg\n");
+      return 0;
+    }
+
+  ASSIGN_R (ptr);
+  ASSIGN_R (reg);
+  ASSIGN (aop);
+  ASSIGN (sz);
+  ASSIGN (Z);
+  ASSIGN (W);
+
+  return GEN_OPCODE16 ();
+}
+
+INSTR_T
+bfin_gen_ldstii (REG_T ptr, REG_T reg, Expr_Node * poffset, int W, int op)
+{
+  int offset;
+  int value = 0;
+  INIT (LDSTii);
+
+
+  if (!IS_PREG (*ptr))
+    {
+      fprintf (stderr, "Warning: possible mixup of Preg/Dreg\n");
+      return 0;
+    }
+
+  switch (op)
+    {
+    case 1:
+    case 2:
+      value = EXPR_VALUE (poffset) >> 1;
+      break;
+    case 0:
+    case 3:
+      value = EXPR_VALUE (poffset) >> 2;
+      break;
+    }
+
+  ASSIGN_R (ptr);
+  ASSIGN_R (reg);
+
+  offset = value;
+  ASSIGN (offset);
+  ASSIGN (W);
+  ASSIGN (op);
+
+  return GEN_OPCODE16 ();
+}
+
+INSTR_T
+bfin_gen_ldstiifp (REG_T sreg, Expr_Node * poffset, int W)
+{
+  /* Set bit 4 if it's a Preg.  */
+  int reg = (sreg->regno & CODE_MASK) | (IS_PREG (*sreg) ? 0x8 : 0x0);
+  int offset = ((~(EXPR_VALUE (poffset) >> 2)) & 0x1f) + 1;
+  INIT (LDSTiiFP);
+  ASSIGN (reg);
+  ASSIGN (offset);
+  ASSIGN (W);
+
+  return GEN_OPCODE16 ();
+}
+
+INSTR_T
+bfin_gen_ldstpmod (REG_T ptr, REG_T reg, int aop, int W, REG_T idx)
+{
+  INIT (LDSTpmod);
+
+  ASSIGN_R (ptr);
+  ASSIGN_R (reg);
+  ASSIGN (aop);
+  ASSIGN (W);
+  ASSIGN_R (idx);
+
+  return GEN_OPCODE16 ();
+}
+
+INSTR_T
+bfin_gen_dspldst (REG_T i, REG_T reg, int aop, int W, int m)
+{
+  INIT (DspLDST);
+
+  ASSIGN_R (i);
+  ASSIGN_R (reg);
+  ASSIGN (aop);
+  ASSIGN (W);
+  ASSIGN (m);
+
+  return GEN_OPCODE16 ();
+}
+
+INSTR_T
+bfin_gen_logi2op (int opc, int src, int dst)
+{
+  INIT (LOGI2op);
+
+  ASSIGN (opc);
+  ASSIGN (src);
+  ASSIGN (dst);
+
+  return GEN_OPCODE16 ();
+}
+
+INSTR_T
+bfin_gen_brcc (int T, int B, Expr_Node * poffset)
+{
+  int offset;
+  INIT (BRCC);
+
+  ASSIGN (T);
+  ASSIGN (B);
+  offset = ((EXPR_VALUE (poffset) >> 1));
+  ASSIGN (offset);
+  return conscode (gencode (c_code.opcode), Expr_Node_Gen_Reloc (poffset, BFD_RELOC_BFIN_10_PCREL));
+}
+
+INSTR_T
+bfin_gen_ujump (Expr_Node * poffset)
+{
+  int offset;
+  INIT (UJump);
+
+  offset = ((EXPR_VALUE (poffset) >> 1));
+  ASSIGN (offset);
+
+  return conscode (gencode (c_code.opcode),
+                   Expr_Node_Gen_Reloc (
+                       poffset, BFD_RELOC_BFIN_12_PCREL_JUMP_S));
+}
+
+INSTR_T
+bfin_gen_alu2op (REG_T dst, REG_T src, int opc)
+{
+  INIT (ALU2op);
+
+  ASSIGN_R (dst);
+  ASSIGN_R (src);
+  ASSIGN (opc);
+
+  return GEN_OPCODE16 ();
+}
+
+INSTR_T
+bfin_gen_compi2opd (REG_T dst, int src, int op)
+{
+  INIT (COMPI2opD);
+
+  ASSIGN_R (dst);
+  ASSIGN (src);
+  ASSIGN (op);
+
+  return GEN_OPCODE16 ();
+}
+
+INSTR_T
+bfin_gen_compi2opp (REG_T dst, int src, int op)
+{
+  INIT (COMPI2opP);
+
+  ASSIGN_R (dst);
+  ASSIGN (src);
+  ASSIGN (op);
+
+  return GEN_OPCODE16 ();
+}
+
+INSTR_T
+bfin_gen_dagmodik (REG_T i, int op)
+{
+  INIT (DagMODik);
+
+  ASSIGN_R (i);
+  ASSIGN (op);
+
+  return GEN_OPCODE16 ();
+}
+
+INSTR_T
+bfin_gen_dagmodim (REG_T i, REG_T m, int op, int br)
+{
+  INIT (DagMODim);
+
+  ASSIGN_R (i);
+  ASSIGN_R (m);
+  ASSIGN (op);
+  ASSIGN (br);
+
+  return GEN_OPCODE16 ();
+}
+
+INSTR_T
+bfin_gen_ptr2op (REG_T dst, REG_T src, int opc)
+{
+  INIT (PTR2op);
+
+  ASSIGN_R (dst);
+  ASSIGN_R (src);
+  ASSIGN (opc);
+
+  return GEN_OPCODE16 ();
+}
+
+INSTR_T
+bfin_gen_comp3op (REG_T src0, REG_T src1, REG_T dst, int opc)
+{
+  INIT (COMP3op);
+
+  ASSIGN_R (src0);
+  ASSIGN_R (src1);
+  ASSIGN_R (dst);
+  ASSIGN (opc);
+
+  return GEN_OPCODE16 ();
+}
+
+INSTR_T
+bfin_gen_ccflag (REG_T x, int y, int opc, int I, int G)
+{
+  INIT (CCflag);
+
+  ASSIGN_R (x);
+  ASSIGN (y);
+  ASSIGN (opc);
+  ASSIGN (I);
+  ASSIGN (G);
+
+  return GEN_OPCODE16 ();
+}
+
+INSTR_T
+bfin_gen_ccmv (REG_T src, REG_T dst, int T)
+{
+  int s, d;
+  INIT (CCmv);
+
+  ASSIGN_R (src);
+  ASSIGN_R (dst);
+  s = (GROUP (src));
+  ASSIGN (s);
+  d = (GROUP (dst));
+  ASSIGN (d);
+  ASSIGN (T);
+
+  return GEN_OPCODE16 ();
+}
+
+INSTR_T
+bfin_gen_cc2stat (int cbit, int op, int D)
+{
+  INIT (CC2stat);
+
+  ASSIGN (cbit);
+  ASSIGN (op);
+  ASSIGN (D);
+
+  return GEN_OPCODE16 ();
+}
+
+INSTR_T
+bfin_gen_regmv (REG_T src, REG_T dst)
+{
+  int gs, gd;
+  INIT (RegMv);
+
+  ASSIGN_R (src);
+  ASSIGN_R (dst);
+
+  gs = (GROUP (src));
+  ASSIGN (gs);
+  gd = (GROUP (dst));
+  ASSIGN (gd);
+
+  return GEN_OPCODE16 ();
+}
+
+INSTR_T
+bfin_gen_cc2dreg (int op, REG_T reg)
+{
+  INIT (CC2dreg);
+
+  ASSIGN (op);
+  ASSIGN_R (reg);
+
+  return GEN_OPCODE16 ();
+}
+
+INSTR_T
+bfin_gen_progctrl (int prgfunc, int poprnd)
+{
+  INIT (ProgCtrl);
+
+  ASSIGN (prgfunc);
+  ASSIGN (poprnd);
+
+  return GEN_OPCODE16 ();
+}
+
+INSTR_T
+bfin_gen_cactrl (REG_T reg, int a, int op)
+{
+  INIT (CaCTRL);
+
+  ASSIGN_R (reg);
+  ASSIGN (a);
+  ASSIGN (op);
+
+  return GEN_OPCODE16 ();
+}
+
+INSTR_T
+bfin_gen_pushpopmultiple (int dr, int pr, int d, int p, int W)
+{
+  INIT (PushPopMultiple);
+
+  ASSIGN (dr);
+  ASSIGN (pr);
+  ASSIGN (d);
+  ASSIGN (p);
+  ASSIGN (W);
+
+  return GEN_OPCODE16 ();
+}
+
+INSTR_T
+bfin_gen_pushpopreg (REG_T reg, int W)
+{
+  int grp;
+  INIT (PushPopReg);
+
+  ASSIGN_R (reg);
+  grp = (GROUP (reg));
+  ASSIGN (grp);
+  ASSIGN (W);
+
+  return GEN_OPCODE16 ();
+}
+
+/* Pseudo Debugging Support.  */
+
+INSTR_T
+bfin_gen_pseudodbg (int fn, int reg, int grp)
+{
+  INIT (PseudoDbg);
+
+  ASSIGN (fn);
+  ASSIGN (reg);
+  ASSIGN (grp);
+
+  return GEN_OPCODE16 ();
+}
+
+INSTR_T
+bfin_gen_pseudodbg_assert (int dbgop, REG_T regtest, int expected)
+{
+  INIT (PseudoDbg_Assert);
+
+  ASSIGN (dbgop);
+  ASSIGN_R (regtest);
+  ASSIGN (expected);
+
+  return GEN_OPCODE32 ();
+}
+
+/* Multiple instruction generation.  */
+
+INSTR_T
+bfin_gen_multi_instr (INSTR_T dsp32, INSTR_T dsp16_grp1, INSTR_T dsp16_grp2)
+{
+  INSTR_T walk;
+
+  /* If it's a 0, convert into MNOP. */
+  if (dsp32)
+    {
+      walk = dsp32->next;
+      SET_MULTI_INSTRUCTION_BIT (dsp32);
+    }
+  else
+    {
+      dsp32 = gencode (0xc803);
+      walk = gencode (0x1800);
+      dsp32->next = walk;
+    }
+
+  if (!dsp16_grp1)
+    {
+      dsp16_grp1 = gencode (0x0000);
+    }
+
+  if (!dsp16_grp2)
+    {
+      dsp16_grp2 = gencode (0x0000);
+    }
+
+  walk->next = dsp16_grp1;
+  dsp16_grp1->next = dsp16_grp2;
+  dsp16_grp2->next = NULL_CODE;
+
+  return dsp32;
+}
+
+INSTR_T
+bfin_gen_loop (Expr_Node *expr, REG_T reg, int rop, REG_T preg)
+{
+  const char *loopsym;
+  char *lbeginsym, *lendsym;
+  Expr_Node_Value lbeginval, lendval;
+  Expr_Node *lbegin, *lend;
+
+  loopsym = expr->value.s_value;
+  lbeginsym = (char *) xmalloc (strlen (loopsym) + strlen ("__BEGIN") + 1);
+  lendsym = (char *) xmalloc (strlen (loopsym) + strlen ("__END") + 1);
+
+  lbeginsym[0] = 0;
+  lendsym[0] = 0;
+
+  strcat (lbeginsym, loopsym);
+  strcat (lbeginsym, "__BEGIN");
+
+  strcat (lendsym, loopsym);
+  strcat (lendsym, "__END");
+
+  lbeginval.s_value = lbeginsym;
+  lendval.s_value = lendsym;
+
+  lbegin = Expr_Node_Create (Expr_Node_Reloc, lbeginval, NULL, NULL);
+  lend   = Expr_Node_Create (Expr_Node_Reloc, lendval, NULL, NULL);
+  return bfin_gen_loopsetup(lbegin, reg, rop, lend, preg);
+}
+
+bfd_boolean
+bfin_eol_in_insn (char *line)
+{
+   /* Allow a new-line to appear in the middle of a multi-issue instruction.  */
+
+   char *temp = line;
+
+  if (*line != '\n')
+    return FALSE;
+
+  /* A semi-colon followed by a newline is always the end of a line.  */
+  if (line[-1] == ';')
+    return FALSE;
+
+  if (line[-1] == '|')
+    return TRUE;
+
+  /* If the || is on the next line, there might be leading whitespace.  */
+  temp++;
+  while (*temp == ' ' || *temp == '\t') temp++;
+
+  if (*temp == '|')
+    return TRUE;
+
+  return FALSE;
+}
+
+bfd_boolean
+bfin_name_is_register (char *name)
+{
+  int i;
+
+  if (*name == '[' || *name == '(')
+    return TRUE;
+
+  if ((name[0] == 'W' || name[0] == 'w') && name[1] == '[')
+    return TRUE;
+
+  if ((name[0] == 'B' || name[0] == 'b') && name[1] == '[')
+    return TRUE;
+
+  if (!strncasecmp (name, "saa(", 4))
+    return TRUE;
+
+  if (!strncasecmp (name, "lsetup(", 7))
+    return TRUE;
+
+  for (i=0; bfin_reg_info[i].name != 0; i++)
+   {
+     if (!strcasecmp (bfin_reg_info[i].name, name))
+       return TRUE;
+   }
+  return FALSE;
+}
+
+void
+bfin_equals (Expr_Node *sym)
+{
+  char *c;
+
+  c = input_line_pointer;
+  while (*c != '=')
+   c--;
+
+  input_line_pointer = c;
+
+  equals ((char *) sym->value.s_value, 1);
+}
+
+bfd_boolean
+bfin_start_label (char *ptr)
+{
+  ptr--;
+  while (!ISSPACE (*ptr) && !is_end_of_line[(unsigned char) *ptr])
+    ptr--;
+
+  ptr++;
+  if (*ptr == '(' || *ptr == '[')
+    return FALSE;
+
+  if (!strncmp (ptr, "saa(", 4))
+    return FALSE;
+
+  if (!strncmp (ptr, "lsetup(", 7))
+    return FALSE;
+
+  return TRUE;
+} 
+
+int
+bfin_force_relocation (struct fix *fixp)
+{
+  if (fixp->fx_r_type ==BFD_RELOC_BFIN_16_LOW
+      || fixp->fx_r_type == BFD_RELOC_BFIN_16_HIGH)
+    return TRUE;
+
+  return generic_force_reloc (fixp);
+}
diff --git a/gas/config/tc-bfin.h b/gas/config/tc-bfin.h
new file mode 100644 (file)
index 0000000..9252e25
--- /dev/null
@@ -0,0 +1,75 @@
+/* tc-bfin.h - header file for tc-bfin.c
+   Copyright 2005
+   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, 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+#define TC_BFIN 1
+#define TC_ADI_BFIN 1
+
+#define TARGET_BYTES_BIG_ENDIAN 0
+
+#define TARGET_ARCH            bfd_arch_bfin
+
+/*
+ * Define the target format macro here.   The value for this should be
+ * "elf32-bfin", not "elf32-little-bfin".  Since the BFD source file 
+ * elf32-bfin.c defines TARGET_LITTLE_NAME to be "elf32-little-bfin",
+ * we must use this value, until this is corrected and BFD is rebuilt.  */
+#ifdef OBJ_ELF
+#define TARGET_FORMAT          "elf32-bfin" 
+#endif
+
+#define LISTING_HEADER "BFIN GAS "
+
+#define WORKING_DOT_WORD
+
+extern void bfin_start_line_hook PARAMS ((void));
+extern bfd_boolean bfin_start_label PARAMS ((char *));
+
+#define md_start_line_hook()    bfin_start_line_hook()
+#define md_number_to_chars     number_to_chars_littleendian
+#define md_convert_frag(b,s,f) as_fatal ("bfin convert_frag\n");
+
+/* Allow for [, ], etc.  */
+#define LEX_BR 6
+
+#define TC_EOL_IN_INSN(PTR) (bfin_eol_in_insn(PTR) ? 1 : 0)
+extern bfd_boolean bfin_eol_in_insn PARAMS ((char *));
+
+/* The instruction is permitted to contain an = character.  */
+#define TC_EQUAL_IN_INSN(C, NAME) (bfin_name_is_register (NAME) ? 1 : 0)
+extern bfd_boolean bfin_name_is_register PARAMS ((char *));
+#define NOP_OPCODE 0x0000 
+
+#define LOCAL_LABELS_FB 1
+
+#define DOUBLESLASH_LINE_COMMENTS
+
+#define TC_START_LABEL(ch ,ptr) (ch == ':' && bfin_start_label (ptr))
+#define tc_fix_adjustable(FIX) bfin_fix_adjustable (FIX)
+extern bfd_boolean bfin_fix_adjustable PARAMS ((struct fix *));
+
+#define TC_FORCE_RELOCATION(FIX) bfin_force_relocation (FIX)
+extern int bfin_force_relocation PARAMS ((struct fix *));
+
+/* Call md_pcrel_from_section(), not md_pcrel_from().  */
+#define MD_PCREL_FROM_SECTION(FIX, SEC) md_pcrel_from_section (FIX, SEC)
+extern long md_pcrel_from_section PARAMS ((struct fix *, segT));
+
+/* end of tc-bfin.h */
index fcf6b6223f99bfea5b5f375146d923172dc55c33..8b026ad7458748503ad060d552d9fa1d9065272d 100755 (executable)
@@ -4641,6 +4641,19 @@ _ACEOF
 
     # Any other special object files needed ?
     case ${cpu_type} in
+
+      bfin)
+        echo ${extra_objects} | grep -s "bfin-parse.o"
+        if test $? -ne 0 ; then
+          extra_objects="$extra_objects bfin-parse.o"
+        fi
+
+        echo ${extra_objects} | grep -s "bfin-lex.o"
+        if test $? -ne 0 ; then
+          extra_objects="$extra_objects bfin-lex.o"
+        fi
+        ;;
+
       fr30 | ip2k | iq2000 | m32r | openrisc)
        using_cgen=yes
        ;;
index 87c339e7860e42fc549148b117acf8e40f407ecf..3449a7dac76bfa7f5ecc909009798452edaf0fad 100644 (file)
@@ -274,6 +274,19 @@ changequote([,])dnl
 
     # Any other special object files needed ?
     case ${cpu_type} in
+
+      bfin)
+        echo ${extra_objects} | grep -s "bfin-parse.o"
+        if test $? -ne 0 ; then
+          extra_objects="$extra_objects bfin-parse.o"
+        fi
+
+        echo ${extra_objects} | grep -s "bfin-lex.o"
+        if test $? -ne 0 ; then
+          extra_objects="$extra_objects bfin-lex.o"
+        fi
+        ;;
+
       fr30 | ip2k | iq2000 | m32r | openrisc)
        using_cgen=yes
        ;;
index dd30a017bb7d45e67d243ad791935decadb5ba20..b2ce87956fc3ec5ab469fa53921a5a388674e93f 100644 (file)
@@ -33,6 +33,7 @@ case ${cpu} in
   am33_2.0)            cpu_type=mn10300 endian=little ;;
   arm*be|arm*b)                cpu_type=arm endian=big ;;
   arm*)                        cpu_type=arm endian=little ;;
+  bfin*)               cpu_type=bfin endian=little ;;
   c4x*)                        cpu_type=tic4x ;;
   crisv32)             cpu_type=cris arch=crisv32 ;;
   crx*)                        cpu_type=crx endian=little ;;
@@ -117,7 +118,9 @@ case ${generic_target} in
   arm-*-pe | thumb-*-pe)               fmt=coff em=pe ;;
   arm-*-riscix*)                       fmt=aout em=riscix ;;
 
-  avr-*-*)                             fmt=elf ;;
+  avr-*-*)                             fmt=elf bfd_gas=yes ;;
+  bfin-*-*)                            fmt=elf bfd_gas=yes ;;
+  bfin-*elf)                           fmt=elf ;;
 
   cris-*-linux-* | crisv32-*-linux-*)
                                        fmt=multi em=linux ;;
index 0fdbe830e16d6e17fc795cf6f4332f341062c19f..b3b25808e1ac33ca07243a6b55aff34a0c2fafaf 100644 (file)
@@ -27,6 +27,7 @@ CPU_DOCS = \
        c-alpha.texi \
        c-arc.texi \
        c-arm.texi \
+       c-bfin.texi \
        c-d10v.texi \
        c-cris.texi \
        c-h8300.texi \
index 04de8175dd8c6309e54c7857abc5d00df525849a..4456fa64a9458024511b7a1c1e79285f058c4c90 100644 (file)
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.9.5 from Makefile.am.
+# Makefile.in generated by automake 1.9.2 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@@ -218,6 +218,7 @@ CPU_DOCS = \
        c-alpha.texi \
        c-arc.texi \
        c-arm.texi \
+       c-bfin.texi \
        c-d10v.texi \
        c-cris.texi \
        c-h8300.texi \
@@ -346,7 +347,7 @@ as.html: as.texinfo
        $(DVIPS) -o $@ $<
 
 uninstall-info-am:
-       @$(PRE_UNINSTALL)
+       $(PRE_UNINSTALL)
        @if (install-info --version && \
             install-info --version 2>&1 | sed 1q | grep -i -v debian) >/dev/null 2>&1; then \
          list='$(INFO_DEPS)'; \
@@ -362,7 +363,7 @@ uninstall-info-am:
          relfile=`echo "$$file" | sed 's|^.*/||'`; \
          relfile_i=`echo "$$relfile" | sed 's|\.info$$||;s|$$|.i|'`; \
          (if cd "$(DESTDIR)$(infodir)"; then \
-            echo " cd '$(DESTDIR)$(infodir)' && rm -f $$relfile $$relfile-[0-9] $$relfile-[0-9][0-9] $$relfile_i[0-9] $$relfile_i[0-9][0-9]"; \
+            echo " rm -f $$relfile $$relfile-[0-9] $$relfile-[0-9][0-9] $$relfile_i[0-9] $$relfile_i[0-9][0-9])"; \
             rm -f $$relfile $$relfile-[0-9] $$relfile-[0-9][0-9] $$relfile_i[0-9] $$relfile_i[0-9][0-9]; \
           else :; fi); \
        done
index 6eb0e2a4589055eca5a6c56f4caaa1d9326494e7..77ff5e97e85f1738b3e0387dc893ad854d3d4fb0 100644 (file)
@@ -29,6 +29,7 @@
 @set ALPHA
 @set ARC
 @set ARM
+@set BFIN
 @set CRIS
 @set D10V
 @set D30V
index 63cc5d135fa9f87c6754b69f2c522bd41653760f..6e8ff3d54fed2c241347a159f7b439f847943c96 100644 (file)
@@ -6083,6 +6083,9 @@ subject, see the hardware manufacturer's manual.
 @ifset ARM
 * ARM-Dependent::               ARM Dependent Features
 @end ifset
+@ifset BFIN
+* BFIN-Dependent::             BFIN Dependent Features
+@end ifset
 @ifset CRIS
 * CRIS-Dependent::              CRIS Dependent Features
 @end ifset
@@ -6193,6 +6196,10 @@ subject, see the hardware manufacturer's manual.
 @include c-arm.texi
 @end ifset
 
+@ifset BFIN
+@include c-bfin.texi
+@end ifset
+
 @ifset CRIS
 @include c-cris.texi
 @end ifset
diff --git a/gas/doc/c-bfin.texi b/gas/doc/c-bfin.texi
new file mode 100644 (file)
index 0000000..dcf649a
--- /dev/null
@@ -0,0 +1,187 @@
+@c Copyright 2005
+@c Free Software Foundation, Inc.
+@c This is part of the GAS manual.
+@c For copying conditions, see the file as.texinfo.
+@ifset GENERIC
+@page
+@node BFIN-Dependent
+@chapter Blackfin Dependent Features
+@end ifset
+@ifclear GENERIC
+@node Machine Dependencies
+@chapter Blackfin Dependent Features
+@end ifclear
+
+@cindex Blackfin support
+@menu
+* BFIN Syntax::                        BFIN Syntax
+* BFIN Directives::            BFIN Directives
+@end menu
+
+@node BFIN Syntax
+@section Syntax
+@cindex BFIN syntax
+@cindex syntax, BFIN
+
+@table @code
+@item Special Characters
+Assembler input is free format and may appear anywhere on the line.
+One instruction may extend across multiple lines or more than one
+instruction may appear on the same line.  White space (space, tab,
+comments or newline) may appear anywhere between tokens.  A token must
+not have embedded spaces.  Tokens include numbers, register names,
+keywords, user identifiers, and also some multicharacter special 
+symbols like "+=", "/*" or "||".
+
+@item Instruction Delimiting
+A semicolon must terminate every instruction.  Sometimes a complete
+instruction will consist of more than one operation.  There are two 
+cases where this occurs.  The first is when two general operations
+are combined.  Normally a comma separates the different parts, as in
+
+@smallexample
+a0= r3.h * r2.l, a1 = r3.l * r2.h ;
+@end smallexample
+
+The second case occurs when a general instruction is combined with one
+or two memory references for joint issue.  The latter portions are
+set off by a "||" token.
+
+@smallexample
+a0 = r3.h * r2.l || r1 = [p3++] || r4 = [i2++];
+@end smallexample
+
+@item Register Names
+
+The assembler treats register names and instruction keywords in a case
+insensitive manner.  User identifiers are case sensitive.  Thus, R3.l,
+R3.L, r3.l and r3.L are all equivalent input to the assembler.
+
+Register names are reserved and may not be used as program identifiers.
+
+Some operations (such as "Move Register") require a register pair. 
+Register pairs are always data registers and are denoted using a colon,
+eg., R3:2.  The larger number must be written firsts.  Note that the 
+hardware only supports odd-even pairs, eg., R7:6, R5:4, R3:2, and R1:0.
+
+Some instructions (such as --SP (Push Multiple)) require a group of
+adjacent registers.  Adjacent registers are denoted in the syntax by
+the range enclosed in parentheses and separated by a colon, eg., (R7:3).
+Again, the larger number appears first.
+
+Portions of a particular register may be individually specified.  This
+is written with a dot (".") following the register name and then a 
+letter denoting the desired portion.  For 32-bit registers, ".H"
+denotes the most significant ("High") portion.  ".L" denotes the
+least-significant portion.  The subdivisions of the 40-bit registers
+are described later.
+
+@item Accumulators
+The set of 40-bit registers A1 and A0 that normally contain data that
+is being manipulated.  Each accumulator can be accessed in four ways.
+
+@table @code
+@item one 40-bit register
+The register will be referred to as A1 or A0.
+@item one 32-bit register
+The registers are designated as A1.W or A0.W.
+@item two 16-bit registers
+The registers are designated as A1.H, A1.L, A0.H or A0.L.
+@item one 8-bit register
+The registers are designated as A1.X or A0.X for the bits that
+extend beyond bit 31.
+@end table
+
+@item Data Registers
+The set of 32-bit registers (R0, R1, R2, R3, R4, R5, R6 and R7) that
+normally contain data for manipulation.  These are abbreviated as 
+D-register or Dreg.  Data registers can be accessed as 32-bit registers
+or as two independent 16-bit registers.  The least significant 16 bits
+of each register is called the "low" half and is desginated with ".L"
+following the register name.  The most significant 16 bits are called
+the "high" half and is designated with ".H". following the name.
+
+@smallexample
+   R7.L, r2.h, r4.L, R0.H
+@end smallexample
+
+@item Pointer Registers
+The set of 32-bit registers (P0, P1, P2, P3, P4, P5, SP and FP) that
+normally contain byte addresses of data structures.  These are
+abbreviated as P-register or Preg.
+
+@smallexample
+p2, p5, fp, sp
+@end smallexample
+
+@item Stack Pointer SP
+The stack pointer contains the 32-bit address of the last occupied
+byte location in the stack.  The stack grows by decrementing the
+stack pointer.
+
+@item Frame Pointer FP
+The frame pointer contains the 32-bit address of the previous frame
+pointer in the stack.  It is located at the top of a frame.
+
+@item Loop Top
+LT0 and LT1.  These registers contain the 32-bit address of the top of
+a zero overhead loop.
+
+@item Loop Count
+LC0 and LC1.  These registers contain the 32-bit counter of the zero
+overhead loop executions.
+
+@item Loop Bottom
+LB0 and LB1.  These registers contain the 32-bit address of the bottom
+of a zero overhead loop.
+
+@item Index Registers
+The set of 32-bit registers (I0, I1, I2, I3) that normally contain byte
+addresses of data structures.  Abbreviated I-register or Ireg.
+
+@item Modify Registers
+The set of 32-bit registers (M0, M1, M2, M3) that normally contain
+offset values that are added and subracted to one of the index
+registers.  Abbreviated as Mreg.
+
+@item Length Registers
+The set of 32-bit registers (L0, L1, L2, L3) that normally contain the
+length in bytes of the circular buffer.  Abbreviated as Lreg.  Clear
+the Lreg to disable circular addressing for the corresponding Ireg.
+
+@item Base Registers
+The set of 32-bit registers (B0, B1, B2, B3) that normally contain the
+base address in bytes of the circular buffer.  Abbreviated as Breg.
+
+@item Floating Point
+The Blackfin family has no hardware floating point but the .float
+directive generates ieee floating point numbers for use with software
+floating point libraries.
+
+@item Blackfin Opcodes
+For detailed information on the Blackfin machine instruction set, see
+the Blackfin(r) Processor Instruction Set Reference.
+
+@end table
+
+@node BFIN Directives
+@section Directives
+@cindex BFIN directives
+@cindex directives, BFIN
+
+The following directives are provided for compatibility with the VDSP assembler.
+
+@table @code
+@item .byte2
+Initializes a four byte data object.
+@item .byte4
+Initializes a two byte data object.
+@item .db
+TBD
+@item .dd
+TBD
+@item .dw
+TBD
+@item .var
+Define and initialize a 32 bit data object.
+@end table