summaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorCatherine Moore <clm@redhat.com>2005-09-30 15:05:07 +0000
committerCatherine Moore <clm@redhat.com>2005-09-30 15:05:07 +0000
commit07c1b327c74f8ed0552ac3871e1c47e33faecfd8 (patch)
treedc589f4974d25ae5e92ad097cddb9584869a1bd3 /gas
parentbfe2612a1433668c85da535144ea3b045dd817f4 (diff)
downloadbinutils-gdb-07c1b327c74f8ed0552ac3871e1c47e33faecfd8.tar.gz
* 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.
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog21
-rw-r--r--gas/Makefile.am34
-rw-r--r--gas/Makefile.in76
-rw-r--r--gas/aclocal.m4457
-rwxr-xr-xgas/config/bfin-aux.h151
-rw-r--r--gas/config/bfin-defs.h383
-rw-r--r--gas/config/bfin-lex.l554
-rw-r--r--gas/config/bfin-parse.y4360
-rw-r--r--gas/config/tc-bfin.c1951
-rw-r--r--gas/config/tc-bfin.h75
-rwxr-xr-xgas/configure13
-rw-r--r--gas/configure.in13
-rw-r--r--gas/configure.tgt5
-rw-r--r--gas/doc/Makefile.am1
-rw-r--r--gas/doc/Makefile.in7
-rw-r--r--gas/doc/all.texi1
-rw-r--r--gas/doc/as.texinfo7
-rw-r--r--gas/doc/c-bfin.texi187
18 files changed, 8140 insertions, 156 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 88b6511c096..c885fcfb0cc 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -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.
diff --git a/gas/Makefile.am b/gas/Makefile.am
index eecedec1925..40fbc7d787a 100644
--- a/gas/Makefile.am
+++ b/gas/Makefile.am
@@ -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 \
diff --git a/gas/Makefile.in b/gas/Makefile.in
index e61635b180e..94b34e8ec77 100644
--- a/gas/Makefile.in
+++ b/gas/Makefile.in
@@ -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
diff --git a/gas/aclocal.m4 b/gas/aclocal.m4
index ca849970a1b..389bef76886 100644
--- a/gas/aclocal.m4
+++ b/gas/aclocal.m4
@@ -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.
@@ -11,11 +11,23 @@
# 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
index 00000000000..be6b63a65ec
--- /dev/null
+++ b/gas/config/bfin-aux.h
@@ -0,0 +1,151 @@
+/* bfin-aux.h ADI Blackfin Header file for gas
+ 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 "bfin-defs.h"
+
+#define REG_T Register *
+
+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);
+
+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);
+
+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);
+
+INSTR_T
+bfin_gen_dsp32shift (int sopcde, REG_T dst0, REG_T src0, REG_T src1,
+ int sop, int hls);
+
+INSTR_T
+bfin_gen_dsp32shiftimm (int sopcde, REG_T dst0, int immag, REG_T src1,
+ int sop, int hls);
+
+INSTR_T
+bfin_gen_ldimmhalf (REG_T reg, int h, int s, int z, Expr_Node *hword,
+ int reloc);
+
+INSTR_T
+bfin_gen_ldstidxi (REG_T ptr, REG_T reg, int w, int sz, int z,
+ Expr_Node *offset);
+
+INSTR_T
+bfin_gen_ldst (REG_T ptr, REG_T reg, int aop, int sz, int z, int w);
+
+INSTR_T
+bfin_gen_ldstii (REG_T ptr, REG_T reg, Expr_Node *offset, int w, int op);
+
+INSTR_T
+bfin_gen_ldstiifp (REG_T reg, Expr_Node *offset, int w);
+
+INSTR_T
+bfin_gen_ldstpmod (REG_T ptr, REG_T reg, int aop, int w, REG_T idx);
+
+INSTR_T
+bfin_gen_dspldst (REG_T i, REG_T reg, int aop, int w, int m);
+
+INSTR_T
+bfin_gen_alu2op (REG_T dst, REG_T src, int opc);
+
+INSTR_T
+bfin_gen_compi2opd (REG_T dst, int src, int op);
+
+INSTR_T
+bfin_gen_compi2opp (REG_T dst, int src, int op);
+
+INSTR_T
+bfin_gen_dagmodik (REG_T i, int op);
+
+INSTR_T
+bfin_gen_dagmodim (REG_T i, REG_T m, int op, int br);
+
+INSTR_T
+bfin_gen_ptr2op (REG_T dst, REG_T src, int opc);
+
+INSTR_T
+bfin_gen_logi2op (int dst, int src, int opc);
+
+INSTR_T
+bfin_gen_comp3op (REG_T src0, REG_T src1, REG_T dst, int opc);
+
+INSTR_T
+bfin_gen_ccmv (REG_T src, REG_T dst, int t);
+
+INSTR_T
+bfin_gen_ccflag (REG_T x, int y, int opc, int i, int g);
+
+INSTR_T
+bfin_gen_cc2stat (int cbit, int op, int d);
+
+INSTR_T
+bfin_gen_regmv (REG_T src, REG_T dst);
+
+INSTR_T
+bfin_gen_cc2dreg (int op, REG_T reg);
+
+INSTR_T
+bfin_gen_brcc (int t, int b, Expr_Node *offset);
+
+INSTR_T
+bfin_gen_ujump (Expr_Node *offset);
+
+INSTR_T
+bfin_gen_cactrl (REG_T reg, int a, int op);
+
+INSTR_T
+bfin_gen_progctrl (int prgfunc, int poprnd);
+
+INSTR_T
+bfin_gen_loopsetup (Expr_Node *soffset, REG_T c, int rop,
+ Expr_Node *eoffset, REG_T reg);
+
+INSTR_T
+bfin_gen_loop (Expr_Node *expr, REG_T reg, int rop, REG_T preg);
+
+INSTR_T
+bfin_gen_pushpopmultiple (int dr, int pr, int d, int p, int w);
+
+INSTR_T
+bfin_gen_pushpopreg (REG_T reg, int w);
+
+INSTR_T
+bfin_gen_calla (Expr_Node *addr, int s);
+
+INSTR_T
+bfin_gen_linkage (int r, int framesize);
+
+INSTR_T
+bfin_gen_pseudodbg (int fn, int reg, int grp);
+
+INSTR_T
+bfin_gen_pseudodbg_assert (int dbgop, REG_T regtest, int expected);
+
+bfd_boolean
+bfin_resource_conflict (INSTR_T dsp32, INSTR_T dsp16_grp1, INSTR_T dsp16_grp2);
+
+INSTR_T
+bfin_gen_multi_instr (INSTR_T dsp32, INSTR_T dsp16_grp1, INSTR_T dsp16_grp2);
diff --git a/gas/config/bfin-defs.h b/gas/config/bfin-defs.h
new file mode 100644
index 00000000000..221e8c40c8f
--- /dev/null
+++ b/gas/config/bfin-defs.h
@@ -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
index 00000000000..df650350a2f
--- /dev/null
+++ b/gas/config/bfin-lex.l
@@ -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
index 00000000000..7751b688d00
--- /dev/null
+++ b/gas/config/bfin-parse.y
@@ -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);
+ }
+ }
+
+
+/* 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
index 00000000000..90763dadb3a
--- /dev/null
+++ b/gas/config/tc-bfin.c
@@ -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
index 00000000000..9252e25d9a7
--- /dev/null
+++ b/gas/config/tc-bfin.h
@@ -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 */
diff --git a/gas/configure b/gas/configure
index fcf6b6223f9..8b026ad7458 100755
--- a/gas/configure
+++ b/gas/configure
@@ -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
;;
diff --git a/gas/configure.in b/gas/configure.in
index 87c339e7860..3449a7dac76 100644
--- a/gas/configure.in
+++ b/gas/configure.in
@@ -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
;;
diff --git a/gas/configure.tgt b/gas/configure.tgt
index dd30a017bb7..b2ce87956fc 100644
--- a/gas/configure.tgt
+++ b/gas/configure.tgt
@@ -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 ;;
diff --git a/gas/doc/Makefile.am b/gas/doc/Makefile.am
index 0fdbe830e16..b3b25808e1a 100644
--- a/gas/doc/Makefile.am
+++ b/gas/doc/Makefile.am
@@ -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 \
diff --git a/gas/doc/Makefile.in b/gas/doc/Makefile.in
index 04de8175dd8..4456fa64a94 100644
--- a/gas/doc/Makefile.in
+++ b/gas/doc/Makefile.in
@@ -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
diff --git a/gas/doc/all.texi b/gas/doc/all.texi
index 6eb0e2a4589..77ff5e97e85 100644
--- a/gas/doc/all.texi
+++ b/gas/doc/all.texi
@@ -29,6 +29,7 @@
@set ALPHA
@set ARC
@set ARM
+@set BFIN
@set CRIS
@set D10V
@set D30V
diff --git a/gas/doc/as.texinfo b/gas/doc/as.texinfo
index 63cc5d135fa..6e8ff3d54fe 100644
--- a/gas/doc/as.texinfo
+++ b/gas/doc/as.texinfo
@@ -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
index 00000000000..dcf649a2b89
--- /dev/null
+++ b/gas/doc/c-bfin.texi
@@ -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